Actions

SCHG How-to

Difference between revisions of "Remove the Speed Cap"

From Sonic Retro

m (I wanted to do this a looong time before.)
m (Text replace - '[[Category:SCHG How-tos|' to '{{S1Howtos}} [[Category:SCHG How-tos|')
Line 229: Line 229:
 
move.w d6,d0</asm>
 
move.w d6,d0</asm>
  
 +
{{S1Howtos}}
 
[[Category:SCHG How-tos|Remove the Speed Cap]]
 
[[Category:SCHG How-tos|Remove the Speed Cap]]

Revision as of 10:28, 13 September 2011

(Ground speed cap fix originally by Tweaker; air speed cap fix originally by Puto)

Ground Speed Cap

Removing the speed cap requires taking a look at Sonic 2's version of Sonic_MoveLeft, and Sonic_MoveRight. First off, we should take a look at Sonic_MoveLeft (for example), and look at its code. <asm>Sonic_MoveLeft:  ; XREF: Sonic_Move move.w $14(a0),d0 beq.s loc_13086 bpl.s loc_130B2

loc_13086: bset #0,$22(a0) bne.s loc_1309A bclr #5,$22(a0) move.b #1,$1D(a0)

loc_1309A: sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_130A6 move.w d1,d0

loc_130A6: move.w d0,$14(a0) move.b #0,$1C(a0); use walking animation rts</asm> This is the section we're looking for. Now, let's look up one of the lines in here until we find a matching pattern in S2. <asm>loc_1C2A4:  ; CODE XREF: h+515C p move.w $14(a0),d0 beq.s loc_1C2AC bpl.s loc_1C2DE

loc_1C2AC:  ; CODE XREF: h+5334 j bset #0,$22(a0) bne.s loc_1C2C0 bclr #5,$22(a0) move.b #1,$1D(a0)

loc_1C2C0:  ; CODE XREF: h+533E j sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_1C2D2 add.w d5,d0 cmp.w d1,d0 ble.s loc_1C2D2 move.w d1,d0

loc_1C2D2:  ; CODE XREF: h+5354 j h+535A j move.w d0,$14(a0) move.b #0,$1C(a0) rts</asm> Success! Now, let's compare the differences here. You'll notice S2's routine has 3 extra lines in it: <asm> add.w d5,d0 cmp.w d1,d0 ble.s loc_1C2D2</asm> So, what we want to do is add this code to Sonic 1's routine. Take these 3 lines and modify them to work with S1. You should end up with this: <asm>Sonic_MoveLeft:  ; XREF: Sonic_Move move.w $14(a0),d0 beq.s loc_13086 bpl.s loc_130B2

loc_13086: bset #0,$22(a0) bne.s loc_1309A bclr #5,$22(a0) move.b #1,$1D(a0)

loc_1309A: sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_130A6 add.w d5,d0 cmp.w d1,d0 ble.s loc_130A6 move.w d1,d0

loc_130A6: move.w d0,$14(a0) move.b #0,$1C(a0); use walking animation rts</asm> Now, we have to do the same for Sonic_MoveRight. Once again, let's find the S2 equivalent of the routine using Sonic 1's routine.

Sonic 1's: <asm>Sonic_MoveRight:  ; XREF: Sonic_Move move.w $14(a0),d0 bmi.s loc_13118 bclr #0,$22(a0) beq.s loc_13104 bclr #5,$22(a0) move.b #1,$1D(a0)

loc_13104: add.w d5,d0 cmp.w d6,d0 blt.s loc_1310C move.w d6,d0

loc_1310C: move.w d0,$14(a0) move.b #0,$1C(a0); use walking animation rts</asm> And, with the same amount of backsearching, we can find Sonic 2's, which is the following: <asm>loc_1C32A:  ; CODE XREF: h+5168 p move.w $14(a0),d0 bmi.s loc_1C35E bclr #0,$22(a0) beq.s loc_1C344 bclr #5,$22(a0) move.b #1,$1D(a0)

loc_1C344:  ; CODE XREF: h+53C2 j add.w d5,d0 cmp.w d6,d0 blt.s loc_1C352 sub.w d5,d0 cmp.w d6,d0 bge.s loc_1C352 move.w d6,d0

loc_1C352:  ; CODE XREF: h+53D4 j h+53DA j move.w d0,$14(a0) move.b #0,$1C(a0) rts</asm> Now, once again, you'll notice the difference between the two routines is the following lines: <asm> sub.w d5,d0 cmp.w d6,d0 bge.s loc_1C352</asm> So, once again, let's apply these changes to work with S1, providing our final, result routine for S1: <asm>Sonic_MoveRight:  ; XREF: Sonic_Move move.w $14(a0),d0 bmi.s loc_13118 bclr #0,$22(a0) beq.s loc_13104 bclr #5,$22(a0) move.b #1,$1D(a0)

loc_13104: add.w d5,d0 cmp.w d6,d0 blt.s loc_1310C sub.w d5,d0 cmp.w d6,d0 bge.s loc_1310C move.w d6,d0

loc_1310C: move.w d0,$14(a0) move.b #0,$1C(a0); use walking animation rts</asm>

And that should be it! Build your new ROM, and the infamous (ground) speed cap should be gone!

Air Speed Cap

However, that still keeps the cap in mid-air. So let's adapt that to fix the speed cap in mid-air too.

Here's the original code:

<asm>Sonic_ChgJumpDir: ; XREF: Obj01_MdJump; Obj01_MdJump2 move.w ($FFFFF760).w,d6 move.w ($FFFFF762).w,d5 asl.w #1,d5 btst #4,$22(a0) bne.s Obj01_ResetScr2 move.w $10(a0),d0 btst #2,($FFFFF602).w; is left being pressed? beq.s loc_13278; if not, branch bset #0,$22(a0) sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_13278 move.w d1,d0

loc_13278: btst #3,($FFFFF602).w; is right being pressed? beq.s Obj01_JumpMove; if not, branch bclr #0,$22(a0) add.w d5,d0 cmp.w d6,d0 blt.s Obj01_JumpMove move.w d6,d0</asm>

As you can see, it works exactly the same way as the MoveLeft/Right routines. So let's apply the same fix. After bgt.s loc_13278, add the following lines: <asm> add.w d5,d0 ; +++ remove this frame's acceleration change cmp.w d1,d0 ; +++ compare speed with top speed ble.s loc_13278 ; +++ if speed was already greater than the maximum, branch</asm>

And do a similar thing after blt.s Obj01_JumpMove: <asm> sub.w d5,d0 ; +++ remove this frame's acceleration change cmp.w d1,d0 ; +++ compare speed with top speed bge.s Obj01_JumpMove ; +++ if speed was already greater than the maximum, branch</asm>

Final result: <asm>Sonic_ChgJumpDir: ; XREF: Obj01_MdJump; Obj01_MdJump2 move.w ($FFFFF760).w,d6 move.w ($FFFFF762).w,d5 asl.w #1,d5 btst #4,$22(a0) bne.s Obj01_ResetScr2 move.w $10(a0),d0 btst #2,($FFFFF602).w; is left being pressed? beq.s loc_13278; if not, branch bset #0,$22(a0) sub.w d5,d0 move.w d6,d1 neg.w d1 cmp.w d1,d0 bgt.s loc_13278 add.w d5,d0 ; +++ remove this frame's acceleration change cmp.w d1,d0 ; +++ compare speed with top speed ble.s loc_13278 ; +++ if speed was already greater than the maximum, branch move.w d1,d0

loc_13278: btst #3,($FFFFF602).w; is right being pressed? beq.s Obj01_JumpMove; if not, branch bclr #0,$22(a0) add.w d5,d0 cmp.w d6,d0 blt.s Obj01_JumpMove sub.w d5,d0 ; +++ remove this frame's acceleration change cmp.w d1,d0 ; +++ compare speed with top speed bge.s Obj01_JumpMove ; +++ if speed was already greater than the maximum, branch move.w d6,d0</asm>

SCHG How-To Guide: Sonic the Hedgehog (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix the SEGA Sound | Display the Press Start Button Text | Fix the Level Select Menu | Fix the Hidden Points Bug | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix the Walk-Jump Bug | Correct Drowning Bugs | Fix the Death Boundary Bug | Fix the Camera Follow Bug | Fix Song Restoration Bugs | Fix the HUD Blinking | Fix the Level Select Graphics Bug | Fix a remember sprite related bug
Changing Design Choices
Change Spike Behavior | Collide with Water After Being Hurt | Fix Special Stage Jumping Physics | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Remove the Speed Cap | Port the REV01 Background Effects | Port Sonic 2's Level Art Loader | Retain Rings Between Acts | Add Sonic 2 (Simon Wai Prototype) Level Select | Improve ObjectMove Subroutines | Port Sonic 2 Level Select
Adding Features
Add Spin Dash ( Part 1 / Part 2 / Part 3 / Part 4 ) | Add Eggman Monitor | Add Super Sonic | Add the Air Roll
Sound Features
Expand the Sound Index | Play Different Songs Per Act | Port Sonic 2 Final Sound Driver | Port Sonic 3's Sound Driver | Port Flamewing's Sonic 3 & Knuckles Sound Driver | Change The SEGA Sound
Extending the Game
Load Chunks From ROM | Add Extra Characters | Make an Alternative Title Screen | Use Dynamic Tilesets | Make GHZ Load Alternate Art | Make Ending Load Alternate Art | Add a New Zone | Set Up the Goggle Monitor | Add New Moves | Add a Dynamic Collision System | Dynamic Special Stage Walls System | Extend Sprite Mappings and Art Limit | Enigma Credits | Use Dynamic Palettes
Miscellaneous
Convert the Hivebrain 2005 Disassembly to ASM68K
Split Disassembly Guides
Set Up a Split Disassembly | Basic Level Editing | Basic Art Editing | Basic ASM Editing (Spin Dash)