Add Extra Characters To Sonic 2
From Sonic Retro
(Original guide by ManicRemix)
(Guide updated by ThomasSpeedrunner and JGMR)
I was very surprised that this guide didn't exist anywhere else. It seems like nowadays this is the "what everybody has in their hacks" type of thing. This guide will show you how to add extra characters to Sonic the Hedgehog 2 (16-bit). We will use the Xenowhirl/SVN/Hg/GitHub disassembly. In this guide, I will refer to Knuckles and Amy.
First, open up s2.asm. Search for "Obj_Index:".
You will see this (or something like it). Here's what you'll find if you're using the Xenowhirl/SVN disassembly:
; =========================================================================== ; --------------------------------------------------------------------------- ; OBJECT POINTER ARRAY ; object pointers ; sprite pointers ; object list ; sprite list ; ; This array contains the pointers to all the objects used in the game. ; The item in the comment is the hex pointer index value used by the game ; (and our hacking guides) to reference an object. ; --------------------------------------------------------------------------- Obj_Index: ; ObjPtrs: ; loc_1600C: dc.l Obj01 ; Sonic dc.l Obj02 ; Tails dc.l Obj03 ; Collision plane/layer switcher dc.l Obj04 ; Surface of the water dc.l Obj05 ; Tails' tails dc.l Obj06 ; Rotating cylinder in MTZ, twisting spiral pathway in EHZ dc.l Obj07 ; Oil in OOZ dc.l Obj08 ; Water splash in Aquatic Ruin Zone, Spindash dust dc.l Obj09 ; Sonic in Special Stage dc.l Obj0A ; Small bubbles from Sonic's face while underwater...
And it will go on in this format. If you're using the Hg/GitHub disassembly, it may look like this:
; =========================================================================== ; --------------------------------------------------------------------------- ; OBJECT POINTER ARRAY ; object pointers ; sprite pointers ; object list ; sprite list ; ; This array contains the pointers to all the objects used in the game. ; --------------------------------------------------------------------------- Obj_Index: ; ObjPtrs: ; loc_1600C: ObjPtr_Sonic: dc.l Obj01 ; Sonic ObjPtr_Tails: dc.l Obj02 ; Tails ObjPtr_PlaneSwitcher: dc.l Obj03 ; Collision plane/layer switcher ObjPtr_WaterSurface: dc.l Obj04 ; Surface of the water ObjPtr_TailsTails: dc.l Obj05 ; Tails' tails ObjPtr_Spiral: dc.l Obj06 ; Rotating cylinder in MTZ, twisting spiral pathway in EHZ ObjPtr_Oil: dc.l Obj07 ; Oil in OOZ ObjPtr_SpindashDust: ObjPtr_Splash: dc.l Obj08 ; Water splash in Aquatic Ruin Zone, Spindash dust ObjPtr_SonicSS: dc.l Obj09 ; Sonic in Special Stage ObjPtr_SmallBubbles: dc.l Obj0A ; Small bubbles from Sonic's face while underwater...
And it will go on in this format. Now, search for "dc.l ObjNull". Replace these lines:
dc.l ObjNull ; Obj4C dc.l ObjNull ; Obj4D
with this. For the Xenowhirl/SVN disassemblies, you should have this:
dc.l Obj4C ; Knuckles dc.l Obj4D ; Amy
For the Hg/GitHub disassemblies, this is how it should look like:
ObjPtr_Knuckles: dc.l Obj4C ; Knuckles ObjPtr_Amy: dc.l Obj4D ; Amy
You've now created a Knuckles object and an Amy object. These are the object IDs that will be used for your two new characters.
Next, search for "InitPlayers:". You will see this (or something like it). Here's what you'll find if you're using the Xenowhirl/SVN disassembly:
InitPlayers_TailsAlone: move.b #2,(MainCharacter).w ; load Obj02 Tails object at $FFFFB000 move.b #8,(Tails_Dust).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100 addi.w #4,(MainCharacter+y_pos).w rts
If you're using the Hg/GitHub disassembly, it may look like this:
InitPlayers_TailsAlone: move.b #ObjID_Tails,(MainCharacter+id).w ; load Obj02 Tails object at $FFFFB000 move.b #ObjID_SpindashDust,(Tails_Dust+id).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100 addi_.w #4,(MainCharacter+y_pos).w rts
Now, below:
InitPlayers_TailsAlone:
add
subq.w #1,d0 bne.s InitPlayers_KnuxAlone ; branch if this is a Knuckles alone game
Now, below the "rts", add the following. It should look like this for Xenowhirl/SVN disassemblies:
InitPlayers_KnuxAlone: subq.w #1,d0 bne.s InitPlayers_AmyAlone ; branch if this is an Amy alone game move.b #$4C,(MainCharacter).w move.b #8,(Sonic_Dust).w rts InitPlayers_AmyAlone: move.b #$4D,(MainCharacter).w move.b #8,(Sonic_Dust).w rts
Or this for Hg/GitHub disassemblies:
InitPlayers_KnuxAlone: subq.w #1,d0 bne.s InitPlayers_AmyAlone ; branch if this is an Amy alone game move.b #ObjID_Knuckles,(MainCharacter+id).w move.b #ObjID_SpindashDust,(Sonic_Dust+id).w rts InitPlayers_AmyAlone: move.b #ObjID_Amy,(MainCharacter+id).w move.b #ObjID_SpindashDust,(Sonic_Dust+id).w rts
Now, to actually set up the characters. We'll show you two methods, one for the Xenowhirl/SVN disassembly and one for the Hg/GitHub disassembly. We'll start with the Xenowhirl/SVN disassembly first, but if you're using the Hg/GitHub disassembly, you can skip the following and move on to the Hg/GitHub disassembly section.
First, search for "word_917A:", and replace "dc.w $2FF" with "dc.w $4FF". The number you put there will represent the number of characters you have. This is "Sonic", "Tails", "Amy", & "Knuckles".
Next, search for "off_92DE:", and below "byte_981C", add "dc.l byte_KTEA", and "dc.l byte_AYRE".
Now search for "byte_981C: dc.b $E,"TAILS ALONE "", and below it add
byte_KTEA: dc.b $E,"KNUCKLES ALONE " byte_AYRE: dc.b $E,"AMY ALONE "
Now, the next method is for the Hg/GitHub disassemblies. Go to s2.constants.asm. Find this line:
ObjID_Buzzer = id(ObjPtr_Buzzer) ; 4B
And insert this under it:
ObjID_Knuckles = id(ObjPtr_Knuckles) ; 4C ObjID_Amy = id(ObjPtr_Amy) ; 4D
Next, go to "OptionScreen_Choices:", and find this line:
dc.l (3-1)<<24|(Player_option&$FFFFFF)
Change the 3 to a 5. This will allow for Knuckles and Amy player options. Now go here:
off_92D2: dc.l TextOptScr_SonicAndMiles dc.l TextOptScr_SonicAlone dc.l TextOptScr_MilesAlone
And add this under it:
dc.l TextOptScr_KnuxAlone dc.l TextOptScr_AmyAlone
Now, head here:
off_92DE: dc.l TextOptScr_SonicAndTails dc.l TextOptScr_SonicAlone dc.l TextOptScr_TailsAlone
Add the same two lines as before under:
dc.l TextOptScr_TailsAlone
Now find this:
TextOptScr_TailsAlone: menutxt "TAILS ALONE " ; byte_981C:
And add this below it:
TextOptScr_KnuxAlone: menutxt "KNUCKLES ALONE " TextOptScr_AmyAlone: menutxt "AMY ALONE "
And there you have it! You now have two new characters. Now you will need to make new sprites, palette, and code for them to work. A good starting point would be to copy and paste Sonic's code into a new ASM file and change the labels so that you don't get "symbol double defined" errors. Happy hacking!
|Add Extra Characters To Sonic 2]]