Difference between revisions of "Port Sonic 3's Sound Driver to Sonic 1"
From Sonic Retro
(→recovering...) |
(→Replacing 68k driver with new Z80 driver) |
||
Line 492: | Line 492: | ||
dc.b $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $90 | dc.b $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $90 | ||
dc.b $90, $90, $90, $90 | dc.b $90, $90, $90, $90 | ||
− | |||
; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| |
Revision as of 05:35, 4 March 2011
(Original guide by Kram1024)
Updated by Kram1024
You probably saw a quick and dirty way to do this on SSRG, but lets do it the proper way, the way that sonic team would do it.
Contents
Overview
First off, Sonic 3's sound driver has the V_Int reloader built into it so it is not needed, some routines need replacement, sounds need fixing, and we need to replace the sounds and music. We will be using the hivebrain version, if you wish to do it via svn version, I am sure you can come up with a way that works by seeing what changes I made in the hivebrain version.
Preparing to use Sonic 3/K/3K sound system
The Vertical Interrupt and Horizontal Interrupt need to be fixed, since the sonic 1/2 system uses them but the Sonic 3/K/3K system doesn't.
Removal of master V_Int branch to s1driver point
first we will fix the vertical interrupt, by changing: <asm> loc_B5E: ; XREF: loc_B88 jsr (sub_71B4C).l </asm>
to: <asm> loc_B5E: ; XREF: loc_B88 nop </asm>
Removal of H_Int branch point to s1driver
Now we locate: <asm> loc_119E: ; XREF: PalToCRAM clr.b ($FFFFF64F).w movem.l d0-a6,-(sp) bsr.w Demo_Time jsr (sub_71B4C).l movem.l (sp)+,d0-a6 rte
- End of function PalToCRAM
</asm> See another familiar line? Yes, you've got it, do the same thing to it: <asm> loc_119E: ; XREF: PalToCRAM clr.b ($FFFFF64F).w movem.l d0-a6,-(sp) bsr.w Demo_Time nop movem.l (sp)+,d0-a6 rte
- End of function PalToCRAM
</asm> That effectively disables the sonic1 style v_int and h_int driver reloading that we will not need and prevents a nasty error down the road.
Upgrading the Load Driver Routine
Okay, we disabled the sonic1 driver junk, wouldn't we want now to use the sonic3 driver instead? Here is where we start installing it. Locate: <asm>
- ---------------------------------------------------------------------------
- Subroutine to load the sound driver
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
SoundDriverLoad: ; XREF: GameClrRAM; TitleScreen
nop
move.w #$100,($A11100).l ; stop the Z80
move.w #$100,($A11200).l ; reset the Z80
lea (Kos_Z80).l,a0 ; load sound driver
lea ($A00000).l,a1
bsr.w KosDec ; decompress
move.w #0,($A11200).l
nop
nop
nop
nop
move.w #$100,($A11200).l ; reset the Z80
move.w #0,($A11100).l ; start the Z80
rts
- End of function SoundDriverLoad
</asm>
and replace it all with: <asm>
- ---------------------------------------------------------------------------
- Subroutine to load the sound driver
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
SoundDriverLoad: ; XREF: GameClrRAM; TitleScreen nop move.w #$100,($A11100).l ; Z80 bus request - Start move.w #$100,($A11200).l ; Z80 stop reset lea (DriverData).l,a0 lea ($A00000).l,a1 move.w #DriverDataEnd-DriverData,d0
DriverLoadLoop: move.b (a0)+,(a1)+ dbf d0,DriverLoadLoop lea (DriverPointers).l,a0 lea ($A01300).l,a1 move.w #DriverPointersEnd-DriverPointers,d0
DriverPointersLoadLoop: move.b (a0)+,(a1)+ dbf d0, DriverPointersLoadLoop lea (UniversalVoiceBank).l,a0 lea ($A017D8).l,a1 move.w #UniversalVoiceBankEnd-UniversalVoiceBank,d0
UniversalVoiceBankLoadLoop: move.b (a0)+,(a1)+ dbf d0,UniversalVoiceBankLoadLoop lea (DriverResetData).l,a0 lea ($A01C00).l,a1 move.w #DriverResetDataEnd-DriverResetData,d0
DriverResetDataLoadLoop: move.b (a0)+,(a1)+ dbf d0,DriverResetDataLoadLoop btst #6,($FFFFFFF8).w beq.s DriverAlreadyInitialized move.b #1,($A01C02).l
DriverAlreadyInitialized: move.w #0,($A11200).l nop nop nop nop move.w #$100,($A11200).l ; Z80 start reset move.w #0,($A11100).l ; Z80 bus request - Stop rts
- End of function SoundDriverLoad
DriverResetData:
dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DriverResetDataEnd:
</asm>
Upgrading the Playback Routines
Now we have the code to load the new driver, time to add the new playback routines.
Upgrade Music Routine
First the PlaySound routine, locate: <asm>
- ---------------------------------------------------------------------------
- Subroutine to play a sound or music track
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PlaySound:
move.b d0,($FFFFF00A).w
rts
- End of function PlaySound
</asm>
and replace it completely with: <asm>
- ---------------------------------------------------------------------------
- Subroutine to play a sound or music track
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PlaySound:
cmpi.w #$FB,d0
blt.s PlayNotSpecialFlag
bhi.s TestForNormalSpeed
move #8,d0
jmp SetTempo
TestForNormalSpeed: cmpi.w #$FC,d0 bne.s PlayNotSpecialFlag clr.w d0 jmp SetTempo
PlayNotSpecialFlag: move.w #$100,($A11100).l
PlaySoundZ80NotStopped: btst #0,($A11100).l bne.s PlaySoundZ80NotStopped ; loop until it says it's stopped move.b d0,($A01C0A).l move.w #0,($A11100).l rts
- End of function PlaySound
- ---------------------------------------------------------------------------
- Exclusive sound/music subroutine
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PlaySound_Ex: tst.b 4(A0) bpl.s SkipPlaySound_Special </asm>
sound playback routines
now find: <asm>
- ---------------------------------------------------------------------------
- Subroutine to play a special sound/music (E0-E4)
- E0 - Fade out
- E1 - Sega
- E2 - Speed up
- E3 - Normal speed
- E4 - Stop
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PlaySound_Special:
move.b d0,($FFFFF00B).w
rts
- End of function PlaySound_Special
- ===========================================================================
- ---------------------------------------------------------------------------
- Unused sound/music subroutine
- ---------------------------------------------------------------------------
PlaySound_Unk: move.b d0,($FFFFF00C).w rts </asm>
and replace it entirely with: <asm>
- ---------------------------------------------------------------------------
- Unused sound/music subroutine
- ---------------------------------------------------------------------------
PlaySound_Unk: nop
- ---------------------------------------------------------------------------
- Subroutine to play a special sound/music (FB-FF)
- ---------------------------------------------------------------------------
PlaySound_Special: move.w #$100,($A11100).l
PlaySound_SpecialZ80NotStopped: btst #0,($A11100).l bne.s PlaySound_SpecialZ80NotStopped cmp.b ($A01C0B).l,d0 beq.s PlaySound_Special1 tst.b ($A01C0B).l bne.s PlaySound_Special0 move.b d0,($A01C0B).l move.w #0,($A11100).l rts
PlaySound_Special0: move.b d0,($A01C0C).l
PlaySound_Special1: move.w #0,($A11100).l
SkipPlaySound_Special: rts
- End of function PlaySound_Special
- ---------------------------------------------------------------------------
- Subroutine to change the music tempo
- ---------------------------------------------------------------------------
SetTempo: move.w #$100,($A11100).l
SetTempoZ80NotStopped: btst #0,($A11100).l bne.s SetTempoZ80NotStopped move.b D0,($A01C08).l move.w #0,($A11100).l rts </asm>
Upgrading Pause / Resume routines
Now the playback routines are fixed and we have a routine to set the tempo the way the sneakers do, which we will elaberate later on, but we still have to update the pause / resume routines to the sonic 3 equivilents.
Find: <asm>
- ---------------------------------------------------------------------------
- Subroutine to pause the game
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PauseGame: ; XREF: Level_MainLoop; et al
nop
tst.b ($FFFFFE12).w ; do you have any lives left?
beq.s Unpause ; if not, branch
tst.w ($FFFFF63A).w ; is game already paused?
bne.s loc_13BE ; if yes, branch
btst #7,($FFFFF605).w ; is Start button pressed?
beq.s Pause_DoNothing ; if not, branch
loc_13BE: move.w #1,($FFFFF63A).w ; freeze time move.b #1,($FFFFF003).w ; pause music
loc_13CA: move.b #$10,($FFFFF62A).w bsr.w DelayProgram tst.b ($FFFFFFE1).w ; is slow-motion cheat on? beq.s Pause_ChkStart ; if not, branch btst #6,($FFFFF605).w ; is button A pressed? beq.s Pause_ChkBC ; if not, branch move.b #4,($FFFFF600).w ; set game mode to 4 (title screen) nop bra.s loc_1404
- ===========================================================================
Pause_ChkBC: ; XREF: PauseGame btst #4,($FFFFF604).w ; is button B pressed? bne.s Pause_SlowMo ; if yes, branch btst #5,($FFFFF605).w ; is button C pressed? bne.s Pause_SlowMo ; if yes, branch
Pause_ChkStart: ; XREF: PauseGame btst #7,($FFFFF605).w ; is Start button pressed? beq.s loc_13CA ; if not, branch
loc_1404: ; XREF: PauseGame move.b #$80,($FFFFF003).w
Unpause: ; XREF: PauseGame move.w #0,($FFFFF63A).w ; unpause the game
Pause_DoNothing: ; XREF: PauseGame rts
- ===========================================================================
Pause_SlowMo: ; XREF: PauseGame move.w #1,($FFFFF63A).w move.b #$80,($FFFFF003).w rts
- End of function PauseGame
</asm>
and replace it completely with: <asm>
- ---------------------------------------------------------------------------
- Subroutine to pause the game
- ---------------------------------------------------------------------------
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
PauseGame: ; XREF: Level_MainLoop; et al
nop
tst.b ($FFFFFE12).w
beq Unpause
tst.w ($FFFFF63A).w
bne.s PauseGame_AlreadyPaused
move.b ($FFFFF605).w,d0
or.b ($FFFFF607).w,d0
andi.b #$80,d0
beq Pause_DoNothing
PauseGame_AlreadyPaused: move.w #1,($FFFFF63A).w move.w #$100,($A11100).l
PauseGameZ80NotStopped: btst #0,($A11100).l bne.s PauseGameZ80NotStopped move.b #1,($A01C10).l move.w #0,($A11100).l
PauseGameLoop: move.b #$10,($FFFFF62A).w jsr DelayProgram tst.b ($FFFFFFE1).w ; Edit: the value is $FFFFFFE1 in Sonic 1 beq.s Pause_ChkStart btst #6,($FFFFF605).w beq.s Pause_ChkBC move.b #$4,($FFFFF600).w ; Go To Title Screen nop bra.s PauseGame1
Pause_ChkBC: btst #4,($FFFFF604).w bne.s Pause_SlowMo btst #5,($FFFFF605).w bne.s Pause_SlowMo
Pause_ChkStart: cmpi.b #$E,($FFFFFE10).w bcs.s PauseGame0 cmpi.b #$12,($FFFFFE10).w bhi.s PauseGame0 tst.b ($FFFFFF8B).w bpl.s PauseGame0 btst #4,($FFFFF605).w beq.s PauseGame0 move.b #$C0,($FFFFF600).w bra.s PauseGame1
PauseGame0: move.b ($FFFFF605).w,d0 or.b ($FFFFF607).w,d0 andi.b #$80,d0 beq.s PauseGameLoop
PauseGame1: move.w #$100,($A11100).l
Pause_ChkStartZ80NotStopped: btst #0,($A11100).l bne.s Pause_ChkStartZ80NotStopped move.b #$80,($A01C10).l move.w #0,($A11100).l
Unpause: move.w #0,($FFFFF63A).w
Pause_DoNothing: rts
Pause_SlowMo: move.w #1,($FFFFF63A).w move.w #$100,($A11100).l
Pause_SlowMoZ80NotStopped: btst #0,($A11100).l bne.s Pause_SlowMoZ80NotStopped move.b #$80,($A01C10).l move.w #0,($A11100).l rts
- End of function PauseGame
</asm>
Replacing 68k driver with new Z80 driver
We need the sound driver itself if we are going to have any sound and music, so we locate: <asm> align 2
Go_SoundTypes: dc.l SoundTypes ; XREF: Sound_Play Go_SoundD0: dc.l SoundD0Index ; XREF: Sound_D0toDF Go_MusicIndex: dc.l MusicIndex ; XREF: Sound_81to9F Go_SoundIndex: dc.l SoundIndex ; XREF: Sound_A0toCF off_719A0: dc.l byte_71A94 ; XREF: Sound_81to9F Go_PSGIndex: dc.l PSG_Index ; XREF: sub_72926
- ---------------------------------------------------------------------------
- PSG instruments used in music
- ---------------------------------------------------------------------------
PSG_Index: dc.l PSG1, PSG2, PSG3 dc.l PSG4, PSG5, PSG6 dc.l PSG7, PSG8, PSG9 PSG1: binclude sound\psg1.bin PSG2: binclude sound\psg2.bin PSG3: binclude sound\psg3.bin PSG4: binclude sound\psg4.bin PSG6: binclude sound\psg6.bin PSG5: binclude sound\psg5.bin PSG7: binclude sound\psg7.bin PSG8: binclude sound\psg8.bin PSG9: binclude sound\psg9.bin
byte_71A94: dc.b 7, $72, $73, $26, $15, 8, $FF, 5
- ---------------------------------------------------------------------------
- Music Pointers
- ---------------------------------------------------------------------------
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
- ---------------------------------------------------------------------------
- Type of sound being played ($90 = music; $70 = normal sound effect)
- ---------------------------------------------------------------------------
SoundTypes: dc.b $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90 dc.b $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $90, $80 dc.b $70, $70, $70, $70, $70, $70, $70, $70, $70, $68, $70, $70, $70, $60, $70, $70 dc.b $60, $70, $60, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $7F, $60 dc.b $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $70, $80 dc.b $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $80, $90 dc.b $90, $90, $90, $90
- ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
sub_71B4C: ; XREF: loc_B10; PalToCRAM
move.w #$100,($A11100).l ; stop the Z80
nop
nop
nop
loc_71B5A: btst #0,($A11100).l bne.s loc_71B5A
btst #7,($A01FFD).l beq.s loc_71B82 move.w #0,($A11100).l ; start the Z80 nop nop nop nop nop bra.s sub_71B4C
- ===========================================================================
loc_71B82: lea ($FFF000).l,a6 clr.b $E(a6) tst.b 3(a6) ; is music paused? bne.w loc_71E50 ; if yes, branch subq.b #1,1(a6) bne.s loc_71B9E jsr sub_7260C(pc)
loc_71B9E: move.b 4(a6),d0 beq.s loc_71BA8 jsr sub_72504(pc)
loc_71BA8: tst.b $24(a6) beq.s loc_71BB2 jsr sub_7267C(pc)
loc_71BB2: tst.w $A(a6) ; is music or sound being played? beq.s loc_71BBC ; if not, branch jsr Sound_Play(pc)
loc_71BBC: cmpi.b #$80,9(a6) beq.s loc_71BC8 jsr Sound_ChkValue(pc)
loc_71BC8: lea $40(a6),a5 tst.b (a5) bpl.s loc_71BD4 jsr sub_71C4E(pc)
loc_71BD4: clr.b 8(a6) moveq #5,d7
loc_71BDA: adda.w #$30,a5 tst.b (a5) bpl.s loc_71BE6 jsr sub_71CCA(pc)
loc_71BE6: dbf d7,loc_71BDA
moveq #2,d7
loc_71BEC: adda.w #$30,a5 tst.b (a5) bpl.s loc_71BF8 jsr sub_72850(pc)
loc_71BF8: dbf d7,loc_71BEC
move.b #$80,$E(a6) moveq #2,d7
loc_71C04: adda.w #$30,a5 tst.b (a5) bpl.s loc_71C10 jsr sub_71CCA(pc)
loc_71C10: dbf d7,loc_71C04
moveq #2,d7
loc_71C16: adda.w #$30,a5 tst.b (a5) bpl.s loc_71C22 jsr sub_72850(pc)
loc_71C22: dbf d7,loc_71C16 move.b #$40,$E(a6) adda.w #$30,a5 tst.b (a5) bpl.s loc_71C38 jsr sub_71CCA(pc)
loc_71C38: adda.w #$30,a5 tst.b (a5) bpl.s loc_71C44 jsr sub_72850(pc)
loc_71C44: move.w #0,($A11100).l ; start the Z80 rts
- End of function sub_71B4C
</asm>