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