Spin dash
A move that charges a roll in place and releases it at speed, from Sonic the Hedgehog 2 on.
On this page
A spin dash charges a roll while the character crouches and launches it on release. In Sonic the Hedgehog 2 a jump press while ducking starts the charge1, further presses add to it as it leaks away2, and the release sets a speed of 8 to 12 px/frame3,3. Sonic 3 & Knuckles keeps the move unchanged4. Sonic the Hedgehog has none5.
- NoneSonic the Hedgehog (1991). No spin dash: standing, he can only jump, walk, or curl up.5
- One pressSonic Advance 2 (2002). One press is a full charge, 9 px/frame on release, which leaks by a 32nd each frame.6
- ChargedSonic the Hedgehog 2 (1992). Crouching, jump presses rev up a roll that letting go of Down launches, faster the harder it was revved.1,2,3Sonic 3 & Knuckles (1994). Sonic 2's spin dash, which Knuckles has too.4,7,8
Games
| Game | Year | How | Note |
|---|---|---|---|
| Sonic Advance 2 | 2002 | One press | one press is a full charge, 9 px/frame on release, which leaks by a 32nd each frame |
| Sonic the Hedgehog 2 | 1992 | Charged | crouching, jump presses rev up a roll that letting go of Down launches, faster the harder it was revved |
| Sonic 3 & Knuckles | 1994 | Charged | Sonic 2's spin dash, which Knuckles has too |
Every claim about this mechanic, by game (11)
References
- ^ abThe spin dash starts when a jump button is pressed while Sonic shows his ducking animation;
Sonic_CheckSpindashruns beforeSonic_Jumpand skips the rest of the frame.Codesonicretro/s2disasmHow we know
37603 cmpi.b #AniIDSonAni_Duck,anim(a0) ⋮ 37606 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 ⋮ 37611 addq.l #4,sp 37612 move.b #1,spindash_flag(a0) 37613 move.w #0,spindash_counter(a0)
s2.asm lines 37600–37613 at 4ef457c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abEach jump press while charging adds
$200to the spin dash counter, capped at$800, and each frame the counter loses 1/32 of itself.Codesonicretro/s2disasmHow we know
37714 move.w spindash_counter(a0),d0 37715 lsr.w #5,d0 37716 sub.w d0,spindash_counter(a0) ⋮ 37726 addi.w #$200,spindash_counter(a0) 37727 cmpi.w #$800,spindash_counter(a0) ⋮ 37729 move.w #$800,spindash_counter(a0)
s2.asm lines 37711–37729 at 4ef457c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abcReleasing Down sets Sonic's ground speed from the counter's high byte,
$800plus$80a step, from 8 px/frame uncharged to 12 at full charge (Super Sonic$B00to$F00).Codesonicretro/s2disasmrevisedHow we know
37635 btst #button_down,d0 37636 bne.w Sonic_ChargingSpindash ⋮ 37645 move.b spindash_counter(a0),d0 37646 add.w d0,d0 37647 move.w SpindashSpeeds(pc,d0.w),inertia(a0)
s2.asm lines 37633–37647 at 4ef457c · upstream ↗ 37688SpindashSpeeds: 37689 dc.w $800 ; 0 ⋮ 37697 dc.w $C00 ; 8 ⋮ 37699SpindashSpeedsSuper: 37700 dc.w $B00 ; 0
s2.asm lines 37688–37708 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.
- ^ abThe spin dash is Sonic 2's, with the same
$200a press to$800, the same 1/32 decay, and the same release speeds from$800to$C00.Codesonicretro/skdisasm · sonicretro/s2disasmrevisedHow we know
23741 move.b spin_dash_counter(a0),d0 23742 add.w d0,d0 23743 move.w word_11CF2(pc,d0.w),ground_vel(a0)
sonic3k.asm lines 23740–23743 at 73de97c · upstream ↗ 23773word_11CF2: 23774 dc.w $800 23775 dc.w $880
sonic3k.asm lines 23773–23782 at 73de97c · upstream ↗ 23799 lsr.w #5,d0 23800 sub.w d0,spin_dash_counter(a0) ⋮ 23811 addi.w #$200,spin_dash_counter(a0) 23812 cmpi.w #$800,spin_dash_counter(a0)
sonic3k.asm lines 23798–23814 at 73de97c · upstream ↗ 37688SpindashSpeeds: 37689 dc.w $800 ; 0 ⋮ 37697 dc.w $C00 ; 8
s2.asm lines 37688–37697 at 4ef457c · upstream ↗ 37715 lsr.w #5,d0 37716 sub.w d0,spindash_counter(a0) ⋮ 37726 addi.w #$200,spindash_counter(a0) 37727 cmpi.w #$800,spindash_counter(a0)
s2.asm lines 37714–37729 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.
- ^ abSonic 1 has no spin dash; standing on the ground,
Sonic_MdNormalchecks only for a jump, the slope, the d-pad, and a roll.Codesonicretro/s1disasm · sonicretro/s2disasmHow we know
318 bsr.w Sonic_Jump ; check if we need to jump 319 bsr.w Sonic_SlopeResistWalk ; handle resistance from running up slopes 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 316–325 at 15dfa3a · upstream ↗ 36515 bsr.w Sonic_CheckSpindash ; check for spindashs2.asm lines 36514–36515 at 4ef457c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^While the spin dash charges, each jump press adds
Q(2.0)(512) toqSpindashAcceland then raises it to at leastQ(8.0)(2048) withMAX, so one press is a full charge, the starting press included:Player_TryInitSpindashrunsPlayer_InitSpindashand thenPlayer_Spindashin the same frame. Each frame Down stays held first takes 1/32 off the charge. Releasing Down sets the ground speed fromsSpinDashSpeedsat the charge's whole part, capped at 8: 6 px/frame plus 3/8 a step, up to 9, so a release on the frame after a press always gives 9 px/frame (computed). In Sonic 2 the starting press setsspindash_counterto 0, and each later press adds$200up to a cap of$800, so a full charge takes five presses in all (computed); its release speeds run from 8 to 12 px/frame.CodeSAT-R/sa2 · sonicretro/s2disasmrevisedHow we know
9898bool32 Player_TryInitSpindash(Player *p) ⋮ 9900 u32 r6 = 0; 9901 if (p->charState == CHARSTATE_CROUCH) { 9902 if (p->frameInput & gPlayerControls.jump) { 9903 PLAYERFN_SET_AND_CALL(Player_InitSpindash, p);
src/game/shared/stage/player.c lines 9898–9904 at 393357f · upstream ↗ 7186void Player_InitSpindash(Player *p) ⋮ 7195 p->qSpindashAccel = 0; ⋮ 7203 PLAYERFN_SET_AND_CALL(Player_Spindash, p);
src/game/shared/stage/player.c lines 7186–7203 at 393357f · upstream ↗ 7212 if (!(p->heldInput & DPAD_DOWN)) { ⋮ 7217 index = I(p->qSpindashAccel); 7218 if (index > 8) 7219 index = 8; ⋮ 7221 speed = sSpinDashSpeeds[index]; ⋮ 7225 p->qSpeedGround = speed;
src/game/shared/stage/player.c lines 7212–7225 at 393357f · upstream ↗ 7230 } else { 7231 s16 pitch = p->qSpindashAccel; ⋮ 7233 s16 pitch2 = pitch; 7234 if (pitch2 != 0) { 7235 pitch = pitch2 - (I(pitch << 3)); ⋮ 7240 if (p->frameInput & gPlayerControls.jump) { ⋮ 7248 pitch += Q(2.0); 7249 pitch = MAX(pitch, Q(8.0));
src/game/shared/stage/player.c lines 7230–7249 at 393357f · upstream ↗ 558static const s16 sSpinDashSpeeds[9] = { 559 Q_8_8(6.000 + 0 * (3. / 8.)), // ⋮ 567 Q_8_8(6.000 + 8 * (3. / 8.)), //
src/game/shared/stage/player.c lines 558–567 at 393357f · upstream ↗ 37605 move.b (Ctrl_1_Press_Logical).w,d0 37606 andi.b #button_B_mask|button_C_mask|button_A_mask,d0 37607 beq.w return_1AC8C ⋮ 37612 move.b #1,spindash_flag(a0) 37613 move.w #0,spindash_counter(a0)
s2.asm lines 37605–37613 at 4ef457c · upstream ↗ 37726 addi.w #$200,spindash_counter(a0) 37727 cmpi.w #$800,spindash_counter(a0) 37728 blo.s Obj01_Spindash_ResetScr 37729 move.w #$800,spindash_counter(a0)
s2.asm lines 37726–37729 at 4ef457c · upstream ↗ 37688SpindashSpeeds: 37689 dc.w $800 ; 0 ⋮ 37697 dc.w $C00 ; 8
s2.asm lines 37688–37697 at 4ef457c · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^Crouching (animation 8), a press of A, B, or C starts the spin dash's charge at 0; while Down stays held, each frame first takes 1/32 of the counter (rounded down) and a press adds
$200, to$800; letting go of Down releases it, curling him (5 px down) and setting the ground speed from the counter's high byte (spindash; Super Sonic's table is faster), negated facing left. On the start, charge, and release frames he doesn't move, and the floor sensors still run. The charge's decay, step, and cap are Sonic 2's.Codesonicretro/skdisasm · sonicretro/s2disasmrevisedHow we know
23681SonicKnux_Spindash: 23682 tst.b spin_dash_flag(a0) 23683 bne.s loc_11C5E 23684 cmpi.b #8,anim(a0) ⋮ 23686 move.b (Ctrl_1_pressed_logical).w,d0 23687 andi.b #button_A_mask|button_B_mask|button_C_mask,d0 ⋮ 23692 addq.l #4,sp 23693 move.b #1,spin_dash_flag(a0) 23694 move.w #0,spin_dash_counter(a0)
sonic3k.asm lines 23679–23696 at 73de97c · upstream ↗ 23739 move.b #0,spin_dash_flag(a0) ⋮ 23741 move.b spin_dash_counter(a0),d0 ⋮ 23743 move.w word_11CF2(pc,d0.w),ground_vel(a0)
sonic3k.asm lines 23737–23746 at 73de97c · upstream ↗ 23770 jsr (Play_SFX).l 23771 bra.s loc_11D5E
sonic3k.asm lines 23770–23771 at 73de97c · upstream ↗ 23798 move.w spin_dash_counter(a0),d0 23799 lsr.w #5,d0 23800 sub.w d0,spin_dash_counter(a0) ⋮ 23811 addi.w #$200,spin_dash_counter(a0) 23812 cmpi.w #$800,spin_dash_counter(a0) ⋮ 23816loc_11D5E: 23817 addq.l #4,sp
sonic3k.asm lines 23796–23822 at 73de97c · upstream ↗ 37715 lsr.w #5,d0 37716 sub.w d0,spindash_counter(a0) ⋮ 37726 addi.w #$200,spindash_counter(a0) 37727 cmpi.w #$800,spindash_counter(a0)
s2.asm lines 37714–37729 at 4ef457c · 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.
- ^The Sonic & Knuckles manual gives Knuckles the spin dash and moves of his own: he breaks through walls, glides on a second press of the button in the air, and climbs walls.ManualSonic & Knuckles US manual
How we know
Knuckles uses a Spin Dash just like Sonic, but he also. has unique moves of his own. For one thing, he bashes through walls like nobody else! … Glide + Press Button A, Bor C twice quickly — once to get some air and again to start gliding. … Wall Climb ® Get close to a wall.
Knuckles' moves · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-26.
Sources
Code
- 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
- Sonic Retro contributors. 2026. “s1disasm: Sonic the Hedgehog (16-bit) disassembly (sonicretro/s1disasm).” Commit 15dfa3a. sonicretro/s1disasm @ 15dfa3a · licence, all uses