Colour, rung 6b — palette cycling: animate without touching a pixel.
The oldest trick in the 2D book. The picture on screen never changes: every tile, every tilemap entry, every scroll register is frozen after init. All that moves is CGRAM — each frame we rotate the 16 palette entries by one slot, and the diagonal bands appear to flow. This is how the SNES animates waterfalls, lava, fire, marquee lights and "loading" shimmers for the cost of a 32-byte CGRAM reload, no VRAM traffic at all.
The scene is built procedurally — zero assets. Sixteen solid 4bpp tiles (tile i is a flat fill of palette index i) are generated in C at init, and the tilemap is laid out as tile = (row + col) & 15 so colour index runs along every diagonal. Cycling the palette then slides those diagonals across the screen.
ROM mode: LoROM (project default).
- SNES Concepts
- CGRAM is a live lookup table: rewrite an entry and every pixel that indexes it changes colour this frame — no redraw
- setColor() / dmaCopyCGram() are VBlank-only (CGRAM port is ignored during active display) — the rotation happens right after WaitForVBlank
- 4bpp planar tile format (32 bytes/tile, two interleaved bitplane pairs), built byte by byte in C
- A seamless colour loop: the 16 entries wrap (entry 15 → entry 0 is continuous) so the cycle never jumps
- What to Observe
- Boot: a rainbow of diagonal bands drifting steadily up-and-left. Press START to freeze the cycle — the bands stop dead, proving nothing on screen actually moved; press again to resume. cycle_pos counts every rotation (probe oracle).
- Modules Used
- console, dma, background, input
- See also
- lib/include/snes/video.h — setColor(), RGB()
-
lib/include/snes/dma.h — dmaCopyCGram()