Spirograph
Motion & Curves
The curve a pen traces through a hole in a small gear rolling inside a ring — a
hypotrochoid — drawn live on the Super Nintendo and driven with the joypad. Written in C
and compiled to a real .sfc ROM with the
llvm-mos-based 65816 toolchain (16-bit
accumulator, +mos-a16). Each point is a sin/cos lookup plus two fixed-point
multiplies; the figure blooms stroke-by-stroke into a bitmap canvas in WRAM. Cycle through
four curve families — hypotrochoid, epitrochoid, rose and Lissajous.
↑/↓ ring · ←/→ wheel · Q/W pen · X/A family · Shift preset · Enter reset
Click the screen, then play. The rose draws itself in over a second or two; change a dial and it re-blooms — tab away and it pauses.
Controls
| Keys | Action |
|---|---|
| ↑ / ↓ | Ring radius R + / − |
| ← / → | Wheel radius r − / + |
| Q / W | Pen offset d − / + |
| X / A | Next / previous curve family |
| Shift | Cycle gear preset |
| Enter | Reset |
The four curve families
Cycle them with X (next) / A (previous) — each re-blooms the canvas.
The on-screen HUD shows the live R (ring), W (wheel), D
(pen) and the petal count.
| Family | What it is |
|---|---|
| HYPOTROCHOID | pen inside the wheel as it rolls inside the ring — the classic rosette |
| EPITROCHOID | wheel rolls outside the ring — a ring of interlocking loops |
| ROSE | rhodonea ρ = cos(kθ) — a k-petalled flower |
| LISSAJOUS | x = sin(aθ+δ), y = sin(bθ) — the crossing-wave figure |
Tips
- The bloom is the point. Each new sample is line-connected to the last, so the figure draws itself; nudging ↑↓/←→/QW changes the gear and re-blooms a fresh curve.
- Gear presets (Shift) jump between classic Spirograph wheel/ring sets — each a different petal count (ring ÷ gcd of ring and wheel).
- It's a compiler stress-test. The whole point is the sin/cos-LUT + fixed-point-multiply inner loop and the gear-ratio divide — exercising the 65816 16-bit-accumulator codegen.
Written in C with an LLVM/65816 SNES toolchain and verified pixel-for-pixel
against two emulators (MAME + bsnes-jg). The player above is that exact cycle-accurate core — hit
Verify fidelity to reproduce the build gate's WRAM assert (curve-math hash
0x32D4) live in this tab. No far pointers, so the same program is checked five ways:
host == default == +mos-a16 == +mos-xy16.