Saturating-Cast Kaleidoscope

Rendering & Graphics

A 6-fold hex kaleidoscope on a Super Nintendo whose colours are driven by saturating float-to-int casts: fminf/fmaxf clamp a float intensity into the int16 range, then (int16_t) truncates — with the llvm-mos legalizer at line 502 inserting a NaN guard automatically. Saturated outer tiles form crisp flat-colour plateaus; inner tiles show the colour gradient as phase sweeps. Compiler stress-test #77, the first demo to call fminf/fmaxf.

loading core…

Self-running — saturation boundary pulses through the mandala as phase sweeps.

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

What it is

Each tile maps to a hex axial coordinate triple (q, r, s=−q−r); sorting the absolute values |q|,|r|,|s| folds the grid into the first sextant, giving 6-fold symmetry without trigonometry. A float intensity is then computed from the sorted triple and an advancing phase: intensity = a²·200 − b²·50 + phase. For large a (outer rings) the intensity exceeds the int16 range and saturates; for inner tiles the cast stays in-range and the 4 colour levels visible. As phase sweeps continuously, the saturation boundary pulses in and out.

// Per-tile colour in the 6-fold hex kaleidoscope:
// q=tx-8, r=ty-8, s=-q-r  (hex axial coords)
// a,b,c = sort(|q|,|r|,|s|)   (first sextant → 6-fold symmetry)

float fa = (float)a;
float a2 = fa * fa;         // __mulsf3: 0..225
float tb = (float)b * (float)b * 50.0f;  // __mulsf3 x2
float raw = a2 * 200.0f - tb;  // __mulsf3 + __subsf3

float intensity = raw + phase_f;  // __addsf3

// Saturating cast:
float lo = fminf(32767.0f, intensity);  // G_FMINNUM
float hi = fmaxf(-32768.0f, lo);        // G_FMAXNUM
int16_t iv = (int16_t)hi;              // G_FPTOSI (legalizer inserts NaN guard)

// colour = top 2 bits of (iv shifted to unsigned):
colour = (uint8_t)((uint16_t)(iv + 32768) >> 14);
// → INT16_MIN→0, [-16384,-1]→1, [0,16383]→2, [16384,INT16_MAX]→3

Compiler stress-test

ItemWhat it exercises
G_FMINNUMfminf(32767.0f, x) lowers to G_FMINNUM → SDK fminf (math.cc:18 in llvm-mos-sdk). On the 65816 this is a function call to the soft-float min comparison, not an inline instruction. This is the first demo in the battery to call fminf/fmaxf.
G_FMAXNUMfmaxf(-32768.0f, lo) lowers to G_FMAXNUM → SDK fmaxf (math.cc:19). Together with G_FMINNUM, this creates the two-sided clamp that prevents the int16 cast from hitting undefined behaviour on out-of-range floats.
G_FPTOSI + legalizer :502(int16_t)hi lowers to G_FPTOSI. The MOS legalizer at line 502 inserts a NaN guard (buildIsFPClass(fcNan) + G_SELECT) so that a NaN input maps to INT16_MIN instead of UB. This is distinct from demo #44 (integer __builtin_add_overflow / G_UADDO) and #59 (exact 64-bit round-trip, no clamp).
saturation plateausTiles with large a (Chebyshev hex distance from centre) compute a² × 200 which exceeds INT16_MAX = 32767 well before the edge — so those tiles saturate to colour 3 (gold). When phase_f is strongly negative, all tiles saturate to INT16_MIN → colour 0 (indigo). The phase sweeps continuously, so the saturation boundary pulses in and out across the mandala.
6-fold symmetryHex axial coordinates (q, r, s=−q−r) have intrinsic 6-fold rotational symmetry when |q|, |r|, |s| are sorted. Tiles that are rotations of each other in hexagonal space share the same (a, b, c) triple and therefore the same intensity, giving a kaleidoscope without any trigonometry.

Written in C with the llvm-mos 65816 toolchain and verified against bsnes-jg and MAME. Hit Verify fidelity to reproduce the build gate's WRAM assert (gate CRC 0xC8CF — 16-phase × 8-tile rotating-XOR fold of sc_tile_color) live in this tab. No far pointers — host == default == +mos-a16 == +mos-xy16, -verify clean.