Rolling
A platformer state in which the character curls into a ball that keeps its running speed, can't accelerate, and gains more from downhill slopes.
On this page
Rolling curls the character into a ball that keeps the speed it had. In Sonic the Hedgehog Down at speed starts a roll1, which can’t accelerate and slows by a small friction whatever is held2. Sonic 2 and Sonic 3 & Knuckles keep the numbers3,4. Slopes push a roll harder than a run5.
- Slopes onlySonic the Hedgehog (1991). Down at speed curls Sonic up; on flat ground a roll never speeds up, only slows.1,2,6Sonic the Hedgehog 2 (1992). Down while moving curls Sonic up; on flat ground a roll only slows.7,3Sonic 3 & Knuckles (1994). Down curls him only at twice Sonic 2's speed, and a slowing roll stands him up before it stops.4,8,9
Games
| Game | Year | How | Note |
|---|---|---|---|
| Sonic the Hedgehog | 1991 | Slopes only | Down at speed curls Sonic up; on flat ground a roll never speeds up, only slows |
| Sonic the Hedgehog 2 | 1992 | Slopes only | Down while moving curls Sonic up; on flat ground a roll only slows |
| Sonic 3 & Knuckles | 1994 | Slopes only | Down curls him only at twice Sonic 2's speed, and a slowing roll stands him up before it stops |
Every claim about this mechanic, by game (7)
References
- ^ abIn the running game, on flat ground, Down without Left or Right curls Sonic into a roll when his ground speed, after this frame's friction, is at least
$80either way: from$8Cwritten in by the probe he rolls, from$8Bhe doesn't.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Rolling”How we know
1150 move.w obInertia(a0),d0 ; get Sonic's current ground speed ⋮ 1155 cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster? 1156 blo.s .noroll ; if not, branch 1157 move.b (v_jpadhold2).w,d0 ; get held buttons 1158 andi.b #btnL+btnR,d0 ; is left/right being held? 1159 bne.s .noroll ; if yes, prevent rolling (some kind of fat-fingering convenience feature?) 1160 btst #bitDn,(v_jpadhold2).w ; is down being held? 1161 bne.s Sonic_ChkRoll ; if yes, branch
_incObj/01 Sonic.asm lines 1150–1161 at 15dfa3a · upstream ↗ 1177 bset #status_rolling_bit,obStatus(a0) ; set rolling flag 1178 move.b #sonic_roll_height,obHeight(a0) ; set Sonic's hitbox height to rolling size ⋮ 1187 addq.w #sonic_height-sonic_roll_height,obY(a0) ; adjust Y-position to align Sonic to the floor
_incObj/01 Sonic.asm lines 1176–1187 at 15dfa3a · upstream ↗ 320 bsr.w Sonic_Move ; handle Sonic's left/right movement 321 bsr.w Sonic_Roll ; check if we need to roll
_incObj/01 Sonic.asm lines 320–321 at 15dfa3a · upstream ↗ In Sonic 1, 2, and 3, the Player can't begin to roll unless absolute Ground Speed is greater than or equal to 0.5 (128 subpixels)
Criteria · archived copy ↗ Measured by a script. It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-25.
- ^ abIn the running game, on flat ground, a roll never speeds up: friction takes
$6a frame whatever is held, holding against the roll takes another$20, and a ground speed past$1000written in by the probe gives an X speed of exactly ±$1000(16 px/frame).Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Rolling”How we know
767Sonic_RollSpeed: 768 move.w (v_sonspeedmax).w,d6 ; get Sonic's current max speed... 769 asl.w #1,d6 ; ...doubled while rolling 770 move.w (v_sonspeedacc).w,d5 ; get Sonic's current acceleration... 771 asr.w #1,d5 ; ...halved while rolling 772 move.w (v_sonspeeddec).w,d4 ; get Sonic's current deceleration... 773 asr.w #2,d4 ; ...divided by 4 while rolling
_incObj/01 Sonic.asm lines 767–773 at 15dfa3a · upstream ↗ 791.notright: 792 move.w obInertia(a0),d0 ; get Sonic's current ground speed 793 beq.s Sonic_RollSlowdownDone ; is he standing still? if yes, branch 794 bmi.s .rollingleft ; is he moving to the left? if yes, branch 795 sub.w d5,d0 ; slightly decrease Sonic's current roll speed 796 bcc.s .stillrollingright ; if still rolling, branch 797 move.w #0,d0 ; reset speed to zero on sign change
_incObj/01 Sonic.asm lines 791–797 at 15dfa3a · upstream ↗ 912Sonic_RollRight: 913 move.w obInertia(a0),d0 ; get Sonic's current ground speed 914 bmi.s .changedirection ; has Sonic changed direction? if yes, branch 915 bclr #status_xflip_bit,obStatus(a0) ; clear X-flip flag (Sonic is facing right) 916 move.b #id_Roll,obAnim(a0) ; use "rolling" animation 917 rts ; return
_incObj/01 Sonic.asm lines 912–917 at 15dfa3a · upstream ↗ 863 cmpi.w #$1000,d1 ; is new X-velocity bigger than maximum screen shift speed? (rightward) ⋮ 873 move.w d1,obVelX(a0) ; set new X-velocity
_incObj/01 Sonic.asm lines 863–873 at 15dfa3a · upstream ↗ roll_friction_speed 0.0234375 (6 subpixels) roll_deceleration_speed 0.125 (32 subpixels)
Constants · archived copy ↗ Measured by a script. It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-25.
- ^ abRolling, Sonic slows by half his acceleration (
$6) a frame, by$20more against the d-pad, and his X speed is clamped to$1000(16 px/frame).Codesonicretro/s2disasm · sonicretro/s1disasmrevisedHow we know
37057 move.w (Sonic_acceleration).w,d5 37058 asr.w #1,d5 ; natural roll deceleration = 1/2 normal acceleration
s2.asm lines 37057–37059 at 4ef457c · upstream ↗ 37137 cmpi.w #$1000,d1 ⋮ 37139 move.w #$1000,d1 ; limit Sonic's speed rolling right
s2.asm lines 37137–37143 at 4ef457c · upstream ↗ asr.w #1,d5 … move.w (v_sonspeeddec).w,d4 … asr.w #2,d4
_incObj/01 Sonic.asm#L770-L773 · upstream ↗ cmpi.w #$1000,d1 … move.w #$1000,d1
_incObj/01 Sonic.asm#L863-L865 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^ abRolling keeps Sonic 2's numbers, friction of half the acceleration (
$6),$20more against the d-pad, and X speed clamped to$1000.Codesonicretro/skdisasm · sonicretro/s2disasmrevisedHow we know
22962 move.w Acceleration-Max_speed(a4),d5 22963 asr.w #1,d5 ⋮ 22969 move.w #$20,d4
sonic3k.asm lines 22962–22969 at 73de97c · upstream ↗ 23055 cmpi.w #$1000,d1 23056 ble.s loc_115F6 23057 move.w #$1000,d1
sonic3k.asm lines 23055–23057 at 73de97c · upstream ↗ 37058 asr.w #1,d5 ; natural roll deceleration = 1/2 normal accelerations2.asm lines 37057–37059 at 4ef457c · upstream ↗ 37137 cmpi.w #$1000,d1 37138 ble.s + 37139 move.w #$1000,d1 ; limit Sonic's speed rolling right
s2.asm lines 37137–37139 at 4ef457c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^In the running game, on a 45° ramp built from Green Hill's
$E0ramp block, every ground frame's ground speed matched the flat-ground rules after a slope term of the sine of his angle times$20while he ran,$50while he rolled downhill and a quarter of that uphill; standing still on the ramp for 60 frames, he didn't move.Verifiedsonicretro/s1disasmHow we know
1330 jsr (CalcSine).l ; get sine and cosine values for angle 1331 muls.w #$20,d0 ; multiply by resist force while walking 1332 asr.l #8,d0 ; shift down a byte ⋮ 1334 tst.w obInertia(a0) ; check Sonic's ground speed 1335 beq.s .return ; if he's standing still, branch
_incObj/01 Sonic.asm lines 1329–1339 at 15dfa3a · upstream ↗ 1369 muls.w #$50,d0 ; multiply by resist force while rolling (2.5x larger than walking) ⋮ 1376 asr.l #2,d0 ; reduce resist force while ascending a slope
_incObj/01 Sonic.asm lines 1369–1376 at 15dfa3a · upstream ↗ Measured by a script. It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-22.
Checked by a second AI model, 2026-10-25.
- ^In the running game, a roll started at top speed on flat ground stops on its 255th frame whether forward is held or not, and Sonic stands up on that frame.Verifiedsonicretro/s1disasm
How we know
795 sub.w d5,d0 ; slightly decrease Sonic's current roll speed ⋮ 818 tst.w obInertia(a0) ; is Sonic standing still? 819 bne.s Sonic_AngledRollSpeed ; if not, branch ⋮ 821 bclr #status_rolling_bit,obStatus(a0) ; clear rolling flag
_incObj/01 Sonic.asm lines 791–825 at 15dfa3a · upstream ↗ Measured by a script. It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-25.
Checked by a second AI model, 2026-10-25.
- ^Sonic curls into a roll when Down is held without Left or Right and his ground speed is at least
$80either way, as in Sonic 1.Codesonicretro/s2disasm · sonicretro/s1disasmrevisedHow we know
37345 mvabs.w inertia(a0),d0 37346 cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster? ⋮ 37349 andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed? ⋮ 37351 btst #button_down,(Ctrl_1_Held_Logical).w ; is down being pressed?
s2.asm lines 37345–37352 at 4ef457c · upstream ↗ 1155 cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster? ⋮ 1158 andi.b #btnL+btnR,d0 ; is left/right being held? ⋮ 1160 btst #bitDn,(v_jpadhold2).w ; is down being held?
_incObj/01 Sonic.asm lines 1155–1161 at 15dfa3a · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^With Down held, neither Left nor Right, and no infinite-inertia flag (bit 7 of status_secondary), Sonic curls into a roll at a ground speed of
$100or more either way, twice Sonic 2's$80; slower than that, unless he stands on an object, he crouches, where Sonic 2 and Sonic 3 alone crouch only fromSonic_Move's standstill branch.Codesonicretro/skdisasm · sonicretro/s2disasmrevisedHow we know
23258SonicKnux_Roll: ⋮ 23262 andi.b #button_left_mask|button_right_mask,d0 ; is left/right being pressed? 23263 bne.s locret_1177E ; if yes, branch 23264 btst #button_down,(Ctrl_1_logical).w ; is down being pressed? ⋮ 23271 cmpi.w #$100,d0 ; is Sonic moving at $100 speed or faster? 23272 bhs.s Player_ChkRoll ; if so, branch 23273 btst #Status_OnObj,status(a0) 23274 bne.s locret_1177E 23275 move.b #8,anim(a0) ; enter ducking animation
sonic3k.asm lines 23258–23278 at 73de97c · upstream ↗ 37345 mvabs.w inertia(a0),d0 37346 cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster? 37347 blo.s Obj01_NoRoll ; if not, branch
s2.asm lines 37345–37352 at 4ef457c · upstream ↗ 20970 cmpi.w #$80,d0 ; is Sonic moving at $80 speed or faster? 20971 blo.s locret_127D0 ; if so, branch
s3.asm lines 20970–20976 at 73de97c · upstream ↗ 36788Sonic_Duck: 36789 btst #button_down,(Ctrl_1_Held_Logical).w ; is down being pressed? 36790 beq.s Obj01_ResetScr ; if not, branch 36791 move.b #AniIDSonAni_Duck,anim(a0) ; use "ducking" animation
s2.asm lines 36788–36791 at 4ef457c · upstream ↗ 20420loc_12362: 20421 btst #button_down,(Ctrl_1_held_logical).w 20422 beq.s loc_1238C 20423 move.b #8,anim(a0)
s3.asm lines 20420–20423 at 73de97c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Revised after a check by a second AI model, 2026-10-26.
- ^Outside pinball mode (spin_dash_flag set on a roll) and without the infinite-inertia flag, a roll ends once friction and the d-pad leave the ground speed under
$80either way, and the speed left is kept; Sonic 2 and Sonic 3 alone unroll only at 0. Standing up moves his center 5 px up with normal gravity. In pinball mode a positive flag sets the speed to$400in his facing direction instead, and a negative one skips the d-pad, friction, and this check.Codesonicretro/skdisasm · sonicretro/s2disasmrevisedHow we know
23007 move.w ground_vel(a0),d0 ⋮ 23012 cmpi.w #$80,d0 23013 bhs.s loc_115C6 ⋮ 23016 bclr #Status_Roll,status(a0) 23017 move.b y_radius(a0),d0 23018 move.b default_y_radius(a0),y_radius(a0) ⋮ 23021 sub.b default_y_radius(a0),d0 ⋮ 23028 add.w d0,y_pos(a0)
sonic3k.asm lines 23007–23028 at 73de97c · upstream ↗ 37097Sonic_CheckRollStop: 37098 tst.w inertia(a0) 37099 bne.s Obj01_Roll_ResetScr ⋮ 37102 bclr #status.player.rolling,status(a0) ⋮ 37106 subq.w #5,y_pos(a0)
s2.asm lines 37097–37106 at 4ef457c · upstream ↗ 20728 tst.w ground_vel(a0) 20729 bne.s loc_12636 ⋮ 20732 bclr #Status_Roll,status(a0)
s3.asm lines 20728–20739 at 73de97c · upstream ↗ 22970 tst.b spin_dash_flag(a0) 22971 bmi.w loc_115C6 22972 tst.b status_secondary(a0) 22973 bmi.w loc_115C6
sonic3k.asm lines 22970–22973 at 73de97c · upstream ↗ 23032loc_115B4: 23033 move.w #$400,ground_vel(a0) 23034 btst #Status_Facing,status(a0) 23035 beq.s loc_115C6 23036 neg.w ground_vel(a0)
sonic3k.asm lines 23032–23036 at 73de97c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Revised after a check by a second AI model, 2026-10-26.
Sources
Code
- Sonic Retro contributors. 2026. “s1disasm: Sonic the Hedgehog (16-bit) disassembly (sonicretro/s1disasm).” Commit 15dfa3a. sonicretro/s1disasm @ 15dfa3a · licence, all uses
- Sonic Retro contributors. 2026. “s2disasm: Sonic the Hedgehog 2 (16-bit) disassembly (sonicretro/s2disasm).” Commit 4ef457c. sonicretro/s2disasm @ 4ef457c · licence, all uses
- Sonic Retro contributors. 2026. “skdisasm: Sonic 3 & Knuckles disassembly (sonicretro/skdisasm).” Commit 73de97c. sonicretro/skdisasm @ 73de97c · licence, all uses
Secondary
- Sonic Retro contributors. n.d. “Sonic Physics Guide: Rolling.” Sonic Retro. original · archived · licence, all uses