How To Port the Sonic 2 Clone Driver into Sonic 2 HG Dissasembly

Discussion in 'Engineering & Reverse Engineering' started by Caverns 4, Jun 10, 2013.

  1. Caverns 4

    Caverns 4

    Member
    342
    0
    16
    Sanik Quest: Journey To The Right
    There are a few bugs I have noticed. One is that the spindash sound will not raise pitch. The music is not a perfect adaptation of Sonic 2's music, particularly sometimes the PSG channels sound slightly different. This is most noticable in Emerald Hill's music. Besides this, there are no problems.

    If the above bugs will not bother you too badly, then you'll like using the Sonic 2 Clone Driver after working with Sonic 2's own sound driver. The Clone Driver is much easier to port music to, and in fact, Sonic 1 music can even just be bincluded into the ROM. This is because it's based on the Sonic 1 sound driver, and uses similar (if not the same) formatting.

    With this out of the way, now it's time to edit the Sonic 2 HG Dissasembly!

    Step 1 - getting started
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    Back up your dissasembly if you haven't already.

    To start, go into your sound folder, where you'll have a DAC folder, a music folder, and a PCM folder.

    DELETE THEM ALL!

    and then extract "Sonic 2 Clone Driver_fixed.7z" into the main folder of your dissasembly.

    And then open up s2.sounddriver.asm, we're going to delete a lot of data from it.

    Find zMasterPlaylist and delete the following lines:
    Code (Text):
    1. ; zbyte_11F5h:
    2. zMasterPlaylist:
    3.  
    4. ; Music IDs
    5. offset :=   MusicPoint2
    6. ptrsize :=  2
    7. idstart :=  80h
    8. ; note: +20h means uncompressed, here
    9. ; +40h is an (ignored) flag, possibly to force PAL mode on/off
    10.  
    11. zMusIDPtr_2PResult: db  id(MusPtr_2PResult) ; 92
    12. zMusIDPtr_EHZ:      db  id(MusPtr_EHZ)      ; 81
    13. zMusIDPtr_MCZ_2P:   db  id(MusPtr_MCZ_2P)   ; 85
    14. zMusIDPtr_OOZ:      db  id(MusPtr_OOZ)      ; 8F
    15. zMusIDPtr_MTZ:      db  id(MusPtr_MTZ)      ; 82
    16. zMusIDPtr_HTZ:      db  id(MusPtr_HTZ)      ; 94
    17. zMusIDPtr_ARZ:      db  id(MusPtr_ARZ)      ; 86
    18. zMusIDPtr_CNZ_2P:   db  id(MusPtr_CNZ_2P)   ; 80
    19. zMusIDPtr_CNZ:      db  id(MusPtr_CNZ)      ; 83
    20. zMusIDPtr_DEZ:      db  id(MusPtr_DEZ)      ; 87
    21. zMusIDPtr_MCZ:      db  id(MusPtr_MCZ)      ; 84
    22. zMusIDPtr_EHZ_2P:   db  id(MusPtr_EHZ_2P)   ; 91
    23. zMusIDPtr_SCZ:      db  id(MusPtr_SCZ)      ; 8E
    24. zMusIDPtr_CPZ:      db  id(MusPtr_CPZ)      ; 8C
    25. zMusIDPtr_WFZ:      db  id(MusPtr_WFZ)      ; 90
    26. zMusIDPtr_HPZ:      db  id(MusPtr_HPZ)      ; 9B
    27. zMusIDPtr_Options:  db  id(MusPtr_Options)  ; 89
    28. zMusIDPtr_SpecStage:    db  id(MusPtr_SpecStage)    ; 88
    29. zMusIDPtr_Boss:     db  id(MusPtr_Boss)     ; 8D
    30. zMusIDPtr_EndBoss:  db  id(MusPtr_EndBoss)  ; 8B
    31. zMusIDPtr_Ending:   db  id(MusPtr_Ending)   ; 8A
    32. zMusIDPtr_SuperSonic:   db  id(MusPtr_SuperSonic)   ; 93
    33. zMusIDPtr_Invincible:   db  id(MusPtr_Invincible)   ; 99
    34. zMusIDPtr_ExtraLife:    db  id(MusPtr_ExtraLife)+20h; B5
    35. zMusIDPtr_Title:    db  id(MusPtr_Title)    ; 96
    36. zMusIDPtr_EndLevel: db  id(MusPtr_EndLevel) ; 97
    37. zMusIDPtr_GameOver: db  id(MusPtr_GameOver)+20h ; B8
    38. zMusIDPtr_Continue: db  (MusPtr_Continue-MusicPoint1)/ptrsize   ; 0
    39. zMusIDPtr_Emerald:  db  id(MusPtr_Emerald)+20h  ; BA
    40. zMusIDPtr_Credits:  db  id(MusPtr_Credits)+20h  ; BD
    41. zMusIDPtr_Countdown:    db  id(MusPtr_Drowning)+40h ; DC
    42. zMusIDPtr__End:
    Then go to zDACMasterPlaylist, and delete these:
    Code (Text):
    1.     db  id(zDACPtr_Sample1),17h     ; 81h
    2.     db  id(zDACPtr_Sample2),1       ; 82h
    3.     db  id(zDACPtr_Sample3),6       ; 83h
    4.     db  id(zDACPtr_Sample4),8       ; 84h
    5.     db  id(zDACPtr_Sample5),1Bh     ; 85h
    6.     db  id(zDACPtr_Sample6),0Ah     ; 86h
    7.     db  id(zDACPtr_Sample7),1Bh     ; 87h
    8.     db  id(zDACPtr_Sample5),12h     ; 88h
    9.     db  id(zDACPtr_Sample5),15h     ; 89h
    10.     db  id(zDACPtr_Sample5),1Ch     ; 8Ah
    11.     db  id(zDACPtr_Sample5),1Dh     ; 8Bh
    12.     db  id(zDACPtr_Sample6),2       ; 8Ch
    13.     db  id(zDACPtr_Sample6),5       ; 8Dh
    14.     db  id(zDACPtr_Sample6),8       ; 8Eh
    15.     db  id(zDACPtr_Sample7),8       ; 8Fh
    16.     db  id(zDACPtr_Sample7),0Bh     ; 90h
    17.     db  id(zDACPtr_Sample7),12h     ; 91h
    Step 2 - Deleting broken references
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------
    Now open up s2.asm, and search for the line "; end of 'ROM'" near the end of your dissasemby.

    On the empty line before it, past this:

    Code (Text):
    1.   include "Sonic 2 Clone Driver.asm"
    2.   even
    After this, search for "SoundIndex:", and delete everything for it, up to and including "SndPtr__End:"
    Now there are many unused sounds, Sound20 - Sound70 in the dissasembly that will be unused. If you wish, delete those too, as they will only take space.

    Once you've done that, locate "MusicPoint2:", and delete that, and everything below it it until the following line:

    Code (Text):
    1.     if * > soundBankStart + $8000
    Leave this line and everything below it alone for the time being.

    Now find the line
    Code (Text):
    1. ; loc_F1E8C:
    Below this line is where the Sega sound is included. If we delete it, we will get errors. If we leave I, we will get errors. So what do we do? Change it!
    Replace this:
    Code (Text):
    1. ; -------------------------------------------------------------------------------
    2. ; Sega Intro Sound
    3. ; 8-bit unsigned raw audio at 16Khz
    4. ; -------------------------------------------------------------------------------
    5. ; loc_F1E8C:
    6. Snd_Sega:   BINCLUDE    "sound/PCM/SEGA.bin"
    7. Snd_Sega_End:
    8.  
    9.     if Snd_Sega_End - Snd_Sega > $8000
    10.         fatal "Sega sound must fit within $8000 bytes, but you have a $\{Snd_Sega_End-Snd_Sega} byte Sega sound."
    11.     endif
    12.     if Snd_Sega_End - Snd_Sega > Size_of_SEGA_sound
    13.         fatal "Size_of_SEGA_sound = $\{Size_of_SEGA_sound}, but you have a $\{Snd_Sega_End-Snd_Sega} byte Sega sound."
    14.     endif
    With this:

    Code (Text):
    1. ; loc_F1E8C:
    2. Snd_Sega:   rts
    3. Snd_Sega_End:
    Now, we need to delete the old BINCLUDEd DAC samples. Got to loc_ED100, or SndDAC_Start.
    Staring at line "; loc_ED100:", delete everything down to (But not including) this chunk of code.

    Code (Text):
    1. ; --------------------------------------------------------------------
    2. ; Nemesis compressed art (20 blocks)
    3. ; Buzzer's fireball
    4. ArtNem_Buzzer_Fireball: BINCLUDE    "art/nemesis/Fireball 1 (Buzzer).bin"
    5. ; --------------------------------------------------------------------
    That is art used in the game, so obviously we don't want that to get deleted.

    Right above if, you will also see this line:

    Code (Text):
    1.     cnop -Size_of_DAC_samples, $8000
    You need to delete that too.

    Finally, search for sub_EC000, or "SoundDriverLoad", which will look like this:

    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Subroutine to load the sound driver
    3. ; ---------------------------------------------------------------------------
    4. ; sub_EC000:
    5. SoundDriverLoad:
    6.     move    sr,-(sp)
    7.     movem.l d0-a6,-(sp)
    8.     move    #$2700,sr
    9.     lea (Z80_Bus_Request).l,a3
    10.     lea (Z80_Reset).l,a2
    11.     moveq   #0,d2
    12.     move.w  #$100,d1
    13.     move.w  d1,(a3) ; get Z80 bus
    14.     move.w  d1,(a2) ; release Z80 reset (was held high by console on startup)
    15. -   btst    d2,(a3)
    16.     bne.s   -   ; wait until the 68000 has the bus
    17.     jsr DecompressSoundDriver(pc)
    18.     btst    #0,(VDP_control_port+1).l   ; check video mode
    19.     sne (Z80_RAM+zPalModeByte).l    ; set if PAL
    20.     move.w  d2,(a2) ; hold Z80 reset
    21.     move.w  d2,(a3) ; release Z80 bus
    22.     moveq   #$E6,d0
    23. -   dbf d0,-    ; wait for 2,314 cycles
    24.     move.w  d1,(a2) ; release Z80 reset
    25.     movem.l (sp)+,d0-a6
    26.     move    (sp)+,sr
    27.     rts
    Delete the whole thing, as it will now do nothing but cause an error.

    Step 3 - Replace a bunch of stuff.
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------
    Search for the routine VintRet (Search for "VintRet:"), and you'll have something like this:

    Code (Text):
    1. VintRet:
    2.     addq.l  #1,(Vint_runcount).w
    3.     movem.l (sp)+,d0-a6
    4.     rte
    Replace it with this:

    Code (Text):
    1. VintRet:
    2.     jsr Init_Sonic1_Sound_Driver    ; init Sonic 1 sound driver
    3.     addq.l  #1,(Vint_runcount).w
    4.     movem.l (sp)+,d0-a6
    5.     rte
    Next, go to JmpTo_SoundDriverLoad, and find all of this:

    Code (Text):
    1. JmpTo_SoundDriverLoad
    2.  
    3.     nop
    4.  
    5.     jmp (SoundDriverLoad).l
    6. ; End of function JmpTo_SoundDriverLoad
    7.  
    8. ; ===========================================================================
    9.  
    10. ; unused mostly-leftover subroutine to load the sound driver
    11.  
    12. ; SoundDriverLoadS1:
    13.     move.w  #$100,(Z80_Bus_Request).l ; stop the Z80
    14.     move.w  #$100,(Z80_Reset).l; reset the Z80
    15.     lea (Z80_RAM).l,a1
    16.     move.b  #$F3,(a1)+
    17.     move.b  #$F3,(a1)+
    18.     move.b  #$C3,(a1)+
    19.     move.b  #0,(a1)+
    20.     move.b  #0,(a1)+
    21.     move.w  #0,(Z80_Reset).l
    22.     nop
    23.     nop
    24.     nop
    25.     nop
    26.     move.w  #$100,(Z80_Reset).l ; reset the Z80
    27.     move.w  #0,(Z80_Bus_Request).l ; start the Z80
    28.     rts
    and replace it like this:

    Code (Text):
    1. JmpTo_SoundDriverLoad
    2.     move.w  #$100,(Z80_Bus_Request).l ; stop the Z80
    3.     move.w  #$100,(Z80_Reset).l ; reset the Z80
    4.     lea (Kos_Z80).l,a0
    5.     lea (Z80_RAM).l,a1
    6.     bsr.w   KosDec
    7.     move.b  #$F3,(a1)+
    8.     move.b  #$F3,(a1)+
    9.     move.b  #$C3,(a1)+
    10.     move.b  #0,(a1)+
    11.     move.b  #0,(a1)+
    12.     move.w  #0,(Z80_Reset).l
    13.     nop
    14.     nop
    15.     nop
    16.     nop
    17.     move.w  #$100,(Z80_Reset).l ; reset the Z80
    18.     move.w  #0,(Z80_Bus_Request).l ; start the Z80
    19.     rts
    Next, find PlayMusic, which should look like this this:

    Code (Text):
    1. ; sub_135E:
    2. PlayMusic:
    3.     tst.b   (Music_to_play).w
    4.     bne.s   +
    5.     move.b  d0,(Music_to_play).w
    6.     rts
    7. +
    8.     move.b  d0,(Music_to_play_2).w
    9.     rts
    10. ; End of function PlayMusic
    And replace it with this:
    Code (Text):
    1. ; sub_135E:
    2. PlayMusic:
    3. ;   tst.b   ($FFFFFFE0).w
    4. ;   bne.s   +
    5. ;   move.b  d0,($FFFFFFE0).w
    6.     move.b  d0,($FFFFF00A).w
    7.     rts
    8. +
    9.     move.b  d0,($FFFFF00A).w
    10.     rts
    11. ; End of function PlayMusic
    Right beneath that should be PlaySound. Replace PlaySound with this:
    Code (Text):
    1. ; sub_1370
    2. PlaySound:
    3.     move.b  d0,($FFFFF00B).w
    4.     rts
    5. ; End of function PlaySound
    Now we need to change PlaySoundStereo, which should be right beath PlaySound.
    Replace it with this:
    Code (Text):
    1. ; sub_1376:
    2. PlaySoundStereo:
    3.     bra.s   PlayMusic   ; skip over routine (For S1 driver)
    4.     move.b  d0,(SFX_to_play_2).w
    5.     rts
    6. ; End of function PlaySoundStereo
    Now PlaySoundLocal is the next thing to edit, and again, it should be right below PlaySoundStereo.
    Replace it with this:
    Code (Text):
    1. ; sub_137C:
    2. PlaySoundLocal:
    3.     tst.b   render_flags(a0)
    4.     bpl.s   +
    5.     move.b  d0,($FFFFF00B).w
    6. +
    7.     rts
    Below this is the routine PauseGame. Rather than replacing that entire routine, we are simply going to find this:

    Code (Text):
    1. +
    2.     move.w  #1,(Game_paused).w  ; freeze time
    3.     move.b  #MusID_Pause,(Music_to_play).w  ; pause music
    And replace it with this:

    Code (Text):
    1. +
    2.     move.w  #1,(Game_paused).w  ; freeze time
    3.     move.b  #1,($FFFFF003).w    ; pause music
    Now go to Pause_Resume, which should look like this:

    Code (Text):
    1. ; loc_13F2:
    2. Pause_Resume:
    3.     move.b  #MusID_Unpause,(Music_to_play).w
    Replace it with this:

    Code (Text):
    1. ; loc_13F2:
    2. Pause_Resume:
    3.     move.b  #$80,($FFFFF003).w
    Now, find Pause_SlowMo, which should be this:

    Code (Text):
    1. ; loc_1400:
    2. Pause_SlowMo:
    3.     move.w  #1,(Game_paused).w
    4.     move.b
    5.     #MusID_Unpause,(Music_to_play).w
    6.     rts
    Replace it with the following:

    Code (Text):
    1. ; loc_1400:
    2. Pause_SlowMo:
    3.     move.w  #1,(Game_paused).w
    4.     move.b  #1,($FFFFF003).w
    5.     rts
    Next, find SpecialStage_Unpause, which should be this:

    Code (Text):
    1. ; loc_541A:
    2. SpecialStage_Unpause:
    3.     move.b  #MusID_Unpause,(Music_to_play).w
    4.     move.b  #8,(Vint_routine).w
    5.     bra.w   WaitForVint
    And replace it with this:

    Code (Text):
    1. ; loc_541A:
    2. SpecialStage_Unpause:
    3.     move.b  #1,($FFFFF003).w
    4.     move.b  #8,(Vint_routine).w
    5.     bra.w   WaitForVint
    Finally, we're going to do something that will clean up some RAM for us later in the guide.
    Do a search and replace (Usually CTRL+H) for "Underwater_palette_2". Replace all with "Underwater_palette".
    I don't know why the game used two different section for underwater palettes, but I've done this change in my hack and it did no harm.

    We're done with the first part of this guide! Try to build your Rom, and you'll get some errors! Fun!
    Next up, we'll be fixing these errors.

    Step 4 - Break it until it's fixed!
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------
    If you look at the log, you'll see a lot of errors like this one:

    > > >Sonic 2 Clone Driver.asm(42): error: unknown opcode
    > > > INCBIN
    > > > PSG7: incbin sound\psg7.bin

    Luckily, this is a simple fix. Open up Sonic 2 Clone Driver.asm, anf find and replace (CRTL+H usually) all instances of "INCBIN" with "BINCLUDE" (Without the quotes, obviously).

    Now repeat the process, replacing all intances of "@loc" with "Lloc". The HG dissasembly does not like local routines, so this converts them into normal routines to avoid errors.

    Save the file, and compile the ROM again. I got 437 errors, and of course, they need to be fixed as well.

    On the bright side, you can close s2.asm and Sonic 2 Clone Driver.asn, they are all fixed.

    Step 5 - Strippers
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Re-Open s2.sounddriver.asm, because we need to strip it down even more.

    Find zDACPtrTbl, and delete everything down to the line "idstart := 81h"

    Go to "zBankSwitchToMusic:", and delete the contents of that routine.(Everything between "zBankSwitchToMusic:" and "ret"
    Go to "zUpdateDAC:" and again delete everything down to "ret".

    Now find this line:

    Code (Text):
    1. ensure1byteoffset macro maxsize
    Delete everything between that and endm, but leave those two lines, otherwise you will get errors.

    If you build the ROM now, you will get 393 errors, but almost all of these are duplicates or fixed just by fixing another.
    Don't close s2.sounddriver.asm just yet, we'll be stripping more content from that later. Right now however, we're going to fix the bulk of these errors.

    Step 6 - Identity Crisis
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Open s2.constants.asm. 393 is a lot of errors, but all it takes to fix them is a copy+paste job for you.

    Find the line "; Music IDs". You'll see this:

    Code (Text):
    1. ; Music IDs
    2. offset :=   zMasterPlaylist
    3. ptrsize :=  1
    4. idstart :=  $81
    5. ; $80 is reserved for silence, so if you make idstart $80 or less,
    6. ; you may need to insert a dummy zMusIDPtr in the $80 slot
    delete everything from there down to "MusID__End = id(zMusIDPtr__End) ; A0", and paste the following where it used to be:

    Code (Text):
    1. ; Music IDs
    2. offset :=   MusicIndex
    3. ptrsize :=  1
    4. idstart :=  $81
    5. ; $80 is reserved for silence, so if you make idstart $80 or less,
    6. ; you may need to insert a dummy zMusIDPtr in the $80 slot
    7.  
    8. MusID__First =          idstart
    9. MusID_2PResult =    $81
    10. MusID_EHZ =             $82
    11. MusID_MCZ_2P =          $83
    12. MusID_OOZ =             $84
    13. MusID_MTZ =             $85
    14. MusID_HTZ =             $86
    15. MusID_ARZ =             $87
    16. MusID_CNZ_2P =          $88
    17. MusID_CNZ =             $89
    18. MusID_DEZ =             $8A
    19. MusID_MCZ =             $8B
    20. MusID_EHZ_2P =          $8C
    21. MusID_SCZ =             $8D
    22. MusID_CPZ =             $8E
    23. MusID_WFZ =             $8F
    24. MusID_HPZ =             $90
    25. MusID_Options =         $91
    26. MusID_SpecStage =   $92
    27. MusID_Boss =            $93
    28. MusID_EndBoss =         $94
    29. MusID_Ending =          $95
    30. MusID_SuperSonic =  $96
    31. MusID_Invincible =  $97
    32. MusID_ExtraLife =   $98
    33. MusID_Title =           $99
    34. MusID_EndLevel =    $9A
    35. MusID_GameOver =    $9B
    36. MusID_Continue =    $9C
    37. MusID_Emerald =         $9D
    38. MusID_Credits =         $9E
    39. MusID_Countdown =   $9F
    40. MusID__End   =      $A0
    The music is all fixed, now all that's left is the sound effects:

    Find the line "; Sound IDs", and delete everything down to the line "; Special sound IDs". Leve the special IDs alone.

    In place of the text you deleted, just paste this:

    Code (Text):
    1. ; Sound IDs
    2. offset :=   SoundIndex
    3. ptrsize :=  2
    4. idstart :=  $A0
    5.  
    6. SndID__First = idstart
    7. SndID_Jump =                    $A0             ; A0
    8. SndID_Checkpoint =          $A1             ; A1
    9. SndID_SpikeSwitch =         $A2             ; A2
    10. SndID_Hurt =                    $A3             ; A3
    11. SndID_Skidding =            $A4             ; A4
    12. SndID_BlockPush =           $A5             ; A5
    13. SndID_HurtBySpikes =        $A6     ; A6
    14. SndID_Sparkle =             $A7
    15. SndID_Beep =                $A8
    16. SndID_Bwoop =               $A9
    17. SndID_Splash =              $AA
    18. SndID_Swish =               $AB
    19. SndID_BossHit =             $AC
    20. SndID_InhalingBubble =      $AD
    21. SndID_ArrowFiring =         $AE
    22. SndID_LavaBall =            $AE
    23. SndID_Shield =              $Af
    24. SndID_LaserBeam =           $B0
    25. SndID_Zap =                 $B1
    26. SndID_Drown =               $B2
    27. SndID_FireBurn =            $B3
    28. SndID_Bumper =              $B4
    29. SndID_Ring =                $B5     ; B5
    30. SndID_RingRight =           $B5
    31. SndID_SpikesMove =          $B6
    32. SndID_Rumbling =            $B7
    33. SndID_Smash =               $B9
    34. SndID_DoorSlam =            $BB
    35. SndID_SpindashRelease =     $BC     ; BC
    36. SndID_Hammer =              $BD
    37. SndID_Roll =                $BE
    38. SndID_ContinueJingle =      $BF
    39. SndID_CasinoBonus =         $C0
    40. SndID_Explosion =           $C1
    41. SndID_WaterWarning =        $C2
    42. SndID_EnterGiantRing =      $C3
    43. SndID_BossExplosion =       $C4
    44. SndID_TallyEnd =            $C5
    45. SndID_RingSpill =           $C6
    46. SndID_Flamethrower =        $C8
    47. SndID_Bonus =               $C9
    48. SndID_SpecStageEntry =      $CA
    49. SndID_SlowSmash =           $CB
    50. SndID_Spring =              $CC
    51. SndID_Blip =                $CD
    52. SndID_RingLeft =            $B5
    53. SndID_Signpost =            $CF
    54. SndID_CNZBossZap =          $D0
    55. SndID_Signpost2P =          $D3
    56. SndID_OOZLidPop =               $D4
    57. SndID_SlidingSpike =        $D5
    58. SndID_CNZElevator =         $D6
    59. SndID_PlatformKnock =       $D7
    60. SndID_BonusBumper =         $D8
    61. SndID_LargeBumper =         $D9
    62. SndID_Gloop =               $DA
    63. SndID_PreArrowFiring =      $DB
    64. SndID_Fire =                $DC
    65. SndID_ArrowStick =          $DD
    66. SndID_Helicopter =          $DE
    67. SndID_SuperTransform =      $DF
    68. SndID_SpindashRev =         $E0
    69. SndID_Rumbling2 =           $E1
    70. SndID_CNZLaunch =           $E2
    71. SndID_Flipper =             $E3
    72. SndID_HTZLiftClick =        $E4
    73. SndID_Leaves =              $E5
    74. SndID_MegaMackDrop =        $E6
    75. SndID_DrawbridgeMove =      $E7
    76. SndID_QuickDoorSlam =       $E8
    77. SndID_DrawbridgeDown =      $E9
    78. SndID_LaserBurst =          $EA
    79. SndID_Scatter =             $EB
    80. SndID_LaserFloor =          $EB
    81. SndID_Teleport =            $EC
    82. SndID_Error =               $ED
    83. SndID_MechaSonicBuzz =      $EE
    84. SndID_LargeLaser =          $EF
    85. SndID_OilSlide =            $F0
    86. SndID__End  =           $F7
    Step 7 - I am Error
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Now we are going back to s2.sounddriver.asm.
    There are 4 more errors here.
    As before, we're going to solve this by simply emptying out the relavent routines. We can't just delete stuff because a few things in it are still going to be referenced.
    So the first Routine to clean out is zDACAfterDur. change that and remove zloc_22A inside it so it looks like this:

    Code (Text):
    1. zDACAfterDur:
    2.     ret
    There is one more routine to empty. That routine is zloc_78E, or zBGMLoad. Starting at this line:

    Code (Text):
    1. zBGMLoad:
    delete everything down to here:

    Code (Text):
    1.     ; End of DAC/FM init, begin PSG init
    And there you have it! Close s2.sounddriver.asm, Build you ROM and test it!

    Additional Step
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Uh-oh! if you've played up to Chemical Plant Zone Act 2, you'll notice the driver crashes on that level!

    This is because of water. In Sonic 2, the underwater palettes are stored in a section of RAM that is now used by the sound driver, because it's based on Sonic 1's sound driver.
    What we need to do now is relocate the water palette table in RAM, so the Sound Driver can do what it likes. I am going to assume you haven't modified the RAM allocation in your hack here, and go step by step. If you have modifying the RAM in your game, you are probably on your own.

    Let's go back to s2.constants.asm, and find these lines:

    Code (Text):
    1. Underwater_palette_2:       ds.w palette_line_size  ; not sure what it's used for but it's only used when there's water
    2. Underwater_palette_2_line2: ds.w palette_line_size
    3. Underwater_palette_2_line3: ds.w palette_line_size
    4. Underwater_palette_2_line4: ds.w palette_line_size
    5.  
    6. Underwater_palette:     ds.w palette_line_size  ; main palette for underwater parts of the screen
    7. Underwater_palette_line2:   ds.w palette_line_size
    8. Underwater_palette_line3:   ds.w palette_line_size
    9. Underwater_palette_line4:   ds.w palette_line_size
    10.  
    11.                 ds.b    $500    ; $FFFFF100-$FFFFF5FF ; unused, leftover from the Sonic 1 sound driver (and used by it when you port it to Sonic 2)
    12.  
    The last four lines before the ds.b $500 are used by the sound driver now, in addition to the 500 that is labeled as such.

    Replace all of the above lines with this:

    Code (Text):
    1.             ds.b  $100  ; Sonic 1 Sound Driver
    2.                     ds.b    $500    ; Sonic 1 Sound Driver
    After doing that, you will need to find at least $80 free bytes in RAM (besides the space we just put in)
    Fortunately, there is an area of RAM that has $C0 free bytes, and that is where the four lines we lost will go. Search for this:

    Code (Text):
    1. CNZ_saucer_data:
    And you will see this:

    Code (Text):
    1. CNZ_saucer_data:        ds.b    $40 ; the number of saucer bumpers in a group which have been destroyed. Used to decide when to give 500 points instead of 10
    2.                 ds.b    $C0 ; $FFFFE740-$FFFFE7FF ; unused as far as I can tell
    3. Ring_Positions:         ds.b    $600
    Replace it with this:

    Code (Text):
    1. CNZ_saucer_data:        ds.b    $40 ; the number of saucer bumpers in a group which have been destroyed. Used to decide when to give 500 points instead of 10
    2. Underwater_palette:     ds.w palette_line_size  ; main palette for underwater parts of the screen
    3. Underwater_palette_line2:   ds.w palette_line_size
    4. Underwater_palette_line3:   ds.w palette_line_size
    5. Underwater_palette_line4:   ds.w palette_line_size
    6.                 ds.b    $40 ; $FFFFE740-$FFFFE7FF ; unused as far as I can tell
    7. Ring_Positions:         ds.b    $600
    Build it, and test!

    The sega sound will be glitched up, and you can fix it by following this link. Everything that needs to be fixed will be in "Sonic 2 Clone Driver.asm".
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Credits
    Varion Icaria - Puto's sound driver port.
    Esrael - Tweakers driver port, plus fixes for things broken in Puto's port, such as hanging on the title card. Extra thanks for fixing the Sega sound.
    Puto - Fixes for underwater palette stuff, as well as special stage ring stuff, and various other fixes.
    StephenUK - Hints on how to fix the underwater stuff.
    drx - Hacking CulT's VDP calculator.
    Tweaker - Wrote the orignal guide to port Sonic 1's sound driver into Sonic 2.
    ValleyBell - lots of miscallanious help to get this to work, as well as worked on the Sonic 2 Clone Driver.
    ShadowsofYesterday - Telling me the fix for the SEGA sound.
    Caverns4 - I wrote this guide!



    I'm posting this here because I wanted to get some input on improvements I can make, or changes I need to make before posting a How-To on the Wiki. If anyone has any suggestions or help, I would appreciate it very much. One other thing I wasnt cleared up is the credits - did I miss anyone?
     
  2. ShadowsofYesterday

    ShadowsofYesterday

    I have no idea what's going on. Member
    169
    0
    0
    Fort Wayne, IN
    Sonic and the Magic Hat
    Nice guide. Certain parts could use a bit more clarity, like the ds.b $100 thing near the end there (how many of those lines am I replacing with that? All of them, or just four?), but overall it makes something that's a pain in the neck much easier to do, and to my knowledge there isn't an existing guide of this out there.

    Liked, commented, and subscribed.

    Also, the "of" in my name isn't capitalized, but it's a common mistake.
     
  3. Caverns 4

    Caverns 4

    Member
    342
    0
    16
    Sanik Quest: Journey To The Right
    Alright, since it's been here a while with no response, I'm working off the assumption that everything is fine, and and I have posted the guide on the Wiki here:

    http://info.sonicretro.org/Port_the_Sonic_2_Clone_Sound_Driver_to_the_HG_version_of_Sonic_2

    I forgot the "SCHG How-To:" prefix, so I don't know if anyone is capable of editing page titles, but I would appreciate it. I thought is was added automatically to How-to's.

    Again though, if there are any other issues with this guide, feel free to let me know.
     
  4. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,551
    145
    43
    SonLVL
    Fixed.
     
  5. Caverns 4

    Caverns 4

    Member
    342
    0
    16
    Sanik Quest: Journey To The Right
    Thank you very much!

    There is one more thing I noticed.

    under the table for SCHG How-To Guide: Sonic the Hedgehog 2 (16-bit) atthe bottom of the page, my guide doesn't appear on there. It should be there under "Extending the Game". What's wrong?
     
  6. MainMemory

    MainMemory

    Kate the Wolf Tech Member
    4,551
    145
    43
    SonLVL
    It is there, it's the second item in the list.
     
  7. Caverns 4

    Caverns 4

    Member
    342
    0
    16
    Sanik Quest: Journey To The Right
    Odd, it doesn't show for me... Does a page not show in lists for the creator or something?
     
  8. Clownacy

    Clownacy

    Tech Member
    838
    79
    28
    Thanks for the guide, Caverns 4, I have been using it myself until recently, and I believe I have some useful information: while examining the original Sonic 1 sound driver guide for the Xenowhirl disassembly, I noticed that towards the end, the author mentioned removing the Sonic 2 sound driver, and I began thinking "Can the Clone Driver completely replace the original?" which pretty much translates to "Is there a way to just delete s2.sounddriver.asm without incurring several thousand errors?", unfortunately, the guide didn't specify how, leaving it to our imaginations. Now I can happily say that I have found a way, this eliminates the stripping detailed in your guide but doesn't fix any of the faults you mentioned, such as the rev-less spindash or another fault I had discovered: the music doesn't speed up correctly.

    I have, however, a fix for one two and *a* finding for the other. First though, is my method of porting the Clone Driver, the main benefit, as I mentioned, is the elimination of s2.soundriver.asm.
    —SETTING UP—
    As before, delete the contents of the sound folder and extract Sonic 2 Clone Driver.asm along with the new sound folder into your disassembly's main directory.

    Open s2.asm, s2.constants.asm, and Sonic 2 Clone Driver.asm in a suitable text editor.

    Switch to Sonic 2 Clone Driver.asm



    —CLEANING UP THE CLONE DRIVER—
    Now, I don't quite understand when or why this happened, but at the beginning of the Clone Driver's code, you can find a copy of a Sonic 1 sound driver compatible version of SoundDriverLoad, this causes that error Caverns 4 described when he said to delete the one in s2.asm. The copy found in Sonic 2 Clone Driver.asm didn't exist in the original release of the Clone Driver (the one with the faulty EC sound). Anyway, this version of SoundDriverLoad appears to work just fine if you use it instead of the one I'll bring up later, so make your choice, if you don't wish to use it, delete it, it's just wasted space otherwise.

    Now we need to remove some unneeded and potentially catastrophic code; depending on where you include the Clone Driver, this could create a colossal amount of symbol undefined errors among others.

    Scroll to the bottom of the Clone Driver's code and look for this:

    Code (ASM):
    1. EndofRom:
    2.         END


    Delete it.

    Explanation
    This is already defined in s2.asm, and unlike this one, it's actually at the appropriate location; at the end of the ROM. You can guess why this can cause such damage if left intact. Caverns 4's guide masked this by including the Clone Driver just before s2.asm's EndofRom.

    Finally, replace all instances of "incbin" with "BINCLUDE" and "@loc" with "Lloc".

    Explanation
    The Clone Driver's code was adapted for another compiler, making it incompatible with the AS compiler, which the HG disassembly uses, this fix simply makes it compatible.

    That's it for now. Switch to s2.asm



    —REPLACING THE Z80 DRIVER—
    Go to Snd_Driver and you'll see this:

    Code (ASM):
    1. Snd_Driver:
    2.     include "s2.sounddriver.asm" ; CPU Z80
    3.  
    4.     CPU 68000
    5.     padding off
    6.     listing off
    7.     supmode on
    8.     !org (Snd_Driver+Size_of_Snd_driver_guess) ; don't worry; I know what I'm doing
    9.  
    10.  
    11. ; loc_ED04C:
    12. Snd_Driver_End:


    Replace it with this:

    Code (ASM):
    1. Snd_Driver:
    2.     include "Sonic 2 Clone Driver.asm"
    3.  
    4.  
    5. ; loc_ED04C:
    6. Snd_Driver_End:


    Explanation
    We're replacing the reference to the Sonic 2 Z80 driver with one to the modified Sonic 1 68k driver, eliminating the former entirely, no stripping, no wasted space, none of the code within s2.sounddriver.asm will be compiled with the ROM. This will create errors, but those will be fixed. The lines beneath the include won't be needed any more as they're only needed if s2.sounddriver.asm is included, which it isn't.

    The following is quoted from Caverns 4's guide, with some modifications to make use of the HG's RAM labels.

    Back to originality, find sndDriverInput and look for these lines:

    Code (ASM):
    1.     lea (Z80_RAM+zComRange).l,a1 ; $A01B80
    2.     cmpi.b  #$80,8(a1)  ; If this (zReadyFlag) isn't $80, the driver is processing a previous sound request.
    3.     bne.s   loc_10C4    ; So we'll wait until at least the next frame before putting anything in there.


    Delete or comment them out.

    Explanation
    The code calls for zComRange, which doesn't exist any more. I have found no negative effects of removing this code.

    Search and replace "Underwater_palette_2" with "Underwater_palette".



    —THE REAL STRIPPERS—
    Search for "SndDAC_Start:" and above it you'll see this:

    Code (ASM):
    1.     cnop -Size_of_DAC_samples, $8000


    Delete it and everything from SndDAC_Start up to (and including) Mus_Continue.

    Explanation
    They're unneeded by this point, and will only take up space.

    Taking some cues from Caverns 4's guide again, find the routine Snd_Sega and above it you'll find this:

    Code (ASM):
    1.     cnop -Size_of_SEGA_sound, $8000


    Delete it and everything from there up to (but not including) "; end of 'ROM'". Cavern 4's idea of emptying the Snd_Sega routine won't be needed here. SoundIndex and sounds Sound20 - Sound70 are among the code deleted, which is good as it saves us having to find and delete them separately.

    Explanation
    Again, unused, unneeded, and just wastes space. Also, this code:

    Code (ASM):
    1.     if * > soundBankStart + $8000
    2.         fatal "soundBank must fit in $8000 bytes but was $\{*-soundBankStart}. Try moving something to the other bank."
    3.     else
    4.         ;message "soundBank has $\{$8000+soundBankStart-*} bytes free at end."
    5.     endif


    is also only needed if you kept the sounds, which we didn't, so it's been deleted too.

    Find SoundDriverLoad and delete the entire routine, you might as well since it's gonna become unused anyway.

    Now delete everything from DecompressSoundDriver to (and including) sub_EC0DE.

    Explanation
    The Kosinski compressed sound driver isn't here any more, so this is useless, this causes an error which can be fixed by doing so:

    Find

    Code (ASM):
    1.     shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic,movewZ80CompSize


    And just delete the last entry so you have this:

    Code (ASM):
    1.     shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic


    I know there's a warning about deleting entries, but we needn't worry.

    That's it for s2.asm. Switch to s2.constants.asm.



    —CONSTANT QUOTING—
    For the most part I'll be quoting Caverns 4 again with some table tweaks.
    In order to make the RAM labels we pointed to earlier work, we need to define them! Head back to the $600 bytes of free RAM and add a "Clone_Driver_RAM:" label before it, giving you this:

    Code (ASM):
    1. Clone_Driver_RAM:       ds.b    $600    ; leftover from the Sonic 1 sound driver (and used by it when you port it to Sonic 2)
    Now, save all and build, there should be no errors and have the Clone Driver working fully! I do not yet know if this works on real hardware, if anyone does, please do tell, I can confirm that this works on Fusion and MD.emu. Don't forget to apply the Sega sound fix and the fixes found below (if available).
    Here's the spindash rev fix.
    I have ported the code from here to be compatible with the new layout and compiler (credit to shobiz for original code):

    All of this code is in Sonic 2 Clone Driver.asm.

    First, find loc_71BC8, it should look like this:

    Code (ASM):
    1. loc_71BC8:
    2.         lea $40(a6),a5
    3.         tst.b   (a5)
    4.         bpl.s   loc_71BD4
    5.         jsr sub_71C4E(pc)


    Replace it with this:

    Code (ASM):
    1. loc_71BC8:
    2.         tst.b   (Spindash_Timer).w
    3.         beq.s   +
    4.         subq.b  #1,(Spindash_Timer).w
    5. +
    6.         lea $40(a6),a5
    7.         tst.b   (a5)        ; Is DAC track playing?
    8.         bpl.s   loc_71BD4   ; Branch if not
    9.         jsr sub_71C4E(pc)


    Now find Sound_E0plus, it should look like this:

    Code (ASM):
    1. Sound_E0plus:
    2.         cmpi.b  #$F8,d7
    3.         bge.s   Sound_ChkValue_OtherChecks
    4.         subi.b  #$E0,d7
    5.         bra.s   Sound_ChkValue_OtherChecks


    Replace it with this:

    Code (ASM):
    1. Sound_E0plus:
    2.         clr.b   (Spindash_LastSound_Flag).w
    3.         cmp.b   #$E0,d7     ; is this the Spin Dash sound?
    4.         bne.w   +++ ; if not, branch
    5.         move.w  d0,-(sp)
    6.         move.b  (Spindash_Pitch).w,d0   ; store extra frequency
    7.         tst.b   (Spindash_Timer).w  ; is the Spin Dash timer active?
    8.         bne.s   +       ; if it is, branch
    9.         move.b  #-1,d0      ; otherwise, reset frequency (becomes 0 on next line)
    10. +
    11.         addq.b  #1,d0
    12.         cmp.b   #$C,d0      ; has the limit been reached?
    13.         bcc.s   +       ; if it has, branch
    14.         move.b  d0,(Spindash_Pitch).w   ; otherwise, set new frequency
    15. +
    16.         move.b  #1,(Spindash_LastSound_Flag).w  ; set flag
    17.         move.b  #60,(Spindash_Timer).w  ; set timer
    18.         move.w  (sp)+,d0
    19. +
    20.         cmpi.b  #$F8,d7
    21.         bge.s   Sound_ChkValue_OtherChecks
    22.         subi.b  #$E0,d7
    23.         bra.s   Sound_ChkValue_OtherChecks


    Find Sound_A0toCF and look for this:

    Code (ASM):
    1.         tst.b   $24(a6)
    2.         bne.w   loc_722C6


    After it, add

    Code (ASM):
    1.         clr.b   (Spindash_LastSound_Flag).w


    Go to loc_7226E and replace

    Code (ASM):
    1.         movea.l dword_722EC(pc,d3.w),a5


    with

    Code (ASM):
    1.         lea dword_722EC(pc),a5
    2.         movea.l (a5,d3.w),a5


    Now find loc_72276 and replace

    Code (ASM):
    1.         move.w  (a1)+,8(a5)
    2.         move.b  #1,$E(a5)


    with

    Code (ASM):
    1.         move.w  (a1)+,8(a5)
    2.         tst.b   (Spindash_LastSound_Flag).w ; is the Spin Dash sound playing?
    3.         beq.s   +       ; if not, branch
    4.         move.w  d0,-(sp)
    5.         move.b  (Spindash_Pitch).w,d0
    6.         add.b   d0,8(a5)
    7.         move.w  (sp)+,d0
    8. +
    9.         move.b  #1,$E(a5)


    Now we need to declare some RAM variables, this shouldn't be too hard given that we're using the HG disassembly:

    Open s2.constants.asm and look for three of these (they don't have to be together):

    Code (ASM):
    1.                 ds.b    1   ; $FFFFXXXX ; seems unused


    And tack "Spindash_LastSound_Flag" before one of them, "Spindash_Pitch" before another, and "Spindash_Timer" before the last one, so you have these replacing them:

    Code (ASM):
    1. Spindash_LastSound_Flag:    ds.b    1   ; $FFFFXXXX ; seems unused
    2. Spindash_Pitch:         ds.b    1   ; $FFFFXXXX ; seems unused
    3. Spindash_Timer:         ds.b    1   ; $FFFFXXXX ; seems unused

    I'd recommend that you only use byte length values, for the sake of being efficient (after all, there is around 3C0 (excluding that leftover from the Sonic 1 sound driver) bytes of completely unused RAM floating about, most of which is in single separate bytes).

    For those that don't understand what I'm talking about, just find this:

    Code (ASM):
    1.                 ds.b    3   ; $FFFFEEE9-$FFFFEEEB ; seems unused


    And replace it with this:

    Code (ASM):
    1. Spindash_LastSound_Flag:    ds.b    1
    2. Spindash_Pitch:         ds.b    1
    3. Spindash_Timer:         ds.b    1


    That should do it.
    Fixing the PSGs.
    As Caverns 4 mentioned, certain PSG channels sound wrong, such as EHZ's. The reason? They use the wrong PSGs. PSG instruments? PSG voices? I'm not sure. For now I'll just call them "PSGs". I don't know why, but instead of extracting the 4 new PSGs from Sonic 2 and adding them to the Clone Driver, the makers simply changed all references to these PSGs to point to other available PSGs, and even then they missed a few. To my knowledge, the songs affected by this are 82 (EHZ), 83 (MCZ 2 player VS), 84 (OOZ), 8B (MCZ), 8C (EHZ 2 player VS), 92 (Special stage), 95 (Ending), and 9E (Credits). Give them a listen and compare them.

    So, fixing this will require that we find and add these new PSGs from s2.sounddriver.asm to Sonic 2 Clone Driver.asm, then use modified music file that use them.

    Open up s2.sounddriver.asm and head to zPSG_FlutterTbl, unlike the Clone Driver, the PSGs aren't BINCLUDEd or included, instead being a part of the main file. The first nine entries are the oh so familiar Sonic 1 PSGs, unmodified too. The next four are new, so we need to port (read: copy and paste) those.

    We're going to do this in a similar fashion to the ones already included in the Clone Driver; BINCLUDEd .bin files. To begin, just type them up into a hex editor, adding zeros before each single-digit value. For example, PSG 10 should look like this:
    00 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 02 02 02 02 02 02 02 02 02 02 03 03 03 03 03 03 03 03 03 03 04 80
    Then save each PSG to their own file, naming them "psg10.bin" through "psg13.bin" and placing them in the sound folder.

    Now, at the top of Sonic 2 Clone Driver.asm, you should be able to find this:

    Code (ASM):
    1. ; ---------------------------------------------------------------------------
    2. ; PSG instruments used in music
    3. ; ---------------------------------------------------------------------------
    4. PSG_Index:
    5.         dc.l PSG1, PSG2, PSG3
    6.         dc.l PSG4, PSG5, PSG6
    7.         dc.l PSG7, PSG8, PSG9
    8. PSG1:       BINCLUDE    sound\psg\psg1.bin
    9. PSG2:       BINCLUDE    sound\psg\psg2.bin
    10. PSG3:       BINCLUDE    sound\psg\psg3.bin
    11. PSG4:       BINCLUDE    sound\psg\psg4.bin
    12. PSG6:       BINCLUDE    sound\psg\psg6.bin
    13. PSG5:       BINCLUDE    sound\psg\psg5.bin
    14. PSG7:       BINCLUDE    sound\psg\psg7.bin
    15. PSG8:       BINCLUDE    sound\psg\psg8.bin
    16. PSG9:       BINCLUDE    sound\psg\psg9.bin


    Here we shall define our new PSGs. Add some BINCLUDEs pointing to the .bins and point the index to them. You should be left with this:

    Code (ASM):
    1. ; ---------------------------------------------------------------------------
    2. ; PSG instruments used in music
    3. ; ---------------------------------------------------------------------------
    4. PSG_Index:
    5.         dc.l PSG1, PSG2, PSG3
    6.         dc.l PSG4, PSG5, PSG6
    7.         dc.l PSG7, PSG8, PSG9
    8.         dc.l PSG10,PSG11,PSG12
    9.         dc.l PSG13
    10. PSG1:       BINCLUDE    sound\psg\psg1.bin
    11. PSG2:       BINCLUDE    sound\psg\psg2.bin
    12. PSG3:       BINCLUDE    sound\psg\psg3.bin
    13. PSG4:       BINCLUDE    sound\psg\psg4.bin
    14. PSG6:       BINCLUDE    sound\psg\psg6.bin
    15. PSG5:       BINCLUDE    sound\psg\psg5.bin
    16. PSG7:       BINCLUDE    sound\psg\psg7.bin
    17. PSG8:       BINCLUDE    sound\psg\psg8.bin
    18. PSG9:       BINCLUDE    sound\psg\psg9.bin
    19. PSG10:      BINCLUDE    sound\psg\psg10.bin
    20. PSG11:      BINCLUDE    sound\psg\psg11.bin
    21. PSG12:      BINCLUDE    sound\psg\psg12.bin
    22. PSG13:      BINCLUDE    sound\psg\psg13.bin


    That's the PSGs added, now to get the songs that use them, here are the already hacktastic music files hacked further to use the PSGs, link here.

    Sorry for the not being able to go into much depth with this part. I just reverse engineered an asm version of each song with the fixes added and applied the changes to the hex equivalents. Put these into your sound folder and overwrite if needed.
    Here's what (little) I have on the music speed up.
    The music speed up isn't as simple as I hoped it would be, I haven't gotten very far into this due to lack of interest (for now).

    Open up s2.sounddriver.asm and look for zSpedUpTempoTable, it's what you think it is. An equivalent table exists in the Clone Driver, but isn't changed from Sonic 1, it is labelled byte_71A94. The Sonic 1 sound driver is better annotated and documented in the Sonic 1 HG disassembly than it is in the Clone Driver, so I'd look there for further references. I applied the values found in zSpedUpTempoTable to byte_71A94 and had little results; the speed simply wasn't right, Emerald Hill Zone is definitely off, Casino Night sounded off too, both were WAY too slow, if anything, I don't think they changed at all. I haven't looked any further than that, sorry.
     
  9. ValleyBell

    ValleyBell

    Tech Member
    243
    14
    18
    researching SMPS sound drivers
    This reminds me, while helping someone to port the Clone Driver to Sonic 2 HG, I tried making a clean-as-possible port by myself. (I just forgot to post it.)
    The results were these notes: (copy-pasted from my .txt file)
    Code (Text):
    1. 1. remove sound directory
    2.    remove s2.sounddriver.asm
    3. 2. open s2.asm
    4.    remove everything from
    5.     ; Subroutine to load the sound driver
    6.    to
    7.     Mus_Continue:   BINCLUDE    "sound/music/Continue.bin"
    8.    This removes the routines SoundDriverLoad and DecompressSoundDriver.
    9.    Then remove everything from
    10.     cnop -Size_of_SEGA_sound, $8000
    11.    to the line above of
    12.     ; end of 'ROM'
    13.    Also remove movewZ80CompSize from the list of shared symbols (at the bottom of s2.asm).
    14.    Then remove the whole function sndDriverInput and all calls to it.
    15.    Finally comment this line out:
    16.     jmp (SoundDriverLoad).l
    17.    to magically remove some of the "addressing mode not allowed" errors.
    18. 3. open s2.constants.asm
    19.    Remove everthing from
    20.     ; Music IDs
    21.    to
    22.     SndID__End = ...
    23.    and replace them with Caverns 4's MusID and SndID lines.
    24.    Be sure to get rid of any "offset :=", "ptrsize :=", "idstart :=" and "... = idstart" lines.
    25. 4. Complile and test. You should now have a fully working (aside from the lack of sound) Sonic 2 ROM.
    26.  
    27. 5. open s2.constants.asm
    28.    Then search for Underwater_palette_2 and cut those 8 lines that start with Underwater_.
    29.    Now change line below, which is
    30.         ds.b    $500
    31.    to
    32.         ds.b    $600
    33.    
    34.    Now search for Normal_palette and paste the cut lines above of it.
    35.    The line above of the block you pasted should be
    36.         ds.b    $80 ; unused, but SAT buffer can spill over into this area when there are too many sprites on-screen
    37.    Remove it. and change the line directly above to
    38.     Sprite_Table:   ds.b    $200
    39.  
    40. 5. Unpack the Clone Driver and its files and folders into the root directory of the disassembly.
    41. 6. In s2.asm, right above of
    42.     ; end of 'ROM'
    43.    put
    44.         include "Sonic 2 Clone Driver.asm"
    45. 7. Reactivate the line
    46.         jmp (SoundDriverLoad).l
    47. 8. Open Sonic 2 Clone Driver.asm and replace all "incbin" with "binclude".
    48.    Then fix the @ labels by replacing "@loc" with "Lloc".
    49.    Finally, comment these 2 lines out:
    50.     EndofRom:
    51.         END
    52.    [It should compile after this step.]
    53. 9. Open s2.asm
    54.    Right after
    55.     VintRet:
    56.    insert
    57.         jsr Init_Sonic1_Sound_Driver
    58.    [Note: The correct name for this routine would be "Update_Sonic1_Sound_Driver", since it updates the sound driver and doesn't initialize it. Feel free to fix that.]
    59. 10. Replace the PlayMusic routine with this:
    60.     PlayMusic:
    61.         move.b  d0,($FFFFF00A).w
    62.         rts
    63. 11. Replace SFX_to_play and SFX_to_play_2 with $FFFFF00B.
    64. 12. Replace
    65.         move.b  #MusID_Pause,(Music_to_play).w  ; pause music
    66.     with
    67.         move.b  #1,($FFFFF003).w    ; pause music
    68.     and replace
    69.         move.b  #MusID_Unpause,(Music_to_play).w
    70.     with
    71.         move.b  #$80,($FFFFF003).w  ; resume music
    72. 13. Compile, test and enjoy a ROM of Sonic 2 with the Clone Driver.
    73.  
    74. 14. Oh, wait. Ouch - that SEGA sound is corrupted and sounds horrible. Let's fix that quickly.
    75.     Open Sonic 2 Clone Driver.asm and search for "SegaPCM:".
    76.     Now, replace
    77.             cnop $0, (((((*+$6978)>>$10)+$01)*$10000)-$6978)
    78.     SegaPCM:    binclude    sound\segapcm.bin
    79.             even
    80.     with
    81.             align $8000
    82.     SegaPCM:    binclude    sound\segapcm.bin
    83.     SegaPCM_End:
    84.     Yeah, most of them are cosmetic changes, but let's continue.
    85.    
    86.     Search for "PCM_Table:" and append this to the end of the table:
    87.         dc.l    $A00200, SegaPCM
    88.         dc.w    (SegaPCM_End-SegaPCM)/2
    89.         dc.b    $09, 0
    90.     Finally, go to "Sound_E1:" and replace
    91.         move.b  #$88,($A01FFF).l
    92.     with
    93.         move.b  #$88, d0
    94.         jsr Calculate_PCM
    95.         move.b  #$81, ($A01FFF).l   ; can't use #$88, because that one uses hardcoded offsets
    96.     Done. Yes, it can be that easy.
    97.  
    98.  
    99. Note: The word "replace" means "replace all occurrences of it".

    It should strip everything related to the S2 sound driver. (unless I missed something)
    And although it doesn't include the spindash fix, it includes a quick and easy fix for the SEGA sound issue.

    About the speed up table: The tempo algorithms between Sonic 1 and Sonic 2 are completely different, so you'll need to translate the tempo values.
    There are formulas to convert tempo value between any of the Sonic games on the wiki: SCHG:Music_Hacking/Pointer_and_Header_Format#SMPS_main_header

    btw: The SoundDriverLoad was probably added by me. But because I'm cleaning Sonic 2 of all sound code first and insert the Clone Driver then, this wasn't a problem for me.
    This has also the advantage, that it's easily possible to insert the Clone Driver into any other game. (You'd possibly need to port the KosDec, too.)