From 1b0a5c1734b4c25384cb0c95dc87194ddde5ca88 Mon Sep 17 00:00:00 2001 From: Torchkas Date: Sun, 26 Feb 2023 21:24:03 +0100 Subject: [PATCH 1/4] fixed a minor typo --- asm/Commands.asm | 1379 +++++++++++++++++++++++++--------------------- 1 file changed, 736 insertions(+), 643 deletions(-) diff --git a/asm/Commands.asm b/asm/Commands.asm index 7bbe3f92..22c490eb 100755 --- a/asm/Commands.asm +++ b/asm/Commands.asm @@ -1,39 +1,39 @@ arch spc700-raw -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -if !noSFX = !false -TerminateIfSFXPlaying: - mov a, $48 - and a, $1d - beq + - ;WARNING: Won't work if anything else is in the stack! - pop a ;Jump forward one pointer in the stack in order to - pop a ;terminate the entire preceding routine. -+ - ret -endif - -SetBackupSRCN: - mov a, #$40 ; \ Force !BackupSRCN to contain a non-zero value. -ORBackupSRCN: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +if !noSFX = !false +TerminateIfSFXPlaying: + mov a, $48 + and a, $1d + beq + + ;WARNING: Won't work if anything else is in the stack! + pop a ;Jump forward one pointer in the stack in order to + pop a ;terminate the entire preceding routine. ++ + ret +endif + +SetBackupSRCN: + mov a, #$40 ; \ Force !BackupSRCN to contain a non-zero value. +ORBackupSRCN: or a, !BackupSRCN+x ; | - mov !BackupSRCN+x, a ; / - ret - -SetBackupSRCNAndGetBackupInstrTable: + mov !BackupSRCN+x, a ; / + ret + +SetBackupSRCNAndGetBackupInstrTable: push a call SetBackupSRCN call GetBackupInstrTable - pop a - ret - -SetupPercInstrument: + pop a + ret + +SetupPercInstrument: setc sbc a, #$cf ; Also "correct" A. (Percussion instruments are stored "as-is", otherwise we'd subtract #$d0. mov y, #$07 ; Percussion instruments have 7 bytes of data. mov $10, #PercussionTable - mov $11, #PercussionTable>>8 - ret - + mov $11, #PercussionTable>>8 + ret + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdED: ; ADSR { @@ -43,15 +43,15 @@ cmdED: ; ADSR mov y, #$01 ; | mov ($10)+y, a ; / call GetCommandData ; \ - mov y, #$02 ; | Write ADSR 2 to the table. - pop p ; | - bmi + ; | + mov y, #$02 ; | Write ADSR 2 to the table. + pop p ; | + bmi + ; | inc y ; | Write GAIN to the table. + mov ($10)+y, a ; / bra UpdateInstr -} - +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdF3: ; Sample load command { @@ -61,16 +61,16 @@ MSampleLoad: mov ($10)+y, a ; / call GetCommandData ; \ mov y, #$04 ; | Get the pitch multiplier byte. - mov ($10)+y, a ; | -.clearSubmultiplierPatchGate ; | - bra .clearSubmultiplierSkip ; | - inc y ; | Zero out pitch sub-multiplier. - mov a, #$00 ; | - mov ($10)+y, a ; / + mov ($10)+y, a ; | +.clearSubmultiplierPatchGate ; | + bra .clearSubmultiplierSkip ; | + inc y ; | Zero out pitch sub-multiplier. + mov a, #$00 ; | + mov ($10)+y, a ; / .clearSubmultiplierSkip bra UpdateInstr -} - +} + SubC_table2_GAIN: call SetBackupSRCNAndGetBackupInstrTable mov y, #$03 ; \ GAIN byte = parameter @@ -79,13 +79,13 @@ SubC_table2_GAIN: mov a, ($10)+y ; \ Clear ADSR bit 7. and a, #$7f ; / mov ($10)+y, a ; - bra UpdateInstr - + bra UpdateInstr + RestoreMusicSample: call SetBackupSRCNAndGetBackupInstrTable UpdateInstr: mov a, #$00 - bra ApplyInstrumentY6 ; / Set up the current instrument using the backup table instead of the main table. + bra ApplyInstrumentY6 ; / Set up the current instrument using the backup table instead of the main table. cmdDA: ; Change the instrument (also contains code relevant to $E5 and $F3). { @@ -95,7 +95,7 @@ cmdDA: ; Change the instrument (also contains code relevant to $E5 and $F3). mov a, $48 ; \ No noise is playing on this channel. tclr !MusicNoiseChannels, a ; / (EffectModifier is called later) - mov a, y + mov a, y SetInstrument: ; Call this to start playing the instrument in A. mov $10, #InstrumentTable ; \ $10w = the location of the instrument data. @@ -120,7 +120,7 @@ L_0D4B: ; | ??? movw $10, ya ; | pop a ; | setc ; | - sbc a, #30 ; | + sbc a, #30 ; | ApplyInstrumentY6: mov y, #$06 ; / + @@ -129,29 +129,29 @@ ApplyInstrumentY6: ApplyInstrument: ; Call this to play the instrument in A whose data resides in a table pointed to by $14w with a width of y. mul ya ; \ addw ya, $10 ; | - movw $14, ya ; / - - call GetBackupInstrTable - + movw $14, ya ; / + + call GetBackupInstrTable + mov y, #$00 ; \ - mov a, ($14)+y ; / Get the first instrument byte (the sample) - bpl + -if !noSFX = !false - and a, #$1f - mov $0389, a -endif - or (!MusicNoiseChannels), ($48) - bra ++ -+ + mov a, ($14)+y ; / Get the first instrument byte (the sample) + bpl + +if !noSFX = !false + and a, #$1f + mov $0389, a +endif + or (!MusicNoiseChannels), ($48) + bra ++ ++ mov ($10)+y, a ; (save it in the backup table) -++ - mov y, #$05 -- - mov a, ($14)+y - mov ($10)+y, a +++ + mov y, #$05 +- + mov a, ($14)+y + mov ($10)+y, a dbnz y, - -if !noSFX = !false +if !noSFX = !false call TerminateIfSFXPlaying ; If there's a sound effect playing, then don't change anything. endif @@ -168,42 +168,42 @@ endif mov y, #$00 ; \ mov a, ($14)+y ; / Get the first instrument byte (the sample) bmi .noiseInstrument ; If the byte was positive, then it was a sample. Just write it like normal. - + mov $f2, x - mov $f3, a - bra .DSPWriteDirectionGate1 - -.noiseInstrument + mov $f3, a + bra .DSPWriteDirectionGate1 + +.noiseInstrument if !noSFX = !false - cmp !SFXNoiseChannels, #$00 - bne .DSPWriteDirectionGate1 + cmp !SFXNoiseChannels, #$00 + bne .DSPWriteDirectionGate1 endif push y call ModifyNoise - pop y -.DSPWriteDirectionGate1 + pop y +.DSPWriteDirectionGate1 bra .incXY - mov a, x - or a, #$07 + mov a, x + or a, #$07 mov x, a mov y, #$03 - mov a, ($14)+y ; \ mov $f2, x ; | This loop will write to the correct DSP registers for this instrument. - mov $f3, a ; / -.DSPWriteDirectionGate2 + mov $f3, a ; / +.DSPWriteDirectionGate2 bra .incXY dec x dbnz y, - - - mov y, #$04 - bra + - -.incXY - inc x - inc y - cmp y, #$04 + + mov y, #$04 + bra + + +.incXY + inc x + inc y + cmp y, #$04 bne - + pop x @@ -211,7 +211,7 @@ endif mov $0210+x, a ; inc y ; mov a, ($14)+y ; The final byte is the sub multiplier. - mov $02f0+x, a ; + mov $02f0+x, a ; call EffectModifier inc y ; If this was a percussion instrument, @@ -225,7 +225,7 @@ GetBackupInstrTable: mov y, #(6/2) ; | mov a, x ; | This short routine sets $10 to contain a pointer to the current channel's backup instrument data. mul ya ; | - addw ya, $10 ; | + addw ya, $10 ; | movw $10, ya ; / ret @@ -240,11 +240,11 @@ cmdDB: ; Change the pan and a, #$c0 mov !SurroundSound+x, a ; negate voice vol bits mov a, #$00 - mov $0280+x, a + mov $0280+x, a SetVolChangeFlag: or ($5c), ($48) ; set vol chg flag ret -} +} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdE7: ; Change the volume { @@ -252,11 +252,11 @@ cmdE7: ; Change the volume mov a, #$00 mov $0240+x, a bra SetVolChangeFlag ; mark volume changed -} -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SubC_table2_superVolume: mov !VolumeMult+x, a - bra SetVolChangeFlag ; Mark volume changed. + bra SetVolChangeFlag ; Mark volume changed. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;cmdDC: ; Fade the pan @@ -305,12 +305,12 @@ cmdE1: ; Fade the master volume movw $5a, ya ret } -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SubC_7: - mov a, #$00 ; \ + mov a, #$00 ; \ SubC_7_storeTo387: mov $0387, a ; | Set the tempo to normal. - mov a, $51 ; / + mov a, $51 ; / cmdE2: ; Change the tempo { @@ -354,39 +354,39 @@ cmdFD: ; Tremolo off ;0DCA TSampleLoad: - ;and a, #$7F - ;jmp MSampleLoad - + ;and a, #$7F + ;jmp MSampleLoad + } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdE6: ; Second loop { - bne label2 + bne label2 dec a ; \ ? mov $01f0+x,a ; / mov a,$30+x ; \ mov $01e0+x,a ; | Save the current song position into $01e0 mov a,$31+x ; | mov $01e1+x,a ; / - ret ; - -label2: - mov a, $01f0+x - dec a - beq label4 - cmp a, #$fe - bne label3 - mov a, y -label3: - setp - mov.b $01f0&$ff+x,a - mov.b a,$01e0&$ff+x - mov.b y,$01e1&$ff+x + ret ; + +label2: + mov a, $01f0+x + dec a + beq label4 + cmp a, #$fe + bne label3 + mov a, y +label3: + setp + mov.b $01f0&$ff+x,a + mov.b a,$01e0&$ff+x + mov.b y,$01e1&$ff+x clrp mov $30+x,a - mov $31+x,y -label4: + mov $31+x,y +label4: ret } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -402,6 +402,9 @@ cmdE9: ; Loop push a call GetCommandDataFast mov $c0+x, a ; repeat counter = op3 + setc + sbc a, #$96 + bcs ConditionalLoops mov a, $30+x mov $03e0+x, a mov a, $31+x @@ -413,6 +416,94 @@ cmdE9: ; Loop mov $30+x, a mov $03f0+x, a ; set vptr/3F0/1+X to op1/2 ret +ConditionTable: + dw Condition0 + dw Condition1 + dw Condition2 + dw Condition3 + dw Condition4 + dw Condition5 + dw Condition6 + dw Condition7 +ConditionalLoops: ;conditional loops are actually infinite loops that break their loop when a flag is set. + asl a + push x + mov x, a + jmp (Conditiontable+x) + +Condition0: + mov a, !Flag + and a, #$01 + beq looping + pop a + pop a + ret +Condition1: + mov a, !Flag + and a, #$02 + beq looping + pop a + pop a + ret +Condition2: + mov a, !Flag + and a, #$04 + beq looping + pop a + pop a + ret +Condition3: + mov a, !Flag + and a, #$08 + bne looping + pop a + pop a + ret +Condition4: + mov a, !Flag + and a, #$10 + beq looping + pop a + pop a + ret +Condition5: + mov a, !Flag + and a, #$20 + beq looping + pop a + pop a + ret +Condition6: + mov a, !Flag + and a, #$40 + beq looping + pop a + pop a + ret +Condition7: + mov a, !Flag + and a, #$80 + beq looping + pop a + pop a + ret +looping: + mov a, $30+x + mov $03e0+x, a + bcc + + mov a, $31+x + mov $03e1+x, a ; save current vptr in 3E0/1+X +- pop a + mov $31+x, a + mov $03f1+x, a + pop a + mov $30+x, a + mov $03f0+x, a ; set vptr/3F0/1+X to op1/2 + ret ++ mov a, $31+x + dec a + mov $03e1+x, a + bra - } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdEA: ; Fade the vibrato @@ -431,12 +522,12 @@ cmdEA: ; Fade the vibrato ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdEB: ; Pitch envelope (release) { - mov a, #$01 + mov a, #$01 bra L_0E55 } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdEC: ; Pitch envelope (attack) -{ +{ mov a, #$00 L_0E55: mov $0320+x, a @@ -447,12 +538,12 @@ L_0E55: call GetCommandDataFast mov $0321+x, a ret -} -cmdFE: ; Pitch envelope off -{ - mov $0300+x, a - ret -} +} +cmdFE: ; Pitch envelope off +{ + mov $0300+x, a + ret +} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdEE: ; Set the tuning @@ -473,17 +564,17 @@ cmdEF: ; Echo command 1 (channels, volume) movw $63, ya ; set 63/4 from op3 * $100 (evol R) ; set echo vols from shadows -L_0EEB: +L_0EEB: mov $f2, #$2c ; set echo vol L DSP from $62 - mov $f3, $62 + mov $f3, $62 set1 $f2.4 ; set echo vol R DSP from $64 - mov $f3, $64 + mov $f3, $64 ret -} +} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;cmdF0: ; Echo off -{ - ; Handled elsewhere. +;cmdF0: ; Echo off +{ + ; Handled elsewhere. } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdF1: ; Echo command 2 (delay, feedback, FIR) @@ -509,22 +600,22 @@ cmdF1: ; Echo command 2 (delay, feedback, FIR) call GetCommandDataFast ; mov y, #$08 ; mul ya ; - mov x, a ; - mov $f2, #$0f ; -- ; - mov a, EchoFilter0+x ; filter table - mov $f3, a ; - inc x ; - clrc ; - adc $f2,#$10 ; + mov x, a ; + mov $f2, #$0f ; +- ; + mov a, EchoFilter0+x ; filter table + mov $f3, a ; + inc x ; + clrc ; + adc $f2,#$10 ; bpl - ; set echo filter from table idx op3 - bra L_0EEB ; Set the echo volume. - -SetEDLVarDSP: - mov !EchoDelay, a ; \ + bra L_0EEB ; Set the echo volume. + +SetEDLVarDSP: + mov !EchoDelay, a ; \ SetEDLDSP: mov $f2, #$7d ; | Write the new delay. - mov $f3, a ; / + mov $f3, a ; / ret } @@ -568,22 +659,22 @@ SubC_table: dw SubC_9 SubC_0: - not1 $6e.5 ; + not1 $6e.5 ; SubC_00: call HandleYoshiDrums ; Handle the Yoshi drums. - mov a,#$01 - cmp $6e, #$00 - beq SubC_02 - -SubC_01: - tset $0160, a - ret - -SubC_02: - tclr $0160, a + mov a,#$01 + cmp $6e, #$00 + beq SubC_02 + +SubC_01: + tset $0160, a ret -SubC_1: +SubC_02: + tclr $0160, a + ret + +SubC_1: mov a,$48 tclr $0162, a eor a, $0161 @@ -606,26 +697,26 @@ SubC_6: bra SubC_00 SubC_8: - mov !SecondVTable, #$01 ; Toggle which velocity table we're using. + mov !SecondVTable, #$01 ; Toggle which velocity table we're using. cmdF5Ret: ret } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdF5: ; FIR Filter command. { - mov a, #$0f - movw $f2, ya -- clrc - adc $f2,#$10 - bmi cmdF5Ret - call GetCommandData - mov $f3, a + mov a, #$0f + movw $f2, ya +- clrc + adc $f2,#$10 + bmi cmdF5Ret + call GetCommandData + mov $f3, a bra - } -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;cmdF6: ; DSP Write command. -{ - ; Handled elsewhere. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;cmdF6: ; DSP Write command. +{ + ; Handled elsewhere. } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdF7: ; Originally the "write to ARAM command". Disabled by default. @@ -639,12 +730,12 @@ cmdF7: ; Originally the "write to ARAM command". Disabled by default. ; mov y, #$00 ; mov ($14)+y, a ; ret -} +} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;cmdF8: ; Noise command. -{ - ; Handled elsewhere. -} +;cmdF8: ; Noise command. +{ + ; Handled elsewhere. +} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdF9: ; Send data to 5A22 command. { @@ -656,409 +747,411 @@ cmdF9: ; Send data to 5A22 command. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdFA: ; Misc. comamnd that takes a parameter. ;HTuneValues -{ - cmp a, #$7F - beq HotPatchPresetVCMD - cmp a, #$FE - beq HotPatchVCMDByBit +{ + cmp a, #$7F + beq HotPatchPresetVCMD + cmp a, #$FE + beq HotPatchVCMDByBit - mov $14, #SubC_table2+1&$FF + mov $14, #SubC_table2+1&$FF mov $15, #SubC_table2+1>>8&$FF - asl a - mov y, a - adc $15, #$00 - mov a, ($14)+y - push a - decw $14 - mov a, ($14)+y - push a - push y - call GetCommandData - pop y - ;Y will contain the command ID shifted left by one, A will contain - ;the incoming data and X will contain the channel ID. - ret - -HotPatchPresetVCMD: - call GetCommandData - ;bmi HotPatchPresetVCMDUserPatch - mov y, $30+x - push y - mov y, $31+x - push y - asl a - clrc - adc a, #HotPatchPresetTable&$FF - mov $30+x, a - mov a, #HotPatchPresetTable>>8&$FF - adc a, #$00 - mov $31+x, a - call GetCommandDataFast - call HotPatchVCMDByBitByte0 - jmp RestoreTrackPtrFromStack - -HotPatchPresetVCMDUserPatch: - ;Make sure you uncommented bmi HotPatchPresetVCMDUserPatch before - ;using (and the ret opcode)! - - ;Hello there! You've found the user hot patch section! This is - ;reserved for any code modifications you want to make on the fly - ;without accidentally breaking something later on due to a preset ID - ;being overwritten. - - ;ret - -HotPatchVCMDByBit: - call GetCommandData -HotPatchVCMDByBitByte0: - mov $10, a - push p - mov A, #HotPatchVCMDByte0StorageSet&$FF - mov Y, #(HotPatchVCMDByte0StorageSet>>8)&$FF - call HotPatchVCMDByBitProcessByte - pop p -HotPatchVCMDByBitByte1: - call HotPatchVCMDFetchNextByteIfMinus - push p - mov A, #HotPatchVCMDByte1StorageSet&$FF - mov Y, #(HotPatchVCMDByte1StorageSet>>8)&$FF - call HotPatchVCMDByBitProcessByte - pop p - - ;NOTE: For those of you that want to use extra bits, a template is - ;provided below, commented out. You will find the corresponding - ;collection nearby, also commented out. - ;- $10 will contain all of the bits to process in the current byte. - ;- $11 is reserved to execute an indexed X fetch via a subroutine - ; call. The RET opcode is temporarily stored in $16 to do this, - ; then overwritten for byte storage reasons. - ;- $12-$13 store the pointer to an array containing a pointer to the - ; storage set, followed by the number of bytes to write for each of - ; the seven bits to apply the hot patch (the highest bit means - ; fetch another byte: if this is not set, all subsequent bits will - ; be zero). - ;- $14-$15 store the pointer to the storage set. Each byte - ; modified takes up a four-byte storage entry: two for the pointer, - ; one to use when the bit is cleared, and one to use when the bit - ; is set. A template will be found nearby that matches the label - ; name shown. - ;- $16-$17 store the pointer that we will be writing a byte to. - -HotPatchVCMDByBitByte2: - ;call HotPatchVCMDFetchNextByteIfMinus - ;push p - ;mov A, #HotPatchVCMDByte2StorageSet&$FF - ;mov Y, #(HotPatchVCMDByte2StorageSet>>8)&$FF - ;call HotPatchVCMDByBitProcessByte - ;pop p - -HotPatchVCMDByBitByteFetchLoop: - ;There are still bytes to read, but the remaining bits do not yet have a function. - call HotPatchVCMDFetchNextByteIfMinus - bmi HotPatchVCMDByBitByteFetchLoop -HotPatchVCMDByBitByteFetchLoopSkip: - ret - -HotPatchVCMDByBitProcessByte: - mov $11, #$F5 ;MOV A, !A+X opcode - movw $12, ya -HotPatchVCMDByBitProcessByte_count: - mov y, #$07 - mov $14, #$6F ;RET opcode - mov x, #$00 - call $0011 - mov HotPatchVCMDByBitProcessByte_storagePtrLo+1, a - inc x - call $0011 - mov $15, a -- - mov $14, #$6F ;RET opcode - lsr $10 - inc x - call $0011 - push y - mov y, a - beq + -HotPatchVCMDByBitProcessByte_storagePtrLo: - mov $14, #$00 - call HotPatchVCMDByBitProcessStorages -+ - pop y - dbnz y, - - ret - -HotPatchVCMDByBitProcessStorages: -- - push p - push y - mov y, #$00 - mov a, ($14)+y - mov $16, a - inc y - mov a, ($14)+y - mov $17, a - inc y - bcc + - inc y -+ - mov a, ($14)+y - mov y, #$00 - mov ($16)+y, a - mov a, #$04 - addw ya, $14 - movw $14, ya - mov HotPatchVCMDByBitProcessByte_storagePtrLo+1, a - pop y - pop p - dbnz y, - - ret - -HotPatchVCMDByte0StorageSet: - dw HotPatchVCMDByte0Bit0Storages - db (HotPatchVCMDByte0Bit0StoragesEOF-HotPatchVCMDByte0Bit0Storages)/4 - db (HotPatchVCMDByte0Bit1StoragesEOF-HotPatchVCMDByte0Bit1Storages)/4 - db (HotPatchVCMDByte0Bit2StoragesEOF-HotPatchVCMDByte0Bit2Storages)/4 - db (HotPatchVCMDByte0Bit3StoragesEOF-HotPatchVCMDByte0Bit3Storages)/4 - db (HotPatchVCMDByte0Bit4StoragesEOF-HotPatchVCMDByte0Bit4Storages)/4 - db (HotPatchVCMDByte0Bit5StoragesEOF-HotPatchVCMDByte0Bit5Storages)/4 - db (HotPatchVCMDByte0Bit6StoragesEOF-HotPatchVCMDByte0Bit6Storages)/4 - - ;Storage set format: - ;xx xx yy zz - ;xx xx - Storage pointer - ;yy - Byte to store when bit is clear - ;zz - Byte to store when bit is set - - ;Byte 0 Bit 0 Clear - Arpeggio plays during rests - ;Byte 0 Bit 0 Set - Arpeggio doesn't play during rests -HotPatchVCMDByte0Bit0Storages: - dw HandleArpeggioInterrupt_restOpcodeGate - db $B0 ;BCS opcode - db $F0 ;BEQ opcode - - dw HandleArpeggio_restBranchGate+1 - db $00 - db HandleArpeggio_return2-HandleArpeggio_restBranchGate-2 -HotPatchVCMDByte0Bit0StoragesEOF: - - ;Byte 0 Bit 1 Clear - Write ADSR to DSP registers first during instrument setup - ;Byte 0 Bit 1 Clear - Write GAIN to DSP registers first during instrument setup -HotPatchVCMDByte0Bit1Storages: - dw ApplyInstrument_DSPWriteDirectionGate1+1 - db ApplyInstrument_incXY-ApplyInstrument_DSPWriteDirectionGate1-2 - db $00 - - dw ApplyInstrument_DSPWriteDirectionGate2+1 - db ApplyInstrument_incXY-ApplyInstrument_DSPWriteDirectionGate2-2 - db $00 -HotPatchVCMDByte0Bit1StoragesEOF: - - ;Byte 0 Bit 2 Clear - Readahead does not look inside subroutines and loop sections - ;Byte 0 Bit 2 Set - Readahead looks inside subroutines and loop sections -HotPatchVCMDByte0Bit2Storages: - dw L_10B2_loopSectionBranchGate+1 - db $00 - db L_10B2_loopSection-L_10B2_loopSectionBranchGate-2 - - dw L_10B2_subroutineBranchGate+1 - db $00 - db L_10B2_subroutine-L_10B2_subroutineBranchGate-2 - - dw L_10B2_zeroVCMDCheckGate+1 - db L_10B2_jmpToL_10D1-L_10B2_zeroVCMDCheckGate-2 - db L_10B2_subroutineCheck-L_10B2_zeroVCMDCheckGate-2 -HotPatchVCMDByte0Bit2StoragesEOF: - - ;Byte 0 Bit 3 Clear - $DD VCMD does not account for per-channel transposition - ;Byte 0 Bit 3 Set - $DD VCMD accounts for per-channel transposition -HotPatchVCMDByte0Bit3Storages: - dw cmdDDAddHTuneValuesGate+1 - db cmdDDAddHTuneValuesSkip-cmdDDAddHTuneValuesGate-2 - db $00 -HotPatchVCMDByte0Bit3StoragesEOF: - - ;Byte 0 Bit 4 Clear - $F3 VCMD does not zero out pitch base fractional multiplier - ;Byte 0 Bit 4 Set - $F3 VCMD zeroes out pitch base fractional multiplier -HotPatchVCMDByte0Bit4Storages: - dw MSampleLoad_clearSubmultiplierPatchGate+1 - db MSampleLoad_clearSubmultiplierSkip-MSampleLoad_clearSubmultiplierPatchGate-2 - db $00 -HotPatchVCMDByte0Bit4StoragesEOF: - - ;Byte 0 Bit 5 Clear - Echo writes are not disabled when EDL is zero on initial playback of local song - ;Byte 0 Bit 5 Set - Echo writes are disabled when EDL is zero on initial playback of local song - ;NOTE: This bit is sensitive to order of execution! The $FA $04 VCMD - ;must be executed after the patch is set, not before! -HotPatchVCMDByte0Bit5Storages: - dw SubC_table2_reserveBuffer_echoWriteBitClearLoc+1 - db !NCKValue - db $10 -HotPatchVCMDByte0Bit5StoragesEOF: - - ;Byte 0 Bit 6 Clear - When using arpeggio, glissando disables itself after two base notes - ;Byte 0 Bit 6 Set - When using arpeggio, glissando disables itself after one base note -HotPatchVCMDByte0Bit6Storages: - dw cmdFB_glissNoteCounter+1 - db $02 - db $01 -HotPatchVCMDByte0Bit6StoragesEOF: - -HotPatchVCMDByte1StorageSet: - dw HotPatchVCMDByte1Bit0Storages - db (HotPatchVCMDByte1Bit0StoragesEOF-HotPatchVCMDByte1Bit0Storages)/4 - db (HotPatchVCMDByte1Bit1StoragesEOF-HotPatchVCMDByte1Bit1Storages)/4 - db (HotPatchVCMDByte1Bit2StoragesEOF-HotPatchVCMDByte1Bit2Storages)/4 - db (HotPatchVCMDByte1Bit3StoragesEOF-HotPatchVCMDByte1Bit3Storages)/4 - db (HotPatchVCMDByte1Bit4StoragesEOF-HotPatchVCMDByte1Bit4Storages)/4 - db (HotPatchVCMDByte1Bit5StoragesEOF-HotPatchVCMDByte1Bit5Storages)/4 - db (HotPatchVCMDByte1Bit6StoragesEOF-HotPatchVCMDByte1Bit6Storages)/4 - -HotPatchVCMDByte1Bit0Storages: - ;Byte 1 Bit 0 Clear - Rests are forcibly keyed off when read - ;Byte 1 Bit 0 Set - Rests are only keyed off if encountered in readahead - dw if_rest_koffCheckGate - db $F0 ;BEQ opcode - db $2F ;BRA opcode -HotPatchVCMDByte1Bit0StoragesEOF: - -HotPatchVCMDByte1Bit1Storages: - ;This bit is not yet defined. -HotPatchVCMDByte1Bit1StoragesEOF: - -HotPatchVCMDByte1Bit2Storages: - ;This bit is not yet defined. -HotPatchVCMDByte1Bit2StoragesEOF: - -HotPatchVCMDByte1Bit3Storages: - ;This bit is not yet defined. -HotPatchVCMDByte1Bit3StoragesEOF: - -HotPatchVCMDByte1Bit4Storages: - ;This bit is not yet defined. -HotPatchVCMDByte1Bit4StoragesEOF: - -HotPatchVCMDByte1Bit5Storages: - ;This bit is not yet defined. -HotPatchVCMDByte1Bit5StoragesEOF: - -HotPatchVCMDByte1Bit6Storages: - ;This bit is not yet defined. -HotPatchVCMDByte1Bit6StoragesEOF: - -HotPatchVCMDByte2StorageSet: - ;dw HotPatchVCMDByte2Bit0Storages - ;db (HotPatchVCMDByte2Bit0StoragesEOF-HotPatchVCMDByte2Bit0Storages)/4 - ;db (HotPatchVCMDByte2Bit1StoragesEOF-HotPatchVCMDByte2Bit1Storages)/4 - ;db (HotPatchVCMDByte2Bit2StoragesEOF-HotPatchVCMDByte2Bit2Storages)/4 - ;db (HotPatchVCMDByte2Bit3StoragesEOF-HotPatchVCMDByte2Bit3Storages)/4 - ;db (HotPatchVCMDByte2Bit4StoragesEOF-HotPatchVCMDByte2Bit4Storages)/4 - ;db (HotPatchVCMDByte2Bit5StoragesEOF-HotPatchVCMDByte2Bit5Storages)/4 - ;db (HotPatchVCMDByte2Bit6StoragesEOF-HotPatchVCMDByte2Bit6Storages)/4 - -HotPatchVCMDByte2Bit0Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit0StoragesEOF: - -HotPatchVCMDByte2Bit1Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit1StoragesEOF: - -HotPatchVCMDByte2Bit2Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit2StoragesEOF: - -HotPatchVCMDByte2Bit3Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit3StoragesEOF: - -HotPatchVCMDByte2Bit4Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit4StoragesEOF: - -HotPatchVCMDByte2Bit5Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit5StoragesEOF: - -HotPatchVCMDByte2Bit6Storages: - ;dw memory location here - ;db byte to write when bit is cleared here - ;db byte to write when bit is set here - ;repeat as many times as you want prior to the EOF label - ;then proceed to the next bit -HotPatchVCMDByte2Bit6StoragesEOF: - -HotPatchPresetTable: - ;All presets are specified as two bytes for indexing and - ;divisibility reasons. This means the highest byte is set on the - ;first byte. - ;First byte is specified as... - ;%!xyzabcd - ;%! - New byte specified - ;%x - When using arpeggio, glissando disables itself after one base note - ;%y - Echo writes are disabled when EDL is zero on initial playback of local song - ;%z - $F3 VCMD zeroes out pitch base fractional multiplier - ;%a - $DD VCMD accounts for per-channel transposition - ;%b - Readahead looks inside subroutines and loop sections - ;%c - ADSR/GAIN write orders are flipped during instrument setup - ;%d - Arpeggio doesn't play during rests - - ;Second byte is specified as... - ;%!xyzabcd - ;%! - New byte specified - ;%x - Reserved for playback adjustment for other Addmusics - ;%y - Reserved for playback adjustment for other Addmusics - ;%z - Reserved for playback adjustment for other Addmusics - ;%a - Reserved for playback adjustment for other Addmusics - ;%b - Reserved for playback adjustment for other Addmusics - ;%c - Reserved for playback adjustment for other Addmusics - ;%d - Rests are only keyed off if encountered in readahead - - db %10000000 ; 00 - AddmusicK1.0.8 and earlier (not counting Beta) - ; %??0?000? also replicates Vanilla SMW's behavior - db %00000000 ; %???????1 also replicates Vanilla SMW's behavior - db %11111111 ; 01 - AddmusicK1.0.9 - db %00000000 ; - db %10000000 ; 02 - AddmusicK Beta - db %00000000 ; - db %10000000 ; 03 - Romi's Addmusic404 - db %00000001 ; - db %10000000 ; 04 - Addmusic405 - db %00000001 ; - ; NOTE: Although it's not implemented yet, there are - ; readahead-related differences due to the $ED VCMD - ; having inconsistent parameter sizes for $80 and up - ; and Addmusic405 failing to account for these. - db %10001000 ; 05 - AddmusicM - db %00000000 ; - db %10000000 ; 06 - carol's MORE.bin - db %00000001 ; - db %10000000 ; 07 - Vanilla SMW - db %00000001 ; - ; 08-7F - Reserved for future Addmusics (or any extra past ones) + asl a + mov y, a + adc $15, #$00 + mov a, ($14)+y + push a + decw $14 + mov a, ($14)+y + push a + push y + call GetCommandData + pop y + ;Y will contain the command ID shifted left by one, A will contain + ;the incoming data and X will contain the channel ID. + ret + +HotPatchPresetVCMD: + call GetCommandData + ;bmi HotPatchPresetVCMDUserPatch + mov y, $30+x + push y + mov y, $31+x + push y + asl a + clrc + adc a, #HotPatchPresetTable&$FF + mov $30+x, a + mov a, #HotPatchPresetTable>>8&$FF + adc a, #$00 + mov $31+x, a + call GetCommandDataFast + call HotPatchVCMDByBitByte0 + jmp RestoreTrackPtrFromStack + +HotPatchPresetVCMDUserPatch: + ;Make sure you uncommented bmi HotPatchPresetVCMDUserPatch before + ;using (and the ret opcode)! + + ;Hello there! You've found the user hot patch section! This is + ;reserved for any code modifications you want to make on the fly + ;without accidentally breaking something later on due to a preset ID + ;being overwritten. + + ;ret + +HotPatchVCMDByBit: + call GetCommandData +HotPatchVCMDByBitByte0: + mov $10, a + push p + mov A, #HotPatchVCMDByte0StorageSet&$FF + mov Y, #(HotPatchVCMDByte0StorageSet>>8)&$FF + call HotPatchVCMDByBitProcessByte + pop p +HotPatchVCMDByBitByte1: + call HotPatchVCMDFetchNextByteIfMinus + mov $10, a + push p + mov A, #HotPatchVCMDByte1StorageSet&$FF + mov Y, #(HotPatchVCMDByte1StorageSet>>8)&$FF + call HotPatchVCMDByBitProcessByte + pop p + + ;NOTE: For those of you that want to use extra bits, a template is + ;provided below, commented out. You will find the corresponding + ;collection nearby, also commented out. + ;- $10 will contain all of the bits to process in the current byte. + ;- $11 is reserved to execute an indexed X fetch via a subroutine + ; call. The RET opcode is temporarily stored in $16 to do this, + ; then overwritten for byte storage reasons. + ;- $12-$13 store the pointer to an array containing a pointer to the + ; storage set, followed by the number of bytes to write for each of + ; the seven bits to apply the hot patch (the highest bit means + ; fetch another byte: if this is not set, all subsequent bits will + ; be zero). + ;- $14-$15 store the pointer to the storage set. Each byte + ; modified takes up a four-byte storage entry: two for the pointer, + ; one to use when the bit is cleared, and one to use when the bit + ; is set. A template will be found nearby that matches the label + ; name shown. + ;- $16-$17 store the pointer that we will be writing a byte to. + +HotPatchVCMDByBitByte2: + ;call HotPatchVCMDFetchNextByteIfMinus + ;mov $10, a + ;push p + ;mov A, #HotPatchVCMDByte2StorageSet&$FF + ;mov Y, #(HotPatchVCMDByte2StorageSet>>8)&$FF + ;call HotPatchVCMDByBitProcessByte + ;pop p + +HotPatchVCMDByBitByteFetchLoop: + ;There are still bytes to read, but the remaining bits do not yet have a function. + call HotPatchVCMDFetchNextByteIfMinus + bmi HotPatchVCMDByBitByteFetchLoop +HotPatchVCMDByBitByteFetchLoopSkip: + ret + +HotPatchVCMDByBitProcessByte: + mov $11, #$F5 ;MOV A, !A+X opcode + movw $12, ya +HotPatchVCMDByBitProcessByte_count: + mov y, #$07 + mov $14, #$6F ;RET opcode + mov x, #$00 + call $0011 + mov HotPatchVCMDByBitProcessByte_storagePtrLo+1, a + inc x + call $0011 + mov $15, a +- + mov $14, #$6F ;RET opcode + lsr $10 + inc x + call $0011 + push y + mov y, a + beq + +HotPatchVCMDByBitProcessByte_storagePtrLo: + mov $14, #$00 + call HotPatchVCMDByBitProcessStorages ++ + pop y + dbnz y, - + ret + +HotPatchVCMDByBitProcessStorages: +- + push p + push y + mov y, #$00 + mov a, ($14)+y + mov $16, a + inc y + mov a, ($14)+y + mov $17, a + inc y + bcc + + inc y ++ + mov a, ($14)+y + mov y, #$00 + mov ($16)+y, a + mov a, #$04 + addw ya, $14 + movw $14, ya + mov HotPatchVCMDByBitProcessByte_storagePtrLo+1, a + pop y + pop p + dbnz y, - + ret + +HotPatchVCMDByte0StorageSet: + dw HotPatchVCMDByte0Bit0Storages + db (HotPatchVCMDByte0Bit0StoragesEOF-HotPatchVCMDByte0Bit0Storages)/4 + db (HotPatchVCMDByte0Bit1StoragesEOF-HotPatchVCMDByte0Bit1Storages)/4 + db (HotPatchVCMDByte0Bit2StoragesEOF-HotPatchVCMDByte0Bit2Storages)/4 + db (HotPatchVCMDByte0Bit3StoragesEOF-HotPatchVCMDByte0Bit3Storages)/4 + db (HotPatchVCMDByte0Bit4StoragesEOF-HotPatchVCMDByte0Bit4Storages)/4 + db (HotPatchVCMDByte0Bit5StoragesEOF-HotPatchVCMDByte0Bit5Storages)/4 + db (HotPatchVCMDByte0Bit6StoragesEOF-HotPatchVCMDByte0Bit6Storages)/4 + + ;Storage set format: + ;xx xx yy zz + ;xx xx - Storage pointer + ;yy - Byte to store when bit is clear + ;zz - Byte to store when bit is set + + ;Byte 0 Bit 0 Clear - Arpeggio plays during rests + ;Byte 0 Bit 0 Set - Arpeggio doesn't play during rests +HotPatchVCMDByte0Bit0Storages: + dw HandleArpeggioInterrupt_restOpcodeGate + db $B0 ;BCS opcode + db $F0 ;BEQ opcode + + dw HandleArpeggio_restBranchGate+1 + db $00 + db HandleArpeggio_return2-HandleArpeggio_restBranchGate-2 +HotPatchVCMDByte0Bit0StoragesEOF: + + ;Byte 0 Bit 1 Clear - Write ADSR to DSP registers first during instrument setup + ;Byte 0 Bit 1 Clear - Write GAIN to DSP registers first during instrument setup +HotPatchVCMDByte0Bit1Storages: + dw ApplyInstrument_DSPWriteDirectionGate1+1 + db ApplyInstrument_incXY-ApplyInstrument_DSPWriteDirectionGate1-2 + db $00 + + dw ApplyInstrument_DSPWriteDirectionGate2+1 + db ApplyInstrument_incXY-ApplyInstrument_DSPWriteDirectionGate2-2 + db $00 +HotPatchVCMDByte0Bit1StoragesEOF: + + ;Byte 0 Bit 2 Clear - Readahead does not look inside subroutines and loop sections + ;Byte 0 Bit 2 Set - Readahead looks inside subroutines and loop sections +HotPatchVCMDByte0Bit2Storages: + dw L_10B2_loopSectionBranchGate+1 + db $00 + db L_10B2_loopSection-L_10B2_loopSectionBranchGate-2 + + dw L_10B2_subroutineBranchGate+1 + db $00 + db L_10B2_subroutine-L_10B2_subroutineBranchGate-2 + + dw L_10B2_zeroVCMDCheckGate+1 + db L_10B2_jmpToL_10D1-L_10B2_zeroVCMDCheckGate-2 + db L_10B2_subroutineCheck-L_10B2_zeroVCMDCheckGate-2 +HotPatchVCMDByte0Bit2StoragesEOF: + + ;Byte 0 Bit 3 Clear - $DD VCMD does not account for per-channel transposition + ;Byte 0 Bit 3 Set - $DD VCMD accounts for per-channel transposition +HotPatchVCMDByte0Bit3Storages: + dw cmdDDAddHTuneValuesGate+1 + db cmdDDAddHTuneValuesSkip-cmdDDAddHTuneValuesGate-2 + db $00 +HotPatchVCMDByte0Bit3StoragesEOF: + + ;Byte 0 Bit 4 Clear - $F3 VCMD does not zero out pitch base fractional multiplier + ;Byte 0 Bit 4 Set - $F3 VCMD zeroes out pitch base fractional multiplier +HotPatchVCMDByte0Bit4Storages: + dw MSampleLoad_clearSubmultiplierPatchGate+1 + db MSampleLoad_clearSubmultiplierSkip-MSampleLoad_clearSubmultiplierPatchGate-2 + db $00 +HotPatchVCMDByte0Bit4StoragesEOF: + + ;Byte 0 Bit 5 Clear - Echo writes are not disabled when EDL is zero on initial playback of local song + ;Byte 0 Bit 5 Set - Echo writes are disabled when EDL is zero on initial playback of local song + ;NOTE: This bit is sensitive to order of execution! The $FA $04 VCMD + ;must be executed after the patch is set, not before! +HotPatchVCMDByte0Bit5Storages: + dw SubC_table2_reserveBuffer_echoWriteBitClearLoc+1 + db !NCKValue + db $10 +HotPatchVCMDByte0Bit5StoragesEOF: + + ;Byte 0 Bit 6 Clear - When using arpeggio, glissando disables itself after two base notes + ;Byte 0 Bit 6 Set - When using arpeggio, glissando disables itself after one base note +HotPatchVCMDByte0Bit6Storages: + dw cmdFB_glissNoteCounter+1 + db $02 + db $01 +HotPatchVCMDByte0Bit6StoragesEOF: + +HotPatchVCMDByte1StorageSet: + dw HotPatchVCMDByte1Bit0Storages + db (HotPatchVCMDByte1Bit0StoragesEOF-HotPatchVCMDByte1Bit0Storages)/4 + db (HotPatchVCMDByte1Bit1StoragesEOF-HotPatchVCMDByte1Bit1Storages)/4 + db (HotPatchVCMDByte1Bit2StoragesEOF-HotPatchVCMDByte1Bit2Storages)/4 + db (HotPatchVCMDByte1Bit3StoragesEOF-HotPatchVCMDByte1Bit3Storages)/4 + db (HotPatchVCMDByte1Bit4StoragesEOF-HotPatchVCMDByte1Bit4Storages)/4 + db (HotPatchVCMDByte1Bit5StoragesEOF-HotPatchVCMDByte1Bit5Storages)/4 + db (HotPatchVCMDByte1Bit6StoragesEOF-HotPatchVCMDByte1Bit6Storages)/4 + +HotPatchVCMDByte1Bit0Storages: + ;Byte 1 Bit 0 Clear - Rests are forcibly keyed off when read + ;Byte 1 Bit 0 Set - Rests are only keyed off if encountered in readahead + dw if_rest_koffCheckGate + db $F0 ;BEQ opcode + db $2F ;BRA opcode +HotPatchVCMDByte1Bit0StoragesEOF: + +HotPatchVCMDByte1Bit1Storages: + ;This bit is not yet defined. +HotPatchVCMDByte1Bit1StoragesEOF: + +HotPatchVCMDByte1Bit2Storages: + ;This bit is not yet defined. +HotPatchVCMDByte1Bit2StoragesEOF: + +HotPatchVCMDByte1Bit3Storages: + ;This bit is not yet defined. +HotPatchVCMDByte1Bit3StoragesEOF: + +HotPatchVCMDByte1Bit4Storages: + ;This bit is not yet defined. +HotPatchVCMDByte1Bit4StoragesEOF: + +HotPatchVCMDByte1Bit5Storages: + ;This bit is not yet defined. +HotPatchVCMDByte1Bit5StoragesEOF: + +HotPatchVCMDByte1Bit6Storages: + ;This bit is not yet defined. +HotPatchVCMDByte1Bit6StoragesEOF: + +HotPatchVCMDByte2StorageSet: + ;dw HotPatchVCMDByte2Bit0Storages + ;db (HotPatchVCMDByte2Bit0StoragesEOF-HotPatchVCMDByte2Bit0Storages)/4 + ;db (HotPatchVCMDByte2Bit1StoragesEOF-HotPatchVCMDByte2Bit1Storages)/4 + ;db (HotPatchVCMDByte2Bit2StoragesEOF-HotPatchVCMDByte2Bit2Storages)/4 + ;db (HotPatchVCMDByte2Bit3StoragesEOF-HotPatchVCMDByte2Bit3Storages)/4 + ;db (HotPatchVCMDByte2Bit4StoragesEOF-HotPatchVCMDByte2Bit4Storages)/4 + ;db (HotPatchVCMDByte2Bit5StoragesEOF-HotPatchVCMDByte2Bit5Storages)/4 + ;db (HotPatchVCMDByte2Bit6StoragesEOF-HotPatchVCMDByte2Bit6Storages)/4 + +HotPatchVCMDByte2Bit0Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit0StoragesEOF: + +HotPatchVCMDByte2Bit1Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit1StoragesEOF: + +HotPatchVCMDByte2Bit2Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit2StoragesEOF: + +HotPatchVCMDByte2Bit3Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit3StoragesEOF: + +HotPatchVCMDByte2Bit4Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit4StoragesEOF: + +HotPatchVCMDByte2Bit5Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit5StoragesEOF: + +HotPatchVCMDByte2Bit6Storages: + ;dw memory location here + ;db byte to write when bit is cleared here + ;db byte to write when bit is set here + ;repeat as many times as you want prior to the EOF label + ;then proceed to the next bit +HotPatchVCMDByte2Bit6StoragesEOF: + +HotPatchPresetTable: + ;All presets are specified as two bytes for indexing and + ;divisibility reasons. This means the highest byte is set on the + ;first byte. + ;First byte is specified as... + ;%!xyzabcd + ;%! - New byte specified + ;%x - When using arpeggio, glissando disables itself after one base note + ;%y - Echo writes are disabled when EDL is zero on initial playback of local song + ;%z - $F3 VCMD zeroes out pitch base fractional multiplier + ;%a - $DD VCMD accounts for per-channel transposition + ;%b - Readahead looks inside subroutines and loop sections + ;%c - ADSR/GAIN write orders are flipped during instrument setup + ;%d - Arpeggio doesn't play during rests + + ;Second byte is specified as... + ;%!xyzabcd + ;%! - New byte specified + ;%x - Reserved for playback adjustment for other Addmusics + ;%y - Reserved for playback adjustment for other Addmusics + ;%z - Reserved for playback adjustment for other Addmusics + ;%a - Reserved for playback adjustment for other Addmusics + ;%b - Reserved for playback adjustment for other Addmusics + ;%c - Reserved for playback adjustment for other Addmusics + ;%d - Rests are only keyed off if encountered in readahead + + db %10000000 ; 00 - AddmusicK1.0.8 and earlier (not counting Beta) + ; %??0?000? also replicates Vanilla SMW's behavior + db %00000000 ; %???????1 also replicates Vanilla SMW's behavior + db %11111111 ; 01 - AddmusicK1.0.9 + db %00000000 ; + db %10000000 ; 02 - AddmusicK Beta + db %00000000 ; + db %10000000 ; 03 - Romi's Addmusic404 + db %00000001 ; + db %10000000 ; 04 - Addmusic405 + db %00000001 ; + ; NOTE: Although it's not implemented yet, there are + ; readahead-related differences due to the $ED VCMD + ; having inconsistent parameter sizes for $80 and up + ; and Addmusic405 failing to account for these. + db %10001000 ; 05 - AddmusicM + db %00000000 ; + db %10000000 ; 06 - carol's MORE.bin + db %00000001 ; + db %10000000 ; 07 - Vanilla SMW + db %00000001 ; + ; 08-7F - Reserved for future Addmusics (or any extra past ones) ; 80-FF - See HotPatchPresetVCMDUserPatch (doesn't use the bit table) SubC_table2: @@ -1074,8 +1167,8 @@ SubC_table2: mov !HTuneValues+x, a ret -.gainRest - ;$F4 $05 has been replaced. This function can be replicated by a +.gainRest + ;$F4 $05 has been replaced. This function can be replicated by a ;type 3 remote code command. ;mov !RestGAINReplacement+x, a ; There is no memory location allocated for this at the moment. ;ret @@ -1124,7 +1217,7 @@ cmdFB: ; Arpeggio command. and a, #$7f ; \ inc a ; | Put this value into the type. mov !ArpType+x, a ; / - + .glissNoteCounter mov a, #$02 ; \ Force the note count to be non-zero, so it's treated as a valid command. mov !ArpNoteCount+x, a ; / @@ -1135,26 +1228,26 @@ cmdFB: ; Arpeggio command. mov !ArpSpecial+x, a ; / Yes, its purpose changes here. mov a, #$00 ; \ - mov !ArpCurrentDelta+x, a ; / The current pitch change is 0. + mov !ArpCurrentDelta+x, a ; / The current pitch change is 0. HandleArpeggio_return: - ret - -cmdFB_fetchLength: + ret + +cmdFB_fetchLength: call GetCommandDataFast ; \ Save the length between each change. mov !ArpLength+x, a ; | - mov !ArpTimeLeft+x, a ; / + mov !ArpTimeLeft+x, a ; / ret HandleArpeggio: ; Routine that controls all things arpeggio-related. mov a, !ArpNoteCount+x ; \ If the note count is 0, then this channel is not using arpeggio. beq .return ; / -.nextNoteCheck - beq .skipWaitTimeCheck - mov a, !WaitTime ; \ - cmp a, !ArpLength+x ; | Don't prepare another note when the next base note is to be keyed on. - bcs .skipWaitTimeCheck ; | An exception is made if the requested length is less than or equal - cmp a, $70+x ; | to !WaitTime, since they bypass keying off anyways that way. - bcs .return ; / +.nextNoteCheck + beq .skipWaitTimeCheck + mov a, !WaitTime ; \ + cmp a, !ArpLength+x ; | Don't prepare another note when the next base note is to be keyed on. + bcs .skipWaitTimeCheck ; | An exception is made if the requested length is less than or equal + cmp a, $70+x ; | to !WaitTime, since they bypass keying off anyways that way. + bcs .return ; / .skipWaitTimeCheck mov a, !ArpTimeLeft+x ; \ dec a ; | Decrement the timer. @@ -1163,31 +1256,31 @@ HandleArpeggio: ; Routine that controls all things arpeggio-related. cbne !WaitTime, .return ; If the time left is 2 (or 1), then key off this voice in preparation. ; Otherwise, do nothing. -.keyOffVoice - call TerminateOnLegatoEnable ; Key off the current voice (with conditions). +.keyOffVoice + call TerminateOnLegatoEnable ; Key off the current voice (with conditions). ;mov a, $48 ; \ ;mov y, #$5c ; | Key off this voice (but only if there's no sound effect currently playing on it). jmp KeyOffVoiceWithCheck ; / .doStuff - mov a, !ArpType+x ; - beq .normal ; - mov y, a + mov a, !ArpType+x ; + beq .normal ; + mov y, a mov a, !ArpCurrentDelta+x ; cmp y, #$01 ; \ If it's 1, then it's a trill beq .trill ; / ;cmp y, #$02 ; \ If it's 2, then it's a glissando. - ;beq .glissando ; / - + ;beq .glissando ; / + .glissando clrc ; \ adc a, !ArpSpecial+x ; | - bra ++ ; / - + bra ++ ; / + .trill eor a, !ArpSpecial+x ; \ Opposite note. - bra ++ ; / + bra ++ ; / .normal ; If it's 0, it's a normal arpeggio. mov a, !ArpNoteIndex+x ; \ @@ -1217,21 +1310,21 @@ HandleArpeggio: ; Routine that controls all things arpeggio-related. .playNote mov a, !ArpLength+x ; \ Now wait for this many ticks again. - mov !ArpTimeLeft+x, a ; / + mov !ArpTimeLeft+x, a ; / if !noSFX = !false - call TerminateIfSFXPlaying + call TerminateIfSFXPlaying endif - mov a, !PreviousNote+x ; \ Play this note. - cmp a, #$c7 ; |(unless it's a rest) -.restBranchGate ; | - beq + ; | + mov a, !PreviousNote+x ; \ Play this note. + cmp a, #$c7 ; |(unless it's a rest) +.restBranchGate ; | + beq + ; | + ; | Default state of this branch gate is open. call NoteVCMD ; / - + call TerminateOnLegatoEnable ; \ Key on the current voice (with conditions). - or ($47), ($48) ; / Set this voice to be keyed on. -.return2 + or ($47), ($48) ; / Set this voice to be keyed on. +.return2 ret } @@ -1240,17 +1333,17 @@ cmdFC: push a ; \ Get and save the remote address (we don't know where it's going). call GetCommandDataFast ; | push a ; / - call GetCommandDataFast ; \ - beq ClearRemoteCodeAddressesPre ; | Handle types #$ff, #$04, and #$00. #$04 and #$00 take effect now; #$ff has special properties. + call GetCommandDataFast ; \ + beq ClearRemoteCodeAddressesPre ; | Handle types #$ff, #$04, and #$00. #$04 and #$00 take effect now; #$ff has special properties. cmp a, #$ff ; | beq .noteStartCommand ; | cmp a, #$04 ; | - beq .immediateCall ; | + beq .immediateCall ; | cmp a, #$06 ; | Handle type $06, which is reserved for AMK beta gain conversions due to containing an auto-restore. - beq .noteStartCommand ; | It takes up a slot normally reserved for key on VCMDs since it comes built-in to the code type AND it needs to execute simultaneously with remote code type $05. - cmp a, #$07 ; | - beq ClearNonKONRemoteCodeAddressesPre ; | - cmp a, #$08 ; | + beq .noteStartCommand ; | It takes up a slot normally reserved for key on VCMDs since it comes built-in to the code type AND it needs to execute simultaneously with remote code type $05. + cmp a, #$07 ; | + beq ClearNonKONRemoteCodeAddressesPre ; | + cmp a, #$08 ; | beq ClearKONRemoteCodeAddressesPre ; / ; pop a ; \ @@ -1265,7 +1358,7 @@ cmdFC: ret ; -.noteStartCommand ; +.noteStartCommand ; mov !remoteCodeType2+x, a ; pop a ; \ mov !remoteCodeTargetAddr2+1+x, a ; | Note start code; get the address back and store it where it belongs. @@ -1305,45 +1398,45 @@ ClearRemoteCodeAddressesPre: pop a call L_1260 -ClearRemoteCodeAddressesAndOpenGate: - %OpenRunningRemoteCodeGate() -ClearRemoteCodeAddresses: - call ClearKONRemoteCodeAddresses +ClearRemoteCodeAddressesAndOpenGate: + %OpenRunningRemoteCodeGate() +ClearRemoteCodeAddresses: + call ClearKONRemoteCodeAddresses call ClearNonKONRemoteCodeAddresses - ret - -ClearRemoteCodeAddressesXInit: - ;mov x, $46 - ;bra ClearRemoteCodeAddresses - + ret + +ClearRemoteCodeAddressesXInit: + ;mov x, $46 + ;bra ClearRemoteCodeAddresses + ClearNonKONRemoteCodeAddressesPre: pop a pop a - call L_1260 - -ClearNonKONRemoteCodeAddressesXInit: - ;mov x, $46 -ClearNonKONRemoteCodeAddresses: - mov a, #$00 + call L_1260 + +ClearNonKONRemoteCodeAddressesXInit: + ;mov x, $46 +ClearNonKONRemoteCodeAddresses: + mov a, #$00 mov !remoteCodeTargetAddr+1+x, a - mov !remoteCodeTargetAddr+x, a + mov !remoteCodeTargetAddr+x, a mov !remoteCodeTimeValue+x, a mov !remoteCodeTimeLeft+x, a - mov !remoteCodeType+x, a - ret - + mov !remoteCodeType+x, a + ret + ClearKONRemoteCodeAddressesPre: pop a pop a - call L_1260 - -ClearKONRemoteCodeAddressesXInit: - ;mov x, $46 -ClearKONRemoteCodeAddresses: - mov a, #$00 + call L_1260 + +ClearKONRemoteCodeAddressesXInit: + ;mov x, $46 +ClearKONRemoteCodeAddresses: + mov a, #$00 mov !remoteCodeTargetAddr2+1+x, a - mov !remoteCodeTargetAddr2+x, a - mov !remoteCodeType2+x, a + mov !remoteCodeTargetAddr2+x, a + mov !remoteCodeType2+x, a ret } From b3585edda5929ba55db49867264e806b3ff4fe24 Mon Sep 17 00:00:00 2001 From: Torchkas Date: Mon, 27 Feb 2023 18:44:17 +0100 Subject: [PATCH 2/4] Added functionality through 1DFA using /usr/bin/bash386 meaning values 80 through 88 control the flag --- asm/Commands.asm | 1 + asm/main.asm | 2972 +++++++++++++++++++++++----------------------- 2 files changed, 1496 insertions(+), 1477 deletions(-) diff --git a/asm/Commands.asm b/asm/Commands.asm index 22c490eb..52323334 100755 --- a/asm/Commands.asm +++ b/asm/Commands.asm @@ -488,6 +488,7 @@ Condition7: pop a ret looping: + pop x mov a, $30+x mov $03e0+x, a bcc + diff --git a/asm/main.asm b/asm/main.asm index fc06a9c4..e88aa84e 100755 --- a/asm/main.asm +++ b/asm/main.asm @@ -63,6 +63,8 @@ incsrc "UserDefines.asm" ; $0211+x: The volume part of the qXX command. ; $0387: Amount the tempo should be increased by (used by the "time is running out!" sound effect to speed up the music). +; $0386 used by !Flag for conditional looping + ; $48: Bitwise indicator of the current channel being processed. ; $5C: Used to indicate that a volume needs to be updated (long routine, so it's only done when necessary). ; $0166: 4 bytes; used as the output byte to send to the 5A22. Originally AMM only used 2 of these, we can use all 4 for whatever we like. @@ -101,7 +103,7 @@ incsrc "UserDefines.asm" !PauseMusic = $0388 ; Pauses the music if not zero. Used in the pause SFX. !ChSFXPtrs = $20 ; Two bytes per channel, so $20 - $2f. -!ChSFXNoteTimer = $01d0 +!ChSFXNoteTimer = $01d0 !ChSFXPriority = $01d1 ;!ChSFXTimeToStart = $01d1 ; Time until the SFX on this channel starts. !ChSFXNoteTimerBackup = $03d1 ; Used to save space when two consecutive notes use the same length. @@ -134,16 +136,18 @@ incsrc "UserDefines.asm" !remoteCodeType = $03a0 ; The remote code type. !remoteCodeTimeLeft = $03a1 ; The amount of time left until we run remote code if the type is 1 or 2. !remoteCodeTimeValue = $01a0 ; The value to set the timer to when necessary. -!remoteCodeTargetAddr2 = $0190 ; The address to jump to for "start of note" code. 16-bit. +!remoteCodeTargetAddr2 = $0190 ; The address to jump to for "start of note" code. 16-bit. !remoteCodeType2 = $03d0 ; The remote code type for negative cases. !InRest = $01a1 +!Flag = $0386 + arch spc700-raw org $000000 base $0400 ; Do not change this. - -if !noSFX = !true -print "NoSFX is enabled" + +if !noSFX = !true +print "NoSFX is enabled" endif { ; Program setup clrp @@ -194,9 +198,9 @@ if !noSFX = !false call ProcessSFX endif call ProcessAPU1Input ; APU1 has to come first since it receives the "pause" sound effects that it pseudo-sends to APU0. - call ProcessAPU0Input + call ProcessAPU0Input if !noSFX = !false - call ProcessAPU3Input + call ProcessAPU3Input endif mov x, #$00 call ReadInputRegister ; read/send APU0 @@ -218,20 +222,20 @@ L_0573: mul ya clrc adc a, $49 - mov $49, a -;Slowdown partial bugfix by KungFuFurby 6/24/20 -;This fix doubles the tolerance the sound driver is able to handle before -;ticks are lost. -;Additional possible fixes: -;- Send Y to $0D (a free byte) OR... -;-- Swap $49 and $44's purpose, and repurpose $45 for utilization with the -; addw opcode instead of being a just a tick counter -;- Read $FD more often (only needed if we overflow from 15 to 0) and -; reserve a memory location for this purpose. - bcs SoundTickOn - cmp y, #$00 - beq L_058D - + mov $49, a +;Slowdown partial bugfix by KungFuFurby 6/24/20 +;This fix doubles the tolerance the sound driver is able to handle before +;ticks are lost. +;Additional possible fixes: +;- Send Y to $0D (a free byte) OR... +;-- Swap $49 and $44's purpose, and repurpose $45 for utilization with the +; addw opcode instead of being a just a tick counter +;- Read $FD more often (only needed if we overflow from 15 to 0) and +; reserve a memory location for this purpose. + bcs SoundTickOn + cmp y, #$00 + beq L_058D + SoundTickOn: mov a, !PauseMusic bne L_0586 @@ -274,11 +278,11 @@ L_059D: } } -ReadInputRegisterIncX2: - inc x -ReadInputRegisterIncX1: - inc x -; send 04+X to APUX; get APUX to 00+X with "debounce"? +ReadInputRegisterIncX2: + inc x +ReadInputRegisterIncX1: + inc x +; send 04+X to APUX; get APUX to 00+X with "debounce"? ;L_05A5: ReadInputRegister: { @@ -294,11 +298,11 @@ L_05C1: ; | mov $00+x, y ; | ret ; / } - -macro OpenRunningRemoteCodeGate() + +macro OpenRunningRemoteCodeGate() mov a, #$f4 ;mov a, d+x opcode - mov runningRemoteCodeGate, a -endmacro + mov runningRemoteCodeGate, a +endmacro RunRemoteCode: { @@ -308,19 +312,19 @@ RunRemoteCode: push a mov a, !remoteCodeTargetAddr+x mov y, a - mov a, !remoteCodeTargetAddr+1+x -RunRemoteCode_Exec: - mov $30+x, y - mov $31+x, a - dec a - bne + - call UseGainInstead - bra RestoreTrackPtrFromStack + mov a, !remoteCodeTargetAddr+1+x +RunRemoteCode_Exec: + mov $30+x, y + mov $31+x, a + dec a + bne + + call UseGainInstead + bra RestoreTrackPtrFromStack + mov a, #$6f ;RET opcode mov runningRemoteCodeGate, a call L_0C57 ; This feels evil. Oh well. At any rate, this'll run the code we give it. - %OpenRunningRemoteCodeGate() + %OpenRunningRemoteCodeGate() RestoreTrackPtrFromStack: pop a mov $31+x, a @@ -339,12 +343,12 @@ RunRemoteCode2: mov y, a mov a, !remoteCodeTargetAddr2+1+x bra RunRemoteCode_Exec -} - -CheckForRemoteCodeType6: - mov a, #$06 - cmp a, !remoteCodeType2+x - ret +} + +CheckForRemoteCodeType6: + mov a, #$06 + cmp a, !remoteCodeType2+x + ret ; handle a note vcmd NoteVCMD: @@ -353,21 +357,21 @@ NoteVCMD: ; A should contain the note (can be percussion or a normal pitch note). cmp a, #$d0 bcs PercNote ; percussion note - cmp a,#$C6 ;;;;;;;;;;;;Code change + cmp a,#$C6 ;;;;;;;;;;;;Code change bcc NormalNote beq L_05CD if_rest: mov a, #$01 mov !InRest+x, a -if !noSFX = !false - call TerminateIfSFXPlaying +if !noSFX = !false + call TerminateIfSFXPlaying endif mov a, !remoteCodeType+x - cmp a, #$03 + cmp a, #$03 if_rest_koffCheckGate: - beq L_05CD - call CheckForRemoteCodeType6 + beq L_05CD + call CheckForRemoteCodeType6 beq L_05CD call KeyOffCurrentVoice tclr $0162, a @@ -377,7 +381,7 @@ L_05CD: PercNote: mov $c1+x, a - dec a + dec a call SetupPercInstrument call ApplyInstrument ; set sample A-$D0 in bank $5FA5 width 6 NormalNote: ;;;;;;;;;;/ Code change @@ -392,19 +396,19 @@ if !noSFX = !false beq NoPitchAdjust ; Don't adjust the pitch. endif ; That says no pitch adjust, but we do more stuff here related to the "no sound effects allowed" club. - - call CheckForRemoteCodeType6 - beq .remoteCodeRestoreInstrumentOnKON - - dec a - cmp a, !remoteCodeType+x - bne .checkRemoteCodeTypes -.remoteCodeRestoreInstrumentOnKON - mov a, #$7F ; \ Don't restore remote gain. + + call CheckForRemoteCodeType6 + beq .remoteCodeRestoreInstrumentOnKON + + dec a + cmp a, !remoteCodeType+x + bne .checkRemoteCodeTypes +.remoteCodeRestoreInstrumentOnKON + mov a, #$7F ; \ Don't restore remote gain. and a, !BackupSRCN+x ; | Instead, restore either the - mov !BackupSRCN+x, a ; / instrument or the sample. - call RestoreInstrumentInformation - + mov !BackupSRCN+x, a ; / instrument or the sample. + call RestoreInstrumentInformation + .checkRemoteCodeTypes mov a, !remoteCodeType+x dec a @@ -417,9 +421,9 @@ endif mov a, !remoteCodeTargetAddr2+1+x beq .noRemoteCode - - mov a, !remoteCodeType2+x - bpl .noRemoteCode + + mov a, !remoteCodeType2+x + bpl .noRemoteCode call RunRemoteCode2 @@ -453,9 +457,9 @@ NoPitchAdjust: mov $b0+x, a ; / or ($5c), ($48) ; set volume changed flg or ($47), ($48) ; set key on shadow vbit -if !noSFX = !false +if !noSFX = !false mov a, $48 ; If $48 is 0, then this is SFX code. - beq L_062B ; Don't adjust the pitch. + beq L_062B ; Don't adjust the pitch. endif mov a, $0300+x ; Get pitch envelope length. mov $90+x, a ; If zero, then we are not processing a pitch envelope. @@ -476,9 +480,9 @@ L_0621: ; L_062B: call DDEEFix ; set DSP pitch from $10/11 -SetPitch: ; -if !noSFX = !false - call TerminateIfSFXPlaying +SetPitch: ; +if !noSFX = !false + call TerminateIfSFXPlaying endif push x mov a, $11 @@ -494,7 +498,7 @@ endif ;mov a, PitchTable+3+y ;push a mov a, PitchTable+2+y - setc + setc sbc a, $14 ;pop y ;subw ya, $14 @@ -515,7 +519,7 @@ endif bne - mov $14, a pop x - mov a, $02f0+x + mov a, $02f0+x push a mov y, $15 mul ya @@ -524,7 +528,7 @@ endif mov y, $14 mul ya push y - mov a, $0210+x + mov a, $0210+x push a mov y, $14 mul ya @@ -541,90 +545,90 @@ endif xcn a ; (if vbit clear in $1d) lsr a or a, #$02 ; A = voice X pitch DSP reg - mov y, $16 - movw $f2, ya - inc a - mov y, $17 - movw $f2, ya + mov y, $16 + movw $f2, ya + inc a + mov y, $17 + movw $f2, ya ret -} - -L_09CDWPreCheck: +} + +L_09CDWPreCheck: mov a, $91+x ; If pitch slide delta is being delayed... beq L_1119 dec $91+x bra L_112A -L_1119: +L_1119: if !noSFX = !false mov a, $1d ; \ Check to see if this channel is muted (by a sound effect or whatever) and a, $48 ; | - bne L_112A ; / -endif - set1 $13.7 ; + bne L_112A ; / +endif + set1 $13.7 ; ; add pitch slide delta and set DSP pitch L_09CD: mov a, #$02b0&$FF ; pitch (notenum fixed-point) - dec $90+x + dec $90+x ;Modifies $02b0-$02b1, $02c0-$02c1, $02d0 - call L_1075Setup2 ; add pitch slide delta to value ;ERROR -L_112A: -DDEEFix: -{ + call L_1075Setup2 ; add pitch slide delta to value ;ERROR +L_112A: +DDEEFix: +{ mov a, $02b1+x - mov y, a + mov y, a mov a, $90+x - beq + + beq + - mov a, $02b0+x bra ++ -+ -if !noSFX = !false ++ +if !noSFX = !false mov a, $48 ; If $48 is 0, then this is SFX code. - beq - ; Don't adjust the pitch. + beq - ; Don't adjust the pitch. and a, $1d - bne - + bne - endif mov a, $02d1+x ; Make sure that the correct fine tune value is used for the music. - mov $02b0+x, a -++ + mov $02b0+x, a +++ movw $10, ya ; notenum to $10/11 - ret -} - + ret +} + if !noSFX = !false -ForceSFXEchoOff: - setc +ForceSFXEchoOff: + setc ForceSFXEchoOn: - mov a, #$00 + mov a, #$00 adc a, #$ff - mov !SFXEchoChannels, a + mov !SFXEchoChannels, a bra EffectModifier -endif - +endif + SubC_table2_PitchMod: mov !MusicPModChannels, a ; \ This is for music. - bra EffectModifier ; / Call the effect modifier routine. - + bra EffectModifier ; / Call the effect modifier routine. + SubC_3: eor (!MusicEchoChannels), ($48) - bra EffectModifier + bra EffectModifier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmdF8: ; Noise command. { Noiz: - or (!MusicNoiseChannels), ($48) -if !noSFX = !false - and a, #$1f - mov $0389, a - cmp !SFXNoiseChannels, #$00 - bne + -endif - call ModifyNoise + or (!MusicNoiseChannels), ($48) +if !noSFX = !false + and a, #$1f + mov $0389, a + cmp !SFXNoiseChannels, #$00 + bne + +endif + call ModifyNoise + -} +} EffectModifier: ; Call this whenever either $1d or the various echo, noise, or pitch modulation addresses are modified. { @@ -638,10 +642,10 @@ EffectModifier: ; Call this whenever either $1d or the various echo, noise, o ; M is !WhateverMusicChannels, ; E is !WhateverSFXChannels. ; and S is $1d (the current channels for which SFX are enabled) - ; Yay logic! - + ; Yay logic! + clrc ; \ - adc $f2, #$10 ; / Get the next DSP register. + adc $f2, #$10 ; / Get the next DSP register. if !noSFX = !false mov a, $1d ; \ a = S @@ -649,14 +653,14 @@ if !noSFX = !false and a, (X) ; / a = S'M mov $10, a - + ;Go grab !SFXPModChannels+x. mov a, $03+x ; \ a = S and a, $1d ; | a = SE - or a, $10 ; / a = S'M + SE - inc x -else - mov a, (X+) + or a, $10 ; / a = S'M + SE + inc x +else + mov a, (X+) endif ; \ Write to the relevant DSP register. @@ -671,28 +675,28 @@ endif -} -if !noSFX = !false -macro RestoreVolLevelsPostNoise() - mov a, $d0+x - mov $f3, a - inc $f2 - mov a, $d1+x - mov $f3, a - mov a, $13 - tclr $1a, a -endmacro - -macro NoiseBackupThenZeroVolLevels() - mov a, $f3 - mov $d0+x, a - mov $f3, #$00 - inc $f2 - mov a, $f3 - mov $d1+x, a - mov $f3, #$00 - or ($1a), ($13) -endmacro +} +if !noSFX = !false +macro RestoreVolLevelsPostNoise() + mov a, $d0+x + mov $f3, a + inc $f2 + mov a, $d1+x + mov $f3, a + mov a, $13 + tclr $1a, a +endmacro + +macro NoiseBackupThenZeroVolLevels() + mov a, $f3 + mov $d0+x, a + mov $f3, #$00 + inc $f2 + mov a, $f3 + mov $d1+x, a + mov $f3, #$00 + or ($1a), ($13) +endmacro ProcessSFX: ; Major code changes ahead. { ; Originally, the SMW SFX were handled within their port handling routines. @@ -746,117 +750,117 @@ EndSFX: ; Of course, that doesn't work so well when some channels don't map to input ports... - mov a, $18 -if !useSFXSequenceFor1DFASFX = !false - bbc!1DFASFXChannel $18, + - cmp $1c, #$00 - bne ++ -endif + mov a, $18 +if !useSFXSequenceFor1DFASFX = !false + bbc!1DFASFXChannel $18, + + cmp $1c, #$00 + bne ++ +endif + ; \ - tclr $1d, a ; | Clear the bit of $1d that this SFX corresponds to. + tclr $1d, a ; | Clear the bit of $1d that this SFX corresponds to. ++ tclr !SFXNoiseChannels, a ; / Turn noise off for this channel's SFX. - call EffectModifier - mov a, !SFXNoiseChannels -if !noiseFrequencySFXInstanceResolution = !true - beq .restoreMusicNoise - call SetSFXNoise - call ModifyNoise - bra RestoreInstrumentInformation -else - bne RestoreInstrumentInformation -endif -.restoreMusicNoise: - mov $1f, a -if !useSFXSequenceFor1DFASFX = !false - bbc!1DFASFXChannel $18, + - mov a, $1c - bne ++ -endif -+ - mov !ChSFXPriority+x, a -++ - mov a, $0389 + call EffectModifier + mov a, !SFXNoiseChannels +if !noiseFrequencySFXInstanceResolution = !true + beq .restoreMusicNoise + call SetSFXNoise + call ModifyNoise + bra RestoreInstrumentInformation +else + bne RestoreInstrumentInformation +endif +.restoreMusicNoise: + mov $1f, a +if !useSFXSequenceFor1DFASFX = !false + bbc!1DFASFXChannel $18, + + mov a, $1c + bne ++ +endif ++ + mov !ChSFXPriority+x, a +++ + mov a, $0389 call ModifyNoise - mov a, !MusicNoiseChannels - and a, $1a - beq RestoreInstrumentInformation - mov $12, a - mov a, !SFXNoiseChannels - tclr $12, a - mov $13, #$01 - ;Restore VxVOL DSP registers of all music noise channels. - mov x, #$00 + mov a, !MusicNoiseChannels + and a, $1a + beq RestoreInstrumentInformation + mov $12, a + mov a, !SFXNoiseChannels + tclr $12, a + mov $13, #$01 + ;Restore VxVOL DSP registers of all music noise channels. + mov x, #$00 mov $f2, x -- - lsr $12 - push p - bcc ++ -if !noiseFrequencySFXInstanceResolution = !true - call RestoreVolLevelsPostNoise -else - %RestoreVolLevelsPostNoise() -endif -++ - call NoiseSetVolLevelsNextCh - pop p +- + lsr $12 + push p + bcc ++ +if !noiseFrequencySFXInstanceResolution = !true + call RestoreVolLevelsPostNoise +else + %RestoreVolLevelsPostNoise() +endif +++ + call NoiseSetVolLevelsNextCh + pop p bne - mov x, $46 ; \ endif - + RestoreInstrumentInformation: ; \ Call this with x = currentchannel*2 to restore all instrument properties for that channel. - mov a, !BackupSRCN+x ; | - push p ; | + mov a, !BackupSRCN+x ; | + push p ; | asl a ; | bmi .restoreSample ; | mov a, $c1+x ; | Fix instrument. beq .doneRestoring ; | dec a ; | - call SetInstrument ; | -.checkRemoteGainRestoration ; | - pop p ; | - bpl .doneRestoringNoPop ; | Fix remote gain. + call SetInstrument ; | +.checkRemoteGainRestoration ; | + pop p ; | + bpl .doneRestoringNoPop ; | Fix remote gain. bra RestoreRemoteGain ; / -.doneRestoring ; - pop p ; +.doneRestoring ; + pop p ; .doneRestoringNoPop ; ret ; ; .restoreSample ; \ - call RestoreMusicSample ; / Fix sample. + call RestoreMusicSample ; / Fix sample. bra .checkRemoteGainRestoration -} - +} + SubC_9: call FetchVoiceXAndZeroA ; \ Turn the current instrument back on. mov !BackupSRCN+x, a ; | And make sure it's an instrument, not a sample or something. - bra RestoreInstrumentInformation ; / This ensures stuff like an instrument's ADSR is restored as well. - -UseGainInstead: - setp - mov $0170&$FF+x, y - clrp - mov a, #$80 - call ORBackupSRCN -if !noSFX = !false - call TerminateIfSFXPlaying -endif -RestoreRemoteGain: - mov a, $0170+x - mov y, a + bra RestoreInstrumentInformation ; / This ensures stuff like an instrument's ADSR is restored as well. + +UseGainInstead: + setp + mov $0170&$FF+x, y + clrp + mov a, #$80 + call ORBackupSRCN +if !noSFX = !false + call TerminateIfSFXPlaying +endif +RestoreRemoteGain: + mov a, $0170+x + mov y, a mov a, x ; \ lsr a ; | GAIN Register into a xcn a ; | - or a, #$07 ; / - movw $f2, ya ; Write - dec a ; \ - dec a ; | Clear ADSR bit to force GAIN. - mov y, #$7f ; | - movw $f2, ya ; / - ret + or a, #$07 ; / + movw $f2, ya ; Write + dec a ; \ + dec a ; | Clear ADSR bit to force GAIN. + mov y, #$7f ; | + movw $f2, ya ; / + ret if !noSFX = !false HandleSFXVoice: @@ -868,9 +872,9 @@ HandleSFXVoice: jmp .processSFXPitch + .getMoreSFXData - call GetNextSFXByte - bne + ; If the current byte is zero, then end it. - jmp EndSFX + call GetNextSFXByte + bne + ; If the current byte is zero, then end it. + jmp EndSFX + bmi .noteOrCommand ; If it's negative, then it's a command or note. mov !ChSFXNoteTimerBackup+x, a @@ -883,22 +887,22 @@ HandleSFXVoice: lsr a ; | xcn a ; | Put the left volume DSP register for this channel into y. if !noiseFrequencySFXInstanceResolution = !true - mov y, a ; | - pop a ; | + mov y, a ; | + pop a ; | call .setVolFromNoiseSetting ; | call DSPWrite ; / Set the volume for the left speaker. inc y ; \ - call DSPWrite ; / Set the volume for the right speaker. We might change it later, but this saves space. -else - pop y - movw $f2, ya ; Set the volume for the left speaker. - inc a - movw $f2, ya ; Set the volume for the right speaker. We might change it later, but this saves space. + call DSPWrite ; / Set the volume for the right speaker. We might change it later, but this saves space. +else + pop y + movw $f2, ya ; Set the volume for the left speaker. + inc a + movw $f2, ya ; Set the volume for the right speaker. We might change it later, but this saves space. endif call GetNextSFXByte ; bmi .noteOrCommand ; If the byte is positive, then set the right volume to the byte we just got. if !noiseFrequencySFXInstanceResolution = !true - call .setVolFromNoiseSetting ; + call .setVolFromNoiseSetting ; endif mov $f3, a ; > Set the volume for the right speaker. call GetNextSFXByte ; @@ -917,55 +921,55 @@ endif .noteOrCommand ; SFX commands! cmp a, #$dd ; \ - beq .pitchBendCommand ; / $DD is the pitch bend command. + beq .pitchBendCommand ; / $DD is the pitch bend command. cmp a, #$eb ; \ - beq .pitchBendCommand2 ; / $EB is...another pitch bend command. - + beq .pitchBendCommand2 ; / $EB is...another pitch bend command. + cmp a, #$fd ; \ - beq .executeCode ; / $FD is the code execution command. - cmp a, #$da ; \ + beq .executeCode ; / $FD is the code execution command. + cmp a, #$da ; \ beq .instrumentCommand ; / $DA is the instrument command. cmp a, #$fe ; \ beq .loopSFX ; / $FE is the restart SFX command. bcc .playNote ; / Play a note. - mov a, !ChSFXPtrs+x ; \ Move back one byte. - bne + ; | - dec !ChSFXPtrs+1+x ; | -+ ; | - dec !ChSFXPtrs+x ; | - mov a, $18 ; | #$FF is the loop the last note command. + mov a, !ChSFXPtrs+x ; \ Move back one byte. + bne + ; | + dec !ChSFXPtrs+1+x ; | ++ ; | + dec !ChSFXPtrs+x ; | + mov a, $18 ; | #$FF is the loop the last note command. bra .keyOnNote ; / ; other $80+ .loopSFX mov a, !ChSFXPtrBackup+1+x ; \ mov !ChSFXPtrs+1+x, a ; | Set the current pointer to the backup pointer, mov a, !ChSFXPtrBackup+x ; | Thus restarting this sound effect. - mov !ChSFXPtrs+x, a ; / + mov !ChSFXPtrs+x, a ; / .braToGetMoreSFXData bra .getMoreSFXData .playNote call NoteVCMD ; Loooooooong routine that starts playing the note in A on channel (X/2). - mov a, $18 - setp - mov y, !InRest&$ff+x - clrp - beq .keyOnNote - call KeyOffVoices - bra .setNoteLength + mov a, $18 + setp + mov y, !InRest&$ff+x + clrp + beq .keyOnNote + call KeyOffVoices + bra .setNoteLength .keyOnNote call KeyOnVoices ; Key on the voice. .setNoteLength mov a, !ChSFXNoteTimerBackup+x ; \ Get the length of the note back mov !ChSFXNoteTimer+x, a ; / And since it was actually a length, store it. -.processSFXPitch - mov a, $91+x ; If pitch slide is not being delayed... - beq .noPitchSlideDelay - dec $91+x -.return1 - ret +.processSFXPitch + mov a, $91+x ; If pitch slide is not being delayed... + beq .noPitchSlideDelay + dec $91+x +.return1 + ret .noPitchSlideDelay mov a, $90+x ; pitch slide counter beq .noPitchSlide @@ -1001,10 +1005,10 @@ endif ; DA .instrumentCommand mov a, $18 ; \ Disable noise for this channel. - tclr !SFXNoiseChannels, a ; / (EffectModifier is called a bit later) -if !noiseFrequencySFXInstanceResolution = !true + tclr !SFXNoiseChannels, a ; / (EffectModifier is called a bit later) +if !noiseFrequencySFXInstanceResolution = !true tclr $1a, a -endif +endif .getInstrumentByte call GetNextSFXByte ; Get the parameter for the instrument command. @@ -1012,208 +1016,208 @@ endif call SetSFXInstrument ; No noise here! bra .braToGetMoreSFXData ; We're done here; get the next SFX command. .noise - and a, #$1f ; \ Noise can only be from #$00 - #$1F - or (!SFXNoiseChannels), ($18) + and a, #$1f ; \ Noise can only be from #$00 - #$1F + or (!SFXNoiseChannels), ($18) if !noiseFrequencySFXInstanceResolution = !true - mov $01f1+x, a - cmp !SFXNoiseChannels, $18 - beq .noiseNoPrevSFXFrequency - call SetSFXNoise - bra .noiseCheckMusic - -.noiseNoPrevSFXFrequency - mov $1f, #$00 -if !noiseFrequencyMatchChecks = !true - mov $1e, a -else - ;Store the channel number instead. - mov $1e, x -endif -endif - ;All music channels with noise need to have their VxVOL values - ;zeroed out here if the frequency is not a match. + mov $01f1+x, a + cmp !SFXNoiseChannels, $18 + beq .noiseNoPrevSFXFrequency + call SetSFXNoise + bra .noiseCheckMusic + +.noiseNoPrevSFXFrequency + mov $1f, #$00 +if !noiseFrequencyMatchChecks = !true + mov $1e, a +else + ;Store the channel number instead. + mov $1e, x +endif +endif + ;All music channels with noise need to have their VxVOL values + ;zeroed out here if the frequency is not a match. .noiseCheckMusic -if !noiseFrequencyMatchChecks = !true - cmp a, $0389 - beq .noiseSetFreq -endif - cmp !MusicNoiseChannels, #$00 - beq .noiseSetFreq - push x - push a - mov $12, !MusicNoiseChannels - mov a, $1a - or a, !SFXNoiseChannels - or a, $1d - tclr $12, a - mov $13, #$01 - ;Zero out VxVOL DSP registers of all music noise channels. - mov x, #$00 - mov $f2, x -- - lsr $12 - push p - bcc + -if !noiseFrequencySFXInstanceResolution = !true - call NoiseBackupThenZeroVolLevels -else - %NoiseBackupThenZeroVolLevels() -endif -+ - call NoiseSetVolLevelsNextCh - pop p - bne - - - pop a - pop x - +if !noiseFrequencyMatchChecks = !true + cmp a, $0389 + beq .noiseSetFreq +endif + cmp !MusicNoiseChannels, #$00 + beq .noiseSetFreq + push x + push a + mov $12, !MusicNoiseChannels + mov a, $1a + or a, !SFXNoiseChannels + or a, $1d + tclr $12, a + mov $13, #$01 + ;Zero out VxVOL DSP registers of all music noise channels. + mov x, #$00 + mov $f2, x +- + lsr $12 + push p + bcc + +if !noiseFrequencySFXInstanceResolution = !true + call NoiseBackupThenZeroVolLevels +else + %NoiseBackupThenZeroVolLevels() +endif ++ + call NoiseSetVolLevelsNextCh + pop p + bne - + + pop a + pop x + .noiseSetFreq call ModifyNoise - bra .getInstrumentByte ; Now we...go back until we find an actual instrument? Odd way of doing it, but I guess that works. -if !noiseFrequencySFXInstanceResolution = !true -.setVolFromNoiseSetting - mov $11, a - mov a, $18 - and a, !SFXNoiseChannels - beq .setNormalVol -if !noiseFrequencyMatchChecks = !true - mov a, $01f1+x - cmp a, $1e - beq .setNormalVol -else - cmp x, $1e - beq .setNormalVol -endif - mov a, !ChSFXPriority+x - cmp a, $1f - bcc .storeVolFromNoiseSetting - bne .setNormalVol - cmp x, #$0e - beq .setNormalVol -;Now we scan the priorities of all channels higher than this one. - mov $12, x -- - adc $12, #$02 - push x - mov a, !ChSFXPriority+x - mov x, $12 - cmp a, !ChSFXPriority+x - pop x - bcc .storeVolFromNoiseSetting - bne .setNormalVol - cmp $12, #$0e - bcc - -.storeVolFromNoiseSetting - mov a, y - lsr a - mov a, $11 - bcc + - mov $d1+x, a - bra .setZeroVolFromNoiseSetting -+ - mov $d0+x, a -.setZeroVolFromNoiseSetting - mov a, #$00 - ret -.setNormalVol - mov a, $11 - ret - -SetSFXNoise: - push x - ;Decide which SFX channel's noise frequency will be used as the - ;comparison point, using priority as the factor. Ties favor highest - ;channel ID. - mov $12, !SFXNoiseChannels - mov x, #$00 - mov $13, x - setc -- - asl $13 - lsr $12 - push p - bcc + - mov a, !ChSFXPriority+x - cmp a, $1f - bcc + - mov $1f, a - mov a, $01f1+x -if !noiseFrequencyMatchChecks = !true - mov $1e, a -else - mov $11, a - ;We'll just store the winning channel number instead, since we only - ;have one channel to allocate for noise. - ;The frequency to use is stored in scratch RAM. - mov $1e, x -endif -+ - inc x - inc x - pop p - bne - - ;OK, we have our winning frequency, now compare and set VxVOL values - ;based off of noise frequency. - mov $12, !SFXNoiseChannels - mov a, $13 - tclr $12, a -if !noiseFrequencyMatchChecks = !true - mov a, $1e -else - mov a, $11 -endif - mov x, #$00 - mov $f2, x - mov $13, #$01 -- - lsr $12 - push p - push a - bcc ++ -if !noiseFrequencyMatchChecks = !true - cmp a, $01f1+x -else - cmp x, $1e -endif - beq + - setc - call NoiseBackupThenZeroVolLevels - bra ++ -+ - clrc - mov a, $13 - and a, $1a - beq ++ - setc - call RestoreVolLevelsPostNoise -++ - call NoiseSetVolLevelsNextCh - pop a - pop p - bne - - - pop x - ret - -NoiseBackupThenZeroVolLevels: - %NoiseBackupThenZeroVolLevels() - ret - -RestoreVolLevelsPostNoise: - %RestoreVolLevelsPostNoise() - ret - -endif - -NoiseSetVolLevelsNextCh: - notc - adc $f2, #$0f - inc x - inc x - asl $13 - ret - -SetSFXInstrument: + bra .getInstrumentByte ; Now we...go back until we find an actual instrument? Odd way of doing it, but I guess that works. +if !noiseFrequencySFXInstanceResolution = !true +.setVolFromNoiseSetting + mov $11, a + mov a, $18 + and a, !SFXNoiseChannels + beq .setNormalVol +if !noiseFrequencyMatchChecks = !true + mov a, $01f1+x + cmp a, $1e + beq .setNormalVol +else + cmp x, $1e + beq .setNormalVol +endif + mov a, !ChSFXPriority+x + cmp a, $1f + bcc .storeVolFromNoiseSetting + bne .setNormalVol + cmp x, #$0e + beq .setNormalVol +;Now we scan the priorities of all channels higher than this one. + mov $12, x +- + adc $12, #$02 + push x + mov a, !ChSFXPriority+x + mov x, $12 + cmp a, !ChSFXPriority+x + pop x + bcc .storeVolFromNoiseSetting + bne .setNormalVol + cmp $12, #$0e + bcc - +.storeVolFromNoiseSetting + mov a, y + lsr a + mov a, $11 + bcc + + mov $d1+x, a + bra .setZeroVolFromNoiseSetting ++ + mov $d0+x, a +.setZeroVolFromNoiseSetting + mov a, #$00 + ret +.setNormalVol + mov a, $11 + ret + +SetSFXNoise: + push x + ;Decide which SFX channel's noise frequency will be used as the + ;comparison point, using priority as the factor. Ties favor highest + ;channel ID. + mov $12, !SFXNoiseChannels + mov x, #$00 + mov $13, x + setc +- + asl $13 + lsr $12 + push p + bcc + + mov a, !ChSFXPriority+x + cmp a, $1f + bcc + + mov $1f, a + mov a, $01f1+x +if !noiseFrequencyMatchChecks = !true + mov $1e, a +else + mov $11, a + ;We'll just store the winning channel number instead, since we only + ;have one channel to allocate for noise. + ;The frequency to use is stored in scratch RAM. + mov $1e, x +endif ++ + inc x + inc x + pop p + bne - + ;OK, we have our winning frequency, now compare and set VxVOL values + ;based off of noise frequency. + mov $12, !SFXNoiseChannels + mov a, $13 + tclr $12, a +if !noiseFrequencyMatchChecks = !true + mov a, $1e +else + mov a, $11 +endif + mov x, #$00 + mov $f2, x + mov $13, #$01 +- + lsr $12 + push p + push a + bcc ++ +if !noiseFrequencyMatchChecks = !true + cmp a, $01f1+x +else + cmp x, $1e +endif + beq + + setc + call NoiseBackupThenZeroVolLevels + bra ++ ++ + clrc + mov a, $13 + and a, $1a + beq ++ + setc + call RestoreVolLevelsPostNoise +++ + call NoiseSetVolLevelsNextCh + pop a + pop p + bne - + + pop x + ret + +NoiseBackupThenZeroVolLevels: + %NoiseBackupThenZeroVolLevels() + ret + +RestoreVolLevelsPostNoise: + %RestoreVolLevelsPostNoise() + ret + +endif + +NoiseSetVolLevelsNextCh: + notc + adc $f2, #$0f + inc x + inc x + asl $13 + ret + +SetSFXInstrument: mov y, #$09 ; \ mul ya ; | Set up the instrument table for SFX mov x, a ; | @@ -1230,338 +1234,338 @@ SetSFXInstrument: dbnz $12, - ; / mov a, SFXInstrumentTable+x ; \ mov x, $46 ; | Set pitch base multiplier. - mov $0210+x, a ; / + mov $0210+x, a ; / mov a, #$00 ; \ Disable sub-tuning - mov $02f0+x, a ; / + mov $02f0+x, a ; / ret } -if !PSwitchIsSFX = !true - -PSwitchPtrs: - dw PSwitchCh0 - dw PSwitchCh1 - dw PSwitchCh2 +if !PSwitchIsSFX = !true + +PSwitchPtrs: + dw PSwitchCh0 + dw PSwitchCh1 + dw PSwitchCh2 PSwitchCh2: - db $DA, $02 ; @2 - db $FD ; #jsr PSwitchInitCh1And2 - dw PSwitchInitCh1And2 + db $DA, $02 ; @2 + db $FD ; #jsr PSwitchInitCh1And2 + dw PSwitchInitCh1And2 PSwitchCh2NoteLen3X1: - db $30, $00, $C6 ; r=24 + db $30, $00, $C6 ; r=24 PSwitchCh2NoteLen2X1: - db $20, $00, $26, $A4 ; y0o4c=16 + db $20, $00, $26, $A4 ; y0o4c=16 PSwitchCh2NoteLen1: - db $10, $0A, $1D, $9F ; y5o3g=8 + db $10, $0A, $1D, $9F ; y5o3g=8 PSwitchCh2NoteLen2: - db $10, $00, $C6 ; r=8 + db $10, $00, $C6 ; r=8 PSwitchCh2NoteLen3: - db $10, $13, $13, $AB ; y10o4g=8 + db $10, $13, $13, $AB ; y10o4g=8 PSwitchCh2NoteLen4: - db $10, $17, $0F, $9F ; y12o3c=8 + db $10, $17, $0F, $9F ; y12o3c=8 PSwitchCh2NoteLen2X2: - db $20, $1D, $0A, $A4 ; y15o4c=4 + db $20, $1D, $0A, $A4 ; y15o4c=4 PSwitchCh2NoteLen5: db $10, $26, $00, $9F ; y20o3g=8 PSwitchCh2NoteLen3X2: - db $30, $00, $C6 ; r=24 + db $30, $00, $C6 ; r=24 PSwitchCh2NoteLen2X3: - db $20, $26, $00, $A5 ; y20o4c+=16 + db $20, $26, $00, $A5 ; y20o4c+=16 PSwitchCh2NoteLen6: - db $10, $1D, $0A, $A0 ; y15o3g+=8 + db $10, $1D, $0A, $A0 ; y15o3g+=8 PSwitchCh2NoteLen7: - db $10, $00, $C6 ; r=8 + db $10, $00, $C6 ; r=8 PSwitchCh2NoteLen8: - db $10, $13, $13, $AC ; y10o4g+=8 + db $10, $13, $13, $AC ; y10o4g+=8 PSwitchCh2NoteLen9: - db $10, $0C, $18, $A0 ; y7o3c+=8 + db $10, $0C, $18, $A0 ; y7o3c+=8 PSwitchCh2NoteLen2X4: - db $20, $1D, $0A, $A5 ; y5o4c+=4 + db $20, $1D, $0A, $A5 ; y5o4c+=4 PSwitchCh2NoteLen10: - db $10, $00, $26, $A0 ; y0o3g+=8 - db $FD ; #jsr PSwitchNextLoopCh2 + db $10, $00, $26, $A0 ; y0o3g+=8 + db $FD ; #jsr PSwitchNextLoopCh2 dw PSwitchNextLoopCh2 db $FE ; loop PSwitchCh1: - db $DA, $02 ; @2 - db $FD ; #jsr PSwitchInitCh1And2 - dw PSwitchInitCh1And2 + db $DA, $02 ; @2 + db $FD ; #jsr PSwitchInitCh1And2 + dw PSwitchInitCh1And2 PSwitchCh1NoteLen2X1: - db $20, $26, $00, $8C ; y0o2c=16 + db $20, $26, $00, $8C ; y0o2c=16 PSwitchCh1NoteLen4X1: - db $40, $93 ; y0o2g=8^24 + db $40, $93 ; y0o2g=8^24 PSwitchCh1NoteLen3X1: db $30, $98 ; y0o3c=24 db $93 ; y0o2g=24 PSwitchCh1NoteLen2X2: - db $20, $04, $22, $8D ; y2o2c+=16 + db $20, $04, $22, $8D ; y2o2c+=16 PSwitchCh1NoteLen4X2: - db $40, $0A, $1D, $94 ; y5o2g+=8^24 + db $40, $0A, $1D, $94 ; y5o2g+=8^24 PSwitchCh1NoteLen3X2: - db $30, $13, $13, $99 ; y10o3c+=24 + db $30, $13, $13, $99 ; y10o3c+=24 PSwitchCh1NoteLen3X3: - db $30, $1E, $08, $94 ; y16o2g+=24 - db $FD ; #jsr PSwitchNextLoopCh1 + db $30, $1E, $08, $94 ; y16o2g+=24 + db $FD ; #jsr PSwitchNextLoopCh1 dw PSwitchNextLoopCh1 db $FE -PSwitchCh0: - db $DA, $09 ; @9 - db $FD ; #jsr PSwitchInitCh0 - dw PSwitchInitCh0 +PSwitchCh0: + db $DA, $09 ; @9 + db $FD ; #jsr PSwitchInitCh0 + dw PSwitchInitCh0 PSwitchCh0NoteLen: db $10, $0D, $B0 ; o4g=8 db $B0 ; o4g=8 db $B9 ; o5e=8 - db $B9 ; o5e=8 - db $FD ; #jsr PSwitchNextLoopCh0 + db $B9 ; o5e=8 + db $FD ; #jsr PSwitchNextLoopCh0 dw PSwitchNextLoopCh0 - db $FE - -PSwitchInitCh1And2: - ;Set the ADSR of the current channel to match the real one, since - ;there is no SFX instrument that exactly replicates this parameter. - mov a, $46 - lsr a - xcn a - or a, #$06 - mov $f2, a - mov $f3, #$6a - bra PSwitchInit - -PSwitchInitCh0: - mov a, #$00 - mov PSwitchCh0LoopCounter+1, a -PSwitchInit: - ;Don't call this again for subsequent loops. - mov x, $46 - mov a, !ChSFXPtrBackup+x - clrc - adc a, #$05 - mov !ChSFXPtrBackup+x, a - mov a, !ChSFXPtrBackup+1+x - adc a, #$00 - mov !ChSFXPtrBackup+1+x, a - ;Init loop counter - mov a, #$00 - mov PSwitchLoopCounter+1, a - call PSwitchSetNoteLengthCh0 - call PSwitchSetNoteLengthCh1 - call PSwitchSetNoteLengthCh2 - ret - -PSwitchNextLoopCh2: -if !PSwitchSFXCh2ID < 7 - clrc - mov a, $1b - and a, #($ff<<(!PSwitchSFXCh2ID+1))&$ff -- - asl a - bcs PSwitchSetNoteLengthCh2 - bne - -endif - call PSwitchIncLoopCounter - -PSwitchSetNoteLengthCh2: - mov y, PSwitchLoopCounter+1 - mov a, PSwitchNoteLengths+y - push y - mov y, #$0a -- - push a - mov a, PSwitchCh2NoteLenOffsets-1+y - mov x, a - pop a - mov PSwitchCh2NoteLen1+x, a - dbnz y, - - pop y - - asl a - mov PSwitchCh2NoteLen2X1, a - mov PSwitchCh2NoteLen2X2, a - mov PSwitchCh2NoteLen2X3, a - mov PSwitchCh2NoteLen2X4, a - clrc - adc a, PSwitchNoteLengths+y - mov PSwitchCh2NoteLen3X1, a - mov PSwitchCh2NoteLen3X2, a - ret - -PSwitchCh2NoteLenOffsets: - db PSwitchCh2NoteLen1-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen2-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen3-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen4-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen5-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen6-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen7-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen8-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen9-PSwitchCh2NoteLen1 - db PSwitchCh2NoteLen10-PSwitchCh2NoteLen1 - -PSwitchNextLoopCh1: -if !PSwitchSFXCh1ID < 7 - clrc - mov a, $1b - and a, #($ff<<(!PSwitchSFXCh1ID+1))&$ff -- - asl a - bcs PSwitchSetNoteLengthCh1 - bne - -endif - call PSwitchIncLoopCounter - -PSwitchSetNoteLengthCh1: - mov y, PSwitchLoopCounter+1 - mov a, PSwitchNoteLengths+y - asl a - mov PSwitchCh1NoteLen2X1, a - mov PSwitchCh1NoteLen2X2, a - clrc - adc a, PSwitchNoteLengths+y - mov PSwitchCh1NoteLen3X1, a - mov PSwitchCh1NoteLen3X2, a - mov PSwitchCh1NoteLen3X3, a - clrc - adc a, PSwitchNoteLengths+y - mov PSwitchCh1NoteLen4X1, a - mov PSwitchCh1NoteLen4X2, a - ret - -PSwitchNextLoopCh0: -PSwitchCh0LoopCounter: - mov a, #$00 - inc a - mov PSwitchCh0LoopCounter+1, a - cmp a, #$06 - bcc PSwitchSetNoteLengthCh0 - mov a, #$00 - mov PSwitchCh0LoopCounter+1, a - -PSwitchCh0IncMainLoopCounter: -if !PSwitchSFXCh0ID < 7 - clrc - mov a, $1b - and a, #($ff<<(!PSwitchSFXCh0ID+1))&$ff -- - asl a - bcs PSwitchSetNoteLengthCh0 - bne - -endif - call PSwitchIncLoopCounter - -PSwitchSetNoteLengthCh0: - mov y, PSwitchLoopCounter+1 - mov a, PSwitchNoteLengths+y - mov PSwitchCh0NoteLen, a - ret - -PSwitchLoopCounter: -PSwitchIncLoopCounter: - mov a, #$00 - cmp a, #$04 - bcs + - inc PSwitchLoopCounter+1 -+ - ret - -PSwitchNoteLengths: + db $FE + +PSwitchInitCh1And2: + ;Set the ADSR of the current channel to match the real one, since + ;there is no SFX instrument that exactly replicates this parameter. + mov a, $46 + lsr a + xcn a + or a, #$06 + mov $f2, a + mov $f3, #$6a + bra PSwitchInit + +PSwitchInitCh0: + mov a, #$00 + mov PSwitchCh0LoopCounter+1, a +PSwitchInit: + ;Don't call this again for subsequent loops. + mov x, $46 + mov a, !ChSFXPtrBackup+x + clrc + adc a, #$05 + mov !ChSFXPtrBackup+x, a + mov a, !ChSFXPtrBackup+1+x + adc a, #$00 + mov !ChSFXPtrBackup+1+x, a + ;Init loop counter + mov a, #$00 + mov PSwitchLoopCounter+1, a + call PSwitchSetNoteLengthCh0 + call PSwitchSetNoteLengthCh1 + call PSwitchSetNoteLengthCh2 + ret + +PSwitchNextLoopCh2: +if !PSwitchSFXCh2ID < 7 + clrc + mov a, $1b + and a, #($ff<<(!PSwitchSFXCh2ID+1))&$ff +- + asl a + bcs PSwitchSetNoteLengthCh2 + bne - +endif + call PSwitchIncLoopCounter + +PSwitchSetNoteLengthCh2: + mov y, PSwitchLoopCounter+1 + mov a, PSwitchNoteLengths+y + push y + mov y, #$0a +- + push a + mov a, PSwitchCh2NoteLenOffsets-1+y + mov x, a + pop a + mov PSwitchCh2NoteLen1+x, a + dbnz y, - + pop y + + asl a + mov PSwitchCh2NoteLen2X1, a + mov PSwitchCh2NoteLen2X2, a + mov PSwitchCh2NoteLen2X3, a + mov PSwitchCh2NoteLen2X4, a + clrc + adc a, PSwitchNoteLengths+y + mov PSwitchCh2NoteLen3X1, a + mov PSwitchCh2NoteLen3X2, a + ret + +PSwitchCh2NoteLenOffsets: + db PSwitchCh2NoteLen1-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen2-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen3-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen4-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen5-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen6-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen7-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen8-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen9-PSwitchCh2NoteLen1 + db PSwitchCh2NoteLen10-PSwitchCh2NoteLen1 + +PSwitchNextLoopCh1: +if !PSwitchSFXCh1ID < 7 + clrc + mov a, $1b + and a, #($ff<<(!PSwitchSFXCh1ID+1))&$ff +- + asl a + bcs PSwitchSetNoteLengthCh1 + bne - +endif + call PSwitchIncLoopCounter + +PSwitchSetNoteLengthCh1: + mov y, PSwitchLoopCounter+1 + mov a, PSwitchNoteLengths+y + asl a + mov PSwitchCh1NoteLen2X1, a + mov PSwitchCh1NoteLen2X2, a + clrc + adc a, PSwitchNoteLengths+y + mov PSwitchCh1NoteLen3X1, a + mov PSwitchCh1NoteLen3X2, a + mov PSwitchCh1NoteLen3X3, a + clrc + adc a, PSwitchNoteLengths+y + mov PSwitchCh1NoteLen4X1, a + mov PSwitchCh1NoteLen4X2, a + ret + +PSwitchNextLoopCh0: +PSwitchCh0LoopCounter: + mov a, #$00 + inc a + mov PSwitchCh0LoopCounter+1, a + cmp a, #$06 + bcc PSwitchSetNoteLengthCh0 + mov a, #$00 + mov PSwitchCh0LoopCounter+1, a + +PSwitchCh0IncMainLoopCounter: +if !PSwitchSFXCh0ID < 7 + clrc + mov a, $1b + and a, #($ff<<(!PSwitchSFXCh0ID+1))&$ff +- + asl a + bcs PSwitchSetNoteLengthCh0 + bne - +endif + call PSwitchIncLoopCounter + +PSwitchSetNoteLengthCh0: + mov y, PSwitchLoopCounter+1 + mov a, PSwitchNoteLengths+y + mov PSwitchCh0NoteLen, a + ret + +PSwitchLoopCounter: +PSwitchIncLoopCounter: + mov a, #$00 + cmp a, #$04 + bcs + + inc PSwitchLoopCounter+1 ++ + ret + +PSwitchNoteLengths: db $0D, $0D, $0B, $09, $07 -endif - -if !useSFXSequenceFor1DFASFX = !false -CheckAPU1SFXPriority: - mov y, a - ;mov y, #$00 ;Default priority - cmp a, #$01 - bne + - mov y, !JumpSFX1DFAPriority ;Priority for jump SFX - bra .gotPriority -+ - ;cmp a, #$04 - ;bne + - mov y, !GirderSFX1DFAPriority ;Priority for girder SFX - ;bra .gotPriority -+ - -.gotPriority - cmp y, !ChSFXPriority+(!1DFASFXChannel*2) - bcs + - ;Jump to ProcessAPU1SFX (saved in the stack) - ret -+ - - mov !ChSFXPriority+(!1DFASFXChannel*2), y +endif + +if !useSFXSequenceFor1DFASFX = !false +CheckAPU1SFXPriority: + mov y, a + ;mov y, #$00 ;Default priority + cmp a, #$01 + bne + + mov y, !JumpSFX1DFAPriority ;Priority for jump SFX + bra .gotPriority ++ + ;cmp a, #$04 + ;bne + + mov y, !GirderSFX1DFAPriority ;Priority for girder SFX + ;bra .gotPriority ++ + +.gotPriority + cmp y, !ChSFXPriority+(!1DFASFXChannel*2) + bcs + + ;Jump to ProcessAPU1SFX (saved in the stack) + ret ++ + + mov !ChSFXPriority+(!1DFASFXChannel*2), y L_0A14: - mov $05, a ; - pop a ;Don't jump to ProcessAPU1SFX + mov $05, a ; + pop a ;Don't jump to ProcessAPU1SFX pop a ; - ;cmp $05, #$01 - ;bne + - mov a, #$34 -+ - cmp $05, #$04 - bne + - mov a, #$1c -+ + ;cmp $05, #$01 + ;bne + + mov a, #$34 ++ + cmp $05, #$04 + bne + + mov a, #$1c ++ mov $1c, a mov a, #(1<>8&$ff - mov !ChSFXPtrs+1+x, a - mov a, #$03 - mov !ChSFXNoteTimer+x, a -+ - ret - -SFXTerminateVCMD: - db $00 - -if !useSFXSequenceFor1DFASFX = !true -CheckAPU1SFXPriority: + set1 $1d.!1DFASFXChannel ; Turn off channel 7's music +if !PSwitchIsSFX = !true + clr1 $1b.!1DFASFXChannel ; Turn off channel 7's P-Switch allocation +endif + mov x, #(!1DFASFXChannel*2) +endif + +SFXTerminateCh: + mov a, !ChSFXPtrs+1+x + beq + + mov a, #SFXTerminateVCMD&$ff + mov !ChSFXPtrs+x, a + mov a, #SFXTerminateVCMD>>8&$ff + mov !ChSFXPtrs+1+x, a + mov a, #$03 + mov !ChSFXNoteTimer+x, a ++ + ret + +SFXTerminateVCMD: + db $00 + +if !useSFXSequenceFor1DFASFX = !true +CheckAPU1SFXPriority: mov x, #(!1DFASFXChannel*2) mov y, #$01 - mov $10, #(1<>8&$FF - bra .gottenPointerNoPop -.useAPU1GirderSFX - mov a, #APU1GirderClickSFXSequence&$FF - mov y, #APU1GirderClickSFXSequence>>8&$FF - bra .gottenPointerNoPop -endif - ; -.loadFromSFXTable1 ; -if !PSwitchIsSFX = !true - cmp $03, #$81 ; - bcs .PSwitchSFX + bcc .loadFromSFXTable0 ; / +if !useSFXSequenceFor1DFASFX = !true + bne .loadFromSFXTable1 + cmp y, #$04*2 + beq .useAPU1GirderSFX + ;cmp y, #$01*2 + ;beq .useAPU1JumpSFX +.useAPU1JumpSFX + mov a, #APU1JumpSFXSequence&$FF + mov y, #APU1JumpSFXSequence>>8&$FF + bra .gottenPointerNoPop +.useAPU1GirderSFX + mov a, #APU1GirderClickSFXSequence&$FF + mov y, #APU1GirderClickSFXSequence>>8&$FF + bra .gottenPointerNoPop +endif + ; +.loadFromSFXTable1 ; +if !PSwitchIsSFX = !true + cmp $03, #$81 ; + bcs .PSwitchSFX endif mov a, SFXTable1-1+y ; \ push a ; | Move the pointer to the current SFX to the correct pointer. @@ -1682,66 +1686,66 @@ endif mov a, SFXTable0-1+y ; \ push a ; | mov a, SFXTable0-2+y ; / -if !PSwitchIsSFX = !true - bra .gottenPointer - +if !PSwitchIsSFX = !true + bra .gottenPointer + .PSwitchSFX - ;Because the high bit gets shifted out, we don't need to do any more + ;Because the high bit gets shifted out, we don't need to do any more ;modifications to Y. - mov a, PSwitchPtrs-1+y - push a - mov a, PSwitchPtrs-2+y - + mov a, PSwitchPtrs-1+y + push a + mov a, PSwitchPtrs-2+y + endif -.gottenPointer - pop y -.gottenPointerNoPop - movw $14, ya - -;Check SFX priority. - mov y, #$00 - mov a, ($14)+y - cmp a, #$E0 - beq .getSFXPriority - mov a, #$00 - bra .sfxPriorityCheck -.getSFXPriority - incw $14 - mov a, ($14)+y - incw $14 - -.sfxPriorityCheck - pop y - push a - mov a, !ChSFXPtrs+1+x - pop a - beq .checkAPU1SFX - - cmp a, !ChSFXPriority+x - bcs .checkAPU1SFX - -.noSFXOverwrite - pop a - ret - -.checkAPU1SFX -if !useSFXSequenceFor1DFASFX = !false - ;Check and see if APU1 SFX is playing there via detecting $1D. - ;APU1 SFX is playing if APU0/APU3 SFX sequence data is not playing, - ;but $1D has a voice bit set. - push a - mov a, $1d - and a, $10 - pop a - beq .sfxAllocAllowed - - ;Stop all APU1 SFX on the same channel. - mov $05, #$00 - mov $1c, #$00 -endif - -.sfxAllocAllowed - mov !ChSFXPriority+x, a +.gottenPointer + pop y +.gottenPointerNoPop + movw $14, ya + +;Check SFX priority. + mov y, #$00 + mov a, ($14)+y + cmp a, #$E0 + beq .getSFXPriority + mov a, #$00 + bra .sfxPriorityCheck +.getSFXPriority + incw $14 + mov a, ($14)+y + incw $14 + +.sfxPriorityCheck + pop y + push a + mov a, !ChSFXPtrs+1+x + pop a + beq .checkAPU1SFX + + cmp a, !ChSFXPriority+x + bcs .checkAPU1SFX + +.noSFXOverwrite + pop a + ret + +.checkAPU1SFX +if !useSFXSequenceFor1DFASFX = !false + ;Check and see if APU1 SFX is playing there via detecting $1D. + ;APU1 SFX is playing if APU0/APU3 SFX sequence data is not playing, + ;but $1D has a voice bit set. + push a + mov a, $1d + and a, $10 + pop a + beq .sfxAllocAllowed + + ;Stop all APU1 SFX on the same channel. + mov $05, #$00 + mov $1c, #$00 +endif + +.sfxAllocAllowed + mov !ChSFXPriority+x, a pop a mov $0004+y, a ; > Tell the SPC to process this SFX. ;mov a, #$01 ; \ We need to wait 2 ticks before processing SFX. @@ -1749,13 +1753,13 @@ endif mov a, $10 ; \ call KeyOffVoices or ($1d), ($10) ; -if !PSwitchIsSFX = !true - cmp $03, #$81 ; - or ($1b), ($10) - bcs .PSwitchSFXChSet - eor ($1b), ($10) -.PSwitchSFXChSet -endif +if !PSwitchIsSFX = !true + cmp $03, #$81 ; + or ($1b), ($10) + bcs .PSwitchSFXChSet + eor ($1b), ($10) +.PSwitchSFXChSet +endif mov a, $15 mov !ChSFXPtrs+1+x, a ; Store to current pointer @@ -1766,7 +1770,7 @@ endif ; call EffectModifier mov a, #$00 ; \ - mov $90+x, a ; | + mov $90+x, a ; | mov $91+x, a ; / .return ; ;ret ; @@ -1779,86 +1783,86 @@ endif ; mov a, #$02 - mov !ChSFXNoteTimer+x, a ; Prevent an edge case. + mov !ChSFXNoteTimer+x, a ; Prevent an edge case. endif ret } -; - -if !noSFX = !false -APU1CMDJumpArray: - dw CheckAPU1SFXPriority ;01 - dw EnableYoshiDrums ;02 - dw DisableYoshiDrums ;03 - dw CheckAPU1SFXPriority ;04 - dw ForceSFXEchoOff ;05 - dw ForceSFXEchoOn ;06 - dw PlayPauseSFX ;07 - dw PlayUnpauseSFX ;08 - dw PlayUnpauseSilentSFX ;09 -APU1CMDJumpArrayEOF: +; + +if !noSFX = !false +APU1CMDJumpArray: + dw CheckAPU1SFXPriority ;01 + dw EnableYoshiDrums ;02 + dw DisableYoshiDrums ;03 + dw CheckAPU1SFXPriority ;04 + dw ForceSFXEchoOff ;05 + dw ForceSFXEchoOn ;06 + dw PlayPauseSFX ;07 + dw PlayUnpauseSFX ;08 + dw PlayUnpauseSilentSFX ;09 +APU1CMDJumpArrayEOF: endif HandleYoshiDrums: ; Subroutine. Call it any time anything Yoshi-drum related happens. - mov $5e, #$00 + mov $5e, #$00 mov a, $6e .drumSet - tset $5e, a - - ;If you are using any extra code that also sets the mute flag, send - ;all of them over to HandleYoshiDrums_externalChMuteFlags+1 (and - ;uncomment the two lines below) so that they get preserved - ;accordingly. The +1 is important, since it's embedded in code (and - ;labels can't go in the middle of opcodes unless I were to input raw - ;hex opcodes instead of letting the assembler do its job). -HandleYoshiDrums_externalChMuteFlags: - ;mov a, #$00 - ;tset $5e, a - + tset $5e, a + + ;If you are using any extra code that also sets the mute flag, send + ;all of them over to HandleYoshiDrums_externalChMuteFlags+1 (and + ;uncomment the two lines below) so that they get preserved + ;accordingly. The +1 is important, since it's embedded in code (and + ;labels can't go in the middle of opcodes unless I were to input raw + ;hex opcodes instead of letting the assembler do its job). +HandleYoshiDrums_externalChMuteFlags: + ;mov a, #$00 + ;tset $5e, a + mov a, $5e - jmp KeyOffVoices - -UnpauseMusic: + jmp KeyOffVoices + +UnpauseMusic: mov a, #$00 - mov !PauseMusic, a -.unsetMute: + mov !PauseMusic, a +.unsetMute: mov a, !SpeedUpBackUp ;\ - mov $0387, a ;/ Restore the tempo. - - clr1 !NCKValue.6 ; Unset the mute flag. - jmp SetFLGFromNCKValue - -.silent: + mov $0387, a ;/ Restore the tempo. + + clr1 !NCKValue.6 ; Unset the mute flag. + jmp SetFLGFromNCKValue + +.silent: mov a, #$01 ;\ Set pause flag to solve issue when doing start+select quickly - mov !PauseMusic, a ;/ - + mov !PauseMusic, a ;/ + mov $f2, #$5c ; \ Key off voices - mov $f3, #$ff ; / (so the music doesn't restart playing when using start+select) - - dec a - mov $f2, #$2c ;\ - mov $f3, a ;| Mute echo. - set1 $f2.4 ;| - mov $f3, a ;/ - bra .unsetMute - -;The cases here are different: carry is implied cleared if jump array is -;used, and carry is implied set if a standard branch is used. -if !noSFX = !false -EnableYoshiDrums: ; Enable Yoshi drums. - setc -DisableYoshiDrums: ; And disable them. -else -DisableYoshiDrums: ; And disable them. - clrc -EnableYoshiDrums: ; Enable Yoshi drums. -endif - ;Toggle between TSET/TCLR using the carry to toggle between opcodes. - mov1 HandleYoshiDrums_drumSet&$1FFF.6, c - bra HandleYoshiDrums + mov $f3, #$ff ; / (so the music doesn't restart playing when using start+select) + + dec a + mov $f2, #$2c ;\ + mov $f3, a ;| Mute echo. + set1 $f2.4 ;| + mov $f3, a ;/ + bra .unsetMute + +;The cases here are different: carry is implied cleared if jump array is +;used, and carry is implied set if a standard branch is used. +if !noSFX = !false +EnableYoshiDrums: ; Enable Yoshi drums. + setc +DisableYoshiDrums: ; And disable them. +else +DisableYoshiDrums: ; And disable them. + clrc +EnableYoshiDrums: ; Enable Yoshi drums. +endif + ;Toggle between TSET/TCLR using the carry to toggle between opcodes. + mov1 HandleYoshiDrums_drumSet&$1FFF.6, c + bra HandleYoshiDrums L_099C: mov a, #$6c ; Mute, disable echo. We don't want any rogue sounds during upload @@ -1869,134 +1873,148 @@ L_099C: mov a, #$ff call KeyOffVoices - inc a + inc a call SetEDLDSP ; Also set the delay to 0. mov $02, a ; mov $06, a ; Reset the song number - mov $0A, a ; + mov $0A, a ; if !noSFX = !false - mov $1d, a + mov $1d, a endif - mov !MaxEchoDelay, a ; - mov a, #!reserveBufferZeroEDLGateDistance + mov !MaxEchoDelay, a ; + mov a, #!reserveBufferZeroEDLGateDistance mov SubC_table2_reserveBuffer_zeroEDLGate+1, a call EffectModifier jmp L_12F2 ; do standardish SPC transfer ;ERROR ; Note that after this, the program is "reset"; it jumps to wherever the 5A22 tells it to. ; The stack is also cleared. - ;ret + ;ret ProcessAPU1Input: ; Input from SMW $1DFA - mov a, $01 -if !noSFX = !false -if !useSFXSequenceFor1DFASFX = !false - beq ProcessAPU1SFX -else - bne .hasCommand -.terminate: - ret -.hasCommand: -endif + mov a, $01 +if !noSFX = !false +if !useSFXSequenceFor1DFASFX = !false + beq ProcessAPU1SFX +else + bne .hasCommand +.terminate: + ret +.hasCommand: +endif endif cmp a, #$ff - beq L_099C -if !noSFX = !true - cmp a, #$08 ; 08 unpauses music - beq UnpauseMusic - cmp a, #$07 ; 07 pauses music - beq PauseMusic - cmp a, #$09 ; KevinM's edit: + beq L_099C + cmp a, #$ +if !noSFX = !true + cmp a, #$08 ; 08 unpauses music + beq UnpauseMusic + cmp a, #$07 ; 07 pauses music + beq PauseMusic + cmp a, #$09 ; KevinM's edit: beq UnpauseMusic_silent ; 09 unpauses music, but with the silent sfx cmp a, #$02 ; 02 = turn on Yoshi drums beq EnableYoshiDrums ; cmp a, #$03 ; 03 = turn off Yoshi drums - beq DisableYoshiDrums ; -endif -if !noSFX = !false - cmp a, #((APU1CMDJumpArrayEOF-APU1CMDJumpArray)/2)+1 -if !useSFXSequenceFor1DFASFX = !false - bcs ProcessAPU1SFX - mov y, #ProcessAPU1SFX>>8&$ff - push y - mov y, #ProcessAPU1SFX&$ff - push y -else - bcs .terminate -endif - asl a - mov x, a - lsr a - jmp (APU1CMDJumpArray-2+x) + beq DisableYoshiDrums ; +endif + push a + cmp a, #$80 + bpl SkipConditional + setc + sbc a, #$80 + mov x, a + mov a, (ConditionalTable+x) + and !Flag, a +SkipConditional: + pop a +if !noSFX = !false + cmp a, #((APU1CMDJumpArrayEOF-APU1CMDJumpArray)/2)+1 +if !useSFXSequenceFor1DFASFX = !false + bcs ProcessAPU1SFX + mov y, #ProcessAPU1SFX>>8&$ff + push y + mov y, #ProcessAPU1SFX&$ff + push y +else + bcs .terminate +endif + asl a + mov x, a + lsr a + jmp (APU1CMDJumpArray-2+x) + +ConditionalTable: +db #$01,#$02,#$04,#$08,#$10,#$20,#$40,#$80 PlayPauseSFX: mov a, #$11 - mov $00, a + mov $00, a - - mov !ProtectSFX6, a - ret - -PlayUnpauseSilentSFX: - mov a, #$2C + mov !ProtectSFX6, a + ret + +PlayUnpauseSilentSFX: + mov a, #$2C bra + PlayUnpauseSFX: mov a, #$12 -+ ++ mov $00, a - mov a, #$00 + mov a, #$00 ;mov $08, #$00 - bra - -else - ret -endif - -PauseMusic: + bra - +else + ret +endif + +PauseMusic: mov a, $0387 ;\ - mov !SpeedUpBackUp, a ;| Set the tempo increase to 0 and save it. + mov !SpeedUpBackUp, a ;| Set the tempo increase to 0 and save it. mov a, #$00 ;| mov $0387, a ;/ - + inc a - mov !PauseMusic, a - - set1 !NCKValue.6 ; Set the mute flag. - ;ModifyNoise, called when restoring the noise frequency, will handle - ;setting the FLG DSP register. + mov !PauseMusic, a + + set1 !NCKValue.6 ; Set the mute flag. + ;ModifyNoise, called when restoring the noise frequency, will handle + ;setting the FLG DSP register. ret - -if !noSFX = !false && !useSFXSequenceFor1DFASFX = !false + +if !noSFX = !false && !useSFXSequenceFor1DFASFX = !false ; ProcessAPU1SFX: mov a, $05 ; cmp a, #$04 ; \ If the currently playing SFX is the girder SFX - beq L_0B08 ; / Then process that. + beq L_0B08 ; / Then process that. cmp a, #$01 ; Else, if it's the jump SFX, then do that stuff. - bne L_0AB0 - + bne L_0AB0 + ; $01 = 01 -L_0A51: ;;;;;;;;/ Code change - mov $48, #$00 ; Let NoteVCMD know that this is SFX code. - +L_0A51: ;;;;;;;;/ Code change + mov $48, #$00 ; Let NoteVCMD know that this is SFX code. + L_0A56: - dbnz $1c, L_0A38 + dbnz $1c, L_0A38 RestoreInstrumentFromAPU1SFX: - clr1 $1d.!1DFASFXChannel - mov a, #$00 - mov $05, a + clr1 $1d.!1DFASFXChannel + mov a, #$00 + mov $05, a mov !ChSFXPriority+(!1DFASFXChannel*2), a - mov x, #(!1DFASFXChannel*2) - jmp RestoreInstrumentInformation - -L_0A38: - cmp $1c, #$30 ; Process the jump SFX. - beq L_0A68 - bcs L_0AB0 -; Beyond this point is essentially the hard-coded way to key on a note and -; manually set the pitch bend parameters, with the timer deciding what + mov x, #(!1DFASFXChannel*2) + jmp RestoreInstrumentInformation + +L_0A38: + cmp $1c, #$30 ; Process the jump SFX. + beq L_0A68 + bcs L_0AB0 +; Beyond this point is essentially the hard-coded way to key on a note and +; manually set the pitch bend parameters, with the timer deciding what ; executes when. cmp $1c, #$2a bne L_0A99 - mov x, #(!1DFASFXChannel*2) + mov x, #(!1DFASFXChannel*2) mov $46, x mov y, #$00 mov $91+x, y @@ -2004,10 +2022,10 @@ L_0A38: mov $90+x, y mov a, #$b9 call CalcPortamentoDelta - bra L_0A99 + bra L_0A99 -L_0A68: - mov $46, #(!1DFASFXChannel*2) +L_0A68: + mov $46, #(!1DFASFXChannel*2) mov a, #$08 call SetSFXInstrument mov a, #$b2 @@ -2018,11 +2036,11 @@ L_0A68: mov $90+x, y mov a, #$b5 call CalcPortamentoDelta - mov y, #$38 + mov y, #$38 call Quick1DFAMonoVolDSPWritesWKON L_0A99: call SFX1DFAKOFFCheck -L_0AA5: +L_0AA5: mov x, #(!1DFASFXChannel*2) mov a, $90+x beq L_0AB0 @@ -2032,44 +2050,44 @@ L_0AB0: ret ; $01 = 04 && $05 != 01 -L_0B08: +L_0B08: mov $48, #$00 ; Let NoteVCMD know that this is SFX code. dbnz $1c, L_0AF2 - bra RestoreInstrumentFromAPU1SFX - -L_0AF2: - cmp $1c, #$18 ; Process the girder SFX. - beq L_0AF7 - bcs L_0AB0 -; Beyond this point is essentially the hard-coded way to key on a couple of + bra RestoreInstrumentFromAPU1SFX + +L_0AF2: + cmp $1c, #$18 ; Process the girder SFX. + beq L_0AF7 + bcs L_0AB0 +; Beyond this point is essentially the hard-coded way to key on a couple of ; notes, with the timer deciding what executes when. cmp $1c, #$0c bne L_0B33 -L_0AF7: +L_0AF7: mov $46, #(!1DFASFXChannel*2) mov a, #$07 call SetSFXInstrument mov a, #$a4 - call NoteVCMD + call NoteVCMD L_0B1C: - mov y, #$28 + mov y, #$28 call Quick1DFAMonoVolDSPWritesWKON -L_0B33: -SFX1DFAKOFFCheck: +L_0B33: +SFX1DFAKOFFCheck: mov a, #$02 cbne $1c, L_0AB0 mov a, #(1<>8 -.setupJumpToIndirectFromIndex: - or ($14), ($46) - bra .jumpToIndirect - -.subroutine: - set1 $11.7 ;Subroutine has been entered. - incw $14 - mov a, ($14)+y - push a - incw $14 - mov a, ($14)+y - push a - incw $14 - mov a, ($14)+y - dec a - beq .subroutineNoLoop - set1 $11.6 ;Subroutine loop is active. -.subroutineNoLoop: - incw $14 - ;Save return point for subroutine. - movw ya, $14 - movw $12, ya - ;Jump inside subroutine. - pop y - pop a - movw $14, ya -.jmpToL_10B2_2: - bra .jmpToL_10B2_1 - -.L_10D1: + ret + +.subroutineNoPreviousEntry: + bbs3 $11, .L_10D1 + mov a, $c0+x + beq .L_10D1 + dec a + mov1 $11.3, c + beq .subroutineExit ;Branch if this was the last subroutine loop. + bcc .subroutineExit ;Branch if subroutine was not exited... + clr1 $11.6 ;Subroutine loop is no longer active. + mov $14, #$03f1&$FF ;Restart subroutine just this once. + bra .setupJumpToIndirect03 ;We limit loops to one iteration to prevent excessive readahead iterations. + +.loopSection: + incw $14 + mov a, ($14)+y + bne .loopSectionNonZero + ;Save return point for loop. + set1 $11.5 ;Loop section was entered. + incw $14 + movw ya, $14 + movw $16, ya + bra .jmpToL_10B2_1 + +.subroutineExit: + mov $14, #$03e1&$FF +.setupJumpToIndirect03: + mov $15, #$03e1>>8 +.setupJumpToIndirectFromIndex: + or ($14), ($46) + bra .jumpToIndirect + +.subroutine: + set1 $11.7 ;Subroutine has been entered. + incw $14 + mov a, ($14)+y + push a + incw $14 + mov a, ($14)+y + push a + incw $14 + mov a, ($14)+y + dec a + beq .subroutineNoLoop + set1 $11.6 ;Subroutine loop is active. +.subroutineNoLoop: + incw $14 + ;Save return point for subroutine. + movw ya, $14 + movw $12, ya + ;Jump inside subroutine. + pop y + pop a + movw $14, ya +.jmpToL_10B2_2: + bra .jmpToL_10B2_1 + +.L_10D1: mov $10, a - clrc + clrc call TerminateOnLegatoEnable ; Key off the current voice (with conditions). mov a, !InRest+x bne .keyoff call CheckForRemoteCodeType6 - beq .keyoffRemoteCodeCheck + beq .keyoffRemoteCodeCheck mov a, !remoteCodeType+x cmp a, #$03 - bne .keyoff - + bne .keyoff + .keyoffRemoteCodeCheck cmp $10, #$c7 beq .keyoffRemoteCodeTypeCheck mov a, $70+x - cbne !WaitTime, .keyoffRemoteCodeTypeCheck + cbne !WaitTime, .keyoffRemoteCodeTypeCheck .keyoff: setc - ret + ret -.keyoffRemoteCodeTypeCheck +.keyoffRemoteCodeTypeCheck call CheckForRemoteCodeType6 beq .skipKeyOffAndRunCode2 .skipKeyOffAndRunCode: call RunRemoteCode -;.skip_keyoff duplicate stored here since it's cheaper memory-wise +;.skip_keyoff duplicate stored here since it's cheaper memory-wise ;(and the distance is too great to go backwards) clrc - ret - -.skipKeyOffAndRunCode2: - call RunRemoteCode2 + ret + +.skipKeyOffAndRunCode2: + call RunRemoteCode2 clrc - ret - -.loopSectionNonZero: - bbs4 $11, .loopSectionClearAndPassThrough ;Branch if loop section is active. - set1 $11.4 ;Loop section is now active. - bbs5 $11, .loopSectionJumpFromScratchRAM ;Branch if loop section was entered via readahead. - mov a, $01f0+x - dec a - ;$01 means that the loop section has been entered and terminated. - beq .loopSectionPassThrough - mov $14, #$01e1&$FF ;Grab pre-existing return address and jump. -.setupJumpToIndirect01: - mov $15, #$01e1>>8 - bra .setupJumpToIndirectFromIndex - -.loopSectionJumpFromScratchRAM: - movw ya, $16 - movw $14, ya - bra .jmpToL_10B2_2 - -.loopSectionClearAndPassThrough: - clr1 $11.4 ;Loop section is no longer active. -.loopSectionPassThrough: - incw $14 + ret + +.loopSectionNonZero: + bbs4 $11, .loopSectionClearAndPassThrough ;Branch if loop section is active. + set1 $11.4 ;Loop section is now active. + bbs5 $11, .loopSectionJumpFromScratchRAM ;Branch if loop section was entered via readahead. + mov a, $01f0+x + dec a + ;$01 means that the loop section has been entered and terminated. + beq .loopSectionPassThrough + mov $14, #$01e1&$FF ;Grab pre-existing return address and jump. +.setupJumpToIndirect01: + mov $15, #$01e1>>8 + bra .setupJumpToIndirectFromIndex + +.loopSectionJumpFromScratchRAM: + movw ya, $16 + movw $14, ya + bra .jmpToL_10B2_2 + +.loopSectionClearAndPassThrough: + clr1 $11.4 ;Loop section is no longer active. +.loopSectionPassThrough: + incw $14 bra .jmpToL_10B2_2 -} - -TerminateOnLegatoEnable: +} + +TerminateOnLegatoEnable: mov a, $48 and a,$0161 and a,$0162 - beq + - ;WARNING: Won't work if anything else is in the stack! - pop a ;Jump forward one pointer in the stack in order to - pop a ;terminate the entire preceding routine. -+ + beq + + ;WARNING: Won't work if anything else is in the stack! + pop a ;Jump forward one pointer in the stack in order to + pop a ;terminate the entire preceding routine. ++ ret L_10A1: @@ -3204,19 +3222,19 @@ L_10A1: beq .doKeyOffCheck ;L_10AC ; mov a, !remoteCodeType+x ; \ Branch away if we have no code to run before a note ends. - cmp a, #$02 ; | - beq .checkRemoteCodeTimeValue + cmp a, #$02 ; | + beq .checkRemoteCodeTimeValue cmp a, #$05 bne .noRemoteCode ; / - + .checkRemoteCodeTimeValue setp mov.b a, !remoteCodeTimeValue&$ff+x ; \ - cmp a, (X) ;$0100&$ff+x ; | Also branch if we're not ready to run said code yet. + cmp a, (X) ;$0100&$ff+x ; | Also branch if we're not ready to run said code yet. clrp ; | bne .noRemoteCode ; / - call ShouldSkipKeyOff ; \ If we're going to skip the keyoff, then also don't run the code. + call ShouldSkipKeyOff ; \ If we're going to skip the keyoff, then also don't run the code. mov1 HandleArpeggio_nextNoteCheck.5, c ; | Switch between a BEQ/BNE opcode depending on the output. bcc .noRemoteCode ; / @@ -3233,22 +3251,22 @@ L_10A1: + clr1 $13.7 ; - mov a, $90+x ; + mov a, $90+x ; if !noSFX = !false beq L_10E4 ; mov a, $48 ; and a, $1d ; - beq L_1111 ; -else - bne L_1111 + beq L_1111 ; +else + bne L_1111 endif L_10E4: mov a, ($30+x) ; Code for handling the $DD command. cmp a, #$dd ; I don't know why this is here instead of in its dispatch table. - beq + ; Maybe so that it can properly do the "read-ahead" effect? - call L_112A - bra L_1133 -+ + beq + ; Maybe so that it can properly do the "read-ahead" effect? + call L_112A + bra L_1133 ++ if !noSFX = !false mov a, $48 ; \ and a, $1d ; | Check to see if the current channel is disabled with a sound effect. @@ -3257,7 +3275,7 @@ if !noSFX = !false L_10F3: call L_1260 dbnz $10, L_10F3 - bra L_1111 + bra L_1111 endif L_10FB: call L_1260 ; \ @@ -3267,20 +3285,20 @@ L_10FB: mov $90+x, a ; | call GetCommandDataFast ; / clrc - adc a, $43 -cmdDDAddHTuneValuesGate: - bra cmdDDAddHTuneValuesSkip + adc a, $43 +cmdDDAddHTuneValuesGate: + bra cmdDDAddHTuneValuesSkip clrc - adc a, !HTuneValues+x + adc a, !HTuneValues+x cmdDDAddHTuneValuesSkip: call CalcPortamentoDelta L_1111: - call L_09CDWPreCheck + call L_09CDWPreCheck L_1133: mov a, $a1+x beq L_1140 mov a, $0340+x - cbne $a0+x, L_113E + cbne $a0+x, L_113E L_1144: ; Process vibrato. @@ -3339,16 +3357,16 @@ L_1191: addw ya, $10 ;Add vibrato offset to resulting pitch. movw $10, ya L_1195: - jmp SetPitch - + jmp SetPitch + L_113E: inc $a0+x L_1140: bbs1 $13.7, L_1195 ; If $13.7 is set, recalibrate the pitch. + - ret + ret -; per-voice fades/dsps? +; per-voice fades/dsps? HandleVoice: clr1 $13.7 @@ -3578,7 +3596,7 @@ Start: clrp ; ;mov $0387, a - mov !PauseMusic, a + mov !PauseMusic, a if !noSFX = !false mov $0389, a endif @@ -3597,30 +3615,30 @@ endif mov a, #$00 - mov !ChSFXPtrs-1+y, a ; \ Turn off sound effects - dbnz y, - ; / -if !PSwitchIsSFX = !true + dbnz y, - ; / +if !PSwitchIsSFX = !true mov $1b, #$00 -endif +endif JumpToUploadLocation: jmp ($0014+x) ; Jump to address incsrc "InstrumentData.asm" -if !noSFX = !false -if !useSFXSequenceFor1DFASFX = !true -APU1JumpSFXSequence: - db $E0 - db !JumpSFX1DFAPriority - db $DA,$08,$05,$38,$DD,$B2,$00,$05,$B5,$2A,$EB,$01,$12,$B9,$00 -APU1GirderClickSFXSequence: - db $E0 - db !GirderSFX1DFAPriority - db $DA,$07,$0C,$28,$A4,$A4,$00 -endif +if !noSFX = !false +if !useSFXSequenceFor1DFASFX = !true +APU1JumpSFXSequence: + db $E0 + db !JumpSFX1DFAPriority + db $DA,$08,$05,$38,$DD,$B2,$00,$05,$B5,$2A,$EB,$01,$12,$B9,$00 +APU1GirderClickSFXSequence: + db $E0 + db !GirderSFX1DFAPriority + db $DA,$07,$0C,$28,$A4,$A4,$00 +endif SFXTable0: - SFXTable1: + SFXTable1: endif SongPointers: From a0c62765eb5a0461b7337d52946f8de531507350 Mon Sep 17 00:00:00 2001 From: Torchkas Date: Mon, 27 Feb 2023 18:57:36 +0100 Subject: [PATCH 3/4] typo --- asm/Commands.asm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/asm/Commands.asm b/asm/Commands.asm index 52323334..d040ff6a 100755 --- a/asm/Commands.asm +++ b/asm/Commands.asm @@ -416,6 +416,7 @@ cmdE9: ; Loop mov $30+x, a mov $03f0+x, a ; set vptr/3F0/1+X to op1/2 ret + ConditionTable: dw Condition0 dw Condition1 @@ -425,11 +426,12 @@ ConditionTable: dw Condition5 dw Condition6 dw Condition7 + ConditionalLoops: ;conditional loops are actually infinite loops that break their loop when a flag is set. asl a push x mov x, a - jmp (Conditiontable+x) + jmp (ConditionTable+x) Condition0: mov a, !Flag From 72799a5e8fcbeafff14e98de049231d620d251f9 Mon Sep 17 00:00:00 2001 From: Torchkas Date: Tue, 28 Feb 2023 11:04:15 +0100 Subject: [PATCH 4/4] test song --- music/conditioloop.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 music/conditioloop.txt diff --git a/music/conditioloop.txt b/music/conditioloop.txt new file mode 100644 index 00000000..bfad119e --- /dev/null +++ b/music/conditioloop.txt @@ -0,0 +1,2 @@ +#0 w255 t48 +[c8e16d8f16e8g16f8a16g4]150 \ No newline at end of file