1;-------------------------------------------------------------------------------
2; GoatTracker V2.73 alternative SID write order playroutine
3;
4; NOTE: This playroutine source code does not fall under the GPL license!
5; Use it, or song binaries created from it freely for any purpose, commercial
6; or noncommercial.
7;
8; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer.
9; Does not directly compile on DASM etc.
10;-------------------------------------------------------------------------------
11
12        ;Defines will be inserted by the relocator here
13
14              .IF (ZPGHOSTREGS == 0)
15mt_temp1        = zpbase+0
16mt_temp2        = zpbase+1
17              .ELSE
18ghostfreqlo     = zpbase+0
19ghostfreqhi     = zpbase+1
20ghostpulselo    = zpbase+2
21ghostpulsehi    = zpbase+3
22ghostwave       = zpbase+4
23ghostad         = zpbase+5
24ghostsr         = zpbase+6
25ghostfiltcutlow = zpbase+21
26ghostfiltcutoff = zpbase+22
27ghostfiltctrl   = zpbase+23
28ghostfilttype   = zpbase+24
29mt_temp1        = zpbase+25
30mt_temp2        = zpbase+26
31              .ENDIF
32
33        ;Defines for the music data
34        ;Patterndata notes
35
36ENDPATT         = $00
37INS             = $00
38FX              = $40
39FXONLY          = $50
40NOTE            = $60
41REST            = $bd
42KEYOFF          = $be
43KEYON           = $bf
44FIRSTPACKEDREST = $c0
45PACKEDREST      = $00
46
47        ;Effects
48
49DONOTHING       = $00
50PORTAUP         = $01
51PORTADOWN       = $02
52TONEPORTA       = $03
53VIBRATO         = $04
54SETAD           = $05
55SETSR           = $06
56SETWAVE         = $07
57SETWAVEPTR      = $08
58SETPULSEPTR     = $09
59SETFILTPTR      = $0a
60SETFILTCTRL     = $0b
61SETFILTCUTOFF   = $0c
62SETMASTERVOL    = $0d
63SETFUNKTEMPO    = $0e
64SETTEMPO        = $0f
65
66        ;Orderlist commands
67
68REPEAT          = $d0
69TRANSDOWN       = $e0
70TRANS           = $f0
71TRANSUP         = $f0
72LOOPSONG        = $ff
73
74        ;Wave,pulse,filttable comands
75
76LOOPWAVE        = $ff
77LOOPPULSE       = $ff
78LOOPFILT        = $ff
79SETPULSE        = $80
80SETFILTER       = $80
81SETCUTOFF       = $00
82
83                .ORG (base)
84
85        ;Jump table
86
87                jmp mt_init
88                jmp mt_play
89              .IF (SOUNDSUPPORT != 0)
90                jmp mt_playsfx
91              .ENDIF
92              .IF (VOLSUPPORT != 0)
93                jmp mt_setmastervol
94              .ENDIF
95
96        ;Author info
97
98              .IF (NOAUTHORINFO == 0)
99
100authorinfopos   = base + $20
101checkpos1:
102              .IF ((authorinfopos - checkpos1) > 15)
103mt_tick0jumptbl:
104                .BYTE (mt_tick0_0 % 256)
105                .BYTE (mt_tick0_12 % 256)
106                .BYTE (mt_tick0_12 % 256)
107                .BYTE (mt_tick0_34 % 256)
108                .BYTE (mt_tick0_34 % 256)
109                .BYTE (mt_tick0_5 % 256)
110                .BYTE (mt_tick0_6 % 256)
111                .BYTE (mt_tick0_7 % 256)
112                .BYTE (mt_tick0_8 % 256)
113                .BYTE (mt_tick0_9 % 256)
114                .BYTE (mt_tick0_a % 256)
115                .BYTE (mt_tick0_b % 256)
116                .BYTE (mt_tick0_c % 256)
117                .BYTE (mt_tick0_d % 256)
118                .BYTE (mt_tick0_e % 256)
119                .BYTE (mt_tick0_f % 256)
120              .ENDIF
121
122checkpos2:
123              .IF ((authorinfopos - checkpos2) > 4)
124mt_effectjumptbl:
125                .BYTE (mt_effect_0 % 256)
126                .BYTE (mt_effect_12 % 256)
127                .BYTE (mt_effect_12 % 256)
128                .BYTE (mt_effect_3 % 256)
129                .BYTE (mt_effect_4 % 256)
130              .ENDIF
131
132checkpos3:
133              .IF ((authorinfopos - checkpos3) > 1)
134mt_funktempotbl:
135                .BYTE (8,5)
136              .ENDIF
137
138        ;This is pretty stupid way of filling left-out space, but .ORG
139        ;seemed to bug
140
141checkpos4:
142              .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF
143checkpos5:
144              .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF
145checkpos6:
146              .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF
147
148mt_author:
149
150                .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
151                .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
152              .ENDIF
153
154        ;0 Instrument vibrato
155
156mt_tick0_0:
157              .IF (NOEFFECTS == 0)
158              .IF (NOINSTRVIB == 0)
159                lda mt_insvibparam-1,y
160                jmp mt_tick0_34
161              .ELSE
162              .IF (NOVIB == 0)
163                lda #$00
164                jmp mt_tick0_34
165              .ENDIF
166              .ENDIF
167              .ENDIF
168
169        ;1,2 Portamentos
170
171
172mt_tick0_12:
173              .IF (NOVIB == 0)
174                tay
175                lda #$00
176                sta mt_chnvibtime,x
177                tya
178              .ENDIF
179
180        ;3,4 Toneportamento, Vibrato
181
182mt_tick0_34:
183              .IF (NOEFFECTS == 0)
184              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
185                sta mt_chnparam,x
186                lda mt_chnnewfx,x
187                sta mt_chnfx,x
188              .ENDIF
189                rts
190              .ENDIF
191
192        ;5 Set AD
193
194mt_tick0_5:
195              .IF (NOSETAD == 0)
196              .IF (BUFFEREDWRITES == 0)
197                sta SIDBASE+$05,x
198              .ELSE
199              .IF (GHOSTREGS == 0)
200                sta mt_chnad,x
201              .ELSE
202                sta <ghostad,x
203              .ENDIF
204              .ENDIF
205                rts
206              .ENDIF
207
208        ;6 Set Sustain/Release
209
210mt_tick0_6:
211              .IF (NOSETSR == 0)
212              .IF (BUFFEREDWRITES == 0)
213                sta SIDBASE+$06,x
214              .ELSE
215              .IF (GHOSTREGS == 0)
216                sta mt_chnsr,x
217              .ELSE
218                sta <ghostsr,x
219              .ENDIF
220              .ENDIF
221                rts
222              .ENDIF
223
224        ;7 Set waveform
225
226mt_tick0_7:
227              .IF (NOSETWAVE == 0)
228                sta mt_chnwave,x
229                rts
230              .ENDIF
231
232        ;8 Set wavepointer
233
234mt_tick0_8:
235              .IF (NOSETWAVEPTR == 0)
236                sta mt_chnwaveptr,x
237              .IF (NOWAVEDELAY == 0)
238                lda #$00                        ;Make sure possible delayed
239                sta mt_chnwavetime,x            ;waveform execution goes
240              .ENDIF                            ;correctly
241                rts
242              .ENDIF
243
244        ;9 Set pulsepointer
245
246mt_tick0_9:
247              .IF (NOSETPULSEPTR == 0)
248                sta mt_chnpulseptr,x
249                lda #$00                        ;Reset pulse step duration
250                sta mt_chnpulsetime,x
251                rts
252              .ENDIF
253
254        ;a Set filtpointer
255
256mt_tick0_a:
257              .IF (NOSETFILTPTR == 0)
258              .IF (NOFILTERMOD == 0)
259                ldy #$00
260                sty mt_filttime+1
261              .ENDIF
262mt_tick0_a_step:
263                sta mt_filtstep+1
264                rts
265              .ENDIF
266
267        ;b Set filtcontrol (channels & resonance)
268
269mt_tick0_b:
270              .IF (NOSETFILTCTRL == 0)
271                sta mt_filtctrl+1
272              .IF (NOSETFILTPTR == 0)
273                beq mt_tick0_a_step          ;If 0, stop also step-programming
274              .ELSE
275                bne mt_tick0_b_noset
276                sta mt_filtstep+1
277mt_tick0_b_noset:
278              .ENDIF
279                rts
280              .ENDIF
281
282        ;c Set cutoff
283
284mt_tick0_c:
285              .IF (NOSETFILTCUTOFF == 0)
286                sta mt_filtcutoff+1
287                rts
288              .ENDIF
289
290        ;d Set mastervolume / timing mark
291
292mt_tick0_d:
293              .IF (NOSETMASTERVOL == 0)
294              .IF (NOAUTHORINFO == 0)
295                cmp #$10
296                bcs mt_tick0_d_timing
297              .ENDIF
298mt_setmastervol:
299                sta mt_masterfader+1
300                rts
301              .IF (NOAUTHORINFO == 0)
302mt_tick0_d_timing:
303                sta mt_author+31
304                rts
305              .ENDIF
306              .ENDIF
307
308        ;e Funktempo
309
310mt_tick0_e:
311              .IF (NOFUNKTEMPO == 0)
312                tay
313                lda mt_speedlefttbl-1,y
314                sta mt_funktempotbl
315                lda mt_speedrighttbl-1,y
316                sta mt_funktempotbl+1
317                lda #$00
318              .IF (NOCHANNELTEMPO == 0)
319                beq mt_tick0_f_setglobaltempo
320              .ENDIF
321              .ENDIF
322
323        ;f Set Tempo
324
325mt_tick0_f:
326              .IF ((NOCHANNELTEMPO == 0) && (NOGLOBALTEMPO == 0))
327                bmi mt_tick0_f_setchantempo     ;Channel or global tempo?
328              .ENDIF
329mt_tick0_f_setglobaltempo:
330              .IF (NOGLOBALTEMPO == 0)
331                sta mt_chntempo
332              .IF (NUMCHANNELS > 1)
333                sta mt_chntempo+7
334              .ENDIF
335              .IF (NUMCHANNELS > 2)
336                sta mt_chntempo+14
337              .ENDIF
338                rts
339              .ENDIF
340mt_tick0_f_setchantempo:
341              .IF (NOCHANNELTEMPO == 0)
342                and #$7f
343                sta mt_chntempo,x
344                rts
345              .ENDIF
346
347        ;Continuous effect code
348
349        ;0 Instrument vibrato
350
351              .IF (NOINSTRVIB == 0)
352mt_effect_0_delay:
353                dec mt_chnvibdelay,x
354mt_effect_0_donothing:
355                jmp mt_done
356mt_effect_0:    beq mt_effect_0_donothing         ;Speed 0 = no vibrato at all
357                lda mt_chnvibdelay,x
358                bne mt_effect_0_delay
359              .ELSE
360mt_effect_0:
361mt_effect_0_donothing:
362                jmp mt_done
363              .ENDIF
364
365        ;4 Vibrato
366
367mt_effect_4:
368              .IF (NOVIB == 0)
369              .IF (NOCALCULATEDSPEED == 0)
370                lda mt_speedlefttbl-1,y
371              .IF (NONORMALSPEED == 0)
372                bmi mt_effect_4_nohibyteclear
373                ldy #$00                        ;Clear speed highbyte
374                sty <mt_temp2
375              .ENDIF
376mt_effect_4_nohibyteclear:
377                and #$7f
378                sta mt_effect_4_speedcmp+1
379              .ELSE
380                lda #$00                        ;Clear speed highbyte
381                sta <mt_temp2
382              .ENDIF
383                lda mt_chnvibtime,x
384                bmi mt_effect_4_nodir
385              .IF (NOCALCULATEDSPEED != 0)
386                cmp mt_speedlefttbl-1,y
387              .ELSE
388mt_effect_4_speedcmp:
389                cmp #$00
390              .ENDIF
391                bcc mt_effect_4_nodir2
392                beq mt_effect_4_nodir
393                eor #$ff
394mt_effect_4_nodir:
395                clc
396mt_effect_4_nodir2:
397                adc #$02
398mt_vibdone:
399                sta mt_chnvibtime,x
400                lsr
401                bcc mt_freqadd
402                bcs mt_freqsub
403              .ENDIF
404
405        ;1,2,3 Portamentos
406
407mt_effect_3:
408              .IF (NOTONEPORTA == 0)
409                tya
410                beq mt_effect_3_found           ;Speed $00 = tie note
411              .ENDIF
412mt_effect_12:
413              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0))
414              .IF (NOCALCULATEDSPEED != 0)
415                lda mt_speedlefttbl-1,y
416                sta <mt_temp2
417              .ENDIF
418              .ENDIF
419              .IF (NOPORTAMENTO == 0)
420
421              .IF (NOWAVECMD != 0)
422                lda mt_chnfx,x
423              .ELSE
424mt_effectnum:
425                lda #$00
426              .ENDIF
427                cmp #$02
428                bcc mt_freqadd
429                beq mt_freqsub
430              .ELSE
431              .IF (NOTONEPORTA == 0)
432                sec
433              .ENDIF
434              .ENDIF
435              .IF (NOTONEPORTA == 0)
436                ldy mt_chnnote,y
437              .IF (GHOSTREGS == 0)
438                lda mt_chnfreqlo,x              ;Calculate offset to the
439                sbc mt_freqtbllo-FIRSTNOTE,y    ;right frequency
440                pha
441                lda mt_chnfreqhi,x
442              .ELSE
443                lda <ghostfreqlo,x              ;Calculate offset to the
444                sbc mt_freqtbllo-FIRSTNOTE,y    ;right frequency
445                pha
446                lda <ghostfreqhi,x
447              .ENDIF
448                sbc mt_freqtblhi-FIRSTNOTE,y
449                tay
450                pla
451                bcs mt_effect_3_down            ;If positive, have to go down
452
453mt_effect_3_up:
454                adc <mt_temp1                   ;Add speed to offset
455                tya                             ;If changes sign, we're done
456                adc <mt_temp2
457                bpl mt_effect_3_found
458              .ENDIF
459
460
461              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
462mt_freqadd:
463              .IF (GHOSTREGS == 0)
464                lda mt_chnfreqlo,x
465                adc <mt_temp1
466                sta mt_chnfreqlo,x
467                lda mt_chnfreqhi,x
468              .ELSE
469                lda <ghostfreqlo,x
470                adc <mt_temp1
471                sta <ghostfreqlo,x
472                lda <ghostfreqhi,x
473              .ENDIF
474                adc <mt_temp2
475                jmp mt_storefreqhi
476              .ENDIF
477
478              .IF (NOTONEPORTA == 0)
479mt_effect_3_down:
480                sbc <mt_temp1                   ;Subtract speed from offset
481                tya                             ;If changes sign, we're done
482                sbc <mt_temp2
483                bmi mt_effect_3_found
484              .ENDIF
485
486              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
487mt_freqsub:
488              .IF (GHOSTREGS == 0)
489                lda mt_chnfreqlo,x
490                sbc <mt_temp1
491                sta mt_chnfreqlo,x
492                lda mt_chnfreqhi,x
493              .ELSE
494                lda <ghostfreqlo,x
495                sbc <mt_temp1
496                sta <ghostfreqlo,x
497                lda <ghostfreqhi,x
498              .ENDIF
499                sbc <mt_temp2
500                jmp mt_storefreqhi
501              .ENDIF
502
503mt_effect_3_found:
504              .IF (NOTONEPORTA == 0)
505              .IF (NOCALCULATEDSPEED == 0)
506                lda mt_chnnote,x
507                jmp mt_wavenoteabs
508              .ELSE
509                ldy mt_chnnote,y
510                jmp mt_wavenote
511              .ENDIF
512              .ENDIF
513
514        ;Init routine
515
516mt_init:
517              .IF (NUMSONGS > 1)
518                sta mt_init+5
519                asl
520                adc #$00
521              .ENDIF
522                sta mt_initsongnum+1
523                rts
524
525        ;Play soundeffect -routine
526
527              .IF (SOUNDSUPPORT != 0)
528        ;Sound FX init routine
529
530mt_playsfx:     sta mt_playsfxlo+1
531                sty mt_playsfxhi+1
532                lda mt_chnsfx,x                   ;Need a priority check?
533                beq mt_playsfxok
534                tya                               ;Check address highbyte
535                cmp mt_chnsfxhi,x
536                bcc mt_playsfxskip                ;Lower than current -> skip
537                bne mt_playsfxok                  ;Higher than current -> OK
538                lda mt_playsfxlo+1                ;Check address lowbyte
539                cmp mt_chnsfxlo,x
540                bcc mt_playsfxskip                ;Lower than current -> skip
541mt_playsfxok:   lda #$01
542                sta mt_chnsfx,x
543mt_playsfxlo:   lda #$00
544                sta mt_chnsfxlo,x
545mt_playsfxhi:   lda #$00
546                sta mt_chnsfxhi,x
547mt_playsfxskip: rts
548              .ENDIF
549
550        ;Set mastervolume -routine
551
552              .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0))
553mt_setmastervol:
554                sta mt_masterfader+1
555                rts
556              .ENDIF
557
558        ;Playroutine
559
560mt_play:
561                .IF ((ZPGHOSTREGS == 0) && (GHOSTREGS != 0))
562                ldx #0                          ;In full ghosting mode copy
563mt_copyregs:    lda ghostregs,x                 ;previous frame's SID values in one step
564                sta SIDBASE,x
565                inx
566                cpx #25
567                bne mt_copyregs
568                .ENDIF
569
570                ldx #$00                        ;Channel index
571
572        ;Song initialization
573
574mt_initsongnum:
575                ldy #$00
576                bmi mt_filtstep
577                txa
578                ldx #NUMCHANNELS * 14 - 1
579mt_resetloop:
580                sta mt_chnsongptr,x             ;Reset sequencer + voice
581                dex                             ;variables on all channels
582                bpl mt_resetloop
583              .IF (GHOSTREGS == 0)
584              .IF (NUMCHANNELS == 2)
585                sta SIDBASE+$12
586              .ENDIF
587              .IF (NUMCHANNELS == 1)
588                sta SIDBASE+$0b
589                sta SIDBASE+$12
590              .ENDIF
591                sta SIDBASE+$15                       ;Reset filter cutoff lowbyte
592              .ELSE
593                sta <ghostfiltcutlow
594              .ENDIF
595                sta mt_filtctrl+1             ;Switch filter off & reset
596              .IF (NOFILTER == 0)
597                sta mt_filtstep+1             ;step-programming
598              .ENDIF
599                stx mt_initsongnum+1          ;Reset initflag
600                tax
601              .IF (NUMCHANNELS == 3)
602                jsr mt_initchn
603                ldx #$07
604                jsr mt_initchn
605                ldx #$0e
606              .ENDIF
607              .IF (NUMCHANNELS == 2)
608                jsr mt_initchn
609                ldx #$07
610              .ENDIF
611mt_initchn:
612              .IF (NUMSONGS > 1)
613                tya
614                iny
615                sta mt_chnsongnum,x             ;Store index to songtable
616              .ENDIF
617mt_defaulttempo:
618                lda #DEFAULTTEMPO               ;Set default tempo
619                sta mt_chntempo,x
620                lda #$01
621                sta mt_chncounter,x             ;Reset counter
622                sta mt_chninstr,x               ;Reset instrument
623                jmp mt_loadregswave             ;Load waveform
624
625        ;Filter execution
626
627mt_filtstep:
628              .IF (NOFILTER == 0)
629                ldy #$00                        ;See if filter stopped
630                beq mt_filtdone
631              .IF (NOFILTERMOD == 0)
632mt_filttime:
633                lda #$00                        ;See if time left for mod.
634                bne mt_filtmod                  ;step
635              .ENDIF
636mt_newfiltstep:
637                lda mt_filttimetbl-1,y          ;$80-> = set filt parameters
638                beq mt_setcutoff                ;$00 = set cutoff
639              .IF (NOFILTERMOD == 0)
640                bpl mt_newfiltmod
641              .ENDIF
642mt_setfilt:
643                asl                             ;Set passband
644                sta mt_filttype+1
645                lda mt_filtspdtbl-1,y           ;Set resonance/channel
646                sta mt_filtctrl+1
647                lda mt_filttimetbl,y            ;Check for cutoff setting
648                bne mt_nextfiltstep2            ;following immediately
649mt_setcutoff2:
650                iny
651mt_setcutoff:
652                lda mt_filtspdtbl-1,y           ;Take cutoff value
653                sta mt_filtcutoff+1
654              .IF (NOFILTERMOD == 0)
655                jmp mt_nextfiltstep
656mt_newfiltmod:
657                sta mt_filttime+1               ;$01-$7f = new modulation step
658mt_filtmod:
659                lda mt_filtspdtbl-1,y           ;Take filt speed
660                clc
661                adc mt_filtcutoff+1
662                sta mt_filtcutoff+1
663                dec mt_filttime+1
664                bne mt_storecutoff
665              .ENDIF
666mt_nextfiltstep:
667                lda mt_filttimetbl,y           ;Jump in filttable?
668mt_nextfiltstep2:
669                cmp #LOOPFILT
670                iny
671                tya
672                bcc mt_nofiltjump
673                lda mt_filtspdtbl-1,y          ;Take jump point
674mt_nofiltjump:
675                sta mt_filtstep+1
676mt_filtdone:
677mt_filtcutoff:
678                lda #$00
679mt_storecutoff:
680              .IF (GHOSTREGS == 0)
681                sta SIDBASE+$16
682              .ELSE
683                sta <ghostfiltcutoff
684              .ENDIF
685              .ENDIF
686mt_filtctrl:
687                lda #$00
688              .IF (GHOSTREGS == 0)
689                sta SIDBASE+$17
690              .ELSE
691                sta <ghostfiltctrl
692              .ENDIF
693mt_filttype:
694                lda #$00
695mt_masterfader:
696                ora #$0f                        ;Master volume fader
697              .IF (GHOSTREGS == 0)
698                sta SIDBASE+$18
699              .ELSE
700                sta <ghostfilttype
701              .ENDIF
702
703              .IF (NUMCHANNELS == 3)
704                jsr mt_execchn
705                ldx #$07
706                jsr mt_execchn
707                ldx #$0e
708              .ENDIF
709              .IF (NUMCHANNELS == 2)
710                jsr mt_execchn
711                ldx #$07
712              .ENDIF
713
714        ;Channel execution
715
716mt_execchn:
717                dec mt_chncounter,x               ;See if tick 0
718                beq mt_tick0
719
720        ;Ticks 1-n
721
722mt_notick0:
723                bpl mt_effects
724                lda mt_chntempo,x               ;Reload tempo if negative
725
726              .IF (NOFUNKTEMPO == 0)
727                cmp #$02
728                bcs mt_nofunktempo              ;Funktempo: bounce between
729                tay                             ;funktable indexes 0,1
730                eor #$01
731                sta mt_chntempo,x
732                lda mt_funktempotbl,y
733                sbc #$00
734              .ENDIF
735
736mt_nofunktempo:
737                sta mt_chncounter,x
738mt_effects:
739                jmp mt_waveexec
740
741        ;Sequencer repeat
742
743mt_repeat:
744              .IF (NOREPEAT == 0)
745                sbc #REPEAT
746                inc mt_chnrepeat,x
747                cmp mt_chnrepeat,x
748                bne mt_nonewpatt
749mt_repeatdone:
750                lda #$00
751                sta mt_chnrepeat,x
752                beq mt_repeatdone2
753              .ENDIF
754
755        ;Tick 0
756
757mt_tick0:
758              .IF (NOEFFECTS == 0)
759                ldy mt_chnnewfx,y               ;Setup tick 0 FX jumps
760                lda mt_tick0jumptbl,y
761                sta mt_tick0jump1+1
762                sta mt_tick0jump2+1
763              .ENDIF
764
765        ;Sequencer advance
766
767mt_checknewpatt:
768                lda mt_chnpattptr,x             ;Fetch next pattern?
769                bne mt_nonewpatt
770mt_sequencer:
771                ldy mt_chnsongnum,y
772                lda mt_songtbllo,y              ;Get address of sequence
773                sta <mt_temp1
774                lda mt_songtblhi,y
775                sta <mt_temp2
776                ldy mt_chnsongptr,y
777                lda (mt_temp1),y                ;Get pattern from sequence
778                cmp #LOOPSONG                   ;Check for loop
779                bcc mt_noloop
780                iny
781                lda (mt_temp1),y
782                tay
783                lda (mt_temp1),y
784mt_noloop:
785              .IF (NOTRANS == 0)
786                cmp #TRANSDOWN                  ;Check for transpose
787                bcc mt_notrans
788                sbc #TRANS
789                sta mt_chntrans,x
790                iny
791                lda (mt_temp1),y
792              .ENDIF
793mt_notrans:
794              .IF (NOREPEAT == 0)
795                cmp #REPEAT                     ;Check for repeat
796                bcs mt_repeat
797              .ENDIF
798                sta mt_chnpattnum,x             ;Store pattern number
799mt_repeatdone2:
800                iny
801                tya
802                sta mt_chnsongptr,x             ;Store songposition
803
804        ;New note start
805
806mt_nonewpatt:
807                ldy mt_chninstr,y
808              .IF (FIXEDPARAMS == 0)
809                lda mt_insgatetimer-1,y
810                sta mt_chngatetimer,x
811              .ENDIF
812                lda mt_chnnewnote,x             ;Test new note init flag
813                beq mt_nonewnoteinit
814mt_newnoteinit:
815                sec
816                sbc #NOTE
817                sta mt_chnnote,x
818                lda #$00
819              .IF (NOEFFECTS == 0)
820              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
821                sta mt_chnfx,x                  ;Reset effect
822              .ENDIF
823              .ENDIF
824                sta mt_chnnewnote,x             ;Reset newnote action
825              .IF (NOINSTRVIB == 0)
826                lda mt_insvibdelay-1,y          ;Load instrument vibrato
827                sta mt_chnvibdelay,x
828              .IF (NOEFFECTS == 0)
829                lda mt_insvibparam-1,y
830                sta mt_chnparam,x
831              .ENDIF
832              .ENDIF
833              .IF (NOTONEPORTA == 0)
834                lda mt_chnnewfx,x               ;If toneportamento, skip
835                cmp #TONEPORTA                  ;most of note init
836                beq mt_nonewnoteinit
837              .ENDIF
838
839              .IF (FIXEDPARAMS == 0)
840                lda mt_insfirstwave-1,y         ;Load first frame waveform
841              .IF (NOFIRSTWAVECMD == 0)
842                beq mt_skipwave
843                cmp #$fe
844                bcs mt_skipwave2                ;Skip waveform but load gate
845              .ENDIF
846              .ELSE
847                lda #FIRSTWAVEPARAM
848              .ENDIF
849                sta mt_chnwave,x
850              .IF ((BUFFEREDWRITES == 0) && (NOFIRSTWAVECMD != 0))
851                sta SIDBASE+$04,x
852              .ENDIF
853              .IF ((NUMLEGATOINSTR > 0) || (NOFIRSTWAVECMD == 0))
854                lda #$ff
855mt_skipwave2:
856                sta mt_chngate,x                ;Reset gateflag
857              .ELSE
858                inc mt_chngate,x
859              .ENDIF
860mt_skipwave:
861
862              .IF ((BUFFEREDWRITES == 0) && (NOFIRSTWAVECMD == 0))
863                lda mt_chnwave,x
864                and mt_chngate,x
865                sta SIDBASE+$04,x
866              .ENDIF
867
868                lda mt_inswaveptr-1,y           ;Load waveptr
869                sta mt_chnwaveptr,x
870              .IF (NOPULSE == 0)
871                lda mt_inspulseptr-1,y          ;Load pulseptr (if nonzero)
872                beq mt_skippulse
873                sta mt_chnpulseptr,x
874              .IF (NOPULSEMOD == 0)
875                lda #$00                        ;Reset pulse step duration
876                sta mt_chnpulsetime,x
877              .ENDIF
878              .ENDIF
879mt_skippulse:
880              .IF (NOFILTER == 0)
881                lda mt_insfiltptr-1,y         ;Load filtptr (if nonzero)
882                beq mt_skipfilt
883                sta mt_filtstep+1
884              .IF (NOFILTERMOD == 0)
885                lda #$00
886                sta mt_filttime+1
887              .ENDIF
888              .ENDIF
889mt_skipfilt:
890
891                lda mt_insad-1,y                ;Load Attack/Decay
892              .IF (BUFFEREDWRITES == 0)
893                sta SIDBASE+$05,x
894              .ELSE
895              .IF (GHOSTREGS == 0)
896                sta mt_chnad,x
897              .ELSE
898                sta <ghostad,x
899              .ENDIF
900              .ENDIF
901                lda mt_inssr-1,y                ;Load Sustain/Release
902              .IF (BUFFEREDWRITES == 0)
903                sta SIDBASE+$06,x
904              .ELSE
905              .IF (GHOSTREGS == 0)
906                sta mt_chnsr,x
907              .ELSE
908                sta <ghostsr,x
909              .ENDIF
910              .ENDIF
911
912              .IF (NOEFFECTS == 0)
913                lda mt_chnnewparam,x            ;Execute tick 0 FX after
914mt_tick0jump1:                                  ;newnote init
915              .IF (BUFFEREDWRITES == 0)
916                jmp mt_tick0_0
917              .ELSE
918                jsr mt_tick0_0
919                jmp mt_loadregs
920              .ENDIF
921              .ELSE
922              .IF (BUFFEREDWRITES == 0)
923                rts
924              .ELSE
925                jmp mt_loadregs
926              .ENDIF
927              .ENDIF
928
929              .IF (NOWAVECMD == 0)
930mt_wavecmd:
931                jmp mt_execwavecmd
932              .ENDIF
933
934        ;Tick 0 effect execution
935
936mt_nonewnoteinit:
937              .IF (NOEFFECTS == 0)
938                lda mt_chnnewparam,x            ;No new note init: exec tick 0
939mt_tick0jump2:
940                jsr mt_tick0_0                  ;FX, and wavetable afterwards
941              .ENDIF
942
943        ;Wavetable execution
944
945mt_waveexec:
946                ldy mt_chnwaveptr,y
947                beq mt_wavedone
948                lda mt_wavetbl-1,y
949              .IF (NOWAVEDELAY == 0)
950                cmp #$10                        ;0-15 used as delay
951                bcs mt_nowavedelay              ;+ no wave change
952                cmp mt_chnwavetime,x
953                beq mt_nowavechange
954                inc mt_chnwavetime,x
955                bne mt_wavedone
956mt_nowavedelay:
957                sbc #$10
958              .ELSE
959                beq mt_nowavechange
960              .ENDIF
961              .IF (NOWAVECMD == 0)
962                cmp #$e0
963                bcs mt_nowavechange
964              .ENDIF
965                sta mt_chnwave,x
966mt_nowavechange:
967                lda mt_wavetbl,y
968                cmp #LOOPWAVE                  ;Check for wavetable jump
969                iny
970                tya
971                bcc mt_nowavejump
972              .IF (NOWAVECMD != 0)
973                clc
974              .ENDIF
975                lda mt_notetbl-1,y
976mt_nowavejump:
977                sta mt_chnwaveptr,x
978              .IF (NOWAVEDELAY == 0)
979                lda #$00
980                sta mt_chnwavetime,x
981              .ENDIF
982
983              .IF (NOWAVECMD == 0)
984                lda mt_wavetbl-2,y
985                cmp #$e0
986                bcs mt_wavecmd
987              .ENDIF
988
989                lda mt_notetbl-2,y
990
991              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
992                bne mt_wavefreq                 ;No frequency-change?
993
994        ;No frequency-change / continuous effect execution
995
996mt_wavedone:
997              .IF (REALTIMEOPTIMIZATION != 0)
998                lda mt_chncounter,x             ;No continuous effects on tick0
999              .IF (PULSEOPTIMIZATION != 0)
1000                beq mt_gatetimer
1001              .ELSE
1002                beq mt_done
1003              .ENDIF
1004              .ENDIF
1005              .IF (NOEFFECTS == 0)
1006                ldy mt_chnfx,y
1007              .IF (NOWAVECMD == 0)
1008              .IF (.DEFINED(mt_effectnum))
1009                sty mt_effectnum+1
1010              .ENDIF
1011              .ENDIF
1012                lda mt_effectjumptbl,y
1013                sta mt_effectjump+1
1014                ldy mt_chnparam,y
1015              .ELSE
1016                ldy mt_chninstr,y
1017                lda mt_insvibparam-1,y
1018                tay
1019              .ENDIF
1020mt_setspeedparam:
1021              .IF (NOCALCULATEDSPEED != 0)
1022                lda mt_speedrighttbl-1,y
1023                sta <mt_temp1
1024              .ELSE
1025              .IF (NONORMALSPEED == 0)
1026                lda mt_speedlefttbl-1,y
1027                bmi mt_calculatedspeed
1028mt_normalspeed:
1029                sta <mt_temp2
1030                lda mt_speedrighttbl-1,y
1031                sta <mt_temp1
1032                jmp mt_effectjump
1033              .ELSE
1034              .IF (NOZEROSPEED == 0)
1035                bne mt_calculatedspeed
1036mt_zerospeed:
1037                sty <mt_temp1
1038                sty <mt_temp2
1039                beq mt_effectjump
1040              .ENDIF
1041              .ENDIF
1042mt_calculatedspeed:
1043                lda mt_speedrighttbl-1,y
1044                sta mt_cscount+1
1045                sty mt_csresty+1
1046                ldy mt_chnlastnote,y
1047                lda mt_freqtbllo+1-FIRSTNOTE,y
1048                sec
1049                sbc mt_freqtbllo-FIRSTNOTE,y
1050                sta <mt_temp1
1051                lda mt_freqtblhi+1-FIRSTNOTE,y
1052                sbc mt_freqtblhi-FIRSTNOTE,y
1053mt_cscount:     ldy #$00
1054                beq mt_csresty
1055mt_csloop:      lsr
1056                ror <mt_temp1
1057                dey
1058                bne mt_csloop
1059mt_csresty:     ldy #$00
1060                sta <mt_temp2
1061              .ENDIF
1062mt_effectjump:
1063                jmp mt_effect_0
1064              .ELSE
1065                beq mt_wavedone
1066              .ENDIF
1067
1068        ;Setting note frequency
1069
1070mt_wavefreq:
1071                bpl mt_wavenoteabs
1072                adc mt_chnnote,x
1073                and #$7f
1074mt_wavenoteabs:
1075              .IF (NOCALCULATEDSPEED == 0)
1076                sta mt_chnlastnote,x
1077              .ENDIF
1078                tay
1079mt_wavenote:
1080              .IF (NOVIB == 0)
1081                lda #$00                        ;Reset vibrato phase
1082                sta mt_chnvibtime,x
1083              .ENDIF
1084                lda mt_freqtbllo-FIRSTNOTE,y
1085              .IF (GHOSTREGS == 0)
1086                sta mt_chnfreqlo,x
1087                lda mt_freqtblhi-FIRSTNOTE,y
1088mt_storefreqhi:
1089                sta mt_chnfreqhi,x
1090              .ELSE
1091                sta <ghostfreqlo,x
1092                lda mt_freqtblhi-FIRSTNOTE,y
1093mt_storefreqhi:
1094                sta <ghostfreqhi,x
1095              .ENDIF
1096
1097        ;Check for new note fetch
1098
1099              .IF ((NOTONEPORTA != 0) && (NOPORTAMENTO != 0) && (NOVIB != 0))
1100mt_wavedone:
1101              .ENDIF
1102mt_done:
1103              .IF (PULSEOPTIMIZATION != 0)
1104                lda mt_chncounter,x             ;Check for gateoff timer
1105mt_gatetimer:
1106              .IF (FIXEDPARAMS == 0)
1107                cmp mt_chngatetimer,x
1108              .ELSE
1109                cmp #GATETIMERPARAM
1110              .ENDIF
1111
1112                beq mt_getnewnote               ;Fetch new notes if equal
1113              .ENDIF
1114
1115        ;Pulse execution
1116              .IF (NOPULSE == 0)
1117mt_pulseexec:
1118                ldy mt_chnpulseptr,y            ;See if pulse stopped
1119                beq mt_pulseskip
1120              .IF (PULSEOPTIMIZATION != 0)
1121                ora mt_chnpattptr,x             ;Skip when sequencer executed
1122                beq mt_pulseskip
1123              .ENDIF
1124              .IF (NOPULSEMOD == 0)
1125                lda mt_chnpulsetime,x           ;Pulse step counter time left?
1126                bne mt_pulsemod
1127              .ENDIF
1128mt_newpulsestep:
1129                lda mt_pulsetimetbl-1,y         ;Set pulse, or new modulation
1130              .IF (NOPULSEMOD == 0)
1131                bpl mt_newpulsemod              ;step?
1132              .ENDIF
1133mt_setpulse:
1134              .IF (SIMPLEPULSE == 0)
1135              .IF (GHOSTREGS == 0)
1136                sta mt_chnpulsehi,x             ;Highbyte
1137              .ELSE
1138                sta <ghostpulsehi,x
1139              .ENDIF
1140              .ENDIF
1141                lda mt_pulsespdtbl-1,y          ;Lowbyte
1142              .IF (GHOSTREGS == 0)
1143                sta mt_chnpulselo,x
1144              .ELSE
1145                sta <ghostpulselo,x
1146              .IF (SIMPLEPULSE != 0)
1147                sta <ghostpulsehi,x
1148              .ENDIF
1149              .ENDIF
1150              .IF (NOPULSEMOD == 0)
1151                jmp mt_nextpulsestep
1152mt_newpulsemod:
1153                sta mt_chnpulsetime,x
1154mt_pulsemod:
1155              .IF (SIMPLEPULSE == 0)
1156                lda mt_pulsespdtbl-1,y          ;Take pulse speed
1157                clc
1158                bpl mt_pulseup
1159              .IF (GHOSTREGS == 0)
1160                dec mt_chnpulsehi,x
1161mt_pulseup:
1162                adc mt_chnpulselo,x             ;Add pulse lowbyte
1163                sta mt_chnpulselo,x
1164                bcc mt_pulsenotover
1165                inc mt_chnpulsehi,x
1166              .ELSE
1167                dec <ghostpulsehi,x
1168mt_pulseup:
1169                adc <ghostpulselo,x             ;Add pulse lowbyte
1170                sta <ghostpulselo,x
1171                bcc mt_pulsenotover
1172                inc <ghostpulsehi,x
1173              .ENDIF
1174mt_pulsenotover:
1175              .ELSE
1176              .IF (GHOSTREGS == 0)
1177                lda mt_chnpulselo,x
1178                clc
1179                adc mt_pulsespdtbl-1,y
1180                adc #$00
1181                sta mt_chnpulselo,x
1182              .ELSE
1183                lda <ghostpulselo,x
1184                clc
1185                adc mt_pulsespdtbl-1,y
1186                adc #$00
1187                sta <ghostpulselo,x
1188                sta <ghostpulsehi,x
1189              .ENDIF
1190              .ENDIF
1191                dec mt_chnpulsetime,x
1192                bne mt_pulsedone2
1193              .ENDIF
1194
1195mt_nextpulsestep:
1196                lda mt_pulsetimetbl,y           ;Jump in pulsetable?
1197                cmp #LOOPPULSE
1198                iny
1199                tya
1200                bcc mt_nopulsejump
1201                lda mt_pulsespdtbl-1,y          ;Take jump point
1202mt_nopulsejump:
1203                sta mt_chnpulseptr,x
1204mt_pulsedone:
1205              .IF (BUFFEREDWRITES == 0)
1206                lda mt_chnpulselo,x
1207              .ENDIF
1208mt_pulsedone2:
1209              .IF (BUFFEREDWRITES == 0)
1210                sta SIDBASE+$02,x
1211              .IF (SIMPLEPULSE == 0)
1212                lda mt_chnpulsehi,x
1213              .ENDIF
1214                sta SIDBASE+$03,x
1215              .ENDIF
1216mt_pulseskip:
1217              .ENDIF
1218
1219              .IF (PULSEOPTIMIZATION == 0)
1220                lda mt_chncounter,x             ;Check for gateoff timer
1221mt_gatetimer:
1222              .IF (FIXEDPARAMS == 0)
1223                cmp mt_chngatetimer,x
1224              .ELSE
1225                cmp #GATETIMERPARAM
1226              .ENDIF
1227
1228                beq mt_getnewnote               ;Fetch new notes if equal
1229              .ENDIF
1230
1231                jmp mt_loadregs
1232
1233        ;New note fetch
1234
1235mt_getnewnote:
1236                ldy mt_chnpattnum,y
1237                lda mt_patttbllo,y
1238                sta <mt_temp1
1239                lda mt_patttblhi,y
1240                sta <mt_temp2
1241                ldy mt_chnpattptr,y
1242                lda (mt_temp1),y
1243                cmp #FX
1244                bcc mt_instr                    ;Instr. change
1245              .IF (NOEFFECTS == 0)
1246                cmp #NOTE
1247                bcc mt_fx                       ;FX
1248              .ENDIF
1249                cmp #FIRSTPACKEDREST
1250                bcc mt_note                     ;Note only
1251
1252        ;Packed rest handling
1253
1254mt_packedrest:
1255                lda mt_chnpackedrest,x
1256                bne mt_packedrestnonew
1257                lda (mt_temp1),y
1258mt_packedrestnonew:
1259                adc #$00
1260                sta mt_chnpackedrest,x
1261                beq mt_rest
1262                bne mt_loadregs
1263
1264        ;Instrument change
1265
1266mt_instr:
1267                sta mt_chninstr,x               ;Instrument change, followed
1268                iny
1269                lda (mt_temp1),y                ;by either FX or note
1270
1271              .IF (NOEFFECTS == 0)
1272                cmp #NOTE
1273                bcs mt_note
1274
1275        ;Effect change
1276
1277mt_fx:
1278                cmp #FXONLY                     ;Note follows?
1279                and #$0f
1280                sta mt_chnnewfx,x
1281                beq mt_fx_noparam               ;Effect 0 - no param.
1282                iny
1283                lda (mt_temp1),y
1284                sta mt_chnnewparam,x
1285mt_fx_noparam:
1286                bcs mt_rest
1287mt_fx_getnote:
1288                iny
1289                lda (mt_temp1),y
1290              .ENDIF
1291
1292        ;Note handling
1293
1294mt_note:
1295                cmp #REST                   ;Rest or gateoff/on?
1296              .IF (NOGATE == 0)
1297                bcc mt_normalnote
1298              .ENDIF
1299                beq mt_rest
1300mt_gate:
1301              .IF (NOGATE == 0)
1302                ora #$f0
1303                bne mt_setgate
1304              .ENDIF
1305
1306        ;Prepare for note start; perform hardrestart
1307
1308mt_normalnote:
1309              .IF (NOTRANS == 0)
1310                adc mt_chntrans,x
1311              .ENDIF
1312                sta mt_chnnewnote,x
1313              .IF (NOTONEPORTA == 0)
1314                lda mt_chnnewfx,x           ;If toneportamento, no gateoff
1315                cmp #TONEPORTA
1316                beq mt_rest
1317              .ENDIF
1318              .IF (((NUMHRINSTR > 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0))
1319                lda mt_chninstr,x
1320                cmp #FIRSTNOHRINSTR         ;Instrument order:
1321              .IF (NUMLEGATOINSTR > 0)
1322                bcs mt_nohr_legato          ;With HR - no HR - legato
1323              .ELSE
1324                bcs mt_skiphr
1325              .ENDIF
1326              .ENDIF
1327              .IF (NUMHRINSTR > 0)
1328                lda #ADPARAM                ;Hard restart
1329              .IF (BUFFEREDWRITES == 0)
1330                sta SIDBASE+$05,x
1331              .ELSE
1332              .IF (GHOSTREGS == 0)
1333                sta mt_chnad,x
1334              .ELSE
1335                sta <ghostad,x
1336              .ENDIF
1337              .ENDIF
1338                lda #SRPARAM
1339              .IF (BUFFEREDWRITES == 0)
1340                sta SIDBASE+$06,x
1341              .ELSE
1342              .IF (GHOSTREGS == 0)
1343                sta mt_chnsr,x
1344              .ELSE
1345                sta <ghostsr,x
1346              .ENDIF
1347              .ENDIF
1348              .ENDIF
1349mt_skiphr:
1350                lda #$fe
1351mt_setgate:
1352                sta mt_chngate,x
1353
1354        ;Check for end of pattern
1355
1356mt_rest:
1357                iny
1358                lda (mt_temp1),y
1359                beq mt_endpatt
1360                tya
1361mt_endpatt:
1362                sta mt_chnpattptr,x
1363
1364        ;Load voice registers
1365
1366mt_loadregs:
1367              .IF (BUFFEREDWRITES == 0)
1368mt_loadregswave:lda mt_chnwave,x
1369                and mt_chngate,x
1370                sta SIDBASE+$04,x
1371                lda mt_chnfreqlo,x
1372                sta SIDBASE+$00,x
1373                lda mt_chnfreqhi,x
1374                sta SIDBASE+$01,x
1375              .ELSE
1376              .IF (SOUNDSUPPORT != 0)
1377                ldy mt_chnsfx,y
1378                bne mt_sfxexec
1379              .ENDIF
1380              .IF (GHOSTREGS == 0)
1381mt_loadregswave:lda mt_chnwave,x
1382                and mt_chngate,x
1383                sta SIDBASE+$04,x
1384                lda mt_chnfreqlo,x
1385                sta SIDBASE+$00,x
1386                lda mt_chnfreqhi,x
1387                sta SIDBASE+$01,x
1388                lda mt_chnpulselo,x
1389              .IF (SIMPLEPULSE == 0)
1390                sta SIDBASE+$02,x
1391                lda mt_chnpulsehi,x
1392                sta SIDBASE+$03,x
1393              .ELSE
1394                sta SIDBASE+$02,x
1395                sta SIDBASE+$03,x
1396              .ENDIF
1397              .IF (SOUNDSUPPORT != 0)
1398                lda mt_chnsfx,x
1399                bne mt_loadskipadsr
1400              .ENDIF
1401                lda mt_chnad,x
1402                sta SIDBASE+$05,x
1403                lda mt_chnsr,x
1404                sta SIDBASE+$06,x
1405mt_loadskipadsr:
1406              .ELSE
1407mt_loadregswave:lda mt_chnwave,x
1408                and mt_chngate,x
1409                sta <ghostwave,x
1410              .ENDIF
1411              .ENDIF
1412                rts
1413
1414              .IF (NUMLEGATOINSTR > 0)
1415mt_nohr_legato:
1416                cmp #FIRSTLEGATOINSTR
1417                bcc mt_skiphr
1418                bcs mt_rest
1419              .ENDIF
1420
1421        ;Sound FX code
1422
1423              .IF (SOUNDSUPPORT != 0)
1424              .IF (GHOSTREGS == 0)
1425
1426        ;Sound FX code without ghostregs
1427
1428mt_sfxexec:     lda mt_chnsfxlo,x
1429                sta <mt_temp1
1430                lda mt_chnsfxhi,x
1431                sta <mt_temp2
1432                lda #$fe
1433                sta mt_chngate,x
1434                lda #$00
1435                sta mt_chnwaveptr,x
1436                inc mt_chnsfx,x
1437                cpy #$02
1438                beq mt_sfxexec_frame0
1439                bcs mt_sfxexec_framen
1440                sta SIDBASE+$05,x                ;Hardrestart before sound FX
1441                sta SIDBASE+$06,x                ;begins
1442                bcc mt_loadregswave
1443mt_sfxexec_frame0:
1444                tay
1445                lda (mt_temp1),y           ;Load ADSR
1446                sta SIDBASE+$05,x
1447                iny
1448                lda (mt_temp1),y
1449                sta SIDBASE+$06,x
1450                iny
1451                lda (mt_temp1),y           ;Load pulse
1452                sta SIDBASE+$02,x
1453                sta SIDBASE+$03,x
1454                lda #$09                   ;Testbit
1455mt_sfxexec_wavechg:
1456                sta mt_chnwave,x
1457                sta SIDBASE+$04,x
1458mt_sfxexec_done:
1459                rts
1460mt_sfxexec_framen:
1461                lda (mt_temp1),y
1462                bne mt_sfxexec_noend
1463mt_sfxexec_end:
1464                sta mt_chnsfx,x
1465                beq mt_sfxexec_wavechg
1466mt_sfxexec_noend:
1467                tay
1468                lda mt_freqtbllo-$80,y        ;Get frequency
1469                sta SIDBASE+$00,x
1470                lda mt_freqtblhi-$80,y
1471                sta SIDBASE+$01,x
1472                ldy mt_chnsfx,y
1473                lda (mt_temp1),y              ;Then take a look at the next
1474                beq mt_sfxexec_done           ;byte
1475                cmp #$82                      ;Is it a waveform or a note?
1476                bcs mt_sfxexec_done
1477                inc mt_chnsfx,x
1478                bcc mt_sfxexec_wavechg
1479
1480              .ELSE
1481
1482        ;Sound FX code with ghostregs
1483
1484mt_sfxexec:
1485                lda mt_chnsfxlo,x
1486                sta <mt_temp1
1487                lda mt_chnsfxhi,x
1488                sta <mt_temp2
1489                lda #$fe
1490                sta mt_chngate,x
1491                lda #$00
1492                sta mt_chnwaveptr,x
1493                inc mt_chnsfx,x
1494                cpy #$02
1495                bcc mt_sfxexec_fr1                  ;Hardrestart frame?
1496                beq mt_sfxexec_fr2                  ;First or nth frame?
1497mt_sfxexec_fr3:
1498                lda (mt_temp1),y
1499                bne mt_sfxexec_noend
1500mt_sfxexec_end:
1501                sta mt_chnsfx,x
1502                beq mt_sfxexec_wavechg
1503mt_sfxexec_noend:
1504                tay
1505                lda mt_freqtbllo-$80,y        ;Get frequency
1506                sta <ghostfreqlo,x
1507                lda mt_freqtblhi-$80,y
1508                sta <ghostfreqhi,x
1509                ldy mt_chnsfx,y
1510                lda (mt_temp1),y              ;Then take a look at the next
1511                beq mt_sfxexec_done           ;byte
1512                cmp #$82                      ;Is it a waveform or a note?
1513                bcs mt_sfxexec_done
1514                inc mt_chnsfx,x
1515mt_sfxexec_wavechg:
1516                sta mt_chnwave,x
1517                sta <ghostwave,x
1518mt_sfxexec_done:
1519                ldy #$00
1520                lda (mt_temp1),y             ;Load ADSR
1521                sta <ghostad,x
1522                iny
1523                lda (mt_temp1),y
1524                sta <ghostsr,x
1525                iny
1526                lda (mt_temp1),y             ;Load pulse
1527                sta <ghostpulselo,x
1528                sta <ghostpulsehi,x
1529                rts
1530
1531mt_sfxexec_fr1:
1532                sta <ghostad,x               ;Hardrestart before sound FX
1533                sta <ghostsr,x               ;begins
1534                bcc mt_loadregswave
1535
1536mt_sfxexec_fr2:
1537                lda #$09
1538                bne mt_sfxexec_wavechg
1539
1540              .ENDIF
1541              .ENDIF
1542
1543        ;Wavetable command exec
1544
1545              .IF (NOWAVECMD == 0)
1546mt_execwavecmd:
1547                and #$0f
1548                sta <mt_temp1
1549                lda mt_notetbl-2,y
1550                sta <mt_temp2
1551                ldy <mt_temp1
1552              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
1553                cpy #$05
1554                bcs mt_execwavetick0
1555mt_execwavetickn:
1556              .IF (.DEFINED(mt_effectnum))
1557                sty mt_effectnum+1
1558              .ENDIF
1559                lda mt_effectjumptbl,y
1560                sta mt_effectjump+1
1561                ldy <mt_temp2
1562                jmp mt_setspeedparam
1563              .ENDIF
1564mt_execwavetick0:
1565                lda mt_tick0jumptbl,y
1566                sta mt_execwavetick0jump+1
1567                lda <mt_temp2
1568mt_execwavetick0jump:
1569                jsr mt_tick0_0
1570                jmp mt_done
1571              .ENDIF
1572
1573              .IF (NOEFFECTS == 0)
1574              .IF (!.DEFINED(mt_tick0jumptbl))
1575mt_tick0jumptbl:
1576                .BYTE (mt_tick0_0 % 256)
1577                .BYTE (mt_tick0_12 % 256)
1578                .BYTE (mt_tick0_12 % 256)
1579                .BYTE (mt_tick0_34 % 256)
1580                .BYTE (mt_tick0_34 % 256)
1581                .BYTE (mt_tick0_5 % 256)
1582                .BYTE (mt_tick0_6 % 256)
1583                .BYTE (mt_tick0_7 % 256)
1584                .BYTE (mt_tick0_8 % 256)
1585                .BYTE (mt_tick0_9 % 256)
1586                .BYTE (mt_tick0_a % 256)
1587                .BYTE (mt_tick0_b % 256)
1588                .BYTE (mt_tick0_c % 256)
1589                .BYTE (mt_tick0_d % 256)
1590                .BYTE (mt_tick0_e % 256)
1591                .BYTE (mt_tick0_f % 256)
1592              .ENDIF
1593              .ENDIF
1594
1595              .IF (NOEFFECTS == 0)
1596              .IF (!.DEFINED(mt_effectjumptbl))
1597              .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0))
1598mt_effectjumptbl:
1599                .BYTE (mt_effect_0 % 256)
1600                .BYTE (mt_effect_12 % 256)
1601                .BYTE (mt_effect_12 % 256)
1602                .BYTE (mt_effect_3 % 256)
1603                .BYTE (mt_effect_4 % 256)
1604              .ENDIF
1605              .ENDIF
1606              .ENDIF
1607
1608              .IF (!.DEFINED(mt_funktempotbl))
1609              .IF (NOFUNKTEMPO == 0)
1610mt_funktempotbl:
1611                .BYTE (8,5)
1612              .ENDIF
1613              .ENDIF
1614
1615              .IF ((NOEFFECTS == 0) || (NOWAVEDELAY == 0) || (NOTRANS == 0) || (NOREPEAT == 0) || (FIXEDPARAMS == 0) || (GHOSTREGS != 0) || (BUFFEREDWRITES != 0) || (NOCALCULATEDSPEED == 0))
1616
1617              ;Normal channel variables
1618
1619mt_chnsongptr:
1620                .BYTE (0)
1621mt_chntrans:
1622                .BYTE (0)
1623mt_chnrepeat:
1624                .BYTE (0)
1625mt_chnpattptr:
1626                .BYTE (0)
1627mt_chnpackedrest:
1628                .BYTE (0)
1629mt_chnnewfx:
1630                .BYTE (0)
1631mt_chnnewparam:
1632                .BYTE (0)
1633
1634              .IF (NUMCHANNELS > 1)
1635                .BYTE (0,0,0,0,0,0,0)
1636              .ENDIF
1637              .IF (NUMCHANNELS > 2)
1638                .BYTE (0,0,0,0,0,0,0)
1639              .ENDIF
1640
1641mt_chnfx:
1642                .BYTE (0)
1643mt_chnparam:
1644                .BYTE (0)
1645mt_chnnewnote:
1646                .BYTE (0)
1647mt_chnwaveptr:
1648                .BYTE (0)
1649mt_chnwave:
1650                .BYTE (0)
1651mt_chnpulseptr:
1652                .BYTE (0)
1653mt_chnpulsetime:
1654                .BYTE (0)
1655
1656              .IF (NUMCHANNELS > 1)
1657                .BYTE (0,0,0,0,0,0,0)
1658              .ENDIF
1659              .IF (NUMCHANNELS > 2)
1660                .BYTE (0,0,0,0,0,0,0)
1661              .ENDIF
1662
1663mt_chnsongnum:
1664                .BYTE (0)
1665mt_chnpattnum:
1666                .BYTE (0)
1667mt_chntempo:
1668                .BYTE (0)
1669mt_chncounter:
1670                .BYTE (0)
1671mt_chnnote:
1672                .BYTE (0)
1673mt_chninstr:
1674                .BYTE (1)
1675mt_chngate:
1676                .BYTE ($fe)
1677
1678              .IF (NUMCHANNELS > 1)
1679                .BYTE (1,0,0,0,0,1,$fe)
1680              .ENDIF
1681              .IF (NUMCHANNELS > 2)
1682                .BYTE (2,0,0,0,0,1,$fe)
1683              .ENDIF
1684
1685              .IF ((GHOSTREGS == 0) || (NOCALCULATEDSPEED == 0))
1686
1687mt_chnvibtime:
1688                .BYTE (0)
1689mt_chnvibdelay:
1690                .BYTE (0)
1691mt_chnwavetime:
1692                .BYTE (0)
1693mt_chnfreqlo:
1694                .BYTE (0)
1695mt_chnfreqhi:
1696                .BYTE (0)
1697mt_chnpulselo:
1698                .BYTE (0)
1699mt_chnpulsehi:
1700                .BYTE (0)
1701
1702              .IF (NUMCHANNELS > 1)
1703                .BYTE (0,0,0,0,0,0,0)
1704              .ENDIF
1705              .IF (NUMCHANNELS > 2)
1706                .BYTE (0,0,0,0,0,0,0)
1707              .ENDIF
1708
1709              .IF ((BUFFEREDWRITES != 0) || (FIXEDPARAMS == 0) || (NOCALCULATEDSPEED == 0))
1710mt_chnad:
1711                .BYTE (0)
1712mt_chnsr:
1713                .BYTE (0)
1714mt_chnsfx:
1715                .BYTE (0)
1716mt_chnsfxlo:
1717                .BYTE (0)
1718mt_chnsfxhi:
1719                .BYTE (0)
1720mt_chngatetimer:
1721                .BYTE (0)
1722mt_chnlastnote:
1723                .BYTE (0)
1724
1725              .IF (NUMCHANNELS > 1)
1726                .BYTE (0,0,0,0,0,0,0)
1727              .ENDIF
1728              .IF (NUMCHANNELS > 2)
1729                .BYTE (0,0,0,0,0,0,0)
1730              .ENDIF
1731
1732              .ENDIF
1733
1734              .ELSE
1735
1736mt_chnvibtime:
1737                .BYTE (0)
1738mt_chnvibdelay:
1739                .BYTE (0)
1740mt_chnwavetime:
1741                .BYTE (0)
1742mt_chnsfx:
1743                .BYTE (0)
1744mt_chnsfxlo:
1745                .BYTE (0)
1746mt_chnsfxhi:
1747                .BYTE (0)
1748mt_chngatetimer:
1749                .BYTE (0)
1750
1751              .IF (NUMCHANNELS > 1)
1752                .BYTE (0,0,0,0,0,0,0)
1753              .ENDIF
1754              .IF (NUMCHANNELS > 2)
1755                .BYTE (0,0,0,0,0,0,0)
1756              .ENDIF
1757
1758              .ENDIF
1759
1760              .ELSE
1761
1762              ;Optimized channel variables
1763
1764mt_chnsongptr:
1765                .BYTE (0)
1766mt_chnpattptr:
1767                .BYTE (0)
1768mt_chnpackedrest:
1769                .BYTE (0)
1770mt_chnnewnote:
1771                .BYTE (0)
1772mt_chnwaveptr:
1773                .BYTE (0)
1774mt_chnwave:
1775                .BYTE (0)
1776mt_chnpulseptr:
1777                .BYTE (0)
1778
1779              .IF (NUMCHANNELS > 1)
1780                .BYTE (0,0,0,0,0,0,0)
1781              .ENDIF
1782              .IF (NUMCHANNELS > 2)
1783                .BYTE (0,0,0,0,0,0,0)
1784              .ENDIF
1785
1786mt_chnpulsetime:
1787                .BYTE (0)
1788mt_chnpulselo:
1789                .BYTE (0)
1790mt_chnpulsehi:
1791                .BYTE (0)
1792mt_chnvibtime:
1793                .BYTE (0)
1794mt_chnvibdelay:
1795                .BYTE (0)
1796mt_chnfreqlo:
1797                .BYTE (0)
1798mt_chnfreqhi:
1799                .BYTE (0)
1800
1801              .IF (NUMCHANNELS > 1)
1802                .BYTE (0,0,0,0,0,0,0)
1803              .ENDIF
1804              .IF (NUMCHANNELS > 2)
1805                .BYTE (0,0,0,0,0,0,0)
1806              .ENDIF
1807
1808mt_chnsongnum:
1809                .BYTE (0)
1810mt_chnpattnum:
1811                .BYTE (0)
1812mt_chntempo:
1813                .BYTE (0)
1814mt_chncounter:
1815                .BYTE (0)
1816mt_chnnote:
1817                .BYTE (0)
1818mt_chninstr:
1819                .BYTE (1)
1820mt_chngate:
1821                .BYTE ($fe)
1822
1823              .IF (NUMCHANNELS > 1)
1824                .BYTE (1,0,0,0,0,1,$fe)
1825              .ENDIF
1826              .IF (NUMCHANNELS > 2)
1827                .BYTE (2,0,0,0,0,1,$fe)
1828              .ENDIF
1829
1830              .ENDIF
1831
1832              .IF ((GHOSTREGS != 0) && (ZPGHOSTREGS == 0))
1833ghostregs:    .BYTE (0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0)
1834ghostfreqlo     = ghostregs+0
1835ghostfreqhi     = ghostregs+1
1836ghostpulselo    = ghostregs+2
1837ghostpulsehi    = ghostregs+3
1838ghostwave       = ghostregs+4
1839ghostad         = ghostregs+5
1840ghostsr         = ghostregs+6
1841ghostfiltcutlow = ghostregs+21
1842ghostfiltcutoff = ghostregs+22
1843ghostfiltctrl   = ghostregs+23
1844ghostfilttype   = ghostregs+24
1845              .ENDIF
1846
1847        ;Songdata & frequencytable will be inserted by the relocator here
1848
1849