Difference between revisions of "Tailsguy24/How to Port Knuckles into Sonic 2"
From Sonic Retro
< User:Tailsguy24
GerbilSoft (talk | contribs) (Moved from Sandbox. Sandbox is for testing out simple stuff, not writing a whole article.) |
(Added some interwiki and external links. I'm still working on Additional Step #4) |
||
(8 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | + | It surprises me that nobody else took up responsibility for making this guide, considering I, as a major fan of hacks, have seen [[Knuckles]] implemented in [[Sonic 2]] on more than one occasion. Today, I'll be explaining how you, too, can implement Knuckles in your Sonic 2 hack. | |
− | It surprises me that nobody else took up responsibility for making this guide, considering I, as a major fan of hacks, have seen Knuckles implemented in Sonic 2 on more than one occasion. Today, I'll be explaining how you, too, can implement Knuckles in your Sonic 2 hack. | + | ==What You'll Need== |
− | |||
*This guide (no duh, really) | *This guide (no duh, really) | ||
− | *The Hg disassembly of Sonic 2 | + | *The [http://repo.sonicretro.org/MegaDrive-Genesis-32X/s2disasm_hg/archive/default.zip Hg disassembly of Sonic 2] |
− | *The one known disassembly of Knuckles in Sonic 2, found on the long list of [[disassemblies]]. | + | *The one known [http://repo.sonicretro.org/MegaDrive-Genesis-32X/ktes2_hg/archive/default.zip disassembly of Knuckles in Sonic 2], found on the long list of [[disassemblies]]. |
− | *The ConTEXT text editor (because Notepad will take WAY too long to process anything | + | *The [http://www.contexteditor.org/ ConTEXT] text editor (or [http://notepad-plus-plus.org/ Notepad++] with the [[File:UserDefineLang-68000-Z80.zip]] ported), because Notepad will take WAY too long to process anything |
− | *Your favorite Genesis emulator (I recommend Kega Fusion but you can use any Genesis emulator you'd like) | + | *Your favorite Genesis emulator (I recommend [[Kega Fusion]] but you can use any [http://segaretro.org/Category:Mega_Drive_Emulators Genesis emulator] you'd like) |
+ | *[[SonMapEd]] | ||
+ | *The [http://repo.sonicretro.org/MegaDrive-Genesis-32X/skdisasm_hg/archive/default.zip S3K Hg disassembly] (for art and other related stuff) | ||
− | + | ==IMPORTANT NOTES== | |
− | '''DO NOT''' try to rebuild the ROM once you've started this guide or you will get build errors. | + | First note: '''DO NOT''' try to rebuild the ROM once you've started this guide or you will get build errors. |
− | + | Second note: There is quite a lot of code added in this tutorial and it '''will''' make the ASM file's size quite a bit bigger than they were before. 150+ KB, to be precise. | |
+ | |||
+ | Third note: This guide is used on a clean disassembly, so make sure that your disassembly does not have any objects already ported. | ||
+ | |||
+ | Fourth note: In addition to the second note, this guide, if followed, will also cause the size of the ROM to double. Port Sonic 1's sound driver first so nothing fails. | ||
+ | |||
+ | Final note: Please remember that this is a work-in-progress guide that I will improve upon as more is uncovered. | ||
==Step 1: Creating the Knuckles object== | ==Step 1: Creating the Knuckles object== | ||
− | First, open up s2.asm in | + | First, open up s2.asm in the text editor and search for "dc.l ObjNull." This should come up: |
<asm> | <asm> | ||
dc.l ObjNull ; Obj4C | dc.l ObjNull ; Obj4C | ||
Line 33: | Line 40: | ||
==Step 2: Creating the offset table== | ==Step 2: Creating the offset table== | ||
− | Now that you have created your Knuckles object, go to whatever folder you saved the Knuckles in Sonic 2 disassembly to, open s2k.asm in | + | Now that you have created your Knuckles object, go to whatever folder you saved the Knuckles in Sonic 2 disassembly to, open s2k.asm in the text editor, and scroll down or search until you find the following code: |
<asm> | <asm> | ||
Obj01_Index: dc.w Obj01_Init-Obj01_Index ; 0 ; ... | Obj01_Index: dc.w Obj01_Init-Obj01_Index ; 0 ; ... | ||
Line 4,636: | Line 4,643: | ||
Change all "Obj01"s to "Obj4C"s. | Change all "Obj01"s to "Obj4C"s. | ||
==And we're done!== | ==And we're done!== | ||
− | Finally, we can stop worrying about Knuckles' code and get on with our lives. : | + | Finally, we can stop worrying about Knuckles' code and get on with our lives. :D |
− | + | ==Additional Steps== | |
− | + | ===Additional Step #1: Making Obj4C's ObjPtr=== | |
+ | Just when you thought you were done with this, you found out that I found out this! Getting tired? Well, this step should begin to solve your problems! Go to s2.constants.asm and find these two lines: | ||
+ | <asm> | ||
+ | ObjID_Buzzer = id(ObjPtr_Buzzer) ; 4B | ||
+ | ObjID_Aquis = id(ObjPtr_Aquis) ; 50 | ||
+ | </asm> | ||
+ | Uh oh, it seems an observant eye may catch the fact that the index goes from 4B straight to 50. skipping the first four null object values. We're going to add one to change that number to three. Between the two previously mentioned lines, add this: | ||
+ | <asm> | ||
+ | ObjID_Knuckles = id(ObjPtr_Knuckles) ; 4C | ||
+ | </asm> | ||
+ | And there you go! However, there is still much more to do. | ||
+ | ===Additional Step #2: Upgrading some branch commands=== | ||
+ | Now look at the s2.log file (the one with all the errors) and you should see this: | ||
+ | <asm> | ||
+ | > > >s2.asm(57477): error: jump distance too big | ||
+ | > > > bsr.w ResumeMusic ; <-- | ||
+ | > > >s2.asm(57504): error: jump distance too big | ||
+ | > > > bsr.w ResumeMusic ; <-- | ||
+ | > > >s2.asm(57524): error: jump distance too big | ||
+ | > > > bsr.w ResumeMusic ; <-- | ||
+ | > > >s2.asm(57546): error: jump distance too big | ||
+ | > > > bsr.w AnglePos ; <-- | ||
+ | > > >s2.asm(57671): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftCeilingDist ; <-- | ||
+ | > > >s2.asm(57680): error: jump distance too big | ||
+ | > > > bsr.w CheckRightCeilingDist ; <-- | ||
+ | > > >s2.asm(58216): error: jump distance too big | ||
+ | > > > bsr.w AnglePos ; <-- | ||
+ | > > >s2.asm(58447): error: jump distance too big | ||
+ | > > > bsr.w CalcRoomInFront ; <-- ; Also known as Sonic_WalkSpeed in Sonic 1 | ||
+ | > > >s2.asm(58935): error: jump distance too big | ||
+ | > > > bsr.w CalcRoomOverHead ; <-- | ||
+ | > > >s2.asm(59163): error: jump distance too big | ||
+ | > > > bsr.w AnglePos ; <-- | ||
+ | > > >s2.asm(59244): error: jump distance too big | ||
+ | > > > bsr.w AnglePos | ||
+ | > > >s2.asm(59433): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftWallDist ; <-- | ||
+ | > > >s2.asm(59441): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59462): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftWallDist ; <-- | ||
+ | > > >s2.asm(59470): error: jump distance too big | ||
+ | > > > bsr.w CheckCeilingDist ; <-- | ||
+ | > > >s2.asm(59486): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59513): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftWallDist ; <-- | ||
+ | > > >s2.asm(59521): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59529): error: jump distance too big | ||
+ | > > > bsr.w CheckCeilingDist ; <-- | ||
+ | > > >s2.asm(59540): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59548): error: jump distance too big | ||
+ | > > > bsr.w CheckCeilingDist ; <-- | ||
+ | > > >s2.asm(59598): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftWallDist ; <-- | ||
+ | > > >s2.asm(59605): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59662): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftWallDist ; <-- | ||
+ | > > >s2.asm(59672): error: jump distance too big | ||
+ | > > > bsr.w CheckCeilingDist ; <-- | ||
+ | > > >s2.asm(59701): error: jump distance too big | ||
+ | > > > bsr.w CheckLeftWallDist ; <-- | ||
+ | > > >s2.asm(59708): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59715): error: jump distance too big | ||
+ | > > > bsr.w CheckCeilingDist ; <-- | ||
+ | > > >s2.asm(59740): error: jump distance too big | ||
+ | > > > bsr.w CheckRightWallDist ; <-- | ||
+ | > > >s2.asm(59750): error: jump distance too big | ||
+ | > > > bsr.w CheckCeilingDist ; <-- | ||
+ | > > >s2.asm(59875): error: jump distance too big | ||
+ | > > > blt.w JmpTo_KillCharacter | ||
+ | > > >s2.asm(59893): error: symbol double defined | ||
+ | > > > JMPTO_KILLCHARACTER | ||
+ | > > > JmpTo_KillCharacter: ; ... | ||
+ | > > >s2.asm(59923): error: jump distance too big | ||
+ | > > > bsr.w CheckGameOver | ||
+ | > > >s2.asm(59935): error: symbol double defined | ||
+ | > > > CHECKGAMEOVER | ||
+ | > > > CheckGameOver: | ||
+ | </asm> | ||
+ | At every indicated line, change 'bsr.w' to 'jsr'. Here's an example: | ||
+ | <asm> | ||
+ | bsr.w CalcRoomInFront ; Also known as Sonic_WalkSpeed in Sonic 1 | ||
+ | </asm> | ||
+ | Change it to this: | ||
+ | <asm> | ||
+ | jsr CalcRoomInFront ; Also known as Sonic_WalkSpeed in Sonic 1 | ||
+ | </asm> | ||
+ | Now go get 'em, tiger. However, there are also 2 label-command pairs in need of renaming. | ||
+ | Both of 'em are at the end of this list. Change this: | ||
+ | <asm> | ||
+ | bsr.w CheckGameOver | ||
+ | </asm> | ||
+ | Add "Knux" (no quotes) to it so it looks like this: | ||
+ | <asm> | ||
+ | bsr.w CheckGameOverKnux | ||
+ | </asm> | ||
+ | Do the same thing with the other command, as well as their respective labels. You must be getting tired of this, and trust me, we're almost done, but now there's another set of errors to fix. | ||
+ | ===Additional Step #3: Repairing a few branches=== | ||
+ | The second error list should look like this: | ||
+ | <asm> | ||
+ | > > >s2.asm(57287): error: symbol undefined | ||
+ | > > > SK_Map_Knuckles | ||
+ | > > > move.l #SK_Map_Knuckles,4(a0) ; SK_Map_Knuckles | ||
+ | > > >s2.asm(57297): error: symbol undefined | ||
+ | > > > Adjust2PArtPointer2_Useless | ||
+ | > > > bsr.w Adjust2PArtPointer2_Useless | ||
+ | > > >s2.asm(57814): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(57867): error: symbol undefined | ||
+ | > > > sub_3192E6 | ||
+ | > > > bsr.w sub_3192E6 ; Doesn't exist in S2 | ||
+ | > > >s2.asm(57915): error: symbol undefined | ||
+ | > > > sub_318FF6 | ||
+ | > > > bsr.w sub_318FF6 | ||
+ | > > >s2.asm(58046): error: symbol undefined | ||
+ | > > > loc_319208 | ||
+ | > > > bra.w loc_319208 | ||
+ | > > >s2.asm(58052): error: symbol undefined | ||
+ | > > > loc_3193D2 | ||
+ | > > > bra.w loc_3193D2 | ||
+ | > > >s2.asm(59449): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(59500): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(59563): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(59612): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(59687): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(59765): error: symbol undefined | ||
+ | > > > Player_CheckFloor | ||
+ | > > > bsr.w Player_CheckFloor | ||
+ | > > >s2.asm(60380): error: symbol undefined | ||
+ | > > > SK_PLC_Knuckles | ||
+ | > > > lea (SK_PLC_Knuckles).l,a2 ; SK_PLC_Knuckles | ||
+ | > > >s2.asm(60380): error: addressing mode not allowed here | ||
+ | > > > lea (SK_PLC_Knuckles).l,a2 ; SK_PLC_Knuckles | ||
+ | > > >s2.asm(60401): error: symbol undefined | ||
+ | > > > SK_ArtUnc_Knux | ||
+ | > > > lea (SK_ArtUnc_Knux).l,a1 ; SK_ArtUnc_Knux | ||
+ | > > >s2.asm(60401): error: addressing mode not allowed here | ||
+ | > > > lea (SK_ArtUnc_Knux).l,a1 ; SK_ArtUnc_Knux | ||
+ | > > >s2.asm(74551): error: addressing mode not allowed on 68000 | ||
+ | > > > move.w word_38810(pc,d1.w),d2 | ||
+ | > > >s2.asm(74551): error: addressing mode not allowed here | ||
+ | > > > move.w word_38810(pc,d1.w),d2 | ||
+ | > > >s2.asm(74556): error: addressing mode not allowed on 68000 | ||
+ | > > > lea byte_38820(pc,d1.w),a1 | ||
+ | > > >s2.asm(74556): error: addressing mode not allowed here | ||
+ | > > > lea byte_38820(pc,d1.w),a1 | ||
+ | > > >s2.asm(83462): error: addressing mode not allowed on 68000 | ||
+ | > > > lea Touch_Sizes(pc,d0.w),a2 | ||
+ | > > >s2.asm(83462): error: addressing mode not allowed here | ||
+ | > > > lea Touch_Sizes(pc,d0.w),a2 | ||
+ | > > >s2.asm(83726): error: addressing mode not allowed on 68000 | ||
+ | > > > move.w Enemy_Points(pc,d0.w),d0 | ||
+ | > > >s2.asm(83726): error: addressing mode not allowed here | ||
+ | > > > move.w Enemy_Points(pc,d0.w),d0 | ||
+ | > > >s2.asm(85000): error: addressing mode not allowed on 68000 | ||
+ | > > > move.w AnimPatMaps(pc,d0.w),d0 | ||
+ | > > >s2.asm(85000): error: addressing mode not allowed here | ||
+ | > > > move.w AnimPatMaps(pc,d0.w),d0 | ||
+ | > > >s2.asm(85001): error: addressing mode not allowed on 68000 | ||
+ | > > > lea AnimPatMaps(pc,d0.w),a0 | ||
+ | > > >s2.asm(85001): error: addressing mode not allowed here | ||
+ | > > > lea AnimPatMaps(pc,d0.w),a0 | ||
+ | </asm> | ||
+ | About half of those errors can be fixed by going through the Knuckles code and replacing each instance of this: | ||
+ | <asm> | ||
+ | bsr.w Player_CheckFloor | ||
+ | </asm> | ||
+ | With this: | ||
+ | <asm> | ||
+ | jsr Sonic_CheckFloor | ||
+ | </asm> | ||
+ | This will ensure that all three characters branch to the same location for floor checks. | ||
+ | ===Additional Step #4: Porting a bunch more stuff=== | ||
+ | Yep. In case the very clear subheading didn't give it away, we're porting even MORE stuff from our KiS2 disassembly. I know you're getting tired, but there's still more to do! Still on the second error list, but don't worry! We're almost done porting Knuckles! | ||
+ | ====Additional Step 4.1: ART AND STUFF==== | ||
+ | The moment you've probably been awaiting for God-knows-how-long. Here's where SonMapEd and the S3K disassembly come into play. |
Latest revision as of 10:32, 29 April 2013
It surprises me that nobody else took up responsibility for making this guide, considering I, as a major fan of hacks, have seen Knuckles implemented in Sonic 2 on more than one occasion. Today, I'll be explaining how you, too, can implement Knuckles in your Sonic 2 hack.
Contents
What You'll Need
- This guide (no duh, really)
- The Hg disassembly of Sonic 2
- The one known disassembly of Knuckles in Sonic 2, found on the long list of disassemblies.
- The ConTEXT text editor (or Notepad++ with the File:UserDefineLang-68000-Z80.zip ported), because Notepad will take WAY too long to process anything
- Your favorite Genesis emulator (I recommend Kega Fusion but you can use any Genesis emulator you'd like)
- SonMapEd
- The S3K Hg disassembly (for art and other related stuff)
IMPORTANT NOTES
First note: DO NOT try to rebuild the ROM once you've started this guide or you will get build errors.
Second note: There is quite a lot of code added in this tutorial and it will make the ASM file's size quite a bit bigger than they were before. 150+ KB, to be precise.
Third note: This guide is used on a clean disassembly, so make sure that your disassembly does not have any objects already ported.
Fourth note: In addition to the second note, this guide, if followed, will also cause the size of the ROM to double. Port Sonic 1's sound driver first so nothing fails.
Final note: Please remember that this is a work-in-progress guide that I will improve upon as more is uncovered.
Step 1: Creating the Knuckles object
First, open up s2.asm in the text editor and search for "dc.l ObjNull." This should come up: <asm>
dc.l ObjNull ; Obj4C dc.l ObjNull ; Obj4D dc.l ObjNull ; Obj4E dc.l ObjNull ; Obj4F
</asm> Change this line: <asm>
dc.l ObjNull ; Obj4C
</asm>
To this: <asm>
dc.l Obj4C ; Knuckles
</asm>
We've created our Knuckles object. Now let's get started.
Step 2: Creating the offset table
Now that you have created your Knuckles object, go to whatever folder you saved the Knuckles in Sonic 2 disassembly to, open s2k.asm in the text editor, and scroll down or search until you find the following code: <asm> Obj01_Index: dc.w Obj01_Init-Obj01_Index ; 0 ; ... dc.w Obj01_Control-Obj01_Index ; 1 dc.w Obj01_Hurt-Obj01_Index ; 2 dc.w Obj01_Dead-Obj01_Index ; 3 dc.w Obj01_Gone-Obj01_Index ; 4 dc.w Obj01_Respawning-Obj01_Index ; 5 </asm> Back in s2.asm, copy and paste the following piece of code above the description of the Masher object: <asm>
- ----------------------------------------------------------------------------
- Object 01 - Knuckles
- ----------------------------------------------------------------------------
Obj01: ; a0=character tst.w (Debug_placement_mode).w ; is debug mode being used? beq.s Obj01_Normal ; if not, branch jmp (DebugMode).l
- ---------------------------------------------------------------------------
- loc_19F5C
Obj01_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Obj01_Index(pc,d0.w),d1 jmp Obj01_Index(pc,d1.w)
- End of function Obj01
- ----------------------------------------------------------------------------
</asm> Now copy the code I mentioned earlier in this step, and paste it below the code displayed above. Then, replace all of the "dc.w"'s with "offsetTableEntry.w"'s, delete the "-Obj01_Index" on the end of each line, move all of the entries down one line, add "offsetTable" to the top, and change all of the 01's in the whole section of code to 4C's. If you're following this guide correctly, your code should look like this: <asm>
- ----------------------------------------------------------------------------
- Object 4C - Knuckles
- ----------------------------------------------------------------------------
Obj4C: ; a0=character tst.w (Debug_placement_mode).w ; is debug mode being used? beq.s Obj4C_Normal ; if not, branch jmp (DebugMode).l
- ---------------------------------------------------------------------------
- loc_19F5C
Obj4C_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Obj4C_Index(pc,d0.w),d1 jmp Obj4C_Index(pc,d1.w)
- End of function Obj4C
- ----------------------------------------------------------------------------
Obj4C_Index: offsetTable
offsetTableEntry.w Obj4C_Init ; 0
offsetTableEntry.w Obj4C_Control ; 2 offsetTableEntry.w Obj4C_Hurt ; 4 offsetTableEntry.w Obj4C_Dead ; 6 offsetTableEntry.w Obj4C_Gone ; 8 offsetTableEntry.w Obj4C_Respawning ; $A ... </asm> Now that THAT is done and over with, let's continue to importing Knuckles' many modes (or whatever you people call them).
Step 3: Obj4C_Init
Going back to s2k.asm , you should see this piece of code right below the code I mentioned earlier in Step 2: <asm>
- ---------------------------------------------------------------------------
Obj01_Init: ; ... addq.b #2,$24(a0) move.b #$13,$16(a0) move.b #9,$17(a0) move.l #SK_Map_Knuckles,4(a0) ; SK_Map_Knuckles move.b #2,$18(a0) move.b #$18,$19(a0) move.b #4,1(a0) move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE30).w bne.s Obj01_Init_Continued move.w #$780,2(a0) bsr.w Adjust2PArtPointer2_Useless move.b #$C,$3E(a0) move.b #$D,$3F(a0) move.w 8(a0),($FFFFFE32).w move.w $C(a0),($FFFFFE34).w move.w 2(a0),($FFFFFE3C).w move.w $3E(a0),($FFFFFE3E).w
Obj01_Init_Continued: ; ... move.b #0,$2C(a0) move.b #4,$2D(a0) move.b #0,($FFFFFE19).w move.b #$1E,$28(a0) sub.w #$20,8(a0) add.w #4,$C(a0) move.w #0,($FFFFEED2).w move.w #$3F,d2
loc_3153EC: ; ... bsr.w Knuckles_RecordPositions subq.w #4,a1 move.l #0,(a1) dbf d2,loc_3153EC add.w #$20,8(a0) sub.w #4,$C(a0) </asm> All we need to do is copy this, paste it below our already ported code, and change all of the 01's to 4C's. Now you should have this below the offset table: <asm>
- ---------------------------------------------------------------------------
Obj4C_Init: ; ... addq.b #2,$24(a0) move.b #$13,$16(a0) move.b #9,$17(a0) move.l #SK_Map_Knuckles,4(a0) ; SK_Map_Knuckles move.b #2,$18(a0) move.b #$18,$19(a0) move.b #4,1(a0) move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE30).w bne.s Obj4C_Init_Continued move.w #$780,2(a0) bsr.w Adjust2PArtPointer2_Useless move.b #$C,$3E(a0) move.b #$D,$3F(a0) move.w 8(a0),($FFFFFE32).w move.w $C(a0),($FFFFFE34).w move.w 2(a0),($FFFFFE3C).w move.w $3E(a0),($FFFFFE3E).w
Obj4C_Init_Continued: ; ... move.b #0,$2C(a0) move.b #4,$2D(a0) move.b #0,($FFFFFE19).w move.b #$1E,$28(a0) sub.w #$20,8(a0) add.w #4,$C(a0) move.w #0,($FFFFEED2).w move.w #$3F,d2
loc_3153EC: ; ... bsr.w Knuckles_RecordPositions subq.w #4,a1 move.l #0,(a1) dbf d2,loc_3153EC add.w #$20,8(a0) sub.w #4,$C(a0) </asm>
Step 4: Obj4C_Control
This one is the most important. It actually makes up approximately 90% of the code for Knuckles. Therefore, we definitely need to port this.
Step 4: Part 1: Starting off
First, we have to modify the Obj01_Modes offset table from s2k.asm so we can use it for our Knuckles. Below the code mentioned above, you should see this: <asm> Obj01_Control: ; ... tst.w ($FFFFFFDA).w beq.s loc_315422 btst #4,($FFFFF605).w beq.s loc_315422 move.w #1,($FFFFFE08).w clr.b ($FFFFF7CC).w rts
- ---------------------------------------------------------------------------
loc_315422: ; ... tst.b ($FFFFF7CC).w bne.s loc_31542E move.w ($FFFFF604).w,($FFFFF602).w
loc_31542E: ; ... btst #0,$2A(a0) beq.s loc_31543E move.b #0,$21(a0) bra.s loc_315450
- ---------------------------------------------------------------------------
loc_31543E: ; ... moveq #0,d0 move.b $22(a0),d0
and.w #6,d0 move.w Obj01_Modes(pc,d0.w),d1 jsr Obj01_Modes(pc,d1.w)
loc_315450: ; ... cmp.w #$FF00,($FFFFEECC).w bne.s loc_31545E and.w #$7FF,$C(a0)
loc_31545E: ; ... bsr.s Knuckles_Display bsr.w Knuckles_Super bsr.w Knuckles_RecordPositions bsr.w Knuckles_Water move.b ($FFFFF768).w,$36(a0) move.b ($FFFFF76A).w,$37(a0) tst.b ($FFFFF7C7).w beq.s loc_31548A tst.b $1C(a0) bne.s loc_31548A move.b $1D(a0),$1C(a0)
loc_31548A: ; ... bsr.w Knuckles_Animate tst.b $2A(a0) bmi.s loc_31549A jsr TouchResponse
loc_31549A: ; ... bra.w LoadKnucklesDynPLC
- ---------------------------------------------------------------------------
Obj01_Modes: dc.w Obj01_MdNormal-Obj01_Modes ; 0 ; ... dc.w Obj01_MdAir-Obj01_Modes ; 1 dc.w Obj01_MdRoll-Obj01_Modes ; 2 dc.w Obj01_MdJump-Obj01_Modes ; 3 </asm>
Do the same thing that was done with the code in Step 2. It should now look like this: <asm> Obj4C_Control: ; ... tst.w ($FFFFFFDA).w beq.s loc_315422 btst #4,($FFFFF605).w beq.s loc_315422 move.w #1,($FFFFFE08).w clr.b ($FFFFF7CC).w rts
- ---------------------------------------------------------------------------
loc_315422: ; ... tst.b ($FFFFF7CC).w bne.s loc_31542E move.w ($FFFFF604).w,($FFFFF602).w
loc_31542E: ; ... btst #0,$2A(a0) beq.s loc_31543E move.b #0,$21(a0) bra.s loc_315450
- ---------------------------------------------------------------------------
loc_31543E: ; ... moveq #0,d0 move.b $22(a0),d0 and.w #6,d0 move.w Obj4C_Modes(pc,d0.w),d1 jsr Obj4C_Modes(pc,d1.w)
loc_315450: ; ... cmp.w #$FF00,($FFFFEECC).w bne.s loc_31545E and.w #$7FF,$C(a0)
loc_31545E: ; ... bsr.s Knuckles_Display bsr.w Knuckles_Super bsr.w Knuckles_RecordPositions bsr.w Knuckles_Water move.b ($FFFFF768).w,$36(a0) move.b ($FFFFF76A).w,$37(a0) tst.b ($FFFFF7C7).w beq.s loc_31548A tst.b $1C(a0) bne.s loc_31548A move.b $1D(a0),$1C(a0)
loc_31548A: ; ... bsr.w Knuckles_Animate tst.b $2A(a0) bmi.s loc_31549A jsr TouchResponse
loc_31549A: ; ... bra.w LoadKnucklesDynPLC
- ---------------------------------------------------------------------------
Obj4C_Modes: offsetTable
offsetTableEntry.w Obj4C_MdNormal_Checks ; 0 ; not airborne or rolling
offsetTableEntry.w Obj4C_MdAir ; 2 ; airborne offsetTableEntry.w Obj4C_MdRoll ; 4 ; rolling offsetTableEntry.w Obj4C_MdJump ; 6 ; jumping </asm>
Step 4: Part 2: Obj4C_MdNormal
Back to s2k.asm! The next bit of code you'll want to find is this: <asm>
- =============== S U B R O U T I N E =======================================
Knuckles_Display: ; ...
move.w $30(a0),d0
beq.s Obj01_Display
subq.w #1,$30(a0)
lsr.w #3,d0
bcc.s Obj01_CheckInvincibility
Obj01_Display: ; ... jsr DisplaySprite
Obj01_CheckInvincibility: ; ... btst #1,$2B(a0) beq.s Obj01_CheckSpeedShoes tst.w $32(a0) beq.s Obj01_CheckSpeedShoes subq.w #1,$32(a0) bne.s Obj01_CheckSpeedShoes tst.b ($FFFFF7AA).w bne.s Obj01_RemoveInvincibility cmp.b #$C,$28(a0) bcs.s Obj01_RemoveInvincibility move.w ($FFFFFF90).w,d0 jsr PlayMusic
Obj01_RemoveInvincibility: ; ... bclr #1,$2B(a0)
Obj01_CheckSpeedShoes: ; ... btst #2,$2B(a0) beq.s Obj01_ExitCheck tst.w $34(a0) beq.s Obj01_ExitCheck subq.w #1,$34(a0) bne.s Obj01_ExitCheck move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE19).w beq.s Obj01_RemoveSpeedShoes move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w
Obj01_RemoveSpeedShoes: ; ... bclr #2,$2B(a0) move.w #$FC,d0 jmp PlayMusic
- ---------------------------------------------------------------------------
Obj01_ExitCheck: ; ... rts
- End of function Knuckles_Display
- =============== S U B R O U T I N E =======================================
Knuckles_RecordPositions: ; ...
move.w ($FFFFEED2).w,d0
lea ($FFFFE500).w,a1
lea (a1,d0.w),a1
move.w 8(a0),(a1)+
move.w $C(a0),(a1)+
addq.b #4,($FFFFEED3).w
lea ($FFFFE400).w,a1
lea (a1,d0.w),a1
move.w ($FFFFF602).w,(a1)+
move.w $22(a0),(a1)+
rts
- End of function Knuckles_RecordPositions
- =============== S U B R O U T I N E =======================================
Knuckles_Water: ; ...
tst.b ($FFFFF730).w
bne.s Obj01_InWater
return_31556C: ; ... rts
- ---------------------------------------------------------------------------
Obj01_InWater: ; ... move.w ($FFFFF646).w,d0 cmp.w $C(a0),d0 bge.s Obj01_OutWater bset #6,$22(a0) bne.s return_31556C move.l a0,a1 bsr.w ResumeMusic move.b #$A,($FFFFD080).w move.b #$81,($FFFFD0A8).w move.l a0,($FFFFD0BC).w move.w #$300,($FFFFF760).w move.w #6,($FFFFF762).w move.w #$40,($FFFFF764).w tst.b ($FFFFFE19).w beq.s loc_3155C0 move.w #$400,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$60,($FFFFF764).w
loc_3155C0: ; ... asr $10(a0) asr $12(a0) asr $12(a0) beq.s return_31556C move.w #$100,($FFFFD11C).w move.w #$AA,d0 jmp PlaySound
- ---------------------------------------------------------------------------
Obj01_OutWater: ; ... bclr #6,$22(a0) beq.s return_31556C move.l a0,a1 bsr.w ResumeMusic move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE19).w beq.s loc_315616 move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w
loc_315616: ; ... cmp.b #4,$24(a0) beq.s loc_315622 asl $12(a0)
loc_315622: ; ... tst.w $12(a0) beq.w return_31556C move.w #$100,($FFFFD11C).w move.l a0,a1 bsr.w ResumeMusic cmp.w #$F000,$12(a0) bgt.s loc_315644 move.w #$F000,$12(a0)
loc_315644: ; ... move.w #$AA,d0 jmp PlaySound
- End of function Knuckles_Water
- =============== S U B R O U T I N E =======================================
Obj01_MdNormal: ; ...
bsr.w Knuckles_Spindash
bsr.w Knuckles_Jump
bsr.w Knuckles_SlopeResist
bsr.w Knuckles_Move
bsr.w Knuckles_Roll
bsr.w Knuckles_LevelBoundaries
jsr ObjectMove ; AKA SpeedToPos in Sonic 1
bsr.w AnglePos
bsr.w Knuckles_SlopeRepel
rts
- End of function Obj01_MdNormal
</asm> Put that below the code we've already ported, then go through it and replace each and every "Obj01" with "Obj4C." You should get this: <asm>
- =============== S U B R O U T I N E =======================================
Knuckles_Display: ; ...
move.w $30(a0),d0
beq.s Obj4C_Display
subq.w #1,$30(a0)
lsr.w #3,d0
bcc.s Obj4C_CheckInvincibility
Obj4C_Display: ; ... jsr DisplaySprite
Obj4C_CheckInvincibility: ; ... btst #1,$2B(a0) beq.s Obj4C_CheckSpeedShoes tst.w $32(a0) beq.s Obj4C_CheckSpeedShoes subq.w #1,$32(a0) bne.s Obj4C_CheckSpeedShoes tst.b ($FFFFF7AA).w bne.s Obj4C_RemoveInvincibility cmp.b #$C,$28(a0) bcs.s Obj4C_RemoveInvincibility move.w ($FFFFFF90).w,d0 jsr PlayMusic
Obj4C_RemoveInvincibility: ; ... bclr #1,$2B(a0)
Obj4C_CheckSpeedShoes: ; ... btst #2,$2B(a0) beq.s Obj4C_ExitCheck tst.w $34(a0) beq.s Obj4C_ExitCheck subq.w #1,$34(a0) bne.s Obj4C_ExitCheck move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE19).w beq.s Obj4C_RemoveSpeedShoes move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w
Obj4C_RemoveSpeedShoes: ; ... bclr #2,$2B(a0) move.w #$FC,d0 jmp PlayMusic
- ---------------------------------------------------------------------------
Obj4C_ExitCheck: ; ... rts
- End of function Knuckles_Display
- =============== S U B R O U T I N E =======================================
Knuckles_RecordPositions: ; ...
move.w ($FFFFEED2).w,d0
lea ($FFFFE500).w,a1
lea (a1,d0.w),a1
move.w 8(a0),(a1)+
move.w $C(a0),(a1)+
addq.b #4,($FFFFEED3).w
lea ($FFFFE400).w,a1
lea (a1,d0.w),a1
move.w ($FFFFF602).w,(a1)+
move.w $22(a0),(a1)+
rts
- End of function Knuckles_RecordPositions
- =============== S U B R O U T I N E =======================================
Knuckles_Water: ; ...
tst.b ($FFFFF730).w
bne.s Obj4C_InWater
return_31556C: ; ... rts
- ---------------------------------------------------------------------------
Obj4C_InWater: ; ... move.w ($FFFFF646).w,d0 cmp.w $C(a0),d0 bge.s Obj4C_OutWater bset #6,$22(a0) bne.s return_31556C move.l a0,a1 bsr.w ResumeMusic move.b #$A,($FFFFD080).w move.b #$81,($FFFFD0A8).w move.l a0,($FFFFD0BC).w move.w #$300,($FFFFF760).w move.w #6,($FFFFF762).w move.w #$40,($FFFFF764).w tst.b ($FFFFFE19).w beq.s loc_3155C0 move.w #$400,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$60,($FFFFF764).w
loc_3155C0: ; ... asr $10(a0) asr $12(a0) asr $12(a0) beq.s return_31556C move.w #$100,($FFFFD11C).w move.w #$AA,d0 jmp PlaySound
- ---------------------------------------------------------------------------
Obj4C_OutWater: ; ... bclr #6,$22(a0) beq.s return_31556C move.l a0,a1 bsr.w ResumeMusic move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE19).w beq.s loc_315616 move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w
loc_315616: ; ... cmp.b #4,$24(a0) beq.s loc_315622 asl $12(a0)
loc_315622: ; ... tst.w $12(a0) beq.w return_31556C
move.w #$100,($FFFFD11C).w
move.l a0,a1 bsr.w ResumeMusic cmp.w #$F000,$12(a0) bgt.s loc_315644 move.w #$F000,$12(a0)
loc_315644: ; ... move.w #$AA,d0 jmp PlaySound
- End of function Knuckles_Water
- =============== S U B R O U T I N E =======================================
Obj4C_MdNormal: ; ...
bsr.w Knuckles_Spindash
bsr.w Knuckles_Jump
bsr.w Knuckles_SlopeResist
bsr.w Knuckles_Move
bsr.w Knuckles_Roll
bsr.w Knuckles_LevelBoundaries
jsr ObjectMove ; AKA SpeedToPos in Sonic 1
bsr.w AnglePos
bsr.w Knuckles_SlopeRepel
rts
- End of function Obj4C_MdNormal
</asm> And we're done with the Obj4C_MdNormal_Checks subroutine! Now we can get the rest of the code in without worrying about errors, provided you're following this guide correctly.
Step 4: Part 3: Obj4C_MdAir
Not very complicated, just find this, place it below the ported code and replace each "Obj01" with a "Obj4C." <asm>
- =============== S U B R O U T I N E =======================================
Obj01_MdAir: ; ...
tst.b $21(a0)
bne.s Obj01_MdAir_Gliding
bsr.w Knuckles_JumpHeight
bsr.w Knuckles_ChgJumpDir
bsr.w Knuckles_LevelBoundaries
jsr ObjectMoveAndFall
btst #6,$22(a0)
beq.s loc_31569C
sub.w #$28,$12(a0)
loc_31569C: ; ... bsr.w Knuckles_JumpAngle bsr.w Knuckles_DoLevelCollision rts
- ---------------------------------------------------------------------------
Obj01_MdAir_Gliding: ; ... bsr.w Knuckles_GlideSpeedControl bsr.w Knuckles_LevelBoundaries jsr ObjectMove ; AKA SpeedToPos in Sonic 1 bsr.w Knuckles_GlideControl
return_3156B8: ; ... rts
- End of function Obj01_MdAir
</asm> You should end up with this: <asm>
- =============== S U B R O U T I N E =======================================
Obj4C_MdAir: ; ...
tst.b $21(a0)
bne.s Obj4C_MdAir_Gliding
bsr.w Knuckles_JumpHeight
bsr.w Knuckles_ChgJumpDir
bsr.w Knuckles_LevelBoundaries
jsr ObjectMoveAndFall
btst #6,$22(a0)
beq.s loc_31569C
sub.w #$28,$12(a0)
loc_31569C: ; ... bsr.w Knuckles_JumpAngle bsr.w Knuckles_DoLevelCollision rts
- ---------------------------------------------------------------------------
Obj4C_MdAir_Gliding: ; ... bsr.w Knuckles_GlideSpeedControl bsr.w Knuckles_LevelBoundaries jsr ObjectMove ; AKA SpeedToPos in Sonic 1 bsr.w Knuckles_GlideControl
return_3156B8: ; ... rts
- End of function Obj4C_MdAir
</asm> I told you it wasn't complicated.
Step 4: Part 4: Everything having to do with Knuckles' gliding
And we don't even need to change anything. WOOHOO! <asm>
- =============== S U B R O U T I N E =======================================
Knuckles_GlideControl: ; ...
- FUNCTION CHUNK AT 00315C40 SIZE 0000003C BYTES
move.b $21(a0),d0 beq.s return_3156B8 cmp.b #2,d0 beq.w Knuckles_FallingFromGlide cmp.b #3,d0 beq.w Knuckles_Sliding cmp.b #4,d0 beq.w Knuckles_Climbing_Wall cmp.b #5,d0 beq.w Knuckles_Climbing_Up
Knuckles_NormalGlide: move.b #$A,$16(a0) move.b #$A,$17(a0) bsr.w Knuckles_DoLevelCollision2 btst #5,($FFFFF7AC).w bne.w Knuckles_BeginClimb move.b #$13,$16(a0) move.b #9,$17(a0) btst #1,($FFFFF7AC).w beq.s Knuckles_BeginSlide move.b ($FFFFF602).w,d0 and.b #$70,d0 bne.s loc_31574C move.b #2,$21(a0) move.b #$21,$1C(a0) bclr #0,$22(a0) tst.w $10(a0) bpl.s loc_315736 bset #0,$22(a0)
loc_315736: ; ... asr $10(a0) asr $10(a0) move.b #$13,$16(a0) move.b #9,$17(a0) rts
- ---------------------------------------------------------------------------
loc_31574C: ; ... bra.w sub_315C7C
- ---------------------------------------------------------------------------
Knuckles_BeginSlide: ; ... bclr #0,$22(a0) tst.w $10(a0) bpl.s loc_315762 bset #0,$22(a0)
loc_315762: ; ... move.b $26(a0),d0 add.b #$20,d0 and.b #$C0,d0 beq.s loc_315780 move.w $14(a0),$10(a0) move.w #0,$12(a0) bra.w Knuckles_ResetOnFloor_Part2
- ---------------------------------------------------------------------------
loc_315780: ; ... move.b #3,$21(a0) move.b #$CC,$1A(a0) move.b #$7F,$1E(a0) move.b #0,$1B(a0) cmp.b #$C,$28(a0) bcs.s return_3157AC move.b #6,($FFFFD124).w move.b #$15,($FFFFD11A).w
return_3157AC: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_BeginClimb: ; ... tst.b ($FFFFF7AD).w bmi.w loc_31587A move.b $3F(a0),d5 move.b $1F(a0),d0 add.b #$40,d0 bpl.s loc_3157D8 bset #0,$22(a0) bsr.w CheckLeftCeilingDist or.w d0,d1 bne.s Knuckles_FallFromGlide addq.w #1,8(a0) bra.s loc_3157E8
- ---------------------------------------------------------------------------
loc_3157D8: ; ... bclr #0,$22(a0) bsr.w CheckRightCeilingDist or.w d0,d1 bne.w loc_31586A
loc_3157E8: ; ... move.b #$13,$16(a0) move.b #9,$17(a0) tst.b ($FFFFFE19).w beq.s loc_315804 cmp.w #$480,$14(a0) bcs.s loc_315804 nop
loc_315804: ; ... move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.b #4,$21(a0) move.b #$B7,$1A(a0) move.b #$7F,$1E(a0) move.b #0,$1B(a0) move.b #3,$1F(a0) move.w 8(a0),$A(a0) rts
- ---------------------------------------------------------------------------
Knuckles_FallFromGlide: ; ... move.w 8(a0),d3 move.b $16(a0),d0 ext.w d0 sub.w d0,d3 subq.w #1,d3
loc_31584A: ; ... move.w $C(a0),d2 sub.w #$B,d2 jsr ChkFloorEdge_Part2 tst.w d1 bmi.s loc_31587A cmp.w #$C,d1 bcc.s loc_31587A add.w d1,$C(a0) bra.w loc_3157E8
- ---------------------------------------------------------------------------
loc_31586A: ; ... move.w 8(a0),d3 move.b $16(a0),d0 ext.w d0 add.w d0,d3 addq.w #1,d3 bra.s loc_31584A
- ---------------------------------------------------------------------------
loc_31587A: ; ... move.b #2,$21(a0) move.b #$21,$1C(a0) move.b #$13,$16(a0) move.b #9,$17(a0) bset #1,($FFFFF7AC).w rts
- ---------------------------------------------------------------------------
Knuckles_FallingFromGlide: ; ... bsr.w Knuckles_ChgJumpDir add.w #$38,$12(a0) btst #6,$22(a0) beq.s loc_3158B2 sub.w #$28,$12(a0)
loc_3158B2: ; ... bsr.w Knuckles_DoLevelCollision2 btst #1,($FFFFF7AC).w bne.s return_315900 move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.b $16(a0),d0 sub.b #$13,d0 ext.w d0 add.w d0,$C(a0) move.b $26(a0),d0 add.b #$20,d0 and.b #$C0,d0 beq.s loc_3158F0 bra.w Knuckles_ResetOnFloor_Part2
- ---------------------------------------------------------------------------
loc_3158F0: ; ... bsr.w Knuckles_ResetOnFloor_Part2 move.w #$F,$2E(a0) move.b #$23,$1C(a0)
return_315900: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_Sliding: ; ... move.b ($FFFFF602).w,d0 and.b #$70,d0 beq.s loc_315926 tst.w $10(a0) bpl.s loc_31591E add.w #$20,$10(a0) bmi.s loc_31591C bra.s loc_315926
- ---------------------------------------------------------------------------
loc_31591C: ; ... bra.s loc_315958
- ---------------------------------------------------------------------------
loc_31591E: ; ... sub.w #$20,$10(a0) bpl.s loc_315958
loc_315926: ; ... move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.b $16(a0),d0 sub.b #$13,d0 ext.w d0 add.w d0,$C(a0) bsr.w Knuckles_ResetOnFloor_Part2 move.w #$F,$2E(a0) move.b #$22,$1C(a0) rts
- ---------------------------------------------------------------------------
loc_315958: ; ... move.b #$A,$16(a0) move.b #$A,$17(a0) bsr.w Knuckles_DoLevelCollision2 bsr.w Player_CheckFloor cmp.w #$E,d1 bge.s loc_315988 add.w d1,$C(a0) move.b d3,$26(a0) move.b #$13,$16(a0) move.b #9,$17(a0) rts
- ---------------------------------------------------------------------------
loc_315988: ; ... move.b #2,$21(a0) move.b #$21,$1C(a0) move.b #$13,$16(a0) move.b #9,$17(a0) bset #1,($FFFFF7AC).w rts
- ---------------------------------------------------------------------------
Knuckles_Climbing_Wall: ; ... tst.b ($FFFFF7AD).w bmi.w loc_315BAE move.w 8(a0),d0 cmp.w $A(a0),d0 bne.w loc_315BAE btst #3,$22(a0) bne.w loc_315BAE move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.l #$FFFFD600,($FFFFF796).w cmp.b #$D,$3F(a0) beq.s loc_3159F0 move.l #$FFFFD900,($FFFFF796).w
loc_3159F0: ; ... move.b $3F(a0),d5 move.b #$A,$16(a0) move.b #$A,$17(a0) moveq #0,d1 btst #0,($FFFFF602).w beq.w loc_315A76 move.w $C(a0),d2 sub.w #$B,d2 bsr.w sub_315C22 cmp.w #4,d1 bge.w Knuckles_ClimbUp ; Climb onto the floor above you tst.w d1 bne.w loc_315B30 move.b $3F(a0),d5 move.w $C(a0),d2 subq.w #8,d2 move.w 8(a0),d3 bsr.w sub_3192E6 ; Doesn't exist in S2 tst.w d1 bpl.s loc_315A46 sub.w d1,$C(a0) moveq #1,d1 bra.w loc_315B04
- ---------------------------------------------------------------------------
loc_315A46: ; ... subq.w #1,$C(a0) tst.b ($FFFFFE19).w beq.s loc_315A54 subq.w #1,$C(a0)
loc_315A54: ; ... moveq #1,d1 move.w ($FFFFEECC).w,d0 cmp.w #-$100,d0 beq.w loc_315B04 add.w #$10,d0 cmp.w $C(a0),d0 ble.w loc_315B04 move.w d0,$C(a0) bra.w loc_315B04
- ---------------------------------------------------------------------------
loc_315A76: ; ... btst #1,($FFFFF602).w beq.w loc_315B04 cmp.b #$BD,$1A(a0) bne.s loc_315AA2 move.b #$B7,$1A(a0) addq.w #3,$C(a0) subq.w #3,8(a0) btst #0,$22(a0) beq.s loc_315AA2 addq.w #6,8(a0)
loc_315AA2: ; ... move.w $C(a0),d2 add.w #$B,d2 bsr.w sub_315C22 tst.w d1 bne.w loc_315BAE move.b $3E(a0),d5 move.w $C(a0),d2 add.w #9,d2 move.w 8(a0),d3 bsr.w sub_318FF6 tst.w d1 bpl.s loc_315AF4 add.w d1,$C(a0) move.b ($FFFFF768).w,$26(a0) move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) bsr.w Knuckles_ResetOnFloor_Part2 move.b #5,$1C(a0) rts
- ---------------------------------------------------------------------------
loc_315AF4: ; ... addq.w #1,$C(a0) tst.b ($FFFFFE19).w beq.s loc_315B02 addq.w #1,$C(a0)
loc_315B02: ; ... moveq #-1,d1
loc_315B04: ; ... tst.w d1 beq.s loc_315B30 subq.b #1,$1F(a0) bpl.s loc_315B30 move.b #3,$1F(a0) add.b $1A(a0),d1 cmp.b #$B7,d1 bcc.s loc_315B22 move.b #$BC,d1
loc_315B22: ; ... cmp.b #$BC,d1 bls.s loc_315B2C move.b #$B7,d1
loc_315B2C: ; ... move.b d1,$1A(a0)
loc_315B30: ; ... move.b #$20,$1E(a0) move.b #0,$1B(a0) move.b #$13,$16(a0) move.b #9,$17(a0) move.w ($FFFFF602).w,d0 and.w #$70,d0 beq.s return_315B94 move.w #$FC80,$12(a0) move.w #$400,$10(a0) bchg #0,$22(a0) bne.s loc_315B6A neg.w $10(a0)
loc_315B6A: ; ... bset #1,$22(a0) move.b #1,$3C(a0) move.b #$E,$16(a0) move.b #7,$17(a0) move.b #2,$1C(a0) bset #2,$22(a0) move.b #0,$21(a0)
return_315B94: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_ClimbUp: ; ... move.b #5,$21(a0) ; Climb up to the floor above you cmp.b #$BD,$1A(a0) beq.s return_315BAC move.b #0,$1F(a0) bsr.s sub_315BDA
return_315BAC: ; ... rts
- ---------------------------------------------------------------------------
loc_315BAE: ; ... move.b #2,$21(a0) move.w #$2121,$1C(a0) move.b #$CB,$1A(a0) move.b #7,$1E(a0) move.b #1,$1B(a0) move.b #$13,$16(a0) move.b #9,$17(a0) rts
- End of function Knuckles_GlideControl
- =============== S U B R O U T I N E =======================================
sub_315BDA: ; ...
moveq #0,d0
move.b $1F(a0),d0
lea word_315C12(pc,d0.w),a1
move.b (a1)+,$1A(a0)
move.b (a1)+,d0
ext.w d0
btst #0,$22(a0)
beq.s loc_315BF6
neg.w d0
loc_315BF6: ; ... add.w d0,8(a0) move.b (a1)+,d1 ext.w d1 add.w d1,$C(a0) move.b (a1)+,$1E(a0) addq.b #4,$1F(a0) move.b #0,$1B(a0) rts
- End of function sub_315BDA
- ---------------------------------------------------------------------------
word_315C12: dc.w $BD03,$FD06,$BE08,$F606,$BFF8,$F406,$D208,$FB06; 0 ; ...
- =============== S U B R O U T I N E =======================================
sub_315C22: ; ...
- FUNCTION CHUNK AT 00319208 SIZE 00000020 BYTES
- FUNCTION CHUNK AT 003193D2 SIZE 00000024 BYTES
move.b $3F(a0),d5 btst #0,$22(a0) bne.s loc_315C36 move.w 8(a0),d3 bra.w loc_319208
- ---------------------------------------------------------------------------
loc_315C36: ; ... move.w 8(a0),d3 subq.w #1,d3 bra.w loc_3193D2
- End of function sub_315C22
- ---------------------------------------------------------------------------
- START OF FUNCTION CHUNK FOR Knuckles_GlideControl
Knuckles_Climbing_Up: ; ... tst.b $1E(a0) bne.s return_315C7A bsr.w sub_315BDA cmp.b #$10,$1F(a0) bne.s return_315C7A move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) btst #0,$22(a0) beq.s loc_315C70 subq.w #1,8(a0)
loc_315C70: ; ... bsr.w Knuckles_ResetOnFloor_Part2 move.b #5,$1C(a0)
return_315C7A: ; ... rts
- END OF FUNCTION CHUNK FOR Knuckles_GlideControl
- =============== S U B R O U T I N E =======================================
sub_315C7C: ; ...
move.b #$20,$1E(a0)
move.b #0,$1B(a0)
move.w #$2020,$1C(a0)
bclr #5,$22(a0)
bclr #0,$22(a0)
moveq #0,d0
move.b $1F(a0),d0
add.b #$10,d0
lsr.w #5,d0
move.b byte_315CC2(pc,d0.w),d1
move.b d1,$1A(a0)
cmp.b #$C4,d1
bne.s return_315CC0
bset #0,$22(a0)
move.b #$C0,$1A(a0)
return_315CC0: ; ... rts
- End of function sub_315C7C
- ---------------------------------------------------------------------------
byte_315CC2: dc.b $C0,$C1,$C2,$C3,$C4,$C3,$C2,$C1; 0 ; ...
- =============== S U B R O U T I N E =======================================
Knuckles_GlideSpeedControl: ; ...
cmp.b #1,$21(a0)
bne.w loc_315D88
move.w $14(a0),d0
cmp.w #$400,d0
bcc.s loc_315CE2
addq.w #8,d0
bra.s loc_315CFC
- ---------------------------------------------------------------------------
loc_315CE2: ; ... cmp.w #$1800,d0 bcc.s loc_315CFC move.b $1F(a0),d1 and.b #$7F,d1 bne.s loc_315CFC addq.w #4,d0 tst.b ($FFFFFE19).w beq.s loc_315CFC addq.w #8,d0
loc_315CFC: ; ... move.w d0,$14(a0) move.b $1F(a0),d0 btst #2,($FFFFF602).w beq.s loc_315D1C cmp.b #$80,d0 beq.s loc_315D1C tst.b d0 bpl.s loc_315D18 neg.b d0
loc_315D18: ; ... addq.b #2,d0 bra.s loc_315D3A
- ---------------------------------------------------------------------------
loc_315D1C: ; ... btst #3,($FFFFF602).w beq.s loc_315D30 tst.b d0 beq.s loc_315D30 bmi.s loc_315D2C neg.b d0
loc_315D2C: ; ... addq.b #2,d0 bra.s loc_315D3A
- ---------------------------------------------------------------------------
loc_315D30: ; ... move.b d0,d1 and.b #$7F,d1 beq.s loc_315D3A addq.b #2,d0
loc_315D3A: ; ... move.b d0,$1F(a0) move.b $1F(a0),d0 jsr CalcSine muls.w $14(a0),d1 asr.l #8,d1 move.w d1,$10(a0) cmp.w #$80,$12(a0) blt.s loc_315D62 sub.w #$20,$12(a0) bra.s loc_315D68
- ---------------------------------------------------------------------------
loc_315D62: ; ... add.w #$20,$12(a0)
loc_315D68: ; ... move.w ($FFFFEECC).w,d0 cmp.w #$FF00,d0 beq.w loc_315D88 add.w #$10,d0 cmp.w $C(a0),d0 ble.w loc_315D88 asr $10(a0) asr $14(a0)
loc_315D88: ; ... cmp.w #$60,($FFFFEED8).w beq.s return_315D9A bcc.s loc_315D96 addq.w #4,($FFFFEED8).w
loc_315D96: ; ... subq.w #2,($FFFFEED8).w
return_315D9A: ; ... rts
- End of function Knuckles_GlideSpeedControl
- ---------------------------------------------------------------------------
</asm>
Just to Recap
At this point, you should have this code ported: <asm>
- ----------------------------------------------------------------------------
- Object 4C - Knuckles
- ----------------------------------------------------------------------------
Obj4C: ; a0=character tst.w (Debug_placement_mode).w ; is debug mode being used? beq.s Obj4C_Normal ; if not, branch jmp (DebugMode).l
- ---------------------------------------------------------------------------
- loc_19F5C
Obj4C_Normal: moveq #0,d0 move.b routine(a0),d0 move.w Obj4C_Index(pc,d0.w),d1 jmp Obj4C_Index(pc,d1.w)
- End of function Obj4C
- ----------------------------------------------------------------------------
Obj4C_Index: offsetTable
offsetTableEntry.w Obj4C_Init ; 0
offsetTableEntry.w Obj4C_Control ; 2 offsetTableEntry.w Obj4C_Hurt ; 4 offsetTableEntry.w Obj4C_Dead ; 6 offsetTableEntry.w Obj4C_Gone ; 8 offsetTableEntry.w Obj4C_Respawning ; $A
- ----------------------------------------------------------------------------
Obj4C_Init: ; ... addq.b #2,$24(a0) move.b #$13,$16(a0) move.b #9,$17(a0) move.l #SK_Map_Knuckles,4(a0) ; SK_Map_Knuckles move.b #2,$18(a0) move.b #$18,$19(a0) move.b #4,1(a0) move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE30).w bne.s Obj4C_Init_Continued move.w #$780,2(a0) bsr.w Adjust2PArtPointer2_Useless move.b #$C,$3E(a0) move.b #$D,$3F(a0) move.w 8(a0),($FFFFFE32).w move.w $C(a0),($FFFFFE34).w move.w 2(a0),($FFFFFE3C).w move.w $3E(a0),($FFFFFE3E).w
Obj4C_Init_Continued: ; ... move.b #0,$2C(a0) move.b #4,$2D(a0) move.b #0,($FFFFFE19).w move.b #$1E,$28(a0) sub.w #$20,8(a0) add.w #4,$C(a0) move.w #0,($FFFFEED2).w move.w #$3F,d2
loc_3153EC: ; ... bsr.w Knuckles_RecordPositions subq.w #4,a1 move.l #0,(a1) dbf d2,loc_3153EC add.w #$20,8(a0) sub.w #4,$C(a0)
Obj4C_Control: ; ... tst.w ($FFFFFFDA).w beq.s loc_315422 btst #4,($FFFFF605).w beq.s loc_315422 move.w #1,($FFFFFE08).w clr.b ($FFFFF7CC).w rts
- ---------------------------------------------------------------------------
loc_315422: ; ... tst.b ($FFFFF7CC).w bne.s loc_31542E move.w ($FFFFF604).w,($FFFFF602).w
loc_31542E: ; ... btst #0,$2A(a0) beq.s loc_31543E move.b #0,$21(a0) bra.s loc_315450
- ---------------------------------------------------------------------------
loc_31543E: ; ... moveq #0,d0 move.b $22(a0),d0 and.w #6,d0 move.w Obj4C_Modes(pc,d0.w),d1 jsr Obj4C_Modes(pc,d1.w)
loc_315450: ; ... cmp.w #$FF00,($FFFFEECC).w bne.s loc_31545E and.w #$7FF,$C(a0)
loc_31545E: ; ... bsr.s Knuckles_Display bsr.w Knuckles_Super bsr.w Knuckles_RecordPositions bsr.w Knuckles_Water move.b ($FFFFF768).w,$36(a0) move.b ($FFFFF76A).w,$37(a0) tst.b ($FFFFF7C7).w beq.s loc_31548A tst.b $1C(a0) bne.s loc_31548A move.b $1D(a0),$1C(a0)
loc_31548A: ; ... bsr.w Knuckles_Animate tst.b $2A(a0) bmi.s loc_31549A jsr TouchResponse
loc_31549A: ; ... bra.w LoadKnucklesDynPLC
- ---------------------------------------------------------------------------
Obj4C_Modes: dc.w Obj4C_MdNormal_Checks ; 0 ; not airborne or rolling dc.w Obj4C_MdAir ; 2 ; airborne dc.w Obj4C_MdRoll ; 4 ; rolling dc.w Obj4C_MdJump ; 6 ; jumping
- =============== S U B R O U T I N E =======================================
Knuckles_Display: ; ...
move.w $30(a0),d0
beq.s Obj4C_Display
subq.w #1,$30(a0)
lsr.w #3,d0
bcc.s Obj4C_CheckInvincibility
Obj4C_Display: ; ... jsr DisplaySprite
Obj4C_CheckInvincibility: ; ... btst #1,$2B(a0) beq.s Obj4C_CheckSpeedShoes tst.w $32(a0) beq.s Obj4C_CheckSpeedShoes subq.w #1,$32(a0) bne.s Obj4C_CheckSpeedShoes tst.b ($FFFFF7AA).w bne.s Obj4C_RemoveInvincibility cmp.b #$C,$28(a0) bcs.s Obj4C_RemoveInvincibility move.w ($FFFFFF90).w,d0 jsr PlayMusic
Obj4C_RemoveInvincibility: ; ... bclr #1,$2B(a0)
Obj4C_CheckSpeedShoes: ; ... btst #2,$2B(a0) beq.s Obj4C_ExitCheck tst.w $34(a0) beq.s Obj4C_ExitCheck subq.w #1,$34(a0) bne.s Obj4C_ExitCheck move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE19).w beq.s Obj4C_RemoveSpeedShoes move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w
Obj4C_RemoveSpeedShoes: ; ... bclr #2,$2B(a0) move.w #$FC,d0 jmp PlayMusic
- ---------------------------------------------------------------------------
Obj4C_ExitCheck: ; ... rts
- End of function Knuckles_Display
- =============== S U B R O U T I N E =======================================
Knuckles_RecordPositions: ; ...
move.w ($FFFFEED2).w,d0
lea ($FFFFE500).w,a1
lea (a1,d0.w),a1
move.w 8(a0),(a1)+
move.w $C(a0),(a1)+
addq.b #4,($FFFFEED3).w
lea ($FFFFE400).w,a1
lea (a1,d0.w),a1
move.w ($FFFFF602).w,(a1)+
move.w $22(a0),(a1)+
rts
- End of function Knuckles_RecordPositions
- =============== S U B R O U T I N E =======================================
Knuckles_Water: ; ...
tst.b ($FFFFF730).w
bne.s Obj4C_InWater
return_31556C: ; ... rts
- ---------------------------------------------------------------------------
Obj4C_InWater: ; ... move.w ($FFFFF646).w,d0 cmp.w $C(a0),d0 bge.s Obj4C_OutWater bset #6,$22(a0) bne.s return_31556C move.l a0,a1 bsr.w ResumeMusic move.b #$A,($FFFFD080).w move.b #$81,($FFFFD0A8).w move.l a0,($FFFFD0BC).w move.w #$300,($FFFFF760).w move.w #6,($FFFFF762).w move.w #$40,($FFFFF764).w tst.b ($FFFFFE19).w beq.s loc_3155C0 move.w #$400,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$60,($FFFFF764).w
loc_3155C0: ; ... asr $10(a0) asr $12(a0) asr $12(a0) beq.s return_31556C move.w #$100,($FFFFD11C).w move.w #$AA,d0 jmp PlaySound
- ---------------------------------------------------------------------------
Obj4C_OutWater: ; ... bclr #6,$22(a0) beq.s return_31556C move.l a0,a1 bsr.w ResumeMusic move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w tst.b ($FFFFFE19).w beq.s loc_315616 move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w
loc_315616: ; ... cmp.b #4,$24(a0) beq.s loc_315622 asl $12(a0)
loc_315622: ; ... tst.w $12(a0) beq.w return_31556C
move.w #$100,($FFFFD11C).w
move.l a0,a1 bsr.w ResumeMusic cmp.w #$F000,$12(a0) bgt.s loc_315644 move.w #$F000,$12(a0)
loc_315644: ; ... move.w #$AA,d0 jmp PlaySound
- End of function Knuckles_Water
- =============== S U B R O U T I N E =======================================
Obj4C_MdNormal: ; ...
bsr.w Knuckles_Spindash
bsr.w Knuckles_Jump
bsr.w Knuckles_SlopeResist
bsr.w Knuckles_Move
bsr.w Knuckles_Roll
bsr.w Knuckles_LevelBoundaries
jsr ObjectMove ; AKA SpeedToPos in Sonic 1
bsr.w AnglePos
bsr.w Knuckles_SlopeRepel
rts
- End of function Obj4C_MdNormal
- =============== S U B R O U T I N E =======================================
Obj4C_MdAir: ; ...
tst.b $21(a0)
bne.s Obj4C_MdAir_Gliding
bsr.w Knuckles_JumpHeight
bsr.w Knuckles_ChgJumpDir
bsr.w Knuckles_LevelBoundaries
jsr ObjectMoveAndFall
btst #6,$22(a0)
beq.s loc_31569C
sub.w #$28,$12(a0)
loc_31569C: ; ... bsr.w Knuckles_JumpAngle bsr.w Knuckles_DoLevelCollision rts
- ---------------------------------------------------------------------------
Obj4C_MdAir_Gliding: ; ... bsr.w Knuckles_GlideSpeedControl bsr.w Knuckles_LevelBoundaries jsr ObjectMove ; AKA SpeedToPos in Sonic 1 bsr.w Knuckles_GlideControl
return_3156B8: ; ... rts
- End of function Obj4C_MdAir
- =============== S U B R O U T I N E =======================================
Knuckles_GlideControl: ; ...
- FUNCTION CHUNK AT 00315C40 SIZE 0000003C BYTES
move.b $21(a0),d0 beq.s return_3156B8 cmp.b #2,d0 beq.w Knuckles_FallingFromGlide cmp.b #3,d0 beq.w Knuckles_Sliding cmp.b #4,d0 beq.w Knuckles_Climbing_Wall cmp.b #5,d0 beq.w Knuckles_Climbing_Up
Knuckles_NormalGlide: move.b #$A,$16(a0) move.b #$A,$17(a0) bsr.w Knuckles_DoLevelCollision2 btst #5,($FFFFF7AC).w bne.w Knuckles_BeginClimb move.b #$13,$16(a0) move.b #9,$17(a0) btst #1,($FFFFF7AC).w beq.s Knuckles_BeginSlide move.b ($FFFFF602).w,d0 and.b #$70,d0 bne.s loc_31574C move.b #2,$21(a0) move.b #$21,$1C(a0) bclr #0,$22(a0) tst.w $10(a0) bpl.s loc_315736 bset #0,$22(a0)
loc_315736: ; ... asr $10(a0) asr $10(a0) move.b #$13,$16(a0) move.b #9,$17(a0) rts
- ---------------------------------------------------------------------------
loc_31574C: ; ... bra.w sub_315C7C
- ---------------------------------------------------------------------------
Knuckles_BeginSlide: ; ... bclr #0,$22(a0) tst.w $10(a0) bpl.s loc_315762 bset #0,$22(a0)
loc_315762: ; ... move.b $26(a0),d0 add.b #$20,d0 and.b #$C0,d0 beq.s loc_315780 move.w $14(a0),$10(a0) move.w #0,$12(a0) bra.w Knuckles_ResetOnFloor_Part2
- ---------------------------------------------------------------------------
loc_315780: ; ... move.b #3,$21(a0) move.b #$CC,$1A(a0) move.b #$7F,$1E(a0) move.b #0,$1B(a0) cmp.b #$C,$28(a0) bcs.s return_3157AC move.b #6,($FFFFD124).w move.b #$15,($FFFFD11A).w
return_3157AC: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_BeginClimb: ; ... tst.b ($FFFFF7AD).w bmi.w loc_31587A move.b $3F(a0),d5 move.b $1F(a0),d0 add.b #$40,d0 bpl.s loc_3157D8 bset #0,$22(a0) bsr.w CheckLeftCeilingDist or.w d0,d1 bne.s Knuckles_FallFromGlide addq.w #1,8(a0) bra.s loc_3157E8
- ---------------------------------------------------------------------------
loc_3157D8: ; ... bclr #0,$22(a0) bsr.w CheckRightCeilingDist or.w d0,d1 bne.w loc_31586A
loc_3157E8: ; ... move.b #$13,$16(a0) move.b #9,$17(a0) tst.b ($FFFFFE19).w beq.s loc_315804 cmp.w #$480,$14(a0) bcs.s loc_315804 nop
loc_315804: ; ... move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.b #4,$21(a0) move.b #$B7,$1A(a0) move.b #$7F,$1E(a0) move.b #0,$1B(a0) move.b #3,$1F(a0) move.w 8(a0),$A(a0) rts
- ---------------------------------------------------------------------------
Knuckles_FallFromGlide: ; ... move.w 8(a0),d3 move.b $16(a0),d0 ext.w d0 sub.w d0,d3 subq.w #1,d3
loc_31584A: ; ... move.w $C(a0),d2 sub.w #$B,d2 jsr ChkFloorEdge_Part2 tst.w d1 bmi.s loc_31587A cmp.w #$C,d1 bcc.s loc_31587A add.w d1,$C(a0) bra.w loc_3157E8
- ---------------------------------------------------------------------------
loc_31586A: ; ... move.w 8(a0),d3 move.b $16(a0),d0 ext.w d0 add.w d0,d3 addq.w #1,d3 bra.s loc_31584A
- ---------------------------------------------------------------------------
loc_31587A: ; ... move.b #2,$21(a0) move.b #$21,$1C(a0) move.b #$13,$16(a0) move.b #9,$17(a0) bset #1,($FFFFF7AC).w rts
- ---------------------------------------------------------------------------
Knuckles_FallingFromGlide: ; ... bsr.w Knuckles_ChgJumpDir add.w #$38,$12(a0) btst #6,$22(a0) beq.s loc_3158B2 sub.w #$28,$12(a0)
loc_3158B2: ; ... bsr.w Knuckles_DoLevelCollision2 btst #1,($FFFFF7AC).w bne.s return_315900 move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.b $16(a0),d0 sub.b #$13,d0 ext.w d0 add.w d0,$C(a0) move.b $26(a0),d0 add.b #$20,d0 and.b #$C0,d0 beq.s loc_3158F0 bra.w Knuckles_ResetOnFloor_Part2
- ---------------------------------------------------------------------------
loc_3158F0: ; ... bsr.w Knuckles_ResetOnFloor_Part2 move.w #$F,$2E(a0) move.b #$23,$1C(a0)
return_315900: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_Sliding: ; ... move.b ($FFFFF602).w,d0 and.b #$70,d0 beq.s loc_315926 tst.w $10(a0) bpl.s loc_31591E add.w #$20,$10(a0) bmi.s loc_31591C bra.s loc_315926
- ---------------------------------------------------------------------------
loc_31591C: ; ... bra.s loc_315958
- ---------------------------------------------------------------------------
loc_31591E: ; ... sub.w #$20,$10(a0) bpl.s loc_315958
loc_315926: ; ... move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.b $16(a0),d0 sub.b #$13,d0 ext.w d0 add.w d0,$C(a0) bsr.w Knuckles_ResetOnFloor_Part2 move.w #$F,$2E(a0) move.b #$22,$1C(a0) rts
- ---------------------------------------------------------------------------
loc_315958: ; ... move.b #$A,$16(a0) move.b #$A,$17(a0) bsr.w Knuckles_DoLevelCollision2 bsr.w Player_CheckFloor cmp.w #$E,d1 bge.s loc_315988 add.w d1,$C(a0) move.b d3,$26(a0) move.b #$13,$16(a0) move.b #9,$17(a0) rts
- ---------------------------------------------------------------------------
loc_315988: ; ... move.b #2,$21(a0) move.b #$21,$1C(a0) move.b #$13,$16(a0) move.b #9,$17(a0) bset #1,($FFFFF7AC).w rts
- ---------------------------------------------------------------------------
Knuckles_Climbing_Wall: ; ... tst.b ($FFFFF7AD).w bmi.w loc_315BAE move.w 8(a0),d0 cmp.w $A(a0),d0 bne.w loc_315BAE btst #3,$22(a0) bne.w loc_315BAE move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.l #$FFFFD600,($FFFFF796).w cmp.b #$D,$3F(a0) beq.s loc_3159F0 move.l #$FFFFD900,($FFFFF796).w
loc_3159F0: ; ... move.b $3F(a0),d5 move.b #$A,$16(a0) move.b #$A,$17(a0) moveq #0,d1 btst #0,($FFFFF602).w beq.w loc_315A76 move.w $C(a0),d2 sub.w #$B,d2 bsr.w sub_315C22 cmp.w #4,d1 bge.w Knuckles_ClimbUp ; Climb onto the floor above you tst.w d1 bne.w loc_315B30 move.b $3F(a0),d5 move.w $C(a0),d2 subq.w #8,d2 move.w 8(a0),d3 bsr.w sub_3192E6 ; Doesn't exist in S2 tst.w d1 bpl.s loc_315A46 sub.w d1,$C(a0) moveq #1,d1 bra.w loc_315B04
- ---------------------------------------------------------------------------
loc_315A46: ; ... subq.w #1,$C(a0) tst.b ($FFFFFE19).w beq.s loc_315A54 subq.w #1,$C(a0)
loc_315A54: ; ... moveq #1,d1 move.w ($FFFFEECC).w,d0 cmp.w #-$100,d0 beq.w loc_315B04 add.w #$10,d0 cmp.w $C(a0),d0 ble.w loc_315B04 move.w d0,$C(a0) bra.w loc_315B04
- ---------------------------------------------------------------------------
loc_315A76: ; ... btst #1,($FFFFF602).w beq.w loc_315B04 cmp.b #$BD,$1A(a0) bne.s loc_315AA2 move.b #$B7,$1A(a0) addq.w #3,$C(a0) subq.w #3,8(a0) btst #0,$22(a0) beq.s loc_315AA2 addq.w #6,8(a0)
loc_315AA2: ; ... move.w $C(a0),d2 add.w #$B,d2 bsr.w sub_315C22 tst.w d1 bne.w loc_315BAE move.b $3E(a0),d5 move.w $C(a0),d2 add.w #9,d2 move.w 8(a0),d3 bsr.w sub_318FF6 tst.w d1 bpl.s loc_315AF4 add.w d1,$C(a0) move.b ($FFFFF768).w,$26(a0) move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) bsr.w Knuckles_ResetOnFloor_Part2 move.b #5,$1C(a0) rts
- ---------------------------------------------------------------------------
loc_315AF4: ; ... addq.w #1,$C(a0) tst.b ($FFFFFE19).w beq.s loc_315B02 addq.w #1,$C(a0)
loc_315B02: ; ... moveq #-1,d1
loc_315B04: ; ... tst.w d1 beq.s loc_315B30 subq.b #1,$1F(a0) bpl.s loc_315B30 move.b #3,$1F(a0) add.b $1A(a0),d1 cmp.b #$B7,d1 bcc.s loc_315B22 move.b #$BC,d1
loc_315B22: ; ... cmp.b #$BC,d1 bls.s loc_315B2C move.b #$B7,d1
loc_315B2C: ; ... move.b d1,$1A(a0)
loc_315B30: ; ... move.b #$20,$1E(a0) move.b #0,$1B(a0) move.b #$13,$16(a0) move.b #9,$17(a0) move.w ($FFFFF602).w,d0 and.w #$70,d0 beq.s return_315B94 move.w #$FC80,$12(a0) move.w #$400,$10(a0) bchg #0,$22(a0) bne.s loc_315B6A neg.w $10(a0)
loc_315B6A: ; ... bset #1,$22(a0) move.b #1,$3C(a0) move.b #$E,$16(a0) move.b #7,$17(a0) move.b #2,$1C(a0) bset #2,$22(a0) move.b #0,$21(a0)
return_315B94: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_ClimbUp: ; ... move.b #5,$21(a0) ; Climb up to the floor above you cmp.b #$BD,$1A(a0) beq.s return_315BAC move.b #0,$1F(a0) bsr.s sub_315BDA
return_315BAC: ; ... rts
- ---------------------------------------------------------------------------
loc_315BAE: ; ... move.b #2,$21(a0) move.w #$2121,$1C(a0) move.b #$CB,$1A(a0) move.b #7,$1E(a0) move.b #1,$1B(a0) move.b #$13,$16(a0) move.b #9,$17(a0) rts
- End of function Knuckles_GlideControl
- =============== S U B R O U T I N E =======================================
sub_315BDA: ; ...
moveq #0,d0
move.b $1F(a0),d0
lea word_315C12(pc,d0.w),a1
move.b (a1)+,$1A(a0)
move.b (a1)+,d0
ext.w d0
btst #0,$22(a0)
beq.s loc_315BF6
neg.w d0
loc_315BF6: ; ... add.w d0,8(a0) move.b (a1)+,d1 ext.w d1 add.w d1,$C(a0) move.b (a1)+,$1E(a0) addq.b #4,$1F(a0) move.b #0,$1B(a0) rts
- End of function sub_315BDA
- ---------------------------------------------------------------------------
word_315C12: dc.w $BD03,$FD06,$BE08,$F606,$BFF8,$F406,$D208,$FB06; 0 ; ...
- =============== S U B R O U T I N E =======================================
sub_315C22: ; ...
- FUNCTION CHUNK AT 00319208 SIZE 00000020 BYTES
- FUNCTION CHUNK AT 003193D2 SIZE 00000024 BYTES
move.b $3F(a0),d5 btst #0,$22(a0) bne.s loc_315C36 move.w 8(a0),d3 bra.w loc_319208
- ---------------------------------------------------------------------------
loc_315C36: ; ... move.w 8(a0),d3 subq.w #1,d3 bra.w loc_3193D2
- End of function sub_315C22
- ---------------------------------------------------------------------------
- START OF FUNCTION CHUNK FOR Knuckles_GlideControl
Knuckles_Climbing_Up: ; ... tst.b $1E(a0) bne.s return_315C7A bsr.w sub_315BDA cmp.b #$10,$1F(a0) bne.s return_315C7A move.w #0,$14(a0) move.w #0,$10(a0) move.w #0,$12(a0) btst #0,$22(a0) beq.s loc_315C70 subq.w #1,8(a0)
loc_315C70: ; ... bsr.w Knuckles_ResetOnFloor_Part2 move.b #5,$1C(a0)
return_315C7A: ; ... rts
- END OF FUNCTION CHUNK FOR Knuckles_GlideControl
- =============== S U B R O U T I N E =======================================
sub_315C7C: ; ...
move.b #$20,$1E(a0)
move.b #0,$1B(a0)
move.w #$2020,$1C(a0)
bclr #5,$22(a0)
bclr #0,$22(a0)
moveq #0,d0
move.b $1F(a0),d0
add.b #$10,d0
lsr.w #5,d0
move.b byte_315CC2(pc,d0.w),d1
move.b d1,$1A(a0)
cmp.b #$C4,d1
bne.s return_315CC0
bset #0,$22(a0)
move.b #$C0,$1A(a0)
return_315CC0: ; ... rts
- End of function sub_315C7C
- ---------------------------------------------------------------------------
byte_315CC2: dc.b $C0,$C1,$C2,$C3,$C4,$C3,$C2,$C1; 0 ; ...
- =============== S U B R O U T I N E =======================================
Knuckles_GlideSpeedControl: ; ...
cmp.b #1,$21(a0)
bne.w loc_315D88
move.w $14(a0),d0
cmp.w #$400,d0
bcc.s loc_315CE2
addq.w #8,d0
bra.s loc_315CFC
- ---------------------------------------------------------------------------
loc_315CE2: ; ... cmp.w #$1800,d0 bcc.s loc_315CFC move.b $1F(a0),d1 and.b #$7F,d1 bne.s loc_315CFC addq.w #4,d0 tst.b ($FFFFFE19).w beq.s loc_315CFC addq.w #8,d0
loc_315CFC: ; ... move.w d0,$14(a0) move.b $1F(a0),d0 btst #2,($FFFFF602).w beq.s loc_315D1C cmp.b #$80,d0 beq.s loc_315D1C tst.b d0 bpl.s loc_315D18 neg.b d0
loc_315D18: ; ... addq.b #2,d0 bra.s loc_315D3A
- ---------------------------------------------------------------------------
loc_315D1C: ; ... btst #3,($FFFFF602).w beq.s loc_315D30 tst.b d0 beq.s loc_315D30 bmi.s loc_315D2C neg.b d0
loc_315D2C: ; ... addq.b #2,d0 bra.s loc_315D3A
- ---------------------------------------------------------------------------
loc_315D30: ; ... move.b d0,d1 and.b #$7F,d1 beq.s loc_315D3A addq.b #2,d0
loc_315D3A: ; ... move.b d0,$1F(a0) move.b $1F(a0),d0 jsr CalcSine muls.w $14(a0),d1 asr.l #8,d1 move.w d1,$10(a0) cmp.w #$80,$12(a0) blt.s loc_315D62 sub.w #$20,$12(a0) bra.s loc_315D68
- ---------------------------------------------------------------------------
loc_315D62: ; ... add.w #$20,$12(a0)
loc_315D68: ; ... move.w ($FFFFEECC).w,d0 cmp.w #$FF00,d0 beq.w loc_315D88 add.w #$10,d0 cmp.w $C(a0),d0 ble.w loc_315D88 asr $10(a0) asr $14(a0)
loc_315D88: ; ... cmp.w #$60,($FFFFEED8).w beq.s return_315D9A bcc.s loc_315D96 addq.w #4,($FFFFEED8).w
loc_315D96: ; ... subq.w #2,($FFFFEED8).w
return_315D9A: ; ... rts
- End of function Knuckles_GlideSpeedControl
- ---------------------------------------------------------------------------
</asm>
Step 5: Obj4C_MdRoll and Obj4C_MdJump
Paste this below the code mentioned above, changing the "Obj01"s to "Obj4C"s: <asm> Obj01_MdRoll: ; ... tst.b $39(a0) bne.s loc_315DA6 bsr.w Knuckles_Jump
loc_315DA6: ; ... bsr.w Knuckles_RollRepel bsr.w Knuckles_RollSpeed bsr.w Knuckles_LevelBoundaries jsr ObjectMove ; AKA SpeedToPos in Sonic 1 bsr.w AnglePos bsr.w Knuckles_SlopeRepel rts
- ---------------------------------------------------------------------------
Obj01_MdJump: ; ... bsr.w Knuckles_JumpHeight bsr.w Knuckles_ChgJumpDir bsr.w Knuckles_LevelBoundaries jsr ObjectMoveAndFall btst #6,$22(a0) beq.s loc_315DE2 sub.w #$28,$12(a0)
loc_315DE2: ; ... bsr.w Knuckles_JumpAngle bsr.w Knuckles_DoLevelCollision rts
</asm> Done! Piece of cake.
Step 6: TONS of essential coding!
Well, it's time to actually get something accomplished movement-wise, don't you think? That's where this step comes in. Put the following heap of code below the code we already have: <asm>
- =============== S U B R O U T I N E =======================================
Knuckles_Move: ; ...
move.w ($FFFFF760).w,d6
move.w ($FFFFF762).w,d5
move.w ($FFFFF764).w,d4
tst.b $2B(a0)
bmi.w Obj01_Traction
tst.w $2E(a0)
bne.w Obj01_ResetScreen
btst #2,($FFFFF602).w
beq.s Obj01_NotLeft
bsr.w Knuckles_MoveLeft
Obj01_NotLeft: ; ... btst #3,($FFFFF602).w beq.s Obj01_NotRight bsr.w Knuckles_MoveRight
Obj01_NotRight: ; ... move.b $26(a0),d0 add.b #$20,d0 and.b #$C0,d0 bne.w Obj01_ResetScreen tst.w $14(a0) bne.w Obj01_ResetScreen bclr #5,$22(a0) move.b #5,$1C(a0) btst #3,$22(a0) beq.w Knuckles_Balance moveq #0,d0 move.b $3D(a0),d0 lsl.w #6,d0 lea ($FFFFB000).w,a1 lea (a1,d0.w),a1 tst.b $22(a1) bmi.w Knuckles_LookUp moveq #0,d1 move.b $19(a1),d1 move.w d1,d2 add.w d2,d2 subq.w #2,d2 add.w 8(a0),d1 sub.w 8(a1),d1 cmp.w #2,d1 blt.s Knuckles_BalanceOnObjLeft cmp.w d2,d1 bge.s Knuckles_BalanceOnObjRight bra.w Knuckles_LookUp
- ---------------------------------------------------------------------------
Knuckles_BalanceOnObjRight: ; ... btst #0,$22(a0) bne.s loc_315E9A move.b #6,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
loc_315E9A: ; ... bclr #0,$22(a0) move.b #0,$1E(a0) move.b #4,$1B(a0) move.w #$606,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
Knuckles_BalanceOnObjLeft: ; ... btst #0,$22(a0) beq.s loc_315EC8 move.b #6,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
loc_315EC8: ; ... bset #0,$22(a0) move.b #0,$1E(a0) move.b #4,$1B(a0) move.w #$606,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
Knuckles_Balance: ; ... jsr ChkFloorEdge cmp.w #$C,d1 blt.w Knuckles_LookUp cmp.b #3,$36(a0) bne.s Knuckles_BalanceLeft btst #0,$22(a0) bne.s loc_315F0C move.b #6,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
loc_315F0C: ; ... bclr #0,$22(a0) move.b #0,$1E(a0) move.b #4,$1B(a0) move.w #$606,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
Knuckles_BalanceLeft: ; ... cmp.b #3,$37(a0) bne.s Knuckles_LookUp btst #0,$22(a0) beq.s loc_315F42 move.b #6,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
loc_315F42: ; ... bset #0,$22(a0) move.b #0,$1E(a0) move.b #4,$1B(a0) move.w #$606,$1C(a0) bra.w Obj01_ResetScreen
- ---------------------------------------------------------------------------
Knuckles_LookUp: ; ... btst #0,($FFFFF602).w beq.s Knuckles_Duck move.b #7,$1C(a0) addq.w #1,($FFFFF66C).w cmp.w #$78,($FFFFF66C).w bcs.s Obj01_ResetScreen_Part2 move.w #$78,($FFFFF66C).w cmp.w #$C8,($FFFFEED8).w beq.s Obj01_UpdateSpeedOnGround addq.w #2,($FFFFEED8).w bra.s Obj01_UpdateSpeedOnGround
- ---------------------------------------------------------------------------
Knuckles_Duck: ; ... btst #1,($FFFFF602).w beq.s Obj01_ResetScreen move.b #8,$1C(a0) addq.w #1,($FFFFF66C).w cmp.w #$78,($FFFFF66C).w bcs.s Obj01_ResetScreen_Part2 move.w #$78,($FFFFF66C).w cmp.w #8,($FFFFEED8).w beq.s Obj01_UpdateSpeedOnGround subq.w #2,($FFFFEED8).w bra.s Obj01_UpdateSpeedOnGround
- ---------------------------------------------------------------------------
Obj01_ResetScreen: ; ... move.w #0,($FFFFF66C).w
Obj01_ResetScreen_Part2: ; ... cmp.w #$60,($FFFFEED8).w beq.s Obj01_UpdateSpeedOnGround bcc.s loc_315FCE addq.w #4,($FFFFEED8).w
loc_315FCE: ; ... subq.w #2,($FFFFEED8).w
Obj01_UpdateSpeedOnGround: ; ... tst.b ($FFFFFE19).w beq.s loc_315FDC move.w #$C,d5
loc_315FDC: ; ... move.b ($FFFFF602).w,d0 and.b #$C,d0 bne.s Obj01_Traction move.w $14(a0),d0 beq.s Obj01_Traction bmi.s Obj01_SettleLeft sub.w d5,d0 bcc.s loc_315FF6 move.w #0,d0
loc_315FF6: ; ... move.w d0,$14(a0) bra.s Obj01_Traction
- ---------------------------------------------------------------------------
Obj01_SettleLeft: ; ... add.w d5,d0 bcc.s loc_316004 move.w #0,d0
loc_316004: ; ... move.w d0,$14(a0)
Obj01_Traction: ; ... move.b $26(a0),d0 jsr CalcSine muls.w $14(a0),d1 asr.l #8,d1 move.w d1,$10(a0) muls.w $14(a0),d0 asr.l #8,d0 move.w d0,$12(a0)
Obj01_CheckWallsOnGround: ; ... move.b $26(a0),d0 add.b #$40,d0 bmi.s return_3160A6 move.b #$40,d1 tst.w $14(a0) beq.s return_3160A6 bmi.s loc_31603E neg.w d1
loc_31603E: ; ... move.b $26(a0),d0 add.b d1,d0 move.w d0,-(sp) bsr.w CalcRoomInFront ; Also known as Sonic_WalkSpeed in Sonic 1 move.w (sp)+,d0 tst.w d1 bpl.s return_3160A6 asl.w #8,d1 add.b #$20,d0 and.b #$C0,d0 beq.s loc_3160A2 cmp.b #$40,d0 beq.s loc_316088 cmp.b #$80,d0 beq.s loc_316082 add.w d1,$10(a0) move.w #0,$14(a0) btst #0,$22(a0) bne.s return_316080 bset #5,$22(a0)
return_316080: ; ... rts
- ---------------------------------------------------------------------------
loc_316082: ; ... sub.w d1,$12(a0) rts
- ---------------------------------------------------------------------------
loc_316088: ; ... sub.w d1,$10(a0) move.w #0,$14(a0) btst #0,$22(a0) beq.s return_316080 bset #5,$22(a0) rts
- ---------------------------------------------------------------------------
loc_3160A2: ; ... add.w d1,$12(a0)
return_3160A6: ; ... rts
- End of function Knuckles_Move
- =============== S U B R O U T I N E =======================================
Knuckles_MoveLeft: ; ...
move.w $14(a0),d0
beq.s loc_3160B0
bpl.s Knuckles_TurnLeft
loc_3160B0: ; ... bset #0,$22(a0) bne.s loc_3160C4 bclr #5,$22(a0) move.b #1,$1D(a0)
loc_3160C4: ; ... sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_3160D6 add.w d5,d0 cmp.w d1,d0 ble.s loc_3160D6 move.w d1,d0
loc_3160D6: ; ... move.w d0,$14(a0) move.b #0,$1C(a0) rts
- ---------------------------------------------------------------------------
Knuckles_TurnLeft: ; ... sub.w d4,d0 bcc.s loc_3160EA move.w #-$80,d0
loc_3160EA: ; ... move.w d0,$14(a0) move.b $26(a0),d1 add.b #$20,d1 and.b #$C0,d1 bne.s return_31612C cmp.w #$400,d0 blt.s return_31612C move.b #$D,$1C(a0) bclr #0,$22(a0) move.w #$A4,d0 jsr PlaySound cmp.b #$C,$28(a0) bcs.s return_31612C move.b #6,($FFFFD124).w move.b #$15,($FFFFD11A).w
return_31612C: ; ... rts
- End of function Knuckles_MoveLeft
- =============== S U B R O U T I N E =======================================
Knuckles_MoveRight: ; ...
move.w $14(a0),d0
bmi.s Knuckles_TurnRight
bclr #0,$22(a0)
beq.s loc_316148
bclr #5,$22(a0)
move.b #1,$1D(a0)
loc_316148: ; ... add.w d5,d0 cmp.w d6,d0 blt.s loc_316156 sub.w d5,d0 cmp.w d6,d0 bge.s loc_316156 move.w d6,d0
loc_316156: ; ... move.w d0,$14(a0) move.b #0,$1C(a0) rts
- ---------------------------------------------------------------------------
Knuckles_TurnRight: ; ... add.w d4,d0 bcc.s loc_31616A move.w #$80,d0
loc_31616A: ; ... move.w d0,$14(a0) move.b $26(a0),d1 add.b #$20,d1 and.b #$C0,d1 bne.s return_3161AC cmp.w #$FC00,d0 bgt.s return_3161AC move.b #$D,$1C(a0) bset #0,$22(a0) move.w #$A4,d0 jsr PlaySound cmp.b #$C,$28(a0) bcs.s return_3161AC move.b #6,($FFFFD124).w move.b #$15,($FFFFD11A).w
return_3161AC: ; ... rts
- End of function Knuckles_MoveRight
- =============== S U B R O U T I N E =======================================
Knuckles_RollSpeed: ; ...
move.w ($FFFFF760).w,d6
asl.w #1,d6
move.w ($FFFFF762).w,d5
asr.w #1,d5
move.w #$20,d4
tst.b $2B(a0)
bmi.w Obj01_Roll_ResetScreen
tst.w $2E(a0)
bne.s Knuckles_Apply_RollSpeed
btst #2,($FFFFF602).w
beq.s loc_3161D8
bsr.w Knuckles_RollLeft
loc_3161D8: ; ... btst #3,($FFFFF602).w beq.s Knuckles_Apply_RollSpeed bsr.w Knuckles_RollRight
Knuckles_Apply_RollSpeed: ; ... move.w $14(a0),d0 beq.s Knuckles_CheckRollStop bmi.s Knuckles_ApplyRollSpeedLeft sub.w d5,d0 bcc.s loc_3161F4 move.w #0,d0
loc_3161F4: ; ... move.w d0,$14(a0) bra.s Knuckles_CheckRollStop
- ---------------------------------------------------------------------------
Knuckles_ApplyRollSpeedLeft: ; ... add.w d5,d0 bcc.s loc_316202 move.w #0,d0
loc_316202: ; ... move.w d0,$14(a0)
Knuckles_CheckRollStop: ; ... tst.w $14(a0) bne.s Obj01_Roll_ResetScreen tst.b $39(a0) bne.s Knuckles_KeepRolling bclr #2,$22(a0) move.b #$13,$16(a0) move.b #9,$17(a0) move.b #5,$1C(a0) subq.w #5,$C(a0) bra.s Obj01_Roll_ResetScreen
- ---------------------------------------------------------------------------
- magically gives Knuckles an extra push if he's going to stop rolling where it's not allowed
- (such as in an S-curve in HTZ or a stopper chamber in CNZ)
Knuckles_KeepRolling: ; ...
move.w #$400,$14(a0)
btst #0,$22(a0)
beq.s Obj01_Roll_ResetScreen
neg.w $14(a0)
Obj01_Roll_ResetScreen: ; ... cmp.w #$60,($FFFFEED8).w beq.s Knuckles_SetRollSpeeds bcc.s loc_316250 addq.w #4,($FFFFEED8).w
loc_316250: ; ... subq.w #2,($FFFFEED8).w
Knuckles_SetRollSpeeds: ; ... move.b $26(a0),d0 jsr CalcSine muls.w $14(a0),d0 asr.l #8,d0 move.w d0,$12(a0) muls.w $14(a0),d1 asr.l #8,d1 cmp.w #$1000,d1 ble.s loc_316278 move.w #$1000,d1
loc_316278: ; ... cmp.w #-$1000,d1 bge.s loc_316282 move.w #-$1000,d1
loc_316282: ; ... move.w d1,$10(a0) bra.w Obj01_CheckWallsOnGround
- End of function Knuckles_RollSpeed
- =============== S U B R O U T I N E =======================================
Knuckles_RollLeft: ; ...
move.w $14(a0),d0
beq.s loc_316292
bpl.s Knuckles_BrakeRollingRight
loc_316292: ; ... bset #0,$22(a0) move.b #2,$1C(a0) rts
- ---------------------------------------------------------------------------
Knuckles_BrakeRollingRight: ; ... sub.w d4,d0 bcc.s loc_3162A8 move.w #-$80,d0
loc_3162A8: ; ... move.w d0,$14(a0) rts
- End of function Knuckles_RollLeft
- =============== S U B R O U T I N E =======================================
Knuckles_RollRight: ; ...
move.w $14(a0),d0
bmi.s Knuckles_BrakeRollingLeft
bclr #0,$22(a0)
move.b #2,$1C(a0)
rts
- ---------------------------------------------------------------------------
Knuckles_BrakeRollingLeft: ; ... add.w d4,d0 bcc.s loc_3162CA move.w #$80,d0
loc_3162CA: ; ... move.w d0,$14(a0) rts
- End of function Knuckles_RollRight
- ---------------------------------------------------------------------------
- Subroutine for moving Knuckles left or right when he's in the air
- ---------------------------------------------------------------------------
- =============== S U B R O U T I N E =======================================
Knuckles_ChgJumpDir: ; ...
move.w ($FFFFF760).w,d6
move.w ($FFFFF762).w,d5
asl.w #1,d5
btst #4,$22(a0)
bne.s Obj01_Jump_ResetScreen
move.w $10(a0),d0
btst #2,($FFFFF602).w
beq.s loc_31630E
bset #0,$22(a0)
sub.w d5,d0
move.w d6,d1
neg.w d1
cmp.w d1,d0
bgt.s loc_31630E
tst.w ($FFFFFFD0).w
bne.w loc_31630C
add.w d5,d0
cmp.w d1,d0
ble.s loc_31630E
loc_31630C: ; ... move.w d1,d0
loc_31630E: ; ... btst #3,($FFFFF602).w beq.s loc_316332 bclr #0,$22(a0) add.w d5,d0 cmp.w d6,d0 blt.s loc_316332 tst.w ($FFFFFFD0).w bne.w loc_316330 sub.w d5,d0 cmp.w d6,d0 bge.s loc_316332
loc_316330: ; ... move.w d6,d0
loc_316332: ; ... move.w d0,$10(a0)
Obj01_Jump_ResetScreen: ; ... cmp.w #$60,($FFFFEED8).w beq.s Knuckles_JumpPeakDecelerate bcc.s loc_316344 addq.w #4,($FFFFEED8).w
loc_316344: ; ... subq.w #2,($FFFFEED8).w
Knuckles_JumpPeakDecelerate: ; ... cmp.w #-$400,$12(a0) bcs.s return_316376 move.w $10(a0),d0 move.w d0,d1 asr.w #5,d1 beq.s return_316376 bmi.s Knuckles_JumpPeakDecelerateLeft sub.w d1,d0 bcc.s loc_316364 move.w #0,d0
loc_316364: ; ... move.w d0,$10(a0) rts
- ---------------------------------------------------------------------------
Knuckles_JumpPeakDecelerateLeft: ; ... sub.w d1,d0 bcs.s loc_316372 move.w #0,d0
loc_316372: ; ... move.w d0,$10(a0)
return_316376: ; ... rts
- End of function Knuckles_ChgJumpDir
- =============== S U B R O U T I N E =======================================
Knuckles_LevelBoundaries: ; ...
move.l 8(a0),d1
move.w $10(a0),d0
ext.l d0
asl.l #8,d0
add.l d0,d1
swap d1
move.w ($FFFFEEC8).w,d0
add.w #$10,d0
cmp.w d1,d0
bhi.s Knuckles_Boundary_Sides
move.w ($FFFFEECA).w,d0
add.w #$128,d0
tst.b ($FFFFF7AA).w
bne.s loc_3163A6
add.w #$40,d0
loc_3163A6: ; ... cmp.w d1,d0 bls.s Knuckles_Boundary_Sides
Knuckles_Boundary_CheckBottom: ; ... move.w ($FFFFEECE).w,d0 add.w #$E0,d0 cmp.w $C(a0),d0 blt.s Knuckles_Boundary_Bottom rts
- ---------------------------------------------------------------------------
Knuckles_Boundary_Bottom: ; ... jmp KillCharacter
- ---------------------------------------------------------------------------
Knuckles_Boundary_Sides: ; ... move.w d0,8(a0) move.w #0,$A(a0) move.w #0,$10(a0) move.w #0,$14(a0) bra.s Knuckles_Boundary_CheckBottom
- End of function Knuckles_LevelBoundaries
- =============== S U B R O U T I N E =======================================
Knuckles_Roll: ; ...
tst.b $2B(a0)
bmi.s Obj01_NoRoll
move.w $14(a0),d0
bpl.s loc_3163E6
neg.w d0
loc_3163E6: ; ... cmp.w #$80,d0 bcs.s Obj01_NoRoll move.b ($FFFFF602).w,d0 and.b #$C,d0 bne.s Obj01_NoRoll btst #1,($FFFFF602).w bne.s Obj01_ChkRoll
Obj01_NoRoll: ; ... rts
- ---------------------------------------------------------------------------
Obj01_ChkRoll: ; ... btst #2,$22(a0) beq.s Obj01_DoRoll rts
- ---------------------------------------------------------------------------
Obj01_DoRoll: ; ... bset #2,$22(a0) move.b #$E,$16(a0) move.b #7,$17(a0) move.b #2,$1C(a0) addq.w #5,$C(a0) move.w #$BE,d0 jsr PlaySound tst.w $14(a0) bne.s return_31643C move.w #$200,$14(a0)
return_31643C: ; ... rts
- End of function Knuckles_Roll
- =============== S U B R O U T I N E =======================================
Knuckles_Jump: ; ...
move.b ($FFFFF603).w,d0
and.b #$70,d0
beq.w return_3164EC
moveq #0,d0
move.b $26(a0),d0
add.b #$80,d0
bsr.w CalcRoomOverHead
cmp.w #6,d1
blt.w return_3164EC
move.w #$600,d2
btst #6,$22(a0)
beq.s loc_316470
move.w #$300,d2
loc_316470: ; ... tst.w ($FFFFFFD0).w ; Check for demo mode (note: in normal Sonic 2, this is the level select flag!) beq.s loc_31647A add.w #$80,d2 ; Set the jump height to Sonic's height in Demo mode because Sonic Team were too lazy to record new demos for S2&K.
loc_31647A: ; ... moveq #0,d0 move.b $26(a0),d0 sub.b #$40,d0 jsr CalcSine muls.w d2,d1 asr.l #8,d1 add.w d1,$10(a0) muls.w d2,d0 asr.l #8,d0 add.w d0,$12(a0) bset #1,$22(a0) bclr #5,$22(a0) addq.l #4,sp move.b #1,$3C(a0) clr.b $38(a0)
loc_3164B2: move.w #$A0,d0 jsr PlaySound move.b #$13,$16(a0) move.b #9,$17(a0) btst #2,$22(a0) bne.s Knuckles_RollJump move.b #$E,$16(a0) move.b #7,$17(a0) move.b #2,$1C(a0) bset #2,$22(a0) addq.w #5,$C(a0)
return_3164EC: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_RollJump: ; ... bset #4,$22(a0) rts
- End of function Knuckles_Jump
- =============== S U B R O U T I N E =======================================
Knuckles_JumpHeight: ; ...
tst.b $3C(a0)
beq.s Knuckles_UpwardsVelocityCap
move.w #-$400,d1
btst #6,$22(a0)
beq.s loc_31650C
move.w #-$200,d1
loc_31650C: ; ... cmp.w $12(a0),d1 ble.w Knuckles_CheckGlide ; Check if Knuckles should begin a glide move.b ($FFFFF602).w,d0 and.b #$70,d0 bne.s return_316522 move.w d1,$12(a0)
return_316522: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_UpwardsVelocityCap: ; ... tst.b $39(a0) bne.s return_316538 cmp.w #-$FC0,$12(a0) bge.s return_316538 move.w #-$FC0,$12(a0)
return_316538: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_CheckGlide: ; ... tst.w ($FFFFFFD0).w ; Don't glide on demos bne.w return_3165D2 tst.b $21(a0) bne.w return_3165D2 move.b ($FFFFF603).w,d0 and.b #$70,d0 beq.w return_3165D2 tst.b ($FFFFFE19).w bne.s Knuckles_BeginGlide cmp.b #7,($FFFFFFB1).w bcs.s Knuckles_BeginGlide cmp.w #50,($FFFFFE20).w bcs.s Knuckles_BeginGlide tst.b ($FFFFFE1E).w bne.s Knuckles_TurnSuper
Knuckles_BeginGlide: ; ... bclr #2,$22(a0) move.b #$A,$16(a0) move.b #$A,$17(a0) bclr #4,$22(a0) move.b #1,$21(a0) add.w #$200,$12(a0) bpl.s loc_31659E move.w #0,$12(a0)
loc_31659E: ; ... moveq #0,d1 move.w #$400,d0 move.w d0,$14(a0) btst #0,$22(a0) beq.s loc_3165B4 neg.w d0 moveq #-$80,d1
loc_3165B4: ; ... move.w d0,$10(a0) move.b d1,$1F(a0) move.w #0,$26(a0) move.b #0,($FFFFF7AC).w bset #1,($FFFFF7AC).w bsr.w sub_315C7C
return_3165D2: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_TurnSuper: ; ... move.b #1,($FFFFF65F).w move.b #$F,($FFFFF65E).w move.b #1,($FFFFFE19).w move.w #60,($FFFFF670).w move.b #$81,$2A(a0) move.b #$1F,$1C(a0) move.b #$7E,($FFFFD040).w move.w #$800,($FFFFF760).w move.w #$18,($FFFFF762).w move.w #$C0,($FFFFF764).w move.w #0,$32(a0) bset #1,$2B(a0) move.w #$DF,d0 jsr PlaySound move.w #$96,d0 jmp PlayMusic
- End of function Knuckles_JumpHeight
- ---------------------------------------------------------------------------
rts
- =============== S U B R O U T I N E =======================================
Knuckles_Super: ; ...
tst.b ($FFFFFE19).w
beq.w return_3166C8
tst.b ($FFFFFE1E).w
beq.s loc_31667E
subq.w #1,($FFFFF670).w
bpl.w return_3166C8
move.w #60,($FFFFF670).w
tst.w ($FFFFFE20).w
beq.s loc_31667E
or.b #1,($FFFFFE1D).w
cmp.w #1,($FFFFFE20).w
beq.s loc_316672
cmp.w #10,($FFFFFE20).w
beq.s loc_316672
cmp.w #100,($FFFFFE20).w
bne.s loc_316678
loc_316672: ; ... or.b #%10000000,($FFFFFE1D).w
loc_316678: ; ... subq.w #1,($FFFFFE20).w bne.s return_3166C8
loc_31667E: ; ... move.b #2,($FFFFF65F).w move.w #40,($FFFFF65C).w move.b #0,($FFFFFE19).w move.b #1,$1D(a0) move.w #1,$32(a0) move.w #$600,($FFFFF760).w move.w #$C,($FFFFF762).w move.w #$80,($FFFFF764).w btst #6,$22(a0) beq.s return_3166C8 move.w #$300,($FFFFF760).w move.w #6,($FFFFF762).w move.w #$40,($FFFFF764).w
return_3166C8: ; ... rts
- End of function Knuckles_Super
- =============== S U B R O U T I N E =======================================
Knuckles_Spindash: ; ...
tst.b $39(a0)
bne.s Knuckles_UpdateSpindash
cmp.b #8,$1C(a0)
bne.s return_316718
move.b ($FFFFF603).w,d0
and.b #$70,d0
beq.w return_316718
move.b #9,$1C(a0)
move.w #$E0,d0
jsr PlaySound
addq.l #4,sp
move.b #1,$39(a0)
move.w #0,$3A(a0)
cmp.b #$C,$28(a0)
bcs.s loc_316710
move.b #2,($FFFFD11C).w
loc_316710: ; ... bsr.w Knuckles_LevelBoundaries bsr.w AnglePos
return_316718: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_UpdateSpindash: ; ... move.b ($FFFFF602).w,d0 btst #1,d0 bne.w Knuckles_ChargingSpindash move.b #$E,$16(a0) move.b #7,$17(a0) move.b #2,$1C(a0) addq.w #5,$C(a0) move.b #0,$39(a0) moveq #0,d0 move.b $3A(a0),d0 add.w d0,d0 move.w Spindash_Speeds(pc,d0.w),$14(a0) tst.b ($FFFFFE19).w beq.s loc_31675C move.w Super_Spindash_Speeds(pc,d0.w),$14(a0)
loc_31675C: ; ... move.w $14(a0),d0 sub.w #$800,d0 add.w d0,d0 and.w #$1F00,d0 neg.w d0 add.w #$2000,d0 move.w d0,($FFFFEED0).w ; Lock camera for a certain number of frames btst #0,$22(a0) beq.s loc_316780 neg.w $14(a0)
loc_316780: ; ... bset #2,$22(a0) move.b #0,($FFFFD11C).w move.w #$BC,d0 jsr PlaySound bra.s Obj01_Spindash_ResetScreen
- ---------------------------------------------------------------------------
Spindash_Speeds: ; ... dc.w $800, $880, $900, $980, $A00, $A80, $B00, $B80, $C00; 0 Super_Spindash_Speeds: ; ... dc.w $B00, $B80, $C00, $C80, $D00, $D80, $E00, $E80, $F00; 0
- ---------------------------------------------------------------------------
Knuckles_ChargingSpindash: ; ... tst.w $3A(a0) beq.s loc_3167D4 move.w $3A(a0),d0 lsr.w #5,d0 sub.w d0,$3A(a0) bcc.s loc_3167D4 move.w #0,$3A(a0)
loc_3167D4: ; ... move.b ($FFFFF603).w,d0 and.b #$70,d0 beq.w Obj01_Spindash_ResetScreen move.w #$900,$1C(a0) move.w #$E0,d0 jsr PlaySound add.w #$200,$3A(a0) cmp.w #$800,$3A(a0) bcs.s Obj01_Spindash_ResetScreen move.w #$800,$3A(a0)
Obj01_Spindash_ResetScreen: ; ... addq.l #4,sp cmp.w #$60,($FFFFEED8).w beq.s loc_316818 bcc.s loc_316814 addq.w #4,($FFFFEED8).w
loc_316814: ; ... subq.w #2,($FFFFEED8).w
loc_316818: ; ... bsr.w Knuckles_LevelBoundaries bsr.w AnglePos rts
- End of function Knuckles_Spindash
- =============== S U B R O U T I N E =======================================
Knuckles_SlopeResist: ; ...
move.b $26(a0),d0
add.b #$60,d0
cmp.b #$C0,d0
bcc.s return_316856
move.b $26(a0),d0
jsr CalcSine
muls.w #$20,d0
asr.l #8,d0
tst.w $14(a0)
beq.s return_316856
bmi.s loc_316852
tst.w d0
beq.s return_316850
add.w d0,$14(a0)
return_316850: ; ... rts
- ---------------------------------------------------------------------------
loc_316852: ; ... add.w d0,$14(a0)
return_316856: ; ... rts
- End of function Knuckles_SlopeResist
- =============== S U B R O U T I N E =======================================
Knuckles_RollRepel: ; ...
move.b $26(a0),d0
add.b #$60,d0
cmp.b #$C0,d0
bcc.s return_316892
move.b $26(a0),d0
jsr CalcSine
muls.w #$50,d0
asr.l #8,d0
tst.w $14(a0)
bmi.s loc_316888
tst.w d0
bpl.s loc_316882
asr.l #2,d0
loc_316882: ; ... add.w d0,$14(a0) rts
- ---------------------------------------------------------------------------
loc_316888: ; ... tst.w d0 bmi.s loc_31688E asr.l #2,d0
loc_31688E: ; ... add.w d0,$14(a0)
return_316892: ; ... rts
- End of function Knuckles_RollRepel
- =============== S U B R O U T I N E =======================================
Knuckles_SlopeRepel: ; ...
nop
tst.b $38(a0)
bne.s return_3168CE
tst.w $2E(a0)
bne.s loc_3168D0
move.b $26(a0),d0
add.b #$20,d0
and.b #$C0,d0
beq.s return_3168CE
move.w $14(a0),d0
bpl.s loc_3168B8
neg.w d0
loc_3168B8: ; ... cmp.w #$280,d0 bcc.s return_3168CE clr.w $14(a0) bset #1,$22(a0) move.w #$1E,$2E(a0)
return_3168CE: ; ... rts
- ---------------------------------------------------------------------------
loc_3168D0: ; ... subq.w #1,$2E(a0) rts
- End of function Knuckles_SlopeRepel
- =============== S U B R O U T I N E =======================================
Knuckles_JumpAngle: ; ...
move.b $26(a0),d0
beq.s Knuckles_JumpFlip
bpl.s loc_3168E6
addq.b #2,d0
bcc.s BraTo_Knuckles_JumpAngleSet
moveq #0,d0
BraTo_Knuckles_JumpAngleSet: ; ... bra.s Knuckles_JumpAngleSet
- ---------------------------------------------------------------------------
loc_3168E6: ; ... subq.b #2,d0 bcc.s Knuckles_JumpAngleSet moveq #0,d0
Knuckles_JumpAngleSet: ; ... move.b d0,$26(a0)
Knuckles_JumpFlip: ; ... move.b $27(a0),d0 beq.s return_316934 tst.w $14(a0) bmi.s Knuckles_JumpLeftFlip
Knuckles_JumpRightFlip: ; ... move.b $2D(a0),d1 add.b d1,d0 bcc.s BraTo_Knuckles_JumpFlipSet subq.b #1,$2C(a0) bcc.s BraTo_Knuckles_JumpFlipSet move.b #0,$2C(a0) moveq #0,d0
BraTo_Knuckles_JumpFlipSet: ; ... bra.s Knuckles_JumpFlipSet
- ---------------------------------------------------------------------------
Knuckles_JumpLeftFlip: ; ... tst.b $29(a0) bne.s Knuckles_JumpRightFlip move.b $2D(a0),d1 sub.b d1,d0 bcc.s Knuckles_JumpFlipSet subq.b #1,$2C(a0) bcc.s Knuckles_JumpFlipSet move.b #0,$2C(a0) moveq #0,d0
Knuckles_JumpFlipSet: ; ... move.b d0,$27(a0)
return_316934: ; ... rts
- End of function Knuckles_JumpAngle
- =============== S U B R O U T I N E =======================================
Knuckles_DoLevelCollision2: ; ...
move.l #$FFFFD600,($FFFFF796).w
cmp.b #$C,$3E(a0)
beq.s loc_31694E
move.l #$FFFFD900,($FFFFF796).w
loc_31694E: ; ... move.b $3F(a0),d5 move.w $10(a0),d1 move.w $12(a0),d2 jsr CalcAngle sub.b #$20,d0 and.b #$C0,d0 cmp.b #$40,d0 beq.w Knuckles_HitLeftWall2 cmp.b #$80,d0 beq.w Knuckles_HitCeilingAndWalls2 cmp.b #$C0,d0 beq.w Knuckles_HitRightWall2 bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_316998 sub.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
loc_316998: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s loc_3169B0 add.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
loc_3169B0: ; ... bsr.w Player_CheckFloor tst.w d1 bpl.s return_3169CC add.w d1,$C(a0) move.b d3,$26(a0) move.w #0,$12(a0) bclr #1,($FFFFF7AC).w
return_3169CC: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitLeftWall2: ; ... bsr.w CheckLeftWallDist tst.w d1 bpl.s Knuckles_HitCeilingAlt sub.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
Knuckles_HitCeilingAlt: ; ... bsr.w CheckCeilingDist tst.w d1 bpl.s Knuckles_HitFloor neg.w d1 cmp.w #$14,d1 bcc.s loc_316A08 add.w d1,$C(a0) tst.w $12(a0) bpl.s return_316A06 move.w #0,$12(a0)
return_316A06: ; ... rts
- ---------------------------------------------------------------------------
loc_316A08: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s return_316A20 add.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
return_316A20: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitFloor: ; ... tst.w $12(a0) bmi.s return_316A44 bsr.w Player_CheckFloor tst.w d1 bpl.s return_316A44 add.w d1,$C(a0) move.b d3,$26(a0) move.w #0,$12(a0) bclr #1,($FFFFF7AC).w
return_316A44: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitCeilingAndWalls2: ; ... bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_316A5E sub.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
loc_316A5E: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s loc_316A76 add.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
loc_316A76: ; ... bsr.w CheckCeilingDist tst.w d1 bpl.s return_316A88 sub.w d1,$C(a0) move.w #0,$12(a0)
return_316A88: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitRightWall2: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s loc_316AA2 add.w d1,8(a0) move.w #0,$10(a0) bset #5,($FFFFF7AC).w
loc_316AA2: ; ... bsr.w CheckCeilingDist tst.w d1 bpl.s loc_316ABC sub.w d1,$C(a0) tst.w $12(a0) bpl.s return_316ABA move.w #0,$12(a0)
return_316ABA: ; ... rts
- ---------------------------------------------------------------------------
loc_316ABC: ; ... tst.w $12(a0) bmi.s return_316ADE bsr.w Player_CheckFloor tst.w d1 bpl.s return_316ADE add.w d1,$C(a0) move.b d3,$26(a0) move.w #0,$12(a0) bclr #1,($FFFFF7AC).w
return_316ADE: ; ... rts
- End of function Knuckles_DoLevelCollision2
- =============== S U B R O U T I N E =======================================
Knuckles_DoLevelCollision: ; ...
move.l #$FFFFD600,($FFFFF796).w
cmp.b #$C,$3E(a0)
beq.s loc_316AF8
move.l #$FFFFD900,($FFFFF796).w
loc_316AF8: ; ... move.b $3F(a0),d5 move.w $10(a0),d1 move.w $12(a0),d2 jsr CalcAngle sub.b #$20,d0 and.b #$C0,d0 cmp.b #$40,d0 beq.w Knuckles_HitLeftWall cmp.b #$80,d0 beq.w Knuckles_HitCeilingAndWalls cmp.b #$C0,d0 beq.w Knuckles_HitRightWall bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_316B3C sub.w d1,8(a0) move.w #0,$10(a0)
loc_316B3C: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s loc_316B4E add.w d1,8(a0) move.w #0,$10(a0)
loc_316B4E: ; ... bsr.w Player_CheckFloor tst.w d1 bpl.s return_316BC0 move.b $12(a0),d2 addq.b #8,d2 neg.b d2 cmp.b d2,d1 bge.s loc_316B66 cmp.b d2,d0 blt.s return_316BC0
loc_316B66: ; ... add.w d1,$C(a0) move.b d3,$26(a0) bsr.w Knuckles_ResetOnFloor move.b d3,d0 add.b #$20,d0 and.b #$40,d0 bne.s loc_316B9E move.b d3,d0 add.b #$10,d0 and.b #$20,d0 beq.s loc_316B90 asr $12(a0) bra.s loc_316BB2
- ---------------------------------------------------------------------------
loc_316B90: ; ... move.w #0,$12(a0) move.w $10(a0),$14(a0) rts
- ---------------------------------------------------------------------------
loc_316B9E: ; ... move.w #0,$10(a0) cmp.w #$FC0,$12(a0) ble.s loc_316BB2 move.w #$FC0,$12(a0)
loc_316BB2: ; ... move.w $12(a0),$14(a0) tst.b d3 bpl.s return_316BC0 neg.w $14(a0)
return_316BC0: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitLeftWall: ; ... bsr.w CheckLeftWallDist tst.w d1 bpl.s Knuckles_HitCeiling sub.w d1,8(a0) move.w #0,$10(a0) move.w $12(a0),$14(a0) rts
- ---------------------------------------------------------------------------
Knuckles_HitCeiling: ; ... bsr.w CheckCeilingDist tst.w d1 bpl.s Knuckles_HitFloor_0 sub.w d1,$C(a0) tst.w $12(a0) bpl.s return_316BF4 move.w #0,$12(a0)
return_316BF4: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitFloor_0: ; ... tst.w $12(a0) bmi.s return_316C1C bsr.w Player_CheckFloor tst.w d1 bpl.s return_316C1C add.w d1,$C(a0) move.b d3,$26(a0) bsr.w Knuckles_ResetOnFloor move.w #0,$12(a0) move.w $10(a0),$14(a0)
return_316C1C: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitCeilingAndWalls: ; ... bsr.w CheckLeftWallDist tst.w d1 bpl.s loc_316C30 sub.w d1,8(a0) move.w #0,$10(a0)
loc_316C30: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s loc_316C42 add.w d1,8(a0) move.w #0,$10(a0)
loc_316C42: ; ... bsr.w CheckCeilingDist tst.w d1 bpl.s return_316C78 sub.w d1,$C(a0) move.b d3,d0 add.b #$20,d0 and.b #$40,d0 bne.s loc_316C62 move.w #0,$12(a0) rts
- ---------------------------------------------------------------------------
loc_316C62: ; ... move.b d3,$26(a0) bsr.w Knuckles_ResetOnFloor move.w $12(a0),$14(a0) tst.b d3 bpl.s return_316C78 neg.w $14(a0)
return_316C78: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitRightWall: ; ... bsr.w CheckRightWallDist tst.w d1 bpl.s Knuckles_HitCeiling2 add.w d1,8(a0) move.w #0,$10(a0) move.w $12(a0),$14(a0) rts
- ---------------------------------------------------------------------------
Knuckles_HitCeiling2: ; ... bsr.w CheckCeilingDist tst.w d1 bpl.s Knuckles_HitFloor2 sub.w d1,$C(a0) tst.w $12(a0) bpl.s return_316CAC move.w #0,$12(a0)
return_316CAC: ; ... rts
- ---------------------------------------------------------------------------
Knuckles_HitFloor2: ; ... tst.w $12(a0) bmi.s return_316CD4 bsr.w Player_CheckFloor tst.w d1 bpl.s return_316CD4 add.w d1,$C(a0) move.b d3,$26(a0) bsr.w Knuckles_ResetOnFloor move.w #0,$12(a0) move.w $10(a0),$14(a0)
return_316CD4: ; ... rts
- End of function Knuckles_DoLevelCollision
- =============== S U B R O U T I N E =======================================
Knuckles_ResetOnFloor: ; ...
tst.b $39(a0)
bne.s Knuckles_ResetOnFloor_Part3
move.b #0,$1C(a0)
- End of function Knuckles_ResetOnFloor
- =============== S U B R O U T I N E =======================================
Knuckles_ResetOnFloor_Part2: ; ...
move.b $16(a0),d0
move.b #$13,$16(a0)
move.b #9,$17(a0)
btst #2,$22(a0)
beq.s Knuckles_ResetOnFloor_Part3
bclr #2,$22(a0)
move.b #0,$1C(a0)
sub.b #$13,d0
ext.w d0
add.w d0,$C(a0)
Knuckles_ResetOnFloor_Part3: ; ... bclr #1,$22(a0) bclr #5,$22(a0) bclr #4,$22(a0) move.b #0,$3C(a0) move.w #0,($FFFFF7D0).w move.b #0,$27(a0) move.b #0,$29(a0) move.b #0,$2C(a0) move.w #0,($FFFFF66C).w move.b #0,$21(a0) cmp.b #$20,$1C(a0) bcc.s loc_316D5C cmp.b #$14,$1C(a0) bne.s return_316D62
loc_316D5C: ; ... move.b #0,$1C(a0)
return_316D62: ; ... rts
- End of function Knuckles_ResetOnFloor_Part2
- =============== S U B R O U T I N E =======================================
Obj01_Hurt: ; ...
- FUNCTION CHUNK AT 00316E14 SIZE 0000001C BYTES
tst.w ($FFFFFFDA).w beq.s Obj01_Hurt_Normal btst #4,($FFFFF605).w beq.s Obj01_Hurt_Normal move.w #1,($FFFFFE08).w clr.b ($FFFFF7CC).w rts
- ---------------------------------------------------------------------------
Obj01_Hurt_Normal: ; ... tst.b $25(a0) bmi.w Knuckles_HurtInstantRecover jsr ObjectMove ; AKA SpeedToPos in Sonic 1 add.w #$30,$12(a0) btst #6,$22(a0) beq.s loc_316DA0 sub.w #$20,$12(a0)
loc_316DA0: ; ... cmp.w #$FF00,($FFFFEECC).w bne.s loc_316DAE and.w #$7FF,$C(a0)
loc_316DAE: ; ... bsr.w Knuckles_HurtStop bsr.w Knuckles_LevelBoundaries bsr.w Knuckles_RecordPositions bsr.w Knuckles_Animate bsr.w LoadKnucklesDynPLC jmp DisplaySprite
- End of function Obj01_Hurt
- =============== S U B R O U T I N E =======================================
Knuckles_HurtStop: ; ...
move.w ($FFFFEECE).w,d0
add.w #$E0,d0
cmp.w $C(a0),d0
blt.w JmpTo_KillCharacter
bsr.w Knuckles_DoLevelCollision
btst #1,$22(a0)
bne.s return_316E0C
moveq #0,d0
move.w d0,$12(a0)
move.w d0,$10(a0)
move.w d0,$14(a0)
move.b d0,$2A(a0)
move.b #0,$1C(a0)
subq.b #2,$24(a0)
move.w #$78,$30(a0)
move.b #0,$39(a0)
return_316E0C: ; ... rts
- ---------------------------------------------------------------------------
JmpTo_KillCharacter: ; ... jmp KillCharacter
- End of function Knuckles_HurtStop
- ---------------------------------------------------------------------------
- START OF FUNCTION CHUNK FOR Obj01_Hurt
Knuckles_HurtInstantRecover: ; ... subq.b #2,$24(a0) move.b #0,$25(a0) bsr.w Knuckles_RecordPositions bsr.w Knuckles_Animate bsr.w LoadKnucklesDynPLC jmp DisplaySprite
- END OF FUNCTION CHUNK FOR Obj01_Hurt
- =============== S U B R O U T I N E =======================================
Obj01_Dead: ; ...
tst.w ($FFFFFFDA).w
beq.s loc_316E4A
btst #4,($FFFFF605).w
beq.s loc_316E4A
move.w #1,($FFFFFE08).w
clr.b ($FFFFF7CC).w
rts
- ---------------------------------------------------------------------------
loc_316E4A: ; ... bsr.w CheckGameOver jsr ObjectMoveAndFall bsr.w Knuckles_RecordPositions bsr.w Knuckles_Animate bsr.w LoadKnucklesDynPLC jmp DisplaySprite
- End of function Obj01_Dead
- =============== S U B R O U T I N E =======================================
CheckGameOver: ; ...
move.b #1,($FFFFEEBE).w
move.b #0,$39(a0)
move.w ($FFFFEECE).w,d0
add.w #$100,d0
cmp.w $C(a0),d0
bge.w return_316F64
move.b #8,$24(a0)
move.w #$3C,$3A(a0)
addq.b #1,($FFFFFE1C).w
subq.b #1,($FFFFFE12).w
bne.s Obj01_ResetLevel
move.w #0,$3A(a0)
move.b #$39,($FFFFB080).w
move.b #$39,($FFFFB0C0).w
move.b #1,($FFFFB0DA).w
move.w a0,($FFFFB0BE).w
clr.b ($FFFFFE1A).w
Obj01_Finished: ; ... clr.b ($FFFFFE1E).w clr.b ($FFFFFECA).w move.b #8,$24(a0) move.w #$9B,d0 jsr PlayMusic moveq #3,d0 jmp LoadPLC
- ---------------------------------------------------------------------------
Obj01_ResetLevel: ; ... tst.b ($FFFFFE1A).w beq.s Obj01_ResetLevel_Part2 move.w #0,$3A(a0) move.b #$39,($FFFFB080).w move.b #$39,($FFFFB0C0).w move.b #2,($FFFFB09A).w move.b #3,($FFFFB0DA).w move.w a0,($FFFFB0BE).w bra.s Obj01_Finished
- ---------------------------------------------------------------------------
Obj01_ResetLevel_Part2: ; ... tst.w ($FFFFFFDC).w beq.s return_316F64 move.b #0,($FFFFEEBE).w move.b #$A,$24(a0) move.w ($FFFFFE32).w,8(a0) move.w ($FFFFFE34).w,$C(a0) move.w ($FFFFFE3C).w,2(a0) move.w ($FFFFFE3E).w,$3E(a0) clr.w ($FFFFFE20).w clr.b ($FFFFFE1B).w move.b #0,$2A(a0) move.b #5,$1C(a0) move.w #0,$10(a0) move.w #0,$12(a0) move.w #0,$14(a0) move.b #2,$22(a0) move.w #0,$2E(a0) move.w #0,$3A(a0)
return_316F64: ; ... rts
- End of function CheckGameOver
- =============== S U B R O U T I N E =======================================
Obj01_Gone: ; ...
tst.w $3A(a0)
beq.s return_316F78
subq.w #1,$3A(a0)
bne.s return_316F78
move.w #1,($FFFFFE02).w
return_316F78: ; ... rts
- End of function Obj01_Gone
- ---------------------------------------------------------------------------
Obj01_Respawning: ; ... tst.w ($FFFFEEB0).w bne.s loc_316F8C tst.w ($FFFFEEB2).w bne.s loc_316F8C move.b #2,$24(a0)
loc_316F8C: ; ... bsr.w Knuckles_Animate bsr.w LoadKnucklesDynPLC jmp DisplaySprite
- =============== S U B R O U T I N E =======================================
Knuckles_Animate: ; ...
lea (KnucklesAniData).l,a1
moveq #0,d0
move.b $1C(a0),d0
cmp.b $1D(a0),d0
beq.s KAnim_Do
move.b d0,$1D(a0)
move.b #0,$1B(a0)
move.b #0,$1E(a0)
bclr #5,$22(a0)
KAnim_Do: ; ... add.w d0,d0 add.w (a1,d0.w),a1 move.b (a1),d0 bmi.s KAnim_WalkRun move.b $22(a0),d1 and.b #1,d1 and.b #$FC,1(a0) or.b d1,1(a0) subq.b #1,$1E(a0) bpl.s KAnim_Delay move.b d0,$1E(a0)
KAnim_Do2: ; ... moveq #0,d1 move.b $1B(a0),d1 move.b 1(a1,d1.w),d0 cmp.b #$FC,d0 bcc.s KAnim_End_FF
KAnim_Next: ; ... move.b d0,$1A(a0) addq.b #1,$1B(a0)
KAnim_Delay: ; ... rts
- ---------------------------------------------------------------------------
KAnim_End_FF: ; ... addq.b #1,d0 bne.s KAnim_End_FE move.b #0,$1B(a0) move.b 1(a1),d0 bra.s KAnim_Next
- ---------------------------------------------------------------------------
KAnim_End_FE: ; ... addq.b #1,d0 bne.s KAnim_End_FD move.b 2(a1,d1.w),d0 sub.b d0,$1B(a0) sub.b d0,d1 move.b 1(a1,d1.w),d0 bra.s KAnim_Next
- ---------------------------------------------------------------------------
KAnim_End_FD: ; ... addq.b #1,d0 bne.s KAnim_End move.b 2(a1,d1.w),$1C(a0)
KAnim_End: ; ... rts
- ---------------------------------------------------------------------------
KAnim_WalkRun: ; ... addq.b #1,d0 bne.w KAnim_Roll moveq #0,d0 move.b $27(a0),d0 bne.w KAnim_Tumble moveq #0,d1 move.b $26(a0),d0 bmi.s loc_31704E beq.s loc_31704E subq.b #1,d0
loc_31704E: ; ... move.b $22(a0),d2 and.b #1,d2 bne.s loc_31705A not.b d0
loc_31705A: ; ... add.b #$10,d0 bpl.s loc_317062 moveq #3,d1
loc_317062: ; ... and.b #$FC,1(a0) eor.b d1,d2 or.b d2,1(a0) btst #5,$22(a0) bne.w KAnim_Push lsr.b #4,d0 and.b #6,d0 move.w $14(a0),d2 bpl.s loc_317086 neg.w d2
loc_317086: ; ... tst.b $2B(a0) bpl.w loc_317090 add.w d2,d2
loc_317090: ; ... lea (KnucklesAni_Run).l,a1 cmp.w #$600,d2 bcc.s loc_3170A4 lea (KnucklesAni_Walk).l,a1 add.b d0,d0
loc_3170A4: ; ... add.b d0,d0 move.b d0,d3 moveq #0,d1 move.b $1B(a0),d1 move.b 1(a1,d1.w),d0 cmp.b #$FF,d0 bne.s loc_3170C2 move.b #0,$1B(a0) move.b 1(a1),d0
loc_3170C2: ; ... move.b d0,$1A(a0) add.b d3,$1A(a0) subq.b #1,$1E(a0) bpl.s return_3170E4 neg.w d2 add.w #$800,d2 bpl.s loc_3170DA moveq #0,d2
loc_3170DA: ; ... lsr.w #8,d2 move.b d2,$1E(a0) addq.b #1,$1B(a0)
return_3170E4: ; ... rts
- ---------------------------------------------------------------------------
KAnim_Tumble: ; ... move.b $27(a0),d0 moveq #0,d1 move.b $22(a0),d2 and.b #1,d2 bne.s KAnim_Tumble_Left and.b #$FC,1(a0) add.b #$B,d0 divu.w #$16,d0 add.b #$31,d0 move.b d0,$1A(a0) move.b #0,$1E(a0) rts
- ---------------------------------------------------------------------------
KAnim_Tumble_Left: ; ... and.b #$FC,1(a0) tst.b $29(a0) beq.s loc_31712C or.b #1,1(a0) add.b #$B,d0 bra.s loc_317138
- ---------------------------------------------------------------------------
loc_31712C: ; ... or.b #3,1(a0) neg.b d0 add.b #-$71,d0
loc_317138: ; ... divu.w #$16,d0 add.b #$31,d0 move.b d0,$1A(a0) move.b #0,$1E(a0) rts
- ---------------------------------------------------------------------------
KAnim_Roll: ; ... subq.b #1,$1E(a0) bpl.w KAnim_Delay addq.b #1,d0 bne.s KAnim_Push move.w $14(a0),d2 bpl.s loc_317160 neg.w d2
loc_317160: ; ... lea (KnucklesAni_Roll2).l,a1 cmp.w #$600,d2 bcc.s loc_317172 lea (KnucklesAni_Roll).l,a1
loc_317172: ; ... neg.w d2 add.w #$400,d2 bpl.s loc_31717C moveq #0,d2
loc_31717C: ; ... lsr.w #8,d2 move.b d2,$1E(a0) move.b $22(a0),d1 and.b #1,d1 and.b #$FC,1(a0) or.b d1,1(a0) bra.w KAnim_Do2
- ---------------------------------------------------------------------------
KAnim_Push: ; ... subq.b #1,$1E(a0) bpl.w KAnim_Delay move.w $14(a0),d2 bmi.s loc_3171A8 neg.w d2
loc_3171A8: ; ... add.w #$800,d2 bpl.s loc_3171B0 moveq #0,d2
loc_3171B0: ; ... lsr.w #8,d2 move.b d2,$1E(a0) lea (KnucklesAni_Push).l,a1 move.b $22(a0),d1 and.b #1,d1 and.b #$FC,1(a0) or.b d1,1(a0) bra.w KAnim_Do2
- End of function Knuckles_Animate
- ---------------------------------------------------------------------------
KnucklesAniData:dc.w KnucklesAni_Walk-KnucklesAniData; 0 ; ... dc.w KnucklesAni_Run-KnucklesAniData; 1 dc.w KnucklesAni_Roll-KnucklesAniData; 2 dc.w KnucklesAni_Roll2-KnucklesAniData; 3 dc.w KnucklesAni_Push-KnucklesAniData; 4 dc.w KnucklesAni_Wait-KnucklesAniData; 5 dc.w KnucklesAni_Balance-KnucklesAniData; 6 dc.w KnucklesAni_LookUp-KnucklesAniData; 7 dc.w KnucklesAni_Duck-KnucklesAniData; 8 dc.w KnucklesAni_Spindash-KnucklesAniData; 9 dc.w KnucklesAni_Unused-KnucklesAniData; 10 dc.w KnucklesAni_Pull-KnucklesAniData; 11 dc.w KnucklesAni_Balance2-KnucklesAniData; 12 dc.w KnucklesAni_Stop-KnucklesAniData; 13 dc.w KnucklesAni_Float-KnucklesAniData; 14 dc.w KnucklesAni_Float2-KnucklesAniData; 15 dc.w KnucklesAni_Spring-KnucklesAniData; 16 dc.w KnucklesAni_Hang-KnucklesAniData; 17 dc.w KnucklesAni_Unused_0-KnucklesAniData; 18 dc.w KnucklesAni_S3EndingPose-KnucklesAniData; 19 dc.w KnucklesAni_WFZHang-KnucklesAniData; 20 dc.w KnucklesAni_Bubble-KnucklesAniData; 21 dc.w KnucklesAni_DeathBW-KnucklesAniData; 22 dc.w KnucklesAni_Drown-KnucklesAniData; 23 dc.w KnucklesAni_Death-KnucklesAniData; 24 dc.w KnucklesAni_OilSlide-KnucklesAniData; 25 dc.w KnucklesAni_Hurt-KnucklesAniData; 26 dc.w KnucklesAni_OilSlide_0-KnucklesAniData; 27 dc.w KnucklesAni_Blank-KnucklesAniData; 28 dc.w KnucklesAni_Unused_1-KnucklesAniData; 29 dc.w KnucklesAni_Unused_2-KnucklesAniData; 30 dc.w KnucklesAni_Transform-KnucklesAniData; 31 dc.w KnucklesAni_Gliding-KnucklesAniData; 32 dc.w KnucklesAni_FallFromGlide-KnucklesAniData; 33 dc.w KnucklesAni_GetUp-KnucklesAniData; 34 dc.w KnucklesAni_HardFall-KnucklesAniData; 35 dc.w KnucklesAni_Badass-KnucklesAniData; 36 KnucklesAni_Walk:dc.b $FF, 7, 8, 1, 2, 3, 4, 5, 6,$FF; 0 ; ... KnucklesAni_Run:dc.b $FF,$21,$22,$23,$24,$FF,$FF,$FF,$FF,$FF; 0 ; ... KnucklesAni_Roll:dc.b $FE,$9A,$96,$9A,$97,$9A,$98,$9A,$99,$FF; 0 ; ... KnucklesAni_Roll2:dc.b $FE,$9A,$96,$9A,$97,$9A,$98,$9A,$99,$FF; 0 ; ... KnucklesAni_Push:dc.b $FD,$CE,$CF,$D0,$D1,$FF,$FF,$FF,$FF,$FF; 0 ; ... KnucklesAni_Wait:dc.b 5,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56; 0 ; ... dc.b $56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56; 13 dc.b $56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56; 26 dc.b $56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$56,$D2; 39 dc.b $D2,$D2,$D3,$D3,$D3,$D2,$D2,$D2,$D3,$D3,$D3,$D2,$D2; 52 dc.b $D2,$D3,$D3,$D3,$D2,$D2,$D2,$D3,$D3,$D3,$D2,$D2,$D2; 65 dc.b $D3,$D3,$D3,$D2,$D2,$D2,$D3,$D3,$D3,$D2,$D2,$D2,$D3; 78 dc.b $D3,$D3,$D2,$D2,$D2,$D3,$D3,$D3,$D2,$D2,$D2,$D3,$D3; 91 dc.b $D3,$D4,$D4,$D4,$D4,$D4,$D7,$D8,$D9,$DA,$DB,$D8,$D9; 104 dc.b $DA,$DB,$D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB,$D8,$D9,$DA; 117 dc.b $DB,$D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB; 130 dc.b $DC,$DD,$DC,$DD,$DE,$DE,$D8,$D7,$FF; 143 KnucklesAni_Balance:dc.b 3,$9F,$9F,$A0,$A0,$A1,$A1,$A2,$A2,$A3,$A3,$A4,$A4; 0 ; ... dc.b $A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5; 13 dc.b $A5,$A5,$A6,$A6,$A6,$A7,$A7,$A7,$A8,$A8,$A9,$A9,$AA; 26 dc.b $AA,$FE, 6 ; 39 KnucklesAni_LookUp:dc.b 5,$D5,$D6,$FE, 1 ; 0 ; ... KnucklesAni_Duck:dc.b 5,$9B,$9C,$FE, 1 ; 0 ; ... KnucklesAni_Spindash:dc.b 0,$86,$87,$86,$88,$86,$89,$86,$8A,$86,$8B,$FF; 0 ; ... KnucklesAni_Unused:dc.b 9,$BA,$C5,$C6,$C6,$C6,$C6,$C6,$C6,$C7,$C7,$C7,$C7; 0 ; ... dc.b $C7,$C7,$C7,$C7,$C7,$C7,$C7,$C7,$FD, 0; 13 KnucklesAni_Pull:dc.b $F,$8F,$FF ; 0 ; ... KnucklesAni_Balance2:dc.b 3,$A1,$A1,$A2,$A2,$A3,$A3,$A4,$A4,$A5,$A5,$A5,$A5; 0 ; ... dc.b $A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$A6,$A6; 13 dc.b $A6,$A7,$A7,$A7,$A8,$A8,$A9,$A9,$AA,$AA,$FE; 26 dc.b 6 KnucklesAni_Stop:dc.b 3,$9D,$9E,$9F,$A0,$FD, 0 ; 0 ; ... KnucklesAni_Float:dc.b 7,$C0,$FF ; 0 ; ... KnucklesAni_Float2:dc.b 5,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$FF; 0 ; ... KnucklesAni_Spring:dc.b $2F,$8E,$FD, 0 ; 0 ; ... KnucklesAni_Hang:dc.b 1,$AE,$AF,$FF ; 0 ; ... KnucklesAni_Unused_0:dc.b $F,$43,$43,$43,$FE, 1 ; 0 ; ... KnucklesAni_S3EndingPose:dc.b 5,$B1,$B2,$B2,$B2,$B3,$B4,$FE, 1, 7,$B1,$B3,$B3; 0 ; ... dc.b $B3,$B3,$B3,$B3,$B2,$B3,$B4,$B3,$FE, 4; 13 KnucklesAni_WFZHang:dc.b $13,$91,$FF ; 0 ; ... KnucklesAni_Bubble:dc.b $B,$B0,$B0, 3, 4,$FD, 0 ; 0 ; ... KnucklesAni_DeathBW:dc.b $20,$AC,$FF ; 0 ; ... KnucklesAni_Drown:dc.b $20,$AD,$FF ; 0 ; ... KnucklesAni_Death:dc.b $20,$AB,$FF ; 0 ; ... KnucklesAni_OilSlide:dc.b 9,$8C,$FF ; 0 ; ... KnucklesAni_Hurt:dc.b $40,$8D,$FF ; 0 ; ... KnucklesAni_OilSlide_0:dc.b 9,$8C,$FF ; 0 ; ... KnucklesAni_Blank:dc.b $77, 0,$FF ; 0 ; ... KnucklesAni_Unused_1:dc.b $13,$D0,$D1,$FF ; 0 ; ... KnucklesAni_Unused_2:dc.b 3,$CF,$C8,$C9,$CA,$CB,$FE ; 0 ; ... dc.b 4 KnucklesAni_Gliding:dc.b $1F,$C0,$FF ; 0 ; ... KnucklesAni_FallFromGlide:dc.b 7,$CA,$CB,$FE, 1 ; 0 ; ... KnucklesAni_GetUp:dc.b $F,$CD,$FD, 0 ; 0 ; ... KnucklesAni_HardFall:dc.b $F,$9C,$FD, 0 ; 0 ; ... KnucklesAni_Badass:dc.b 5,$D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB; 0 ; ... dc.b $D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB,$D8,$D9,$DA,$DB,$D8; 13 dc.b $D9,$DA,$DB,$D8,$D9,$DA,$DB,$DC,$DD,$DC,$DD,$DE,$DE; 26 dc.b $FF ; 39 KnucklesAni_Transform:dc.b 2,$EB,$EB,$EC,$ED,$EC,$ED,$EC,$ED,$EC,$ED,$EC,$ED; 0 ; ... dc.b $FD, 0, 0 ; 13
- =============== S U B R O U T I N E =======================================
LoadKnucklesDynPLC: ; ...
moveq #0,d0
move.b $1A(a0),d0
- End of function LoadKnucklesDynPLC
- START OF FUNCTION CHUNK FOR sub_333D66
LoadKnucklesDynPLC_Part2: ; ... cmp.b ($FFFFF766).w,d0 beq.w return_31753E move.b d0,($FFFFF766).w lea (SK_PLC_Knuckles).l,a2 ; SK_PLC_Knuckles add.w d0,d0 add.w (a2,d0.w),a2 move.w (a2)+,d5 subq.w #1,d5 bmi.w return_31753E moveq #0,d3 lea ($FFFFF100).w,a3 ; RAM address where the converted art will be stored lea ArtConvTable(pc),a4 ; Load art-conversion table
KPLC_ReadEntry: ; ... moveq #0,d0 moveq #0,d1 move.w (a2)+,d1 move.w d1,d4 rol.w #4,d4 and.w #$F,d4 addq.w #1,d3 add.w d4,d3 and.w #$FFF,d1 lsl.l #5,d1 lea (SK_ArtUnc_Knux).l,a1 ; SK_ArtUnc_Knux add.l d1,a1
KPLC_ConvertArtFromS3K: ; ... move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ move.b (a1)+,d0 move.b (a4,d0.w),(a3)+ ; Repeated $20 times dbf d4,KPLC_ConvertArtFromS3K dbf d5,KPLC_ReadEntry move.l #$FFF100,d1 ; RAM address where the converted art was stored move.w #$F000,d2 ; VRAM address for Knuckles' art lsl.w #4,d3 jmp QueueDMATransfer
- ---------------------------------------------------------------------------
return_31753E: ; ... rts
- END OF FUNCTION CHUNK FOR sub_333D66
- ---------------------------------------------------------------------------
- This table converts art using palette indexes set for S&K to palette indexes set for S2.
- Format
- The rightmost nybble of entry X in any row = the new index that replaces color X.
- Similarly, the leftmost nybble of entry X in any column = the new index that replaces color X.
- Specific replacements
- $0 -> $0
- $1 -> $6
- $2 -> $5
- $3 -> $3
- $4 -> $2
- $5 -> $4
- $6 -> $C
- $7 -> $D
- $8 -> $E
- $9 -> $F
- $A -> $A
- $B -> $B
- $C -> $7
- $D -> $8
- $E -> $9
- $F -> $1
- ---------------------------------------------------------------------------
ArtConvTable: dc.b $00,$06,$05,$03,$02,$04,$0C,$0D,$0E,$0F,$0A,$0B,$07,$08,$09,$01; 0 ; ... dc.b $60,$66,$65,$63,$62,$64,$6C,$6D,$6E,$6F,$6A,$6B,$67,$68,$69,$61; 16 dc.b $50,$56,$55,$53,$52,$54,$5C,$5D,$5E,$5F,$5A,$5B,$57,$58,$59,$51; 32 dc.b $30,$36,$35,$33,$32,$34,$3C,$3D,$3E,$3F,$3A,$3B,$37,$38,$39,$31; 48 dc.b $20,$26,$25,$23,$22,$24,$2C,$2D,$2E,$2F,$2A,$2B,$27,$28,$29,$21; 64 dc.b $40,$46,$45,$43,$42,$44,$4C,$4D,$4E,$4F,$4A,$4B,$47,$48,$49,$41; 80 dc.b $C0,$C6,$C5,$C3,$C2,$C4,$CC,$CD,$CE,$CF,$CA,$CB,$C7,$C8,$C9,$C1; 96 dc.b $D0,$D6,$D5,$D3,$D2,$D4,$DC,$DD,$DE,$DF,$DA,$DB,$D7,$D8,$D9,$D1; 112 dc.b $E0,$E6,$E5,$E3,$E2,$E4,$EC,$ED,$EE,$EF,$EA,$EB,$E7,$E8,$E9,$E1; 128 dc.b $F0,$F6,$F5,$F3,$F2,$F4,$FC,$FD,$FE,$FF,$FA,$FB,$F7,$F8,$F9,$F1; 144 dc.b $A0,$A6,$A5,$A3,$A2,$A4,$AC,$AD,$AE,$AF,$AA,$AB,$A7,$A8,$A9,$A1; 160 dc.b $B0,$B6,$B5,$B3,$B2,$B4,$BC,$BD,$BE,$BF,$BA,$BB,$B7,$B8,$B9,$B1; 176 dc.b $70,$76,$75,$73,$72,$74,$7C,$7D,$7E,$7F,$7A,$7B,$77,$78,$79,$71; 192 dc.b $80,$86,$85,$83,$82,$84,$8C,$8D,$8E,$8F,$8A,$8B,$87,$88,$89,$81; 208 dc.b $90,$96,$95,$93,$92,$94,$9C,$9D,$9E,$9F,$9A,$9B,$97,$98,$99,$91; 224 dc.b $10,$16,$15,$13,$12,$14,$1C,$1D,$1E,$1F,$1A,$1B,$17,$18,$19,$11; 240
- ---------------------------------------------------------------------------
</asm> Change all "Obj01"s to "Obj4C"s.
And we're done!
Finally, we can stop worrying about Knuckles' code and get on with our lives. :D
Additional Steps
Additional Step #1: Making Obj4C's ObjPtr
Just when you thought you were done with this, you found out that I found out this! Getting tired? Well, this step should begin to solve your problems! Go to s2.constants.asm and find these two lines: <asm> ObjID_Buzzer = id(ObjPtr_Buzzer) ; 4B ObjID_Aquis = id(ObjPtr_Aquis) ; 50 </asm> Uh oh, it seems an observant eye may catch the fact that the index goes from 4B straight to 50. skipping the first four null object values. We're going to add one to change that number to three. Between the two previously mentioned lines, add this: <asm> ObjID_Knuckles = id(ObjPtr_Knuckles) ; 4C </asm> And there you go! However, there is still much more to do.
Additional Step #2: Upgrading some branch commands
Now look at the s2.log file (the one with all the errors) and you should see this: <asm> > > >s2.asm(57477): error: jump distance too big > > > bsr.w ResumeMusic ; <-- > > >s2.asm(57504): error: jump distance too big > > > bsr.w ResumeMusic ; <-- > > >s2.asm(57524): error: jump distance too big > > > bsr.w ResumeMusic ; <-- > > >s2.asm(57546): error: jump distance too big > > > bsr.w AnglePos ; <-- > > >s2.asm(57671): error: jump distance too big > > > bsr.w CheckLeftCeilingDist ; <-- > > >s2.asm(57680): error: jump distance too big > > > bsr.w CheckRightCeilingDist ; <-- > > >s2.asm(58216): error: jump distance too big > > > bsr.w AnglePos ; <-- > > >s2.asm(58447): error: jump distance too big > > > bsr.w CalcRoomInFront ; <-- ; Also known as Sonic_WalkSpeed in Sonic 1 > > >s2.asm(58935): error: jump distance too big > > > bsr.w CalcRoomOverHead ; <-- > > >s2.asm(59163): error: jump distance too big > > > bsr.w AnglePos ; <-- > > >s2.asm(59244): error: jump distance too big > > > bsr.w AnglePos > > >s2.asm(59433): error: jump distance too big > > > bsr.w CheckLeftWallDist ; <-- > > >s2.asm(59441): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59462): error: jump distance too big > > > bsr.w CheckLeftWallDist ; <-- > > >s2.asm(59470): error: jump distance too big > > > bsr.w CheckCeilingDist ; <-- > > >s2.asm(59486): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59513): error: jump distance too big > > > bsr.w CheckLeftWallDist ; <-- > > >s2.asm(59521): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59529): error: jump distance too big > > > bsr.w CheckCeilingDist ; <-- > > >s2.asm(59540): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59548): error: jump distance too big > > > bsr.w CheckCeilingDist ; <-- > > >s2.asm(59598): error: jump distance too big > > > bsr.w CheckLeftWallDist ; <-- > > >s2.asm(59605): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59662): error: jump distance too big > > > bsr.w CheckLeftWallDist ; <-- > > >s2.asm(59672): error: jump distance too big > > > bsr.w CheckCeilingDist ; <-- > > >s2.asm(59701): error: jump distance too big > > > bsr.w CheckLeftWallDist ; <-- > > >s2.asm(59708): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59715): error: jump distance too big > > > bsr.w CheckCeilingDist ; <-- > > >s2.asm(59740): error: jump distance too big > > > bsr.w CheckRightWallDist ; <-- > > >s2.asm(59750): error: jump distance too big > > > bsr.w CheckCeilingDist ; <-- > > >s2.asm(59875): error: jump distance too big > > > blt.w JmpTo_KillCharacter > > >s2.asm(59893): error: symbol double defined > > > JMPTO_KILLCHARACTER > > > JmpTo_KillCharacter: ; ... > > >s2.asm(59923): error: jump distance too big > > > bsr.w CheckGameOver > > >s2.asm(59935): error: symbol double defined > > > CHECKGAMEOVER > > > CheckGameOver: </asm> At every indicated line, change 'bsr.w' to 'jsr'. Here's an example: <asm>
bsr.w CalcRoomInFront ; Also known as Sonic_WalkSpeed in Sonic 1
</asm> Change it to this: <asm>
jsr CalcRoomInFront ; Also known as Sonic_WalkSpeed in Sonic 1
</asm> Now go get 'em, tiger. However, there are also 2 label-command pairs in need of renaming. Both of 'em are at the end of this list. Change this: <asm>
bsr.w CheckGameOver
</asm> Add "Knux" (no quotes) to it so it looks like this: <asm>
bsr.w CheckGameOverKnux
</asm> Do the same thing with the other command, as well as their respective labels. You must be getting tired of this, and trust me, we're almost done, but now there's another set of errors to fix.
Additional Step #3: Repairing a few branches
The second error list should look like this: <asm> > > >s2.asm(57287): error: symbol undefined > > > SK_Map_Knuckles > > > move.l #SK_Map_Knuckles,4(a0) ; SK_Map_Knuckles > > >s2.asm(57297): error: symbol undefined > > > Adjust2PArtPointer2_Useless > > > bsr.w Adjust2PArtPointer2_Useless > > >s2.asm(57814): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(57867): error: symbol undefined > > > sub_3192E6 > > > bsr.w sub_3192E6 ; Doesn't exist in S2 > > >s2.asm(57915): error: symbol undefined > > > sub_318FF6 > > > bsr.w sub_318FF6 > > >s2.asm(58046): error: symbol undefined > > > loc_319208 > > > bra.w loc_319208 > > >s2.asm(58052): error: symbol undefined > > > loc_3193D2 > > > bra.w loc_3193D2 > > >s2.asm(59449): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(59500): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(59563): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(59612): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(59687): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(59765): error: symbol undefined > > > Player_CheckFloor > > > bsr.w Player_CheckFloor > > >s2.asm(60380): error: symbol undefined > > > SK_PLC_Knuckles > > > lea (SK_PLC_Knuckles).l,a2 ; SK_PLC_Knuckles > > >s2.asm(60380): error: addressing mode not allowed here > > > lea (SK_PLC_Knuckles).l,a2 ; SK_PLC_Knuckles > > >s2.asm(60401): error: symbol undefined > > > SK_ArtUnc_Knux > > > lea (SK_ArtUnc_Knux).l,a1 ; SK_ArtUnc_Knux > > >s2.asm(60401): error: addressing mode not allowed here > > > lea (SK_ArtUnc_Knux).l,a1 ; SK_ArtUnc_Knux > > >s2.asm(74551): error: addressing mode not allowed on 68000 > > > move.w word_38810(pc,d1.w),d2 > > >s2.asm(74551): error: addressing mode not allowed here > > > move.w word_38810(pc,d1.w),d2 > > >s2.asm(74556): error: addressing mode not allowed on 68000 > > > lea byte_38820(pc,d1.w),a1 > > >s2.asm(74556): error: addressing mode not allowed here > > > lea byte_38820(pc,d1.w),a1 > > >s2.asm(83462): error: addressing mode not allowed on 68000 > > > lea Touch_Sizes(pc,d0.w),a2 > > >s2.asm(83462): error: addressing mode not allowed here > > > lea Touch_Sizes(pc,d0.w),a2 > > >s2.asm(83726): error: addressing mode not allowed on 68000 > > > move.w Enemy_Points(pc,d0.w),d0 > > >s2.asm(83726): error: addressing mode not allowed here > > > move.w Enemy_Points(pc,d0.w),d0 > > >s2.asm(85000): error: addressing mode not allowed on 68000 > > > move.w AnimPatMaps(pc,d0.w),d0 > > >s2.asm(85000): error: addressing mode not allowed here > > > move.w AnimPatMaps(pc,d0.w),d0 > > >s2.asm(85001): error: addressing mode not allowed on 68000 > > > lea AnimPatMaps(pc,d0.w),a0 > > >s2.asm(85001): error: addressing mode not allowed here > > > lea AnimPatMaps(pc,d0.w),a0 </asm> About half of those errors can be fixed by going through the Knuckles code and replacing each instance of this: <asm>
bsr.w Player_CheckFloor
</asm> With this: <asm>
jsr Sonic_CheckFloor
</asm> This will ensure that all three characters branch to the same location for floor checks.
Additional Step #4: Porting a bunch more stuff
Yep. In case the very clear subheading didn't give it away, we're porting even MORE stuff from our KiS2 disassembly. I know you're getting tired, but there's still more to do! Still on the second error list, but don't worry! We're almost done porting Knuckles!
Additional Step 4.1: ART AND STUFF
The moment you've probably been awaiting for God-knows-how-long. Here's where SonMapEd and the S3K disassembly come into play.