Raw HDMA table in C — per-scanline wave, krom-style.
Builds an HDMA table BY HAND in C and animates it the way the original assembler demo does: the table is written once, and each VBlank the table START POINTER advances one entry — the ripple pattern flows up the screen (line L reads entry phase+L, so each crest sits at X0-phase) without a single byte of the table being rewritten. This is the classic per-scanline effect that plain DMA cannot do: one BG1 horizontal scroll value per line, traced along a sine.
The companion example hdma_wave shows the same visual through the library's high-level engine (hdmaWaveH / hdmaWaveUpdate, double-buffered RAM tables). THIS example is the low-level counterpart: it teaches the HDMA table FORMAT itself — [line-count, value...] entries, terminator, and the repoint-per-frame animation idiom.
C port of "SNES Wave HDMA Demo" by krom (Peter Lemon), github.com/PeterLemon/SNES, PPU/HDMA/WaveHDMA — technique reproduced on the snes/hdma.h API in the original demo configuration (BG Mode 3, full-screen 256-color image). Art is original: procedurally generated water caustics (res/water.bmp), no krom assets.
- SNES Concepts
- HDMA table format: count byte (1 = apply to one scanline) followed by the register payload (2 bytes for a write-twice register), then a 0x00 terminator byte
- HDMA_MODE_1REG_2X: one register written twice per line — exactly what the 16-bit scroll registers ($210D BG1HOFS low/high) expect
- Animation by START-POINTER repoint (hdmaSetup once per frame with table + phase*3): the table itself is immutable, so HDMA never observes a partially rewritten entry — no tearing, ~zero CPU cost
- BG Mode 3 (8bpp, 256 colors) with a full-screen image — the same configuration as the original demo (~57 KB of unique tiles, split across two ROM banks; the tilemap sits above them at VRAM $7C00, mirroring krom's layout)
- What to Observe
- A water image distorted into tight sine ripples flowing UPWARD at one scanline per frame — krom's exact TABLE (896 entries extracted verbatim) and exact cadence (wrap at 672), so the displacement field is byte-identical to the original demo's
- White horizontal ruler lines every 64px stay perfectly straight (HOFS only shifts lines horizontally) while the verticals undulate
- No flicker or black lines: the table always covers 224 lines from any start phase
- Modules Used
- console, dma, background, hdma
- See also
- hdma.h, examples/hdma/hdma_wave (high-level engine)