So one day, about a year ago, I decided to try to port flamewing's S3K Sound driver into Sonic 2. I had originally planned to release this quite a while ago, but have been real busy with real life. This guide was written with the HG version of the Sonic 2 disassembly in mind, however, it should work with the old and ancient Xenowhirl disassembly as well. For HG users, this guide will fix the sound effects/music so it uses all Sonic 2 sound effects and music. Unfortunately, for Xeno users, you will have to manually go through and fix all the sound/music ids by hand. Anyway, on to the guide: QuotePorting Flamewing's S3K Sound Driver into Sonic the Hedgehog 2 PREPARING FOR THE SOUND DRIVER 1. Go to - VintSub0: and delete these three lines Code (ASM): stopZ80 ; stop the Z80 bsr.w sndDriverInput ; give input to the sound driver startZ80 You should have something that looks like this: Code (ASM): VintSub0: cmpi.b #GameModeID_TitleCard|GameModeID_Demo,(Game_Mode).w ; pre-level Demo Mode? beq.s loc_4C4 cmpi.b #GameModeID_TitleCard|GameModeID_Level,(Game_Mode).w ; pre-level Zone play mode? beq.s loc_4C4 cmpi.b #GameModeID_Demo,(Game_Mode).w ; Demo Mode? beq.s loc_4C4 cmpi.b #GameModeID_Level,(Game_Mode).w ; Zone play mode? beq.s loc_4C4 ; stopZ80 ; S3K ; stop the Z80 ; S3K ; bsr.w sndDriverInput ; S3K ; give input to the sound driver ; startZ80 ; S3K ; start the Z80 bra.s VintRet ; --------------------------------------------------------------------------- 2. Ok, Next got to the following labels: • loc_54A: • Vint0_noWater: • loc_748: • VintSub18: • VintSub16: • loc_EFE: And delete this line: Code (ASM): bsr.w sndDriverInput 3. Similarly, go to these labels as well • Vint10_specialStage: • loc_BD6: and delete this line: Code (ASM): jsr (sndDriverInput).l 4. Go to Code (ASM): SS_PNTA_Transfer_Table: Once there, scroll down just a little and you will see: Code (ASM): jsr (sndDriverInput).l Delete that as well. UPGRADING THE LOAD DRIVER ROUTINE 1. Go to Code (ASM): sndDriverInput: and delete all the code right before JmpTo_LoadTilesAsYouMove: Under that is: Code (ASM): DecompressSoundDriver: Delete all of it up to: Code (ASM): Snd_Driver: But make sure that you leave this line or you will get an error: Code (ASM): ; WARNING: the build script needs editing if you rename this label movewZ80CompSize: move.w #Snd_Driver_End-Snd_Driver,d7 2. OK, let's start adding the S3K driver!!!!! Go to: Code (ASM): JmpTo_SoundDriverLoad: Delete these: Code (ASM): nop jmp (SoundDriverLoad).l and ADD the following: Code (ASM): nop move.w #$100,(Z80_bus_request).l move.w #$100,(Z80_reset).l ; release Z80 reset lea (Z80_Snd_Driver).l,a0 lea (Z80_RAM).l,a1 bsr.w KosDec lea (Z80_RAM+$1300).l,a1 bsr.w KosDec lea (Z80_Blank_Dat).l,a0 lea (Z80_RAM+zVariablesStart).l,a1 move.w #$F,d0 - move.b (a0)+,(a1)+ dbf d0,- btst #6,(Graphics_flags).w beq.s + move.b #1,(Z80_RAM+zPalFlag).l ; set PAL mode flag + move.w #0,(Z80_reset).l ; reset Z80 nop nop nop nop move.w #$100,(Z80_reset).l ; release reset startZ80 rts ; End of function SndDrvInit ; --------------------------------------------------------------------------- Z80_Blank_Dat: dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; --------------------------------------------------------------------------- Upgrading the Playback Routines 1. Find Code (ASM): PlayMusic: and replace it's code with the following: Code (ASM): stopZ80 move.b d0,(Z80_RAM+zMusicNumber).l startZ80 + rts 2. Next, is a little different. Delete all of: Code (ASM): PlaySoundLocal: PlaySoundStereo: PlaySound: Replace it with: Code (ASM): ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| PlaySoundLocal: tst.b render_flags(a0) bpl.s +++ ; rts PlaySoundStereo: PlaySound: stopZ80 cmp.b (Z80_RAM+zSFXNumber0).l,d0 beq.s ++ tst.b (Z80_RAM+zSFXNumber0).l bne.s + move.b d0,(Z80_RAM+zSFXNumber0).l startZ80 rts + move.b d0,(Z80_RAM+zSFXNumber1).l + startZ80 + rts ; End of function PlaySound ; =============== S U B R O U T I N E ======================================= Change_Music_Tempo: stopZ80 move.b d0,(Z80_RAM+zTempoSpeedup).l startZ80 rts ; End of function Change_Music_Tempo Upgrading Pause / Resume routines 1. So, starting from where we left off, PauseGame should be right under the PlayMusic/PlaySound routines. First thing we need to do, is fix a future error. So, from PauseGame, scroll down until you see this: Code (ASM): beq.s Pause_DoNothing ; if not, branch That should be the 9th line from PauseGame. Let's edit it to this: Code (ASM): beq.w Pause_DoNothing ; if not, branch 2. Continue scrolling until you find: Code (ASM): move.b #MusID_Pause,(Music_to_play).w ; pause music Delete it, and replace it with these three lines: Code (ASM): stopZ80 move.b #1,(Z80_RAM+zPauseFlag).l ; Pause the music startZ80 3. To resume music, Go to: Code (ASM): ; loc_13F2: Pause_Resume: And delete this: Code (ASM): move.b #MusID_Unpause,(Music_to_play).w Replace it with: Code (ASM): stopZ80 move.b #$80,(Z80_RAM+zPauseFlag).l ; Unpause music startZ80 4. And to fix the Slow motion pause/unpause, Go to: Code (ASM): ; loc_1400: Pause_SlowMo: And delete: Code (ASM): move.b #MusID_Unpause,(Music_to_play).w Replace it with: Code (ASM): stopZ80 move.b #$80,(Z80_RAM+zPauseFlag).l ; Unpause music startZ80 5. Next, fixing the speed shoes! Go to: Code (ASM): super_shoes_Tails: Delete these: Code (ASM): move.w #MusID_SpeedUp,d0 jmp (PlayMusic).l ; Speed up tempo and replace it with: Code (ASM): moveq #8,d0 jmp (Change_Music_Tempo).l Next, go to: Code (ASM): Obj01_RmvSpeed: Delete these two lines: Code (ASM): move.w #MusID_SlowDown,d0 ; Slow down tempo jmp (PlayMusic).l and replace them with this: Code (ASM): moveq #0,d0 jmp (Change_Music_Tempo).l Same thing as before, but with Tails. Find this: Code (ASM): Obj02_RmvSpeed: (*note: that line is commented out.) Replace these lines: Code (ASM): move.w #MusID_SlowDown,d0 ; Slow down tempo jmp (PlayMusic).l with these: Code (ASM): moveq #0,d0 jmp (Change_Music_Tempo).l Replacing S2 driver with new S3K driver 1. Go to: Code (ASM): Snd_Driver: and delete the inner contents. It should look like this when you are done: Code (ASM): Snd_Driver: ; loc_ED04C: Snd_Driver_End: 2. After that, delete everything after that label, upto but not including Code (ASM): ArtNem_Buzzer_Fireball: 3. Find Code (ASM): Snd_Sega: and delete the cnop above it, and everything afterwards up to Code (ASM): Sound70: including the data after it, Code (ASM): if * > soundBankStart + $8000 and the 4 lines after as well. Now, right above Code (ASM): ; end of 'ROM' add this line: Code (ASM): Z80_Snd_Driver: include "s2.sounddriver.asm" align $8000 4. Download flamewing's sound diver: http://www.mediafire...songs-sfx-v3.7z Now open the compressed file and copy everything to the sound folder. in the sound folder, delete "Z80 Sound Driver.asm" file. 5. Now Download this: https://www.dropbox....sounddriver.asm and replace s2.sounddriver.asm in your Sonic hack folder with the one of the same name that you downloaded. 6. download this package: https://www.dropbox....21rtc/win32.rar and replace win32 folder with it. 7. Last, download https://www.dropbox..../Sega%20PCM.bin and put it in you "sound" folder. FIXING CONSTANTS AND MUSIC/SOUND POINTERS 1. Open s2.constnts.asm 2. Change Code (ASM): Size_of_Snd_driver_guess = $F64 to Code (ASM): Size_of_Snd_driver_guess = $1580 3. Find Code (ASM): zMasterPlaylist Here is what the area we are going to change looks like now: Code (ASM): ; 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 Go ahead and delete it and replace it with the following: Code (ASM): ; Music IDs offset := z80_MusicPointers ptrsize := 2 idstart := 1 MusID__First = idstart MusID_2PResult = id(Snd_AIZ1_Ptr) ; 01 MusID_EHZ = id(Snd_AIZ2_Ptr) ; 02 MusID_MCZ_2P = id(Snd_HCZ1_Ptr) ; 03 MusID_OOZ = id(Snd_HCZ2_Ptr) ; 04 MusID_MTZ = id(Snd_MGZ1_Ptr) ; 05 MusID_HTZ = id(Snd_MGZ2_Ptr) ; 06 MusID_ARZ = id(Snd_CNZ2_Ptr) ; 07 MusID_CNZ_2P = id(Snd_CNZ1_Ptr) ; 08 MusID_CNZ = id(Snd_FBZ1_Ptr) ; 09 MusID_DEZ = id(Snd_FBZ2_Ptr) ; 0A MusID_MCZ = id(Snd_MHZ1_Ptr) ; 0B MusID_EHZ_2P = id(Snd_MHZ2_Ptr) ; 0C MusID_SCZ = id(Snd_SOZ1_Ptr) ; 0D MusID_CPZ = id(Snd_SOZ2_Ptr) ; 0E MusID_WFZ = id(Snd_LRZ1_Ptr) ; 0F MusID_HPZ = id(Snd_LRZ2_Ptr) ; 10 MusID_Options = id(Snd_SSZ_Ptr) ; 11 MusID_SpecStage = id(Snd_DEZ1_Ptr) ; 12 MusID_Boss = id(Snd_DEZ2_Ptr) ; 13 MusID_EndBoss = id(Snd_Minib_SK_Ptr) ; 14 MusID_Ending = id(Snd_Boss_Ptr) ; 15 MusID_SuperSonic = id(Snd_DDZ_Ptr) ; 16 MusID_Invincible = id(Snd_PachBonus_Ptr) ; 17 MusID_ExtraLife = MusID_1UP ; 18 MusID_Title = id(Snd_SpecialS_Ptr) ; 19 MusID_EndLevel = id(Snd_SlotBonus_Ptr) ; 1A MusID_GameOver = id(Snd_Knux_Ptr) ; 1B MusID_Continue = id(Snd_Title_Ptr) ; 1C MusID_Emerald = id(Snd_Emerald_Ptr) ; 1D MusID_Credits = id(Snd_ICZ2_Ptr) ; 1E MusID_Countdown = id(Snd_Drown_Ptr) ; 1F MusID__End = id(zMusIDPtr__End) ; 20 4. We are going to do the same for the sound effects. right after the music pointers, you should see the following: Code (ASM): ; 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 Delete it and replace it with this Code (ASM): ; Sound IDs offset := z80_SFXPointers ptrsize := 2 idstart := MusID__End SndID__First = idstart SndID_Ring = id(Sound_33_Ptr) ; 20 SndID_RingRight = id(Sound_34_Ptr) ; 21 SndID_Jump = id(Sound_35_Ptr) ; 22 SndID_Checkpoint = id(Sound_36_Ptr) ; 23 SndID_SpikeSwitch = id(Sound_37_Ptr) ; 24 SndID_Hurt = id(Sound_38_Ptr) ; 25 SndID_Skidding = id(Sound_39_Ptr) ; 26 SndID_BlockPush = id(Sound_3A_Ptr) ; 27 SndID_HurtBySpikes = id(Sound_3B_Ptr) ; 28 SndID_Sparkle = id(Sound_3C_Ptr) ; 29 SndID_Beep = id(Sound_3D_Ptr) ; 2A SndID_Bwoop = id(Sound_3E_Ptr) ; 2B SndID_Splash = id(Sound_3F_Ptr) ; 2C SndID_Swish = id(Sound_40_Ptr) ; 2D SndID_BossHit = id(Sound_41_Ptr) ; 2E SndID_InhalingBubble = id(Sound_42_Ptr) ; 2E SndID_ArrowFiring = id(Sound_43_Ptr) ; 2F ; MOVE SndID_LavaBall = id(Sound_43_Ptr) ; 30 SndID_Shield = id(Sound_44_Ptr) ; 31 SndID_LaserBeam = id(Sound_45_Ptr) ; 32 SndID_Zap = id(Sound_46_Ptr) ; 33 SndID_Drown = id(Sound_47_Ptr) ; 34 SndID_FireBurn = id(Sound_48_Ptr) ; 36 SndID_Bumper = id(Sound_49_Ptr) ; 37 SndID_SpikesMove = id(Sound_4A_Ptr) ; 39 SndID_Rumbling = id(Sound_4B_Ptr) ; 3B SndID_Smash = id(Sound_4D_Ptr) ; 3C SndID_DoorSlam = id(Sound_4F_Ptr) ; 3D SndID_SpindashRelease = id(Sound_50_Ptr) ; 3E SndID_Hammer = id(Sound_51_Ptr) ; 3F SndID_Roll = id(Sound_52_Ptr) ; 40 SndID_ContinueJingle = id(Sound_53_Ptr) ; 41 SndID_CasinoBonus = id(Sound_54_Ptr) ; 42 SndID_Explosion = id(Sound_55_Ptr) ; 43 SndID_WaterWarning = id(Sound_56_Ptr) ; 44 SndID_EnterGiantRing = id(Sound_57_Ptr) ; 45 SndID_BossExplosion = id(Sound_58_Ptr) ; 46 SndID_TallyEnd = id(Sound_59_Ptr) ; 48 SndID_RingSpill = id(Sound_5A_Ptr) ; 49 SndID_Flamethrower = id(Sound_5C_Ptr) ; 4A SndID_Bonus = id(Sound_5D_Ptr) ; 4B SndID_SpecStageEntry = id(Sound_5E_Ptr) ; 4C SndID_SlowSmash = id(Sound_5F_Ptr) ; 4D SndID_Spring = id(Sound_60_Ptr) ; 4E SndID_Blip = id(Sound_61_Ptr) ; 4F SndID_RingLeft = id(Sound_62_Ptr) ; 50 SndID_Signpost = id(Sound_63_Ptr) ; 53 SndID_CNZBossZap = id(Sound_66_Ptr) ; 54 SndID_Signpost2P = id(Sound_67_Ptr) ; 55 SndID_OOZLidPop = id(Sound_68_Ptr) ; 56 SndID_SlidingSpike = id(Sound_69_Ptr) ; 57 SndID_CNZElevator = id(Sound_6A_Ptr) ; 58 SndID_PlatformKnock = id(Sound_6B_Ptr) ; 59 SndID_BonusBumper = id(Sound_6C_Ptr) ; 5A SndID_LargeBumper = id(Sound_6D_Ptr) ; 5B SndID_Gloop = id(Sound_6E_Ptr) ; 5C SndID_PreArrowFiring = id(Sound_6F_Ptr) ; 5D SndID_Fire = id(Sound_70_Ptr) ; 5E SndID_ArrowStick = id(Sound_71_Ptr) ; 5F SndID_Helicopter = id(Sound_71_Ptr) ; 60 SndID_SuperTransform = id(Sound_72_Ptr) ; 61 SndID_SpindashRev = id(Sound_73_Ptr) ; 62 SndID_Rumbling2 = id(Sound_74_Ptr) ; 63 SndID_CNZLaunch = id(Sound_75_Ptr) ; 64 SndID_Flipper = id(Sound_76_Ptr) ; 65 SndID_HTZLiftClick = id(Sound_77_Ptr) ; 66 SndID_Leaves = id(Sound_78_Ptr) ; 67 SndID_MegaMackDrop = id(Sound_79_Ptr) ; 68 SndID_DrawbridgeMove = id(Sound_7A_Ptr) ; 69 SndID_QuickDoorSlam = id(Sound_7B_Ptr) ; 6A SndID_DrawbridgeDown = id(Sound_7C_Ptr) ; 6B SndID_LaserBurst = id(Sound_7D_Ptr) ; 6B SndID_Scatter = id(Sound_7E_Ptr) ; 6C SndID_LaserFloor = id(Sound_7E_Ptr) ; 6D SndID_Teleport = id(Sound_7F_Ptr) ; 6E SndID_Error = id(Sound_80_Ptr) ; 6F SndID_MechaSonicBuzz = id(Sound_81_Ptr) ; 70 SndID_LargeLaser = id(Sound_82_Ptr) ; 71 SndID_OilSlide = id(Sound_83_Ptr) ; 72 SndID__End = id(Sound_End_Ptr) ; F1 ; Special sound IDs MusID_StopSFX = FadeID__First+3 ; F8 MusID_FadeOut = FadeID__First ; F9 SndID_SegaSound = SndID_Sega ; FA MusID_SpeedUp = 8 ; FB MusID_SlowDown = 0 ; FC MusID_Stop = $FE ; FD MusID_Pause = 1 ; FE MusID_Unpause = $80 ; FF FIXING SOUND TEST 1. Fixing the sound test in the options menu is very easy. First, go to Code (ASM): OptionScreen_Controls: and find this line: Code (ASM): addi.w #$80,d0 Delete it. 2. Right under that find Code (ASM): OptionScreen_Choices: It should look like this Code (ASM): ; word_917A: OptionScreen_Choices: dc.l (3-1)<<24|(Player_option&$FFFFFF) dc.l (2-1)<<24|(Two_player_items&$FFFFFF) dc.l ($80-1)<<24|(Sound_test_sound&$FFFFFF) We want to edit that last line. Change the ($80-1) to $FF. So it should look like: Code (ASM): ; word_917A: OptionScreen_Choices: dc.l (3-1)<<24|(Player_option&$FFFFFF) dc.l (2-1)<<24|(Two_player_items&$FFFFFF) dc.l $FF<<24|(Sound_test_sound&$FFFFFF) 3. To fix the Level Select Sound test, go to Code (ASM): LevSelControls_CheckLR: find this section of code: Code (ASM): btst #button_left,d1 beq.s + subq.b #1,d0 bcc.s + moveq #$7F,d0 Remove the last two lines. It should now look like this: Code (ASM): btst #button_left,d1 beq.s + subq.b #1,d0 Under that, is this: Code (ASM): beq.s + addq.b #1,d0 cmpi.w #$80,d0 blo.s + moveq #0,d0 Delete the last three lines. It should now look like this: Code (ASM): beq.s + addq.b #1,d0 Right under that section of code you should see: Code (ASM): + btst #button_A,d1 beq.s + addi.b #$10,d0 andi.b #$7F,d0 As before, delete the last line. Should look like this: Code (ASM): + btst #button_A,d1 beq.s + addi.b #$10,d0 And last, the final part of the code, look for Code (ASM): addi.w #$80,d0 And delete it! The whole routine should look like this: (I commented my lines out) Code (ASM): ; loc_9522: LevSelControls_CheckLR: cmpi.w #$15,(Level_select_zone).w ; are we in the sound test? bne.s LevSelControls_SwitchSide ; no move.w (Sound_test_sound).w,d0 move.b (Ctrl_1_Press).w,d1 btst #button_left,d1 beq.s + subq.b #1,d0 ; bcc.s + ; moveq #$7F,d0 + btst #button_right,d1 beq.s + addq.b #1,d0 ; cmpi.w #$80,d0 ; blo.s + ; moveq #0,d0 + btst #button_A,d1 beq.s + addi.b #$10,d0 ; andi.b #$7F,d0 + move.w d0,(Sound_test_sound).w andi.w #button_B_mask|button_C_mask,d1 beq.s + ; rts move.w (Sound_test_sound).w,d0 ; addi.w #$80,d0 ; here bsr.w JmpTo_PlayMusic lea (debug_cheat).l,a0 lea (super_sonic_cheat).l,a2 lea (Night_mode_flag).w,a1 moveq #1,d2 ; flag to tell the routine to enable the Super Sonic cheat bsr.w CheckCheats + rts Now build and enjoy! That about wraps that up. I would like to thank flamewing for his awesome s3k driver and his very cool tool! Go here to see what his driver and tool is about.
Thank you for sharing this! I did some fixes on this: s2.constants: Change this: Code (Text): ; 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 Into this: Code (Text): ; Special sound IDs MusID_StopSFX = FadeID__First+3 ; F8 MusID_FadeOut = -$1F ; F9 SndID_SegaSound = SndID_Sega ; FA MusID_SpeedUp = 8 ; FB MusID_SlowDown = 0 ; FC MusID_Stop = -2 ; FD MusID_Pause = 1 ; FE MusID_Unpause = $80 ; FF Now the MusID_Stop is fixed. I got it from s3k ASM. In s2.sounddriver, I did some changes in this too. change this: Code (Text): ; --------------------------------------------------------------------------- ; =========================================================================== ; Music Banks ; =========================================================================== ; Music Bank 1 ; --------------------------------------------------------------------------- Snd_Bank1_Start: startBank Snd_FBZ1: include "Sound/s2/Music/CNZ.asm" Snd_FBZ2: include "Sound/s2/Music/DEZ.asm" Snd_MHZ1: include "Sound/s2/Music/MCZ.asm" Snd_MHZ2: include "Sound/s2/Music/EHZ_2p.asm" Snd_SOZ1: include "Sound/s2/Music/SCZ.asm" Snd_SOZ2: include "Sound/s2/Music/CPZ.asm" Snd_LRZ1: include "Sound/s2/Music/WFZ.asm" Snd_LRZ2: include "Sound/s2/Music/HPZ.asm" Snd_SSZ: include "Sound/s2/Music/Options.asm" Snd_DEZ1: include "Sound/s2/Music/SpecStg.asm" Snd_DEZ2: include "Sound/s2/Music/Boss.asm" Snd_Minib_SK: include "Sound/s2/Music/End_Boss.asm" Snd_Boss: include "Sound/s2/Music/Ending.asm" Snd_DDZ: include "Sound/s2/Music/Supersonic.asm" Snd_PachBonus: include "Sound/s2/Music/Invincible.asm" Snd_SpecialS: include "Sound/s2/Music/Title screen.asm" Snd_SlotBonus: include "Sound/s2/Music/End of level.asm" Snd_Knux: include "Sound/s2/Music/Game Over.asm" Snd_Title: include "Sound/s2/Music/Continue.asm" Snd_1UP: include "Sound/s2/Music/Extra life.asm" Snd_Emerald: include "Sound/s2/Music/Got Emerald.asm" finishBank ; --------------------------------------------------------------------------- ; s3/Music Bank 2 ; --------------------------------------------------------------------------- Snd_Bank2_Start: startBank Snd_AIZ1: include "Sound/s2/Music/Results screen 2p.asm" Snd_AIZ2: include "Sound/s2/Music/EHZ.asm" Snd_HCZ1: include "Sound/s2/Music/MCZ_2p.asm" Snd_HCZ2: include "Sound/s2/Music/OOZ.asm" Snd_MGZ1: include "Sound/s2/Music/MTZ.asm" Snd_MGZ2: include "Sound/s2/Music/HTZ.asm" Snd_CNZ2: include "Sound/s2/Music/ARZ.asm" Snd_CNZ1: include "Sound/s2/Music/CNZ_2p.asm" finishBank ; --------------------------------------------------------------------------- ; s3/Music Bank 3 ; --------------------------------------------------------------------------- Snd_Bank3_Start: startBank Snd_ICZ2: include "Sound/s2/Music/Credits.asm" Snd_ICZ1: include "Sound/sk/Music/ICZ1.asm" Snd_LBZ2: include "Sound/sk/Music/LBZ2.asm" Snd_LBZ1: include "Sound/sk/Music/LBZ1.asm" Snd_SKCredits: include "Sound/sk/Music/Credits.asm" Snd_GameOver: include "Sound/sk/Music/Game Over.asm" Snd_Continue: include "Sound/sk/Music/Continue.asm" Snd_Results: include "Sound/sk/Music/Level Outro.asm" Snd_Invic: include "Sound/sk/Music/Invincible.asm" Snd_Menu: include "Sound/sk/Music/Menu.asm" Snd_FinalBoss: include "Sound/sk/Music/Final Boss.asm" Snd_PresSega: include "Sound/sk/Music/Game Complete.asm" finishBank ; --------------------------------------------------------------------------- ; s3/Music Bank 4 ; --------------------------------------------------------------------------- Snd_Bank4_Start: startBank Snd_GumBonus: include "Sound/sk/Music/Gum Ball Machine.asm" Snd_ALZ: include "Sound/sk/Music/Azure Lake.asm" Snd_BPZ: include "Sound/sk/Music/Balloon Park.asm" Snd_DPZ: include "Sound/sk/Music/Desert Palace.asm" Snd_CGZ: include "Sound/sk/Music/Chrome Gadget.asm" Snd_EMZ: include "Sound/sk/Music/Endless Mine.asm" Snd_S3Credits: include "Sound/sk/Music/Sonic 3 Credits.asm" Snd_2PMenu: include "Sound/sk/Music/Competition Menu.asm" Snd_Drown: include "Sound/sk/Music/Countdown.asm" finishBank into this: Code (Text): ; --------------------------------------------------------------------------- ; =========================================================================== ; Music Banks ; =========================================================================== ; Music Bank 1 ; --------------------------------------------------------------------------- Snd_Bank1_Start: startBank Snd_FBZ1: include "Sound/s2/Music/CNZ.asm" Snd_FBZ2: include "Sound/s2/Music/DEZ.asm" Snd_MHZ1: include "Sound/s2/Music/WFZ.asm" Snd_MHZ2: include "Sound/s2/Music/HPZ.asm" Snd_SOZ1: include "Sound/s2/Music/Options.asm" Snd_SOZ2: include "Sound/s2/Music/SpecStg.asm" Snd_LRZ1: include "Sound/s2/Music/Boss.asm" Snd_LRZ2: include "Sound/s2/Music/End_Boss.asm" Snd_SSZ: include "Sound/s2/Music/Ending.asm" Snd_DEZ1: include "Sound/s2/Music/Supersonic.asm" Snd_DEZ2: include "Sound/s2/Music/Invincible.asm" Snd_Minib_SK: include "Sound/s2/Music/Extra life.asm" Snd_Boss: include "Sound/s2/Music/Title screen.asm" Snd_DDZ: include "Sound/s2/Music/End of level.asm" Snd_PachBonus: include "Sound/s2/Music/Game Over.asm" Snd_SpecialS: include "Sound/s2/Music/Continue.asm" Snd_SlotBonus: include "Sound/s2/Music/Got Emerald.asm" Snd_Knux: include "Sound/s2/Music/Drowning.asm" Snd_Title: include "Sound/sk/Music/Title.asm" Snd_1UP: include "Sound/sk/Music/1UP.asm" Snd_Emerald: include "Sound/sk/Music/Chaos Emerald.asm" finishBank ; --------------------------------------------------------------------------- ; s3/Music Bank 2 ; --------------------------------------------------------------------------- Snd_Bank2_Start: startBank Snd_AIZ1: include "Sound/s2/Music/Results screen 2p.asm" Snd_AIZ2: include "Sound/s2/Music/EHZ.asm" Snd_HCZ1: include "Sound/s2/Music/MCZ_2p.asm" Snd_HCZ2: include "Sound/s2/Music/OOZ.asm" Snd_MGZ1: include "Sound/s2/Music/MTZ.asm" Snd_MGZ2: include "Sound/s2/Music/HTZ.asm" Snd_CNZ2: include "Sound/s2/Music/CNZ_2p.asm" Snd_CNZ1: include "Sound/s2/Music/ARZ.asm" finishBank ; --------------------------------------------------------------------------- ; s3/Music Bank 3 ; --------------------------------------------------------------------------- Snd_Bank3_Start: startBank Snd_ICZ2: include "Sound/s2/Music/EHZ_2p.asm" Snd_ICZ1: include "Sound/s2/Music/MCZ.asm" Snd_LBZ2: include "Sound/s2/Music/CPZ.asm" Snd_LBZ1: include "Sound/s2/Music/SCZ.asm" Snd_SKCredits: include "Sound/sk/Music/Credits.asm" Snd_GameOver: include "Sound/sk/Music/Game Over.asm" Snd_Continue: include "Sound/sk/Music/Continue.asm" Snd_Results: include "Sound/sk/Music/Level Outro.asm" Snd_Invic: include "Sound/sk/Music/Invincible.asm" Snd_Menu: include "Sound/sk/Music/Menu.asm" Snd_FinalBoss: include "Sound/sk/Music/Final Boss.asm" Snd_PresSega: include "Sound/sk/Music/Game Complete.asm" finishBank ; --------------------------------------------------------------------------- ; s3/Music Bank 4 ; --------------------------------------------------------------------------- Snd_Bank4_Start: startBank Snd_GumBonus: include "Sound/s2/Music/Credits.asm" Snd_ALZ: include "Sound/sk/Music/Azure Lake.asm" Snd_BPZ: include "Sound/sk/Music/Balloon Park.asm" Snd_DPZ: include "Sound/sk/Music/Desert Palace.asm" Snd_CGZ: include "Sound/sk/Music/Chrome Gadget.asm" Snd_EMZ: include "Sound/sk/Music/Endless Mine.asm" Snd_S3Credits: include "Sound/sk/Music/Sonic 3 Credits.asm" Snd_2PMenu: include "Sound/sk/Music/Competition Menu.asm" Snd_Drown: include "Sound/sk/Music/Countdown.asm" finishBank Now the this correct the order that the music plays in the sound test number like in Sonic 2. Now look for this in s2.sounddriver: Code (Text): MusID_1UP = 2Ah Change 2Ah to 18h. Now thanks to this Sound Driver, now we can use the unused RAM that is located here: $F100-$F5FF
Can I bother you for the rom itself, I've always wanted to have a version of Sonic 2 where the sounds effects didn't cut out the music channels, I just don't fancy going back into ASM after trying to put in the spindash into Sonic 1 a while back.
I knew I was forgetting to add something to this! Also, the one I sent you was missing info about speeding/slowing the music via speed shoes. It's fixed in my original post! Sure.
Thanks. There are still some drop outs in the music (in Hill Top Zone) when jumping and collecting rings. Is this mod there just to improve it or get rid of all the drop outs?
It was never meant to get rid of any drop outs in sound. The thing is some sounds are using channels that the song is using so you hear part of the song "drop out". As far as I know, I don't think that can be fixed.
This is impossible without losing channels on the music. The Genesis has a limited number of sound channels, all of which are typically used in music, and none of which can play more than a single note at a time*. Unless you completely disable all sound effects, they will always cut into the music. * Technically, you can mix samples before sending them to the DAC, but you lose accuracy in both samples.
I know the channels are limited and are monophonic, I've always thought that it would be impossible but this is where my confusion started. That's why I jumped straight to Hill Top Zone to check out the fix.
A note and a bugfix: I swear this driver has a problem with holding notes, just listen to the opening of ARZ, oww... This could just be me however: my left speaker's faulty so I'm only hearing the right audio channel. Spindash revs don't increase in pitch, and there exist some bothersome hardcoded values. Time for a little HG treatment! Fixing this: Spoiler First off, let's make the spindash detection more dynamic: Code (ASM): z80_SoundDriver: !org 0 ; z80 Align, handled by the build process CPU Z80 listing off MusID_1UP = 2Ah SndID_Spindash = 0ABh SndID__FirstContinuous = 0BCh MusID_SKCredits = 0DCh FadeID__First = 0E1h FadeID__End = 0E6h SndID_StopSega = 0FEh SndID_Sega = 0FFh It is actually worth working on not only SndID_Spindash, but MusID_1UP and MusID_SKCredits. The hardcoding really just makes things difficult, but we'll just stick with the spindash for now. Delete its entry so that you're left with this: Code (ASM): z80_SoundDriver: !org 0 ; z80 Align, handled by the build process CPU Z80 listing off MusID_1UP = 2Ah SndID__FirstContinuous = 0BCh MusID_SKCredits = 0DCh FadeID__First = 0E1h FadeID__End = 0E6h SndID_StopSega = 0FEh SndID_Sega = 0FFh Now, run a search-and-replace of SndID_Spindash in s2.sounddriver.asm (the new one), replacing it with SndID_SpindashRev. But this alone won't fix our problems, the pitch still doesn't increase. As you could tell by that code we deleted, the spindash sound was AB(.asm), go to sound/sk/sfx and open AB.asm, then go to sound/s2/sfx and open sound60.asm up. You'll want to compare the FM5 channels: Sound 60 (S2) Spoiler Code (ASM): ; FM5 Data Sound60_SpindashRev_FM5: smpsSetvoice $00 smpsModSet $00, $01, $20, $F6 dc.b nG5, $16, smpsNoAttack smpsModOff dc.b nG6, $18, smpsNoAttack Sound60_SpindashRev_Loop00: dc.b $04, smpsNoAttack smpsAlterVol $03 smpsLoop $00, $10, Sound60_SpindashRev_Loop00 smpsStop Sound AB (S&K) Spoiler Code (ASM): ; FM5 Data Sound_AB_FM5: smpsSpindashRev smpsSetvoice $00 smpsModSet $01, $01, $1A, $01 dc.b nC5, $18, smpsNoAttack smpsModSet $00, $00, $00, $00 dc.b $02 Sound_AB_Loop00: dc.b smpsNoAttack, $02 smpsFMAlterVol $02 smpsLoop $00, $18, Sound_AB_Loop00 smpsResetSpindashRev smpsStop See the cause? The S&K variant references some functions that the S2 variant does not! smpsSpindashRev and smpsResetSpindashRev! Apply these to Sound60, you should have something like this: Code (ASM): ; FM5 Data Sound60_SpindashRev_FM5: smpsSpindashRev smpsSetvoice $00 smpsModSet $00, $01, $20, $F6 dc.b nG5, $16, smpsNoAttack smpsModOff dc.b nG6, $18, smpsNoAttack Sound60_SpindashRev_Loop00: dc.b $04, smpsNoAttack smpsAlterVol $03 smpsLoop $00, $10, Sound60_SpindashRev_Loop00 smpsResetSpindashRev smpsStop Save and build, and the rev's pitch increase should now work! But wait! Rev a bunch of times, and the pitch goes too high! The S3&K driver has its own way of managing spindash pitch, I'm looking into porting the S2 method over, but for now we can just work around this: Go to cfSpindashRev, you should find this: Code (ASM): cfSpindashRev: ld hl, zSpindashRev ; hl = pointer to escalating transposition ld a, (hl) ; a = value of escalating transposition add a, (ix+zTrackKeyOffset) ; Add in current track key offset ld (ix+zTrackKeyOffset), a ; Store result as new track key offset cp 10h ; Is the current transposition 10h? jp z, + ; Branch if yes inc (hl) ; Otherwise, increase escalating transposition + dec de ; Put parameter byte back ret That 10h needs changing, 09h sounds close enough. Done and done, but the spindash still isn't perfect, each rev audibly silences the one before it just as in S3K, I'm still looking into that. Now, onto those issue from earlier. Code (ASM): z80_SoundDriver: !org 0 ; z80 Align, handled by the build process CPU Z80 listing off MusID_1UP = 2Ah SndID__FirstContinuous = 0BCh MusID_SKCredits = 0DCh FadeID__First = 0E1h FadeID__End = 0E6h SndID_StopSega = 0FEh SndID_Sega = 0FFh Back here, let's get to work on MusID_1UP, starting with deleting that entry. Next, head over to s2.constants.asm and change the MusID_ExtraLife entry to this: Code (ASM): MusID_ExtraLife = id(Snd_1UP_Ptr) ; 18 Once again, in s2.sounddriver.asm do a search-and-replace of MusID_1UP with MusID_ExtraLife. Done. Lastly, back at z80_SoundDriver, let's get rid of the MusID_SKCredits entry, then, go to zPlaySoundByIndex: Code (ASM): zPlaySoundByIndex: cp MusID_SKCredits ; Is this the credits music? jp z, zPlayMusicCredits ; Branch if yes cp SndID_Sega ; Is this the SEGA sound? jp z, zPlaySegaSound ; Branch if yes ; etcetera Delete the check, unless of course you're using the S&K credits in your hack, in which case you'll want to make the check match its MusID. Also, a little cleaning: Spoiler Code (ASM): ; WARNING: the build script needs editing if you rename this label movewZ80CompSize: move.w #Snd_Driver_End-Snd_Driver,d7 Delete this. Code (ASM): Snd_Driver: ; loc_ED04C: Snd_Driver_End: Delete this too. Find this: Code (ASM): shared word_728C_user,Obj5F_MapUnc_7240,off_3A294,MapRUnc_Sonic,movewZ80CompSize Delete the last entry. I'm certainly interested in this driver, after leaving the Clone Driver due to RAM and CPU demands, and being too stupid to figure out how to expand the music index in the S2 driver, this has certainly caught my interest. Just too bad this thing's incompatible with everything, even itself: I adjust the settings at the top of the file so it only bincludes the S2 DAC samples, and the thing goes and doesn't compile the second DAC bank despite still being referenced and needed!
The driver changed the way held notes are specified; specifically, it changed how silence is held. Old songs need to be edited accordingly. Well, the driver was intended originally as a drop-in replacement for the S&K driver, but with the ability to use S1 and S2 songs; so I never really tried to assemble it with only S2 DAC samples.