1;------------------------------------------------------------------------------- 2; GoatTracker V2.73 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 #24 ;In full ghosting mode copy 563mt_copyregs: lda ghostregs,x ;previous frame's SID values in one step 564 sta SIDBASE,x 565 dex 566 bpl mt_copyregs 567 .ENDIF 568 569 ldx #$00 ;Channel index 570 571 ;Song initialization 572 573mt_initsongnum: 574 ldy #$00 575 bmi mt_filtstep 576 txa 577 ldx #NUMCHANNELS * 14 - 1 578mt_resetloop: 579 sta mt_chnsongptr,x ;Reset sequencer + voice 580 dex ;variables on all channels 581 bpl mt_resetloop 582 .IF (GHOSTREGS == 0) 583 .IF (NUMCHANNELS == 2) 584 sta SIDBASE+$12 585 .ENDIF 586 .IF (NUMCHANNELS == 1) 587 sta SIDBASE+$0b 588 sta SIDBASE+$12 589 .ENDIF 590 sta SIDBASE+$15 ;Reset filter cutoff lowbyte 591 .ELSE 592 sta <ghostfiltcutlow 593 .ENDIF 594 sta mt_filtctrl+1 ;Switch filter off & reset 595 .IF (NOFILTER == 0) 596 sta mt_filtstep+1 ;step-programming 597 .ENDIF 598 stx mt_initsongnum+1 ;Reset initflag 599 tax 600 .IF (NUMCHANNELS == 3) 601 jsr mt_initchn 602 ldx #$07 603 jsr mt_initchn 604 ldx #$0e 605 .ENDIF 606 .IF (NUMCHANNELS == 2) 607 jsr mt_initchn 608 ldx #$07 609 .ENDIF 610mt_initchn: 611 .IF (NUMSONGS > 1) 612 tya 613 iny 614 sta mt_chnsongnum,x ;Store index to songtable 615 .ENDIF 616mt_defaulttempo: 617 lda #DEFAULTTEMPO ;Set default tempo 618 sta mt_chntempo,x 619 lda #$01 620 sta mt_chncounter,x ;Reset counter 621 sta mt_chninstr,x ;Reset instrument 622 jmp mt_loadregswaveonly ;Load waveform 623 624 ;Filter execution 625 626mt_filtstep: 627 .IF (NOFILTER == 0) 628 ldy #$00 ;See if filter stopped 629 beq mt_filtdone 630 .IF (NOFILTERMOD == 0) 631mt_filttime: 632 lda #$00 ;See if time left for mod. 633 bne mt_filtmod ;step 634 .ENDIF 635mt_newfiltstep: 636 lda mt_filttimetbl-1,y ;$80-> = set filt parameters 637 beq mt_setcutoff ;$00 = set cutoff 638 .IF (NOFILTERMOD == 0) 639 bpl mt_newfiltmod 640 .ENDIF 641mt_setfilt: 642 asl ;Set passband 643 sta mt_filttype+1 644 lda mt_filtspdtbl-1,y ;Set resonance/channel 645 sta mt_filtctrl+1 646 lda mt_filttimetbl,y ;Check for cutoff setting 647 bne mt_nextfiltstep2 ;following immediately 648mt_setcutoff2: 649 iny 650mt_setcutoff: 651 lda mt_filtspdtbl-1,y ;Take cutoff value 652 sta mt_filtcutoff+1 653 .IF (NOFILTERMOD == 0) 654 jmp mt_nextfiltstep 655mt_newfiltmod: 656 sta mt_filttime+1 ;$01-$7f = new modulation step 657mt_filtmod: 658 lda mt_filtspdtbl-1,y ;Take filt speed 659 clc 660 adc mt_filtcutoff+1 661 sta mt_filtcutoff+1 662 dec mt_filttime+1 663 bne mt_storecutoff 664 .ENDIF 665mt_nextfiltstep: 666 lda mt_filttimetbl,y ;Jump in filttable? 667mt_nextfiltstep2: 668 cmp #LOOPFILT 669 iny 670 tya 671 bcc mt_nofiltjump 672 lda mt_filtspdtbl-1,y ;Take jump point 673mt_nofiltjump: 674 sta mt_filtstep+1 675mt_filtdone: 676mt_filtcutoff: 677 lda #$00 678mt_storecutoff: 679 .IF (GHOSTREGS == 0) 680 sta SIDBASE+$16 681 .ELSE 682 sta <ghostfiltcutoff 683 .ENDIF 684 .ENDIF 685mt_filtctrl: 686 lda #$00 687 .IF (GHOSTREGS == 0) 688 sta SIDBASE+$17 689 .ELSE 690 sta <ghostfiltctrl 691 .ENDIF 692mt_filttype: 693 lda #$00 694mt_masterfader: 695 ora #$0f ;Master volume fader 696 .IF (GHOSTREGS == 0) 697 sta SIDBASE+$18 698 .ELSE 699 sta <ghostfilttype 700 .ENDIF 701 702 .IF (NUMCHANNELS == 3) 703 jsr mt_execchn 704 ldx #$07 705 jsr mt_execchn 706 ldx #$0e 707 .ENDIF 708 .IF (NUMCHANNELS == 2) 709 jsr mt_execchn 710 ldx #$07 711 .ENDIF 712 713 ;Channel execution 714 715mt_execchn: 716 dec mt_chncounter,x ;See if tick 0 717 beq mt_tick0 718 719 ;Ticks 1-n 720 721mt_notick0: 722 bpl mt_effects 723 lda mt_chntempo,x ;Reload tempo if negative 724 725 .IF (NOFUNKTEMPO == 0) 726 cmp #$02 727 bcs mt_nofunktempo ;Funktempo: bounce between 728 tay ;funktable indexes 0,1 729 eor #$01 730 sta mt_chntempo,x 731 lda mt_funktempotbl,y 732 sbc #$00 733 .ENDIF 734 735mt_nofunktempo: 736 sta mt_chncounter,x 737mt_effects: 738 jmp mt_waveexec 739 740 ;Sequencer repeat 741 742mt_repeat: 743 .IF (NOREPEAT == 0) 744 sbc #REPEAT 745 inc mt_chnrepeat,x 746 cmp mt_chnrepeat,x 747 bne mt_nonewpatt 748mt_repeatdone: 749 lda #$00 750 sta mt_chnrepeat,x 751 beq mt_repeatdone2 752 .ENDIF 753 754 ;Tick 0 755 756mt_tick0: 757 .IF (NOEFFECTS == 0) 758 ldy mt_chnnewfx,y ;Setup tick 0 FX jumps 759 lda mt_tick0jumptbl,y 760 sta mt_tick0jump1+1 761 sta mt_tick0jump2+1 762 .ENDIF 763 764 ;Sequencer advance 765 766mt_checknewpatt: 767 lda mt_chnpattptr,x ;Fetch next pattern? 768 bne mt_nonewpatt 769mt_sequencer: 770 ldy mt_chnsongnum,y 771 lda mt_songtbllo,y ;Get address of sequence 772 sta <mt_temp1 773 lda mt_songtblhi,y 774 sta <mt_temp2 775 ldy mt_chnsongptr,y 776 lda (mt_temp1),y ;Get pattern from sequence 777 cmp #LOOPSONG ;Check for loop 778 bcc mt_noloop 779 iny 780 lda (mt_temp1),y 781 tay 782 lda (mt_temp1),y 783mt_noloop: 784 .IF (NOTRANS == 0) 785 cmp #TRANSDOWN ;Check for transpose 786 bcc mt_notrans 787 sbc #TRANS 788 sta mt_chntrans,x 789 iny 790 lda (mt_temp1),y 791 .ENDIF 792mt_notrans: 793 .IF (NOREPEAT == 0) 794 cmp #REPEAT ;Check for repeat 795 bcs mt_repeat 796 .ENDIF 797 sta mt_chnpattnum,x ;Store pattern number 798mt_repeatdone2: 799 iny 800 tya 801 sta mt_chnsongptr,x ;Store songposition 802 803 ;New note start 804 805mt_nonewpatt: 806 ldy mt_chninstr,y 807 .IF (FIXEDPARAMS == 0) 808 lda mt_insgatetimer-1,y 809 sta mt_chngatetimer,x 810 .ENDIF 811 lda mt_chnnewnote,x ;Test new note init flag 812 beq mt_nonewnoteinit 813mt_newnoteinit: 814 sec 815 sbc #NOTE 816 sta mt_chnnote,x 817 lda #$00 818 .IF (NOEFFECTS == 0) 819 .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) 820 sta mt_chnfx,x ;Reset effect 821 .ENDIF 822 .ENDIF 823 sta mt_chnnewnote,x ;Reset newnote action 824 .IF (NOINSTRVIB == 0) 825 lda mt_insvibdelay-1,y ;Load instrument vibrato 826 sta mt_chnvibdelay,x 827 .IF (NOEFFECTS == 0) 828 lda mt_insvibparam-1,y 829 sta mt_chnparam,x 830 .ENDIF 831 .ENDIF 832 .IF (NOTONEPORTA == 0) 833 lda mt_chnnewfx,x ;If toneportamento, skip 834 cmp #TONEPORTA ;most of note init 835 beq mt_nonewnoteinit 836 .ENDIF 837 838 .IF (FIXEDPARAMS == 0) 839 lda mt_insfirstwave-1,y ;Load first frame waveform 840 .IF (NOFIRSTWAVECMD == 0) 841 beq mt_skipwave 842 cmp #$fe 843 bcs mt_skipwave2 ;Skip waveform but load gate 844 .ENDIF 845 .ELSE 846 lda #FIRSTWAVEPARAM 847 .ENDIF 848 sta mt_chnwave,x 849 .IF ((NUMLEGATOINSTR > 0) || (NOFIRSTWAVECMD == 0)) 850 lda #$ff 851mt_skipwave2: 852 sta mt_chngate,x ;Reset gateflag 853 .ELSE 854 inc mt_chngate,x 855 .ENDIF 856mt_skipwave: 857 858 .IF (NOPULSE == 0) 859 lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) 860 beq mt_skippulse 861 sta mt_chnpulseptr,x 862 .IF (NOPULSEMOD == 0) 863 lda #$00 ;Reset pulse step duration 864 sta mt_chnpulsetime,x 865 .ENDIF 866 .ENDIF 867mt_skippulse: 868 .IF (NOFILTER == 0) 869 lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) 870 beq mt_skipfilt 871 sta mt_filtstep+1 872 .IF (NOFILTERMOD == 0) 873 lda #$00 874 sta mt_filttime+1 875 .ENDIF 876 .ENDIF 877mt_skipfilt: 878 879 lda mt_inswaveptr-1,y ;Load waveptr 880 sta mt_chnwaveptr,x 881 882 lda mt_inssr-1,y ;Load Sustain/Release 883 .IF (BUFFEREDWRITES == 0) 884 sta SIDBASE+$06,x 885 .ELSE 886 .IF (GHOSTREGS == 0) 887 sta mt_chnsr,x 888 .ELSE 889 sta <ghostsr,x 890 .ENDIF 891 .ENDIF 892 lda mt_insad-1,y ;Load Attack/Decay 893 .IF (BUFFEREDWRITES == 0) 894 sta SIDBASE+$05,x 895 .ELSE 896 .IF (GHOSTREGS == 0) 897 sta mt_chnad,x 898 .ELSE 899 sta <ghostad,x 900 .ENDIF 901 .ENDIF 902 903 .IF (NOEFFECTS == 0) 904 lda mt_chnnewparam,x ;Execute tick 0 FX after 905mt_tick0jump1: ;newnote init 906 jsr mt_tick0_0 907 .ENDIF 908 .IF (BUFFEREDWRITES == 0) 909 jmp mt_loadregswaveonly 910 .ELSE 911 jmp mt_loadregs 912 .ENDIF 913 914 .IF (NOWAVECMD == 0) 915mt_wavecmd: 916 jmp mt_execwavecmd 917 .ENDIF 918 919 ;Tick 0 effect execution 920 921mt_nonewnoteinit: 922 .IF (NOEFFECTS == 0) 923 lda mt_chnnewparam,x ;No new note init: exec tick 0 924mt_tick0jump2: 925 jsr mt_tick0_0 ;FX, and wavetable afterwards 926 .ENDIF 927 928 ;Wavetable execution 929 930mt_waveexec: 931 ldy mt_chnwaveptr,y 932 beq mt_wavedone 933 lda mt_wavetbl-1,y 934 .IF (NOWAVEDELAY == 0) 935 cmp #$10 ;0-15 used as delay 936 bcs mt_nowavedelay ;+ no wave change 937 cmp mt_chnwavetime,x 938 beq mt_nowavechange 939 inc mt_chnwavetime,x 940 bne mt_wavedone 941mt_nowavedelay: 942 sbc #$10 943 .ELSE 944 beq mt_nowavechange 945 .ENDIF 946 .IF (NOWAVECMD == 0) 947 cmp #$e0 948 bcs mt_nowavechange 949 .ENDIF 950 sta mt_chnwave,x 951mt_nowavechange: 952 lda mt_wavetbl,y 953 cmp #LOOPWAVE ;Check for wavetable jump 954 iny 955 tya 956 bcc mt_nowavejump 957 .IF (NOWAVECMD != 0) 958 clc 959 .ENDIF 960 lda mt_notetbl-1,y 961mt_nowavejump: 962 sta mt_chnwaveptr,x 963 .IF (NOWAVEDELAY == 0) 964 lda #$00 965 sta mt_chnwavetime,x 966 .ENDIF 967 968 .IF (NOWAVECMD == 0) 969 lda mt_wavetbl-2,y 970 cmp #$e0 971 bcs mt_wavecmd 972 .ENDIF 973 974 lda mt_notetbl-2,y 975 976 .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) 977 bne mt_wavefreq ;No frequency-change? 978 979 ;No frequency-change / continuous effect execution 980 981mt_wavedone: 982 .IF (REALTIMEOPTIMIZATION != 0) 983 lda mt_chncounter,x ;No continuous effects on tick0 984 .IF (PULSEOPTIMIZATION != 0) 985 beq mt_gatetimer 986 .ELSE 987 beq mt_done 988 .ENDIF 989 .ENDIF 990 .IF (NOEFFECTS == 0) 991 ldy mt_chnfx,y 992 .IF (NOWAVECMD == 0) 993 .IF (.DEFINED(mt_effectnum)) 994 sty mt_effectnum+1 995 .ENDIF 996 .ENDIF 997 lda mt_effectjumptbl,y 998 sta mt_effectjump+1 999 ldy mt_chnparam,y 1000 .ELSE 1001 ldy mt_chninstr,y 1002 lda mt_insvibparam-1,y 1003 tay 1004 .ENDIF 1005mt_setspeedparam: 1006 .IF (NOCALCULATEDSPEED != 0) 1007 lda mt_speedrighttbl-1,y 1008 sta <mt_temp1 1009 .ELSE 1010 .IF (NONORMALSPEED == 0) 1011 lda mt_speedlefttbl-1,y 1012 bmi mt_calculatedspeed 1013mt_normalspeed: 1014 sta <mt_temp2 1015 lda mt_speedrighttbl-1,y 1016 sta <mt_temp1 1017 jmp mt_effectjump 1018 .ELSE 1019 .IF (NOZEROSPEED == 0) 1020 bne mt_calculatedspeed 1021mt_zerospeed: 1022 sty <mt_temp1 1023 sty <mt_temp2 1024 beq mt_effectjump 1025 .ENDIF 1026 .ENDIF 1027mt_calculatedspeed: 1028 lda mt_speedrighttbl-1,y 1029 sta mt_cscount+1 1030 sty mt_csresty+1 1031 ldy mt_chnlastnote,y 1032 lda mt_freqtbllo+1-FIRSTNOTE,y 1033 sec 1034 sbc mt_freqtbllo-FIRSTNOTE,y 1035 sta <mt_temp1 1036 lda mt_freqtblhi+1-FIRSTNOTE,y 1037 sbc mt_freqtblhi-FIRSTNOTE,y 1038mt_cscount: ldy #$00 1039 beq mt_csresty 1040mt_csloop: lsr 1041 ror <mt_temp1 1042 dey 1043 bne mt_csloop 1044mt_csresty: ldy #$00 1045 sta <mt_temp2 1046 .ENDIF 1047mt_effectjump: 1048 jmp mt_effect_0 1049 .ELSE 1050 beq mt_wavedone 1051 .ENDIF 1052 1053 ;Setting note frequency 1054 1055mt_wavefreq: 1056 bpl mt_wavenoteabs 1057 adc mt_chnnote,x 1058 and #$7f 1059mt_wavenoteabs: 1060 .IF (NOCALCULATEDSPEED == 0) 1061 sta mt_chnlastnote,x 1062 .ENDIF 1063 tay 1064mt_wavenote: 1065 .IF (NOVIB == 0) 1066 lda #$00 ;Reset vibrato phase 1067 sta mt_chnvibtime,x 1068 .ENDIF 1069 lda mt_freqtbllo-FIRSTNOTE,y 1070 .IF (GHOSTREGS == 0) 1071 sta mt_chnfreqlo,x 1072 lda mt_freqtblhi-FIRSTNOTE,y 1073mt_storefreqhi: 1074 sta mt_chnfreqhi,x 1075 .ELSE 1076 sta <ghostfreqlo,x 1077 lda mt_freqtblhi-FIRSTNOTE,y 1078mt_storefreqhi: 1079 sta <ghostfreqhi,x 1080 .ENDIF 1081 1082 ;Check for new note fetch 1083 1084 .IF ((NOTONEPORTA != 0) && (NOPORTAMENTO != 0) && (NOVIB != 0)) 1085mt_wavedone: 1086 .ENDIF 1087mt_done: 1088 .IF (PULSEOPTIMIZATION != 0) 1089 lda mt_chncounter,x ;Check for gateoff timer 1090mt_gatetimer: 1091 .IF (FIXEDPARAMS == 0) 1092 cmp mt_chngatetimer,x 1093 .ELSE 1094 cmp #GATETIMERPARAM 1095 .ENDIF 1096 1097 beq mt_getnewnote ;Fetch new notes if equal 1098 .ENDIF 1099 1100 ;Pulse execution 1101 .IF (NOPULSE == 0) 1102mt_pulseexec: 1103 ldy mt_chnpulseptr,y ;See if pulse stopped 1104 beq mt_pulseskip 1105 .IF (PULSEOPTIMIZATION != 0) 1106 ora mt_chnpattptr,x ;Skip when sequencer executed 1107 beq mt_pulseskip 1108 .ENDIF 1109 .IF (NOPULSEMOD == 0) 1110 lda mt_chnpulsetime,x ;Pulse step counter time left? 1111 bne mt_pulsemod 1112 .ENDIF 1113mt_newpulsestep: 1114 lda mt_pulsetimetbl-1,y ;Set pulse, or new modulation 1115 .IF (NOPULSEMOD == 0) 1116 bpl mt_newpulsemod ;step? 1117 .ENDIF 1118mt_setpulse: 1119 .IF (SIMPLEPULSE == 0) 1120 .IF (GHOSTREGS == 0) 1121 sta mt_chnpulsehi,x ;Highbyte 1122 .ELSE 1123 sta <ghostpulsehi,x 1124 .ENDIF 1125 .ENDIF 1126 lda mt_pulsespdtbl-1,y ;Lowbyte 1127 .IF (GHOSTREGS == 0) 1128 sta mt_chnpulselo,x 1129 .ELSE 1130 sta <ghostpulselo,x 1131 .IF (SIMPLEPULSE != 0) 1132 sta <ghostpulsehi,x 1133 .ENDIF 1134 .ENDIF 1135 .IF (NOPULSEMOD == 0) 1136 jmp mt_nextpulsestep 1137mt_newpulsemod: 1138 sta mt_chnpulsetime,x 1139mt_pulsemod: 1140 .IF (SIMPLEPULSE == 0) 1141 lda mt_pulsespdtbl-1,y ;Take pulse speed 1142 clc 1143 bpl mt_pulseup 1144 .IF (GHOSTREGS == 0) 1145 dec mt_chnpulsehi,x 1146mt_pulseup: 1147 adc mt_chnpulselo,x ;Add pulse lowbyte 1148 sta mt_chnpulselo,x 1149 bcc mt_pulsenotover 1150 inc mt_chnpulsehi,x 1151 .ELSE 1152 dec <ghostpulsehi,x 1153mt_pulseup: 1154 adc <ghostpulselo,x ;Add pulse lowbyte 1155 sta <ghostpulselo,x 1156 bcc mt_pulsenotover 1157 inc <ghostpulsehi,x 1158 .ENDIF 1159mt_pulsenotover: 1160 .ELSE 1161 .IF (GHOSTREGS == 0) 1162 lda mt_chnpulselo,x 1163 clc 1164 adc mt_pulsespdtbl-1,y 1165 adc #$00 1166 sta mt_chnpulselo,x 1167 .ELSE 1168 lda <ghostpulselo,x 1169 clc 1170 adc mt_pulsespdtbl-1,y 1171 adc #$00 1172 sta <ghostpulselo,x 1173 sta <ghostpulsehi,x 1174 .ENDIF 1175 .ENDIF 1176 dec mt_chnpulsetime,x 1177 bne mt_pulsedone2 1178 .ENDIF 1179 1180mt_nextpulsestep: 1181 lda mt_pulsetimetbl,y ;Jump in pulsetable? 1182 cmp #LOOPPULSE 1183 iny 1184 tya 1185 bcc mt_nopulsejump 1186 lda mt_pulsespdtbl-1,y ;Take jump point 1187mt_nopulsejump: 1188 sta mt_chnpulseptr,x 1189mt_pulsedone: 1190 .IF (BUFFEREDWRITES == 0) 1191 lda mt_chnpulselo,x 1192 .ENDIF 1193mt_pulsedone2: 1194 .IF (BUFFEREDWRITES == 0) 1195 sta SIDBASE+$02,x 1196 .IF (SIMPLEPULSE == 0) 1197 lda mt_chnpulsehi,x 1198 .ENDIF 1199 sta SIDBASE+$03,x 1200 .ENDIF 1201mt_pulseskip: 1202 .ENDIF 1203 1204 .IF (PULSEOPTIMIZATION == 0) 1205 lda mt_chncounter,x ;Check for gateoff timer 1206mt_gatetimer: 1207 .IF (FIXEDPARAMS == 0) 1208 cmp mt_chngatetimer,x 1209 .ELSE 1210 cmp #GATETIMERPARAM 1211 .ENDIF 1212 1213 beq mt_getnewnote ;Fetch new notes if equal 1214 .ENDIF 1215 1216 jmp mt_loadregs 1217 1218 ;New note fetch 1219 1220mt_getnewnote: 1221 ldy mt_chnpattnum,y 1222 lda mt_patttbllo,y 1223 sta <mt_temp1 1224 lda mt_patttblhi,y 1225 sta <mt_temp2 1226 ldy mt_chnpattptr,y 1227 lda (mt_temp1),y 1228 cmp #FX 1229 bcc mt_instr ;Instr. change 1230 .IF (NOEFFECTS == 0) 1231 cmp #NOTE 1232 bcc mt_fx ;FX 1233 .ENDIF 1234 cmp #FIRSTPACKEDREST 1235 bcc mt_note ;Note only 1236 1237 ;Packed rest handling 1238 1239mt_packedrest: 1240 lda mt_chnpackedrest,x 1241 bne mt_packedrestnonew 1242 lda (mt_temp1),y 1243mt_packedrestnonew: 1244 adc #$00 1245 sta mt_chnpackedrest,x 1246 beq mt_rest 1247 bne mt_loadregs 1248 1249 ;Instrument change 1250 1251mt_instr: 1252 sta mt_chninstr,x ;Instrument change, followed 1253 iny 1254 lda (mt_temp1),y ;by either FX or note 1255 1256 .IF (NOEFFECTS == 0) 1257 cmp #NOTE 1258 bcs mt_note 1259 1260 ;Effect change 1261 1262mt_fx: 1263 cmp #FXONLY ;Note follows? 1264 and #$0f 1265 sta mt_chnnewfx,x 1266 beq mt_fx_noparam ;Effect 0 - no param. 1267 iny 1268 lda (mt_temp1),y 1269 sta mt_chnnewparam,x 1270mt_fx_noparam: 1271 bcs mt_rest 1272mt_fx_getnote: 1273 iny 1274 lda (mt_temp1),y 1275 .ENDIF 1276 1277 ;Note handling 1278 1279mt_note: 1280 cmp #REST ;Rest or gateoff/on? 1281 .IF (NOGATE == 0) 1282 bcc mt_normalnote 1283 .ENDIF 1284 beq mt_rest 1285mt_gate: 1286 .IF (NOGATE == 0) 1287 ora #$f0 1288 bne mt_setgate 1289 .ENDIF 1290 1291 ;Prepare for note start; perform hardrestart 1292 1293mt_normalnote: 1294 .IF (NOTRANS == 0) 1295 adc mt_chntrans,x 1296 .ENDIF 1297 sta mt_chnnewnote,x 1298 .IF (NOTONEPORTA == 0) 1299 lda mt_chnnewfx,x ;If toneportamento, no gateoff 1300 cmp #TONEPORTA 1301 beq mt_rest 1302 .ENDIF 1303 .IF (((NUMHRINSTR > 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) 1304 lda mt_chninstr,x 1305 cmp #FIRSTNOHRINSTR ;Instrument order: 1306 .IF (NUMLEGATOINSTR > 0) 1307 bcs mt_nohr_legato ;With HR - no HR - legato 1308 .ELSE 1309 bcs mt_skiphr 1310 .ENDIF 1311 .ENDIF 1312 .IF (NUMHRINSTR > 0) 1313 lda #SRPARAM ;Hard restart 1314 .IF (BUFFEREDWRITES == 0) 1315 sta SIDBASE+$06,x 1316 .ELSE 1317 .IF (GHOSTREGS == 0) 1318 sta mt_chnsr,x 1319 .ELSE 1320 sta <ghostsr,x 1321 .ENDIF 1322 .ENDIF 1323 lda #ADPARAM 1324 .IF (BUFFEREDWRITES == 0) 1325 sta SIDBASE+$05,x 1326 .ELSE 1327 .IF (GHOSTREGS == 0) 1328 sta mt_chnad,x 1329 .ELSE 1330 sta <ghostad,x 1331 .ENDIF 1332 .ENDIF 1333 1334 .ENDIF 1335mt_skiphr: 1336 lda #$fe 1337mt_setgate: 1338 sta mt_chngate,x 1339 1340 ;Check for end of pattern 1341 1342mt_rest: 1343 iny 1344 lda (mt_temp1),y 1345 beq mt_endpatt 1346 tya 1347mt_endpatt: 1348 sta mt_chnpattptr,x 1349 1350 ;Load voice registers 1351 1352mt_loadregs: 1353 .IF (BUFFEREDWRITES == 0) 1354 lda mt_chnfreqlo,x 1355 sta SIDBASE+$00,x 1356 lda mt_chnfreqhi,x 1357 sta SIDBASE+$01,x 1358mt_loadregswaveonly: 1359 lda mt_chnwave,x 1360 and mt_chngate,x 1361 sta SIDBASE+$04,x 1362 .ELSE 1363 .IF (SOUNDSUPPORT != 0) 1364 ldy mt_chnsfx,y 1365 bne mt_sfxexec 1366 .ENDIF 1367 .IF (GHOSTREGS == 0) 1368 lda mt_chnad,x 1369 sta SIDBASE+$05,x 1370 lda mt_chnsr,x 1371 sta SIDBASE+$06,x 1372 lda mt_chnpulselo,x 1373 .IF (SIMPLEPULSE == 0) 1374 sta SIDBASE+$02,x 1375 lda mt_chnpulsehi,x 1376 sta SIDBASE+$03,x 1377 .ELSE 1378 sta SIDBASE+$02,x 1379 sta SIDBASE+$03,x 1380 .ENDIF 1381mt_loadregswavefreq: 1382 lda mt_chnfreqlo,x 1383 sta SIDBASE+$00,x 1384 lda mt_chnfreqhi,x 1385 sta SIDBASE+$01,x 1386mt_loadregswaveonly: 1387 lda mt_chnwave,x 1388 and mt_chngate,x 1389 sta SIDBASE+$04,x 1390 .ELSE 1391mt_loadregswaveonly: 1392 lda mt_chnwave,x 1393 and mt_chngate,x 1394 sta <ghostwave,x 1395 .ENDIF 1396 .ENDIF 1397 rts 1398 1399 .IF (NUMLEGATOINSTR > 0) 1400mt_nohr_legato: 1401 cmp #FIRSTLEGATOINSTR 1402 bcc mt_skiphr 1403 bcs mt_rest 1404 .ENDIF 1405 1406 ;Sound FX code 1407 1408 .IF (SOUNDSUPPORT != 0) 1409 .IF (GHOSTREGS == 0) 1410 1411 ;Sound FX code without ghostregs 1412 1413mt_sfxexec: lda mt_chnsfxlo,x 1414 sta <mt_temp1 1415 lda mt_chnsfxhi,x 1416 sta <mt_temp2 1417 lda #$fe 1418 sta mt_chngate,x 1419 lda #$00 1420 sta mt_chnwaveptr,x 1421 inc mt_chnsfx,x 1422 cpy #$02 1423 beq mt_sfxexec_frame0 1424 bcs mt_sfxexec_framen 1425 sta SIDBASE+$06,x ;Hardrestart before sound FX 1426 sta SIDBASE+$05,x ;begins 1427 bcc mt_loadregswavefreq 1428mt_sfxexec_frame0: 1429 tay 1430 lda (mt_temp1),y ;Load ADSR 1431 sta SIDBASE+$05,x 1432 iny 1433 lda (mt_temp1),y 1434 sta SIDBASE+$06,x 1435 iny 1436 lda (mt_temp1),y ;Load pulse 1437 sta SIDBASE+$02,x 1438 sta SIDBASE+$03,x 1439 lda #$09 ;Testbit 1440mt_sfxexec_wavechg: 1441 sta mt_chnwave,x 1442 sta SIDBASE+$04,x 1443mt_sfxexec_done: 1444 rts 1445mt_sfxexec_framen: 1446 lda (mt_temp1),y 1447 bne mt_sfxexec_noend 1448mt_sfxexec_end: 1449 sta mt_chnsfx,x 1450 beq mt_sfxexec_wavechg 1451mt_sfxexec_noend: 1452 tay 1453 lda mt_freqtbllo-$80,y ;Get frequency 1454 sta SIDBASE+$00,x 1455 lda mt_freqtblhi-$80,y 1456 sta SIDBASE+$01,x 1457 ldy mt_chnsfx,y 1458 lda (mt_temp1),y ;Then take a look at the next 1459 beq mt_sfxexec_done ;byte 1460 cmp #$82 ;Is it a waveform or a note? 1461 bcs mt_sfxexec_done 1462 inc mt_chnsfx,x 1463 bcc mt_sfxexec_wavechg 1464 1465 .ELSE 1466 1467 ;Sound FX code with ghostregs 1468 1469mt_sfxexec: 1470 lda mt_chnsfxlo,x 1471 sta <mt_temp1 1472 lda mt_chnsfxhi,x 1473 sta <mt_temp2 1474 lda #$fe 1475 sta mt_chngate,x 1476 lda #$00 1477 sta mt_chnwaveptr,x 1478 inc mt_chnsfx,x 1479 cpy #$02 1480 bcc mt_sfxexec_fr1 ;Hardrestart frame? 1481 beq mt_sfxexec_fr2 ;First or nth frame? 1482mt_sfxexec_fr3: 1483 lda (mt_temp1),y 1484 bne mt_sfxexec_noend 1485mt_sfxexec_end: 1486 sta mt_chnsfx,x 1487 beq mt_sfxexec_wavechg 1488mt_sfxexec_noend: 1489 tay 1490 lda mt_freqtbllo-$80,y ;Get frequency 1491 sta <ghostfreqlo,x 1492 lda mt_freqtblhi-$80,y 1493 sta <ghostfreqhi,x 1494 ldy mt_chnsfx,y 1495 lda (mt_temp1),y ;Then take a look at the next 1496 beq mt_sfxexec_done ;byte 1497 cmp #$82 ;Is it a waveform or a note? 1498 bcs mt_sfxexec_done 1499 inc mt_chnsfx,x 1500mt_sfxexec_wavechg: 1501 sta mt_chnwave,x 1502 sta <ghostwave,x 1503mt_sfxexec_done: 1504 ldy #$00 1505 lda (mt_temp1),y ;Load ADSR 1506 sta <ghostad,x 1507 iny 1508 lda (mt_temp1),y 1509 sta <ghostsr,x 1510 iny 1511 lda (mt_temp1),y ;Load pulse 1512 sta <ghostpulselo,x 1513 sta <ghostpulsehi,x 1514 rts 1515 1516mt_sfxexec_fr1: 1517 sta <ghostad,x ;Hardrestart before sound FX 1518 sta <ghostsr,x ;begins 1519 bcc mt_loadregswaveonly 1520 1521mt_sfxexec_fr2: 1522 lda #$09 1523 bne mt_sfxexec_wavechg 1524 1525 .ENDIF 1526 .ENDIF 1527 1528 ;Wavetable command exec 1529 1530 .IF (NOWAVECMD == 0) 1531mt_execwavecmd: 1532 and #$0f 1533 sta <mt_temp1 1534 lda mt_notetbl-2,y 1535 sta <mt_temp2 1536 ldy <mt_temp1 1537 .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) 1538 cpy #$05 1539 bcs mt_execwavetick0 1540mt_execwavetickn: 1541 .IF (.DEFINED(mt_effectnum)) 1542 sty mt_effectnum+1 1543 .ENDIF 1544 lda mt_effectjumptbl,y 1545 sta mt_effectjump+1 1546 ldy <mt_temp2 1547 jmp mt_setspeedparam 1548 .ENDIF 1549mt_execwavetick0: 1550 lda mt_tick0jumptbl,y 1551 sta mt_execwavetick0jump+1 1552 lda <mt_temp2 1553mt_execwavetick0jump: 1554 jsr mt_tick0_0 1555 jmp mt_done 1556 .ENDIF 1557 1558 .IF (NOEFFECTS == 0) 1559 .IF (!.DEFINED(mt_tick0jumptbl)) 1560mt_tick0jumptbl: 1561 .BYTE (mt_tick0_0 % 256) 1562 .BYTE (mt_tick0_12 % 256) 1563 .BYTE (mt_tick0_12 % 256) 1564 .BYTE (mt_tick0_34 % 256) 1565 .BYTE (mt_tick0_34 % 256) 1566 .BYTE (mt_tick0_5 % 256) 1567 .BYTE (mt_tick0_6 % 256) 1568 .BYTE (mt_tick0_7 % 256) 1569 .BYTE (mt_tick0_8 % 256) 1570 .BYTE (mt_tick0_9 % 256) 1571 .BYTE (mt_tick0_a % 256) 1572 .BYTE (mt_tick0_b % 256) 1573 .BYTE (mt_tick0_c % 256) 1574 .BYTE (mt_tick0_d % 256) 1575 .BYTE (mt_tick0_e % 256) 1576 .BYTE (mt_tick0_f % 256) 1577 .ENDIF 1578 .ENDIF 1579 1580 .IF (NOEFFECTS == 0) 1581 .IF (!.DEFINED(mt_effectjumptbl)) 1582 .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) 1583mt_effectjumptbl: 1584 .BYTE (mt_effect_0 % 256) 1585 .BYTE (mt_effect_12 % 256) 1586 .BYTE (mt_effect_12 % 256) 1587 .BYTE (mt_effect_3 % 256) 1588 .BYTE (mt_effect_4 % 256) 1589 .ENDIF 1590 .ENDIF 1591 .ENDIF 1592 1593 .IF (!.DEFINED(mt_funktempotbl)) 1594 .IF (NOFUNKTEMPO == 0) 1595mt_funktempotbl: 1596 .BYTE (8,5) 1597 .ENDIF 1598 .ENDIF 1599 1600 .IF ((NOEFFECTS == 0) || (NOWAVEDELAY == 0) || (NOTRANS == 0) || (NOREPEAT == 0) || (FIXEDPARAMS == 0) || (GHOSTREGS != 0) || (BUFFEREDWRITES != 0) || (NOCALCULATEDSPEED == 0)) 1601 1602 ;Normal channel variables 1603 1604mt_chnsongptr: 1605 .BYTE (0) 1606mt_chntrans: 1607 .BYTE (0) 1608mt_chnrepeat: 1609 .BYTE (0) 1610mt_chnpattptr: 1611 .BYTE (0) 1612mt_chnpackedrest: 1613 .BYTE (0) 1614mt_chnnewfx: 1615 .BYTE (0) 1616mt_chnnewparam: 1617 .BYTE (0) 1618 1619 .IF (NUMCHANNELS > 1) 1620 .BYTE (0,0,0,0,0,0,0) 1621 .ENDIF 1622 .IF (NUMCHANNELS > 2) 1623 .BYTE (0,0,0,0,0,0,0) 1624 .ENDIF 1625 1626mt_chnfx: 1627 .BYTE (0) 1628mt_chnparam: 1629 .BYTE (0) 1630mt_chnnewnote: 1631 .BYTE (0) 1632mt_chnwaveptr: 1633 .BYTE (0) 1634mt_chnwave: 1635 .BYTE (0) 1636mt_chnpulseptr: 1637 .BYTE (0) 1638mt_chnpulsetime: 1639 .BYTE (0) 1640 1641 .IF (NUMCHANNELS > 1) 1642 .BYTE (0,0,0,0,0,0,0) 1643 .ENDIF 1644 .IF (NUMCHANNELS > 2) 1645 .BYTE (0,0,0,0,0,0,0) 1646 .ENDIF 1647 1648mt_chnsongnum: 1649 .BYTE (0) 1650mt_chnpattnum: 1651 .BYTE (0) 1652mt_chntempo: 1653 .BYTE (0) 1654mt_chncounter: 1655 .BYTE (0) 1656mt_chnnote: 1657 .BYTE (0) 1658mt_chninstr: 1659 .BYTE (1) 1660mt_chngate: 1661 .BYTE ($fe) 1662 1663 .IF (NUMCHANNELS > 1) 1664 .BYTE (1,0,0,0,0,1,$fe) 1665 .ENDIF 1666 .IF (NUMCHANNELS > 2) 1667 .BYTE (2,0,0,0,0,1,$fe) 1668 .ENDIF 1669 1670 .IF ((GHOSTREGS == 0) || (NOCALCULATEDSPEED == 0)) 1671 1672mt_chnvibtime: 1673 .BYTE (0) 1674mt_chnvibdelay: 1675 .BYTE (0) 1676mt_chnwavetime: 1677 .BYTE (0) 1678mt_chnfreqlo: 1679 .BYTE (0) 1680mt_chnfreqhi: 1681 .BYTE (0) 1682mt_chnpulselo: 1683 .BYTE (0) 1684mt_chnpulsehi: 1685 .BYTE (0) 1686 1687 .IF (NUMCHANNELS > 1) 1688 .BYTE (0,0,0,0,0,0,0) 1689 .ENDIF 1690 .IF (NUMCHANNELS > 2) 1691 .BYTE (0,0,0,0,0,0,0) 1692 .ENDIF 1693 1694 .IF ((BUFFEREDWRITES != 0) || (FIXEDPARAMS == 0) || (NOCALCULATEDSPEED == 0)) 1695mt_chnad: 1696 .BYTE (0) 1697mt_chnsr: 1698 .BYTE (0) 1699mt_chnsfx: 1700 .BYTE (0) 1701mt_chnsfxlo: 1702 .BYTE (0) 1703mt_chnsfxhi: 1704 .BYTE (0) 1705mt_chngatetimer: 1706 .BYTE (0) 1707mt_chnlastnote: 1708 .BYTE (0) 1709 1710 .IF (NUMCHANNELS > 1) 1711 .BYTE (0,0,0,0,0,0,0) 1712 .ENDIF 1713 .IF (NUMCHANNELS > 2) 1714 .BYTE (0,0,0,0,0,0,0) 1715 .ENDIF 1716 1717 .ENDIF 1718 1719 .ELSE 1720 1721mt_chnvibtime: 1722 .BYTE (0) 1723mt_chnvibdelay: 1724 .BYTE (0) 1725mt_chnwavetime: 1726 .BYTE (0) 1727mt_chnsfx: 1728 .BYTE (0) 1729mt_chnsfxlo: 1730 .BYTE (0) 1731mt_chnsfxhi: 1732 .BYTE (0) 1733mt_chngatetimer: 1734 .BYTE (0) 1735 1736 .IF (NUMCHANNELS > 1) 1737 .BYTE (0,0,0,0,0,0,0) 1738 .ENDIF 1739 .IF (NUMCHANNELS > 2) 1740 .BYTE (0,0,0,0,0,0,0) 1741 .ENDIF 1742 1743 .ENDIF 1744 1745 .ELSE 1746 1747 ;Optimized channel variables 1748 1749mt_chnsongptr: 1750 .BYTE (0) 1751mt_chnpattptr: 1752 .BYTE (0) 1753mt_chnpackedrest: 1754 .BYTE (0) 1755mt_chnnewnote: 1756 .BYTE (0) 1757mt_chnwaveptr: 1758 .BYTE (0) 1759mt_chnwave: 1760 .BYTE (0) 1761mt_chnpulseptr: 1762 .BYTE (0) 1763 1764 .IF (NUMCHANNELS > 1) 1765 .BYTE (0,0,0,0,0,0,0) 1766 .ENDIF 1767 .IF (NUMCHANNELS > 2) 1768 .BYTE (0,0,0,0,0,0,0) 1769 .ENDIF 1770 1771mt_chnpulsetime: 1772 .BYTE (0) 1773mt_chnpulselo: 1774 .BYTE (0) 1775mt_chnpulsehi: 1776 .BYTE (0) 1777mt_chnvibtime: 1778 .BYTE (0) 1779mt_chnvibdelay: 1780 .BYTE (0) 1781mt_chnfreqlo: 1782 .BYTE (0) 1783mt_chnfreqhi: 1784 .BYTE (0) 1785 1786 .IF (NUMCHANNELS > 1) 1787 .BYTE (0,0,0,0,0,0,0) 1788 .ENDIF 1789 .IF (NUMCHANNELS > 2) 1790 .BYTE (0,0,0,0,0,0,0) 1791 .ENDIF 1792 1793mt_chnsongnum: 1794 .BYTE (0) 1795mt_chnpattnum: 1796 .BYTE (0) 1797mt_chntempo: 1798 .BYTE (0) 1799mt_chncounter: 1800 .BYTE (0) 1801mt_chnnote: 1802 .BYTE (0) 1803mt_chninstr: 1804 .BYTE (1) 1805mt_chngate: 1806 .BYTE ($fe) 1807 1808 .IF (NUMCHANNELS > 1) 1809 .BYTE (1,0,0,0,0,1,$fe) 1810 .ENDIF 1811 .IF (NUMCHANNELS > 2) 1812 .BYTE (2,0,0,0,0,1,$fe) 1813 .ENDIF 1814 1815 .ENDIF 1816 1817 .IF ((GHOSTREGS != 0) && (ZPGHOSTREGS == 0)) 1818ghostregs: .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) 1819ghostfreqlo = ghostregs+0 1820ghostfreqhi = ghostregs+1 1821ghostpulselo = ghostregs+2 1822ghostpulsehi = ghostregs+3 1823ghostwave = ghostregs+4 1824ghostad = ghostregs+5 1825ghostsr = ghostregs+6 1826ghostfiltcutlow = ghostregs+21 1827ghostfiltcutoff = ghostregs+22 1828ghostfiltctrl = ghostregs+23 1829ghostfilttype = ghostregs+24 1830 .ENDIF 1831 1832 ;Songdata & frequencytable will be inserted by the relocator here 1833 1834