Actions

SCHG How-to

Expand the music index to start at $00 instead of $80

From Sonic Retro

(Original guide by HPZMan)

(S2 addition by Clownacy)

Note for Sonic 1: If you’re going to use all sound slots in Sonic 1, refer to this guide here for a newer method. - JGMR

Here's a easy way on how to use all slots from $00 to $FF on the Sonic 1 M68K Sound Driver and Sonic 2 Z80 Sound Driver.

Sonic 1

Some notes:

  • After the changes, the addresses $FFFFFFFC and $FFFFFFFD will be used. Technically, it aren't new slots. Instead of this, it is a duplication from the slots $80 using a unique different index.

Slots $00 to $7F

Make a search for PlaySound:. You will see this:

PlaySound:
		move.b	d0,($FFFFF00A).w
		rts


Change to this:

PlaySound:
		cmpi.b  #$7F,d0
		ble.s   ChkSounds00to7F
		jmp	 NormalSoundRequest
ChkSounds00to7F:
		cmpi.b  #$01,d0
		bge.s   LoadSlots00to7F
		jmp	 NormalSoundRequest
LoadSlots00to7F:
		add.b   #$80,d0; Add $80 to get slot to starts at $81			
		move.b  #$01,($FFFFFFFC).w; Move $01 to $FFFFFC to make sound driver to load the secound index
NormalSoundRequest:
		move.b	d0,($FFFFF00A).w
		rts


Make a search for PlaySound_Special: You can see this:

PlaySound_Special:
		move.b	d0,($FFFFF00B).w
		rts


Change to this:

PlaySound_Special:
		cmpi.b  #$7F,d0
		ble.s   ChkSounds00to7F_Special
		jmp	 NormalSoundRequest_Special
ChkSounds00to7F_Special:

		cmpi.b  #$01,d0
		bge.s   LoadSlots00to7F_Special
		jmp	 NormalSoundRequest_Special
LoadSlots00to7F_Special:
		add.b   #$80,d0; Add $80 to get slot to starts at $81			
		move.b  #$01,($FFFFFFFC).w; Move $01 to $FFFFFC to make the sound driver to load the secound index
NormalSoundRequest_Special:
		move.b	d0,($FFFFF00B).w
		rts


Search for loc_7202C:, you will see this:

loc_7202C:
		jsr	sub_725CA(pc)
		movea.l	(off_719A0).l,a4
		subi.b	#$81,d7
		move.b	(a4,d7.w),$29(a6)
		movea.l	(Go_MusicIndex).l,a4


Change to this:

loc_7202C:
		jsr	sub_725CA(pc)
		movea.l	(off_719A0).l,a4
		subi.b	#$81,d7
		move.b	(a4,d7.w),$29(a6)
		movea.l	(Go_MusicIndex).l,a4
		cmpi.b  #$01,($FFFFFFFD).w
		bne.s   CheckSounds00to80
		movea.l	(Go_MusicIndexFF).l,a4
		jmp	 NormalIndexLoad
CheckSounds00to80:
		cmpi.b  #$01,($FFFFFFFC).w
		bne.s   NormalIndexLoad
		movea.l	(Go_MusicIndex00).l,a4		
NormalIndexLoad:
		clr.w   ($FFFFFFFC).w


Search for Go_MusicIndex:, you can see this:

Go_MusicIndex:	dc.l MusicIndex; XREF: Sound_81to9F


Below the Go_MusicIndex: code, add this:

Go_MusicIndex00:	dc.l MusicIndex00
Go_MusicIndexFF:	dc.l MusicIndexFF

Slots $E5 to $FF

Search for Sound_ChkValue:, you will see this:

Sound_ChkValue:; XREF: sub_71B4C
		moveq	#0,d7
		move.b	9(a6),d7
		beq.w	Sound_E4
		bpl.s	locret_71F8C
		move.b	#$80,9(a6); reset	music flag
		cmpi.b	#$9F,d7
		bls.w	Sound_81to9F; music	$81-$9F
		cmpi.b	#$A0,d7
		bcs.w	locret_71F8C
		cmpi.b	#$CF,d7
		bls.w	Sound_A0toCF; sound	$A0-$CF
		cmpi.b	#$D0,d7
		bcs.w	locret_71F8C
		cmpi.b	#$E0,d7
		bcs.w	Sound_D0toDF; sound	$D0-$DF
		cmpi.b	#$E4,d7
		bls.s	Sound_E0toE4; sound	$E0-$E4

locret_71F8C:
		rts


Change to this:

Sound_ChkValue:; XREF: sub_71B4C
		moveq	#0,d7
		move.b	9(a6),d7
		beq.w	Sound_E4
		bpl.s	locret_71F8C
		move.b	#$80,9(a6); reset	music flag
		cmpi.b  #$01,($FFFFFFFC).w
		bne.s   Load81to9F
		jmp	 Sound_ChkValueFor00
Load81to9F:
		cmpi.b	#$9F,d7
		bls.w	Sound_81to9F; music	$81-$9F
ContinueSound_ChkValue:
		cmpi.b	#$A0,d7
		bcs.w	locret_71F8C
		cmpi.b	#$CF,d7
		bls.w	Sound_A0toCF; sound	$A0-$CF
		cmpi.b	#$D0,d7
		bcs.w	locret_71F8C
		cmpi.b	#$E0,d7
		bcs.w	Sound_D0toDF; sound	$D0-$DF
		cmpi.b	#$E4,d7
		bls.s	Sound_E0toE4; sound	$E0-$E4
		cmpi.b  #$FF,d7
		bls.w   Sound_E5toFF

locret_71F8C:
		rts


Search for Sound_81to9F: and above Sound_81to9F, add this:

Sound_ChkValueFor00:
		cmpi.b  #$FF,d7; $FF = Last slot for musics in index $00 - $7F ($FF = $7F)
		bls.w   Sound_81to9F
		rts

Sound_E5toFF:
		move.b  #$01,($FFFFFFFD).w
		sub.b   #$64,d7

Inserting new songs

Now you just need to create the pointers for the songs at the index, and include them! To do it for the songs $01 to $7F, create in some place a index called MusicIndex00:. The index have to work like this:

MusicIndex00:
		dc.l	Music01; Music for slot $01
		dc.l	Music02; Music for slot $02
......


To the songs $E5 to $FF, create in some place a index called MusicIndexFF. The index have to work like this:

MusicIndexFF:
		dc.l	MusicE5; Music for slot $E5
		dc.l	MusicE6; Music for slot $E6
......


Making the Sound Test values to start at $00

Search for loc_3550:, you will see this:

		addi.w	#$80,d0

Remove or comment this line.


Make a search for LevelSelect:, below from this you can see:

		addi.w	#$80,d0

Remove or comment this line.


Search for LevSel_Right:, above it you will see this:

		bcc.s	LevSel_Right
		moveq	#$4F,d0; if sound test	moves below 0, set to $4F

Change or comment these lines.


Search for LevSel_Refresh2:, above it you will see this:

		cmpi.w	#$50,d0
		bcs.s	LevSel_Refresh2
		moveq	#0,d0; if sound test	moves above $4F, set to	0

Remove or comment these lines.


Fixing possible problems with sound effects and songs

Go to SoundTypes:, you can see this:

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


Change to this:

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,	$90
		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,	$90
		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,	$90
		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,	$90
		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,	$90
		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,	$90
		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,	$90
		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, $90


It should fix possible problems on play songs/sound effects and will not interfere the original songs and sound effects.

Optional - Putting the default Sonic 1 songs at the $0X slots index

Go to the index for songs $8X, MusicIndex.

Copy the pointers from it, remove them and paste it at the begin from the $0X slot index MusicIndex00.

Done.

Sonic 2

Relocating the silence value

Open s2.sounddriver.asm, and go to zUpdateEverything. There, you'll find this:

	; Apparently if this is 80h, it does not play anything new,
	; otherwise it cues up the next play (flag from 68K for new item)
	ld	a,	(zQueueToPlay)
	cp	80h
	call	nz,zPlaySoundByIndex	; If not 80h, we need to play something new!

As you can tell by the comments, you need to change the cp's value from 80h to 0. But wait! It's better to use an 'or a', which does the same thing, but is faster and smaller. Doing that will give you this:

	; Apparently if this is 00h, it does not play anything new,
	; otherwise it cues up the next play (flag from 68K for new item)
	ld	a,	(zQueueToPlay)
	or	a
	call	nz,zPlaySoundByIndex	; If not 00h, we need to play something new!

Next up, zCycleQueue. Here, we face the same problem: a 'cp 80h'. Again, change it to an 'or a'.

zPlaySoundByIndex. This one's interesting. Here, you can see how, if sound 00h were to be played, the driver would reset itself. This is likely part of its initialisation process, where, initially, sound 00h would technically be queued. We'll have to remove this, but this shouldn't be an issue, as the same reset code is branched to at the Z80's Entry Point. This check is just a leftover from the original Sonic 1 driver, and is now redundant.

Just remove everything until 'ld (ix+8),80h'. Also, change the '80h' in this instruction to '0'. However, if you don't intend for your music IDs to start at 01h, the ID immediately after the silence value, then you'll want to keep the 'cp MusID__First' and 'ret c' instructions, in order to prevent crashes when invalid sounds are played.

zPlaySegaSound. This features a little optimisation we'll have to deal with: instead of a straightforward 'cp 80h', 80h is moved to a register, and that register is used instead. Understandable, since a low cycle count is a necessity for PCM streaming. In fact, a 'cp r' is just as small and just as fast as an 'or a'.

There are two instances of 'ld c,80h', the second one is what we're looking for. Again, you could just move 0 to the register, but while we can't optimise the loop itself, we can slightly optimise the code that sets up the loop. So, remove this instruction. Inside the loop, you'll find 'cp c'. Change this to 'or a'.

zClearTrackPlaybackMem. Here, zQueueToPlay is set to 80h. We don't want that, so change 'ld a,80h' into 'xor a'. Again, instead of 'ld a,0', we're using a smaller and faster way of doing the same thing. Do this at zInitMusicPlayback, also.

That's all for s2.sounddriver.asm. Now, onto s2.asm.

Got to sndDriverInput, and find 'cmpi.b #$80,8(a1)'. Change it to 'tst.b 8(a1)'.

And with that, you're done. As you've seen earlier, even before making the silence sound occupy it, sound 00h was unusable, so in merging the two, we've also freed up a sound ID. Bonus! Now you're free to move your sound IDs to occupy the >80h range of slots, and you don't have to worry about sound 80h, so you can have a song or an SFX occupy it with no ill effects!

But we're not done yet. If you're going to extend your sound IDs into the >80h range, then you'll likely want your sound tests to cover that range, too.

Extending the sound tests

We'll start with the level select's sound test. Go to LevSelControls_CheckLR and remove these two lines:

	bcc.s	+
	moveq	#$7F,d0

Then remove these three:

	cmpi.w	#$80,d0
	blo.s	+
	moveq	#0,d0

Then change this...

	btst	#button_A,d1
	beq.s	+
	addi.b	#$10,d0
	andi.b	#$7F,d0

+

...into this:

	btst    #button_A,d1
        beq.s   +
        addi.b  #$10,d0
        bcc.s   +
        moveq   #0,d0

+

And remove this:

	addi.w	#$80,d0

That's that sound test done. Onto the options menu's sound test.

Go to OptionScreen_Controls, and change this...

	btst	#button_A,d0
	beq.s	+
	addi.b	#$10,d2
	cmp.b	d3,d2
	bls.s	+
	moveq	#0,d2

+

...into this:

	cmpi.b	#2,(Options_menu_box).w
	bne.s	+	; rts
	btst    #button_A,d0
        beq.s   +
        addi.b  #$10,d2
        bcc.s   +
        moveq   #0,d2

+

Under that, remove this:

	addi.w	#$80,d0

Then go to OptionScreen_Choices, and change this...

	dc.l ($80-1)<<24

...into:

	dc.l $FF<<24

Conclusion

With that, we've removed the obstacle of the silence value's placement, freed up a sound ID, optimised the driver's code a little (in both size and speed), and extended the sound tests. All that's left to do is lift the '20h music files per bank' cap.

SCHG How-To Guide: Sonic the Hedgehog (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix the SEGA Sound | Display the Press Start Button Text | Fix the Level Select Menu | Fix the Hidden Points Bug | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix the Walk-Jump Bug | Correct Drowning Bugs | Fix the Death Boundary Bug | Fix the Camera Follow Bug | Fix Song Restoration Bugs | Fix the HUD Blinking | Fix the Level Select Graphics Bug | Fix a remember sprite related bug
Changing Design Choices
Change Spike Behavior | Collide with Water After Being Hurt | Fix Special Stage Jumping Physics | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Remove the Speed Cap | Port the REV01 Background Effects | Port Sonic 2's Level Art Loader | Retain Rings Between Acts | Add Sonic 2 (Simon Wai Prototype) Level Select | Improve ObjectMove Subroutines | Add Sonic 2 Level Select | Collide with Water After Being Hurt | Smooth Out Rotation in Special Stages
Adding Features
Add Spin Dash ( Part 1 (GitHub)/(Hivebrain) / Part 2 / Part 3 / Part 4 ) | Add Eggman Monitor | Add Super Sonic | Add Extended Camera | Add the Air Roll | Add 6-Button Support
Sound Features
Expand the Sound Index | Play Different Songs Per Act | Port Sonic 2 Final Sound Driver | Port Sonic 3's Sound Driver | Change The SEGA Sound
Extending the Game
Load Chunks From ROM | Add Extra Characters | Make an Alternative Title Screen | Use Dynamic Tilesets | Make GHZ Load Alternate Art | Make Ending Load Alternate Art | Add a New Zone | Set Up the Goggle Monitor | Add New Moves | Add a Dynamic Collision System | Dynamic Special Stage Walls System | Extend Sprite Mappings and Art Limit | Enigma Credits | Use Dynamic Palettes
Miscellaneous
Convert the Hivebrain 2005 Disassembly to ASM68K
Split Disassembly Guides
Set Up a Split Disassembly | Basic Level Editing | Basic Art Editing | Basic ASM Editing (Spin Dash)
SCHG How-To Guide: Sonic the Hedgehog 2 (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix Super Sonic Bugs | Use Correct Height When Roll Jumping | Fix Jump Height Bug When Exiting Water | Fix Screen Boundary Spin Dash Bug | Correct Drowning Bugs | Fix Camera Y Position for Tails | Fix Tails Subanimation Error | Fix Tails' Respawn Speeds | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix Rexon Crash | Fix Monitor Collision Bug | Fix EHZ Deformation Bug | Correct CPZ Boss Attack Behavior | Fix Bug in ARZ Boss Arrow's Platform Behavior | Fix ARZ Boss Walking on Air Glitch | Fix ARZ Boss Sprite Behavior | Fix Multiple CNZ Boss Bugs | Fix HTZ Background Scrolling Mountains | Fix OOZ Launcher Speed Up Glitch | Fix DEZ Giant Mech Collision Glitch | Fix Boss Deconstruction Behavior | Fix Speed Bugs | Fix 14 Continues Cheat | Fix Debug Mode Crash | Fix 99+ Lives | Fix Sonic 2's Sega Screen
Design Choices
Remove the Air Speed Cap | Disable Floor Collision While Dying | Modify Super Sonic Transformation Methods & Behavior | Enable/Disable Tails in Certain Levels | Collide with Water After Being Hurt | Retain Rings When Returning at a Star Post | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Insert LZ Water Ripple Effect | Restore Lost CPZ Boss Feature | Prevent SCZ Tornado Spin Dash Death | Improve ObjectMove Subroutines | Port S3K Rings Manager | Port S3K Object Manager | Port S3K Priority Manager | Edit Level Order with ASM‎ | Alter Ring Requirements in Special Stages | Make Special Stage Characters Use Normal DPLCs | Speed Up Ring Loss Process | Change spike behaviour in Sonic 2
Adding Features
Create Insta-kill and High Jump Monitors | Create Clone and Special Stage Monitors | Port Knuckles
Sound Features
Expand Music Index to Start at $00 | Port Sonic 1 Sound Driver | Port Sonic 2 Clone Driver | Port Sonic 3 Sound Driver | Port Flamewing's Sonic 3 & Knuckles Sound Driver | Expand the Music Index to Start at $00 (Sonic 2 Clone Driver Version) | Play Different Songs Per Act
Extending the Game
Extend the Level Index Past $10 | Extend the Level Select | Extend Water Tables | Add Extra Characters | Free Up 2 Universal SSTs

|Expand the music index to start at $00 instead of $80]]