On this page
  1. Related
  2. Games
  3. References
  4. Sources

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

GameYearHowNote
Sonic Advance 22002One pressone press is a full charge, 9 px/frame on release, which leaks by a 32nd each frame
Sonic the Hedgehog 21992Chargedcrouching, jump presses rev up a roll that letting go of Down launches, faster the harder it was revved
Sonic 3 & Knuckles1994ChargedSonic 2's spin dash, which Knuckles has too
Every claim about this mechanic, by game (11)
Sonic the Hedgehog 1991Sonic 1 has no spin dash; standing on the ground, Sonic_MdNormal checks only for a jump, the slope, the d-pad, and a roll.Code
Sonic the Hedgehog 2 1992The spin dash starts when a jump button is pressed while Sonic shows his ducking animation; Sonic_CheckSpindash runs before Sonic_Jump and skips the rest of the frame.Code
Each jump press while charging adds $200 to the spin dash counter, capped at $800, and each frame the counter loses 1/32 of itself.Code
Releasing Down sets Sonic's ground speed from the counter's high byte, $800 plus $80 a step, from 8 px/frame uncharged to 12 at full charge (Super Sonic $B00 to $F00).Code
A frame-by-frame model of Obj01_MdNormal_Checks, Obj01_MdNormal, Obj01_MdRoll, and the air modes, with Sonic_Animate's timing for the standing and blinking animations, matches Sonic the Hedgehog 2 itself, run in MAME with Sonic alone on a floor built of Emerald Hill Act 1's blocks, on every frame of the movement lab's flat-ground presets, eleven scripts of Sonic 2's own moves, and 100 random input scripts.Verified
Letting go of Down while charging curls Sonic (Y + 5), sets his ground speed from the counter's high byte (spindash-speeds, or SpindashSpeedsSuper as Super Sonic), negated facing left, and ends the frame after the floor snap with his X speed unchanged, so he starts moving the next frame.Code
Sonic 2's movement on flat ground is Sonic 1's with five changes: the spin dash, a ground speed above the top kept while forward is held, a blink after standing that skips up to five frames of input, balancing that turns him only when he's far over the edge, and a floor snap that reaches down his X speed's whole pixels plus 4 rather than 14 px.Code
Sonic 3 & Knuckles 1994The spin dash is Sonic 2's, with the same $200 a press to $800, the same 1/32 decay, and the same release speeds from $800 to $C00.Code
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.Code
A frame-by-frame model of Sonic_MdNormal, Sonic_MdRoll, Sonic_MdJump, and SonicKnux_Spindash on flat ground, with the insta-shield, matches Sonic 3 & Knuckles itself, run in MAME with Sonic alone on a floor built of Angel Island Act 1's blocks, on every frame of the movement lab's flat-ground presets, stress scripts, and spin-dash and roll scripts and of 100 random input scripts.Verified
Sonic Advance 2 2002While the spin dash charges, each jump press adds Q(2.0) (512) to qSpindashAccel and then raises it to at least Q(8.0) (2048) with MAX, so one press is a full charge, the starting press included: Player_TryInitSpindash runs Player_InitSpindash and then Player_Spindash in the same frame. Each frame Down stays held first takes 1/32 off the charge. Releasing Down sets the ground speed from sSpinDashSpeeds at 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 sets spindash_counter to 0, and each later press adds $200 up 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.Code

References

  1. ^ abThe spin dash starts when a jump button is pressed while Sonic shows his ducking animation; Sonic_CheckSpindash runs before Sonic_Jump and skips the rest of the frame.Codesonicretro/s2disasm
    How 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.

    In the claim ledger

  2. ^ abEach jump press while charging adds $200 to the spin dash counter, capped at $800, and each frame the counter loses 1/32 of itself.Codesonicretro/s2disasm
    How 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.

    In the claim ledger

  3. ^ abcReleasing Down sets Sonic's ground speed from the counter's high byte, $800 plus $80 a step, from 8 px/frame uncharged to 12 at full charge (Super Sonic $B00 to $F00).Codesonicretro/s2disasmrevised
    How 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.

    In the claim ledger

  4. ^ abThe spin dash is Sonic 2's, with the same $200 a press to $800, the same 1/32 decay, and the same release speeds from $800 to $C00.Codesonicretro/skdisasm · sonicretro/s2disasmrevised
    How 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.

    In the claim ledger

  5. ^ abSonic 1 has no spin dash; standing on the ground, Sonic_MdNormal checks only for a jump, the slope, the d-pad, and a roll.Codesonicretro/s1disasm · sonicretro/s2disasm
    How 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 spindash
    
    s2.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.

    In the claim ledger

  6. ^While the spin dash charges, each jump press adds Q(2.0) (512) to qSpindashAccel and then raises it to at least Q(8.0) (2048) with MAX, so one press is a full charge, the starting press included: Player_TryInitSpindash runs Player_InitSpindash and then Player_Spindash in the same frame. Each frame Down stays held first takes 1/32 off the charge. Releasing Down sets the ground speed from sSpinDashSpeeds at 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 sets spindash_counter to 0, and each later press adds $200 up 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/s2disasmrevised
    How 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.

    In the claim ledger

  7. ^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/s2disasmrevised
    How 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.

    In the claim ledger

  8. ^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.

    In the claim ledger

Sources

Code