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

Running is how a character’s speed on the ground follows the d-pad. Three games span the range, from a speed that switches on and off to one that builds and fades. The lab runs each game’s rules frame by frame, checked against its cartridge.

Interactive: movement-lab (needs JavaScript)

Running, three ways
  • InstantCastlevania (1986). Simon walks at one speed from the first frame and stops dead.1
  • SteppedMega Man (1987). A short first step, then full speed, with no acceleration.2Mega Man 2 (1988). A short first step, then full speed, with no acceleration.3,4Mega Man 3 (1990). One walking speed, with a brief halt after the first step.5
  • Ramp upMetroid (1986). 0.1875 px/frame² to 1.5 px/frame after a still first frame, a stop the moment the d-pad is released, and 16 frames to turn at full speed.6,7,8
  • MomentumSonic the Hedgehog (1991). Speed builds and fades slowly, to a single top speed.9,10Sonic the Hedgehog 2 (1992). Speed builds and fades slowly to a top speed, and on the ground holding forward lets him keep a speed above it.11,12Sonic 3 & Knuckles (1994). The top speed, acceleration, and braking of the first two games.13
  • AnalogSuper Mario 64 (1996). The stick's tilt sets a target speed of up to 32 units/frame, approached by 1.1 − speed/43 a frame.14
  • Run buttonSuper Mario Bros. (1985). Holding B raises his top speed from 1.5 to 2.5 px a frame.15,16
  • P-meterSuper Mario World (1990). A full P-meter raises the top speed from 2.25 to 3 px/frame.17,18Sonic Advance 2 (2002). Holding forward at the 6 px/frame top speed fills a hidden counter, faster with more rings, and boost mode then raises the top speed to 12.19,20,21,22

#Later games

Wolfenstein 3D keeps no velocity for the player, so a step starts and stops at once23, as Simon’s walk does1. Quake III Arena accelerates by Quake’s rule against a friction of 624, and a run settles at the full wish speed, 32025,25. Sonic Advance 2 keeps Sonic’s top speed20,26 but raises his acceleration with the ring count19, where Sonic’s is fixed27. Its boost mode doubles that top speed22. Banjo-Kazooie maps the stick’s tilt to a target of up to 500 units/s28 in five bands28, where Super Mario 64 squares the tilt14.

Mega Man 3 drops Mega Man 2’s slow step speed: from standing, a held direction moves Mega Man at 1.30 px/frame ($01.$4C)5 at once, then holds him still while the turning animation stays on its first frame5. The atlas hasn’t read the sequence data that sets the length of that pause5. Sonic the Hedgehog 2 keeps Sonic the Hedgehog’s top speed, acceleration, and deceleration11,26,27,29. On the ground, holding forward no longer pulls a faster Sonic down to the top speed12. Sonic 3 & Knuckles keeps the same three values13.

#Quirks

  • Super Mario World tests only the speed’s high byte against the cap and adds the acceleration unclamped, so Mario’s top speed cycles around the cap instead of resting on it30.
  • Super Mario Bros. doubles its braking whenever Mario faces away from his motion, so a skid brakes at twice the rate of a release31. Any held button but A stops a slow slide dead32. The level’s first step is doubled too, because Mario’s moving direction starts at 031.
  • Mega Man lands running if a direction was held the frame before he lands, with no first step33.
  • Simon can’t move while he crouches, but he can turn34,35.
  • Sonic the Hedgehog takes 128 frames each way9 to reach top speed or coast to a stop9, and his turn from top speed isn’t symmetric: 140 frames right to left, 130 left to right10,10,36.
  • Celeste uses one rate to speed up, turn, and stop, so Madeline reaches top speed in 6 updates on the ground, 9 in the air37,37,38.

Games

GameYearHowNote
Felix the Cat1992the x speed builds by a step from RAM to a cap of 533/256 px a frame
Castlevania1986InstantSimon walks at one speed from the first frame and stops dead
Metroid II: Return of Samus1991Instant1.5 px/frame from 1- and 2-pixel steps, 2 px/frame with the Varia Suit
Wolfenstein 3D1992Instantno velocity: each frame moves the player by the keys' value, 5,250 units a tic walking and 10,500 running, and stops at once on release
Mega Man1987Steppeda short first step, then full speed, with no acceleration
Mega Man 21988Steppeda short first step, then full speed, with no acceleration
Mega Man 31990Steppedone walking speed, with a brief halt after the first step
Mega Man 61993Steppeda step, a short halt, then the walking speed
Metroid1986Ramp up0.1875 px/frame² to 1.5 px/frame after a still first frame, a stop the moment the d-pad is released, and 16 frames to turn at full speed
Sonic the Hedgehog1991Momentumspeed builds and fades slowly, to a single top speed
Sonic the Hedgehog 21992Momentumspeed builds and fades slowly to a top speed, and on the ground holding forward lets him keep a speed above it
Doom1993Momentuma thrust each tic on the floor against 0.90625 friction, settling near 16.7 units/tic at a run
Sonic 3 & Knuckles1994Momentumthe top speed, acceleration, and braking of the first two games
Duke Nukem 3D1996Momentuma thrust each tic, in the air too, against 0.812 friction from the CON's RUNNINGSPEED
Quake1996Momentumacceleration 10 against friction 4 settles a run at exactly the 320 cap, reached in about a seventh of a second
Quake II1997Momentumacceleration 10 against a friction of 6 settles a run at exactly the 300 cap, the numbers Quake III kept
Quake III Arena1999Momentumacceleration 10 against a friction of 6, up from Quake's 4, so a run still settles at exactly 320 but stops sooner
Celeste2018Momentumone rate to speed up, turn, and stop
Super Mario 641996Analogthe stick's tilt sets a target speed of up to 32 units/frame, approached by 1.1 − speed/43 a frame
Banjo-Kazooie1998Analogfive bands of stick tilt map linearly to a target of up to 500 units/s, closed by a fraction of the gap each frame
Super Mario Bros.1985Run buttonholding B raises his top speed from 1.5 to 2.5 px a frame
Super Mario Bros.: The Lost Levels1986Run buttonSuper Mario Bros.'s top speeds; Luigi takes longer to speed up, stop, and turn
Super Mario Bros. 21988Run buttonB raises the top speed by half, from 1.5 to 2.25 px/frame; carrying an enemy or a block changes the cap
Super Metroid1994Run button2.75 px/frame, and holding dash builds up to 2 px/frame more, 7 with the Speed Booster
Super Mario Bros. 31988P-meterB raises the top speed to 2.5 px/frame, and a full P-meter to 3.5
Super Mario World1990P-metera full P-meter raises the top speed from 2.25 to 3 px/frame
Sonic Advance 22002P-meterholding forward at the 6 px/frame top speed fills a hidden counter, faster with more rings, and boost mode then raises the top speed to 12
Every claim about this mechanic, by game (135)
Super Mario Bros. 1985Horizontal speeds are 4.4 fixed point, whole pixels and sixteenths per frame; MoveObjectHorizontally shifts the sixteenths into the subpixel byte.Code
Mario's top ground speed is $18 walking and $28 running (B held).Code
Each frame PlayerCtrlRoutine splits the d-pad bits, runs the jump check, X_Physics, and the state's routine (which changes the speed, then moves Mario), sets Player_MovingDir from the speed's sign, and only then runs PlayerBGCollision, which lands him.Code
Player_X_MoveForce is a fraction byte below Player_X_Speed, so acceleration works in 1/256 of a sixteenth (1/4096 px/frame) and carries into the speed byte, but MoveObjectHorizontally moves Mario by the speed byte alone.Code
FrictionData gives Mario's acceleration and braking per frame: $E4 running, $98 walking, and $D0 walking while still fast from a run, in 1/4096 px/frame.Code
On the ground X_Physics uses the running row (cap $28, acceleration $E4) while B and the direction Mario moves in are held and for the 9 frames after B goes up; otherwise the walking row (cap $18, $98, or $D0 while RunningSpeed is set or his speed is $21 or more).Code
X_Physics doubles the acceleration whenever Mario faces away from the direction he moves, so a turn brakes at $130, $1A0, or $1C8 a frame.Code
When a held direction carries the speed to its cap or past it, ImposeFriction sets the speed byte to the cap, so a speed above the cap drops to it in one frame.Code
With neither Left nor Right held on the ground, ImposeFriction brakes Mario by the frame's acceleration toward zero and stops once the speed byte reaches 0, leaving the fraction byte as it is.Code
On the ground, GetPlayerAnimSpeed zeroes Mario's speed and turns his moving direction to his facing one when a button other than A is held, the d-pad's Left/Right bits differ from his moving direction, and his speed is below $0B.Code
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.Code
On the ground, Down with Left or Right clears both, so Mario neither walks nor crouches and brakes as if the d-pad were released; big Mario holding Down alone crouches.Code
Measured from a standstill in World 1-1, Mario reaches $18 on frame 40 walking and $28 on frame 45 running, and let go at those speeds he stops in 40 and 49 frames.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, Simon walks 40 px in 40 frames, 1 px per frame.Verified
Simon has no acceleration; each frame on the ground his direction bits are set from the d-pad's held Left and Right, and the move routine shifts him by his speed bytes, 1 px/frame, in that direction or not at all.Verified
While Left or Right is held, the crouching state, and the standing state on a frame that doesn't start a fall, a stair climb, a whip, a jump, or a crouch, set Simon's facing ($0450) from it, so he turns on the first frame, and crouching he can turn without moving. A frame that starts any of those keeps the facing he had.Verified
Down on the ground puts Simon in the crouching state 4 px lower, where the d-pad no longer moves him; letting go stands him back up, and that frame he doesn't move either.Verified
Metroid 1986On the ground Samus accelerates at $30/256 (0.1875) px/frame² toward SamusHorzSpdMax/16 px/frame, which VertAccelerate sets to $18 (1.5 px/frame) while she is grounded. With no direction held, StopHorzMovement clears her horizontal speed at once.Code
From a standstill, the first frame with Left or Right held doesn't move Samus. SamusStand picks the running state, calls SetSamusData, which moves her at her speed of 0, and only then calls SetSamusRun, which sets her acceleration. Her speed rises from the next frame.Code
Running on the ground, Left or Right against Samus's facing turns her and sets the acceleration toward the new side on that frame, through SetSamusRun, but leaves her speed as it is. She slows by 0.1875 px/frame each frame, passes 0, and speeds up the other way: from 1.5 px/frame, 16 frames to 1.5 px/frame the other way (computed).Code
On the ground, the running handler checks Samus's animation before it reads A or the d-pad (LCDBF). Unless it is the running animation (or, with Up held, running and aiming up), it sets that animation and skips the rest of the handler for the frame. A jump press or a released d-pad on that frame is ignored, and she accelerates toward her facing. That happens on her first frame on the ground after a running jump or a fall, and on the frame after a turn: SetSamusRun gives Samus the running animation only if her animation was standing (an_SamusStand), and otherwise the running-and-aiming-up animation (an_SamusRunPntUp).Code
Mega Man 1987Off 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.Code
Mega Man's animation is his state. A Left or Right pressed fresh, with neither held the frame before, starts the first step ($03) with its timer at 0, on the ground or in the air; each frame on the ground after the move, a held direction turns the step into the run ($06) once its timer reads $22, and lands a jump running; a direction let go turns a run into the slide to a stop ($0C, timer 1) and anything else into standing; with no direction this frame or the last, a jump lands into the landing animation ($0F, timer 1), and the slide and the landing end in standing when their timer wraps to 0.Code
After Mega Man's frame, _object_frameset_timer advances his animation's timer from the frameset's first byte: the low nibble counts up to the byte's low nibble, then the high nibble moves to the next animation frame or wraps to 0 after the last. The first step shows 3 frames for 3 frames each; the press frame sets its timer to 0 and the ground check reads it before that frame's advance, so the check first finds $22 on the step's 9th frame; the slide shows 2 frames for 7 each (8 in the shooting pose), and the landing 2 frames for 2 each.Code
Measured from a standstill at the start of Bomb Man's stage, Mega Man's first step lasts 9 frames at 0.125 px/frame, and a released run slides 13 frames at 0.5 px/frame, 6.5 px in all, before he stands; a jump landed with nothing held shows the landing animation for 3 frames.Verified
A buster shot sets aobject_timer to $1F, which shows Mega Man's shooting animations for 15 frames, counting the press frame; their framesets time the slide to a stop at 8 frames per animation frame instead of 7, so a shot fired shortly before or during the slide lengthens it. A Left or Right pressed fresh clears the pose.Code
Each frame _change_direction faces Mega Man toward a held Left or Right before his speed is looked up and he moves, so he reverses at full speed with no skid; a reversal from one held direction to the other isn't a fresh press, so a run stays a run.Verified
Down changes nothing on open ground; _megaman_on_stage reads Up and Down only when a ladder tile is at hand.Verified
Mega Man's ordinary-floor movement differs from Mega Man 2's, measured in Mesen at the start of Bomb Man's stage and of Heat Man's. The first difference: holding Right from a standstill, Mega Man is still in his first step on the 8th frame, moving 0.125 px, where Mega Man 2 runs at 1.375. After it: a slide of 13 frames, not 8; two frames at the ground speed after a jump press, not one; a landing that runs only with a direction held on the landing frame, not the frame before; 0.125 px/frame on a fresh press in mid-air; −0.75 px/frame on the ground, not −0.25, so a walk-off and a ceiling hit fall faster; and a wall push that keeps the X fraction.Verified
Mega Man 2 1988Measured in the game, Mega Man first steps 0.125 px/frame for 7 frames, then runs at 1.375 px/frame.Verified
Mega Man's X is 8.8 fixed point, and his horizontal speed is an 8.8 magnitude that _check_object_horizontal_move adds or subtracts according to the right bit of ztoward.Code
Mega Man never accelerates; each frame his state's row of megaman_status_xcoord_speed_table sets the speed outright, 0 standing, 0.125 px/frame on the first step, 1.375 running, 1.3125 jumping, and 0.5 sliding to a stop.Code
A held direction moves standing Mega Man into the first-step state on the same frame; the step becomes a run when its animation reaches frame 1, a released run becomes a slide, and the slide stops at its animation's frame 2 or restarts the first step if a direction is pressed.Code
_turn_megaman faces Mega Man toward a held Left or Right at the start of every moving state's frame, and the move direction follows the facing that same frame, so he reverses at full speed with no skid.Verified
Measured from a standstill in Heat Man's stage, Mega Man's first step lasts 7 frames, and a released run slides 8 frames at 0.5 px/frame, 4 px in all, before he stands.Verified
Down changes nothing on open ground; of the walking states only _check_shoot_on_ladder reads Up and Down, and only when a ladder is at hand.Verified
Super Mario Bros. 2 1988Holding B raises the top speed by half: running right with nothing carried, from $18 to $24 (1.5 to 2.25 px/frame). Measured in Mesen (MesenCE 2.2.1) from power-on, on the floor at the bottom of 1-1's first area, all four characters run right at 1.5 px/frame and, with B, 2.25 px/frame.Verified
The run button's half is added to whatever cap applies, the carrying speed (carry-speed) or quicksand's $04 as well as the unladen $18. To the left the cap is negative, and halving it with the carry set rounds it away from zero: a cap of $EB to the left becomes $E0, where $15 to the right becomes $1F.Code
On ordinary ground, holding right adds $02 to the speed each frame, so a character reaches walking speed, $18 (1.5 px/frame), 12 frames from a standstill; with neither direction held the ground takes $03 a frame off the speed, to zero. Measured in Mesen (MesenCE 2.2.1) from power-on, on the floor at the bottom of 1-1's first area, each character reaches 1.5 px/frame in 12 frames from a standstill; letting go of everything at 2.25 px/frame drops the speed to the 1.5 cap at once, and friction stops the character 8 frames later.Verified
Left and right push at the same $02 a frame in the air, and with neither held the air keeps the speed. Any push resets a crouch jump's charge (crouch-charge). Crouched on the ground, left and right do nothing, and the ground's friction slows the player. On ice the push comes on one frame in four and the friction on one in sixteen.Code
Super Mario Bros. 2's manual gives B a third use, running faster, and its code raises the top speed by half while B is held (smb2/run-cap). Doki Doki Panic's manual gives B only lifting and throwing. Both manuals say every character runs at the same speed.Manual
Super Mario Bros. 3 1988Off uphill slopes, Mario's speed tops out at $18 walking, $28 holding B, and $38 while the P-meter is full; walking uphill, the cap comes from Player_UphillSpeedVals instead. Measured in Mesen from power-on as Raccoon Mario at World 1-1's start, holding Right levels off at $18, and Right with B at $28 until the meter fills, then at $38.Verified
Below the top speed, a held direction adds the suit's entry in Player_XAccelMain plus the carry from adding its Player_XAccelPseudoFrac entry to Counter_Wiggly, on the ground and in the air. Each frame Counter_Wiggly becomes its high nibble minus $90, so it steps through all 16 high nibbles: computed, an $E0 fraction carries on 14 of every 16 frames, so every suit but the Frog gains 1 on 14 frames in 16, about 0.88 a frame, while the Frog's entry adds 2 every frame. Pressing against the motion adds 2 the other way for every suit. With no direction held on the ground, or over the top speed on the ground, the friction entry takes 1 on each frame without a carry: 14 in 16 for Super, Fire, and Raccoon Mario ($20), 10 in 16 for small, Tanooki, and Hammer Mario ($60), and every frame for the Frog ($00). Over the top speed in the air nothing changes it, and slippery ground uses other entries. Measured in Mesen from power-on as Raccoon Mario at World 1-1's start, holding Right from rest gains 1 on 14 of any 16 frames and reaches $28 (with B) on the 46th.Verified
Mega Man 3 1990Mega 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.Code
The turning animation, $0D, has 2 frames of 6 ticks each: its sequence's count byte is 1 and its tick byte 5, and the sprite engine advances a frame when the tick that started equal to the tick byte ends. While it shows its first frame the ground state doesn't move Mega Man.Code
On the ground Mega Man 3 picks the move from his animation. Standing, a held direction faces him that way, starts the turning animation, and moves him 1.30 px; on the turning animation's first frame he doesn't move; once it reaches its second, a held direction starts the walking animation and moves him, and nothing held stands him. Walking, a direction matching his facing moves him; anything else, letting go or the other direction, starts the turning animation and moves him once more toward his facing. Down alone does nothing on open ground.Code
Measured in Mesen from a standstill in Top Man's stage start, Right held moves Mega Man 1.30 px on its first frame, not at all on the next 5, and 1.30 px on every frame after; let go after a walk, he moves 1.30 px on one more frame and then stands.Verified
Mega Man 3's ordinary-floor movement differs from Mega Man 2's from the first frame of a walk: Right held from a standstill moves him 1.30 px, then nothing for 5 frames, then 1.30 px a frame, where Mega Man 2 moves 0.125 px a frame for 7 frames, then 1.375. A jump differs from its press frame, which lifts him 4.89 px where Mega Man 2 lifts him 0. Letting go of A mid-rise starts the fall at once, where Mega Man 2 cuts a rise of 2 px/frame or more to 1, and falls cap at 7 px/frame instead of 12. He keeps Mega Man 2's gravity, floor and ceiling corners, and 16 px tiles, and adds the slide.Code
Super Mario World 1990Measured on flat ground, Mario's top speed is 20/16 px/frame walking, 36/16 holding Y, and 47/16 to 49/16 once the P-meter is full, near DATA_00D535's $14, $24, and $30.Verified
Each frame the player routine moves Mario by last frame's speed, runs block collision (which lands him), then CODE_00D5F2 updates his horizontal speed, so a speed change first moves him on the next frame and a landing frame already uses the ground rules.Verified
PlayerXSpeed is 16 bits, a high byte in 1/16 px/frame and a low byte below it, so acceleration works in 1/4096 px/frame; position moves by the high byte alone.Code
On flat ground MarioAccel_ speeds Mario toward a held direction by $0180 (1.5/16 px/frame) a frame, with or without Y; holding against his motion uses its turning row, $0280 (2.5/16) walking and $0500 (5/16) with Y.Code
DATA_00D535 caps Mario's ground speed at $14 walking and $24 holding Y, and at $30 while the P-meter is full and charging.Code
CODE_00D742 compares only the speed's high byte with the cap; below it the frame adds the full acceleration, unclamped, and at or past it the frame applies friction instead, so Mario's top speed cycles around the cap.Code
With no direction held on the ground, CODE_00D76B moves Mario's speed 1/16 px/frame a frame toward the slope's target speed, 0 on flat ground, and stops exactly on it.Code
Mario turns at the turning row's rate while his speed's high byte is nonzero and points against the held direction; the step is not clamped at zero, so the last one overshoots into the new direction.Code
A held Left or Right turns Mario to face it on the same frame, on the ground and in the air, unless he carries an item.Code
On flat ground, Down makes Mario duck, and a ducking Mario ignores Left and Right, so friction alone slows him; the duck flag is set only on the ground, so a duck jump stays ducked and steers.Code
Measured from a standstill on Yoshi's Island 1, Mario first passes $14 on frame 14 walking and reaches $24 on frame 24 holding Y; with Y held his P-meter fills 56 frames later.Verified
Mega Man 4 1991Mega Man walks and moves through the air at the speed held in his X speed (ent_xvel), 1.30 px/frame ($01.$4C) on ordinary floor; no walking or air code sets it. The slide writes 2.5 px/frame there, and its end and the jump out of it write $01.$4C back. Measured in Mesen from power-on, at the start of Skull Man's stage, the X speed read $01.$4C and each walking frame moved him 332/256 px.Verified
On the ground Mega Man's sprite sub-type decides whether he moves. Standing ($01), a held direction sets the pause pose ($0D) and moves him one frame; in the pause pose he doesn't move until its animation advances, and then walks ($04) toward a held direction, or stands with none. Walking, the same direction keeps him moving; letting go puts him in the pause pose without a move, and the other direction does too, with one frame's move the new way.Code
The pause pose lasts 6 frames: its animation (sub-type $0D in bank $0D) holds its first frame for 6 animation ticks, one a frame. So from standing, or on a turn, a held direction moves Mega Man on the first frame, holds him still on the next 5, and walks from the 7th; letting go of a walk holds him for 6 frames, whatever the d-pad does, before he stands or walks on. Measured in Mesen from power-on, at the start of Skull Man's stage, Right moved him on frame 1, not on frames 2 to 6, and on every frame from 7 to 40; letting go on frame 41 kept him still in the pause pose on frames 41 to 46, and he stood from frame 47.Verified
Metroid II: Return of Samus 1991Walking has no speed variable to build up: samus_walkRight adds 1 or 2 px to Samus's X position on alternate frames (1.5 px/frame), 2 px/frame with the Varia Suit, and 1 px/frame in water.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 the d-pad the way Sonic runs, or from a standstill, adds son_acceleration, $C, to his ground speed each frame, up to the top speed.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, with neither Left nor Right held, Sonic's ground speed loses the acceleration, $C, each frame toward zero, stopping at exactly 0.Verified
In the running game, on flat ground, holding the d-pad against Sonic's motion subtracts son_deceleration, $80, a frame, and a step that would cross zero sets the speed to $80 the other way: from $40 written in by the probe, Left gives −$80, and from −$40, Right gives $80.Verified
In the running game, on flat ground, reversing from top speed, Sonic running right reaches exactly 0 on the 12th frame and −$C on the 13th, but running left he jumps from −$80 to +$80 on the 12th.Verified
In the running game, on flat ground, turning around from top speed takes 140 frames to reach top speed the other way when Sonic runs right, and 130 when he runs left.Verified
In the running game, on flat ground, Sonic reaches top speed from a standstill in 128 frames, and from top speed he coasts to a stop in 128 frames with the d-pad released.Verified
In the running game, on flat ground, a reversal skids (stopping animation, and facing his motion) when the slowed speed is at least $400 moving right but only $301 moving left, because the angle read overwrites the speed's low byte.Verified
In the running game, on flat ground, the d-pad turns Sonic only when his ground speed is 0 or already that way, so reversing from top speed he keeps facing his motion until the 13th frame, the one after his speed reaches 0 from the right or crosses it from the left.Verified
In 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 $80 either way: from $8C written in by the probe he rolls, from $8B he doesn't.Verified
In the running game, on flat ground, a roll never speeds up: friction takes $6 a frame whatever is held, holding against the roll takes another $20, and a ground speed past $1000 written in by the probe gives an X speed of exactly ±$1000 (16 px/frame).Verified
In the running game, on flat ground, with the slow ground speed written in by the probe, holding against a roll turns it around only below $20 moving right but up to $20 moving left, then friction leaves $7A; other slow speeds stop and stand Sonic up.Verified
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.Verified
In the running game, on flat ground, the jump adds nothing to Sonic's X speed, and because the press frame skips Sonic_Move, he leaves the ground with the previous frame's speed, whatever the d-pad holds on that frame.Verified
In the running game, landing on flat ground keeps Sonic's horizontal speed: on the landing frame his ground speed is that frame's X speed, after its air steering, drag, and move, his Y speed is 0, and he stands uncurled.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
Felix the Cat 1992Holding Right from a standstill in the first stage at power level 0, with $0616 below 3, Felix's x speed grows by a step read from $03B3, 48 (in 1/256 px) there, each frame up to the cap of 533, about 2.08 px a frame, which it reaches on the twelfth frame.Verified
Mega Man 5 1992Mega Man walks and moves through the air at the speed held in his X speed ($03C0.$03A8), 1.30 px/frame ($01.$4C) on ordinary floor; no walking or air code sets it. The slide writes 2.5 px/frame there, and its end and the jump out of it write $01.$4C back. Measured in Mesen from power-on at the start of Stone Man's stage ($26 = 2), the X speed read $01.$4C and each walking frame moved him 332/256 px.Verified
On the ground Mega Man's sprite sub-type decides whether he moves. Standing ($01), a held direction sets the step pose ($0D) and moves him one frame; in the step pose he doesn't move, whatever the d-pad does, until its animation leaves its first frame, and then walks ($04) toward a held direction or stands with none. Walking, the same direction keeps him moving; letting go puts him in the step pose without a move, and the other direction puts him in it with one move that way.Code
The step pose lasts 6 frames: its animation (sub-type $0D, descriptor $01,$05 at $BB28 in bank $13) holds its first frame until its tick count, reset with the sub-type, reaches 5. So from standing, or on a turn, a held direction moves Mega Man on the first frame, holds him still on the next 5, and walks from the 7th; letting go of a walk holds him 6 frames, whatever the d-pad does, before he stands or walks on. Measured in Mesen from power-on at the start of Stone Man's stage.Verified
Sonic the Hedgehog 2 1992Obj01_Init sets Sonic's top speed to $600, his acceleration to $C, and his deceleration to $80 subpixels, Sonic 1's values; speed shoes and Super Sonic swap in others.Code
Holding forward no longer pulls a faster Sonic down to the top speed on the ground; Sonic_MoveRight undoes the frame's acceleration and keeps the speed he had.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
With neither Left nor Right held and the sliding status clear, a standing Sonic's ground speed moves 12 ($C, his acceleration) toward 0 each frame and stops at 0, as in Sonic 1; while sliding, Sonic_Move goes straight to Obj01_Traction, with no d-pad and no friction.Code
Turning against his motion on flat ground, Sonic skids (the stopping animation, still facing his old direction of motion) when his ground speed before the turning step is at least $480 going right or $381 going left, as in Sonic 1: the angle check overwrites the low byte of the speed it then compares.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
Wolfenstein 3D 1992Wolfenstein 3D keeps no velocity for the player: each frame ControlMovement zeroes thrustspeed, and Thrust moves the player straight through ClipMove by the frame's control value times MOVESCALE (150), or BACKMOVESCALE (100) backward. The keyboard sets that value to 35 a tic walking (BASEMOVE) or 70 running (RUNMOVE), times the frame's tics, so a walk moves 5,250 and a run 10,500 units a tic, with 65,536 units to a tile (TILEGLOBAL); Thrust clamps each move to MINDIST*2-1 (45,055), so those rates hold on frames of at most 8 tics walking or 4 running, and longer frames move less a tic. At the 70 tics a second of TickBase's comment a run is about 11.2 tiles a second (computed).Code
Doom 1993Doom's game logic runs in tics of 1/35 second (TICRATE 35).Code
Each tic a Doom player stands on the floor, P_MovePlayer adds a thrust of the command's forward and side moves times 2,048 (1/32 unit per tic for each step of move), the side thrust at 90° to the facing; a keyboard sets the forward move to 25 walking or 50 running and the side move to 24 or 40, and the player gets no thrust in the air.Code
After a Doom thing moves on the floor, its momentum is multiplied by FRICTION (0xe800, 0.90625) each tic, and set to 0 once both axes are under STOPSPEED (1/16 unit per tic) with no move commanded; friction skips missiles, a charging lost soul, anything in the air, and a corpse halfway off a step still moving faster than 1/4 unit per tic on an axis, and the no-momentum cheat stops a player outright. Each axis of momentum is capped at 30 units per tic.Code
Computed from the thrust and friction, not measured: with a thrust of a each tic and friction 0.90625, a Doom player on the floor settles at the speed v where a = 0.09375·v, about 16.7 units per tic (583 units/s) running forward and 8.3 walking; neither comes near the 30-unit cap.Code
Mega Man 6 1993From standing, a held direction moves Mega Man one frame at the walking speed, $01.$4C (1.30 px/frame) from the table at $8BEA, then holds him in the step pose while a counter of 6 ($95) runs out, and walks at 1.30 px/frame from the 7th frame. That is on ordinary floor: on surface type $05 he walks at once, on $15 he carries momentum at up to 2 px/frame (momentum-surfaces), and in tile type $09 he walks at 0.5 px/frame (slow-surface). Measured in Mesen from power-on, at the start of Tomahawk Man's stage, Right moved him 1.30 px on frame 1, not at all on frames 2 to 6, and 1.30 px on each frame after.Verified
On the ground Mega Man 6 runs one of three loops, each ending its frame with a yield and reading the next frame's input after it. Standing, a held direction turns him and starts the step: one move at the walking speed, then 5 frames still (walk-start); after it a held direction walks on, turning to it, and none stands him. Walking, letting go stands him on the same frame, and a held direction against his facing turns him at once and walks on with no new step. A fresh A press jumps from any of the three, before that frame's move, or slides with Down held, except on the frame a walk's direction is let go: that frame goes straight to the standing loop's move, and the press is lost. Down alone does nothing.Code
Each frame, after a loop's checks, Mega Man 6 makes one move through code_3886CE: on ordinary floor and in the air alike, the horizontal speed comes from the d-pad's table at $8BEA, 1.30 px/frame or 0; gravity is added to the vertical speed; he moves by both speeds in 8.8 fixed point; and the tile checks run after the move (collision-order).Code
On tile type $09 ($064B) Mega Man moves slower: a jump starts at $FB.$CC (4.20 px/frame up), the slide at 1.5 px/frame, and walking at 0.5 px/frame, from the tables at $8009 and $8BF6.Code
On surface types $05 and $15 his walking speed is a carried momentum ($A1.$A0). A held direction sets it to full speed at once, 1.30 px/frame on $05 and 2 px/frame on $15; with nothing held it slows by 6/256 px/frame each frame, and holding the other way slows it by 12/256 (computed), until its sign flips and it stops.Code
Sonic 3 & Knuckles 1994Sonic_Init sets the top speed to $600, the acceleration to $C, and the deceleration to $80 subpixels, the values of Sonic 1 and Sonic 2.Code
With neither Left nor Right held, Sonic_Move takes the current acceleration off a standing or running Sonic's ground speed each frame, stopping at 0, as Sonic 2 does; that is $C out of water and without speed shoes (ground-speeds), and $C for Super Sonic. With the infinite-inertia flag some objects set (bit 7 of status_secondary), it skips the d-pad and the friction both.Code
Sonic 3 & Knuckles keeps Sonic 2's skid bug: on flat ground, not mid-flip (flip_type not negative), a reversal skids (stopping animation, facing his motion) when the slowed speed is at least $400 moving right but only $301 moving left, because the angle read overwrites the speed's low byte.Code
On the ground the d-pad turns Sonic only when his ground speed is 0 or already that way, and a skid turns him to face his motion; rolling, the same, with no skid; in the air, Left or Right turns him at once unless he jumped from a roll. While the spin dash charges, the d-pad doesn't turn him. On the ground and rolling, the d-pad is skipped altogether while an object holds his controls: move_lock, the infinite-inertia flag (bit 7 of status_secondary), or, rolling, a negative spin_dash_flag (pinball mode).Code
With room overhead (jump-headroom), a jump press adds the jump speed along the ground's normal, -$680 straight up on flat ground with normal gravity (jump-speed gives the underwater and Super speeds), keeps the X speed, and ends the frame: the jump frame moves nothing. Standing, the jump curls Sonic and moves his center 5 px down (up with reverse gravity); from a roll he keeps the standing size (roll-jump-size).Code
Landing on flat ground keeps Sonic's horizontal speed as his ground speed, sets his Y speed to 0, and, if he was curled and spin_dash_flag is clear (not pinball mode), uncurls him; with normal gravity a ball from a standing jump or a roll moves 5 px up, one from a roll jump doesn't move. It clears the jump, roll-jump, and insta-shield flags; with the bubble shield used, it bounces him instead (shield-moves).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 1994Running accelerates Samus at 0.1875 px/frame² to 2.75 px/frame and slows her at 0.5 px/frame² once she lets go. Holding dash while running builds a separate extra run speed at 0.0625 px/frame², up to 2 px/frame, or 7 with the Speed Booster.Code
Super Metroid's running acceleration is Metroid's, $30/256 (0.1875) px/frame² in both, but its top speed rises from Metroid's 1.5 px/frame to 2.75. Metroid II, between them, has no acceleration and walks at 1.5 px/frame.Code
Duke Nukem 3D 1996Duke Nukem 3D schedules its timer with TS_ScheduleTask at a rate of TICRATE, 120, which the atlas reads as counts per second (the task manager's source isn't in the release), and faketimerhandler reads the player's input and queues one move every TICSPERFRAME counts, TICRATE/26, which integer division makes 4; domovethings runs once per queued move, so on that reading the game runs 30 tics a second (computed), where Doom runs 35.Code
A Duke Nukem 3D keyboard sets the forward and side moves to 40 walking or 80 running (NORMALKEYMOVE), each clamped apart to ±90 (MAXVEL, MAXSVEL); getinput turns the pair by the facing, and each tic processinput adds it to the player's velocity times TICSPERFRAME (4) and 64, doubled while steroids last and the jetpack is off, in the air as on the ground. A hard landing and a few other actions zero the velocity instead. Doom thrusts only on the floor, with moves of 25 or 50 forward and 24 or 40 sideways.Code
After the thrust, Duke Nukem 3D multiplies the player's velocity each tic by dukefriction, which the CON's gamestartup sets from RUNNINGSPEED, 53,200 of 65,536 (0.812; the C default is 0xcc00, 0.797): 0x2000 less when kicking or crouching on the ground, 0x1400 less underwater, and three quarters of it again while shrunk; the velocity drops to 0 once both axes are under 2,048. A steady run moves 4.31 times the per-tic thrust (0.812 / 0.188, computed), and a released run falls under half its speed within 4 tics (computed). Doom keeps 0.90625 of its momentum each tic.Code
Quake 1996On the ground, Quake's SV_UserFriction takes the horizontal speed and lowers it by frame time × friction × the larger of the speed and sv_stopspeed, to no less than 0, scaling all three velocity axes by the same factor; sv_friction defaults to 4 and sv_stopspeed to 100, and when a trace 16 units ahead along the motion finds no floor within 34 units below the feet, the friction is multiplied by edgefriction (default 2). A standing player is left alone.Code
Quake builds the wish velocity from the forward and side moves along the view's forward and right vectors (zero vertical for a walking player), caps its length at sv_maxspeed (default 320), and on the ground runs friction and then SV_Accelerate: if the speed along the wish direction is under the wish speed, it adds sv_accelerate (default 10) × frame time × wish speed along that direction, no more than the shortfall.Code
Computed from the friction and acceleration rules, not measured: because acceleration (10) outpaces friction (4), a Quake player on flat ground settles at exactly the wish speed, 320 units/s at a run; at the 72-frame rate a run from rest reaches it on frame 10 (0.14 s), and letting go from 320 comes to rest after 39 frames (0.54 s).Code
Super Mario 64 1996On the ground the stick's tilt sets a target speed: intendedMag is 32 times the square of the tilt's fraction of full. Below the target Mario gains 1.1 − speed/43 units/frame each frame (1.1 from a standstill); above it, on level ground, he loses 1. The target is at most 32, or 24 on slow floors, and the speed is capped at 48.Code
Quake II 1997On the ground, Quake II's Pmove runs PM_Friction, which lowers the speed by step time × 6 (pm_friction) × the larger of the speed and 100 (pm_stopspeed) on any ground that isn't slick, and then PM_Accelerate with pm_accelerate 10: if the speed along the wish direction is under the wish speed, it adds 10 × step time × wish speed, no more than the shortfall. The wish velocity's length is capped at 300 (pm_maxspeed), or 100 ducked. These are the numbers Quake III keeps (friction 6, acceleration 10), where Quake's friction is 4. Computed, not measured: since 10 outpaces 6, a run settles at exactly 300 units/s. The movement constants are C globals, not cvars.Code
Banjo-Kazooie 1998On the ground the stick's tilt sets Banjo's target speed in five bands of the stick's distance from center, each axis clamped to a raw 7 to 59 (x) or 7 to 61 (y) and scaled to 0 to 1, and the distance capped at 1. Up to 0.12 the target is 0; above it the target rises linearly within each band: 30 to 80 units/s up to 0.2, 80 to 150 up to 0.5, 150 to 225 up to 0.75, and 225 to 500 at full tilt. The decompilers name the bands creep, slow walk, walk, and fast walk. On ground flagged BA_FLAG_13_TOUCHING_DANGEROUS_GROUND, the target is instead 30 to 150 by the distance itself, and 0 inside the 0.12 dead zone. Each frame the horizontal velocity closes the gap to the target by a fraction from a five-entry table (0, 0.07, 0.29, 0.15, 0.05) indexed by the unnamed D_8037C284 (the atlas reads the index as a movement state), unless func_8029CF48 has set an override for that index, which func_8029CED0 then returns instead, times the frame's time over 1/30 s; when an unnamed floor check (func_80294548) passes, the target is first scaled by the slope. Super Mario 64's target is 32 times the square of the tilt, and Mario gains a fixed 1.1 − speed/43 units/frame below it (sm64/walking-speed).Code
Quake III Arena 1999On the ground, Quake III's PM_Friction takes the horizontal speed and lowers it by step time × pm_friction × the larger of the speed and pm_stopspeed, scaling all three velocity axes by the same factor, with pm_friction 6 and pm_stopspeed 100 set in the code; it skips ground friction in water deeper than level 1, on a slick surface, and while the knockback timer runs, and it has no edge friction. Quake's ground friction is the same rule with friction 4 (sv_friction) and the same stop speed, doubled over a ledge (quake/ground-friction).Code
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.Code
Sonic Advance 2 2002In Sonic Advance 2 the ground acceleration rises with the ring count. At the start of each frame Player_HandleBoostThreshold picks a bracket from the rings and Player_ApplyBoostPhysics sets the acceleration from playerBoostPhysicsTable: 8 subpixels (1/256 px/frame) a frame with 10 rings or fewer, 12 with 11 to 49, 14 with 50 to 99, 16 with 100 to 149, and 18 with 150 or more. The deceleration, taken when the d-pad is held against the motion, is 64 in every bracket, and the speed-up item doubles both. With neither Left nor Right held, or while unk2A counts down (a 30-frame timer set when the player slips off a steep slope, in the atlas's reading), Player_HandleGroundMovement takes a fixed 8 a frame off the speed toward 0. Sonic 1's rates are $C (12) to accelerate, the same $C for the friction, and $80 (128) against the motion.Code
Outside boost mode Player_ApplyBoostPhysics sets topSpeed, the speed holding forward builds to in Player_HandleGroundMovement, to 6 px/frame (Q(6.0)), Sonic 1's son_maxspeed ($600). A faster speed, from a slope, is cut only at maxSpeed, by sub_8023260, which the ground state (Player_Idle) calls after adding the slope term: 9 px/frame, or 15 while MOVESTATE_SPIN_ATTACK is set, as a spin dash sets it.Code
Boost mode starts from a run held at the top speed. Holding forward on the ground at 6 px/frame or faster, Player_HandleGroundMovement leaves the speed as it is and adds the frame's acceleration to boostSpeed, in the branch where Sonic 2's Sonic_MoveRight keeps a speed above the top and Sonic 1's cuts it back to the top. At the start of each frame Player_HandleBoostState turns boost mode on once boostSpeed reaches the ring bracket's entry in playerBoostThresholdTable: Q(8) (2048) with 10 rings or fewer, 2040 with 11 to 49, 1680 with 50 to 99, 1440 with 100 to 149, and 1080 with 150 or more. In the air or below the top speed it sets boostSpeed back to 0. With each bracket's acceleration that is 256, 170, 120, 90, and 60 frames of holding forward at the top speed, and half as many with the speed-up item (computed).Code
In boost mode Player_ApplyBoostPhysics raises topSpeed, the speed holding forward builds to, from 6 to 12 px/frame, twice Sonic 1's single top speed (son_maxspeed, $600; computed), and maxSpeed, the ground cap, to 15; the acceleration still follows the ring count. Player_HandleBoostState looks for the end of boost mode only on the ground, where a ground speed below 4.5 px/frame ends it. Among the other ends are a hit (Player_InitHurt), the start of Tails's or Cream's flight, a multiplayer finish, the special stage transition, and InitializePlayer.Code
Celeste 2018MaxRun, Madeline's top running speed, is 90 px/s, and the same limit applies in the air.Code
Each update moves Madeline's horizontal speed toward 90 px/s times the d-pad direction by RunAccel, 1000 px/s² on the ground, so the same rate speeds her up, turns her, and stops her.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
Holding Down on the ground ducks Madeline; while ducked, her speed moves toward 0 at DuckFriction, 500 px/s², whatever the d-pad holds.Code
Jump() adds JumpHBoost, 40 px/s, times the d-pad direction to Madeline's horizontal speed, after that update's running step, so a running jump leaves at 130 px/s.Code
Landing zeroes Madeline's vertical speed and leaves her horizontal speed alone; the landing update has already used the air rates, and the ground rates start on the next.Code
Madeline faces whichever way the d-pad points, on the ground or in the air, updated at the start of each update before her speed changes.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
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. ^ abSimon has no acceleration; each frame on the ground his direction bits are set from the d-pad's held Left and Right, and the move routine shifts him by his speed bytes, 1 px/frame, in that direction or not at all.Verified“Castlevania (USA) (Rev 1)”
    How we know

    In the cartridge (“Castlevania (USA) (Rev 1)”): bank 6 $93D9-$93E3, the standing state: copy the held buttons ($F7) to $0584, then call the direction routine $9809 and the move routine $989A; bank 6 $9815-$982E: direction bits $3C = bit 2 kept | ($0584 AND 3), the held Right (1) and Left (2); bank 6 $989A-$990A: no direction bits, no move; else add or subtract $3E.$3D to his screen X or to the camera; bank 7 $C9A5-$C9AC, stage start sets $3D = 0 and $3E = 1. 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

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

  3. ^Mega Man never accelerates; each frame his state's row of megaman_status_xcoord_speed_table sets the speed outright, 0 standing, 0.125 px/frame on the first step, 1.375 running, 1.3125 jumping, and 0.5 sliding to a stop.Codelsmmega/mm2
    How we know
    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:
    223	.BYTE $00
    224	.BYTE $00
    225	.BYTE $00
    226	.BYTE $00
    227	.BYTE $00
    228	.BYTE $01
    229	.BYTE $01
    230	.BYTE $00
    231	.BYTE $00
    232	.BYTE $00
    233	.BYTE $00
    ⋮
    
    engine/turn_megaman.asm lines 222–243 at 94f0bf3 · upstream ↗
    401run_megaman_lo_jumptable:
    402	.LOBYTES _run_megaman_teleport_out
    403	.LOBYTES _run_megaman_nothing
    404	.LOBYTES _run_megaman_megaman_hit
    405	.LOBYTES _run_megaman_standing
    406	.LOBYTES _run_megaman_walk_slow
    407	.LOBYTES _run_megaman_running
    408	.LOBYTES _run_megaman_jumping
    409	.LOBYTES _run_megaman_landing
    410	.LOBYTES _run_megaman_landing
    
    engine/run_megaman.asm lines 401–412 at 94f0bf3 · 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

  4. ^Measured in the game, Mega Man first steps 0.125 px/frame for 7 frames, then runs at 1.375 px/frame.Verifiedlsmmega/mm2
    How we know
    222megaman_status_xcoord_speed_table:
    223	.BYTE $00
    224	.BYTE $00
    225	.BYTE $00
    226	.BYTE $00
    227	.BYTE $00
    228	.BYTE $01
    229	.BYTE $01
    230	.BYTE $00
    231	.BYTE $00
    232	.BYTE $00
    233	.BYTE $00
    ⋮
    
    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.

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

    In the claim ledger

  5. ^ abcdMega 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

  6. ^On the ground Samus accelerates at $30/256 (0.1875) px/frame² toward SamusHorzSpdMax/16 px/frame, which VertAccelerate sets to $18 (1.5 px/frame) while she is grounded. With no direction held, StopHorzMovement clears her horizontal speed at once.Codenmikstas/metroid-disassembly
    How we know
    2245RunAccelerationTbl:
    2246LCCC0:  .byte $30           ;Accelerate right.
    2247    .byte $D0           ;Accelerate left.
    
    Source_Files/Bank07.asm lines 2245–2247 at 4270d57 · upstream ↗
    5590LE37A:  lda SamusGravity        ;Is Samus rising or falling?
    5591LE37D:  bne ++              ;Branch if yes.
    5592LE37F:  lda #$18            ;
    5593LE381:  sta SamusHorzSpdMax       ;Set Samus maximum running speed.
    
    Source_Files/Bank07.asm lines 5590–5593 at 4270d57 · upstream ↗
    5648HorzAccelerate:
    5649LE3E5:  lda SamusHorzSpdMax
    5650    jsr Amul16       ; * 16
    ⋮
    5653    lda SamusHorzSpdMax
    5654    jsr Adiv16       ; / 16
    ⋮
    5658    lda HorzCntrLinear
    5659    clc
    5660    adc SamusHorzAccel
    5661    sta HorzCntrLinear
    ⋮
    5670    sta ObjHorzSpeed
    ⋮
    5687    lda $00
    5688    sta HorzCntrLinear
    ⋮
    
    Source_Files/Bank07.asm lines 5648–5690 at 4270d57 · upstream ↗
    2316*   lda Joy1Status
    2317    and #$03
    2318    bne +
    2319    jsr LCF55
    
    Source_Files/Bank07.asm lines 2316–2319 at 4270d57 · upstream ↗
    2603ClearHorzMvmntData:
    2604LCF4C:  LDY #$00                ;
    ⋮
    2606        STY HorzCntrLinear      ;linear counter to #$00.
    ⋮
    2609StopHorzMovement:
    ⋮
    2615LCF5D:  JSR NoHorzMoveNoDelay   ;($CF81)Clear horizontal movement and animation delay data.
    ⋮
    2638LCF81:  JSR ClearHorzData       ;($CFB7)Clear all horizontal movement data.
    ⋮
    2664ClearHorzData:
    2665LCFB7:  JSR ClearHorzMvmntData  ;($CF4C)Clear horizontal speed and linear counter.
    
    Source_Files/Bank07.asm lines 2600–2666 at 4270d57 · 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

  7. ^From a standstill, the first frame with Left or Right held doesn't move Samus. SamusStand picks the running state, calls SetSamusData, which moves her at her speed of 0, and only then calls SetSamusRun, which sets her acceleration. Her speed rises from the next frame.Codenmikstas/metroid-disassembly
    How we know
    2162SamusStand:
    2163LCC36:  LDA Joy1Status          ;Status of joypad 1.
    2164LCC38:  AND #$CF                ;Remove SELECT & START status bits.
    2165LCC3A:  BEQ +                   ;Branch if no buttons pressed.
    2166LCC3C:  JSR ClearHrztAnimData   ;($CF5D)Set no horiontal movement and single frame animation.
    ⋮
    2173LCC4B:* JSR BitScan             ;($E1E1)Find which directional button is pressed.
    ⋮
    2176LCC52:  STA SamusDir            ;1=left, 0=right.
    2177LCC54:* TAX                     ;
    2178LCC55:  LDA ActionTable,x       ;Load proper Samus status from table below.
    2179LCC58:  STA ObjAction           ;Save Samus status.
    ⋮
    2190LCC70:  JSR SetSamusData        ;($CD6D)Set Samus control data and animation.
    ⋮
    2194LCC7A:  JSR ChooseRoutine       ;Select routine below.
    ⋮
    
    Source_Files/Bank07.asm lines 2162–2199 at 4270d57 · upstream ↗
    2236    ldx SamusDir
    2237LCCB7:  lda RunAccelerationTbl,x
    2238    sta SamusHorzAccel
    
    Source_Files/Bank07.asm lines 2236–2238 at 4270d57 · upstream ↗

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

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

    In the claim ledger

  8. ^Running on the ground, Left or Right against Samus's facing turns her and sets the acceleration toward the new side on that frame, through SetSamusRun, but leaves her speed as it is. She slows by 0.1875 px/frame each frame, passes 0, and speeds up the other way: from 1.5 px/frame, 16 frames to 1.5 px/frame the other way (computed).Codenmikstas/metroid-disassembly
    How we know
    2316*   lda Joy1Status
    2317    and #$03
    2318    bne +
    2319    jsr LCF55
    2320    jmp LCD6B
    ⋮
    2322*   jsr BitScan         ;($E1E1)
    2323    cmp SamusDir
    2324    beq LCD6B
    2325    sta SamusDir
    2326    jsr LCC98
    
    Source_Files/Bank07.asm lines 2316–2326 at 4270d57 · upstream ↗
    2236    ldx SamusDir
    2237LCCB7:  lda RunAccelerationTbl,x
    2238    sta SamusHorzAccel
    ⋮
    2246LCCC0:  .byte $30           ;Accelerate right.
    2247    .byte $D0           ;Accelerate left.
    
    Source_Files/Bank07.asm lines 2236–2247 at 4270d57 · upstream ↗
    5658    lda HorzCntrLinear
    5659    clc
    5660    adc SamusHorzAccel
    5661    sta HorzCntrLinear
    
    Source_Files/Bank07.asm lines 5658–5661 at 4270d57 · upstream ↗

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

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

    In the claim ledger

  9. ^ abcIn the running game, on flat ground, Sonic reaches top speed from a standstill in 128 frames, and from top speed he coasts to a stop in 128 frames with the d-pad released.Verifiedsonicretro/s1disasmrevised
    How we know
    5son_maxspeed:		equ	$600				; Sonic's max speed
    6son_acceleration:	equ	$C				; Sonic's acceleration
    
    _incObj/01 Sonic.asm lines 5–6 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

  10. ^ abcIn the running game, on flat ground, turning around from top speed takes 140 frames to reach top speed the other way when Sonic runs right, and 130 when he runs left.Verifiedsonicretro/s1disasmrevised
    How we know
    665.changeddirection:
    666		sub.w	d4,d0					; apply deceleration to current speed
    667		bcc.s	.stilldecel       			; if still decelerating, branch
    668		move.w	#-$80,d0        			; set minimum speed on sign change
    
    _incObj/01 Sonic.asm lines 636–672 at 15dfa3a · upstream ↗
    715.alreadyright:
    716		add.w	d5,d0					; add acceleration to current ground speed
    717		cmp.w	d6,d0					; is new speed above max speed?
    718		blt.s	.nocap					; if not, branch
    719		move.w	d6,d0					; cap Sonic's ground speed
    
    _incObj/01 Sonic.asm lines 706–736 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

  11. ^ abObj01_Init sets Sonic's top speed to $600, his acceleration to $C, and his deceleration to $80 subpixels, Sonic 1's values; speed shoes and Super Sonic swap in others.Codesonicretro/s2disasm · sonicretro/s1disasmrevised
    How we know
    36232	move.w	#$600,(Sonic_top_speed).w	; set Sonic's top speed
    36233	move.w	#$C,(Sonic_acceleration).w	; set Sonic's acceleration
    36234	move.w	#$80,(Sonic_deceleration).w	; set Sonic's deceleration
    
    s2.asm lines 36232–36234 at 4ef457c · upstream ↗
    36364	move.w	#$A00,(Sonic_top_speed).w		; restore Super Sonic's top speed
    
    s2.asm lines 36364–36366 at 4ef457c · upstream ↗
    5son_maxspeed:		equ	$600				; Sonic's max speed
    6son_acceleration:	equ	$C				; Sonic's acceleration
    7son_deceleration:	equ	$80				; Sonic's deceleration
    
    _incObj/01 Sonic.asm lines 5–7 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

  12. ^ abHolding forward no longer pulls a faster Sonic down to the top speed on the ground; Sonic_MoveRight undoes the frame's acceleration and keeps the speed he had.Codesonicretro/s2disasm · sonicretro/s1disasmrevised
    How we know
    36998	add.w	d5,d0	; add acceleration to the right
    ⋮
    37001	sub.w	d5,d0	; remove this frame's acceleration change
    ⋮
    37003	bge.s	+		; if speed was already greater than the maximum, branch
    37004	move.w	d6,d0	; limit speed on ground going right
    
    s2.asm lines 36998–37004 at 4ef457c · upstream ↗
    716		add.w	d5,d0					; add acceleration to current ground speed
    717		cmp.w	d6,d0					; is new speed above max speed?
    718		blt.s	.nocap					; if not, branch
    719		move.w	d6,d0					; cap Sonic's ground speed
    
    _incObj/01 Sonic.asm lines 716–719 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

  13. ^ abSonic_Init sets the top speed to $600, the acceleration to $C, and the deceleration to $80 subpixels, the values of Sonic 1 and Sonic 2.Codesonicretro/skdisasm · sonicretro/s1disasm · sonicretro/s2disasmrevised
    How we know
    21950		move.w	#$600,Max_speed-Max_speed(a4)
    21951		move.w	#$C,Acceleration-Max_speed(a4)
    21952		move.w	#$80,Deceleration-Max_speed(a4)
    
    sonic3k.asm lines 21950–21952 at 73de97c · upstream ↗
    22902		add.w	d5,d0
    22903		cmp.w	d6,d0
    22904		blt.s	loc_114AA
    22905		sub.w	d5,d0
    22906		cmp.w	d6,d0
    22907		bge.s	loc_114AA
    22908		move.w	d6,d0
    
    sonic3k.asm lines 22902–22908 at 73de97c · upstream ↗
    5son_maxspeed:		equ	$600				; Sonic's max speed
    6son_acceleration:	equ	$C				; Sonic's acceleration
    7son_deceleration:	equ	$80				; Sonic's deceleration
    
    _incObj/01 Sonic.asm lines 5–7 at 15dfa3a · upstream ↗
    36232	move.w	#$600,(Sonic_top_speed).w	; set Sonic's top speed
    36233	move.w	#$C,(Sonic_acceleration).w	; set Sonic's acceleration
    36234	move.w	#$80,(Sonic_deceleration).w	; set Sonic's deceleration
    
    s2.asm lines 36232–36234 at 4ef457c · upstream ↗
    37001	sub.w	d5,d0	; remove this frame's acceleration change
    
    s2.asm lines 36998–37004 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

  14. ^ abOn the ground the stick's tilt sets a target speed: intendedMag is 32 times the square of the tilt's fraction of full. Below the target Mario gains 1.1 − speed/43 units/frame each frame (1.1 from a standstill); above it, on level ground, he loses 1. The target is at most 32, or 24 on slow floors, and the speed is capped at 48.Coden64decomp/sm64
    How we know
    1295    f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f;
    ⋮
    1298        m->intendedMag = mag / 2.0f;
    
    src/game/mario.c lines 1295–1298 at 9921382 · upstream ↗
    455    if (controller->stickMag > 64) {
    ⋮
    458        controller->stickMag = 64;
    
    src/game/game_init.c lines 455–458 at 9921382 · upstream ↗
    438    if (m->floor != NULL && m->floor->type == SURFACE_SLOW) {
    439        maxTargetSpeed = 24.0f;
    440    } else {
    441        maxTargetSpeed = 32.0f;
    ⋮
    444    targetSpeed = m->intendedMag < maxTargetSpeed ? m->intendedMag : maxTargetSpeed;
    ⋮
    450    if (m->forwardVel <= 0.0f) {
    451        m->forwardVel += 1.1f;
    452    } else if (m->forwardVel <= targetSpeed) {
    453        m->forwardVel += 1.1f - m->forwardVel / 43.0f;
    454    } else if (m->floor->normal.y >= 0.95f) {
    455        m->forwardVel -= 1.0f;
    ⋮
    458    if (m->forwardVel > 48.0f) {
    ⋮
    
    src/game/mario_actions_moving.c lines 438–460 at 9921382 · 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

  15. ^Horizontal speeds are 4.4 fixed point, whole pixels and sixteenths per frame; MoveObjectHorizontally shifts the sixteenths into the subpixel byte.CodeXkeeper0/smb1
    How we know
    6495	ASL                                          ; and move low nybble to high
    6496	ASL
    6497	ASL
    ⋮
    6500	LSR                                          ; move high nybble to low
    6501	LSR
    6502	LSR
    6503	LSR
    
    src/prg.asm lines 6492–6503 at 1cc3c92 · upstream ↗

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

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

    In the claim ledger

  16. ^Mario's top ground speed is $18 walking and $28 running (B held).CodeXkeeper0/smb1 · Jdaster64 n.d.
    How we know
    4873MaxRightXSpdData:
    4874	.db $28, $18, $10
    
    src/prg.asm lines 4873–4874 at 1cc3c92 · upstream ↗
    5009	AND #B_Button
    5010	BNE SetRTmr                                  ; if pressed, skip ahead to set timer
    ⋮
    5014	INY                                          ; if running timer not set or level type is water,
    
    src/prg.asm lines 5000–5014 at 1cc3c92 · upstream ↗
    Maximum walk speed (normal, castle cutscene) 01900 | Maximum running speed 02900
    SMB PHYSICS 101 / GROUND PHYSICS, Mario table · archived copy ↗

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

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

    In the claim ledger

  17. ^DATA_00D535 caps Mario's ground speed at $14 walking and $24 holding Y, and at $30 while the P-meter is full and charging.CodeSMWDisX
    How we know
    9764DATA_00D535:                                  ;!
    9765    db $EC,$14,$DC,$24,$DC,$24,$D0,$30        ;!
    
    bank_00.asm lines 9764–9765 at 30643c7 · upstream ↗
    10083    LDA.B PlayerXSpeed+1
    ⋮
    10087  + CMP.B #con($23,$23,$23,$2C,$2C)
    10088    BMI CODE_00D737
    10089    LDA.B PlayerInAir
    10090    BNE CODE_00D732
    10091    LDA.B #$10
    10092    STA.W RunTakeoffTimer
    10093    BRA CODE_00D736
    ⋮
    10098CODE_00D736:
    10099    INY
    10100CODE_00D737:
    10101    JSR CODE_00D96A
    ⋮
    
    bank_00.asm lines 10083–10106 at 30643c7 · upstream ↗
    10504CODE_00D96A:
    10505    LDA.W PlayerPMeter
    10506    CLC
    10507    ADC.W DATA_00D5EB,Y
    10508    BPL +
    10509    LDA.B #$00
    10510  + CMP.B #con($70,$70,$70,$40,$68)
    10511    BCC +
    10512    INY
    10513    LDA.B #con($70,$70,$70,$40,$68)
    10514  + STA.W PlayerPMeter
    
    bank_00.asm lines 10504–10514 at 30643c7 · upstream ↗
    9908DATA_00D5EB:                                  ;!
    9909    db $FF,$FF,$02                            ;!
    
    bank_00.asm lines 9908–9909 at 30643c7 · 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

  18. ^Measured on flat ground, Mario's top speed is 20/16 px/frame walking, 36/16 holding Y, and 47/16 to 49/16 once the P-meter is full, near DATA_00D535's $14, $24, and $30.VerifiedSMWDisX
    How we know
    9764DATA_00D535:                                  ;!
    9765    db $EC,$14,$DC,$24,$DC,$24,$D0,$30        ;!
    
    bank_00.asm lines 9764–9765 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-20.

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

    In the claim ledger

  19. ^ abIn Sonic Advance 2 the ground acceleration rises with the ring count. At the start of each frame Player_HandleBoostThreshold picks a bracket from the rings and Player_ApplyBoostPhysics sets the acceleration from playerBoostPhysicsTable: 8 subpixels (1/256 px/frame) a frame with 10 rings or fewer, 12 with 11 to 49, 14 with 50 to 99, 16 with 100 to 149, and 18 with 150 or more. The deceleration, taken when the d-pad is held against the motion, is 64 in every bracket, and the speed-up item doubles both. With neither Left nor Right held, or while unk2A counts down (a 30-frame timer set when the player slips off a steep slope, in the atlas's reading), Player_HandleGroundMovement takes a fixed 8 a frame off the speed toward 0. Sonic 1's rates are $C (12) to accelerate, the same $C for the friction, and $80 (128) against the motion.CodeSAT-R/sa2 · sonicretro/s1disasm
    How we know
    4899#if (GAME == GAME_SA2)
    4900    Player_HandleBoostThreshold(p);
    4901    Player_HandleBoostState(p);
    4902    Player_ApplyBoostPhysics(p);
    
    src/game/shared/stage/player.c lines 4899–4902 at 393357f · upstream ↗
    9107void Player_HandleBoostThreshold(Player *p)
    ⋮
    9109    if (gRingCount >= 150) {
    9110        p->boostThreshold = 4;
    9111    } else if (gRingCount >= 100) {
    9112        p->boostThreshold = 3;
    9113    } else if (gRingCount >= 50) {
    9114        p->boostThreshold = 2;
    9115    } else if (gRingCount > 10) {
    9116        p->boostThreshold = 1;
    9117    } else {
    9118        p->boostThreshold = 0;
    
    src/game/shared/stage/player.c lines 9107–9120 at 393357f · upstream ↗
    552static const s16 playerBoostPhysicsTable[5][2] = {
    553    { 8, 64 }, { 12, 64 }, { 14, 64 }, { 16, 64 }, { 18, 64 },
    
    src/game/shared/stage/player.c lines 552–553 at 393357f · upstream ↗
    9926    p->acceleration = playerBoostPhysicsTable[boostThreshold][0];
    9927    p->deceleration = playerBoostPhysicsTable[boostThreshold][1];
    
    src/game/shared/stage/player.c lines 9926–9927 at 393357f · upstream ↗
    4907    Player_HandleInputs(p);
    ⋮
    4910    Player_HandleWater(p);
    
    src/game/shared/stage/player.c lines 4907–4910 at 393357f · upstream ↗
    4429    if (p->itemEffect & PLAYER_ITEM_EFFECT__SPEED_UP) {
    ⋮
    4432        p->acceleration = p->acceleration * 2;
    4433        p->deceleration = p->deceleration * 2;
    4434#else
    4435        p->acceleration = p->acceleration * 2;
    4436        p->deceleration = p->deceleration * 2;
    
    src/game/shared/stage/player.c lines 4429–4437 at 393357f · upstream ↗
    6652    if (!Player_TryTaunt(p) && !Player_TryCrouchOrSpinAttack(p) && !Player_TryJump(p)
    ⋮
    6658        Player_HandleGroundMovement(p);
    
    src/game/shared/stage/player.c lines 6652–6658 at 393357f · upstream ↗
    8965void Player_HandleGroundMovement(Player *p)
    ⋮
    8967    s8 charState = CHARSTATE_INVALID;
    8968    s32 acc = p->acceleration;
    8969    s32 dec = p->deceleration;
    ⋮
    8971    if ((p->SA2_LABEL(unk2A) == 0) && p->heldInput & (DPAD_LEFT | DPAD_RIGHT)) {
    8972        if (p->qSpeedGround > 0) {
    8973            if (p->heldInput & DPAD_RIGHT) {
    8974                if (p->qSpeedGround < p->topSpeed) {
    8975                    p->qSpeedGround += acc;
    
    src/game/shared/stage/player.c lines 8965–8975 at 393357f · upstream ↗
    8984            } else if (p->qSpeedGround >= Q(2.0)) {
    ⋮
    8994                p->qSpeedGround -= dec;
    
    src/game/shared/stage/player.c lines 8984–8994 at 393357f · upstream ↗
    9063    } else {
    9064        s32 grndSpeed = p->qSpeedGround;
    9065        if (grndSpeed > 0) {
    9066            s16 val = grndSpeed - Q(8.0 / 256.0);
    9067            if (val <= 0) {
    9068                val = 0;
    ⋮
    9070            } else {
    
    src/game/shared/stage/player.c lines 9063–9074 at 393357f · upstream ↗
    118#define PLAYERFN_UPDATE_UNK2A(player)                                                                                                      \
    119    {                                                                                                                                      \
    120        if (player->SA2_LABEL(unk2A) != 0) {                                                                                               \
    121            player->SA2_LABEL(unk2A) -= 1;                                                                                                 \
    122        } else if ((player->rotation + Q(0.125)) & 0xC0) {                                                                                 \
    123            if (ABS(player->qSpeedGround) < Q(1.875)) {                                                                                    \
    ⋮
    127                player->SA2_LABEL(unk2A) = GBA_FRAMES_PER_SECOND / 2;                                                                      \
    
    src/game/shared/stage/player.c lines 118–127 at 393357f · upstream ↗
    5son_maxspeed:		equ	$600				; Sonic's max speed
    6son_acceleration:	equ	$C				; Sonic's acceleration
    7son_deceleration:	equ	$80				; Sonic's deceleration
    
    _incObj/01 Sonic.asm lines 5–7 at 15dfa3a · upstream ↗
    499Sonic_CheckDpadLetGo:
    ⋮
    501		andi.b	#btnL+btnR,d0				; is left or right held?
    ⋮
    506		sub.w	d5,d0					; reduce current rightward speed by acceleration
    
    _incObj/01 Sonic.asm lines 499–506 at 15dfa3a · 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

  20. ^ abOutside boost mode Player_ApplyBoostPhysics sets topSpeed, the speed holding forward builds to in Player_HandleGroundMovement, to 6 px/frame (Q(6.0)), Sonic 1's son_maxspeed ($600). A faster speed, from a slope, is cut only at maxSpeed, by sub_8023260, which the ground state (Player_Idle) calls after adding the slope term: 9 px/frame, or 15 while MOVESTATE_SPIN_ATTACK is set, as a spin dash sets it.CodeSAT-R/sa2 · sonicretro/s1disasm
    How we know
    9912void Player_ApplyBoostPhysics(Player *p)
    ⋮
    9914    u32 boostThreshold = p->boostThreshold;
    9915    if (p->isBoosting) {
    9916        p->topSpeed = Q(12.0);
    9917        p->maxSpeed = Q(15.0);
    9918    } else if (p->moveState & MOVESTATE_SPIN_ATTACK) {
    9919        p->topSpeed = Q(6.0);
    9920        p->maxSpeed = Q(15.0);
    9921    } else {
    9922        p->topSpeed = Q(6.0);
    9923        p->maxSpeed = Q(9.0);
    
    src/game/shared/stage/player.c lines 9912–9924 at 393357f · upstream ↗
    8974                if (p->qSpeedGround < p->topSpeed) {
    8975                    p->qSpeedGround += acc;
    ⋮
    8977                    if (p->qSpeedGround > p->topSpeed) {
    8978                        p->qSpeedGround = p->topSpeed;
    
    src/game/shared/stage/player.c lines 8974–8979 at 393357f · upstream ↗
    6658        Player_HandleGroundMovement(p);
    ⋮
    6660        if (((p->rotation + Q(0.375)) & 0xFF) < 0xC0) {
    6661            s32 acceleration = GET_ROTATED_ACCEL(p->rotation);
    ⋮
    6664                p->qSpeedGround += acceleration;
    ⋮
    6669        SA2_LABEL(sub_8023260)(p);
    
    src/game/shared/stage/player.c lines 6658–6669 at 393357f · upstream ↗
    3383void SA2_LABEL(sub_8023260)(Player *p)
    ⋮
    3385    s32 maxSpeed = p->maxSpeed;
    ⋮
    3387    if (p->qSpeedGround > (s16)maxSpeed) {
    3388        p->qSpeedGround = +maxSpeed;
    
    src/game/shared/stage/player.c lines 3383–3388 at 393357f · upstream ↗
    7190    p->moveState |= (MOVESTATE_SPINDASH | MOVESTATE_SPIN_ATTACK);
    
    src/game/shared/stage/player.c line 7190 at 393357f · upstream ↗
    5son_maxspeed:		equ	$600				; Sonic's max speed
    
    _incObj/01 Sonic.asm line 5 at 15dfa3a · 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. ^Boost mode starts from a run held at the top speed. Holding forward on the ground at 6 px/frame or faster, Player_HandleGroundMovement leaves the speed as it is and adds the frame's acceleration to boostSpeed, in the branch where Sonic 2's Sonic_MoveRight keeps a speed above the top and Sonic 1's cuts it back to the top. At the start of each frame Player_HandleBoostState turns boost mode on once boostSpeed reaches the ring bracket's entry in playerBoostThresholdTable: Q(8) (2048) with 10 rings or fewer, 2040 with 11 to 49, 1680 with 50 to 99, 1440 with 100 to 149, and 1080 with 150 or more. In the air or below the top speed it sets boostSpeed back to 0. With each bracket's acceleration that is 256, 170, 120, 90, and 60 frames of holding forward at the top speed, and half as many with the speed-up item (computed).CodeSAT-R/sa2 · sonicretro/s2disasm · sonicretro/s1disasm
    How we know
    8972        if (p->qSpeedGround > 0) {
    8973            if (p->heldInput & DPAD_RIGHT) {
    8974                if (p->qSpeedGround < p->topSpeed) {
    ⋮
    8980                } else {
    8981                    p->boostSpeed += acc;
    
    src/game/shared/stage/player.c lines 8972–8982 at 393357f · upstream ↗
    9009        } else if (p->qSpeedGround < 0) {
    9010            if (p->heldInput & DPAD_LEFT) {
    9011                if (p->qSpeedGround > -p->topSpeed) {
    ⋮
    9017                } else {
    9018                    p->boostSpeed += acc;
    
    src/game/shared/stage/player.c lines 9009–9019 at 393357f · upstream ↗
    556static const s16 playerBoostThresholdTable[5] = { Q(8), Q(7.96875), Q(6.5625), Q(5.625), Q(4.21875) };
    
    src/game/shared/stage/player.c line 556 at 393357f · upstream ↗
    4899#if (GAME == GAME_SA2)
    4900    Player_HandleBoostThreshold(p);
    4901    Player_HandleBoostState(p);
    4902    Player_ApplyBoostPhysics(p);
    
    src/game/shared/stage/player.c lines 4899–4902 at 393357f · upstream ↗
    9122void Player_HandleBoostState(Player *p)
    ⋮
    9124    bool32 isBoostActive = p->isBoosting;
    9125    if (isBoostActive) {
    ⋮
    9134    } else {
    9135        if ((!(p->moveState & MOVESTATE_IN_AIR)) && ((ABS(p->qSpeedGround) >= p->topSpeed))) {
    9136            if (p->boostSpeed >= playerBoostThresholdTable[p->boostThreshold]) {
    9137                p->isBoosting = TRUE;
    ⋮
    9144        } else {
    9145#ifndef NON_MATCHING
    9146            p->boostSpeed = isBoostActive;
    
    src/game/shared/stage/player.c lines 9122–9150 at 393357f · upstream ↗
    552static const s16 playerBoostPhysicsTable[5][2] = {
    553    { 8, 64 }, { 12, 64 }, { 14, 64 }, { 16, 64 }, { 18, 64 },
    
    src/game/shared/stage/player.c lines 552–553 at 393357f · upstream ↗
    4429    if (p->itemEffect & PLAYER_ITEM_EFFECT__SPEED_UP) {
    ⋮
    4432        p->acceleration = p->acceleration * 2;
    ⋮
    4435        p->acceleration = p->acceleration * 2;
    
    src/game/shared/stage/player.c lines 4429–4437 at 393357f · upstream ↗
    36998	add.w	d5,d0	; add acceleration to the right
    36999	cmp.w	d6,d0	; compare new speed with top speed
    37000	blt.s	+		; if new speed is less than the maximum, branch
    37001	sub.w	d5,d0	; remove this frame's acceleration change
    37002	cmp.w	d6,d0	; compare speed with top speed
    37003	bge.s	+		; if speed was already greater than the maximum, branch
    37004	move.w	d6,d0	; limit speed on ground going right
    
    s2.asm lines 36998–37004 at 4ef457c · upstream ↗
    716		add.w	d5,d0					; add acceleration to current ground speed
    717		cmp.w	d6,d0					; is new speed above max speed?
    718		blt.s	.nocap					; if not, branch
    719		move.w	d6,d0					; cap Sonic's ground speed
    
    _incObj/01 Sonic.asm lines 716–719 at 15dfa3a · 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

  22. ^ abIn boost mode Player_ApplyBoostPhysics raises topSpeed, the speed holding forward builds to, from 6 to 12 px/frame, twice Sonic 1's single top speed (son_maxspeed, $600; computed), and maxSpeed, the ground cap, to 15; the acceleration still follows the ring count. Player_HandleBoostState looks for the end of boost mode only on the ground, where a ground speed below 4.5 px/frame ends it. Among the other ends are a hit (Player_InitHurt), the start of Tails's or Cream's flight, a multiplayer finish, the special stage transition, and InitializePlayer.CodeSAT-R/sa2 · sonicretro/s1disasmrevised
    How we know
    9912void Player_ApplyBoostPhysics(Player *p)
    ⋮
    9914    u32 boostThreshold = p->boostThreshold;
    9915    if (p->isBoosting) {
    9916        p->topSpeed = Q(12.0);
    9917        p->maxSpeed = Q(15.0);
    ⋮
    9920        p->maxSpeed = Q(15.0);
    ⋮
    9926    p->acceleration = playerBoostPhysicsTable[boostThreshold][0];
    
    src/game/shared/stage/player.c lines 9912–9927 at 393357f · upstream ↗
    9122void Player_HandleBoostState(Player *p)
    ⋮
    9124    bool32 isBoostActive = p->isBoosting;
    9125    if (isBoostActive) {
    9126        if (!(p->moveState & MOVESTATE_IN_AIR)) {
    9127            p->boostSpeed = playerBoostThresholdTable[p->boostThreshold];
    ⋮
    9129            if (ABS(p->qSpeedGround) < Q(4.5)) {
    9130                p->isBoosting = FALSE;
    9131                p->boostSpeed = 0;
    
    src/game/shared/stage/player.c lines 9122–9133 at 393357f · upstream ↗
    7856void Player_InitHurt(Player *p)
    ⋮
    7858    p->timerInvulnerability = 0x78;
    7859    p->isBoosting = FALSE;
    
    src/game/shared/stage/player.c lines 7856–7859 at 393357f · upstream ↗
    893void Player_Tails_InitFlying(Player *p)
    ⋮
    905    p->isBoosting = FALSE;
    
    src/game/sa2/stage/player_callbacks.c lines 893–905 at 393357f · upstream ↗
    632void Player_Cream_InitFlying(Player *p)
    ⋮
    644    p->isBoosting = FALSE;
    
    src/game/sa2/stage/player_callbacks.c lines 632–644 at 393357f · upstream ↗
    8193void Player_HandleMultiplayerFinish(Player *p)
    ⋮
    8230        p->isBoosting = FALSE;
    
    src/game/shared/stage/player.c lines 8193–8230 at 393357f · upstream ↗
    10050void Player_InitSpecialStageTransition(Player *p)
    ⋮
    10057    p->isBoosting = FALSE;
    
    src/game/shared/stage/player.c lines 10050–10057 at 393357f · upstream ↗
    976void InitializePlayer(Player *p)
    ⋮
    987    if (
    ⋮
    999#if (GAME == GAME_SA2)
    ⋮
    1059#if (GAME == GAME_SA2)
    1060    p->transition = 0;
    1061    p->unk6E = 0;
    1062    p->prevTransition = 0;
    1063    p->isBoosting = FALSE;
    
    src/game/shared/stage/player.c lines 976–1063 at 393357f · upstream ↗
    5son_maxspeed:		equ	$600				; Sonic's max speed
    
    _incObj/01 Sonic.asm line 5 at 15dfa3a · 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. ^Wolfenstein 3D keeps no velocity for the player: each frame ControlMovement zeroes thrustspeed, and Thrust moves the player straight through ClipMove by the frame's control value times MOVESCALE (150), or BACKMOVESCALE (100) backward. The keyboard sets that value to 35 a tic walking (BASEMOVE) or 70 running (RUNMOVE), times the frame's tics, so a walk moves 5,250 and a run 10,500 units a tic, with 65,536 units to a tile (TILEGLOBAL); Thrust clamps each move to MINDIST*2-1 (45,055), so those rates hold on frames of at most 8 tics walking or 4 running, and longer frames move less a tic. At the 70 tics a second of TickBase's comment a run is about 11.2 tiles a second (computed).Codeid-Software/wolf3drevised
    How we know
    18#define MOVESCALE		150l
    19#define BACKMOVESCALE	100l
    
    WOLFSRC/WL_AGENT.C lines 18–19 at 0516778 · upstream ↗
    156	thrustspeed = 0;
    
    WOLFSRC/WL_AGENT.C line 156 at 0516778 · upstream ↗
    205	if (controly < 0)
    ⋮
    207		Thrust (ob->angle,-controly*MOVESCALE);	// move forwards
    ⋮
    209	else if (controly > 0)
    ⋮
    211		angle = ob->angle + ANGLES/2;
    212		if (angle >= ANGLES)
    213			angle -= ANGLES;
    214		Thrust (angle,controly*BACKMOVESCALE);		// move backwards
    
    WOLFSRC/WL_AGENT.C lines 205–214 at 0516778 · upstream ↗
    943	thrustspeed += speed;
    ⋮
    945// moving bounds speed
    ⋮
    947	if (speed >= MINDIST*2)
    948		speed = MINDIST*2-1;
    ⋮
    950	xmove = FixedByFrac(speed,costable[angle]);
    951	ymove = -FixedByFrac(speed,sintable[angle]);
    ⋮
    953	ClipMove(player,xmove,ymove);
    
    WOLFSRC/WL_AGENT.C lines 943–953 at 0516778 · upstream ↗
    115#define MINDIST		(0x5800l)
    
    WOLFSRC/WL_DEF.H line 115 at 0516778 · upstream ↗
    246#define BASEMOVE		35
    247#define RUNMOVE			70
    
    WOLFSRC/WL_PLAY.C lines 246–247 at 0516778 · upstream ↗
    343	if (buttonstate[bt_run])
    ⋮
    345		if (Keyboard[dirscan[di_north]])
    346			controly -= RUNMOVE*tics;
    347		if (Keyboard[dirscan[di_south]])
    348			controly += RUNMOVE*tics;
    349		if (Keyboard[dirscan[di_west]])
    350			controlx -= RUNMOVE*tics;
    351		if (Keyboard[dirscan[di_east]])
    352			controlx += RUNMOVE*tics;
    ⋮
    354	else
    ⋮
    356		if (Keyboard[dirscan[di_north]])
    357			controly -= BASEMOVE*tics;
    
    WOLFSRC/WL_PLAY.C lines 343–357 at 0516778 · upstream ↗
    97#define GLOBAL1		(1l<<16)
    98#define TILEGLOBAL  GLOBAL1
    
    WOLFSRC/WL_DEF.H lines 97–98 at 0516778 · upstream ↗
    17#define	TickBase	70		// 70Hz per tick - used as a base for timer 0
    
    WOLFSRC/ID_SD.H line 17 at 0516778 · 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

  24. ^On the ground, Quake III's PM_Friction takes the horizontal speed and lowers it by step time × pm_friction × the larger of the speed and pm_stopspeed, scaling all three velocity axes by the same factor, with pm_friction 6 and pm_stopspeed 100 set in the code; it skips ground friction in water deeper than level 1, on a slick surface, and while the knockback timer runs, and it has no edge friction. Quake's ground friction is the same rule with friction 4 (sv_friction) and the same stop speed, doubled over a ledge (quake/ground-friction).Codeid-Software/Quake-III-Arena · id-Software/Quakerevised
    How we know
    34float	pm_stopspeed = 100.0f;
    
    code/game/bg_pmove.c line 34 at dbe4ddb · upstream ↗
    44float	pm_friction = 6.0f;
    
    code/game/bg_pmove.c line 44 at dbe4ddb · upstream ↗
    180	VectorCopy( vel, vec );
    181	if ( pml.walking ) {
    182		vec[2] = 0;	// ignore slope movement
    ⋮
    185	speed = VectorLength(vec);
    ⋮
    196	if ( pm->waterlevel <= 1 ) {
    197		if ( pml.walking && !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) {
    198			// if getting knocked back, no friction
    199			if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) {
    200				control = speed < pm_stopspeed ? pm_stopspeed : speed;
    201				drop += control*pm_friction*pml.frametime;
    ⋮
    221	newspeed = speed - drop;
    222	if (newspeed < 0) {
    ⋮
    
    code/game/bg_pmove.c lines 180–229 at dbe4ddb · upstream ↗
    42cvar_t	sv_friction = {"sv_friction","4",false,true};
    43cvar_t	sv_stopspeed = {"sv_stopspeed","100"};
    
    WinQuake/sv_phys.c lines 42–43 at bf4ac42 · upstream ↗
    27cvar_t	sv_edgefriction = {"edgefriction", "2"};
    
    WinQuake/sv_user.c line 27 at bf4ac42 · upstream ↗
    144	if (trace.fraction == 1.0)
    145		friction = sv_friction.value*sv_edgefriction.value;
    146	else
    147		friction = sv_friction.value;
    ⋮
    150	control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
    151	newspeed = speed - host_frametime*control*friction;
    
    WinQuake/sv_user.c lines 144–151 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

  25. ^ abQuake 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

  26. ^ abIn 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.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Running”
    How we know
    5son_maxspeed:		equ	$600				; Sonic's max speed
    
    _incObj/01 Sonic.asm line 5 at 15dfa3a · upstream ↗
    45		move.w	#son_maxspeed,(v_sonspeedmax).w		; set Sonic's top speed
    
    _incObj/01 Sonic.asm line 45 at 15dfa3a · upstream ↗
    940		move.w	(v_sonspeedmax).w,d6			; get Sonic's current top speed
    
    _incObj/01 Sonic.asm line 940 at 15dfa3a · upstream ↗
    top_speed 6
    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.

    In the claim ledger

  27. ^ abIn the running game, on flat ground, holding the d-pad the way Sonic runs, or from a standstill, adds son_acceleration, $C, to his ground speed each frame, up to the top speed.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Running”
    How we know
    6son_acceleration:	equ	$C				; Sonic's acceleration
    
    _incObj/01 Sonic.asm line 6 at 15dfa3a · upstream ↗
    706Sonic_MoveRight:
    707		move.w	obInertia(a0),d0			; get Sonic's current ground speed
    708		bmi.s	.changedirection			; has Sonic changed direction? if yes, branch
    ⋮
    716		add.w	d5,d0					; add acceleration to current ground speed
    717		cmp.w	d6,d0					; is new speed above max speed?
    718		blt.s	.nocap					; if not, branch
    719		move.w	d6,d0					; cap Sonic's ground speed
    
    _incObj/01 Sonic.asm lines 706–723 at 15dfa3a · upstream ↗
    acceleration_speed 0.046875 (12 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.

    In the claim ledger

  28. ^ abOn the ground the stick's tilt sets Banjo's target speed in five bands of the stick's distance from center, each axis clamped to a raw 7 to 59 (x) or 7 to 61 (y) and scaled to 0 to 1, and the distance capped at 1. Up to 0.12 the target is 0; above it the target rises linearly within each band: 30 to 80 units/s up to 0.2, 80 to 150 up to 0.5, 150 to 225 up to 0.75, and 225 to 500 at full tilt. The decompilers name the bands creep, slow walk, walk, and fast walk. On ground flagged BA_FLAG_13_TOUCHING_DANGEROUS_GROUND, the target is instead 30 to 150 by the distance itself, and 0 inside the 0.12 dead zone. Each frame the horizontal velocity closes the gap to the target by a fraction from a five-entry table (0, 0.07, 0.29, 0.15, 0.05) indexed by the unnamed D_8037C284 (the atlas reads the index as a movement state), unless func_8029CF48 has set an override for that index, which func_8029CED0 then returns instead, times the frame's time over 1/30 s; when an unnamed floor check (func_80294548) passes, the target is first scaled by the slope. Super Mario 64's target is 32 times the square of the tilt, and Mario gains a fixed 1.1 − speed/43 units/frame below it (sm64/walking-speed).Codebanjo.decomp/banjo-kazooie · n64decomp/sm64revised
    How we know
    18f32 bsWalkMinCreepVelocity = 30.0f;//creep_min
    19f32 bsWalkCreepSlowWalkVelocityThreshold = 80.0f;//creep_max/slow_walk_min
    20f32 bsWalkSlowWalkWalkVelocityThreshold = 150.0f;//slow_walk_max/walk_min
    21f32 bsWalkWalkFastWalkVelocityThreshold = 225.0f;//walk_max/walk_fast_min
    22f32 bsWalkMaxFastWalkVelocity = 500.0f;//walk_fast_max
    23f32 bsWalkMinMudVelocity = 30.0f; //mud_min
    24f32 bsWalkMaxMudVelocity = 150.0f; //mud_max
    
    src/core2/bs/walk.c lines 18–24 at e8d31fa · upstream ↗
    41void func_802B6D00(void){
    ⋮
    45    sp1C = bastick_getZonePosition();
    46    sp18 = bastick_getZone();
    47    if(player_isOnDangerousGround()){
    48        if(sp18 == 0){
    49            baphysics_set_target_horizontal_velocity(0.0f);
    50        }else{//L802B6D48
    51            baphysics_set_target_horizontal_velocity(ml_interpolate_f(bastick_distance(), bsWalkMinMudVelocity, bsWalkMaxMudVelocity));
    ⋮
    55        switch(sp18){
    56            case 0://802B6D98
    57                baphysics_set_target_horizontal_velocity(0.0f);
    ⋮
    60                baphysics_set_target_horizontal_velocity(ml_interpolate_f(sp1C, bsWalkMinCreepVelocity, bsWalkCreepSlowWalkVelocityThreshold));
    ⋮
    
    src/core2/bs/walk.c lines 41–72 at e8d31fa · upstream ↗
    28f32 bastick_calculateZonePosition(f32 arg0, f32 arg1, f32 arg2){
    29    return (arg0 - arg1)/(arg2 - arg1);
    ⋮
    35    if (bastick.distance <= bastick.zone_markers[0]) {
    36        bastick.zone = 0;
    37        bastick.zone_position = 0.0f;
    ⋮
    63void bastick_resetZones(void) {
    64    bastick_setZoneMax(0, 0.12f);
    65    bastick_setZoneMax(1, 0.2f);
    66    bastick_setZoneMax(2, 0.5f);
    67    bastick_setZoneMax(3, 0.75f);
    68    bastick_setZoneMax(4, 1.0f);
    
    src/core2/bastick.c lines 28–69 at e8d31fa · upstream ↗
    85    bastick.distance = sqrtf(bastick.value[0]*bastick.value[0] + bastick.value[1]*bastick.value[1]);
    ⋮
    100    if (bastick.distance > 1.0) {
    101        bastick.distance = 1.0f;
    
    src/core2/bastick.c lines 85–102 at e8d31fa · upstream ↗
    51f32 controller_clampAndNormaliseJoyAxis(s32 input, s32 min, s32 max)
    ⋮
    53    f32 unit = 1 / 80.f;
    ⋮
    61    if (input > 0)
    ⋮
    63        input = input > max ? max : input < min ? min : input;
    64        input = ((input - min) * 80) / (max - min);
    ⋮
    72    return unit *= input;
    
    src/core1/joy.c lines 51–72 at e8d31fa · upstream ↗
    155        dst[0] = controller_clampAndNormaliseJoyAxis(sInputs[controllerIdx].stick_x, 7, 59);
    156        dst[1] = controller_clampAndNormaliseJoyAxis(sInputs[controllerIdx].stick_y, 7, 61);
    
    src/core1/joy.c lines 155–156 at e8d31fa · upstream ↗
    705f32 ml_interpolate_f(f32 arg0, f32 arg1, f32 arg2)
    ⋮
    707    return arg0 * (arg2 - arg1) + arg1;
    
    src/core1/ml.c lines 705–707 at e8d31fa · upstream ↗
    188bool player_isOnDangerousGround(void){
    189    return baflag_isTrue(BA_FLAG_13_TOUCHING_DANGEROUS_GROUND);
    
    src/core2/playerutils.c lines 188–189 at e8d31fa · upstream ↗
    49    func_80256D0C(0.0f, baphysics_target_yaw, 0.0f, 0.0f, baphysics_target_horizontal_velocity, &baphysics_target_velocity[0], &baphysics_target_velocity[1], &baphysics_target_velocity[2]);
    ⋮
    57    if(func_80294548()){
    ⋮
    71                ml_vec3f_scale(sp60, 1.0 + sp40);
    ⋮
    75                ml_vec3f_scale(sp60, sp40 + 1.0);
    ⋮
    80    ml_vec3f_scale_copy(sp84, sp60, func_8029CED0());
    81    ml_vec3f_scale_copy(sp78, sp6C, func_8029CED0());
    82    ml_vec3f_diff(sp84, sp78);
    83    ml_vec3f_scale(sp84, time_getDelta()/0.0333333);
    84    s_player_velocity[0] += sp84[0];\
    
    src/core2/ba/physics.c lines 49–86 at e8d31fa · upstream ↗
    16f32 func_8029CED0(void) {
    ⋮
    19    temp_v0 = func_8029CEB0();
    20    if (D_8037D1F0[temp_v0] != 0) {
    21        return D_8037D1F8[temp_v0];
    ⋮
    23    return func_8033DE30(temp_v0);
    
    src/core2/code_15F20.c lines 16–23 at e8d31fa · upstream ↗
    30void func_8029CF48(s32 arg0, s32 arg1, f32 arg2) {
    31    D_8037D1F0[arg0] = arg1;
    32    D_8037D1F8[arg0] = arg2;
    
    src/core2/code_15F20.c lines 30–33 at e8d31fa · upstream ↗
    440s32 func_802944F4(void){
    441     return D_8037C284;
    
    src/core2/code_C4B0.c lines 440–441 at e8d31fa · upstream ↗
    77Struct_Core2_B6CE0_1 D_80371E30[] ={
    78    { 0, 0,  0.0f },
    79    { 1, 0, 0.07f },
    80    { 2, 1, 0.29f },
    81    { 3, 2, 0.15f },
    82    { 4, 1, 0.05f }
    
    src/core2/commonParticle.c lines 77–83 at e8d31fa · upstream ↗
    97f32 func_8033DE30(s32 arg0){
    98    return D_80371E30[arg0].unk4;
    
    src/core2/commonParticle.c lines 97–98 at e8d31fa · upstream ↗
    1295    f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f;
    ⋮
    1298        m->intendedMag = mag / 2.0f;
    
    src/game/mario.c lines 1295–1298 at 9921382 · upstream ↗
    450    if (m->forwardVel <= 0.0f) {
    451        m->forwardVel += 1.1f;
    452    } else if (m->forwardVel <= targetSpeed) {
    453        m->forwardVel += 1.1f - m->forwardVel / 43.0f;
    
    src/game/mario_actions_moving.c lines 450–453 at 9921382 · 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

  29. ^In the running game, on flat ground, holding the d-pad against Sonic's motion subtracts son_deceleration, $80, a frame, and a step that would cross zero sets the speed to $80 the other way: from $40 written in by the probe, Left gives −$80, and from −$40, Right gives $80.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Running”
    How we know
    7son_deceleration:	equ	$80				; Sonic's deceleration
    
    _incObj/01 Sonic.asm line 7 at 15dfa3a · upstream ↗
    665.changeddirection:
    666		sub.w	d4,d0					; apply deceleration to current speed
    667		bcc.s	.stilldecel       			; if still decelerating, branch
    668		move.w	#-$80,d0        			; set minimum speed on sign change
    
    _incObj/01 Sonic.asm lines 665–668 at 15dfa3a · upstream ↗
    729.changedirection:
    730		add.w	d4,d0					; apply deceleration to current speed
    731		bcc.s	.stilldecel				; if still decelerating, branch
    732		move.w	#$80,d0					; set minimum speed on sign change
    
    _incObj/01 Sonic.asm lines 729–732 at 15dfa3a · upstream ↗
    At any time an addition or subtraction of deceleration_speed results in Ground Speed changing sign, Ground Speed is set to 0.5 (128 subpixels) in the opposite direction.
    Deceleration · 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

  30. ^CODE_00D742 compares only the speed's high byte with the cap; below it the frame adds the full acceleration, unclamped, and at or past it the frame applies friction instead, so Mario's top speed cycles around the cap.CodeSMWDisX
    How we know
    10107CODE_00D742:
    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
    
    bank_00.asm lines 10107–10113 at 30643c7 · 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

  31. ^ abX_Physics doubles the acceleration whenever Mario faces away from the direction he moves, so a turn brakes at $130, $1A0, or $1C8 a frame.CodeXkeeper0/smb1
    How we know
    5042	LDA PlayerFacingDir
    5043	CMP Player_MovingDir                         ; check facing direction against moving direction
    5044	BEQ ExitPhy                                  ; if the same, branch to leave
    5045	ASL FrictionAdderLow                         ; otherwise shift d7 of friction adder low into carry
    5046	ROL FrictionAdderHigh                        ; then rotate carry onto d0 of friction adder high
    5047ExitPhy:
    
    src/prg.asm lines 5042–5047 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

  32. ^On the ground, GetPlayerAnimSpeed zeroes Mario's speed and turns his moving direction to his facing one when a button other than A is held, the d-pad's Left/Right bits differ from his moving direction, and his speed is below $0B.CodeXkeeper0/smb1
    How we know
    5064ChkSkid:
    5065	LDA SavedJoypadBits                          ; get controller bits
    5066	AND #%01111111                               ; mask out A button
    5067	BEQ SetAnimSpd                               ; if no other buttons pressed, branch ahead of all this
    5068	AND #$03                                     ; mask out all others except left and right
    5069	CMP Player_MovingDir                         ; check against moving direction
    5070	BNE ProcSkid                                 ; if left/right controller bits <> moving direction, branch
    ⋮
    5075ProcSkid:
    5076	LDA Player_XSpeedAbsolute                    ; check player's walking/running speed
    5077	CMP #$0b                                     ; against one last amount
    5078	BCS SetAnimSpd                               ; if greater than this amount, branch
    5079	LDA PlayerFacingDir
    ⋮
    
    src/prg.asm lines 5064–5083 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

  33. ^Mega Man lands into the running state if Left or Right was held on the frame before landing, at 1.375 px/frame from the next frame with no first step, and into the landing-stop state otherwise.Verifiedlsmmega/mm2
    How we know
    225@jump_down:
    226	JSR _check_object_vertical_move
    227	LDA z:z00
    228	BEQ @not_landing
    229	track_queue track_landing
    230	LDX #$05
    231	LDA z:zjoy1_pressed_frame
    232	AND #left_button | right_button
    233	BNE @horizontal_jump_down
    234	LDX #$08
    ⋮
    236@horizontal_jump_down:
    237	STX z:zmegaman_status
    ⋮
    
    engine/run_megaman.asm lines 225–238 at 94f0bf3 · upstream ↗
    1_nmi_wait_0e:
    2	LDA z:zjoy1_pressed
    3	STA z:zjoy1_pressed_frame
    
    home/nmi_wait.asm lines 1–3 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-21.

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

    In the claim ledger

  34. ^Down on the ground puts Simon in the crouching state 4 px lower, where the d-pad no longer moves him; letting go stands him back up, and that frame he doesn't move either.Verified“Castlevania (USA) (Rev 1)”
    How we know

    In the cartridge (“Castlevania (USA) (Rev 1)”): bank 6 $944A-$9457: Down held, state 3, then Y += 4 ($9A69); bank 6 $9539-$9584: the crouching state writes $04 (Down alone) to $0584 before the move, so no direction bits; Down let go: Y −= 4 and state 0 ($9578). 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

  35. ^While Left or Right is held, the crouching state, and the standing state on a frame that doesn't start a fall, a stair climb, a whip, a jump, or a crouch, set Simon's facing ($0450) from it, so he turns on the first frame, and crouching he can turn without moving. A frame that starts any of those keeps the facing he had.Verified“Castlevania (USA) (Rev 1)”revised
    How we know

    In the cartridge (“Castlevania (USA) (Rev 1)”): bank 6 $9458-$9462: held Left/Right shifted right one bit into $0450 (0 right, 1 left); bank 6 $9539-$9584, the crouching state, which does the same at $9557-$955E; bank 6 $9401-$943B, the jump's take-off, which returns before $9458; bank 6 $944A-$9457, the crouch's start, which returns through $9A69 before $9458; bank 6 $93ED-$9400: Up or Down at a stair ($9C10) starts the climb and returns at $9400; bank 6 $943C-$9449: a whip started ($9A2A, carry set) moves the state on and returns; bank 6 $93C5-$93D8, the fall entry, which returns before the move. 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.

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

    In the claim ledger

  36. ^In the running game, on flat ground, reversing from top speed, Sonic running right reaches exactly 0 on the 12th frame and −$C on the 13th, but running left he jumps from −$80 to +$80 on the 12th.Verifiedsonicretro/s1disasmrevised
    How we know
    668		move.w	#-$80,d0        			; set minimum speed on sign change
    
    _incObj/01 Sonic.asm lines 665–668 at 15dfa3a · upstream ↗
    732		move.w	#$80,d0					; set minimum speed on sign change
    
    _incObj/01 Sonic.asm lines 729–732 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

  37. ^ abSimulating 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.CodeNoelFB/Celeste · JamesMcMahon/monocle-engine
    How we know
    2884                float mult = onGround ? 1 : AirMult;
    
    Source/Player/Player.cs lines 2879–2895 at 1b0ce45 · upstream ↗
    854            return val > target ? Math.Max(val - maxMove, target) : Math.Min(val + maxMove, target);
    
    Monocle/Util/Calc.cs lines 852–855 at 759c15a · upstream ↗

    Measured by a script. It fails if the result disagrees with the claim.

    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

  38. ^Each update moves Madeline's horizontal speed toward 90 px/s times the d-pad direction by RunAccel, 1000 px/s² on the ground, so the same rate speeds her up, turns her, and stops her.CodeNoelFB/Celeste
    How we know
    31        public const float RunAccel = 1000f;
    
    Source/Player/Player.cs line 31 at 1b0ce45 · upstream ↗
    2884                float mult = onGround ? 1 : AirMult;
    
    Source/Player/Player.cs line 2884 at 1b0ce45 · upstream ↗
    2893                else
    2894                    Speed.X = Calc.Approach(Speed.X, max * moveX, RunAccel * mult * Engine.DeltaTime);   //Approach the max speed
    
    Source/Player/Player.cs lines 2893–2894 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

  39. ^On the ground X_Physics uses the running row (cap $28, acceleration $E4) while B and the direction Mario moves in are held and for the 9 frames after B goes up; otherwise the walking row (cap $18, $98, or $D0 while RunningSpeed is set or his speed is $21 or more).CodeXkeeper0/smb1revised
    How we know
    4991X_Physics:
    ⋮
    4994	LDA Player_State                             ; if mario is on the ground, branch
    4995	BEQ ProcPRun
    ⋮
    5000ProcPRun:
    5001	INY                                          ; if mario on the ground, increment Y
    5002	LDA AreaType                                 ; check area type
    5003	BEQ ChkRFast                                 ; if water type, branch
    5004	DEY                                          ; decrement Y by default for non-water type area
    5005	LDA Left_Right_Buttons                       ; get left/right controller bits
    5006	CMP Player_MovingDir                         ; check against moving direction
    5007	BNE ChkRFast                                 ; if controller bits <> moving direction, skip this part
    5008	LDA A_B_Buttons                              ; check for b button pressed
    ⋮
    
    src/prg.asm lines 4991–5026 at 1cc3c92 · upstream ↗
    4870MaxLeftXSpdData:
    4871	.db $d8, $e8, $f0
    ⋮
    4873MaxRightXSpdData:
    4874	.db $28, $18, $10
    
    src/prg.asm lines 4870–4874 at 1cc3c92 · upstream ↗
    5055GetPlayerAnimSpeed:
    ⋮
    5058	CMP #$1c                                     ; against preset amount
    5059	BCS SetRunSpd                                ; if greater than a certain amount, branch ahead
    ⋮
    5068	AND #$03                                     ; mask out all others except left and right
    5069	CMP Player_MovingDir                         ; check against moving direction
    5070	BNE ProcSkid                                 ; if left/right controller bits <> moving direction, branch
    5071	LDA #$00                                     ; otherwise set zero value here
    5072SetRunSpd:
    5073	STA RunningSpeed                             ; store zero or running speed here
    
    src/prg.asm lines 5055–5074 at 1cc3c92 · upstream ↗
    126DecTimers:
    127	LDX #$14                                     ; load end offset for end of frame timers
    ⋮
    136	DEC Timers,x                                 ; otherwise decrement the current timer
    
    src/prg.asm lines 126–136 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.

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

    In the claim ledger

Sources

Code

Secondary