]> git.sur5r.net Git - cc65/blob - libsrc/lynx/lynx-snd.s
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / libsrc / lynx / lynx-snd.s
1 ;
2 ; Sound driver for the Atari Lynx.
3 ;
4 ; Karri Kaksonen and Bjoern Spruck, 11.12.2012
5 ;
6
7         .include        "lynx.inc"
8         .include        "zeropage.inc"
9
10         .export         _lynx_snd_init
11         .export         _lynx_snd_active
12         .export         _lynx_snd_play
13         .export         _lynx_snd_stop
14         .export         _lynx_snd_stop_channel
15         .export         _lynx_snd_pause
16         .export         _lynx_snd_continue
17         .interruptor    lynx_snd_handler
18         .import         popa
19         .importzp       ptr1
20
21 ;----------------------------------------------------------------------------
22 ; ZP variables that go into APPZP
23 ;
24
25         .segment "APPZP" : zeropage
26
27 SndSema:                .res    1
28 SndPtrTmp:              .res    2
29 SndTmp:                 .res    2
30 SndEnvPtr:              .res    2
31
32 ;----------------------------------------------------------------------------
33 ; Global variables
34 ;
35
36         .bss
37
38 SndRetAFlag2:           .res    1
39 SndRetAFlag:            .res    1
40 SndPtrLo:               .res    4
41 SndPtrHi:               .res    4
42 SndDelay:               .res    4
43 SndLoopCnt:             .res    4
44 SndLoopPtrLo:           .res    4
45 SndLoopPtrHi:           .res    4
46 SndVolume:              .res    4
47 SndMaxVolume:           .res    4
48 SndNotePlaying:         .res    4
49 SndRetAddr:             .res    8
50 SndActive:              .res    4
51 SndReqStop:             .res    4
52 SndEnvVol:              .res    4
53 SndEnvFrq:              .res    4
54 SndEnvWave:             .res    4
55 SndChannel:             .res    32
56 SndEnvVolCnt:           .res    4
57 SndEnvVolInc:           .res    4
58 SndEnvVolOff:           .res    4
59 SndEnvVolLoop:          .res    4
60 SndEnvVolParts:         .res    4
61 SndEnvVolParts2:        .res    4
62 SndEnvFrqCnt:           .res    4
63 SndEnvFrqInc:           .res    4
64 SndEnvFrqOff:           .res    4
65 SndEnvFrqLoop:          .res    4
66 SndEnvFrqParts:         .res    4
67 SndEnvFrqParts2:        .res    4
68 SndEnvWaveCnt:          .res    4
69 SndEnvWaveOff:          .res    4
70 SndEnvWaveLoop:         .res    4
71 SndEnvWaveParts:        .res    4
72 SndEnvWaveParts2:       .res    4
73
74 MAX_INSTRUMENTS         .set    64
75 SndEnvVolPtrLo:         .res    MAX_INSTRUMENTS
76 SndEnvVolPtrHi:         .res    MAX_INSTRUMENTS
77 SndEnvFrqPtrLo:         .res    MAX_INSTRUMENTS
78 SndEnvFrqPtrHi:         .res    MAX_INSTRUMENTS
79 SndEnvWavePtrLo:        .res    MAX_INSTRUMENTS
80 SndEnvWavePtrHi:        .res    MAX_INSTRUMENTS
81
82         .rodata
83
84 SndOffsets:             .byte   $00,$08,$10,$18
85
86 ;----------------------------------------------------------------------------
87 ; Macros
88 ;
89
90 if_count        .set    0
91 nest_count      .set    0
92
93 .macro  _IFNE
94         if_count        .set    if_count +1
95         nest_count      .set    nest_count +1
96         beq             .ident (.sprintf ("else%04d", if_count))
97         .ident (.sprintf ("push%04d", nest_count)) .set if_count
98 .endmacro
99
100 .macro  _IFEQ
101         if_count        .set    if_count +1
102         nest_count      .set    nest_count +1
103         bne             .ident (.sprintf ("else%04d", if_count))
104         .ident (.sprintf ("push%04d", nest_count)) .set if_count
105 .endmacro
106
107 .macro  _IFMI
108         if_count        .set    if_count +1
109         nest_count      .set    nest_count +1
110         bpl             .ident (.sprintf ("else%04d", if_count))
111         .ident (.sprintf ("push%04d", nest_count)) .set if_count
112 .endmacro
113
114 .macro  _IFPL
115         if_count        .set    if_count +1
116         nest_count      .set    nest_count +1
117         bmi             .ident (.sprintf ("else%04d", if_count))
118         .ident (.sprintf ("push%04d", nest_count)) .set if_count
119 .endmacro
120
121 .macro  _IFGE
122         if_count        .set    if_count +1
123         nest_count      .set    nest_count +1
124         bcc             .ident (.sprintf ("else%04d", if_count))
125         .ident (.sprintf ("push%04d", nest_count)) .set if_count
126 .endmacro
127
128 .macro  _IFCS
129         if_count        .set    if_count +1
130         nest_count      .set    nest_count +1
131         bcc             .ident (.sprintf ("else%04d", if_count))
132         .ident (.sprintf ("push%04d", nest_count)) .set if_count
133 .endmacro
134
135 .macro  _IFCC
136         if_count        .set    if_count +1
137         nest_count      .set    nest_count +1
138         bcs             .ident (.sprintf ("else%04d", if_count))
139         .ident (.sprintf ("push%04d", nest_count)) .set if_count
140 .endmacro
141
142 .macro  _ELSE
143         bra     .ident (.sprintf ("endif%04d", .ident (.sprintf ("push%04d", nest_count))))
144         .ident  (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))) := *
145 .endmacro
146
147 .macro  _ENDIF
148         .if .not .defined( .ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))))
149                 .ident  (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))) := *
150         .endif
151         .ident  (.sprintf ("endif%04d", .ident (.sprintf ("push%04d", nest_count)))) := *
152         nest_count      .set    nest_count -1
153 .endmacro
154
155         .code
156
157 ;----------------------------------------------------------------------------
158 ; void lynx_snd_init() will initialize the sound engine.
159 ;
160
161 _31250Hz        .set    %101
162
163 _lynx_snd_init:
164         php
165         sei
166         lda     #%10011000|_31250Hz
167         sta     STIMCTLA
168         lda     #129
169         sta     STIMBKUP        ; set up a 240Hz IRQ
170
171         stz     AUD0VOL
172         stz     AUD1VOL
173         stz     AUD2VOL
174         stz     AUD3VOL
175
176         stz     $fd44           ; all channels full volume / no attenuation
177         lda     #$ff
178         stz     MSTEREO
179
180         lda     #0
181         sta     AUD0CTLA
182         sta     AUD1CTLA
183         sta     AUD2CTLA
184         sta     AUD3CTLA
185
186         ldx     #3
187         lda     #0
188 init0:  stz     SndActive,x
189         stz     SndReqStop,x
190         stz     SndEnvVol,x
191         stz     SndEnvFrq,x
192         stz     SndEnvWave,x
193         ldy     SndOffsets,x
194         sta     SndChannel+2,y
195         dex
196         bpl     init0
197         stz     SndRetAFlag
198         stz     SndRetAFlag2
199         stz     SndSema
200         plp
201         rts
202
203 ;----------------------------------------------------------------------------
204 ; lynx_snd_handler is run at every sound interrupt
205 ;
206
207 lynx_snd_handler:
208         lda     INTSET
209         and     #SND_INTERRUPT
210         bne     @L0
211         clc
212         rts
213 @L0:
214         lda     #$ff
215         tsb     SndSema
216         bne     endirq
217         phy
218         ; *NOW* set all values which were "pre-set" in last interrupt
219         jsr     SndSetValues
220         cli
221
222         lda SndRetAFlag   ; reset the return flag, but save it first
223         _IFNE
224                 lda #$0F ; MASK
225                 sta SndRetAFlag2
226                 stz SndRetAFlag
227         _ENDIF
228
229         ldx #3
230 irq0:   phx
231         lda SndActive,x
232         _IFNE
233                 lda SndEnvVol,x
234                 _IFNE
235                         phx
236                         jsr SndChangeVol
237                         plx
238                 _ENDIF
239                 lda SndEnvFrq,x
240                 _IFNE
241                         phx
242                         jsr SndChangeFrq
243                         plx
244                 _ENDIF
245                 lda SndEnvWave,x
246                 _IFNE
247                         phx
248                         jsr SndChangeWave
249                         plx
250                 _ENDIF
251                 jsr SndGetCmd
252         _ENDIF
253         plx
254         dex
255         bpl irq0
256         sei
257         ply
258         stz SndSema
259 endirq:
260         clc
261         rts
262
263 ;----------------------------------------------------------------------------
264 ; A process table with addresses to sound functions
265 ;
266
267 SndCmdsLo:
268         .byte <((SndLoop)-1)
269         .byte <((SndDo)-1)
270         .byte <((SndPause)-1)
271         .byte <((SndNoteOff)-1)
272         .byte <((SndSetInstr)-1)
273         .byte <((SndNewNote2)-1)
274         .byte <((SndCallPattern)-1)
275         .byte <((SndRetToSong)-1)
276         .byte <((SndDefEnvVol)-1)
277         .byte <((SndSetEnvVol)-1)
278         .byte <((SndDefEnvFrq)-1)
279         .byte <((SndSetEnvFrq)-1)
280         .byte <((SndDefEnvWave)-1)
281         .byte <((SndSetEnvWave)-1)
282         .byte <((SndSetStereo)-1)
283         .byte <((SndSetAttenuationOn)-1)
284         .byte <((SndSetChnAttenution)-1)
285         .byte <((SndPlayerFreq)-1)
286         .byte <((SndReturnAll)-1)
287
288 SndCmdsHi:
289         .byte >((SndLoop)-1)
290         .byte >((SndDo)-1)
291         .byte >((SndPause)-1)
292         .byte >((SndNoteOff)-1)
293         .byte >((SndSetInstr)-1)
294         .byte >((SndNewNote2)-1)
295         .byte >((SndCallPattern)-1)
296         .byte >((SndRetToSong)-1)
297         .byte >((SndDefEnvVol)-1)
298         .byte >((SndSetEnvVol)-1)
299         .byte >((SndDefEnvFrq)-1)
300         .byte >((SndSetEnvFrq)-1)
301         .byte >((SndDefEnvWave)-1)
302         .byte >((SndSetEnvWave)-1)
303         .byte >((SndSetStereo)-1)
304         .byte >((SndSetAttenuationOn)-1)
305         .byte >((SndSetChnAttenution)-1)
306         .byte >((SndPlayerFreq)-1)
307         .byte >((SndReturnAll)-1)
308
309 ;----------------------------------------------------------------------------
310 ; Get next sound command from stream
311 ;
312
313 SndGetCmd:
314         lda SndReqStop,x
315         bne SndStop
316
317         lda SndRetAFlag2
318         and SndMask,x
319         _IFNE
320                 eor SndRetAFlag2
321                 sta SndRetAFlag2
322                 lda SndRetAddr,x
323                 sta SndPtrLo,x
324                 lda SndRetAddr+4,x
325                 sta SndPtrHi,x
326                 ;;; force the direct continue return
327         _ELSE
328                 dec SndDelay,x
329                 bne cmd991 ;; check special case
330         _ENDIF
331
332         lda SndPtrLo,x
333         sta SndPtrTmp
334         lda SndPtrHi,x
335         sta SndPtrTmp+1
336 cmd0:   lda (SndPtrTmp)
337         beq SndStop
338         _IFMI
339                 and #$7f
340                 tay
341                 jsr SndCallCmd
342         _ELSE
343                 jsr SndNewNote
344         _ENDIF
345         clc
346         tya
347         and #$7f
348         adc SndPtrTmp
349         sta SndPtrLo,x
350         sta SndPtrTmp
351         lda #0
352         adc SndPtrTmp+1
353         sta SndPtrHi,x
354         sta SndPtrTmp+1
355
356         tya
357         bmi cmd0
358 cmd991:
359         ;; now check if delay is only 1 AND next one is return all.
360         lda #1
361         cmp SndDelay,x
362         bne cmd99
363
364         ;; NOW read ahead ONE
365         lda SndPtrLo,x
366         sta SndPtrTmp
367         lda SndPtrHi,x
368         sta SndPtrTmp+1
369
370         lda (SndPtrTmp)
371         cmp #$92 ;; Return all
372         _IFEQ
373                 sta SndRetAFlag ; just set !=0
374         _ENDIF
375 cmd99:  rts
376
377 ;----------------------------------------------------------------------------
378 ; Call function pointed to by y
379 ;
380
381 SndCallCmd:
382         lda SndCmdsHi,y
383         pha
384         lda SndCmdsLo,y
385         pha
386         ldy #1
387         rts
388
389 ;----------------------------------------------------------------------------
390 ; Stop sound on one channel
391 ;
392
393 SndStop:
394         stz SndReqStop,x
395         stz SndActive,x
396         ldy SndOffsets,x
397         lda #0
398         sta SndChannel,y
399         ina ;lda #1
400         sta SndChannel+2,y
401         tay ;ldy #1
402         rts
403
404
405 ;----------------------------------------------------------------------------
406 ; Send a new note, length, volume triplet
407 ;
408
409 SndNewNote:
410         phx
411         sta SndNotePlaying,x
412         pha
413         ldy #1
414         lda (SndPtrTmp),y
415         sta SndDelay,x
416         ldy SndOffsets,x
417         lda SndVolume,x
418         sta SndChannel,y
419         plx
420         lda SndPrescaler,x
421         sta SndChannel+5,y
422         lda SndReload,x
423         sta SndChannel+4,y
424         lda #$FF   ; = -1
425         sta SndChannel+2,y
426         plx
427         lda SndEnvVol,x
428         _IFNE
429                 jsr SndSetEnvVol1
430         _ENDIF
431         lda SndEnvFrq,x
432         _IFNE
433                 jsr SndSetEnvFrq1
434         _ENDIF
435         lda SndEnvWave,x
436         _IFNE
437                 jsr SndSetEnvWave1
438         _ENDIF
439         lda #$2
440         ldy SndDelay,x
441         _IFNE
442                 ora #$80
443         _ENDIF
444         tay
445         rts
446
447 ;----------------------------------------------------------------------------
448 ; Start a loop with count
449 ;
450
451 SndLoop:
452         lda (SndPtrTmp),y
453         sta SndLoopCnt,x
454         lda SndPtrTmp
455         sta SndLoopPtrLo,x
456         lda SndPtrTmp+1
457         sta SndLoopPtrHi,x
458         ldy #$82
459         rts
460
461 SndDo:
462         dec SndLoopCnt,x
463         _IFNE
464                 lda SndLoopPtrLo,x
465                 sta SndPtrTmp
466                 lda SndLoopPtrHi,x
467                 sta SndPtrTmp+1
468                 ldy #$82
469         _ELSE
470                 ldy #$81
471         _ENDIF
472         rts
473
474 ;----------------------------------------------------------------------------
475 ; Sound volume envelope
476 ;
477
478 SndDefEnvVol:
479         phx
480         lda (SndPtrTmp),y               ; env #
481         tax
482
483         iny
484         lda (SndPtrTmp),y
485         sta SndEnvVolPtrLo,x
486         iny
487         lda (SndPtrTmp),y
488         sta SndEnvVolPtrHi,x            ; Ptr to [cnt,inc]
489
490         ldy #$84
491         plx
492         rts
493
494 SndSetEnvVol:
495         lda (SndPtrTmp),y               ; # env
496
497 SndSetEnvVol1:
498         and #$7f
499         sta SndEnvVol,x                 ; save
500         _IFEQ
501                 ldy #$82
502                 rts
503         _ENDIF
504
505         tay
506
507         lda SndEnvVolPtrLo,y
508         sta SndEnvPtr
509         lda SndEnvVolPtrHi,y
510         sta SndEnvPtr+1
511
512         lda (SndEnvPtr)
513         sta SndTmp
514         asl
515         sta SndEnvVolLoop,x             ; here is the loop-start
516
517         ldy #1
518         lda (SndEnvPtr),y
519         sta SndEnvVolParts,x
520         sec
521         sbc SndTmp
522         sta SndEnvVolParts2,x
523
524         stz SndEnvVolCnt,x
525         lda #2
526         sta SndEnvVolOff,x
527
528         ldy #$82
529         rts
530
531 ;----------------------------------------------------------------------------
532 ; Sound frequency envelope
533 ;
534
535 SndDefEnvFrq:
536         phx
537         lda (SndPtrTmp),y               ; env #
538         tax
539
540         iny
541         lda (SndPtrTmp),y
542         sta SndEnvFrqPtrLo,x
543         iny
544         lda (SndPtrTmp),y
545         sta SndEnvFrqPtrHi,x            ; Ptr to [inc,cnt]
546         plx
547         ldy #$84
548         rts
549
550 SndSetEnvFrq:
551         lda (SndPtrTmp),y               ; # env
552
553 SndSetEnvFrq1:
554         and #$7f
555         sta SndEnvFrq,x                 ; save
556         _IFEQ
557                 ldy #$82
558                 rts
559         _ENDIF
560
561         tay
562
563         lda SndEnvFrqPtrLo,y
564         sta SndEnvPtr
565         lda SndEnvFrqPtrHi,y
566         sta SndEnvPtr+1
567
568         lda (SndEnvPtr)
569         sta SndTmp
570         asl
571         sta SndEnvFrqLoop,x
572
573         ldy #1
574         lda (SndEnvPtr),y
575         sta SndEnvFrqParts,x
576         sec
577         sbc SndTmp
578         sta SndEnvFrqParts2,x
579
580         stz SndEnvFrqCnt,x
581         lda #2
582         sta SndEnvFrqOff,x
583
584         ldy #$82
585         rts
586
587 ;----------------------------------------------------------------------------
588 ; Sound frequency envelope
589 ;
590
591 SndDefEnvWave:
592
593         phx
594         lda (SndPtrTmp),y               ; env #
595         tax
596
597         iny
598         lda (SndPtrTmp),y
599         sta SndEnvWavePtrLo,x
600         iny
601         lda (SndPtrTmp),y
602         sta SndEnvWavePtrHi,x            ; Ptr to [inc,cnt]
603         plx
604         ldy #$84
605         rts
606
607 SndSetEnvWave:
608         lda (SndPtrTmp),y               ; # env
609
610 SndSetEnvWave1:
611         and #$7f
612         sta SndEnvWave,x                 ; save
613         _IFEQ
614                 ldy #$82
615                 rts
616         _ENDIF
617
618         tay
619
620         lda SndEnvWavePtrLo,y
621         sta SndEnvPtr
622         lda SndEnvWavePtrHi,y
623         sta SndEnvPtr+1
624
625         lda (SndEnvPtr)
626         sta SndTmp
627         asl ; *4 -2
628         dea
629         asl
630         sta SndEnvWaveLoop,x
631
632         ldy #1
633         lda (SndEnvPtr),y
634         sta SndEnvWaveParts,x
635         sec
636         sbc SndTmp
637         sta SndEnvWaveParts2,x
638
639         stz SndEnvWaveCnt,x
640         lda #2
641         sta SndEnvWaveOff,x
642
643         ldy #$82
644         rts
645
646 ;----------------------------------------------------------------------------
647 ; Pause sound
648 ;
649
650 SndPause:
651                 lda (SndPtrTmp),y
652                 sta SndDelay,x
653                 iny
654 SndDummy:        rts
655 ;;;* This set the new Player Freq instantanious!!!
656 SndPlayerFreq:
657                 lda (SndPtrTmp),y
658                 sta STIMCTLA
659                 iny
660                 lda (SndPtrTmp),y
661                 sta STIMBKUP
662                 ldy #$83
663                 rts
664
665 SndNoteOff:
666                 ldy SndOffsets,x
667                 stz SndNotePlaying,x
668                 lda SndEnvVol,x
669                 ora #$80
670                 sta SndEnvVol,x
671                 lda SndEnvFrq,x
672                 ora #$80
673                 sta SndEnvFrq,x
674                 lda SndEnvWave,x
675                 ora #$80
676                 sta SndEnvWave,x
677                 lda #0
678                 sta SndChannel,y
679                 sta SndChannel+4,y
680                 sta SndChannel+5,y
681                 dea
682                 sta SndChannel+2,y
683                 ldy #$81
684                 rts
685 SndSetInstr:
686                 phx
687                 lda SndOffsets,x
688                 tax
689                 lda (SndPtrTmp),y
690                 sta SndChannel+3,x
691                 iny
692                 lda (SndPtrTmp),y
693                 sta SndChannel+7,x
694                 iny
695                 lda (SndPtrTmp),y
696                 sta SndChannel+1,x
697                 plx
698                 iny
699                 lda (SndPtrTmp),y
700                 sta SndVolume,x
701                 iny
702                 lda (SndPtrTmp),y
703                 sta SndMaxVolume,x
704
705                 ldy #$86
706                 rts
707 SndCallPattern:
708                 clc
709                 lda SndPtrTmp
710                 adc #3
711                 sta SndRetAddr,x
712                 lda SndPtrTmp+1
713                 adc #0
714                 sta SndRetAddr+4,x
715                 ldy #1
716                 lda (SndPtrTmp),y
717                 pha
718                 iny
719                 lda (SndPtrTmp),y
720                 sta SndPtrTmp+1
721                 pla
722                 sta SndPtrTmp
723                 ldy #$80
724                 rts
725
726 SndRetToSong:
727                 lda SndRetAddr,x
728                 sta SndPtrTmp
729                 lda SndRetAddr+4,x
730                 sta SndPtrTmp+1
731                 ldy #$80
732                 rts
733
734 SndReturnAll:
735                 lda #1
736                 sta SndRetAFlag
737                 sta SndDelay,x
738                 ldy #$0
739                 rts
740 SndNewNote2:
741 ;;; Note,length,volume
742
743                 phx
744                   sta SndNotePlaying,x
745                   ldy #1
746                   lda (SndPtrTmp),y             ; reload
747                   pha
748                   iny
749                   lda (SndPtrTmp),y             ; prescale
750                   pha
751                   iny
752                   lda (SndPtrTmp),y         ; laenge
753                   sta SndDelay,x
754
755                   ldy SndOffsets,x
756                   lda SndVolume,x
757                   sta SndChannel,y
758                   pla
759                   sta SndChannel+5,y
760                   pla
761                   sta SndChannel+4,y
762                   lda #$FF ; = -1
763                   sta SndChannel+2,y
764                 plx
765                 lda SndEnvVol,x
766                 _IFNE
767                   jsr SndSetEnvVol1
768                 _ENDIF
769                 lda SndEnvFrq,x
770                 _IFNE
771                   jsr SndSetEnvFrq1
772                 _ENDIF
773                 lda SndEnvWave,x
774                 _IFNE
775                   jsr SndSetEnvWave1
776                 _ENDIF
777                 ldy #4
778                 rts
779
780 SndSetStereo:
781                 ldy #1
782                 lda (SndPtrTmp),y
783                 sta MSTEREO
784                 ldy #$82
785                 rts
786
787 SndSetAttenuationOn:
788                 ldy #1
789                 lda (SndPtrTmp),y
790                 sta $FD44
791                 ldy #$82
792                 rts
793
794 SndSetChnAttenution:
795                 ldy #1
796                 lda (SndPtrTmp),y
797                 sta $FD40,x
798                 ldy #$82
799                 rts
800
801 SndChangeVol:
802                 tay
803                 _IFMI
804 vol99:               rts
805                 _ENDIF
806                 lda SndNotePlaying,x
807                 beq vol99
808
809                 lda SndEnvVolPtrLo,y
810                 sta SndEnvPtr
811                 lda SndEnvVolPtrHi,y
812                 sta SndEnvPtr+1
813
814                 dec SndEnvVolCnt,x
815                 _IFMI
816                   dec SndEnvVolParts,x
817                   _IFMI
818                     lda SndEnvVolLoop,x
819                     _IFNE
820                       tay
821                       lda SndEnvVolParts2,x
822                       sta SndEnvVolParts,x
823                       bra vol1v
824                     _ELSE
825                       tya
826                       ora #$80
827                       sta SndEnvVol,x
828                     _ENDIF
829                   _ELSE
830                     ldy SndEnvVolOff,x
831 vol1v:                 lda (SndEnvPtr),y
832                     sta SndEnvVolCnt,x
833                     iny
834                     lda (SndEnvPtr),y
835                     sta SndEnvVolInc,x
836                     iny
837                     tya
838                     sta SndEnvVolOff,x
839                   _ENDIF
840                   rts
841                 _ENDIF
842
843                   ldy SndOffsets,x
844                   clc
845                   lda SndEnvVolInc,x
846                   _IFEQ
847                     rts
848                   _ENDIF
849                   _IFPL
850                     adc SndChannel,y
851                     cmp SndMaxVolume,x
852                     _IFCS
853                       lda SndMaxVolume,x
854                       stz SndEnvVolInc,x
855                     _ENDIF
856                     cmp #$80
857                     _IFGE
858                       lda #$7f
859                       stz SndEnvVolInc,x
860                     _ENDIF
861                  _ELSE
862                    adc SndChannel,y
863                    _IFCC
864                      lda #0
865                      sta SndEnvVolInc,x
866                      ;; NEU: switch Tremolo off
867                      sta SndNotePlaying,x
868                    _ENDIF
869                    cmp #$80
870                    _IFGE
871                      lda #0
872                      sta SndEnvVolInc,x
873                      ;; NEU: switch Tremolo off
874                      sta SndNotePlaying,x
875                    _ENDIF
876                  _ENDIF
877                   sta SndChannel,y
878                   lda SndChannel+2,y
879                   ora #1 ;; if already -1 ... no effect
880                   sta SndChannel+2,y
881                 rts
882
883
884 SndChangeFrq:
885                 tay
886                 _IFMI
887 frq99:               rts
888                 _ENDIF
889                 lda SndNotePlaying,x
890                 beq frq99
891
892                 lda SndEnvFrqPtrLo,y
893                 sta SndEnvPtr
894                 lda SndEnvFrqPtrHi,y
895                 sta SndEnvPtr+1
896
897                 dec SndEnvFrqCnt,x
898                 _IFMI
899                   dec SndEnvFrqParts,x
900                   _IFMI
901                     lda SndEnvFrqLoop,x
902                     _IFNE
903                       tay
904                       lda SndEnvFrqParts2,x
905                       sta SndEnvFrqParts,x
906                       bra frq1f
907                     _ELSE
908                       tya
909                       ora #$80
910                       sta SndEnvFrq,x
911                     _ENDIF
912                   _ELSE
913                     ldy SndEnvFrqOff,x
914 frq1f:                 lda (SndEnvPtr),y
915                     sta SndEnvFrqCnt,x
916                     iny
917                     lda (SndEnvPtr),y
918                     eor #$ff
919                     ina
920                     sta SndEnvFrqInc,x
921                     iny
922                     tya
923                     sta SndEnvFrqOff,x
924                   _ENDIF
925                   rts
926                   _ENDIF
927                   ldy SndOffsets,x
928                   clc
929                   lda SndEnvFrqInc,x
930                   _IFEQ
931                     rts
932                   _ENDIF
933
934                   _IFMI
935                     adc SndChannel+4,y
936                     _IFPL
937                       pha
938                       lda SndChannel+5,y
939                       _IFNE
940                         dea
941                         sta SndChannel+5,y
942                         pla
943                         eor #128
944                       _ELSE
945                         pla
946                         pha
947                         clc
948                         adc SndEnvFrqInc,x
949                         pla
950                       _ENDIF
951                     _ELSE
952                       pha
953                       lda SndChannel+5,y
954                       _IFEQ
955                         pla
956                         sta SndChannel+4,y
957                         rts
958                       _ENDIF
959                       pla
960                     _ENDIF
961                   _ELSE
962                     adc SndChannel+4,y
963                     _IFPL
964                       pha
965                       lda SndChannel+5,y
966                       cmp #6
967                       _IFNE
968                         ina
969                         sta SndChannel+5,y
970                         pla
971                         eor #128
972                       _ELSE
973                         lda SndChannel+4,y
974                         _IFMI
975                           pla
976                           rts
977                         _ENDIF
978                         pla
979                       _ENDIF
980                     _ELSE
981                       pha
982                       lda SndChannel+5,y
983                       cmp #6
984                       _IFEQ
985                         lda SndChannel+4,y
986                         _IFPL
987                           pla
988                           rts
989                         _ENDIF
990                       _ENDIF
991                       pla
992                     _ENDIF
993                   _ENDIF
994                   sta SndChannel+4,y
995
996                   ora #1 ;; if already -1 -> no effect
997                 rts
998
999 SndChangeWave:
1000                 tay
1001                 ;; Ab hier x Kanal 0-3, y Environment
1002                 _IFMI
1003 wav99:               rts
1004                 _ENDIF
1005                 lda SndNotePlaying,x
1006                 beq wav99
1007
1008
1009                 lda SndEnvWavePtrLo,y
1010                 sta SndEnvPtr
1011                 lda SndEnvWavePtrHi,y
1012                 sta SndEnvPtr+1
1013
1014                 dec SndEnvWaveCnt,x
1015                 _IFMI
1016                   dec SndEnvWaveParts,x
1017                   _IFMI
1018                     lda SndEnvWaveLoop,x
1019                     _IFNE
1020                       tay
1021                       ;; Ab hier x Kanal 0-3, y Offset im Environment
1022                       lda SndEnvWaveParts2,x
1023                       sta SndEnvWaveParts,x
1024                       bra wav1v
1025                     _ELSE
1026                       tya
1027                       ora #$80 ;; beende Env
1028                       sta SndEnvWave,x
1029                     _ENDIF
1030                   _ELSE
1031                     ldy SndEnvWaveOff,x
1032                 ;; Ab hier x Kanal 0-3, y Offset im  Environment
1033 wav1v:                 lda (SndEnvPtr),y
1034                     sta SndEnvWaveCnt,x
1035                   phx
1036                   lda SndOffsets,x
1037                   tax
1038                 ;; Ab hier x Kanal (0-3)*8, y Offset im  Environment
1039
1040                     iny
1041                     lda (SndEnvPtr),y
1042                     sta SndChannel+3,x  ; Shift LO
1043                     iny
1044                     lda (SndEnvPtr),y
1045                     sta SndChannel+7,x   ; Shift HI
1046                     iny
1047                     lda (SndEnvPtr),y
1048                     sta SndChannel+1,x  ; Feedback
1049                     iny
1050                     tya
1051                     ply
1052                 ;; Ab hier x Kanal (0-3)*8,  y Kanal 0-3
1053                     sta SndEnvWaveOff,y
1054                   lda #$FF ; =-1 ;; stop timer to set new values...
1055                   sta SndChannel+2,x
1056                   _ENDIF
1057                 _ENDIF
1058                 rts
1059
1060
1061 SndSetValues:
1062                 ldx #4-1
1063 set0:                ldy SndOffsets,x
1064                   lda SndChannel+2,y
1065                   _IFNE                        ; flag == 0 => don`t set
1066
1067             bit #$80
1068                     _IFNE                       ;
1069                       lda #0
1070                       sta $fd25,y                 ; stop sound timer
1071
1072                       lda SndChannel+3,y
1073                       sta $fd23,y                 ; shifter 1
1074                       ;;lda $fd27,y
1075                       ;;and #$0F
1076                       ;;ora SndChannel+7,y          ; shifter 2
1077                       lda SndChannel+7,y          ; shifter 2
1078                       sta $fd27,y
1079                       lda SndChannel+1,y
1080                       sta $fd21,y                 ; feedback
1081                     _ENDIF
1082
1083                     lda SndChannel,y
1084                     sta $fd20,y                 ; volume
1085                     lda SndChannel+2,y
1086             bit #$80
1087                     _IFNE                       ;
1088                     lda SndChannel+4,y
1089                     sta $fd24,y                 ; reload
1090                     lda SndChannel+5,y
1091                     ora #%00011000 ;;; #%01011000
1092             ;; and #%00111111
1093                     sta $fd25,y                 ; re-enable timer
1094                     _ENDIF
1095
1096                     lda #0
1097                     sta SndChannel+2,y          ; clear flag
1098                 _ENDIF
1099
1100                 dex
1101         _IFPL
1102             jmp set0
1103         _ENDIF
1104         rts
1105
1106 _lynx_snd_play:
1107         sta ptr1
1108         stx ptr1+1
1109         jsr popa
1110         tax
1111         lda ptr1
1112         ldy ptr1+1
1113         php
1114         pha
1115         lda SndActive,x
1116         _IFNE
1117                 dec SndReqStop,x
1118                 lda #1
1119                 sta SndDelay,x
1120 start0:         lda SndActive,x
1121                 bne start0
1122         _ENDIF
1123         bra start1
1124 SndStartSoundx:
1125         php
1126         pha
1127 start1:
1128         sei
1129         pla
1130         sta SndPtrLo,x
1131         tya
1132         sta SndPtrHi,x
1133         lda #1
1134         sta SndDelay,x
1135         stz SndEnvVol,x
1136         stz SndEnvFrq,x
1137         stz SndEnvWave,x
1138         sta SndActive,x
1139         stz SndReqStop,x
1140         plp
1141         rts
1142 SndStartSound2:
1143         pha
1144         lda SndActive,x         ; check default
1145         beq start20                  ; inactive => ok
1146         phx
1147         ldx #3                  ; search free channel
1148 start21:
1149         lda SndActive,x
1150         beq start22                ; found =>
1151         dex
1152         bpl start21
1153         plx                     ; not found
1154         dec SndReqStop,x        ; stop default-channel
1155         lda #1
1156         sta SndDelay,x
1157 start23:
1158         lda SndActive,x
1159         bne start23
1160         bra start20
1161 start22:
1162         pla             ; clear stack
1163 start20:
1164         pla
1165         phx
1166         jsr SndStartSoundx      ; launch new sound
1167         plx
1168         rts
1169
1170 _lynx_snd_stop:
1171         ldx #3
1172         lda SndActive,x
1173         _IFNE
1174 stop0:          dec SndReqStop,x
1175                 lda #1
1176                 sta SndDelay,x
1177 stop1:          lda SndActive,x
1178                 bne stop1
1179         _ENDIF
1180         dex
1181         bpl stop0
1182         rts
1183
1184 _lynx_snd_stop_channel:
1185         tax
1186         lda SndActive,x
1187         _IFNE
1188                 dec SndReqStop,x
1189                 lda #1
1190                 sta SndDelay,x
1191 stopc1:         lda SndActive,x
1192                 bne stopc1
1193         _ENDIF
1194         rts
1195
1196 _lynx_snd_active:
1197         ldx #3
1198         lda #0
1199 act0:   ldy SndActive,x
1200         _IFNE
1201                 ora SndMask,x
1202         _ENDIF
1203         dex
1204         bpl act0
1205         rts
1206
1207 _lynx_snd_pause:
1208         php
1209         sei
1210         lda STIMCTLA
1211         sta SndPauseOff1+1
1212         stz STIMCTLA
1213         lda MSTEREO
1214         sta SndPauseOff2+1
1215         lda #$ff
1216         sta MSTEREO
1217         lda #$18
1218         trb AUD0CTLA
1219         trb AUD1CTLA
1220         trb AUD2CTLA
1221         trb AUD3CTLA
1222         plp
1223         rts
1224
1225 _lynx_snd_continue:
1226         php
1227         sei
1228 SndPauseOff1:
1229         lda #0 ; Selbsmodifizierter Code!!!
1230         sta STIMCTLA
1231 SndPauseOff2:
1232         lda #0 ; Selbsmodifizierter Code!!!
1233         sta MSTEREO
1234
1235         lda #$18
1236         tsb AUD0CTLA
1237         tsb AUD1CTLA
1238         tsb AUD2CTLA
1239         tsb AUD3CTLA
1240
1241         plp
1242         rts
1243
1244         .rodata
1245
1246 SndMask:
1247         .byte 1,2,4,8
1248
1249 SndPrescaler:
1250         .byte $00,$06,$06,$06,$06,$05,$05,$05,$05,$05,$05,$05,$04,$04,$04,$04
1251         .byte $04,$04,$04,$04,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$02,$02
1252         .byte $02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$01,$01,$01,$01,$01
1253         .byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00,$00
1254         .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
1255         .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
1256         .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
1257         .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
1258
1259 SndReload:
1260         .byte $00,$9A,$96,$8F,$86,$FA,$E5,$D1,$BE,$AC,$9C,$8D,$00,$E8,$D3,$C0
1261         .byte $AF,$A0,$93,$87,$FA,$E7,$D6,$C6,$B8,$AC,$A1,$96,$8D,$84,$FA,$EB
1262         .byte $DE,$D2,$C7,$BC,$B3,$AA,$A1,$9A,$93,$8C,$86,$00,$F5,$EB,$E1,$D8
1263         .byte $CF,$C7,$C0,$B9,$B2,$AB,$A5,$A0,$9A,$95,$90,$8B,$87,$82,$FD,$F5
1264         .byte $EE,$E7,$E0,$D9,$D3,$CD,$C8,$C2,$BD,$B8,$B3,$AE,$AA,$A5,$A1,$9D
1265         .byte $99,$96,$92,$8F,$8B,$88,$85,$82,$7F,$7C,$79,$77,$74,$72,$6F,$6D
1266         .byte $6B,$69,$67,$64,$63,$61,$5F,$5D,$5B,$59,$58,$56,$55,$53,$51,$50
1267         .byte $4F,$4D,$4C,$4B,$49,$48,$47,$46,$44,$43,$42,$41,$40,$3F,$3E,$3D
1268
1269
1270