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.

loading core…

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

ItemWhat it exercises
Abs foldThe 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 multiplieszx², 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 bandsEach cell is coloured by how many iterations it survives before |z|² > 4; interior cells (never escape) form the black ship silhouette
Multiply-onlyNo 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.