Actions

SCHG How-to

Difference between revisions of "Port Sonic 1's Sound Driver to Sonic 2"

From Sonic Retro

m
(Added 2007 disasm equates)
Line 36: Line 36:
 
; unused mostly-leftover subroutine to load the sound driver
 
; unused mostly-leftover subroutine to load the sound driver
 
; SoundDriverLoadS1:
 
; SoundDriverLoadS1:
move.w #$100,($A11100).l ; stop the Z80
+
move.w #$100,(Z80_Bus_Request).l ; stop the Z80
move.w #$100,($A11200).l ; reset the Z80
+
move.w #$100,(Z80_Reset).l ; reset the Z80
 
lea (Kos_Z80).l,a0
 
lea (Kos_Z80).l,a0
lea ($A00000).l,a1
+
lea (Z80_RAM).l,a1
bsr.w KozDec
+
bsr.w KosDec
 
move.b #$F3,(a1)+
 
move.b #$F3,(a1)+
 
move.b #$F3,(a1)+
 
move.b #$F3,(a1)+
Line 46: Line 46:
 
move.b #0,(a1)+
 
move.b #0,(a1)+
 
move.b #0,(a1)+
 
move.b #0,(a1)+
move.w #0,($A11200).l
+
move.w #0,(Z80_Reset).l
 
nop
 
nop
 
nop
 
nop
 
nop
 
nop
 
nop
 
nop
move.w #$100,($A11200).l ; reset the Z80
+
move.w #$100,(Z80_Reset).l ; reset the Z80
move.w #0,($A11100).l ; start the Z80
+
move.w #0,(Z80_Bus_Request).l ; start the Z80
 
rts</asm>
 
rts</asm>
  
Line 80: Line 80:
 
Next find PlaySound, and find this:
 
Next find PlaySound, and find this:
 
<asm>PlaySound:
 
<asm>PlaySound:
move.b d0,($FFFFFFE1).w
+
move.b d0,(SFX_to_play).w
 
rts
 
rts
 
; End of function PlaySound</asm>
 
; End of function PlaySound</asm>
Line 92: Line 92:
 
Now, we're going to fix the broken sound effects, such as rings. Look for PlaySoundStereo. It should be this:
 
Now, we're going to fix the broken sound effects, such as rings. Look for PlaySoundStereo. It should be this:
 
<asm>PlaySoundStereo:
 
<asm>PlaySoundStereo:
move.b d0,($FFFFFFE2).w
+
move.b d0,(SFX_to_play_2).w
 
rts
 
rts
 
; End of function PlaySoundStereo</asm>
 
; End of function PlaySoundStereo</asm>
Line 99: Line 99:
 
<asm>PlaySoundStereo:
 
<asm>PlaySoundStereo:
 
bra.s PlayMusic ; skip over routine (For S1 driver)
 
bra.s PlayMusic ; skip over routine (For S1 driver)
move.b d0,($FFFFFFE2).w
+
move.b d0,(SFX_to_play_2).w
 
rts
 
rts
 
; End of function PlaySoundStereo</asm>
 
; End of function PlaySoundStereo</asm>
Line 105: Line 105:
 
Now, look for PlaySoundLocal. It should be this:
 
Now, look for PlaySoundLocal. It should be this:
 
<asm>PlaySoundLocal:
 
<asm>PlaySoundLocal:
tst.b 1(a0)
+
tst.b render_flags(a0)
 
bpl.s +
 
bpl.s +
move.b d0,($FFFFFFE1).w
+
move.b d0,(SFX_to_play).w
 
+
 
+
 
rts
 
rts
Line 114: Line 114:
 
Replace it with this:
 
Replace it with this:
 
<asm>PlaySoundLocal:
 
<asm>PlaySoundLocal:
tst.b 1(a0)
+
tst.b render_flags(a0)
 
bpl.s +
 
bpl.s +
 
move.b d0,($FFFFF00B).w
 
move.b d0,($FFFFF00B).w
Line 122: Line 122:
 
Next, we're going to fix the music so it stops correctly when you pause. Find the "+" after PauseGame, which should be this:
 
Next, we're going to fix the music so it stops correctly when you pause. Find the "+" after PauseGame, which should be this:
 
<asm>+
 
<asm>+
move.w #1,($FFFFF63A).w ; freeze time
+
move.w #1,(Game_paused).w ; freeze time
move.b #-2,($FFFFFFE0).w ; pause music</asm>
+
move.b #-2,(Music_to_play).w ; pause music</asm>
  
 
And replace it with this...
 
And replace it with this...
 
<asm>+
 
<asm>+
move.w #1,($FFFFF63A).w ; freeze time
+
move.w #1,(Game_paused).w ; freeze time
 
move.b #1,($FFFFF003).w ; pause music</asm>
 
move.b #1,($FFFFF003).w ; pause music</asm>
  
 
Next, go to loc_13F2, which should be this:
 
Next, go to loc_13F2, which should be this:
 
<asm>loc_13F2:
 
<asm>loc_13F2:
move.b #-1,($FFFFFFE0).w</asm>
+
move.b #-1,(Music_to_play).w</asm>
  
 
And replace it with this...
 
And replace it with this...
Line 140: Line 140:
 
Now, find Pause_SlowMo, which should be this:
 
Now, find Pause_SlowMo, which should be this:
 
<asm>Pause_SlowMo:
 
<asm>Pause_SlowMo:
move.w #1,($FFFFF63A).w
+
move.w #1,(Game_paused).w
move.b #-1,($FFFFFFE0).w
+
move.b #-1,(Music_to_play).w
 
rts</asm>
 
rts</asm>
  
 
And replace it with this...
 
And replace it with this...
 
<asm>Pause_SlowMo:
 
<asm>Pause_SlowMo:
move.w #1,($FFFFF63A).w
+
move.w #1,(Game_paused).w
 
move.b #1,($FFFFF003).w
 
move.b #1,($FFFFF003).w
 
rts</asm>
 
rts</asm>
Line 152: Line 152:
 
Next, find loc_541A, which should be this:
 
Next, find loc_541A, which should be this:
 
<asm>loc_541A:
 
<asm>loc_541A:
move.b #-1,($FFFFFFE0).w
+
move.b #-1,(Music_to_play).w
move.b #8,($FFFFF62A).w
+
move.b #8,(Delay_Time).w
 
bra.w DelayProgram</asm>
 
bra.w DelayProgram</asm>
  
Line 159: Line 159:
 
<asm>loc_541A:
 
<asm>loc_541A:
 
move.b #1,($FFFFF003).w
 
move.b #1,($FFFFF003).w
move.b #8,($FFFFF62A).w
+
move.b #8,(Delay_Time).w
 
bra.w DelayProgram</asm>
 
bra.w DelayProgram</asm>
  

Revision as of 13:36, 10 May 2008

(Original guide by Tweaker)

Introduction

For anyone who's worked with Sonic 2 before, you'll notice that managing music can be a bit of a hassle. Music has to be in a specific location, has to stay within a certain sound bank... and there's a limited number of sounds you can have in the game. However, the sound driver in Sonic 1 is entirely written in 68k (except for the DAC driver), making it much easier to edit, and much easier to manage music with. There are no limitations on where you can place music data, as the pointers use relative addressing.

So, when Puto comes to me with his own port of the Sonic 1 sound driver, and said he had problems, I showed him a personal port that Esrael made for Sonic 2 Megamix. Together, we were able to fully patch up all the issues that the driver has when ported to Sonic 2. Therefore, we decided we'd make a guide, that, when followed correctly, allows anybody to use the Sonic 1 sound driver in their hack! Included below is the Sonic 1 sound driver in its own separate ASM file, which you can edit freely, along with the original folder structure for the sound driver's music data, sound data, etc.

Anyway, on with the guide!

Instructions

Okay, first we're going to get the actual driver to load. Go to VintRet, which should be this: <asm>VintRet: addq.l #1,($FFFFFE0C).w movem.l (sp)+,d0-a6 rte</asm>

And change it to this... <asm>VintRet: jsr Init_Sonic1_Sound_Driver ; init Sonic 1 sound driver addq.l #1,($FFFFFE0C).w movem.l (sp)+,d0-a6 rte</asm>

Next, go to JmpTo_SoundDriverLoad, which should be this: <asm>JmpTo_SoundDriverLoad nop jmp (SoundDriverLoad).l

End of function JmpTo_SoundDriverLoad</asm>

And change the whole surrounding area to this, including the unused Sonic 1 sound driver loading code... <asm>JmpTo_SoundDriverLoad

nop
jmp (SoundDriverLoad).l
End of function JmpTo_SoundDriverLoad
===========================================================================
unused mostly-leftover subroutine to load the sound driver
SoundDriverLoadS1

move.w #$100,(Z80_Bus_Request).l ; stop the Z80 move.w #$100,(Z80_Reset).l ; reset the Z80 lea (Kos_Z80).l,a0 lea (Z80_RAM).l,a1 bsr.w KosDec move.b #$F3,(a1)+ move.b #$F3,(a1)+ move.b #$C3,(a1)+ move.b #0,(a1)+ move.b #0,(a1)+ move.w #0,(Z80_Reset).l nop nop nop nop move.w #$100,(Z80_Reset).l ; reset the Z80 move.w #0,(Z80_Bus_Request).l ; start the Z80 rts</asm>

Next, find PlayMusic, which should be this: <asm>PlayMusic: tst.b (Music_to_play).w bne.s + move.b d0,(Music_to_play).w rts + move.b d0,(Music_to_play_2).w rts

End of function PlayMusic</asm>

And change it to this... <asm>PlayMusic:

tst.b ($FFFFFFE0).w
bne.s +
move.b d0,($FFFFFFE0).w

move.b d0,($FFFFF00A).w rts + move.b d0,($FFFFF00A).w rts

End of function PlayMusic</asm>

Next find PlaySound, and find this: <asm>PlaySound: move.b d0,(SFX_to_play).w rts

End of function PlaySound</asm>

And replace it with this... <asm>PlaySound: move.b d0,($FFFFF00B).w rts

End of function PlaySound</asm>

Now, we're going to fix the broken sound effects, such as rings. Look for PlaySoundStereo. It should be this: <asm>PlaySoundStereo: move.b d0,(SFX_to_play_2).w rts

End of function PlaySoundStereo</asm>

Replace it with this: <asm>PlaySoundStereo: bra.s PlayMusic ; skip over routine (For S1 driver) move.b d0,(SFX_to_play_2).w rts

End of function PlaySoundStereo</asm>

Now, look for PlaySoundLocal. It should be this: <asm>PlaySoundLocal: tst.b render_flags(a0) bpl.s + move.b d0,(SFX_to_play).w + rts

End of function PlaySoundLocal</asm>

Replace it with this: <asm>PlaySoundLocal: tst.b render_flags(a0) bpl.s + move.b d0,($FFFFF00B).w + rts</asm>

Next, we're going to fix the music so it stops correctly when you pause. Find the "+" after PauseGame, which should be this: <asm>+ move.w #1,(Game_paused).w ; freeze time move.b #-2,(Music_to_play).w ; pause music</asm>

And replace it with this... <asm>+ move.w #1,(Game_paused).w ; freeze time move.b #1,($FFFFF003).w ; pause music</asm>

Next, go to loc_13F2, which should be this: <asm>loc_13F2: move.b #-1,(Music_to_play).w</asm>

And replace it with this... <asm>loc_13F2: move.b #$80,($FFFFF003).w</asm>

Now, find Pause_SlowMo, which should be this: <asm>Pause_SlowMo: move.w #1,(Game_paused).w move.b #-1,(Music_to_play).w rts</asm>

And replace it with this... <asm>Pause_SlowMo: move.w #1,(Game_paused).w move.b #1,($FFFFF003).w rts</asm>

Next, find loc_541A, which should be this: <asm>loc_541A: move.b #-1,(Music_to_play).w move.b #8,(Delay_Time).w bra.w DelayProgram</asm>

And replace it with this... <asm>loc_541A: move.b #1,($FFFFF003).w move.b #8,(Delay_Time).w bra.w DelayProgram</asm>

Now, we're going to fix the underwater palettes, since the sound driver uses some space in RAM that, in S2, is used for underwater palettes. Do a search and replace (ctrl+h) and replace all instances of "$FFFFF08" with "$FFFFFA8" - what this will do is make the game read from the Sonic 1 location for underwater palettes, which is unused in S2, and unaffected by the sound driver.

Next, go to PalLoad4_Water. This is the Sonic 2 equivalent of "PalLoad4_Water" in Sonic 1, and what we're going to do is change a line in it to match the Sonic 1 routine, so the underwater palettes load to the correct address. The routine should look like this: <asm>PalLoad4_Water: lea (PalPointers).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 suba.l #$B00,a3 move.w (a1)+,d7

- move.l (a2)+,(a3)+ dbf d7,- rts

End of function PalLoad4_Water</asm>

Change it to this: <asm>PalLoad4_Water: lea (PalPointers).l,a1 lsl.w #3,d0 adda.w d0,a1 movea.l (a1)+,a2 movea.w (a1)+,a3 suba.l #$80,a3 move.w (a1)+,d7

- move.l (a2)+,(a3)+ dbf d7,- rts

End of function PalLoad4_Water</asm>

What this does is change how much the game subtracts from $FB00, in order to calculate the location to move underwater palettes to.

The final step is to grab a slightly modified version of the Sonic 1 sound driver from Hivebrain's 2005 Sonic 1 disassembly (link below), and insert it into the Sonic 2 disassembly - the location does not matter, though I personally recommend the end of the ROM. You can also delete the Sonic 2 sound driver now, if you wish, though it is not required to do so.

You can either use the include directive to insert S1 Sound Driver.asm, or you can simply copy/paste what's in there. Either will be sufficient.

Note

Certain sound effects and music from Sonic 2 WILL be missing, and you WILL need to add these yourself if you wish to still have them in game. To add a sound effect/music, simply tack it at the end of SoundIndex or MusicIndex. You can also get rid of SoundD0Index (and related setup) if you wish, as Sonic 2 does not have any sound effects that require it. Kega may also mess up a tad bit, not sure why - if anyone can figure it out, let us know.

Sound Driver Files

Download.svg Download the Sonic 1 sound driver files
File: S1SoundDriverFiles.zip (66 kB) (info)

Credits

  • Varion Icaria - Puto's sound driver port.
  • Esrael - My 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.
  • Myself - I helped Puto fix the underwater stuff, and I wrote the guide. =P

And that's it! Enjoy! Let me or Puto know if there's any issues left, and we'll try and patch them up.