SNES HDMA (Horizontal-blanking DMA) More...
#include <snes/types.h>Go to the source code of this file.
Macros | |
| #define | HDMA_CHANNEL_0 0 |
| HDMA channel 0 (conflicts with common DMA usage) | |
| #define | HDMA_CHANNEL_1 1 |
| HDMA channel 1. | |
| #define | HDMA_CHANNEL_2 2 |
| HDMA channel 2. | |
| #define | HDMA_CHANNEL_3 3 |
| HDMA channel 3. | |
| #define | HDMA_CHANNEL_4 4 |
| HDMA channel 4. | |
| #define | HDMA_CHANNEL_5 5 |
| HDMA channel 5. | |
| #define | HDMA_CHANNEL_6 6 |
| HDMA channel 6 (recommended for HDMA) | |
| #define | HDMA_CHANNEL_7 7 |
| HDMA channel 7 (recommended for HDMA) | |
| #define | HDMA_DEST_BG1HOFS 0x0D |
| Destination: BG1 H scroll ($210D) | |
| #define | HDMA_DEST_BG1VOFS 0x0E |
| Destination: BG1 V scroll ($210E) | |
| #define | HDMA_DEST_BG2HOFS 0x0F |
| Destination: BG2 H scroll ($210F) | |
| #define | HDMA_DEST_BG2VOFS 0x10 |
| Destination: BG2 V scroll ($2110) | |
| #define | HDMA_DEST_BG3HOFS 0x11 |
| Destination: BG3 H scroll ($2111) | |
| #define | HDMA_DEST_BG3VOFS 0x12 |
| Destination: BG3 V scroll ($2112) | |
| #define | HDMA_DEST_CGADD 0x21 |
| Destination: CGRAM address ($2121) - for palette effects. | |
| #define | HDMA_DEST_CGDATA 0x22 |
| Destination: CGRAM data ($2122) - for color effects. | |
| #define | HDMA_DEST_COLDATA 0x32 |
| Destination: Fixed color ($2132) | |
| #define | HDMA_DEST_INIDISP 0x00 |
| Destination: INIDISP brightness ($2100) | |
| #define | HDMA_DEST_M7A 0x1B |
| Destination: Mode 7 matrix A ($211B) | |
| #define | HDMA_DEST_WH0 0x26 |
| Destination: Window 1 left ($2126) | |
| #define | HDMA_DEST_WH1 0x27 |
| Destination: Window 1 right ($2127) | |
| #define | HDMA_INDIRECT 0x40 |
| Indirect HDMA flag (OR with mode) | |
| #define | HDMA_MODE_1REG 0x00 |
| HDMA mode: 1 register, 1 byte. | |
| #define | HDMA_MODE_1REG_2X 0x02 |
| HDMA mode: 1 register, 2 bytes written twice. | |
| #define | HDMA_MODE_2REG 0x01 |
| HDMA mode: 2 registers, 2 bytes (low/high) | |
| #define | HDMA_MODE_2REG_2X 0x03 |
| HDMA mode: 2 registers, 4 bytes (2 to each) | |
| #define | HDMA_MODE_4REG 0x04 |
| HDMA mode: 4 registers, 4 bytes. | |
Functions | |
| void | hdmaBrightnessGradient (u8 channel, u8 topBrightness, u8 bottomBrightness) |
| Create a vertical brightness gradient. | |
| void | hdmaBrightnessGradientStop (u8 channel) |
| Stop brightness gradient and restore full brightness. | |
| void | hdmaColorGradient (u8 channel, u8 colorIndex, u16 topColor, u16 bottomColor) |
| Create a per-scanline CGRAM color gradient. | |
| void | hdmaColorGradientStop (u8 channel) |
| Stop color gradient effect. | |
| void | hdmaDisable (u8 channelMask) |
| Disable HDMA channel(s) | |
| void | hdmaDisableAll (void) |
| Disable all HDMA channels. | |
| void | hdmaEnable (u8 channelMask) |
| Enable HDMA channel(s) | |
| u8 | hdmaGetEnabled (void) |
| Get currently enabled HDMA channels. | |
| void | hdmaGradient (u8 channel, const void *colorTable) |
| Set up a fixed color gradient effect. | |
| void | hdmaIrisWipe (u8 channel, u8 layers, u8 centerX, u8 centerY, u8 radius) |
| Create a circular window mask (iris/spotlight effect) | |
| void | hdmaIrisWipeStop (u8 channel) |
| Stop iris wipe effect and restore window registers. | |
| void | hdmaParallax (u8 channel, u8 bg, const void *scrollTable) |
| Set up a background parallax scroll effect. | |
| void | hdmaSetTable (u8 channel, const void *table) |
| Update HDMA table pointer (for dynamic effects) | |
| void | hdmaSetup (u8 channel, u8 mode, u8 destReg, const void *table) |
| Set up an HDMA channel. | |
| void | hdmaSetupBank (u8 channel, u8 mode, u8 destReg, const void *table, u8 bank) |
| Set up an HDMA channel with explicit source bank byte. | |
| void | hdmaWaterRipple (u8 channel, u8 bg, u8 amplitude, u8 speed) |
| Create a water ripple distortion effect. | |
| void | hdmaWaveH (u8 channel, u8 bg, u8 amplitude, u8 frequency) |
| Set up horizontal wave effect (water reflection) | |
| void | hdmaWaveInit (void) |
| Initialize HDMA wave effect system. | |
| void | hdmaWaveSetSpeed (u8 speed) |
| Set wave speed. | |
| void | hdmaWaveStop (void) |
| Stop wave effect and disable HDMA channel. | |
| void | hdmaWaveUpdate (void) |
| Update wave animation. | |
| void | hdmaWindowShape (u8 channel, const void *windowTable) |
| Set up window position HDMA for shape effects. | |
SNES HDMA (Horizontal-blanking DMA)
HDMA transfers data to PPU registers once per scanline during HBlank, enabling effects like color gradients, parallax scrolling, and wave distortion that change across the screen.
HDMA uses a table in memory that specifies:
Each entry in the table is:
Non-repeat mode (bit 7 = 0): Write data ONCE, then skip N-1 scanlines
Use for registers that hold their value (COLDATA, CGADD). Efficient: 1 data set per group, regardless of line count.
Repeat mode (bit 7 = 1): Write same data EVERY scanline for N lines
REQUIRED for scroll registers (BG1HOFS, etc.) and other write-twice/ latched registers that need re-writing every scanline.
hdmaSetup() hardcodes bank $00 for ROM addresses (>= $8000). If the linker places a SUPERFREE table in bank $01+, HDMA will read wrong data. Use hdmaSetupBank() with an explicit bank byte for ROM tables, or use RAM-based tables (always bank $00) for dynamic effects.
BG scroll registers (BG1HOFS, BG1VOFS, etc.) are latched registers that require being written EVERY scanline to maintain their value. Use REPEAT mode (bit 7 = 1) in the HDMA line count for these registers.
Non-repeat mode (bit 7 = 0) writes data only ONCE per group, so the scroll value is lost on subsequent scanlines — causing visible glitches.
Summary:
| #define HDMA_CHANNEL_0 0 |
HDMA channel 0 (conflicts with common DMA usage)
| #define HDMA_CHANNEL_1 1 |
HDMA channel 1.
| #define HDMA_CHANNEL_2 2 |
HDMA channel 2.
| #define HDMA_CHANNEL_3 3 |
HDMA channel 3.
| #define HDMA_CHANNEL_4 4 |
HDMA channel 4.
| #define HDMA_CHANNEL_5 5 |
HDMA channel 5.
| #define HDMA_CHANNEL_6 6 |
HDMA channel 6 (recommended for HDMA)
| #define HDMA_CHANNEL_7 7 |
HDMA channel 7 (recommended for HDMA)
| #define HDMA_DEST_BG1HOFS 0x0D |
Destination: BG1 H scroll ($210D)
| #define HDMA_DEST_BG1VOFS 0x0E |
Destination: BG1 V scroll ($210E)
| #define HDMA_DEST_BG2HOFS 0x0F |
Destination: BG2 H scroll ($210F)
| #define HDMA_DEST_BG2VOFS 0x10 |
Destination: BG2 V scroll ($2110)
| #define HDMA_DEST_BG3HOFS 0x11 |
Destination: BG3 H scroll ($2111)
| #define HDMA_DEST_BG3VOFS 0x12 |
Destination: BG3 V scroll ($2112)
| #define HDMA_DEST_CGADD 0x21 |
Destination: CGRAM address ($2121) - for palette effects.
| #define HDMA_DEST_CGDATA 0x22 |
Destination: CGRAM data ($2122) - for color effects.
| #define HDMA_DEST_COLDATA 0x32 |
Destination: Fixed color ($2132)
| #define HDMA_DEST_INIDISP 0x00 |
Destination: INIDISP brightness ($2100)
| #define HDMA_DEST_M7A 0x1B |
Destination: Mode 7 matrix A ($211B)
| #define HDMA_DEST_WH0 0x26 |
Destination: Window 1 left ($2126)
| #define HDMA_DEST_WH1 0x27 |
Destination: Window 1 right ($2127)
| #define HDMA_INDIRECT 0x40 |
Indirect HDMA flag (OR with mode)
When set, table contains pointers to data instead of data itself. Useful for large tables or dynamic data.
| #define HDMA_MODE_1REG 0x00 |
HDMA mode: 1 register, 1 byte.
Writes 1 byte to destination register each scanline. Table entry: 1 byte line count + 1 byte data
| #define HDMA_MODE_1REG_2X 0x02 |
HDMA mode: 1 register, 2 bytes written twice.
Writes 2 bytes to same register (for double-write registers). Table entry: 1 byte line count + 2 bytes data
| #define HDMA_MODE_2REG 0x01 |
HDMA mode: 2 registers, 2 bytes (low/high)
Writes 2 bytes to consecutive registers (e.g., scroll low/high). Table entry: 1 byte line count + 2 bytes data
| #define HDMA_MODE_2REG_2X 0x03 |
HDMA mode: 2 registers, 4 bytes (2 to each)
Writes 4 bytes: 2 to dest, 2 to dest+1. Table entry: 1 byte line count + 4 bytes data
| #define HDMA_MODE_4REG 0x04 |
HDMA mode: 4 registers, 4 bytes.
Writes 4 bytes to 4 consecutive registers. Table entry: 1 byte line count + 4 bytes data
Create a vertical brightness gradient.
Smoothly fades screen brightness from top to bottom using HDMA on the INIDISP register ($2100). Useful for:
| channel | HDMA channel (6 or 7 recommended) |
| topBrightness | Brightness at top of screen (0-15, 15=full) |
| bottomBrightness | Brightness at bottom of screen (0-15) |
| void hdmaBrightnessGradientStop | ( | u8 | channel | ) |
Stop brightness gradient and restore full brightness.
| channel | The channel used for the gradient |
Create a per-scanline CGRAM color gradient.
Smoothly interpolates a palette color from one value to another across the screen. Uses HDMA to rewrite a CGRAM entry per scanline. Useful for:
| channel | HDMA channel (6 or 7 recommended) |
| colorIndex | CGRAM color index to modify (0-255) |
| topColor | 15-bit SNES color at top of screen (use RGB() macro) |
| bottomColor | 15-bit SNES color at bottom of screen |
| void hdmaColorGradientStop | ( | u8 | channel | ) |
Stop color gradient effect.
| channel | The channel used for the gradient |
| void hdmaDisable | ( | u8 | channelMask | ) |
Disable HDMA channel(s)
Disables the specified HDMA channel(s).
| channelMask | Bitmask of channels to disable |
| void hdmaDisableAll | ( | void | ) |
Disable all HDMA channels.
Convenience function to stop all HDMA activity.
| void hdmaEnable | ( | u8 | channelMask | ) |
Enable HDMA channel(s)
Enables the specified HDMA channel(s). HDMA will start on the next frame.
| channelMask | Bitmask of channels to enable (1 << channel) |
| u8 hdmaGetEnabled | ( | void | ) |
Get currently enabled HDMA channels.
| void hdmaGradient | ( | u8 | channel, |
| const void * | colorTable | ||
| ) |
Set up a fixed color gradient effect.
Creates a vertical color gradient by changing the fixed color register per scanline. Useful for sky gradients, underwater effects, etc.
| channel | HDMA channel to use |
| colorTable | HDMA table with COLDATA values |
Create a circular window mask (iris/spotlight effect)
Uses HDMA to drive window registers (WH0/WH1) per scanline, approximating a circle. Configures all window registers automatically. Useful for:
| channel | HDMA channel (6 or 7 recommended) |
| layers | Layer bitmask to apply window masking (TM_BG1, TM_BG2, etc.) |
| centerX | Horizontal center of circle (0-255) |
| centerY | Vertical center of circle (0-223) |
| radius | Circle radius in pixels (0-128) |
| void hdmaIrisWipeStop | ( | u8 | channel | ) |
Stop iris wipe effect and restore window registers.
Disables the HDMA channel and clears all window masking registers (W12SEL, W34SEL, WOBJSEL, TMW) to restore normal display.
| channel | The channel used for the iris wipe |
Set up a background parallax scroll effect.
Creates horizontal parallax scrolling where each section of the screen scrolls at a different speed based on the scroll table.
| channel | HDMA channel to use |
| bg | Background layer (0=BG1, 1=BG2, 2=BG3) |
| scrollTable | HDMA table with scroll values |
| void hdmaSetTable | ( | u8 | channel, |
| const void * | table | ||
| ) |
Update HDMA table pointer (for dynamic effects)
Changes the table pointer for an already-configured channel. Takes effect on the next frame.
| channel | HDMA channel (0-7) |
| table | New table pointer |
Set up an HDMA channel.
Configures an HDMA channel with the specified parameters. The channel is NOT enabled automatically - call hdmaEnable() to start it.
| channel | HDMA channel (0-7, use HDMA_CHANNEL_6 or _7) |
| mode | Transfer mode (HDMA_MODE_*) |
| destReg | Destination B-bus register (low byte of $21xx address) |
| table | Pointer to HDMA table in ROM or RAM |
Set up an HDMA channel with explicit source bank byte.
Same as hdmaSetup() but allows specifying the ROM bank for HDMA tables in banks other than $00. Use this when your HDMA table is in a SUPERFREE section that may be placed in bank $01+ by the linker.
| channel | HDMA channel (0-7, use HDMA_CHANNEL_6 or _7) |
| mode | Transfer mode (HDMA_MODE_*) |
| destReg | Destination B-bus register (low byte of $21xx address) |
| table | Pointer to HDMA table in ROM or RAM |
| bank | Source bank byte ($00-$3F for LoROM) |
Create a water ripple distortion effect.
Similar to hdmaWaveH but with amplitude that increases from top to bottom, simulating underwater refraction or heat haze. Uses the wave system's double-buffered tables internally.
| channel | HDMA channel (6 or 7 recommended) |
| bg | Background layer (0=BG1, 1=BG2, 2=BG3) |
| amplitude | Maximum ripple amplitude at bottom of screen (1-60 pixels, clamped) |
| speed | Animation speed (1=slow, 4=fast) |
Set up horizontal wave effect (water reflection)
Creates a wavy horizontal distortion, commonly used for:
| channel | HDMA channel to use (6 or 7 recommended) |
| bg | Background layer to affect (0=BG1, 1=BG2, 2=BG3) |
| amplitude | Wave amplitude in pixels (1-60, clamped internally) |
| frequency | Wave frequency (1-16, higher = tighter waves). Period = 256/frequency scanlines. |
| void hdmaWaveInit | ( | void | ) |
Initialize HDMA wave effect system.
Must be called once before using wave effects. Allocates internal buffers and sets up the wave state.
| void hdmaWaveSetSpeed | ( | u8 | speed | ) |
Set wave speed.
| speed | Animation speed (1=slow, 4=fast, default=2) |
| void hdmaWaveStop | ( | void | ) |
Stop wave effect and disable HDMA channel.
Disables the wave effect and frees the HDMA channel.
| void hdmaWaveUpdate | ( | void | ) |
Update wave animation.
Call this once per frame (after WaitForVBlank) to animate the wave effect. Updates the HDMA table with new wave values.
| void hdmaWindowShape | ( | u8 | channel, |
| const void * | windowTable | ||
| ) |
Set up window position HDMA for shape effects.
Uses HDMA to change window boundaries per scanline, creating shapes like circles, triangles, or custom masks.
| channel | HDMA channel to use |
| windowTable | HDMA table with left/right pairs |