Actions

SCHG How-to

Difference between revisions of "Remove the Speed Cap"

From Sonic Retro

m (Air Speed Cap: Fixed weird tabbing issues)
m (I wanted to do this a looong time before.)
Line 161: Line 161:
  
 
<asm>Sonic_ChgJumpDir: ; XREF: Obj01_MdJump; Obj01_MdJump2
 
<asm>Sonic_ChgJumpDir: ; XREF: Obj01_MdJump; Obj01_MdJump2
move.w ($FFFFF760).w,d6
+
move.w ($FFFFF760).w,d6
move.w ($FFFFF762).w,d5
+
move.w ($FFFFF762).w,d5
asl.w #1,d5
+
asl.w #1,d5
btst #4,$22(a0)
+
btst #4,$22(a0)
bne.s Obj01_ResetScr2
+
bne.s Obj01_ResetScr2
move.w $10(a0),d0
+
move.w $10(a0),d0
btst #2,($FFFFF602).w; is left being pressed?
+
btst #2,($FFFFF602).w; is left being pressed?
beq.s loc_13278; if not, branch
+
beq.s loc_13278; if not, branch
bset #0,$22(a0)
+
bset #0,$22(a0)
sub.w d5,d0
+
sub.w d5,d0
move.w d6,d1
+
move.w d6,d1
neg.w d1
+
neg.w d1
cmp.w d1,d0
+
cmp.w d1,d0
bgt.s loc_13278
+
bgt.s loc_13278
move.w d1,d0
+
move.w d1,d0
 +
 
 
loc_13278:
 
loc_13278:
btst #3,($FFFFF602).w; is right being pressed?
+
btst #3,($FFFFF602).w; is right being pressed?
beq.s  Obj01_JumpMove; if not, branch
+
beq.s  Obj01_JumpMove; if not, branch
bclr #0,$22(a0)
+
bclr #0,$22(a0)
add.w d5,d0
+
add.w d5,d0
cmp.w d6,d0
+
cmp.w d6,d0
blt.s Obj01_JumpMove
+
blt.s Obj01_JumpMove
move.w d6,d0</asm>
+
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:
 
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
+
<asm> add.w d5,d0 ; +++ remove this frame's acceleration change
cmp.w d1,d0
+
cmp.w d1,d0 ; +++ compare speed with top speed
ble.s loc_13278</asm>
+
ble.s loc_13278 ; +++ if speed was already greater than the maximum, branch</asm>
  
 
And do a similar thing after blt.s Obj01_JumpMove:
 
And do a similar thing after blt.s Obj01_JumpMove:
<asm> sub.w d5,d0
+
<asm> sub.w d5,d0 ; +++ remove this frame's acceleration change
cmp.w d6,d0
+
cmp.w d1,d0 ; +++ compare speed with top speed
bge.s Obj01_JumpMove</asm>
+
bge.s Obj01_JumpMove ; +++ if speed was already greater than the maximum, branch</asm>
 +
 
 
Final result:
 
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
  
<asm>Sonic_ChgJumpDir: ; CODE XREF: ROM:00012E40 p ...
+
loc_13278:
move.w ($FFFFF760).w,d6
+
btst #3,($FFFFF602).w; is right being pressed?
move.w ($FFFFF762).w,d5
+
beq.s Obj01_JumpMove; if not, branch
asl.w #1,d5
+
bclr #0,$22(a0)
btst #4,$22(a0)
+
add.w d5,d0
bne.s Obj01_ResetScr2
+
cmp.w d6,d0
move.w $10(a0),d0
+
blt.s Obj01_JumpMove
btst #2,($FFFFF602).w; is left being pressed?
+
sub.w d5,d0 ; +++ remove this frame's acceleration change
beq.s loc_13278; if not, branch
+
cmp.w d1,d0 ; +++ compare speed with top speed
bset #0,$22(a0)
+
bge.s Obj01_JumpMove ; +++ if speed was already greater than the maximum, branch
sub.w d5,d0
+
move.w d6,d0</asm>
move.w d6,d1
 
neg.w d1
 
cmp.w d1,d0
 
bgt.s loc_13278
 
add.w d5,d0
 
cmp.w d1,d0
 
ble.s loc_13278
 
move.w d1,d0
 
 
 
loc_13278: ; CODE XREF: Sonic_ChgJumpDir+1C j ...
 
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
 
cmp.w d6,d0
 
bge.s Obj01_JumpMove  
 
move.w d6,d0</asm>
 
  
 
[[Category:SCHG How-tos|Remove the Speed Cap]]
 
[[Category:SCHG How-tos|Remove the Speed Cap]]

Revision as of 10:39, 18 October 2010

(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>