SHARE
TWEET

Chrono Trigger MSU-1 Overhaul

a guest Aug 25th, 2019 268 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Copyright (c) 2016, DarkShock
  2. // Copyright (c) 2019, Cthulhu
  3. //
  4. // Redistribution and use in source and binary forms,
  5. // with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // 1. Redistributions of source code must retain the above copyright notice,
  9. //    this list of conditions and the following disclaimer.
  10. //
  11. // 2. Redistributions in binary form must reproduce the above copyright notice,
  12. //    this list of conditions and the following disclaimer in the documentation
  13. //    and/or other materials provided with the distribution.
  14. //
  15. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  17. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  18. // FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  20. // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. // (INCLUDING, BUT NOT LIMITED TO,
  22. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. // LOSS OF USE, DATA, OR PROFITS;
  24. // OR BUSINESS INTERRUPTION)
  25. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  26. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  28. // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  
  30. arch snes.cpu
  31.  
  32. // Boolean constants
  33. constant false(0)
  34. constant true(1)
  35.  
  36. scope SNES {
  37.     scope MUL {
  38.         // SNES multiplication registers.
  39.         constant OPERAND_A($4202)
  40.         constant OPERAND_B($4203)
  41.         constant RESULT_L($4216)
  42.         constant RESULT_H($4217)
  43.     }
  44.  
  45.     scope DIV {
  46.         // SNES division registers.
  47.         constant DIVIDEND_L($4204)
  48.         constant DIVIDEND_H($4205)
  49.         constant DIVISOR($4206)
  50.         constant QUOTIENT_L($4214)
  51.         constant QUOTIENT_H($4215)
  52.         constant REMAINDER_L($4216)
  53.         constant REMAINDER_H($4217)
  54.     }
  55.  
  56.     scope SPC {
  57.         // SPC communication ports.
  58.         constant COMM0($2140)
  59.         constant COMM1($2141)
  60.         constant COMM2($2142)
  61.         constant COMM3($2143)
  62.     }
  63.  
  64.     macro mul() {
  65.         // x * y = a
  66.  
  67.         stx.w SNES.MUL.OPERAND_A
  68.         sty.w SNES.MUL.OPERAND_B
  69.  
  70.         rep #$20
  71.         xba // Ignored, just here to waste 3 cycles for the multiplication.
  72.         nop
  73.  
  74.         lda.w SNES.MUL.RESULT_L
  75.         sep #$20
  76.     }
  77.  
  78.     macro div() {
  79.         // x / y = a
  80.  
  81.         rep #$10
  82.         stx.w SNES.DIV.DIVIDEND_L
  83.         sep #$10
  84.  
  85.         sty.w SNES.DIV.DIVISOR
  86.  
  87.         rep #$20
  88.         xba // Ignored, just here to waste 3 cycles for the division.
  89.         nop
  90.         nop
  91.         nop
  92.         nop
  93.         nop
  94.  
  95.         lda.w SNES.DIV.QUOTIENT_L
  96.         sep #$20
  97.     }
  98. }
  99.  
  100. scope MSU {
  101.     // MSU memory map I/O.
  102.  
  103.     scope Output {
  104.         constant STATUS($2000)
  105.         constant READ($2001)
  106.         constant ID($2002)
  107.     }
  108.  
  109.     scope Input {
  110.         constant SEEK($2000)
  111.         constant TRACK_LO($2004)
  112.         constant TRACK_HI($2005)
  113.         constant VOLUME($2006)
  114.         constant CONTROL($2007)
  115.     }
  116.  
  117.     scope Flags {
  118.         scope STATUS {
  119.             constant TRACK_MISSING($08)
  120.             constant AUDIO_PLAYING($10)
  121.             constant AUDIO_REPEAT($20)
  122.             constant AUDIO_BUSY($40)
  123.             constant DATA_BUSY($80)
  124.         }
  125.  
  126.         scope CONTROL {
  127.             constant AUDIO_STOP($00)
  128.             constant AUDIO_PLAY($01)
  129.             constant AUDIO_REPEAT($02)
  130.         }
  131.     }
  132.  
  133.     scope Values {
  134.         scope VOLUME {
  135.             constant EMPTY($00)
  136.             constant FULL($FF)
  137.         }
  138.     }
  139. }
  140.  
  141. scope Utility {
  142.     scope Memory {
  143.         constant BANK($7E0000)
  144.         constant OFFSET($1E00)
  145.  
  146.         macro load(variable offset) {
  147.             lda.l Utility.Memory.BANK | Utility.Memory.OFFSET | offset
  148.         }
  149.  
  150.         macro store(variable offset) {
  151.             sta.l Utility.Memory.BANK | Utility.Memory.OFFSET | offset
  152.         }
  153.     }
  154.  
  155.     scope Register {
  156.         constant P($01)
  157.         constant A($02)
  158.         constant X($04)
  159.         constant Y($08)
  160.         constant D($10)
  161.         constant B($20)
  162.         constant ALL(P|A|X|Y|D|B)
  163.  
  164.         macro scope backup(variable flag) {
  165.             // Registers backup.
  166.             if Utility.Register.P & flag {
  167.                 php
  168.             }
  169.  
  170.             variable pflag($00)
  171.  
  172.             if Utility.Register.A & flag {
  173.                 pflag = pflag | $20
  174.             }
  175.             if Utility.Register.X & flag || Utility.Register.Y & flag {
  176.                 pflag = pflag | $10
  177.             }
  178.             if pflag {
  179.                 rep #pflag
  180.             }
  181.  
  182.             if Utility.Register.A & flag {
  183.                 pha
  184.             }
  185.             if Utility.Register.X & flag {
  186.                 phx
  187.             }
  188.             if Utility.Register.Y & flag {
  189.                 phy
  190.             }
  191.             if Utility.Register.D & flag {
  192.                 phd
  193.                 Utility.direct(Utility.Memory.OFFSET)
  194.             }
  195.             if Utility.Register.B & flag {
  196.                 phb
  197.             }
  198.  
  199.             if pflag {
  200.                 sep #pflag
  201.             }
  202.  
  203.             if Utility.Register.B & flag {
  204.                 Utility.absolute($80)
  205.             }
  206.         }
  207.  
  208.         macro scope restore(variable flag) {
  209.             // Registers restore.
  210.             variable pflag($00)
  211.  
  212.             if Utility.Register.A & flag {
  213.                 pflag = pflag | $20
  214.             }
  215.             if Utility.Register.X & flag || Utility.Register.Y & flag {
  216.                 pflag = pflag | $10
  217.             }
  218.             if pflag {
  219.                 rep #pflag
  220.             }
  221.  
  222.             if Utility.Register.B & flag {
  223.                 plb
  224.             }
  225.             if Utility.Register.D & flag {
  226.                 pld
  227.             }
  228.             if Utility.Register.Y & flag {
  229.                 ply
  230.             }
  231.             if Utility.Register.X & flag {
  232.                 plx
  233.             }
  234.             if Utility.Register.A & flag {
  235.                 pla
  236.             }
  237.             if Utility.Register.P & flag {
  238.                 plp
  239.             }
  240.         }
  241.     }
  242.  
  243.     macro direct(variable offset) {
  244.         // Set the direct page register to offset.
  245.         lda.w #offset
  246.         tcd
  247.     }
  248.  
  249.     macro absolute(variable bank) {
  250.         // Set the data bank register to bank.
  251.         lda.b #bank
  252.         pha
  253.         plb
  254.     }
  255.  
  256.     macro ascii(variable char) {
  257.         // Compare an ascii character.
  258.         lda.w source+index
  259.         cmp.b #char
  260.         bne fallback
  261.  
  262.         index = index + 1
  263.     }
  264. }
  265.  
  266. scope Game {
  267.     scope SOUND {
  268.         // Variable addresses
  269.         constant COMMAND($00)
  270.         constant REQUEST($01)
  271.         constant FADE_TIME($01)
  272.         constant FADE_VOLUME($02)
  273.         constant BANK_REQUEST($10)
  274.  
  275.         // Constants
  276.         scope COMMANDS {
  277.             // Constants
  278.             constant PLAY($10)
  279.             constant RESUME($11)
  280.             constant INTERRUPT($14)
  281.             constant FADE($81)
  282.             constant PAUSE($F5)
  283.         }
  284.     }
  285. }
  286.  
  287. scope Track {
  288.     // Track list
  289.     constant LIST($CDF9C8)
  290.     constant SIZE(256)
  291.  
  292.     scope ACTIONS {
  293.         constant NONE($FF)
  294.         constant STOP(MSU.Flags.CONTROL.AUDIO_STOP)
  295.         constant PLAY(MSU.Flags.CONTROL.AUDIO_PLAY)
  296.         constant LOOP(MSU.Flags.CONTROL.AUDIO_PLAY|MSU.Flags.CONTROL.AUDIO_REPEAT)
  297.     }
  298.  
  299.     scope TRACKS {
  300.         constant THEME($18)
  301.         constant THEME_ATTRACT($54)
  302.         constant EPOCH_1999AD($50)
  303.         constant ENDING($3F)
  304.     }
  305. }
  306.  
  307. scope Patch {
  308.     scope Flags {
  309.         constant MSU_SUPPORTED($40)
  310.         constant MSU_UNSUPPORTED($80)
  311.     }
  312.  
  313.     // Patch's address.
  314.    constant ADDRESS(Track.LIST+Track.SIZE)
  315.  
  316.    // RAM variable addresses used by this patch.
  317.    constant FLAGS($E0) // 8-bits
  318.  
  319.    scope COUNTERS {
  320.        constant FRAME($E1) // 8-bits
  321.        constant TIME($E2)  // 16-bits
  322.    }
  323.  
  324.    scope TRACK {
  325.        constant CURRENT($E4)     // 8-bits
  326.        constant FADE($E5)        // 8-bits
  327.        constant FADE_VOLUME($E6) // 16-bits
  328.        constant VOLUME($E7)      // 8-bits
  329.        constant FADE_STEP($E8)   // 16-bits
  330.    }
  331.  
  332.    scope GAME {
  333.        constant ATTRACT($EA) // 8-bits
  334.    }
  335.  
  336.    macro SynchFix(variable seconds, variable value) {
  337.        cpx.w #seconds
  338.        bmi +
  339.        lda.b #value
  340.        bra .Default
  341.        +
  342.    }
  343. }
  344.  
  345. // **********
  346. // * Macros *
  347. // **********
  348. macro scope seek(variable address) {
  349.    variable bank((address >> 16) & $FF)
  350.    variable offset(address & $FFFF)
  351.  
  352.    if {defined BUGFIX_UNCENSOR} {
  353.        if bank >= $40 && bank <= $7D {
  354.            // ExHiROM section, no need to change origin.
  355.            // Physical and ExHiROM addresses are the same.
  356.            origin address
  357.  
  358.            if offset < $8000 {
  359.                base address
  360.            } else {
  361.                base (address & $3FFFFF) | $800000 // Move address to FastROM address.
  362.            }
  363.        } else if (bank >= $00 && bank <= $3F) || (bank >= $80 && bank <= $BF) {
  364.            // ExHiROM section
  365.            if offset < $8000 {
  366.                error "Invalid ExHiROM address."
  367.            }
  368.  
  369.            origin (address & $3FFFFF) | $400000
  370.            base address | $800000 // Move address to FastROM address.
  371.        } else if bank >= $C0 && bank <= $FF {
  372.            // HiROM section, no need to change base.
  373.            origin address & $3FFFFF
  374.            base address
  375.        } else {
  376.            error "Invalid ExHiROM address."
  377.        }
  378.    } else {
  379.        if (bank >= $00 && bank <= $3F) || (bank >= $80 && bank <= $BF) {
  380.            if offset < $8000 {
  381.                error "Invalid HiROM address."
  382.            }
  383.  
  384.            origin address & $3FFFFF
  385.            base address | $800000 // Move address to FastROM address.
  386.        } else if (bank >= $40 && bank <= $7D) || (bank >= $C0 && bank <= $FF) {
  387.            origin address & $3FFFFF
  388.            base address | $800000 // Move address to FastROM address.
  389.        } else {
  390.            error "Invalid HiROM address."
  391.        }
  392.    }
  393. }
  394.  
  395. // ========================
  396. // = Original code hijack =
  397. // ========================
  398.  
  399. // Main
  400. seek($C70004)
  401.    jml Patch.Main
  402.  
  403. // NMI hijack
  404. seek($00FF10)
  405.    jml Patch.UpdateLoop
  406.  
  407. // Check which track ID the game is reading from the ROM.
  408. seek($C307E5)
  409.    jsl Patch.AttractHack
  410.    nop
  411.    nop
  412.    nop
  413.  
  414. // Wait for song to finish command.
  415. seek($C03CC6)
  416.    jsl Patch.WaitTrackFinish
  417.    nop
  418.    nop
  419.    nop
  420.    nop
  421.  
  422. // Wait for song to start (found when switching characters on overworld).
  423. seek($C2CBE0)
  424.    jsl Patch.WaitTrackStart
  425.    nop
  426.    nop
  427.    nop
  428.    nop
  429.    
  430. // Wait for title screen fix.
  431. // This chunk of code is copied into RAM
  432. // by the decompression routine, that's why
  433. // it got a db $80 in the middle.
  434. seek($C335AF)
  435.     nop
  436.     db $80
  437.     jsl Patch.WaitTrackStart
  438.     nop
  439.     nop
  440.  
  441. // Bike Race ending camera animation fix.
  442. // This is a lazy destructive hijack to the compressed code.
  443. // Original code check if the song has started:
  444. // 7e475c lda $2143
  445. // 7e475f and #$0f
  446. // 7e4761 beq $4771
  447. seek($C3257B)
  448.     lda.b #$01
  449.     nop
  450.  
  451. // Epoch 1999 AD and Ending timing fix.
  452. seek($C30C28)
  453. -
  454.     // Equivalent to bra $0bb5
  455.     db $80,$8B
  456.     jsl Patch.EpochAndEndingFix
  457.     bcs -
  458.     rts
  459.  
  460. // Epoch 1999 AD event modification.
  461. // This is a destructive modification.
  462. // Remove syncronisation with music in the event.
  463. // NOTE: Address moved for Bugfix and Uncensor Patch.
  464. if {defined BUGFIX_UNCENSOR} {
  465. seek($81B5EE)
  466. } else {
  467. seek($FA96B1)
  468. }
  469.     // 10 10 is Event Command Jump Forward ten bytes.
  470.     // This is compressed data so the modification is
  471.     // replicated 3 times.
  472.     db $10, $10, 0, 0, 0
  473.    
  474. // Fix for in normal combat with custom music, wrong sfx.
  475. // Tell the SPC routine to always load the data.
  476. seek($C70A8A)
  477.     jml Patch.BattleSampleHack
  478.  
  479. // ============
  480. // = MSU Code =
  481. // ============
  482. seek(Patch.ADDRESS)
  483. scope Patch {
  484.  
  485. scope CheckSupport: {
  486.     // MSU-1 support routine.
  487.     lda.b FLAGS
  488.     bit.b #Flags.MSU_SUPPORTED
  489.     bne .Exit
  490.     bit.b #Flags.MSU_UNSUPPORTED
  491.     bne .Fail
  492.  
  493.     variable source(MSU.Output.ID)
  494.     variable index(0)
  495.     variable fallback(.Unsupported)
  496.  
  497.     Utility.ascii('S')
  498.     Utility.ascii('-')
  499.     Utility.ascii('M')
  500.     Utility.ascii('S')
  501.     Utility.ascii('U')
  502.     Utility.ascii('1')
  503.  
  504.     // Store the flag so we don't have to check for MSU-1 support everytime.
  505.    lda.b FLAGS
  506.    ora.b #Flags.MSU_SUPPORTED
  507.    sta.b FLAGS
  508.  
  509. .Exit:
  510.    sec
  511.    rts
  512.  
  513. .Unsupported:
  514.    // Store the flag so we don't have to check for MSU-1 support everytime.
  515.     lda.b FLAGS
  516.     ora.b #Flags.MSU_UNSUPPORTED
  517.     sta.b FLAGS
  518.  
  519. .Fail:
  520.     clc
  521.     rts
  522. }
  523.  
  524. scope Main: {
  525.     Utility.Register.backup(Utility.Register.ALL)
  526.    
  527.     jsr CheckSupport
  528.     bcc .Default
  529.  
  530.     lda.b Game.SOUND.COMMAND
  531.  
  532.     // Play
  533.     cmp.b #Game.SOUND.COMMANDS.PLAY
  534.     bne +
  535.     jsr PlayTrack
  536.     bra .Default
  537. +
  538.     // Resume
  539.     cmp.b #Game.SOUND.COMMANDS.RESUME
  540.     bne +
  541.     jsr PlayTrack
  542.     bra .Default
  543. +
  544.     // Interrupt
  545.     cmp.b #Game.SOUND.COMMANDS.INTERRUPT
  546.     bne +
  547.     jsr PlayTrack
  548.     bra .Default
  549. +
  550.     // Fade
  551.     cmp.b #Game.SOUND.COMMANDS.FADE
  552.     bne +
  553.     jsr FadeTrack
  554.     bra .Default
  555. +
  556.     // Pause/unpause during battle
  557.     cmp.b #Game.SOUND.COMMANDS.PAUSE
  558.     bne .Default
  559.     jsr PauseTrack
  560.  
  561. .Default:
  562.     // Original routine
  563.     Utility.Register.restore(Utility.Register.ALL)
  564.    
  565.     jml $C70140
  566. }
  567.  
  568. scope PlayTrack: {
  569.     // X: Track ID | Y: Play type
  570.     ldx.b Game.SOUND.REQUEST
  571.     beq .Stop
  572.  
  573.     cpx.b #Track.TRACKS.THEME
  574.     bne +
  575.     lda.b GAME.ATTRACT
  576.     beq +
  577.     // Change attract theme.
  578.     ldx.b #Track.TRACKS.THEME_ATTRACT
  579. +
  580.     cpx.b TRACK.CURRENT
  581.     bne +
  582.     // Is audio still playing?
  583.     lda.w MSU.Output.STATUS
  584.     bit.b #MSU.Flags.STATUS.AUDIO_PLAYING
  585.     bne .Continue
  586. +
  587.     lda.l Track.LIST,x // ldy Track.LIST,x will not work here as ldy doesn't have a long instruction.
  588.    beq .Stop
  589.    bmi .Exit
  590.    tay // Store our play type value on Y so we don't have to get it again.
  591.  
  592.     stz.w MSU.Input.CONTROL
  593.     stx.w MSU.Input.TRACK_LO
  594.     stz.w MSU.Input.TRACK_HI
  595.  
  596. .Check:
  597.     // Wait until MSU-1 is done loading our track.
  598.     lda.w MSU.Output.STATUS
  599.     bit.b #MSU.Flags.STATUS.AUDIO_BUSY
  600.     bne .Check
  601.  
  602.     // Check if track is missing.
  603.     bit.b #MSU.Flags.STATUS.TRACK_MISSING
  604.     bne .Stop
  605.  
  606. .Play:
  607.     stx.b TRACK.CURRENT
  608.  
  609.     // Reset counters at the start of a music.
  610.     stz.b COUNTERS.FRAME
  611.     rep #$20
  612.     stz.b COUNTERS.TIME
  613.     sep #$20
  614.  
  615.     lda.b TRACK.FADE
  616.     bne +
  617.  
  618.     lda.b #MSU.Values.VOLUME.FULL
  619.     sta.b TRACK.VOLUME
  620.  
  621.     stz.b TRACK.FADE_VOLUME
  622. +
  623.     // Set volume.
  624.     lda.b TRACK.VOLUME
  625.     sta.w MSU.Input.VOLUME
  626.  
  627.     // Play/Resume the track.
  628.     sty.w MSU.Input.CONTROL
  629.  
  630. .Continue:
  631.     // Tell the SPC to not play any track.
  632.     stz.b Game.SOUND.REQUEST
  633.  
  634. .Exit:
  635.     rts
  636.  
  637. .Stop:
  638.     // Stop the current track.
  639.     stz.w MSU.Input.CONTROL
  640.     stz.w MSU.Input.VOLUME
  641.  
  642.     stz.b TRACK.CURRENT
  643.     stz.b TRACK.VOLUME
  644.     stz.b TRACK.FADE
  645.     stz.b TRACK.FADE_VOLUME
  646.  
  647.     cpx.b #Track.TRACKS.THEME_ATTRACT
  648.     beq +
  649.     stz.b GAME.ATTRACT
  650. +
  651.     rep #$20
  652.     stz.b TRACK.FADE_STEP
  653.  
  654.     rts
  655. }
  656.  
  657. scope FadeTrack: {
  658.     lda.b Game.SOUND.FADE_VOLUME
  659.     cmp.b TRACK.VOLUME
  660.     beq .Exit
  661.  
  662.     stz.b TRACK.FADE_VOLUME
  663.  
  664.     ldy.b Game.SOUND.FADE_TIME
  665.     beq .Set
  666.     sty.b TRACK.FADE
  667.  
  668.     sec
  669.     sbc.b TRACK.VOLUME
  670.     bcs +
  671.     eor.b #MSU.Values.VOLUME.FULL
  672.     inc
  673. +
  674.     tax
  675.     SNES.div()
  676.  
  677.     bcs +
  678.     eor.b #MSU.Values.VOLUME.FULL
  679. +
  680.     sta.b TRACK.FADE_STEP+1
  681.  
  682.     lda.w SNES.DIV.REMAINDER_L
  683.     xba
  684.     rep #$10
  685.     tax
  686.     SNES.div()
  687.  
  688.     bcs +
  689.     eor.b #MSU.Values.VOLUME.FULL
  690. +
  691.     sta.b TRACK.FADE_STEP
  692.  
  693.     bcs .Exit
  694.  
  695.     rep #$20
  696.     inc.b TRACK.FADE_STEP
  697.  
  698. .Exit:
  699.     rts
  700.  
  701. .Set:
  702.     stz.b TRACK.FADE
  703.  
  704.     cmp.b #MSU.Values.VOLUME.EMPTY
  705.     bne +
  706.     // Stop track if the volume is 0.
  707.     stz.w MSU.Input.CONTROL
  708. +
  709.     sta.b TRACK.VOLUME
  710.     sta.w MSU.Input.VOLUME
  711.  
  712.     rep #$20
  713.     stz.b TRACK.FADE_STEP
  714.  
  715.     rts
  716. }
  717.  
  718. scope PauseTrack: {
  719.     // Do we have a track playing to pause/unpause?
  720.     ldx.b TRACK.CURRENT
  721.     beq .Exit
  722.  
  723.     lda.b Game.SOUND.REQUEST
  724.     cmp.b #Game.SOUND.COMMANDS.PAUSE
  725.     beq .Pause
  726.  
  727.     lda.l Track.LIST,x
  728.     sta.w MSU.Input.CONTROL
  729.  
  730. .Exit:
  731.     rts
  732.  
  733. .Pause:
  734.     stz.w MSU.Input.CONTROL
  735.  
  736.     rts
  737. }
  738.  
  739. scope UpdateLoop: {
  740.     Utility.Register.backup(Utility.Register.P|Utility.Register.A|Utility.Register.D)
  741.  
  742.     lda.b TRACK.CURRENT
  743.     cmp.b #Track.TRACKS.EPOCH_1999AD
  744.     beq +
  745.     cmp.b #Track.TRACKS.ENDING
  746.     beq +
  747.  
  748.     lda.b TRACK.FADE
  749.     beq .Default
  750. +
  751.     lda.l MSU.Output.STATUS
  752.     bit.b #MSU.Flags.STATUS.AUDIO_PLAYING
  753.     beq .Default
  754.  
  755.     lda.b COUNTERS.FRAME
  756.     inc
  757.     cmp.b #60
  758.     bpl .Reset
  759.  
  760.     sta.b COUNTERS.FRAME
  761.  
  762. .Fade:
  763.     lsr // Increase/Reduce volume every odd frame.
  764.     bcc .Default
  765.    
  766.     lda.b TRACK.FADE
  767.     beq .Default
  768.     dec
  769.     sta.b TRACK.FADE
  770.  
  771.     clc
  772.     rep #$20
  773.     lda.b TRACK.FADE_VOLUME
  774.     adc.b TRACK.FADE_STEP
  775.     sta.b TRACK.FADE_VOLUME
  776.     sep #$20
  777.  
  778.     xba
  779.     sta.l MSU.Input.VOLUME
  780.     bne .Default
  781.     // Stop track if the volume is 0.
  782.     lda.b #MSU.Flags.CONTROL.AUDIO_STOP
  783.     sta.l MSU.Input.CONTROL
  784.     stz.b TRACK.FADE
  785.     stz.b TRACK.FADE_VOLUME
  786.  
  787. .Default:
  788.     Utility.Register.restore(Utility.Register.P|Utility.Register.A|Utility.Register.D)
  789.  
  790.     jml $000500
  791.  
  792. .Reset:
  793.     stz.b COUNTERS.FRAME
  794.  
  795.     // Increment counter at each second (each 60 fps).
  796.     // Will be used to fake timing for Epoch 1999 scene and ending.
  797.     rep #$20
  798.     inc.b COUNTERS.TIME
  799.  
  800.     bra .Default
  801. }
  802.  
  803. scope AttractHack: {
  804.     Utility.Register.backup(Utility.Register.P)
  805.  
  806.     rep #$10
  807.  
  808.     cpx.w #$6E01
  809.     bne .Default
  810.  
  811.     sep #$20
  812.     phb
  813.     pla
  814.  
  815.     cmp.b #$DB
  816.     bne .Default
  817.  
  818.     // $DB6E01
  819.     lda.b #true
  820.     Utility.Memory.store(GAME.ATTRACT)
  821.  
  822. .Default:
  823.     Utility.Register.restore(Utility.Register.P)
  824.  
  825.     // Original code
  826.     lda.w $0001,x
  827.     sta.l $002180
  828.  
  829.     rtl
  830. }
  831.  
  832. scope WaitTrackStart: {
  833.     Utility.Memory.load(TRACK.CURRENT)
  834.     beq .Default
  835.  
  836. .MSU:
  837.     lda.l MSU.Output.STATUS
  838.     and.b #MSU.Flags.STATUS.AUDIO_PLAYING
  839.     beq .MSU
  840.  
  841.     rtl
  842.    
  843. .Default:
  844.     // Original code
  845.     lda.l SNES.SPC.COMM3
  846.     and.b #$0F
  847.     beq .Default
  848.    
  849.     rtl
  850. }
  851.  
  852. scope WaitTrackFinish: {
  853.     Utility.Memory.load(TRACK.CURRENT)
  854.     beq .Default
  855.  
  856. .MSU:
  857.     lda.w MSU.Output.STATUS
  858.     and.b #MSU.Flags.STATUS.AUDIO_PLAYING
  859.     bne +
  860.     inx
  861. +
  862.     rtl
  863.    
  864. .Default:
  865.     // Original code
  866.     lda.w SNES.SPC.COMM3
  867.     and.b #$0F
  868.     bne +
  869.     inx
  870. +
  871.     rtl
  872. }
  873.  
  874. scope EpochAndEndingFix: {
  875.     rep #$20
  876.     phd
  877.     Utility.direct(Utility.Memory.OFFSET)
  878.     sep #$20
  879.  
  880.     php
  881.     rep #$10
  882.     phx
  883. -
  884.     lda.b TRACK.CURRENT
  885.     // Original evaluation
  886.     bne +
  887.     lda.l SNES.SPC.COMM2
  888.     cmp.l SNES.SPC.COMM2
  889.     bne -
  890.  
  891.     jmp .Default
  892. +
  893.     ldx.b COUNTERS.TIME
  894.  
  895.     cmp.b #Track.TRACKS.EPOCH_1999AD
  896.     beq .Epoch
  897.     cmp.b #Track.TRACKS.ENDING
  898.     beq .Ending
  899.  
  900.     plx
  901.     plp
  902.     pld
  903.  
  904.     sec
  905.     rtl
  906.  
  907. .Epoch:
  908.     SynchFix(49, 5)
  909.     SynchFix(21, 3)
  910.     SynchFix(16, 2)
  911.     SynchFix(7, 1)
  912.     lda.b #0
  913.  
  914.     bra .Default
  915.    
  916. .Ending:
  917.     SynchFix(280, 10)
  918.     SynchFix(253, 9)
  919.     SynchFix(193, 8)
  920.     SynchFix(159, 7)
  921.     SynchFix(127, 6)
  922.     SynchFix(104, 5)
  923.     SynchFix(77, 4)
  924.     SynchFix(45, 3)
  925.     SynchFix(24, 2)
  926.     SynchFix(17, 1)
  927.     lda.b #0
  928.  
  929. .Default:
  930.     plx
  931.     plp
  932.     pld
  933.  
  934.     // Original code
  935.     and.b #$0F
  936.     cmp ($20)
  937.     bpl +
  938.  
  939.     rep #$20
  940.     dec.b $20
  941.  
  942.     clc
  943.     rtl
  944. +
  945.     sec
  946.     rtl
  947. }
  948.  
  949. scope BattleSampleHack: {
  950.     Utility.Memory.load(Game.SOUND.BANK_REQUEST)
  951.     beq .NotInCombat
  952.  
  953.     jml $C70A96
  954.  
  955. .NotInCombat:
  956.     // Original code
  957.     dec
  958. -
  959.     cmp.w SNES.SPC.COMM0
  960.     beq -
  961.     pla
  962.     pla
  963.     pla
  964.  
  965.     jml $C70192
  966. }
  967.  
  968. }
  969.  
  970. // Track list for MSU-1.
  971. // NONE: Ignored.
  972. // STOP: Stop playing current track.
  973. // PLAY: Play track, but only once.
  974. // LOOP: Play track on loop.
  975. seek(Track.LIST)
  976.     db Track.ACTIONS.STOP // ($00)
  977.     db Track.ACTIONS.LOOP // ($01) 1.05 - Green Memories
  978.     db Track.ACTIONS.LOOP // ($02) 1.09 - Yearnings of the Wind
  979.     db Track.ACTIONS.LOOP // ($03) 3.04 - Corridor of Time
  980.     db Track.ACTIONS.LOOP // ($04) 2.20 - Rhythm of Earth, Wind, and Sky
  981.     db Track.ACTIONS.LOOP // ($05) 2.01 - A Desolate World
  982.     db Track.ACTIONS.LOOP // ($06) 1.06 - Guardia's Millennial Fair
  983.    db Track.ACTIONS.LOOP // ($07) 3.09 - Crono & Marle - A Distant Promise
  984.    db Track.ACTIONS.LOOP // ($08) 1.11 - Secret Of The Forest
  985.    db Track.ACTIONS.LOOP // ($09) 3.05 - Zeal Palace
  986.    db Track.ACTIONS.LOOP // ($0A) 2.10 - Derelict Factory
  987.    db Track.ACTIONS.LOOP // ($0B) 2.19 - Ayla's Theme
  988.     db Track.ACTIONS.LOOP // ($0C) 1.13 - Guardia Castle - Pride & Glory
  989.     db Track.ACTIONS.LOOP // ($0D) 2.05 - Lavos' Theme
  990.    db Track.ACTIONS.LOOP // ($0E) 2.09 - Robo's Theme
  991.     db Track.ACTIONS.PLAY // ($0F) 1.03 - Morning Glow
  992.     db Track.ACTIONS.LOOP // ($10) 1.15 - The Cathedral
  993.     db Track.ACTIONS.STOP // ($11)
  994.     db Track.ACTIONS.STOP // ($12)
  995.     db Track.ACTIONS.LOOP // ($13) 3.10 - The Epoch - Wings of Time
  996.     db Track.ACTIONS.LOOP // ($14) 3.06 - Schala's Theme
  997.    db Track.ACTIONS.LOOP // ($15) 2.14 - Jolly Ol' Spekkio
  998.     db Track.ACTIONS.LOOP // ($16) 1.23 - Critical Moment
  999.     db Track.ACTIONS.LOOP // ($17) 1.21 - The Trial
  1000.     db Track.ACTIONS.LOOP // ($18) 1.02 - The Chrono Trigger Symphony
  1001.     db Track.ACTIONS.STOP // ($19)
  1002.     db Track.ACTIONS.STOP // ($1A)
  1003.     db Track.ACTIONS.LOOP // ($1B) 1.20 - Fanfare 1
  1004.     db Track.ACTIONS.PLAY // ($1C) 2.12 - Fanfare 2
  1005.     db Track.ACTIONS.LOOP // ($1D) 3.03 - Depths of the Night
  1006.     db Track.ACTIONS.LOOP // ($1E) 1.04 - Peaceful Days
  1007.     db Track.ACTIONS.LOOP // ($1F) 1.08 - Strange Occurences
  1008.     db Track.ACTIONS.STOP // ($20)
  1009.     db Track.ACTIONS.STOP // ($21)
  1010.     db Track.ACTIONS.STOP // ($22)
  1011.     db Track.ACTIONS.LOOP // ($23) 1.22 - The Hidden Truth
  1012.     db Track.ACTIONS.PLAY // ($24) 1.16 - A Prayer for the Wayfarer
  1013.     db Track.ACTIONS.PLAY // ($25) 1.14 - Huh
  1014.     db Track.ACTIONS.LOOP // ($26) 2.06 - The Last Day of the World
  1015.     db Track.ACTIONS.LOOP // ($27) 2.07 - Johnny of the Robo Gang
  1016.     db Track.ACTIONS.LOOP // ($28) 2.24 - Magus Confronted
  1017.     db Track.ACTIONS.LOOP // ($29) 1.18 - Boss Battle 1
  1018.     db Track.ACTIONS.LOOP // ($2A) 1.19 - Frog's Theme
  1019.    db Track.ACTIONS.PLAY // ($2B) 1.10 - Good Night
  1020.    db Track.ACTIONS.LOOP // ($2C) 2.08 - Bike Chase
  1021.    db Track.ACTIONS.LOOP // ($2D) 2.04 - Those Without the Will to Live
  1022.    db Track.ACTIONS.PLAY // ($2E) 2.02 - Mystery from the Past
  1023.    db Track.ACTIONS.LOOP // ($2F) 2.16 - Creeping through the Sewers
  1024.    db Track.ACTIONS.PLAY // ($30) 1.01 - A Premonition
  1025.    db Track.ACTIONS.LOOP // ($31) 3.08 - Ocean Palace
  1026.    db Track.ACTIONS.LOOP // ($32) 3.14 - The Final Battle
  1027.    db Track.ACTIONS.LOOP // ($33) 2.03 - Site 16
  1028.    db Track.ACTIONS.STOP // ($34)
  1029.    db Track.ACTIONS.STOP // ($35)
  1030.    db Track.ACTIONS.LOOP // ($36) 2.21 - Burn! Bobonga! Burn!
  1031.    db Track.ACTIONS.STOP // ($37)
  1032.    db Track.ACTIONS.LOOP // ($38) 2.18 - Primeval Mountain
  1033.    db Track.ACTIONS.LOOP // ($39) 3.13 - World Revolution
  1034.    db Track.ACTIONS.STOP // ($3A)
  1035.    db Track.ACTIONS.LOOP // ($3B) 3.07 - Sealed Door
  1036.    db Track.ACTIONS.LOOP // ($3C) 1.17 - Light of Silence
  1037.    db Track.ACTIONS.PLAY // ($3D) 2.15 - Fanfare 3
  1038.    db Track.ACTIONS.LOOP // ($3E) 2.13 - At the End of Time
  1039.    db Track.ACTIONS.PLAY // ($3F) 3.17 - Outskirts of Time
  1040.    db Track.ACTIONS.LOOP // ($40) 2.23 - Strains of Insanity
  1041.    db Track.ACTIONS.STOP // ($41)
  1042.    db Track.ACTIONS.LOOP // ($42) 1.07 - Gato's Song
  1043.     db Track.ACTIONS.STOP // ($43)
  1044.     db Track.ACTIONS.LOOP // ($44) 3.11 - Black Omen
  1045.     db Track.ACTIONS.LOOP // ($45) 1.12 - Battle
  1046.     db Track.ACTIONS.LOOP // ($46) 3.02 - Tyrano Lair
  1047.     db Track.ACTIONS.STOP // ($47)
  1048.     db Track.ACTIONS.PLAY // ($48) 2.22 - The Fiendlord's Keep
  1049.    db Track.ACTIONS.LOOP // ($49) 3.15 - Festival of Stars
  1050.    db Track.ACTIONS.STOP // ($4A)
  1051.    db Track.ACTIONS.STOP // ($4B)
  1052.    db Track.ACTIONS.STOP // ($4C)
  1053.    db Track.ACTIONS.LOOP // ($4D) 3.16 - Epilogue - To My Dear Friends
  1054.    db Track.ACTIONS.LOOP // ($4E) 2.17 - Boss Battle 2
  1055.    db Track.ACTIONS.STOP // ($4F)
  1056.    db Track.ACTIONS.LOOP // ($50) 3.12 - Determination
  1057.    db Track.ACTIONS.LOOP // ($51) 2.11 - Battle 2
  1058.    db Track.ACTIONS.LOOP // ($52) 3.01 - Singing Mountain
  1059.    db Track.ACTIONS.STOP // ($53)
  1060.    db Track.ACTIONS.PLAY // ($54) 1.02 - The Chrono Trigger Symphony
  1061.    db Track.ACTIONS.LOOP // ($55) 2.05 - Lavos' Theme
  1062.     db Track.ACTIONS.STOP // ($56)
  1063.     db Track.ACTIONS.STOP // ($57)
  1064.     db Track.ACTIONS.STOP // ($58)
  1065.     db Track.ACTIONS.STOP // ($59)
  1066.     db Track.ACTIONS.STOP // ($5A)
  1067.     db Track.ACTIONS.STOP // ($5B)
  1068.     db Track.ACTIONS.STOP // ($5C)
  1069.     db Track.ACTIONS.STOP // ($5D)
  1070.     db Track.ACTIONS.STOP // ($5E)
  1071.     db Track.ACTIONS.STOP // ($5F)
  1072.     db Track.ACTIONS.STOP // ($60)
  1073.     db Track.ACTIONS.STOP // ($61)
  1074.     db Track.ACTIONS.STOP // ($62)
  1075.     db Track.ACTIONS.STOP // ($63)
  1076.     db Track.ACTIONS.STOP // ($64)
  1077.     db Track.ACTIONS.STOP // ($65)
  1078.     db Track.ACTIONS.STOP // ($66)
  1079.     db Track.ACTIONS.STOP // ($67)
  1080.     db Track.ACTIONS.STOP // ($68)
  1081.     db Track.ACTIONS.STOP // ($69)
  1082.     db Track.ACTIONS.STOP // ($6A)
  1083.     db Track.ACTIONS.STOP // ($6B)
  1084.     db Track.ACTIONS.STOP // ($6C)
  1085.     db Track.ACTIONS.STOP // ($6D)
  1086.     db Track.ACTIONS.STOP // ($6E)
  1087.     db Track.ACTIONS.STOP // ($6F)
  1088.     db Track.ACTIONS.STOP // ($70)
  1089.     db Track.ACTIONS.STOP // ($71)
  1090.     db Track.ACTIONS.STOP // ($72)
  1091.     db Track.ACTIONS.STOP // ($73)
  1092.     db Track.ACTIONS.STOP // ($74)
  1093.     db Track.ACTIONS.STOP // ($75)
  1094.     db Track.ACTIONS.STOP // ($76)
  1095.     db Track.ACTIONS.STOP // ($77)
  1096.     db Track.ACTIONS.STOP // ($78)
  1097.     db Track.ACTIONS.STOP // ($79)
  1098.     db Track.ACTIONS.STOP // ($7A)
  1099.     db Track.ACTIONS.STOP // ($7B)
  1100.     db Track.ACTIONS.STOP // ($7C)
  1101.     db Track.ACTIONS.STOP // ($7D)
  1102.     db Track.ACTIONS.STOP // ($7E)
  1103.     db Track.ACTIONS.STOP // ($7F)
  1104.     db Track.ACTIONS.STOP // ($80)
  1105.     db Track.ACTIONS.STOP // ($81)
  1106.     db Track.ACTIONS.STOP // ($82)
  1107.     db Track.ACTIONS.STOP // ($83)
  1108.     db Track.ACTIONS.STOP // ($84)
  1109.     db Track.ACTIONS.STOP // ($85)
  1110.     db Track.ACTIONS.STOP // ($86)
  1111.     db Track.ACTIONS.STOP // ($87)
  1112.     db Track.ACTIONS.STOP // ($88)
  1113.     db Track.ACTIONS.STOP // ($89)
  1114.     db Track.ACTIONS.STOP // ($8A)
  1115.     db Track.ACTIONS.STOP // ($8B)
  1116.     db Track.ACTIONS.STOP // ($8C)
  1117.     db Track.ACTIONS.STOP // ($8D)
  1118.     db Track.ACTIONS.STOP // ($8E)
  1119.     db Track.ACTIONS.STOP // ($8F)
  1120.     db Track.ACTIONS.STOP // ($90)
  1121.     db Track.ACTIONS.STOP // ($91)
  1122.     db Track.ACTIONS.STOP // ($92)
  1123.     db Track.ACTIONS.STOP // ($93)
  1124.     db Track.ACTIONS.STOP // ($94)
  1125.     db Track.ACTIONS.STOP // ($95)
  1126.     db Track.ACTIONS.STOP // ($96)
  1127.     db Track.ACTIONS.STOP // ($97)
  1128.     db Track.ACTIONS.STOP // ($98)
  1129.     db Track.ACTIONS.STOP // ($99)
  1130.     db Track.ACTIONS.STOP // ($9A)
  1131.     db Track.ACTIONS.STOP // ($9B)
  1132.     db Track.ACTIONS.STOP // ($9C)
  1133.     db Track.ACTIONS.STOP // ($9D)
  1134.     db Track.ACTIONS.STOP // ($9E)
  1135.     db Track.ACTIONS.STOP // ($9F)
  1136.     db Track.ACTIONS.STOP // ($A0)
  1137.     db Track.ACTIONS.STOP // ($A1)
  1138.     db Track.ACTIONS.STOP // ($A2)
  1139.     db Track.ACTIONS.STOP // ($A3)
  1140.     db Track.ACTIONS.STOP // ($A4)
  1141.     db Track.ACTIONS.STOP // ($A5)
  1142.     db Track.ACTIONS.STOP // ($A6)
  1143.     db Track.ACTIONS.STOP // ($A7)
  1144.     db Track.ACTIONS.STOP // ($A8)
  1145.     db Track.ACTIONS.STOP // ($A9)
  1146.     db Track.ACTIONS.STOP // ($AA)
  1147.     db Track.ACTIONS.STOP // ($AB)
  1148.     db Track.ACTIONS.STOP // ($AC)
  1149.     db Track.ACTIONS.STOP // ($AD)
  1150.     db Track.ACTIONS.STOP // ($AE)
  1151.     db Track.ACTIONS.STOP // ($AF)
  1152.     db Track.ACTIONS.STOP // ($B0)
  1153.     db Track.ACTIONS.STOP // ($B1)
  1154.     db Track.ACTIONS.STOP // ($B2)
  1155.     db Track.ACTIONS.STOP // ($B3)
  1156.     db Track.ACTIONS.STOP // ($B4)
  1157.     db Track.ACTIONS.STOP // ($B5)
  1158.     db Track.ACTIONS.STOP // ($B6)
  1159.     db Track.ACTIONS.STOP // ($B7)
  1160.     db Track.ACTIONS.STOP // ($B8)
  1161.     db Track.ACTIONS.STOP // ($B9)
  1162.     db Track.ACTIONS.STOP // ($BA)
  1163.     db Track.ACTIONS.STOP // ($BB)
  1164.     db Track.ACTIONS.STOP // ($BC)
  1165.     db Track.ACTIONS.STOP // ($BD)
  1166.     db Track.ACTIONS.STOP // ($BE)
  1167.     db Track.ACTIONS.STOP // ($BF)
  1168.     db Track.ACTIONS.STOP // ($C0)
  1169.     db Track.ACTIONS.STOP // ($C1)
  1170.     db Track.ACTIONS.STOP // ($C2)
  1171.     db Track.ACTIONS.STOP // ($C3)
  1172.     db Track.ACTIONS.STOP // ($C4)
  1173.     db Track.ACTIONS.STOP // ($C5)
  1174.     db Track.ACTIONS.STOP // ($C6)
  1175.     db Track.ACTIONS.STOP // ($C7)
  1176.     db Track.ACTIONS.STOP // ($C8)
  1177.     db Track.ACTIONS.STOP // ($C9)
  1178.     db Track.ACTIONS.STOP // ($CA)
  1179.     db Track.ACTIONS.STOP // ($CB)
  1180.     db Track.ACTIONS.STOP // ($CC)
  1181.     db Track.ACTIONS.STOP // ($CD)
  1182.     db Track.ACTIONS.STOP // ($CE)
  1183.     db Track.ACTIONS.STOP // ($CF)
  1184.     db Track.ACTIONS.STOP // ($D0)
  1185.     db Track.ACTIONS.STOP // ($D1)
  1186.     db Track.ACTIONS.STOP // ($D2)
  1187.     db Track.ACTIONS.STOP // ($D3)
  1188.     db Track.ACTIONS.STOP // ($D4)
  1189.     db Track.ACTIONS.STOP // ($D5)
  1190.     db Track.ACTIONS.STOP // ($D6)
  1191.     db Track.ACTIONS.STOP // ($D7)
  1192.     db Track.ACTIONS.STOP // ($D8)
  1193.     db Track.ACTIONS.STOP // ($D9)
  1194.     db Track.ACTIONS.STOP // ($DA)
  1195.     db Track.ACTIONS.STOP // ($DB)
  1196.     db Track.ACTIONS.STOP // ($DC)
  1197.     db Track.ACTIONS.STOP // ($DD)
  1198.     db Track.ACTIONS.STOP // ($DE)
  1199.     db Track.ACTIONS.STOP // ($DF)
  1200.     db Track.ACTIONS.STOP // ($E0)
  1201.     db Track.ACTIONS.STOP // ($E1)
  1202.     db Track.ACTIONS.STOP // ($E2)
  1203.     db Track.ACTIONS.STOP // ($E3)
  1204.     db Track.ACTIONS.STOP // ($E4)
  1205.     db Track.ACTIONS.STOP // ($E5)
  1206.     db Track.ACTIONS.STOP // ($E6)
  1207.     db Track.ACTIONS.STOP // ($E7)
  1208.     db Track.ACTIONS.STOP // ($E8)
  1209.     db Track.ACTIONS.STOP // ($E9)
  1210.     db Track.ACTIONS.STOP // ($EA)
  1211.     db Track.ACTIONS.STOP // ($EB)
  1212.     db Track.ACTIONS.STOP // ($EC)
  1213.     db Track.ACTIONS.STOP // ($ED)
  1214.     db Track.ACTIONS.STOP // ($EE)
  1215.     db Track.ACTIONS.STOP // ($EF)
  1216.     db Track.ACTIONS.STOP // ($F0)
  1217.     db Track.ACTIONS.STOP // ($F1)
  1218.     db Track.ACTIONS.STOP // ($F2)
  1219.     db Track.ACTIONS.STOP // ($F3)
  1220.     db Track.ACTIONS.STOP // ($F4)
  1221.     db Track.ACTIONS.STOP // ($F5)
  1222.     db Track.ACTIONS.STOP // ($F6)
  1223.     db Track.ACTIONS.STOP // ($F7)
  1224.     db Track.ACTIONS.STOP // ($F8)
  1225.     db Track.ACTIONS.STOP // ($F9)
  1226.     db Track.ACTIONS.STOP // ($FA)
  1227.     db Track.ACTIONS.STOP // ($FB)
  1228.     db Track.ACTIONS.STOP // ($FC)
  1229.     db Track.ACTIONS.STOP // ($FD)
  1230.     db Track.ACTIONS.STOP // ($FE)
  1231.     db Track.ACTIONS.NONE // ($FF)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top