How to port the Sonic 1 sound driver to Sonic 2 (Hg disassembly adaptation)

Discussion in 'Tutorials Archive' started by ThomasThePencil, Mar 15, 2013.

Thread Status:
Not open for further replies.
  1. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    911
    Location:
    the united states. where else?
    So lately, I haven't really seen any music hacks in production. Sure, there are a few, such as Joenick69's Sonic 2: Raging Badniks Edition, but there aren't too many. So today, I'll be helping all you Hg people out there port the Sonic 1 sound driver to your hack.

    Here's a little table of contents for you:

    BOTH METHODS:

    Step 1: Porting the sound driver following the original guide

    MY METHOD:

    Step 2.1: Fixing the music ID problems

    Step 3.1: Deleting the music ID's since they're not needed anymore

    CRASH'S METHOD:

    Step 2.2: Replacing the music index in the sound driver

    Step 3.2: Repairing the music ID's to work with our new index

    Let's get started!

    Step 1: Porting the sound driver following the original guide

    First, we need to port the actual driver using the original guide. Link: http://info.sonicretro.org/SCHG_How-to:port_Sonic_1%27s_Sound_Driver_to_Sonic_2

    Once you've done that, move on to step 2.1 for my method, or step 2.2 for Crash's method.

    Step 2.1: Fixing the music ID problems

    This step is easy, but slightly time consuming. You must go through the whole of your ASM file (read: s2.asm) and replace every instance of a MusiD with its corresponding value. For example, suppose you have this:


    move.w #MusID_Boss,d0
    bsr.w JmpTo3_PlayMusic 

    You would look up the value in s2.constants.asm:


    MusID_Boss = id(zMusIDPtr_Boss) ; 93
    And you would replace MusID_Boss with $93. This does not need to be done for special things (read: MusID_StopSFX onward), since they are essentially their own thing (I'll get more into this later).

    Step 3.1: Deleting the music ID's since they're not needed anymore

    This bit is easy peasy spindash breezy (spindash breezy is my way of saying lemon squeezy). Take a look at this:


    ; Music IDs
    offset := zMasterPlaylist
    ptrsize := 1
    idstart := $81
    ; $80 is reserved for silence, so if you make idstart $80 or less,
    ; you may need to insert a dummy zMusIDPtr in the $80 slot

    MusID__First = idstart
    MusID_2PResult = id(zMusIDPtr_2PResult) ; 81 ; DELETE ME
    MusID_EHZ = id(zMusIDPtr_EHZ) ; 82 ; DELETE ME
    MusID_MCZ_2P = id(zMusIDPtr_MCZ_2P) ; 83 ; DELETE ME
    MusID_OOZ = id(zMusIDPtr_OOZ) ; 84 ; DELETE ME
    MusID_MTZ = id(zMusIDPtr_MTZ) ; 85 ; DELETE ME
    MusID_HTZ = id(zMusIDPtr_HTZ) ; 86 ; DELETE ME
    MusID_ARZ = id(zMusIDPtr_ARZ) ; 87 ; DELETE ME
    MusID_CNZ_2P = id(zMusIDPtr_CNZ_2P) ; 88 ; DELETE ME
    MusID_CNZ = id(zMusIDPtr_CNZ) ; 89 ; DELETE ME
    MusID_DEZ = id(zMusIDPtr_DEZ) ; 8A ; DELETE ME
    MusID_MCZ = id(zMusIDPtr_MCZ) ; 8B ; DELETE ME
    MusID_EHZ_2P = id(zMusIDPtr_EHZ_2P) ; 8C ; DELETE ME
    MusID_SCZ = id(zMusIDPtr_SCZ) ; 8D ; DELETE ME
    MusID_CPZ = id(zMusIDPtr_CPZ) ; 8E ; DELETE ME
    MusID_WFZ = id(zMusIDPtr_WFZ) ; 8F ; DELETE ME
    MusID_HPZ = id(zMusIDPtr_HPZ) ; 90 ; DELETE ME
    MusID_Options = id(zMusIDPtr_Options) ; 91 ; DELETE ME
    MusID_SpecStage = id(zMusIDPtr_SpecStage) ; 92 ; DELETE ME
    MusID_Boss = id(zMusIDPtr_Boss) ; 93 ; DELETE ME
    MusID_EndBoss = id(zMusIDPtr_EndBoss) ; 94 ; DELETE ME
    MusID_Ending = id(zMusIDPtr_Ending) ; 95 ; DELETE ME
    MusID_SuperSonic = id(zMusIDPtr_SuperSonic); 96 ; DELETE ME
    MusID_Invincible = id(zMusIDPtr_Invincible); 97 ; DELETE ME
    MusID_ExtraLife = id(zMusIDPtr_ExtraLife) ; 98 ; DELETE ME
    MusID_Title = id(zMusIDPtr_Title) ; 99 ; DELETE ME
    MusID_EndLevel = id(zMusIDPtr_EndLevel) ; 9A ; DELETE ME
    MusID_GameOver = id(zMusIDPtr_GameOver) ; 9B ; DELETE ME
    MusID_Continue = id(zMusIDPtr_Continue) ; 9C ; DELETE ME
    MusID_Emerald = id(zMusIDPtr_Emerald) ; 9D ; DELETE ME
    MusID_Credits = id(zMusIDPtr_Credits) ; 9E ; DELETE ME
    MusID_Countdown = id(zMusIDPtr_Countdown) ; 9F ; DELETE ME
    MusID__End = id(zMusIDPtr__End) ; A0 ; DELETE ME

    ; Sound IDs
    offset := SoundIndex
    ptrsize := 2
    idstart := $A0
    ; $80 is reserved for silence, so if you make idstart $80 or less,
    ; you may need to insert a dummy SndPtr in the $80 slot

    SndID__First = idstart
    SndID_Jump = id(SndPtr_Jump) ; A0
    SndID_Checkpoint = id(SndPtr_Checkpoint) ; A1
    SndID_SpikeSwitch = id(SndPtr_SpikeSwitch) ; A2
    SndID_Hurt = id(SndPtr_Hurt) ; A3
    SndID_Skidding = id(SndPtr_Skidding) ; A4
    SndID_BlockPush = id(SndPtr_BlockPush) ; A5
    SndID_HurtBySpikes = id(SndPtr_HurtBySpikes) ; A6
    SndID_Sparkle = id(SndPtr_Sparkle) ; A7
    SndID_Beep = id(SndPtr_Beep) ; A8
    SndID_Bwoop = id(SndPtr_Bwoop) ; A9
    SndID_Splash = id(SndPtr_Splash) ; AA
    SndID_Swish = id(SndPtr_Swish) ; AB
    SndID_BossHit = id(SndPtr_BossHit) ; AC
    SndID_InhalingBubble = id(SndPtr_InhalingBubble) ; AD
    SndID_ArrowFiring = id(SndPtr_ArrowFiring) ; AE
    SndID_LavaBall = id(SndPtr_LavaBall) ; AE
    SndID_Shield = id(SndPtr_Shield) ; AF
    SndID_LaserBeam = id(SndPtr_LaserBeam) ; B0
    SndID_Zap = id(SndPtr_Zap) ; B1
    SndID_Drown = id(SndPtr_Drown) ; B2
    SndID_FireBurn = id(SndPtr_FireBurn) ; B3
    SndID_Bumper = id(SndPtr_Bumper) ; B4
    SndID_Ring = id(SndPtr_Ring) ; B5
    SndID_RingRight = id(SndPtr_RingRight) ; B5
    SndID_SpikesMove = id(SndPtr_SpikesMove) ; B6
    SndID_Rumbling = id(SndPtr_Rumbling) ; B7
    SndID_Smash = id(SndPtr_Smash) ; B9
    SndID_DoorSlam = id(SndPtr_DoorSlam) ; BB
    SndID_SpindashRelease = id(SndPtr_SpindashRelease) ; BC
    SndID_Hammer = id(SndPtr_Hammer) ; BD
    SndID_Roll = id(SndPtr_Roll) ; BE
    SndID_ContinueJingle = id(SndPtr_ContinueJingle) ; BF
    SndID_CasinoBonus = id(SndPtr_CasinoBonus) ; C0
    SndID_Explosion = id(SndPtr_Explosion) ; C1
    SndID_WaterWarning = id(SndPtr_WaterWarning) ; C2
    SndID_EnterGiantRing = id(SndPtr_EnterGiantRing) ; C3
    SndID_BossExplosion = id(SndPtr_BossExplosion) ; C4
    SndID_TallyEnd = id(SndPtr_TallyEnd) ; C5
    SndID_RingSpill = id(SndPtr_RingSpill) ; C6
    SndID_Flamethrower = id(SndPtr_Flamethrower) ; C8
    SndID_Bonus = id(SndPtr_Bonus) ; C9
    SndID_SpecStageEntry = id(SndPtr_SpecStageEntry) ; CA
    SndID_SlowSmash = id(SndPtr_SlowSmash) ; CB
    SndID_Spring = id(SndPtr_Spring) ; CC
    SndID_Blip = id(SndPtr_Blip) ; CD
    SndID_RingLeft = id(SndPtr_RingLeft) ; CE
    SndID_Signpost = id(SndPtr_Signpost) ; CF
    SndID_CNZBossZap = id(SndPtr_CNZBossZap) ; D0
    SndID_Signpost2P = id(SndPtr_Signpost2P) ; D3
    SndID_OOZLidPop = id(SndPtr_OOZLidPop) ; D4
    SndID_SlidingSpike = id(SndPtr_SlidingSpike) ; D5
    SndID_CNZElevator = id(SndPtr_CNZElevator) ; D6
    SndID_PlatformKnock = id(SndPtr_PlatformKnock) ; D7
    SndID_BonusBumper = id(SndPtr_BonusBumper) ; D8
    SndID_LargeBumper = id(SndPtr_LargeBumper) ; D9
    SndID_Gloop = id(SndPtr_Gloop) ; DA
    SndID_PreArrowFiring = id(SndPtr_PreArrowFiring) ; DB
    SndID_Fire = id(SndPtr_Fire) ; DC
    SndID_ArrowStick = id(SndPtr_ArrowStick) ; DD
    SndID_Helicopter = id(SndPtr_Helicopter) ; DE
    SndID_SuperTransform = id(SndPtr_SuperTransform) ; DF
    SndID_SpindashRev = id(SndPtr_SpindashRev) ; E0
    SndID_Rumbling2 = id(SndPtr_Rumbling2) ; E1
    SndID_CNZLaunch = id(SndPtr_CNZLaunch) ; E2
    SndID_Flipper = id(SndPtr_Flipper) ; E3
    SndID_HTZLiftClick = id(SndPtr_HTZLiftClick) ; E4
    SndID_Leaves = id(SndPtr_Leaves) ; E5
    SndID_MegaMackDrop = id(SndPtr_MegaMackDrop) ; E6
    SndID_DrawbridgeMove = id(SndPtr_DrawbridgeMove) ; E7
    SndID_QuickDoorSlam = id(SndPtr_QuickDoorSlam) ; E8
    SndID_DrawbridgeDown = id(SndPtr_DrawbridgeDown) ; E9
    SndID_LaserBurst = id(SndPtr_LaserBurst) ; EA
    SndID_Scatter = id(SndPtr_Scatter) ; EB
    SndID_LaserFloor = id(SndPtr_LaserFloor) ; EB
    SndID_Teleport = id(SndPtr_Teleport) ; EC
    SndID_Error = id(SndPtr_Error) ; ED
    SndID_MechaSonicBuzz = id(SndPtr_MechaSonicBuzz) ; EE
    SndID_LargeLaser = id(SndPtr_LargeLaser) ; EF
    SndID_OilSlide = id(SndPtr_OilSlide) ; F0
    SndID__End = id(SndPtr__End) ; F1
    if MOMPASS == 2
    if SndID__End > MusID_StopSFX
    fatal "You have too many SndPtrs. SndID__End (${SndID__End}) can't exceed MusID_StopSFX (${MusID_StopSFX})."
    endif
    endif

    ; Special sound IDs

    MusID_StopSFX = $78+$80 ; F8
    MusID_FadeOut = $79+$80 ; F9
    SndID_SegaSound = $7A+$80 ; FA
    MusID_SpeedUp = $7B+$80 ; FB
    MusID_SlowDown = $7C+$80 ; FC
    MusID_Stop = $7D+$80 ; FD
    MusID_Pause = $7E+$80 ; FE
    MusID_Unpause = $7F+$80 ; FF

    All lines that say DELETE ME, well, it's self-explanatory at this point. Delete 'em, as they are no longer required.

    Step 2.2: Replacing the music index in the sound driver

    This is not as time-consuming as the first method, as all you're doing is replacing a list and repairing the music ID's to work with that list.

    First, let's fix the music index. Head into your Sonic 1 sound driver file and go to "MusicIndex:" (no quotes). It should look like this:


    MusicIndex: dc.l Music81, Music82
    dc.l Music83, Music84
    dc.l Music85, Music86
    dc.l Music87, Music88
    dc.l Music89, Music8A
    dc.l Music8B, Music8C
    dc.l Music8D, Music8E
    dc.l Music8F, Music90
    dc.l Music91, Music92
    dc.l Music93


    As you can see, this is only pointing directly to the music, one of the reasons why this needs fixing, as the MusID's can no longer read their music. So replace it with this:


    MusicIndex:
    ptr_mus81: dc.l Music81
    ptr_mus82: dc.l Music82
    ptr_mus83: dc.l Music83
    ptr_mus84: dc.l Music84
    ptr_mus85: dc.l Music85
    ptr_mus86: dc.l Music86
    ptr_mus87: dc.l Music87
    ptr_mus88: dc.l Music88
    ptr_mus89: dc.l Music89
    ptr_mus8A: dc.l Music8A
    ptr_mus8B: dc.l Music8B
    ptr_mus8C: dc.l Music8C
    ptr_mus8D: dc.l Music8D
    ptr_mus8E: dc.l Music8E
    ptr_mus8F: dc.l Music8F
    ptr_mus90: dc.l Music90
    ptr_mus91: dc.l Music91
    ptr_mus92: dc.l Music92
    ptr_mus93: dc.l Music93
    Step 3.2: Repairing the music ID's to work with our new index

    Next, go to s2.constants.asm. Head to the MusID list. It should look like this:




    ; Music IDs
    offset := zMasterPlaylist
    ptrsize := 1
    idstart := $81
    ; $80 is reserved for silence, so if you make idstart $80 or less,
    ; you may need to insert a dummy zMusIDPtr in the $80 slot

    MusID__First = idstart
    MusID_2PResult = id(zMusIDPtr_2PResult) ; 81
    MusID_EHZ = id(zMusIDPtr_EHZ) ; 82
    MusID_MCZ_2P = id(zMusIDPtr_MCZ_2P) ; 83
    MusID_OOZ = id(zMusIDPtr_OOZ) ; 84
    MusID_MTZ = id(zMusIDPtr_MTZ) ; 85
    MusID_HTZ = id(zMusIDPtr_HTZ) ; 86
    MusID_ARZ = id(zMusIDPtr_ARZ) ; 87
    MusID_CNZ_2P = id(zMusIDPtr_CNZ_2P) ; 88
    MusID_CNZ = id(zMusIDPtr_CNZ) ; 89
    MusID_DEZ = id(zMusIDPtr_DEZ) ; 8A
    MusID_MCZ = id(zMusIDPtr_MCZ) ; 8B
    MusID_EHZ_2P = id(zMusIDPtr_EHZ_2P) ; 8C
    MusID_SCZ = id(zMusIDPtr_SCZ) ; 8D
    MusID_CPZ = id(zMusIDPtr_CPZ) ; 8E
    MusID_WFZ = id(zMusIDPtr_WFZ) ; 8F
    MusID_HPZ = id(zMusIDPtr_HPZ) ; 90
    MusID_Options = id(zMusIDPtr_Options) ; 91
    MusID_SpecStage = id(zMusIDPtr_SpecStage) ; 92
    MusID_Boss = id(zMusIDPtr_Boss) ; 93
    MusID_EndBoss = id(zMusIDPtr_EndBoss) ; 94
    MusID_Ending = id(zMusIDPtr_Ending) ; 95
    MusID_SuperSonic = id(zMusIDPtr_SuperSonic); 96
    MusID_Invincible = id(zMusIDPtr_Invincible); 97
    MusID_ExtraLife = id(zMusIDPtr_ExtraLife) ; 98
    MusID_Title = id(zMusIDPtr_Title) ; 99
    MusID_EndLevel = id(zMusIDPtr_EndLevel) ; 9A
    MusID_GameOver = id(zMusIDPtr_GameOver) ; 9B
    MusID_Continue = id(zMusIDPtr_Continue) ; 9C
    MusID_Emerald = id(zMusIDPtr_Emerald) ; 9D
    MusID_Credits = id(zMusIDPtr_Credits) ; 9E
    MusID_Countdown = id(zMusIDPtr_Countdown) ; 9F
    MusID__End = id(zMusIDPtr__End) ; A0


    Change it to this:




    ; Music IDs
    offset := MusicIndex
    ptrsize := 1
    idstart := $81
    ; $80 is reserved for silence, so if you make idstart $80 or less,
    ; you may need to insert a dummy zMusIDPtr in the $80 slot

    MusID_2PResult equ ((ptr_mus81-MusicIndex)/4)+$81 ; 81
    MusID_EHZ equ ((ptr_mus82-MusicIndex)/4)+$81 ; 82
    MusID_MCZ_2P equ ((ptr_mus83-MusicIndex)/4)+$81 ; 83
    MusID_OOZ equ ((ptr_mus84-MusicIndex)/4)+$81 ; 84
    MusID_MTZ equ ((ptr_mus85-MusicIndex)/4)+$81 ; 85
    MusID_HTZ equ ((ptr_mus86-MusicIndex)/4)+$81 ; 86
    MusID_ARZ equ ((ptr_mus87-MusicIndex)/4)+$81 ; 87
    MusID_CNZ_2P equ ((ptr_mus88-MusicIndex)/4)+$81 ; 88
    MusID_CNZ equ ((ptr_mus89-MusicIndex)/4)+$81 ; 89
    MusID_DEZ equ ((ptr_mus8A-MusicIndex)/4)+$81 ; 8A
    MusID_MCZ equ ((ptr_mus8B-MusicIndex)/4)+$81 ; 8B
    MusID_EHZ_2P equ ((ptr_mus8C-MusicIndex)/4)+$81 ; 8C
    MusID_SCZ equ ((ptr_mus8D-MusicIndex)/4)+$81 ; 8D
    MusID_CPZ equ ((ptr_mus8E-MusicIndex)/4)+$81 ; 8E
    MusID_WFZ equ ((ptr_mus8F-MusicIndex)/4)+$81 ; 8F
    MusID_HPZ equ ((ptr_mus90-MusicIndex)/4)+$81 ; 90
    MusID_Options equ ((ptr_mus91-MusicIndex)/4)+$81 ; 91
    MusID_SpecStage equ ((ptr_mus92-MusicIndex)/4)+$81 ; 92
    MusID_Boss equ ((ptr_mus93-MusicIndex)/4)+$81 ; 93
    MusID_EndBoss equ ((ptr_mus94-MusicIndex)/4)+$81 ; 94
    MusID_Ending equ ((ptr_mus95-MusicIndex)/4)+$81 ; 95
    MusID_SuperSonic equ ((ptr_mus96-MusicIndex)/4)+$81 ; 96
    MusID_Invincible equ ((ptr_mus97-MusicIndex)/4)+$81 ; 97
    MusID_ExtraLife equ ((ptr_mus98-MusicIndex)/4)+$81 ; 98
    MusID_Title equ ((ptr_mus99-MusicIndex)/4)+$81 ; 99
    MusID_EndLevel equ ((ptr_mus9A-MusicIndex)/4)+$81 ; 9A
    MusID_GameOver equ ((ptr_mus9B-MusicIndex)/4)+$81 ; 9B
    MusID_Continue equ ((ptr_mus9C-MusicIndex)/4)+$81 ; 9C
    MusID_Emerald equ ((ptr_mus9D-MusicIndex)/4)+$81 ; 9D
    MusID_Credits equ ((ptr_mus9E-MusicIndex)/4)+$81 ; 9E
    MusID_Countdown equ ((ptr_mus9F-MusicIndex)/4)+$81 ; 9F


    Do the same thing with the sound index and sound ID's.

    Final Note

    Just one last thing before you go: certain sound effects and music from Sonic 2 WILL be missing regardless of which method you use, and you WILL need to add the music and sound effects in if you still want them in-game. To add music, simply tack it onto the end of MusicIndex, and if it's a sound, put it at the end of SoundIndex instead.

    Credits

    Tweaker - For the original guide

    Myself - For the original Hg method

    Crash - For the alternate method which makes things a lot easier :D
     
    Last edited by a moderator: Mar 17, 2013
  2. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    911
    Location:
    the united states. where else?
    In case nobody has noticed, this is my first actual ASM edit all by myself!

    Jokes aside, I have opened the topic for discussion of this tutorial and how I could improve upon it. It's a really big step for me, figuring out how to adapt something as big as this to the Hg disassembly. Anyone want to start the discussion?
     
     
    Last edited by a moderator: Mar 16, 2013
  3. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    911
    Location:
    the united states. where else?
    Note that I have added a second method to the guide. That method is Crash's method, and in all honesty, it seems to be faster than my method, so I decided to add it in here.
     
    Last edited by a moderator: Mar 17, 2013
Thread Status:
Not open for further replies.