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