Expand the Sonic 1 sound index
From Sonic Retro
Revision as of 01:45, 17 October 2021 by Alex Field (talk | contribs) (→Part 4: Crash Fix: Explained the crash)
In Sonic 1, the sound index is limited from $81 to $E4, allowing for $63 possible slots; this is unlike Sonic 2, which allows slots from $81 to $FF, and Sonic 3 & Knuckles, which is $01 to $FF. Naturally, some people would like to extend this range.
Fortunately, this isn't very hard to do; in fact, the prototype does allow for more IDs, so why not apply this to the final? Note that this is designed for the Github disassembly, although Hivebrain users shouldn't have a hard time making it work with their disassembly.
Contents
Part 1: $81-$9F
This first part will Firstly, in Constants.asm, change bgm__First to $01.
Secondly, in s1.sounddriver.asm, find this piece of code, and then delete it:
cmpi.b #$80,v_sound_id(a6) ; is song queue set for silence (empty)?
beq.s @nonewsound ; If yes, branch
jsr PlaySoundID(pc)
; loc_71BC8:
@nonewsound:
Then, at CycleSoundQueue, you should see this batch of code:
cmpi.b #$80,v_sound_id(a6) ; Is v_sound_id a $80 (silence/empty)?
beq.s @havesound ; If yes, branch
move.b d1,v_soundqueue0(a6) ; Put sound into v_soundqueue0
bra.s @nextinput
; ===========================================================================
; loc_71F2C:
@havesound:
Delete it too, since it prevents $01-$80 from being played. Just below it, you'll see a return command; delete it and its label, alongside replacing the branch above to PlaySoundID. Finally at PlaySoundID, delete the second and third lines.
We're already done, but we might as well perform a bit of optimization; replace PlaySoundID with this:
moveq #0,d7
move.b v_sound_id(a6),d7
move.b #$80,v_sound_id(a6) ; reset music flag
; Music
cmpi.b #bgm__Last,d7 ; Is this music?
bls.w Sound_PlayBGM ; Branch if yes
cmpi.b #sfx__First,d7 ; Is this after music but before sfx?
blo.w @locret ; Return if yes
; SFX
cmpi.b #sfx__Last,d7 ; Is this sfx?
bls.w Sound_PlaySFX ; Branch if yes
cmpi.b #spec__First,d7 ; Is this after sfx but before special sfx?
blo.w @locret ; Return if yes
; Special SFX
cmpi.b #spec__Last,d7 ; Is this special sfx?
bls.w Sound_PlaySpecial ; Branch if yes
cmpi.b #flg__First,d7 ; Is this after special sfx but before the commands?
blo.w @locret ; Return if yes
; Sound Commands
cmpi.b #flg__Last,d7 ; Is this sound commands?
bls.s Sound_E0toE4 ; Branch if yes
What this does is fully prevent crashes if invalid IDs (i.e. ones that haven't been defined) are played; this also removes the need for this check at LevSel_NoCheat:
; This is a workaround for a bug; see PlaySoundID for more.
; Once you've fixed the bugs there, comment these four instructions out.
cmpi.w #bgm__Last+1,d0 ; is sound $80-$93 being played?
blo.s LevSel_PlaySnd ; if yes, branch
cmpi.w #sfx__First,d0 ; is sound $94-$9F being played?
blo.s LevelSelect ; if yes, branch
LevSel_PlaySnd:
We'll be coming back to the level select later to expand the sound test range, but for now we'll move on to...
Part 2: $E5-$FF
This one, unlike the previous part, is stupidly simple; change flg__First in Constants.asm to $FB. The game's maximum sound range is already $FF, although this does raise the question of why they didn't do this, considering it would've saved more sound IDs for use.
Part 3: Extending the Level Select
Although the sound ID range has already been extended, the level select's sound test range hasn't, so let's fix that.
In sonic.asm, at LevelSelect, remove the 'addi.w #$80,d0'; then, at LevSel_SndTest, remove these two bits of code:
bhs.s LevSel_Right
moveq #$4F,d0 ; if sound test moves below 0, set to $4F
...
cmpi.w #$50,d0
blo.s LevSel_Refresh2
moveq #0,d0 ; if sound test moves above $4F, set to 0
There's another 'addi.w #$80,d0' at LevSel_DrawSnd; delete that as well.
Part 4: Crash Fix
There's one last fix before we leave, and that's to fix crashes when playing a sound with an ID that is above >$3F; at Sound_notA7 and Sound_PlaySpecial, add this before 'move.b (a1)+,d7':
moveq #0,d7
The crash is due to its starting ID being zero based by the sound driver, so $DF = $3F, and $E0 = $40; this is multiplied by 4 (since each pointer is long-word in length), so $3F becomes $FC, and $40 becomes... $100, which is beyond the sound index range, so the line below the one we just inserted blanks the register. This is actually how Ristar handles the fix.
There, now you're done.
|Expand the Sonic 1 sound index]]