SCHG How-to

SCHG How-to:Add the options menu into Sonic 3 & Knuckles

From Sonic Retro

since Mustapha's guide uses a pre-assembled rom AND uses Sonic 3 alone since Sonic 3 & Knuckles does not contain these leftovers (making me wonder why it's in S3K's section in the first place), AND because Nik Pi wants me to do this tutorial, i'm gonna tell you now how to add the S2 options menu into S3K. this guide is for the Github disasm of Sonic & Knuckles, and will (probably) work on 'S3 Complete' (a version of S3K that has the redundancies stripped out)

you'll need:

  • s3.asm
  • sonic3k.asm

open s3.asm and go to:

		lea	(RAM_start).l,a1
		lea	(MapEni_S2Options).l,a0
		move.w	#$70,d0
		bsr.w	Eni_Decomp
		lea	(RAM_start+$160).l,a1
		lea	(MapEni_S2Options).l,a0
		move.w	#$2070,d0
		bsr.w	Eni_Decomp
		clr.b	(Options_menu_box).w
		bsr.w	OptionScreen_DrawSelected
		addq.b	#1,(Options_menu_box).w
		bsr.w	OptionScreen_DrawUnselected
		addq.b	#1,(Options_menu_box).w
		bsr.w	OptionScreen_DrawUnselected
		clr.b	(Options_menu_box).w
		clr.b	(Level_started_flag).w
		clr.w	(Anim_Counters).w
		lea	(AniPLC_SONICMILES).l,a2
		jsr	(AnimateTiles_DoAniPLC).l
		moveq	#4,d0
		bsr.w	LoadPalette
		moveq	#signextendB(mus_DataSelect),d0
		bsr.w	Play_Sound
                ; more code

copy all of the subroutines until you reach

off_6878:	dc.l TextOptScr_0

you will also need to copy

		move.w	(Level_select_cheat_counter).w,d0
		adda.w	d0,a0
		move.w	(Sound_test_sound).w,d0
		cmp.b	(a0),d0
		bne.s	loc_6E88
		addq.w	#1,(Level_select_cheat_counter).w
		tst.b	1(a0)
		bne.s	loc_6E8E
		move.w	#$101,(a1)
		moveq	#signextendB(sfx_RingRight),d0
		jsr	(Play_Sound_2).l

		move.w	#0,(Level_select_cheat_counter).w

		move.w	(Debug_mode_cheat_counter).w,d0
		adda.w	d0,a2
		move.w	(Sound_test_sound).w,d0
		cmp.b	(a2),d0
		bne.s	loc_6EC8
		addq.w	#1,(Debug_mode_cheat_counter).w
		tst.b	1(a2)
		bne.s	locret_6ECE
		tst.w	d2
		bne.s	loc_6EBA
		move.b	#$F,(Continue_count).w
		moveq	#signextendB(mus_Continue),d0
		jsr	(Play_Sound).l
		bra.s	loc_6EC8
; ---------------------------------------------------------------------------

		move.w	#7,(Emerald_count).w
		moveq	#signextendB(mus_Emerald),d0
		jsr	(Play_Sound).l

		move.w	#0,(Debug_mode_cheat_counter).w

		levselstr "* PLAYER SELECT *"
		levselstr "SONIC AND MILES"
		levselstr "SONIC AND TAILS"
		levselstr "SONIC ALONE    "
		levselstr "MILES ALONE    "
		levselstr "TAILS ALONE    "
		levselstr "* VS MODE ITEMS *"
		levselstr "ALL KINDS ITEMS"
		levselstr "TELEPORT ONLY  "
		levselstr "*  SOUND TEST   *"
		levselstr "      00       "


		moveq	#0,d1
		move.b	(a1)+,d1

		move.b	(a1)+,d0
		move.w	d0,(a2)+
		dbf	d1,loc_6542

and you MIGHT need to copy

		dc.b  $19, $65,   9, $17,   0
		dc.b    1,   1,   2,   4,   0
		dc.b    1,   3,   5,   7,   0
		dc.b    2,   4,   5,   6,   0

copy all these to sonic3k.asm you can paste them wherever you like, i personally like to keep them where they were in s3.asm (right before SpecialStage) build now and you'll get tons of errors when trying to build sonic & knuckles most of them are to do with short addressing, so let's get that out of the way you'll need to alter any (Options_menu_box).w's to (Options_menu_box).l, there are ~18 occurences then there's 1 other short addressing occurence this time with 'Current_zone_2p', do the same as to Options_menu_box but it's not over yet! build sk again and you'll find 3 other errors: 2 out of range errors (depending on where you place the subroutines you might not get these) and 1 symbol double defined error. all have to do with 'loc_6696', so to avoid complications, change the label in your subroutines to any valid label (i go with loc_6696b)

you might think 'that's it, right? surely it should bui-' nope, the cake isn't yet eaten. build after you've resolved these errors and you'll get a SWOTH of errors in their place. most of them have to do with 'symbol undefined' but there is 1 (and there will be another one later) involving Update_SSMap being out of range now. let's go fix that.

		bsr.w	Rotate_SSPal
		bsr.w	Do_ControllerPal
		bsr.w	Update_SSMap
		tst.w	(Demo_timer).w
		beq.w	+
		subq.w	#1,(Demo_timer).w
		jmp	(Set_Kos_Bookmark).l

note: there might be 2 errors in this subroutine however there's only 1 shown. let's fix both though

for a start, create 2 new subroutines: (you can name them anything as long as it's a new name that another label doesn't use)

JmpTo_Rotate_SSPal: jmp Rotate_SSPal
JmpTo_Update_SSMap: jmp Update_SSMap

then, change VInt_1C to use them both:

		bsr.w	JmpTo_Rotate_SSPal
		bsr.w	Do_ControllerPal
		bsr.w	JmpTo_Update_SSMap

then let's resolve the symbol unknown errors. first let's fix MapEni_S2Options

		binclude "General/Sprites/S2Menu/Enigma Map/Options Screen.bin"

place it anywhere

remember Options_menu_box and Current_zone_2p? yeah well those don't exist in S3K's RAM they do exist in S3's RAM however and are readily usable, all we need to do is copy them open s3.constants.asm and sonic3k.constants.asm and from s3.constants.asm copy:

phase _tempFF88
Current_zone_2P			ds.b 1			; left over from Sonic 2
Current_act_2P			ds.b 1			; left over from Sonic 2
Options_menu_box =		_tempFF8C		; byte ; left over from Sonic 2
_unkFF98 =			_tempFF98		; word ; unused

copy these into sonic3k.constants.asm anywhere now, if you get new errors after this, resolve them. after that, you WILL encounter this:

> > > sonic3k.asm(1978):9: error: symbol undefined
> > > done1360
> > >   bmi.s $$done
> > >         ~~~~~~
> > > sonic3k.asm(2007):9: error: symbol undefined
> > > done1361
> > >   bmi.s $$done
> > >         ~~~~~~
> > > sonic3k.asm(2376):9: error: symbol undefined
> > > enoughBits1397
> > >   bcc.s $$enoughBits ; branch if a new word doesn't need to be read
> > >         ~~~~~~~~~~~~
> > > sonic3k.asm(2399):9: error: symbol undefined
> > > justEnough1397
> > >   beq.s $$justEnough ; if the word has been exactly exhausted, branch
> > >         ~~~~~~~~~~~~
> > > sonic3k.asm(2571):9: error: symbol undefined
> > > freeSlotFound1412
> > >   beq.s $$freeSlotFound
> > >         ~~~~~~~~~~~~~~~
> > > sonic3k.asm(2621):9: error: symbol undefined
> > > modulesLeft1416
> > >   bne.s $$modulesLeft
> > >         ~~~~~~~~~~~~~
> > > sonic3k.asm(2628):9: error: symbol undefined
> > > decompressionStarted1416
> > >   bmi.s $$decompressionStarted
> > >         ~~~~~~~~~~~~~~~~~~~~~~

there are more errors, and just when you think it's the end they just keep coming. you have to replace all of the symbols with unique names, there's just no other way that i know of

now it should let you build, but wait!! you forgot 1 thing!! how do you access the menu?? for now we're just gonna make it replace the level select menu. the middle options box will lead you the level select menu anyway. go to loc_4270 and replace #$28 with #$24

then go to Gamemodes replace gamemode $24's pointer with MenuScreen_Options. gamemode $24 should be marked with a comment

'NOW that should be-' shush

obviously it's not the end

i mean it works but THIS is likely what you're gonna see, except without a BG and font (image from the S3K polish project i've been working on): Bad.png

in fact, how i got the BG and font loaded is by copying the beginning of MenuScreen_S2Options and adding it to the beginning of MenuScreen_Options

i haven't figured out a way to load the box gfx yet

SCHG How-To Guide: Sonic the Hedgehog 3 and Knuckles
Fixing Bugs
Fix Blue Knuckles | Fix Tails' Respawn Speeds | Fix Super Sonic Bugs
Design Choices
Fix Scattered Rings' Underwater Physics | Edit Level Select Text & Pointers | Work with Water | Make the Slots Bonus Game Rotate Smoothly
Adding Features
Restore (Sonic 2) Options Menu

|Add the options menu into Sonic 3 & Knuckles]]