Actions

SCHG How-to

Port Knuckles into Sonic 2

From Sonic Retro

Revision as of 15:58, 7 February 2013 by MainMemory (talk | contribs)

(Original guide by MainMemory)
Note: this guide is written with the Sonic 2 Hg disassembly in mind.

Getting the Knuckles object and putting it in Sonic 2

First you will need s2k.asm from the Knuckles in Sonic 2 disassembly.
Open s2k.asm, select everything from Obj01: (line 27324) to the end of ArtConvTable (line 30585), and copy it into a new asm file called Knuckles.asm in your S2 disasm folder. This is so we don't accidentally change something in our Sonic 2 disassembly while we're fixing Knuckles.
Open Knuckles.asm and do a Find and Replace operation to replace every instance of "Obj01" (without quotes) with "ObjXX", where XX is the object ID you want Knuckles to use. The following IDs are unused in Sonic 2: 4C, 4D, 4E, 4F, 62, D0, D1, and everything from DD to FF. Use that ID whenever I refer to ObjXX.
Next, do the following replacements: "CheckGameOver" to "ObjXX_CheckGameOver", "JmpTo_KillCharacter" to "JmpToK_KillCharacter", "Player_CheckFloor" to "Sonic_CheckFloor".
Find the line <asm> bsr.w Adjust2PArtPointer2_Useless</asm> and change it to <asm> jsr Adjust2PArtPointer2</asm> Now you'll need to copy some more code from s2k.asm. Specifically, sub_3192E6, loc_318FE8, sub_318FF6, loc_319208 and loc_3193D2. Because they're all small routines, I'll paste them here: <asm>; =============== S U B R O U T I N E =======================================

Doesn't exist in S2

sub_3192E6:  ; ... move.b $17(a0),d0 ext.w d0 sub.w d0,d2 eor.w #$F,d2 lea ($FFFFF768).w,a4 move.w #-$10,a3 move.w #$800,d6 bsr.w FindFloor move.b #$80,d2

loc_319306: bra.w loc_318FE8

End of function sub_3192E6
START OF FUNCTION CHUNK FOR CheckRightWallDist

loc_318FE8:  ; ... move.b ($FFFFF768).w,d3 btst #0,d3 beq.s return_318FF4 move.b d2,d3

return_318FF4:  ; ... rts

END OF FUNCTION CHUNK FOR CheckRightWallDist
=============== S U B R O U T I N E =======================================


sub_318FF6:  ; ... move.b $17(a0),d0 ext.w d0 add.w d0,d2 lea ($FFFFF768).w,a4 move.w #$10,a3 move.w #0,d6 bsr.w FindFloor move.b #0,d2 bra.s loc_318FE8

End of function sub_318FF6
---------------------------------------------------------------------------
This doesn't exist in S2...
START OF FUNCTION CHUNK FOR sub_315C22

loc_319208:  ; ... move.b $17(a0),d0 ext.w d0 add.w d0,d3 lea ($FFFFF768).w,a4 move.w #$10,a3 move.w #0,d6 bsr.w FindWall move.b #$C0,d2 bra.w loc_318FE8

END OF FUNCTION CHUNK FOR sub_315C22
---------------------------------------------------------------------------
START OF FUNCTION CHUNK FOR sub_315C22

loc_3193D2:  ; ... move.b $17(a0),d0 ext.w d0 sub.w d0,d3 eor.w #$F,d3 lea ($FFFFF768).w,a4 move.w #$FFF0,a3 move.w #$400,d6 bsr.w FindWall move.b #$40,d2 bra.w loc_318FE8

END OF FUNCTION CHUNK FOR sub_315C22</asm>

Put this code at the end of Knuckles' asm.

Now we're ready to put the code in our S2 disassembly, so open s2.asm. You can place Knuckles' code wherever you want, but the place that seems to cause the fewest errors is right before Obj79. You can either add the line <asm>include "Knuckles.asm"</asm> or just copy and paste his code in.
When you do that, run build.bat in the S2 disassembly. It should tell you there are 14 errors and to check s2.log, so that's what we'll do. Everything in the log will be in this format:

> > >s2.asm(line#): error: jump distance too big
> > > 	bsr.w	label

What you need to do is go to each line and change the bsr.w to jsr. There is one line that's a bra.w instead, change that to jmp.

Importing Knuckles' art and mappings

If you try to build now, you will see three "symbol undefined" errors: SK_Map_Knuckles, SK_PLC_Knuckles and SK_ArtUnc_Knux. So let's fix those.

For SK_Map_Knuckles, you need to take Knuckles' sprite mappings from S&K and convert them to Sonic 2 format. There are two ways to do this:

  • Using SonMapEd, set the Game Format setting to "Sonic 3 & Knuckles", load the mappings file, change the Game Format setting to "Sonic 2", and save the mappings as Knuckles.asm in the mappings/sprite folder of your S2 disasm.
  • Using my mappings converter, load the mappings with input set to Game: "Sonic 3 & Knuckles", Format: ASM and output set to Game: "Sonic 2", Format: ASM, and save the mappings as Knuckles.asm in the mappings/sprite folder of your S2 disasm.
  • If you're using the MapMacros branch of the S2 disassembly as a base, you can also set the output format to "ASM with Macros".

Then, in s2.asm, somewhere near Mapunc_Sonic, add the line <asm>SK_Map_Knuckles: include "mappings/sprite/Knuckles.asm"</asm>
For SK_PLC_Knuckles, you can simply take Knuckles' DPLCs from S&K and save them as Knuckles.asm in the mappings/spriteDPLC folder of your S2 disasm, since the DPLC format is the same for S3K's players and Sonic 2.
Then, in s2.asm, somewhere near MapRUnc_Sonic, add the line <asm>SK_PLC_Knuckles: include "mappings/spriteDPLC/Knuckles.asm"</asm>
For SK_ArtUnc_Knux, take Knuckles' art from S&K and save it as Knuckles.bin in the art/uncompressed folder of your S2 disasm.
Then, in s2.asm, somewhere near ArtUnc_Sonic, add the lines <asm> align $20 SK_ArtUnc_Knux: BINCLUDE "art/uncompressed/Knuckles.bin"</asm>

Optimizing Knuckles' art loading

This step is optional, but recommended.
You may have noticed that Knuckles' art file is the same file as S3K, even though the two games' palettes are organized differently. This is possible because Knuckles' code dynamically recolors all his sprites in LoadKnucklesDynPLC_Part2. This saves some space in the KiS2 ROM, but for a Sonic 2 hack, it's just wasting CPU, so we'll remove it.
Select everything under the line bmi.w return_31753E in LoadKnucklesDynPLC_Part2 up to (but not including) return_31753E, and delete it. Replace it with this code, modified from LoadSonicDynPLC_Part2: <asm> move.w #tiles_to_bytes(ArtTile_ArtUnc_Sonic),d4

loc_1B86E

KPLC_ReadEntry: moveq #0,d1 move.w (a2)+,d1 move.w d1,d3 lsr.w #8,d3 andi.w #$F0,d3 addi.w #$10,d3 andi.w #$FFF,d1 lsl.l #5,d1 addi.l #SK_ArtUnc_Knux,d1 move.w d4,d2 add.w d3,d4 add.w d3,d4 jsr (QueueDMATransfer).l dbf d5,KPLC_ReadEntry ; repeat for number of entries</asm> Then you can delete ArtConvTable and the comments above it.
Now you just need File:S2KnuxArt.zip, and replace Knuckles' art file (art/uncompressed/Knuckles.bin) with that.