HDR Additive Bloom

Rendering & Graphics

Six drifting glows summed per cell on a Super Nintendo using saturating (overflow-checked) addition — where the lights pile up the field blows out to white instead of wrapping, the high-dynamic-range "bloom" look, done entirely in 8-bit integers via __builtin_add_overflow. 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 lights drift and blow out on their own.

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

What it is

Each of six lights stamps a soft radial glow into an 8-bit intensity field every frame. The glows are added together — but with a twist: the add saturates. Instead of a byte wrapping from 255 back to 0 (which would make bright spots suddenly go dark), the add detects the overflow and clamps to 255:

static inline uint8_t sat_add8(uint8_t a, uint8_t b) {
    uint8_t r;
    return __builtin_add_overflow(a, b, &r) ? 0xFF : r;   // ← adc; bcs
}
// per light, per kernel cell in its footprint:
field[y*W + x] = sat_add8(field[y*W + x], glow[...]);     // overlaps clamp to white

The field is then mapped through a black → blue → magenta → orange → white ramp. Isolated lights show the falloff colours; where two or more overlap, the sum pins at 255 and the ramp tops out at pure white — exactly the "blown-out highlight" of HDR bloom, with no floating point anywhere.

Compiler stress-test

ItemWhat it exercises
__builtin_add_overflowThe saturating add: sum two bytes, and if the add carries out (would exceed 255) clamp to 255 instead of wrapping. Lowers to an add-with-carry then a carry-flag branch.
adc; bcsOn the 65816 the overflow check is a carry-out test — `adc` (add with carry) then `bcs` (branch if carry set) to the clamp. A flag-testing add sequence no other battery demo runs.
HDR / bloomBecause the adds saturate, regions where several glows overlap pile up past 255 and pin at pure white — the "blown-out highlight" look of high-dynamic-range bloom, done in 8-bit integers.
rep/sepMode-switch brackets mark 16-bit accumulator sections under +mos-a16 (the Q4 light-position math). No 32-bit multiply or divide on the hot path — this is a flag/control test.

Overflow-checked / saturating arithmetic is a flag-testing add sequence — carry and overflow flags tested and branched on — that no earlier demo in the battery exercised (their adds either can't overflow in range or wrap silently). It compiles correctly here: the __builtin_add_overflow lowers to adc + a carry branch across the default 8-bit, +mos-a16 and +mos-xy16 backends, all -verify-machineinstrs clean.

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 CRC 0xF951 — a rotate-XOR fold of the clamped-cell count + a field sample) live in this tab. No far pointers — the same source passes every way: host == default == +mos-a16 == +mos-xy16 == bsnes-jg.