|
| #define | AMP_DEFAULT 10 |
| | Module-mode amplitude: default, bounds and step, in pixels.
|
| #define | AMP_MAX 24 |
| #define | AMP_MIN 2 |
| #define | AMP_STEP 2 |
| #define | CH_HAND HDMA_CHANNEL_2 /* not 0 (dmaCopyVram) nor 1 (the NMI's text flush) */ |
| | Channel of the hand-built table (krom's channel 0).
|
| #define | CH_LIB HDMA_CHANNEL_6 |
| | Channel of the hdma module's wave (7 belongs to the OAM DMA).
|
| #define | ENTRY_BYTES 3 |
| | Bytes per HDMA entry in 1REG_2X mode: count + 16-bit value.
|
| #define | VRAM_BG1_GFX 0x0000 |
| | VRAM word address of BG1 tile graphics (image start).
|
| #define | VRAM_BG1_GFX2 0x4000 |
| | VRAM word address of the second tile half (bytes 32768+).
|
| #define | VRAM_BG1_MAP 0x7C00 |
| | VRAM word address of BG1 tilemap — above the 57 KB of tiles, krom's layout (his BG1SC put the map at VRAM byte $F800).
|
| #define | WAVE_FREQ 10 |
| | Module-mode frequency: period = 256 / 10 = 25.6 lines.
|
| #define | WAVE_WRAP 672 |
| | Wrap length of the start-pointer animation, in table entries. krom's exact value: his sine's quasi-period is ~25.8 lines (non- integer), so his seamless wrap needs 672 entries; the table holds 224 more so any start phase has a full screen of valid lines.
|
HDMA wave: build the table by hand, then let the hdma module do it.
One water image, one per-scanline ripple, two ways to make it.
At boot the ripple comes from an HDMA table written BY HAND and animated the way krom's assembler demo does it: the table is never rewritten; each VBlank the table START POINTER advances one entry, so line L reads entry phase+L and the crests flow up the screen. That is the HDMA table format itself — [line-count, value...] entries and a terminator — and the cheapest animation there is.
Press A and the same ripple comes from the hdma module instead: hdmaWaveH() computes the sine table in RAM and hdmaWaveUpdate() animates it, with the amplitude now a parameter (LEFT/RIGHT). The defaults (amplitude 10, frequency 10: a 25.6-line period) sit close to krom's table (round(10 * sin), a ~25.8-line quasi-period), so the switch shows the helper reproducing what the hand-built table did. Press A again to go back.
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
- The same effect from the library: hdmaWaveH / hdmaWaveUpdate / hdmaWaveStop, tables computed and double-buffered in RAM
- 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)
- What to Observe
- At boot: the water image in tight sine ripples flowing UPWARD at one scanline per frame — krom's exact table (896 entries, verbatim) and cadence (wrap at 672); the white rulers every 64px stay straight
- Press A: the hdma module takes over (channel 6 instead of 0); the ripple looks nearly the same
- LEFT/RIGHT (module mode): amplitude from 2 to 24 pixels, in steps of 2
- Press A again: back to the hand-built table, from where it was
- Modules Used
- console, dma, background, input, hdma
- See also
- hdma.h, examples/hdma/hdma_helpers (the other hdma module effects)