OpenSNES
Modern Open-Source SNES Development SDK
Loading...
Searching...
No Matches
main.c File Reference

Indirect HDMA — 32-band backdrop gradient from a pointer table. More...

#include <snes.h>
#include <snes/hdma.h>

Macros

#define BAND_LINES   7
 Scanlines per band (non-repeat count in each table entry).
#define NBANDS   32
 Gradient bands (krom: 32 bands x 7 scanlines = 224 lines).

Functions

int main (void)
 Entry point — static 32-band red gradient, zero per-frame CPU.

Variables

static u8 band_data [32][4]
 Indirect payload blocks, one per band: [0][0][color_lo][color_hi].
static u8 itable [32 *3+1]
 The indirect table: [count][ptr_lo][ptr_hi] per band + terminator.

Detailed Description

Indirect HDMA — 32-band backdrop gradient from a pointer table.

The indirect-HDMA counterpart of gradient_colors: instead of a table carrying the color DATA inline, the table carries [count][pointer] entries and the PPU fetches each band's 4-byte payload through the pointer ($43x7 selects the data bank). The payload blocks live in a separate WRAM array the CPU can edit freely — the classic layout for dynamic per-scanline palettes (the HiColor building block).

C port of "SNES Red Space Indirect HDMA Demo" by krom (Peter Lemon), github.com/PeterLemon/SNES, PPU/HDMA/RedSpaceIndirectHDMA — same configuration: no BG layers at all (main screen = 0), the gradient IS the backdrop, rewritten every 7 scanlines through CGRAM color 0. No assets, static image, zero per-frame CPU.

SNES Concepts
  • INDIRECT HDMA (DMAP bit 6): table entries are [count][ptr16]; the pointed-to data lives in the bank programmed in $43x7 — which plain hdmaSetup never writes; hdmaSetupIndirect() handles both
  • Non-repeat count semantics: count=7 fetches the payload ONCE and holds it for 7 scanlines (a repeat count $87 would fetch a fresh payload every line — that is the HiColor pattern)
  • HDMA_MODE_2REG_2X to CGADD: bytes stream as $2121,$2121,$2122,$2122 so each 4-byte block is [CGADD][CGADD][color_lo][color_hi] — rewriting CGRAM color 0 (the backdrop) per band
  • Extracting a C pointer's bank for $43x7: (u8)((u32)(void *)data >> 16) (post-A6 far pointers)
What to Observe
  • A pure red gradient: brightest red (BGR555 $001F) at the top fading to black at the bottom, in 32 bands of 7 scanlines
  • No tiles, no map, no sprites are loaded — everything on screen is the backdrop color being rewritten mid-frame by the HDMA channel
Modules Used
console, dma, hdma
See also
hdma.h (hdmaSetupIndirect), examples/hdma/gradient_colors

Macro Definition Documentation

◆ BAND_LINES

#define BAND_LINES   7

Scanlines per band (non-repeat count in each table entry).

◆ NBANDS

#define NBANDS   32

Gradient bands (krom: 32 bands x 7 scanlines = 224 lines).

Function Documentation

◆ main()

int main ( void )

Entry point — static 32-band red gradient, zero per-frame CPU.

Faithful to krom's register sequence: DMAP0=%01000011 (indirect | 2REG_2X), BBAD0=$21, A1T0=table, A1B0=$00, DASB0=$00, HDMAEN=ch0, TM=0, screen on. After hdmaEnable() the CPU idles — the PPU rebuilds the gradient from the pointer table on every frame by itself.

Returns
Never returns (infinite loop)

Variable Documentation

◆ band_data

u8 band_data[32][4]
static

Indirect payload blocks, one per band: [0][0][color_lo][color_hi].

In HDMA_MODE_2REG_2X the four bytes stream as $2121,$2121,$2122,$2122: CGADD is set to 0 (twice), then the 16-bit BGR555 color is written to CGDATA — i.e. CGRAM color 0, the backdrop. WRAM (bank $00), so the CPU could animate the colors at any time without touching the table.

◆ itable

u8 itable[32 *3+1]
static

The indirect table: [count][ptr_lo][ptr_hi] per band + terminator.