Newton Floor

Rendering & Graphics

A checkerboard floor rushing toward the horizon on a Super Nintendo — a chip with no divide instruction. The 1/z depth that makes the perspective work is computed by Newton-Raphson refinement: a convergent loop that uses only multiplies. Runs automatically; no joypad needed. Written in C and compiled with the llvm-mos-based 65816 toolchain (+mos-a16, 16-bit accumulator mode).

loading core…

Self-running demo — the checkerboard floor scrolls toward the horizon.

Click the screen to focus, then watch. Tab away and it pauses.

What it is

Perspective needs division: an object at depth z shrinks by 1/z. But the 65816 can't divide — so this computes the reciprocal the way a hardware divider does internally, by iterative refinement:

x = seed(m);                 // rough first guess
repeat 4 times:
    x = x * (2 - m * x);     // each pass DOUBLES the correct digits
// x now equals 1/m  — computed with only multiplies

Start with a rough guess, then each pass of x = x*(2 - m*x) doubles the accuracy. Four multiplies-only passes give a full 16-bit reciprocal — which becomes the 1/z depth of a checkerboard floor. It stays bit-exact across every codegen mode.

Compiler stress-test

ItemWhat it exercises
no divideThe 65816 has no divide instruction at all. This computes 1/z the way hardware dividers do internally — Newton-Raphson refinement, which uses only multiplies and a subtract. Zero divide library calls appear in the compiled code.
quadratic convergenceEach iteration x = x*(2 - m*x) roughly doubles the number of correct bits, so four passes nail a 16-bit reciprocal from a crude linear seed. It is the canonical fixed-point refinement loop.
fixed-pointEverything is 32-bit Q15/Q16 integer arithmetic — the products are sized to fit 32 bits exactly (no 64-bit, no float), so the result is bit-identical on the host and on all three codegen modes.
perspective floorThe reciprocal gives the 1/z depth mapping for a scrolling checkerboard floor: near rows spread wide, far rows compress toward the horizon. host == default == +mos-a16 == +mos-xy16 == bsnes-jg.

Written in C with the llvm-mos 65816 toolchain and verified against bsnes-jg (and MAME where the SPC700 IPL is present). Hit Verify fidelity to reproduce the build gate's WRAM assert (gate hash 0x044A — a fold of the Newton reciprocal over a sweep of inputs) live in this tab. No far pointers — the same source passes every way: host == default == +mos-a16 == +mos-xy16 == bsnes-jg, -verify clean.