Burning Ship
Fractals
The Burning Ship — the
Mandelbrot set's folded cousin — running live on a Super Nintendo. The iteration is almost
identical to the Mandelbrot's, with one twist: it takes the absolute value of the real
and imaginary parts before squaring, z = (|Re z| + i|Im z|)² + c. That single fold
breaks the symmetry and carves out the unmistakable ship silhouette — hull, masts, and a
fleet of trailing mini-ships. Each cell is coloured by its escape time; the bands then cycle so
the sea around the ship flows. Written in C and compiled with the
llvm-mos-based 65816 toolchain
(+mos-a16, 16-bit accumulator). Runs automatically.
Self-running demo — the ship is computed behind the title, then the bands flow.
Click the screen to focus, then watch. Tab away and it pauses.
What it is
Like the Mandelbrot, the Burning Ship asks of each point c in the plane: if you
iterate z → z² + c from zero, does z fly off to infinity, and if so,
how fast? Points that never escape are the set itself (drawn black here); points that escape are
coloured by how many steps they lasted. The Burning Ship differs by one line — it folds each
component to its absolute value first:
for each pixel c = (cx, cy):
zx = zy = 0
for n in 0 .. maxiter:
ax = |zx|; ay = |zy| # the fold
if ax² + ay² > 4: escaped at n
zx = ax² − ay² + cx
zy = 2·ax·ay + cy On the 65816 every quantity is Q12 fixed point and every square/product is a 16×16→32 multiply. The whole 32×28 grid is ground out once behind the title screen (the interior of the ship runs the full iteration count, so it's the slow part), then the escape-band palette is rotated each frame so the surrounding sea shimmers.
Why it stresses the compiler
It shares the fractal family's three 32-bit multiplies per iteration
(zx², zy², |zx·zy|) but adds the abs fold — two
|x| branch/negates per step that the Mandelbrot, Newton, and Julia demos don't
have, and which are the whole reason the ship looks the way it does. It is multiply-only
(no divide), under +mos-a16 rep/sep mode brackets.
Compiler stress-test
| Item | What it exercises |
|---|---|
| Abs fold | The one operation that makes the ship: each iteration takes |Re z| and |Im z| before squaring — z_{n+1} = (|Re z| + i|Im z|)² + c. No other fractal in the battery folds |
| Three multiplies | zx², zy², and |zx·zy| — three 16×16→32 __mulsi3 per iteration in Q12 fixed point, the same count as the Mandelbrot but a different inner-loop shape |
| Escape-time bands | Each cell is coloured by how many iterations it survives before |z|² > 4; interior cells (never escape) form the black ship silhouette |
| Multiply-only | No divide anywhere — the disasm gate asserts zero __udivsi3/__udivmodsi4; the stress is the multiply grind + the abs branch |
The gate sweeps a 16×16 window over the ship and folds each cell's escape count into a
rotating-XOR hash, asserting corpus_result (0x6F2D) is identical on host, default
8-bit SNES, +mos-a16, and +mos-xy16. The Verify fidelity button
reproduces that gate live in this tab via the same cycle-accurate bsnes-jg core used in CI.
Written in C with the llvm-mos 65816 toolchain. Hit Verify fidelity
to reproduce the build gate's WRAM assert (corpus_result = 0x6F2D) live in
this tab. No far pointers — the same logic checked four ways: host == default ==
+mos-a16 == +mos-xy16, with bsnes-jg as the in-browser
confirmation.