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

Air control is how far the player can steer a character in mid-air. Three games span the range, from a jump fixed at take-off to one steered against its own momentum. The lab runs each game’s rules frame by frame, checked against its cartridge; play it, or pick a preset.

Interactive: movement-lab (needs JavaScript)

Air control, three ways
  • FixedCastlevania (1986). The jump goes the way the d-pad pointed at take-off, and the d-pad does nothing in the air.1,2Castlevania II: Simon's Quest (1987). The jump keeps the direction held at take-off, as in Castlevania.3Castlevania III: Dracula's Curse (1989), Trevor, Sypha, and Alucard. The direction is set at take-off and can't be changed in the air.4
  • LatchedCastlevania III: Dracula's Curse (1989), Grant. He can steer in the air, and keeps drifting when the d-pad is let go.5
  • DirectMega Man (1987). Hold a direction and he moves at full speed; let go and he stops.6Mega Man 2 (1988). The d-pad moves him at full speed in the air, and he turns and stops at once.7,8Mega Man 3 (1990). A held direction moves him at walking speed in the air.9Castlevania: Symphony of the Night (1997). A held direction moves him at full speed at once; let go and he drifts to a stop.10
  • Stops on releaseSuper Metroid (1994). In a normal jump, a held direction accelerates Samus to 1.25 px/frame, and letting go stops her base speed.11
  • MomentumSuper Mario World (1990). The d-pad pushes against the speed Mario carries, and with it released he keeps that speed.12,13Super Castlevania IV (1991). The d-pad steers him gradually in the air, and he drifts on when let go.14Sonic the Hedgehog 2 (1992). The d-pad speeds him up either way in the air, twice as fast as on the ground, and near the top of a jump air drag slows him.15,16Sonic 3 & Knuckles (1994). The old steering and drag, but a Sonic faster than his top speed keeps that speed in the air.17,18
  • DampedCeleste (2018). Steering takes 0.65 of the ground's rates, and released, Madeline's speed falls toward 0.19

Prince of Persia fixes a jump as Castlevania does2: its control routine reads no input during a jump’s frames20. Quake III Arena steers with its ground rule at an acceleration of 121 in place of 1022, adding to the speed carried until its component along the wish direction reaches the full wish speed21. Super Mario World’s held direction likewise adds to the speed carried, up to Mario’s top speed12.

Castlevania II: Simon’s Quest keeps Castlevania’s fixed jump: the take-off sets 1 px/frame toward a held direction, and the jumping state reads only B, for the whip3,2. Castlevania III: Dracula’s Curse sets the same take-off speed for every character but Grant, although the atlas hasn’t traced every routine its jumping state calls for a Left or Right read4. A held direction sets Grant’s speed to 1 px/frame in the air, and he keeps moving when it’s let go5. Super Castlevania IV lets Simon steer: a held side adds 0.25 px/frame² up to 1.25 px/frame, and the speed coasts when let go14. Castlevania: Symphony of the Night sets Alucard’s speed to 1.5 px/frame toward a held direction at once, and every jumping frame first slows it by 1/16 px/frame toward 010.

In the air, a held direction moves Mega Man 3’s hero at his walking speed, 1.30 px/frame ($01.$4C)9, on every frame9. Sonic the Hedgehog 2 keeps Sonic the Hedgehog’s air steering and drag15,16,23,24. In Sonic 3 & Knuckles, a Sonic already faster than the top speed keeps his speed in the air, where Sonic and Sonic 2 pulled him down to it17.

#Quirks

  • Super Mario World’s turn overshoots zero, and the game reads only the speed’s high byte, so reversing from a full run takes 29 frames25.
  • Super Mario Bros. keeps a released jump’s speed26, but a jump keeps Mario’s take-off facing27, so steering back brakes at the plain rate until he moves the other way; from a run he crosses zero only 50 frames into the jump28. Compare the two in the lab’s Mario line.
  • Castlevania’s press frame still walks Simon 1 px before the jump fixes his direction29.
  • Sonic the Hedgehog keeps his speed in the air, except near the top of a jump, where drag takes ×31/32 a frame near the top of a jump24,24; a held jump from top speed lands at 6 → 3.41 px/frame30,30. A jump from a roll locks the d-pad31.
  • Celeste doesn’t coast: with the d-pad released in the air, Madeline’s speed falls toward 0 at the air rate, ×0.65 of the ground’s19.

Games

GameYearHowNote
Castlevania1986Fixedthe jump goes the way the d-pad pointed at take-off, and the d-pad does nothing in the air
Castlevania II: Simon's Quest1987Fixedthe jump keeps the direction held at take-off, as in Castlevania
Castlevania III: Dracula's Curse1989FixedTrevor, Sypha, and Alucard · the direction is set at take-off and can't be changed in the air
Prince of Persia1989Fixedthe control routine reads no input during a jump's frames
Castlevania III: Dracula's Curse1989LatchedGrant · he can steer in the air, and keeps drifting when the d-pad is let go
Mega Man1987Directhold a direction and he moves at full speed; let go and he stops
Mega Man 21988Directthe d-pad moves him at full speed in the air, and he turns and stops at once
Mega Man 31990Directa held direction moves him at walking speed in the air
Metroid II: Return of Samus1991Direct1 px/frame toward a held direction in a plain jump, none without
Mega Man 61993Directthe d-pad sets the speed in the air on every frame
Castlevania: Symphony of the Night1997Directa held direction moves him at full speed at once; let go and he drifts to a stop
Super Metroid1994Stops on releasein a normal jump, a held direction accelerates Samus to 1.25 px/frame, and letting go stops her base speed
Super Mario Bros.1985Momentuma held direction speeds him toward it, let go he keeps his speed, and he faces the way he jumped
Metroid1986Momentuma running jump steers by acceleration and a somersault keeps its speed; a standing jump moves 1 px/frame only while held
Super Mario Bros. 31988Momentuma held direction speeds Mario up in the air as on the ground, and let go he keeps his speed
Super Mario World1990Momentumthe d-pad pushes against the speed Mario carries, and with it released he keeps that speed
Sonic the Hedgehog1991Momentumthe d-pad speeds him up either way in the air, twice as fast as on the ground, and near the top of a jump air drag slows him
Super Castlevania IV1991Momentumthe d-pad steers him gradually in the air, and he drifts on when let go
Sonic the Hedgehog 21992Momentumthe d-pad speeds him up either way in the air, twice as fast as on the ground, and near the top of a jump air drag slows him
Sonic 3 & Knuckles1994Momentumthe old steering and drag, but a Sonic faster than his top speed keeps that speed in the air
Quake1996Momentumthe move keys push against the speed carried, but only up to 30 along the wish direction, with no friction in the air
Quake II1997Momentumthe move keys push against the speed carried at a tenth of the ground acceleration, up to the full wish speed along the wish direction
Quake III Arena1999Momentumthe move keys push against the speed carried at a tenth of the ground acceleration, up to the full wish speed along the wish direction
Celeste2018Dampedsteering takes 0.65 of the ground's rates, and released, Madeline's speed falls toward 0
Every claim about this mechanic, by game (51)
Super Mario Bros. 1985In the air X_Physics takes the running cap $28 and acceleration $E4 while Mario's speed is $19 or more, and the walking cap $18 with $98 (or $D0 while RunningSpeed is set) below it, whatever B does.Code
LRAir runs ImposeFriction only while Left or Right is held, so in the air a held direction accelerates Mario toward it up to the cap and a released d-pad keeps his speed.Code
Because a jump keeps Mario's take-off facing, steering back slows him at the plain rate until he moves the other way, then at double the rate ($1A0 from a run).Verified
A frame-by-frame model of X_Physics, GetPlayerAnimSpeed, and ImposeFriction reproduces Mario's speed bytes, facing, moving direction, and run timer on every frame of 17 probed traces, walking, running, skidding, crouching, and jumping.Verified
Castlevania 1986Measured in the game, a jump keeps the direction held at take-off, 1 px per frame that way or none, whatever the d-pad does in the air.Verified
Metroid 1986A running jump sets the top speed to $12 (1.125 px/frame). In the air a held direction sets the acceleration toward it; with neither held, a jump still in the plain jump animation loses its horizontal speed, and a somersault keeps its speed and acceleration.Code
In a jump from a standstill, LD055 sets the whole part of Samus's horizontal speed outright every frame, 1 px/frame toward a held direction and 0 with neither held.Code
In a running jump, the air branch of the running handler poses Samus by SamusJmpDsplcmnt, which a jump sets to 0 and each pixel up adds 1 to and each pixel down takes 1 from. Rising at 24 or more (cpy #$18), she somersaults (an_SamusSalto) unless she is firing; falling at less than 24, she takes the plain jump pose (an_SamusJump), as she does from the running pose. The pose decides whether letting go of the d-pad stops her (metroid-samus/air-run).Code
Mega Man 1987In the air the jumping animation isn't in the speed lookup's table, so each frame sets Mega Man's speed to 1.3125 px/frame ($01.$50) toward a held Left or Right and to 0 with neither; a direction pressed fresh in the air first sets the first step's animation, so that one frame moves 0.125 px/frame.Verified
Castlevania II: Simon's Quest 1987In Simon's Quest the take-off sets Simon's horizontal speed to 1 px/frame toward a held Left or Right, or 0, and the jumping state reads only B, for the whip, so the jump keeps its direction as in Castlevania.Code
Mega Man 2 1988Each airborne frame, _run_megaman_jumping zeroes Mega Man's horizontal speed, then sets it to the jumping state's 1.3125 px/frame ($01.$50) toward a held Left or Right.Code
Measured in the game, Mega Man moves 1.3125 px/frame in the air, turns around on the frame the other direction is pressed, and stops on the frame the d-pad is let go.Verified
Super Mario Bros. 3 1988With neither Left nor Right held, Mario's horizontal speed gets friction only on the ground; in the air the routine returns and he keeps his speed.Code
Castlevania III: Dracula's Curse 1989In Dracula's Curse the take-off shared by every character but Grant (the state tables the disassembly labels Trevor's, Sypha's, and Alucard's all point at it; Grant's has its own) sets the horizontal speed to 1 px/frame toward a held Left or Right, or 0, as in Castlevania.Code
In the air, a held Left or Right sets Grant's horizontal speed to 1 px/frame that way and turns him; with neither held the code leaves the speed as it was, so he keeps moving, until a wall stops him.Code
Prince of Persia 1989GENCTRL, which turns the player's input into moves, picks its branch by the frame the kid shows (standing, starting a run, running, starting a jump up, hanging, turning, or crouching). The frames of the standing and running jumps, 16 to 44, match none of them, and it returns without reading the joystick, so a jump can't be steered once it starts.Code
Super Mario World 1990In the air with neither Left nor Right held, Mario's horizontal routine returns before friction, so he keeps his speed.Code
Holding a direction in the air accelerates Mario by MarioAccel_'s 1.5/16 px/frame each frame up to his top speed, or by 5/16 (2.5/16 without Y) while he still moves the other way.Code
Measured in the game, a running jump keeps 36/16 px/frame when Right is let go, and turning Left in the air reverses it within 8 frames and reaches 36/16 the other way 29 frames after the turn.Verified
In the air Mario's horizontal speed follows the ground's code except that a released d-pad keeps the speed and the cap index never reaches 2 unless he left at full P-meter; a frame-by-frame model of these rules reproduces every probed frame.Verified
Measured frame by frame, a running jump turned with Left and Y held drops from 35/16 px/frame to exactly 0 in 7 frames of −5/16, then gains −1.5/16 a frame and reads −36/16 on the 31st frame of the turn.Verified
Mega Man 4 1991Every frame in the air the d-pad alone sets where Mega Man moves: the air routine copies the held Left or Right into his direction and moves him by his X speed that way, 1.30 px/frame, and with neither held he doesn't move. He turns at once, and nothing carries over from the ground.Code
Metroid II: Return of Samus 1991In a plain jump, poseFunc_jump moves Samus 1 px each frame toward a held direction, and not at all when neither is held.Code
Sonic the Hedgehog 1991In the running game, on flat ground, Sonic's top running speed, son_maxspeed, is $600 (6 px/frame): holding the d-pad his ground speed stops there, and in the air the d-pad caps his X speed there too.Verified
In the running game, on flat ground, holding forward above the top speed pulls Sonic's speed down to it in one frame, on the ground and in the air, because Sonic_MoveRight and the air steering cap after adding without first checking whether he is already faster.Verified
In the running game, on flat ground, after a jump from a roll the d-pad does nothing in the air, neither steering Sonic nor turning him, and air drag still runs.Verified
In the running game, in the air the d-pad adds $18, twice the ground acceleration, to Sonic's X speed each frame either way, with no separate deceleration, up to the top speed.Verified
In the running game, while Sonic rises no faster than 4 px/frame (Y speed −$400 to −1 before that frame's gravity), each frame subtracts his X speed shifted right 5 bits, about 1/32: an X speed of $400 written in by the probe was dragged at Y speeds −$400 and −1, and not at −$401 or 0.Verified
In the running game, on flat ground, a held jump from top speed with the d-pad released is dragged on 18 frames and lands at $369 (3.41 px/frame) to the right but −$35E to the left.Verified
A frame-by-frame model of Sonic_MdNormal, Sonic_MdRoll, and Sonic_MdJump2 on flat ground matches Sonic the Hedgehog itself, run in MAME on a floor built of Green Hill Act 1's blocks, on every frame of the movement lab's flat-ground presets and stress scripts and of 100 random input scripts.Verified
Super Castlevania IV 1991In Super Castlevania IV's jump a held Left or Right adds 0.25 px/frame² toward that side, up to 1.25 px/frame, and with neither held the speed is left as it is, where Castlevania's take-off fixes the direction for the whole jump.Code
Mega Man 5 1992Every frame in the air the d-pad alone sets where Mega Man moves: the air routine copies the held Left or Right into his direction and moves him by his X speed that way, 1.30 px/frame, and with neither held he doesn't move. He turns at once, and nothing carries over from the ground.Code
Sonic the Hedgehog 2 1992In the air Sonic_ChgJumpDir adds twice the acceleration, $18, either way and still caps at the top speed even when Sonic was already faster, as Sonic 1 does.Code
Sonic 2 keeps Sonic 1's air drag; Sonic_JumpPeakDecelerate is instruction for instruction Sonic 1's Sonic_AirDrag, taking X speed shifted right 5 bits while Y speed is from −$400 to −1.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
A jump from a roll sets the roll-jump flag, and while it's set Sonic_ChgJumpDir skips the d-pad, as in Sonic 1; the drag near the top of the jump still applies.Code
Mega Man 6 1993In the air the d-pad sets his horizontal speed from the same table at $8BEA each frame, 1.30 px/frame or 0, and clears any carried momentum, except when his surface ($A7) is $15: then the air loop runs the momentum routine code_388B0F instead, and the carried speed stays (momentum-surfaces). On a ladder, Up or Down moves him along it at the same 1.30 px/frame.Code
Sonic 3 & Knuckles 1994In the air Sonic_ChgJumpDir still adds $18 a frame, but a Sonic already faster than the top speed keeps his speed; Sonic 1 and Sonic 2 pulled him down to it.Code
Sonic 3 & Knuckles keeps Sonic 1's air drag, X speed less X speed shifted right 5 bits while Y speed is from −$400 to −1.Code
A jump from a roll sets the roll-jump flag, and while it is set Sonic_ChgJumpDir skips the d-pad: no steering and no turning, though the air drag still runs. Landing clears it, as Sonic 2's Sonic_ResetOnFloor does; unlike Sonic 2, whose Sonic_JumpHeight only caps the rise, a jump press once his rise is no faster than 4 px/frame (2 underwater) clears it too (insta-shield-motion), as in Sonic 3 alone.Code
A jump press during a jump, once the rise is no faster than 4 px/frame (2 underwater) and before any shield move or insta-shield this jump, clears the roll-jump flag before the shield checks, so a roll jump gets its steering back. With no shield, not invincible, not Super, and short of turning Super (50 rings, Update_HUD_timer nonzero, and seven Super Emeralds, or seven Chaos Emeralds with Emeralds_converted_flag clear), the insta-shield follows and doesn't change his position or speed; with an elemental shield its move follows (shield-moves). Later presses do nothing until he lands.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
On flat ground, Sonic 3 & Knuckles changes when Sonic rolls and stands: Down curls him only from $100, not Sonic 2's $80, and, off objects, crouches him while he is still moving slower, where Sonic 2 crouched only from a standstill; a roll stands up under $80 with that speed kept, where Sonic 2's rolls on to 0 (both outside pinball mode). In the air he keeps a speed above the top while steering, where Sonic 2 pulled him down to it; a second press after a roll jump gives back steering, which Sonic 2's jump never did; a wall push moving sideways no longer ends the frame's checks; and a head 20 px into a ceiling moving left is pushed off a right wall instead, a check Sonic 2 lacks. Standing over a drop, not Super, he turns toward it at once, where Sonic 2 turned only if the floor 6 px the other way was also low.Code
Super Metroid 1994In a normal jump with no acceleration mode set, holding neither left nor right sets Samus's base horizontal speed to 0 that frame; held, the speed table's jumping row accelerates her at 0.75 px/frame² to 1.25 px/frame.Code
Castlevania: Symphony of the Night 1997In Symphony of the Night's jump a held direction sets Alucard's horizontal speed to 1.5 px/frame that way at once, turning him if needed, and every jumping frame first slows it by 1/16 px/frame toward 0, so a released d-pad fades the speed out; Castlevania's take-off fixes Simon's direction for the whole jump.Code
Celeste 2018MaxRun, Madeline's top running speed, is 90 px/s, and the same limit applies in the air.Code
Above 90 px/s with the d-pad held the same way, Madeline slows toward 90 px/s at RunReduce, 400 px/s², instead of the full 1000.Code
In the air both running rates are multiplied by AirMult, 0.65, so steering, stopping, and turning take 650 px/s², and slowing from above the cap 260 px/s².Code
Simulating the code, Madeline reaches 90 px/s from a standstill in 6 updates on the ground and 9 in the air, and needs 11 and 17 to turn from 90 to −90 px/s.Code
Simulating the code, a running jump leaves at 130 px/s and slows back to 90 px/s in 10 airborne updates with the d-pad held; a jump from a standstill with the d-pad held leaves at 56.67 px/s.Code
A frame-by-frame model of Player.Update and NormalUpdate on flat ground matches a statement-by-statement float32 simulation of the released code on every frame of 300 random input scripts, for both delta-time steps.Code

References

  1. ^In Simon's standing state, the frame A goes down starts a jump, unless a block is over his head (ceiling-takeoff); the take-off code points his arc at a fixed table and copies the d-pad's Left and Right bits into his direction.Code“Castlevania (USA) (Rev 1)”revised
    How we know

    In the cartridge (“Castlevania (USA) (Rev 1)”): bank 6 $9366-$9381, the dispatch on Simon's state; state 0 (standing) runs $9380, state 1 (jumping) $9482; bank 6 $9401-$943B: A pressed this frame, a ceiling check, the table pointer from $9B8D, state 1, then direction = facing | (held Right/Left). We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-21.

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

  2. ^ abcMeasured in the game, a jump keeps the direction held at take-off, 1 px per frame that way or none, whatever the d-pad does in the air.Verified“Castlevania (USA) (Rev 1)”
    How we know

    In the cartridge (“Castlevania (USA) (Rev 1)”): bank 6 $9401-$943B; take-off copies the held Right/Left bits into Simon's direction; bank 6 $9479-$9481: horizontal speed $3D/$3E = 0/1, 1 px per frame; bank 6 $948E-$9496, where the jumping state sets that speed and moves Simon each frame. We don't reproduce the bytes.

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on Castlevania (USA) (Rev 1) (SHA-1 4e3ef47de86a…). 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-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  3. ^ abIn Simon's Quest the take-off sets Simon's horizontal speed to 1 px/frame toward a held Left or Right, or 0, and the jumping state reads only B, for the whip, so the jump keeps its direction as in Castlevania.Code“Castlevania II - Simon's Quest (USA)” · “Castlevania (USA) (Rev 1)”
    How we know

    In the cartridge (“Castlevania II - Simon's Quest (USA)”): bank 3 $8905-$8928: held Right ($F7 bit 0) sets X speed $6D.$6C = 1.0, Left −1.0 and facing left, neither 0; bank 3 $89CD-$8A0D, the jumping state: a new B press ($F5 AND $40) goes to the whip; the rest is the vertical speed. We don't reproduce the bytes.

    In the cartridge (“Castlevania (USA) (Rev 1)”): Castlevania's take-off copying the held Left and Right into Simon's direction (castlevania/jump-start). We don't reproduce the bytes.

    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

  4. ^ abIn Dracula's Curse the take-off shared by every character but Grant (the state tables the disassembly labels Trevor's, Sypha's, and Alucard's all point at it; Grant's has its own) sets the horizontal speed to 1 px/frame toward a held Left or Right, or 0, as in Castlevania.Codevinheim3/castlevania3-disasm · “Castlevania (USA) (Rev 1)”
    How we know
    3740playerState06_jumpStart_exceptGrant:
    ⋮
    3743B28_1622:		lda wJoy1ButtonsPressed			; a5 28
    3744B28_1624:		sta $10			; 85 10
    ⋮
    3753B28_1637:		lda $10			; a5 10
    3754B28_1639:		lsr a			; 4a
    3755B28_163a:		bcs B28_1644 ; b0 08
    ⋮
    3757B28_163c:		lsr a			; 4a
    3758B28_163d:		bcs B28_164f ; b0 10
    ⋮
    3761B28_163f:		lda #$00		; a9 00
    3762B28_1641:		tay				; a8 
    3763B28_1642:		beq B28_1658 ; f0 14
    ⋮
    3768B28_1649:		lda #$01		; a9 01
    ⋮
    
    code/playerStateProcessing_b1c.s lines 3740–3781 at 3272648 · upstream ↗
    345@setButtonVars:
    346	lda wTempJoy1ButtonsPressedPass1, x
    347	tay
    ⋮
    355	sty wJoy1ButtonsPressed, x
    
    code/bank1f.s lines 344–356 at 3272648 · upstream ↗
    1826B28_0a91:		ldy wCurrPlayer.w		; ac 4e 05
    ⋮
    1836B28_0a9c:		jsr processAlucardState		; 20 a8 a5
    ⋮
    1840B28_0aa2:		jsr processTrevorState		; 20 7b 93
    ⋮
    1849B28_0ab0:		jsr processSyphaState		; 20 fc 9b
    ⋮
    1853B28_0ab6:		jsr processGrantState		; 20 3b 9c
    
    code/playerStateProcessing_b1c.s lines 1826–1854 at 3272648 · upstream ↗
    3242processTrevorState:
    ⋮
    3249	.dw playerState06_jumpStart_exceptGrant
    
    code/playerStateProcessing_b1c.s lines 3242–3249 at 3272648 · upstream ↗
    4751processSyphaState:
    ⋮
    4758	.dw playerState06_jumpStart_exceptGrant
    
    code/playerStateProcessing_b1c.s lines 4751–4758 at 3272648 · upstream ↗
    918processAlucardState:
    ⋮
    926	.dw playerState06_jumpStart_exceptGrant
    
    code/playerStateProcessing_b1d.s lines 918–926 at 3272648 · upstream ↗
    4784processGrantState:
    ⋮
    4791	.dw playerState06_jumpStart_grant
    
    code/playerStateProcessing_b1c.s lines 4784–4791 at 3272648 · upstream ↗

    In the cartridge (“Castlevania (USA) (Rev 1)”): Castlevania's take-off copying the held Left and Right into Simon's direction (castlevania/jump-start). We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-25.

    Checked by a second AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-25.

    In the claim ledger

  5. ^ abIn the air, a held Left or Right sets Grant's horizontal speed to 1 px/frame that way and turns him; with neither held the code leaves the speed as it was, so he keeps moving, until a wall stops him.Codevinheim3/castlevania3-disasm
    How we know
    5156playerState06_jumpStart_grant:
    
    code/playerStateProcessing_b1c.s lines 5156–5172 at 3272648 · upstream ↗
    5261playerState08_jumping_0c_grant:
    ⋮
    5292; left held
    ⋮
    5309; right held
    ⋮
    5326; nothing above pressed/held
    
    code/playerStateProcessing_b1c.s lines 5261–5329 at 3272648 · upstream ↗
    5344; nothing above pressed/held
    
    code/playerStateProcessing_b1c.s lines 5344–5380 at 3272648 · upstream ↗
    sta wEntityHorizSpeed.w
    code/playerStateProcessing_b1d.s#L1-L4 · 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. ^Off ice, Mega Man never accelerates. Each frame his animation picks a speed from special_object_xcoord_speed_table, 0 standing, 0.125 px/frame on the first step, 1.375 running, 0.5 sliding to a stop, 0 landing, and 0.5625 when hit; any other animation, such as the jump, moves at 1.3125 with a direction held and 0 without.Codelsmmega/mm1revised
    How we know
    1_ice_tsa_move:
    2	LDY #$00
    3	LDA aobject_pointer
    4	LDX #$08
    ⋮
    6@loop:
    7	CMP @special_object_id_table, X
    8	BEQ @yes
    9	DEX
    10	BPL @loop
    11	LDA z:zjoy1_pressed
    12	AND #left_button | right_button
    13	BEQ @regular
    ⋮
    
    engine/ice_tsa.asm lines 1–22 at b606a84 · upstream ↗
    146@special_object_id_table:
    147	.BYTE $00
    148	.BYTE $03
    149	.BYTE $06
    150	.BYTE $0C
    151	.BYTE $0F
    152	.BYTE $12
    153	.BYTE $13
    154	.BYTE $14
    155	.BYTE $6E
    ⋮
    157@special_object_id_index_xcoord_speed_table:
    158	.BYTE $00
    ⋮
    
    engine/ice_tsa.asm lines 146–166 at b606a84 · upstream ↗
    1special_object_xcoord_speed_table:
    2;fraction, integer
    3	.BYTE $00 | $00
    4	.BYTE $00 | $20
    5	.BYTE $01 | $20
    6	.BYTE $00 | $80
    7	.BYTE $01 | $00
    8	.BYTE $04 | $00
    9	.BYTE $05 | $10
    10	.BYTE $01 | $50
    11	.BYTE $01 | $60
    12	.BYTE $00 | $90
    
    data/special_xcoord_speed_table.asm lines 1–12 at b606a84 · upstream ↗
    22_write_special_object_xcoord_speed_continue:
    23	LDA special_object_xcoord_speed_table, Y
    24	PHA
    25	AND #%11110000
    26	STA aobject_xcoord_speed_fraction, X
    27	PLA
    28	AND #%00001111
    29	STA aobject_xcoord_speed, X
    
    home/write_special_object_xcoord_speed.asm lines 22–29 at b606a84 · 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-21.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  7. ^Each airborne frame, _run_megaman_jumping zeroes Mega Man's horizontal speed, then sets it to the jumping state's 1.3125 px/frame ($01.$50) toward a held Left or Right.Codelsmmega/mm2
    How we know
    160_run_megaman_jumping:
    161	JSR _check_shoot_on_ladder
    162	LDA #$00
    163	STA aobject_xcoord_speed_fraction
    164	STA aobject_xcoord_speed
    165	LDA z:zjoy1_pressed
    166	AND #left_button | right_button
    167	BNE @horizontal_jumping
    
    engine/run_megaman.asm lines 160–167 at 94f0bf3 · upstream ↗
    197@horizontal_jumping:
    198	JSR _turn_megaman
    199	JSR _megaman_status_parameter
    
    engine/run_megaman.asm lines 197–199 at 94f0bf3 · upstream ↗
    222megaman_status_xcoord_speed_table:
    ⋮
    228	.BYTE $01
    229	.BYTE $01
    ⋮
    235megaman_status_xcoord_speed_fraction_table:
    ⋮
    241	.BYTE $60
    242	.BYTE $50
    
    engine/turn_megaman.asm lines 222–246 at 94f0bf3 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  8. ^Measured in the game, Mega Man moves 1.3125 px/frame in the air, turns around on the frame the other direction is pressed, and stops on the frame the d-pad is let go.Verifiedlsmmega/mm2revised
    How we know
    162	LDA #$00
    163	STA aobject_xcoord_speed_fraction
    164	STA aobject_xcoord_speed
    165	LDA z:zjoy1_pressed
    166	AND #left_button | right_button
    167	BNE @horizontal_jumping
    ⋮
    192	LDA #$00
    ⋮
    197@horizontal_jumping:
    198	JSR _turn_megaman
    199	JSR _megaman_status_parameter
    
    engine/run_megaman.asm lines 160–202 at 94f0bf3 · upstream ↗
    72_megaman_status_parameter:
    73	LDX z:zmegaman_status
    74	LDA megaman_status_xcoord_speed_table, X
    75	STA aobject_xcoord_speed
    76	LDA megaman_status_xcoord_speed_fraction_table, X
    77	STA aobject_xcoord_speed_fraction
    
    engine/turn_megaman.asm lines 72–77 at 94f0bf3 · upstream ↗
    222megaman_status_xcoord_speed_table:
    ⋮
    228	.BYTE $01
    229	.BYTE $01
    ⋮
    235megaman_status_xcoord_speed_fraction_table:
    ⋮
    241	.BYTE $60
    242	.BYTE $50
    
    engine/turn_megaman.asm lines 222–246 at 94f0bf3 · upstream ↗

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . 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.

    Revised after a check by a second AI model, 2026-10-25.

    In the claim ledger

  9. ^ abcMega Man 3 drops Mega Man 2's slow step speed but keeps a pause. Before each frame's state runs, the prelude sets the speed to $01.$4C (1.30 px/frame) unless he is sliding. From standing, a held direction moves him by it at once and starts the turning animation ($0D); while that animation is on its first frame the ground state doesn't move him, and once it advances he walks at the same 1.30. In the air a held direction moves him at 1.30 on every frame.Codeplasticsmoke/megaman3-disassembly-ca65 · lsmmega/mm2revised
    How we know
    636prelude_check_slide_speed:  lda     ent_xvel ; if X speed whole == $02 (slide speed):
    637        cmp     #$02                    ; slide speed?
    638        bne     prelude_reset_walk_speed ; no → reset to walk speed
    639        lda     player_state            ; load current player state
    640        cmp     #PSTATE_SLIDE           ; check if sliding
    641        beq     prelude_setup_per_frame ; sliding, keep slide speed
    642prelude_reset_walk_speed:  lda     #$4C ; reset walk speed to $01.4C
    643        sta     ent_xvel_sub            ; store walk sub-pixel speed
    644        lda     #$01                    ; walk speed whole = $01
    645        sta     ent_xvel                ; store walk whole speed
    
    src/fixed/game_loop.asm lines 636–645 at 58ca1c3 · upstream ↗
    115player_ground_turning_anim:  lda     #$0D ; OAM $0D = turning animation
    116        jsr     reset_sprite_anim       ; set turning animation
    117        lda     shoot_anim_timer               ; check if shooting
    118        beq     player_ground_move_facing ; not shooting, move facing
    119        jsr     shoot_oam_advance_variant ; update shoot animation variant
    120player_ground_move_facing:  lda     player_facing ; move in facing direction
    121        jmp     player_ground_move_horizontal ; move in facing direction
    ⋮
    125player_ground_walk_handler:  lda     joy1_held ; D-pad L/R held?
    126        and     #$03                    ; mask L/R bits
    127        beq     player_ground_idle      ; no → idle
    128        sta     player_facing           ; update facing direction
    
    src/fixed/player_ground.asm lines 115–128 at 58ca1c3 · upstream ↗
    94        cmp     #$0D                    ; $0D/$0E/$0F = turning/special anims
    95        beq     player_ground_special_anim ; OAM $0D → check if anim complete
    ⋮
    100player_ground_special_anim:  lda     ent_anim_state ; check animation state
    101        bne     player_ground_walk_handler ; → normal walk handler
    102        beq     player_ground_slide_weapon ; anim done → slide/crouch check
    
    src/fixed/player_ground.asm lines 94–102 at 58ca1c3 · upstream ↗
    210        lda     ent_anim_state,x        ; ent_anim_state = current frame index
    211        and     #$7F                    ; (bit 7 preserved)
    212        inc     ent_anim_state,x        ; advance to next frame
    ⋮
    216        lda     #$00                    ; reached end: loop back to frame 0
    217        sta     ent_anim_state,x        ; reset to frame 0
    
    src/fixed/sprites.asm lines 210–217 at 58ca1c3 · upstream ↗
    360player_airborne_walk_shoot:  lda     joy1_held ; D-pad L/R held?
    361        and     #$03                    ; mask L/R bits
    362        beq     player_airborne_shoot_check ; no → skip walk
    363        sta     player_facing           ; update facing direction
    364        jsr     player_ground_move_horizontal ; move L/R with collision
    
    src/fixed/player_ground.asm lines 360–364 at 58ca1c3 · upstream ↗
    259move_sprite_right:  lda     ent_x_sub,x ; load X subpixel position
    260        clc                             ; X subpixel += X subpixel speed
    261        adc     ent_xvel_sub,x          ; add X subpixel velocity
    262        sta     ent_x_sub,x             ; store new X subpixel
    263        lda     ent_x_px,x              ; load X pixel position
    264        adc     ent_xvel,x              ; add X pixel velocity + carry
    265        sta     ent_x_px,x              ; store new X pixel
    
    src/fixed/movement.asm lines 259–265 at 58ca1c3 · upstream ↗
    222megaman_status_xcoord_speed_table:
    223	.BYTE $00
    224	.BYTE $00
    225	.BYTE $00
    226	.BYTE $00
    227	.BYTE $00
    ⋮
    230	.BYTE $00
    231	.BYTE $00
    232	.BYTE $00
    233	.BYTE $00
    ⋮
    235megaman_status_xcoord_speed_fraction_table:
    236	.BYTE $00
    ⋮
    
    engine/turn_megaman.asm lines 222–243 at 94f0bf3 · 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.

    Checked by a second AI model, 2026-10-26.

    In the claim ledger

  10. ^ abIn Symphony of the Night's jump a held direction sets Alucard's horizontal speed to 1.5 px/frame that way at once, turning him if needed, and every jumping frame first slows it by 1/16 px/frame toward 0, so a released d-pad fades the speed out; Castlevania's take-off fixes Simon's direction for the whole jump.CodeXeeynamo/sotn-decomp · “Castlevania (USA) (Rev 1)”
    How we know
    580        DecelerateX(FIX(1.0 / 16));
    ⋮
    597        walkResult = CheckMoveDirection();
    598        if (walkResult != 0) {
    ⋮
    603            SetSpeedX(FIX(1.5));
    
    src/dra/71830.c lines 579–603 at 2be55ee · upstream ↗
    3void DecelerateX(s32 amount) {
    
    src/decelerate.h lines 3–15 at 2be55ee · upstream ↗
    101s32 CheckMoveDirection(void) {
    ⋮
    106        if (g_Player.padPressed & PAD_RIGHT) {
    107            PLAYER.facingLeft = 0;
    ⋮
    114        if (g_Player.padPressed & PAD_RIGHT) {
    
    src/dra/6DF70.c lines 101–115 at 2be55ee · upstream ↗

    In the cartridge (“Castlevania (USA) (Rev 1)”): Castlevania's take-off copying the held Left and Right into Simon's direction (castlevania/jump-start). We don't reproduce the bytes.

    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

  11. ^In a normal jump with no acceleration mode set, holding neither left nor right sets Samus's base horizontal speed to 0 that frame; held, the speed table's jumping row accelerates her at 0.75 px/frame² to 1.25 px/frame.CodeInsaneFirebat/sm_disassembly
    How we know
    LDA.W SamusXAccelerationMode BNE .XMovement LDA.B DP_Controller1Input BIT.W #$0100 BNE .XMovement BIT.W #$0200 BNE .XMovement STZ.B DP_Temp12 STZ.B DP_Temp14 STZ.W SamusXBaseSpeed STZ.W SamusXBaseSubSpeed
    src/bank_90.asm#L2807-L2819 · upstream ↗
    5195;       ________________________________________________________________ X acceleration
    ⋮
    5201    dd wordSwap($00C0*!SPF*$100),wordSwap($0140*!SPF*$100),           wordSwap($0080*!SPF*$100) ; 2: Normal jumping
    
    src/bank_90.asm lines 5195–5201 at 7af131e · 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

  12. ^ abHolding a direction in the air accelerates Mario by MarioAccel_'s 1.5/16 px/frame each frame up to his top speed, or by 5/16 (2.5/16 without Y) while he still moves the other way.CodeSMWDisX
    How we know
    9699    dw $FE80,$FE80,$0180,$0180                ;!
    
    bank_00.asm line 9699 at 30643c7 · upstream ↗
    9717    dw $FD80,$FB00,$0280,$0500                ;!
    
    bank_00.asm line 9717 at 30643c7 · upstream ↗
    10061    LDA.B PlayerXSpeed+1
    10062    BEQ CODE_00D713
    10063    EOR.W MarioAccel_+1,X
    10064    BPL CODE_00D713
    ⋮
    10072  + TXA
    10073    CLC
    10074    ADC.B #$90
    10075    TAX
    
    bank_00.asm lines 10061–10075 at 30643c7 · upstream ↗
    10107CODE_00D742:
    10108    LDA.B PlayerXSpeed+1
    10109    SEC
    10110    SBC.W DATA_00D535,Y
    ⋮
    10115    LDA.W MarioAccel_,X
    
    bank_00.asm lines 10107–10123 at 30643c7 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  13. ^In the air with neither Left nor Right held, Mario's horizontal routine returns before friction, so he keeps his speed.CodeSMWDisX
    How we know
    9998    LDA.B byetudlrHold
    9999    AND.B #$03
    10000    BNE CODE_00D6B1
    
    bank_00.asm lines 9998–10000 at 30643c7 · upstream ↗
    10021  + JMP CODE_00D764
    
    bank_00.asm line 10021 at 30643c7 · upstream ↗
    10125CODE_00D764:
    10126    JSR CODE_00D968
    10127    LDA.B PlayerInAir
    10128    BNE Return00D7A4
    
    bank_00.asm lines 10125–10128 at 30643c7 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  14. ^ abIn Super Castlevania IV's jump a held Left or Right adds 0.25 px/frame² toward that side, up to 1.25 px/frame, and with neither held the speed is left as it is, where Castlevania's take-off fixes the direction for the whole jump.Code“Super Castlevania IV (USA)” · “Castlevania (USA) (Rev 1)”
    How we know

    In the cartridge (“Super Castlevania IV (USA)”): $00:A3FA-$A409, state 4 calling $A8DE each frame; $00:A8DE-$A94C: Right held adds $0000.$4000 to X speed $055A.$0558, capped at 1.25; Left adds $FFFF.$C000, capped at −1.25; neither, return. We don't reproduce the bytes.

    In the cartridge (“Castlevania (USA) (Rev 1)”): Castlevania's take-off copying the held Left and Right into Simon's direction (castlevania/jump-start). We don't reproduce the bytes.

    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

  15. ^ abIn the air Sonic_ChgJumpDir adds twice the acceleration, $18, either way and still caps at the top speed even when Sonic was already faster, as Sonic 1 does.Codesonicretro/s2disasm · sonicretro/s1disasmrevised
    How we know
    37205	move.w	(Sonic_acceleration).w,d5
    37206	asl.w	#1,d5
    ⋮
    37219	move.w	d1,d0	; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)
    ⋮
    37228	move.w	d6,d0	; limit speed in air going right, even if Sonic was already going faster (speed limit/cap)
    
    s2.asm lines 37204–37228 at 4ef457c · upstream ↗
    956		move.w	d1,d0					; cap leftward X-speed to maximum
    ⋮
    966		move.w	d6,d0					; cap rightward X-speed to maximum
    
    _incObj/01 Sonic.asm lines 940–966 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.

    In the claim ledger

  16. ^ abSonic 2 keeps Sonic 1's air drag; Sonic_JumpPeakDecelerate is instruction for instruction Sonic 1's Sonic_AirDrag, taking X speed shifted right 5 bits while Y speed is from −$400 to −1.Codesonicretro/s2disasm · sonicretro/s1disasm
    How we know
    37242	cmpi.w	#-$400,y_vel(a0)	; is Sonic moving faster than -$400 upwards?
    ⋮
    37246	asr.w	#5,d1		; d1 = x_velocity / 32
    ⋮
    37251	sub.w	d1,d0	; reduce x velocity by d1
    ⋮
    37260	sub.w	d1,d0	; reduce x velocity by d1
    
    s2.asm lines 37241–37264 at 4ef457c · upstream ↗
    987		cmpi.w	#-$400,obVelY(a0)			; is Sonic moving faster than -$400 upwards?
    ⋮
    992		asr.w	#5,d1					; divide that copy by $20
    
    _incObj/01 Sonic.asm lines 986–1013 at 15dfa3a · 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

  17. ^ abIn the air Sonic_ChgJumpDir still adds $18 a frame, but a Sonic already faster than the top speed keeps his speed; Sonic 1 and Sonic 2 pulled him down to it.Codesonicretro/skdisasm · sonicretro/s2disasm · sonicretro/s1disasmrevised
    How we know
    23134		sub.w	d5,d0	; add acceleration to the left
    ⋮
    23139		add.w	d5,d0		; remove this frame's acceleration change
    23140		cmp.w	d1,d0		; compare speed with top speed
    23141		ble.s	loc_11682	; if speed was already greater than the maximum, branch
    23142		move.w	d1,d0
    
    sonic3k.asm lines 23129–23155 at 73de97c · upstream ↗
    20850		add.w	d5,d0		; remove this frame's acceleration change
    20851		cmp.w	d1,d0		; compare speed with top speed
    20852		ble.s	loc_126F2	; if speed was already greater than the maximum, branch
    
    s3.asm lines 20845–20866 at 73de97c · upstream ↗
    37219	move.w	d1,d0	; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)
    
    s2.asm lines 37214–37219 at 4ef457c · upstream ↗
    951		sub.w	d5,d0					; increase leftward movement speed
    ⋮
    954		cmp.w	d1,d0					; is new speed exceeding maximum?
    955		bgt.s	.notleft				; if not, branch
    956		move.w	d1,d0					; cap leftward X-speed to maximum
    
    _incObj/01 Sonic.asm lines 951–956 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.

    In the claim ledger

  18. ^Sonic 3 & Knuckles keeps Sonic 1's air drag, X speed less X speed shifted right 5 bits while Y speed is from −$400 to −1.Codesonicretro/skdisasm · sonicretro/s1disasmrevised
    How we know
    23170		cmpi.w	#-$400,y_vel(a0)	; is Sonic moving faster than -$400 upwards?
    ⋮
    23174		asr.w	#5,d1		; d1 = x_velocity / 32
    ⋮
    23178		sub.w	d1,d0	; reduce x velocity by d1
    ⋮
    23188		sub.w	d1,d0	; reduce x velocity by d1
    
    sonic3k.asm lines 23169–23193 at 73de97c · upstream ↗
    987		cmpi.w	#-$400,obVelY(a0)			; is Sonic moving faster than -$400 upwards?
    ⋮
    992		asr.w	#5,d1					; divide that copy by $20
    ⋮
    995		sub.w	d1,d0					; slightly reduce speed (air drag)
    
    _incObj/01 Sonic.asm lines 986–995 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.

    In the claim ledger

  19. ^ abIn the air both running rates are multiplied by AirMult, 0.65, so steering, stopping, and turning take 650 px/s², and slowing from above the cap 260 px/s².CodeNoelFB/Celeste
    How we know
    33        private const float AirMult = .65f;
    
    Source/Player/Player.cs line 33 at 1b0ce45 · upstream ↗
    2884                float mult = onGround ? 1 : AirMult;
    
    Source/Player/Player.cs line 2884 at 1b0ce45 · 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

  20. ^GENCTRL, which turns the player's input into moves, picks its branch by the frame the kid shows (standing, starting a run, running, starting a jump up, hanging, turning, or crouching). The frames of the standing and running jumps, 16 to 44, match none of them, and it returns without reading the joystick, so a jump can't be steered once it starts.Codejmechner/Prince-of-Persia-Apple-II
    How we know
    689:cont ldx CharPosn ;previous frame #
    ⋮
    691 cpx #15
    692 beq :standing
    ⋮
    694 cpx #48
    695 beq :turning
    ⋮
    697 cpx #50
    698 bcc :0
    699 cpx #53
    700 bcc :standing ;turn7-8-9/crouch
    ⋮
    702 cpx #4
    703 bcc :starting ;run4-5-6
    ⋮
    705 cpx #67
    ⋮
    
    01 POP Source/Source/CTRL.S lines 689–718 at 2524355 · upstream ↗
    720:1 cpx #109 ;crouching?
    721 beq :crouching
    ⋮
    723]rts rts
    
    01 POP Source/Source/CTRL.S lines 720–723 at 2524355 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  21. ^ abIn the air, Quake III's PM_AirMove runs friction (no ground friction, which needs the walking flag), builds a flat wish velocity, and calls the same PM_Accelerate as the ground with pm_airaccelerate 1: the push is 1 × step time × wish speed (2.56 units/s per 8 ms step at 320), and it stops only when the velocity's component along the wish direction reaches the full wish speed. Quake's air rule is the reverse: a push ten times as strong (10 × 320 × frame time), cut off when that component reaches 30 (quake/air-accelerate). An #else branch left out by #if 1 would push the velocity toward the wish velocity instead, commented "proper way (avoids strafe jump maxspeed bug), but feels bad". The figures leave out the rounding trap_SnapVector applies to the velocity after each step, engine code the atlas hasn't read.Codeid-Software/Quake-III-Arena · id-Software/Quakerevised
    How we know
    40float	pm_airaccelerate = 1.0f;
    
    code/game/bg_pmove.c line 40 at dbe4ddb · upstream ↗
    610	PM_Friction();
    ⋮
    628		wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
    ⋮
    630	wishvel[2] = 0;
    ⋮
    633	wishspeed = VectorNormalize(wishdir);
    634	wishspeed *= scale;
    ⋮
    636	// not on ground, so little effect on velocity
    637	PM_Accelerate (wishdir, wishspeed, pm_airaccelerate);
    
    code/game/bg_pmove.c lines 610–637 at dbe4ddb · upstream ↗
    197		if ( pml.walking && !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) {
    
    code/game/bg_pmove.c line 197 at dbe4ddb · upstream ↗
    2015	trap_SnapVector( pm->ps->velocity );
    
    code/game/bg_pmove.c line 2015 at dbe4ddb · upstream ↗
    240static void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel ) {
    241#if 1
    ⋮
    246	currentspeed = DotProduct (pm->ps->velocity, wishdir);
    247	addspeed = wishspeed - currentspeed;
    248	if (addspeed <= 0) {
    249		return;
    ⋮
    251	accelspeed = accel*pml.frametime*wishspeed;
    252	if (accelspeed > addspeed) {
    253		accelspeed = addspeed;
    ⋮
    259#else
    260	// proper way (avoids strafe jump maxspeed bug), but feels bad
    ⋮
    267	VectorSubtract( wishVelocity, pm->ps->velocity, pushDir );
    ⋮
    
    code/game/bg_pmove.c lines 240–275 at dbe4ddb · upstream ↗
    212	wishspd = VectorNormalize (wishveloc);
    213	if (wishspd > 30)
    214		wishspd = 30;
    215	currentspeed = DotProduct (velocity, wishveloc);
    216	addspeed = wishspd - currentspeed;
    ⋮
    220	accelspeed = sv_accelerate.value*wishspeed * host_frametime;
    221	if (accelspeed > addspeed)
    222		accelspeed = addspeed;
    
    WinQuake/sv_user.c lines 212–224 at bf4ac42 · 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

  22. ^Quake III's PM_WalkMove runs friction and then PM_Accelerate with pm_accelerate 10, which is Quake's rule (Quake III's PM_Accelerate comment says "q2 style"): if the speed along the wish direction is under the wish speed, it adds 10 × step time × wish speed along that direction, no more than the shortfall. The full wish speed is the player's speed, set before each move from g_speed (320, × 1.3 with Haste). Computed, not measured: since 10 outpaces the friction of 6, a run settles at exactly 320, as Quake's does at 10 against 4; at 8 ms steps it reaches 320 from rest in 19 steps (0.15 s) and stops from 320 in 45 (0.36 s). These figures leave out the rounding trap_SnapVector applies to the velocity after each step, engine code the atlas hasn't read.Codeid-Software/Quake-III-Arena · id-Software/Quakerevised
    How we know
    39float	pm_accelerate = 10.0f;
    
    code/game/bg_pmove.c line 39 at dbe4ddb · upstream ↗
    240static void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel ) {
    241#if 1
    242	// q2 style
    ⋮
    246	currentspeed = DotProduct (pm->ps->velocity, wishdir);
    247	addspeed = wishspeed - currentspeed;
    248	if (addspeed <= 0) {
    249		return;
    ⋮
    251	accelspeed = accel*pml.frametime*wishspeed;
    252	if (accelspeed > addspeed) {
    253		accelspeed = addspeed;
    ⋮
    257		pm->ps->velocity[i] += accelspeed*wishdir[i];	
    
    code/game/bg_pmove.c lines 240–258 at dbe4ddb · upstream ↗
    720	PM_Friction ();
    
    code/game/bg_pmove.c line 720 at dbe4ddb · upstream ↗
    772	if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) {
    773		accelerate = pm_airaccelerate;
    774	} else {
    775		accelerate = pm_accelerate;
    ⋮
    778	PM_Accelerate (wishdir, wishspeed, accelerate);
    
    code/game/bg_pmove.c lines 772–778 at dbe4ddb · upstream ↗
    142	{ &g_speed, "g_speed", "320", 0, 0, qtrue  },
    
    code/game/g_main.c line 142 at dbe4ddb · upstream ↗
    2015	trap_SnapVector( pm->ps->velocity );
    
    code/game/bg_pmove.c line 2015 at dbe4ddb · upstream ↗
    843	client->ps.speed = g_speed.value;
    ⋮
    851	if ( client->ps.powerups[PW_HASTE] ) {
    852		client->ps.speed *= 1.3;
    
    code/game/g_active.c lines 843–853 at dbe4ddb · upstream ↗
    195	currentspeed = DotProduct (velocity, wishdir);
    196	addspeed = wishspeed - currentspeed;
    ⋮
    199	accelspeed = sv_accelerate.value*host_frametime*wishspeed;
    200	if (accelspeed > addspeed)
    201		accelspeed = addspeed;
    
    WinQuake/sv_user.c lines 195–201 at bf4ac42 · upstream ↗
    167cvar_t	sv_maxspeed = {"sv_maxspeed", "320", false, true};
    168cvar_t	sv_accelerate = {"sv_accelerate", "10"};
    
    WinQuake/sv_user.c lines 167–168 at bf4ac42 · 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

  23. ^In the running game, in the air the d-pad adds $18, twice the ground acceleration, to Sonic's X speed each frame either way, with no separate deceleration, up to the top speed.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Air State”
    How we know
    939Sonic_JumpDirection:
    940		move.w	(v_sonspeedmax).w,d6			; get Sonic's current top speed
    941		move.w	(v_sonspeedacc).w,d5			; get Sonic's current acceleration...
    942		asl.w	#1,d5					; ...doubled
    ⋮
    951		sub.w	d5,d0					; increase leftward movement speed
    ⋮
    963		add.w	d5,d0					; increase rightward movement speed
    ⋮
    970		move.w	d0,obVelX(a0)				; update Sonic's horizontal speed
    
    _incObj/01 Sonic.asm lines 939–970 at 15dfa3a · upstream ↗
    there is no distinction for deceleration in the air, either
    Air Acceleration · 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.

    In the claim ledger

  24. ^ abcIn the running game, while Sonic rises no faster than 4 px/frame (Y speed −$400 to −1 before that frame's gravity), each frame subtracts his X speed shifted right 5 bits, about 1/32: an X speed of $400 written in by the probe was dragged at Y speeds −$400 and −1, and not at −$401 or 0.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Air State”
    How we know
    986Sonic_AirDrag:
    987		cmpi.w	#-$400,obVelY(a0)			; is Sonic moving faster than -$400 upwards?
    988		blo.s	.return					; if yes, branch (skip air drag)
    ⋮
    992		asr.w	#5,d1					; divide that copy by $20
    993		beq.s	.return					; if result is zero, branch
    994		bmi.s	.jumpingleftward			; if speed is negative, branch
    995		sub.w	d1,d0					; slightly reduce speed (air drag)
    ⋮
    1007		sub.w	d1,d0					; slightly reduce speed (air drag)
    
    _incObj/01 Sonic.asm lines 986–1013 at 15dfa3a · upstream ↗
    Y Speed must be negative and Y Speed must be more than -4
    Air Drag · 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.

    In the claim ledger

  25. ^In the air Mario's horizontal speed follows the ground's code except that a released d-pad keeps the speed and the cap index never reaches 2 unless he left at full P-meter; a frame-by-frame model of these rules reproduces every probed frame.VerifiedSMWDisXrevised
    How we know
    10061    LDA.B PlayerXSpeed+1
    10062    BEQ CODE_00D713
    10063    EOR.W MarioAccel_+1,X
    10064    BPL CODE_00D713
    ⋮
    10073    CLC
    10074    ADC.B #$90
    10075    TAX
    
    bank_00.asm lines 10061–10075 at 30643c7 · upstream ↗
    10088    BMI CODE_00D737
    10089    LDA.B PlayerInAir
    10090    BNE CODE_00D732
    ⋮
    10095CODE_00D732:
    10096    CMP.B #$0C
    10097    BNE CODE_00D737
    10098CODE_00D736:
    10099    INY
    
    bank_00.asm lines 10083–10101 at 30643c7 · upstream ↗
    10108    LDA.B PlayerXSpeed+1
    10109    SEC
    10110    SBC.W DATA_00D535,Y
    10111    BEQ CODE_00D76B
    10112    EOR.W DATA_00D535,Y
    10113    BPL CODE_00D76B
    ⋮
    10122    ADC.B PlayerXSpeed
    
    bank_00.asm lines 10107–10123 at 30643c7 · upstream ↗
    10126    JSR CODE_00D968
    10127    LDA.B PlayerInAir
    10128    BNE Return00D7A4
    
    bank_00.asm lines 10125–10128 at 30643c7 · upstream ↗
    9983    LDA.B #$0B
    9984    LDY.W PlayerPMeter
    9985    CPY.B #con($70,$70,$70,$40,$68)
    9986    BCC CODE_00D67D
    ⋮
    9992CODE_00D67D:
    9993    STA.B PlayerInAir
    
    bank_00.asm lines 9983–9993 at 30643c7 · upstream ↗

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . 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.

    Revised after a check by a second AI model, 2026-10-25.

    In the claim ledger

  26. ^LRAir runs ImposeFriction only while Left or Right is held, so in the air a held direction accelerates Mario toward it up to the cap and a released d-pad keeps his speed.CodeXkeeper0/smb1
    How we know
    4783LRAir:
    4784	LDA Left_Right_Buttons                       ; check left/right controller bits (check for jumping/falling)
    4785	BEQ JSMove                                   ; if not pressing any, skip
    4786	JSR ImposeFriction                           ; otherwise process horizontal movement
    4787JSMove:
    4788	JSR MovePlayerHorizontally                   ; do a sub to move player horizontally
    
    src/prg.asm lines 4783–4788 at 1cc3c92 · upstream ↗
    4748FallingSub:
    4749	LDA VerticalForceDown
    4750	STA VerticalForce                            ; dump vertical movement force for falling into main one
    4751	JMP LRAir                                    ; movement force, then skip ahead to process left/right movement
    
    src/prg.asm lines 4748–4751 at 1cc3c92 · upstream ↗

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.

    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

  27. ^On the ground OnGroundStateSub turns Mario toward a held Left or Right before friction runs; the jumping and falling routines change his facing only while he swims.CodeXkeeper0/smb1
    How we know
    4735OnGroundStateSub:
    4736	JSR GetPlayerAnimSpeed                       ; do a sub to set animation frame timing
    4737	LDA Left_Right_Buttons
    4738	BEQ GndMove                                  ; if left/right controller bits not set, skip instruction
    4739	STA PlayerFacingDir                          ; otherwise set new facing direction
    4740GndMove:
    
    src/prg.asm lines 4735–4740 at 1cc3c92 · upstream ↗
    4771	LDA SwimmingFlag                             ; if swimming flag not set,
    4772	BEQ LRAir                                    ; branch ahead to last part
    ⋮
    4779LRWater:
    4780	LDA Left_Right_Buttons                       ; check left/right controller bits (check for swimming)
    4781	BEQ LRAir                                    ; if not pressing any, skip
    4782	STA PlayerFacingDir                          ; otherwise set facing direction accordingly
    4783LRAir:
    4784	LDA Left_Right_Buttons                       ; check left/right controller bits (check for jumping/falling)
    
    src/prg.asm lines 4771–4784 at 1cc3c92 · upstream ↗

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.

    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

  28. ^Because a jump keeps Mario's take-off facing, steering back slows him at the plain rate until he moves the other way, then at double the rate ($1A0 from a run).VerifiedXkeeper0/smb1
    How we know
    5042	LDA PlayerFacingDir
    
    src/prg.asm lines 5042–5047 at 1cc3c92 · upstream ↗
    4779LRWater:
    ⋮
    4783LRAir:
    
    src/prg.asm lines 4771–4784 at 1cc3c92 · upstream ↗

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . 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-25.

    In the claim ledger

  29. ^The standing state moves Simon before it checks A, so the press frame walks at 1 px/frame; the take-off then fixes the jump's direction from the d-pad held on that frame, and the jumping state moves him 1 px/frame that way or not at all.Verified“Castlevania (USA) (Rev 1)”
    How we know

    In the cartridge (“Castlevania (USA) (Rev 1)”): bank 6 $93D9-$93E3, the move before the jump check; bank 6 $9401-$943B: the take-off writes held Left/Right into $3C; bank 6 $9479-$9481, the jumping state's speed, 1 px/frame. We don't reproduce the bytes.

    Measured by a script in MesenCE 2.2.1 (build 4b8a196), on Castlevania (USA) (Rev 1) (SHA-1 4e3ef47de86a…). 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-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  30. ^ abIn the running game, on flat ground, a held jump from top speed with the d-pad released is dragged on 18 frames and lands at $369 (3.41 px/frame) to the right but −$35E to the left.Verifiedsonicretro/s1disasmrevised
    How we know
    _incObj/01 Sonic.asm#L986-L1013 · upstream ↗
    5gravity:	equ	$38				; gravity constant used by many objects
    
    _incObj/sub ObjectFall & SpeedToPos.asm line 5 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.

    Revised after a check by a second AI model, 2026-10-25.

    In the claim ledger

  31. ^In the running game, on flat ground, after a jump from a roll the d-pad does nothing in the air, neither steering Sonic nor turning him, and air drag still runs.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Rolling”
    How we know
    1248		btst	#status_rolling_bit,obStatus(a0)	; is Sonic already in a ball state?
    1249		bne.s	.rolljump				; if so, branch
    
    _incObj/01 Sonic.asm lines 1248–1249 at 15dfa3a · upstream ↗
    1263		bset	#status_rolljumping_bit,obStatus(a0)	; set Roll-Jump flag
    
    _incObj/01 Sonic.asm lines 1262–1263 at 15dfa3a · upstream ↗
    944		btst	#status_rolljumping_bit,obStatus(a0)	; is Roll-Jump flag set?
    945		bne.s	Sonic_RollJumpLock			; if yes, prevent midair direction change
    
    _incObj/01 Sonic.asm lines 944–945 at 15dfa3a · upstream ↗
    974Sonic_RollJumpLock:
    ⋮
    986Sonic_AirDrag:
    
    _incObj/01 Sonic.asm lines 974–986 at 15dfa3a · upstream ↗
    In Sonic 1, 2, 3, and Knuckles, you can't control the Player's trajectory through the air with the buttons if you jump while rolling.
    Rolling Jump · 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.

    In the claim ledger

Sources

Code

Secondary