Fixed-point arithmetic
Arithmetic on scaled integers whose fractional scale stays fixed.
On this page
Fixed-point arithmetic represents a value with an integer and an agreed fractional scale. The scale stays implicit in the stored value; the movement examples here use binary fractions1,2,3.
The format can differ by quantity, even within one game. Super Mario Bros. stores horizontal speed in 4.4 fixed point, with sixteenths of a pixel per frame, and vertical speed in 8.8 fixed point, with a 1/256-pixel step1,2. Sonic the Hedgehog stores positions as 16.16 and speeds as 8.8, shifting each speed left 8 bits before adding it to position3. Super Mario World moves in sixteenths of a pixel4.
Fixed point differs from floating point in how it represents the fractional part. Celeste keeps whole-pixel actor positions and a floating-point remainder, then moves by the rounded remainder5.
References
- ^ abHorizontal speeds are 4.4 fixed point, whole pixels and sixteenths per frame;
MoveObjectHorizontallyshifts the sixteenths into the subpixel byte.CodeXkeeper0/smb1How 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.
- ^ abVertical motion is 8.8 fixed point; each frame,
ImposeGravityadds speed to position, the fraction via theYMF_Dummysubpixel byte, then gravity to speed.CodeXkeeper0/smb1How we know
6668 ADC SprObject_Y_MoveForce,x 6669 STA SprObject_YMF_Dummy,x ⋮ 6676 ADC SprObject_Y_Position,x ; add vertical position to vertical speed plus carry ⋮ 6683 ADC $00 ; add downward movement amount to contents of $0433 ⋮ 6685 LDA SprObject_Y_Speed,x ; add carry to vertical speed and store
src/prg.asm lines 6666–6687 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.
- ^ abIn the running game,
ObjectFallandSpeedToPosmove Sonic's 32-bit position each frame by his speed shifted left 8 bits, X by this frame's X speed and Y, in the air, by the Y speed before gravity, so positions are 16.16 and speeds 8.8 fixed point.Verifiedsonicretro/s1disasm · Sonic Retro, “Sonic Physics Guide: Calculations (Pixel and Subpixel)”How we know
16 move.w obVelY(a0),d0 ; load vertical speed 17 addi.w #gravity,obVelY(a0) ; increase vertical speed (apply gravity) 18 ext.l d0 ; extend speed to longword 19 asl.l #8,d0 ; shift speed up a byte (16.16 fixed point) 20 add.l d0,d3 ; add speed to Y-axis position
_incObj/sub ObjectFall & SpeedToPos.asm lines 16–20 at 15dfa3a · upstream ↗ Each pixel is effectively split into 256 slices along both axis and this means the finest fidelity available for movement is 1/256th of a pixel (aka 0.00390625).
Pixel and Subpixel · 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.
- ^
CODE_00DC4Fadds a speed's low nybble to a subpixel byte and its high nybble, sign-extended, plus the carry to the 16-bit position, so Mario moves in sixteenths of a pixel.CodeSMWDisXHow we know
10909CODE_00DC4F: ;! 10910 LDA.B PlayerXSpeed+1,X ;! 10911 ASL A ;! 10912 ASL A ;! 10913 ASL A ;! 10914 ASL A ;! 10915 CLC ;! 10916 ADC.W PlayerXPosSpx,X ;! ⋮ 10920 LDA.B PlayerXSpeed+1,X ;! ⋮ 10930 ADC.B PlayerXPosNext,X ;!
bank_00.asm lines 10909–10933 at 30643c7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^Celeste's actors sit on whole pixels;
MoveVadds the float distance to a remainder, moves by its rounded value, and keeps the fraction.Dev blogThorson 2020 · NoelFB/CelesteHow we know
xRemainder += amount; int move = Round(xRemainder); if (move != 0) { xRemainder -= move;
Actor Basics · archived copy ↗ 935 MoveV(Speed.Y * Engine.DeltaTime, onCollideV);Source/Player/Player.cs line 935 at 1b0ce45 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-27.
Sources
Code
- doppelganger and Xkeeper. 2022. “smb1: Super Mario Bros. disassembly for asm6f (Xkeeper0/smb1).” Commit 1cc3c92. Xkeeper0/smb1 @ 1cc3c92 · licence, all uses
- Sonic Retro contributors. 2026. “s1disasm: Sonic the Hedgehog (16-bit) disassembly (sonicretro/s1disasm).” Commit 15dfa3a. sonicretro/s1disasm @ 15dfa3a · licence, all uses
- IsoFrieze, kaizoman666, mikeyk, and loveemu. 2026. “SMWDisX: Super Mario World disassembly (IsoFrieze/SMWDisX).” Commit 30643c7. IsoFrieze/SMWDisX @ 30643c7 · licence, all uses
- Thorson, Maddy and Noel Berry. 2021. “Celeste: released class files (NoelFB/Celeste).” Commit 1b0ce45. NoelFB/Celeste @ 1b0ce45 · licence, all uses
Primary
- Thorson, Maddy. 2020. “Celeste and TowerFall Physics.” Medium. original · archived · licence, all uses
Secondary
- Sonic Retro contributors. n.d. “Sonic Physics Guide: Calculations (Pixel and Subpixel).” Sonic Retro. original · archived · licence, all uses