Expand the Sonic 1 sound index
From Sonic Retro
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 (2005 and 2021) 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 third and fourth 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.
Part 5: Sound Priorities
You might notice that certain sounds have higher priorities than they did originally; this is because Sonic 1 (and, by extension, most SMPS sound drivers) have a 'sound priority' system that determines which sounds should be played over others, and since we have extended the sound index, it is now reading garbage data.
To fix this, replace SoundPriorities with this:
SoundPriorities:
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $01
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $10
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $20
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $30
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $40
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $50
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $60
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $70
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $80
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $90
dc.b $80,$70,$70,$70,$70,$70,$70,$70,$70,$70,$68,$70,$70,$70,$60,$70 ; $A0
dc.b $70,$60,$70,$60,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$7F ; $B0
dc.b $60,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70,$70 ; $C0
dc.b $80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80,$80 ; $D0
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $E0
dc.b $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90 ; $F0
even
This properly expands the index to include all $FF entries.