Loading...
Searching...
No Matches
main.c File Reference

HDMA-driven sinusoidal wave distortion on background. More...

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

Macros

#define AMP_DEFAULT   3
 
#define AMP_LEVELS   7
 
#define SINE_PERIOD   112
 
#define TABLE_ENTRIES   335
 
#define TABLE_SIZE   1006
 

Functions

int main (void)
 Entry point – HDMA-driven sinusoidal wave distortion on background.
 

Variables

static const u16 amp_offsets [7]
 Pre-computed byte offsets into hdma_tables[] for each amplitude level.
 
static const u8 hdma_tables [7 *1006]
 Pre-computed HDMA sine wave tables for 7 amplitude levels.
 
static const u8 tiles []
 Minimal 4bpp tile data: one empty tile and one solid tile.
 
Wave Effect State

Runtime state variables for the wave distortion effect.

These are static (file-scope) variables, which the compiler places in WRAM via RAMSECTION + .data_init. They persist across frames and are initialized explicitly in main() rather than relying on C static init.

static u8 amp_idx
 
static u8 animating
 
static u8 phase
 
static u8 wave_on
 

Detailed Description

HDMA-driven sinusoidal wave distortion on background.

Creates a wavy horizontal distortion effect by using HDMA to write per-scanline BG1 horizontal scroll offsets (BG1HOFS, $210D). A set of 7 pre-computed sine tables at increasing amplitudes (0 to 24 pixels) are stored in ROM, each containing 335 entries (224 visible scanlines + 111 wrap entries for smooth phase animation). HDMA channel 6 is configured in write-twice mode (1REG_2X) to write both the low and high bytes of BG1HOFS each scanline. When animation is enabled, the table pointer advances by 3 bytes per frame (one HDMA entry), cycling through the wrap portion to create continuous wave motion. The background consists of simple alternating solid/empty tiles to make the distortion clearly visible.

SNES Concepts
  • HDMA write-twice mode (1REG_2X) targeting BG1HOFS ($210D)
  • Per-scanline horizontal scroll offset for wave distortion
  • Repeat-mode HDMA entries (bit 7 set = write every scanline)
  • Pre-computed sine tables with wrap region for seamless animation
  • Bare-metal VRAM and CGRAM writes (no library DMA helpers)
What to Observe
  • Press A to toggle the wave effect on/off
  • Press LEFT/RIGHT to decrease/increase wave amplitude (7 levels)
  • Press UP to start wave animation (the wave scrolls vertically)
  • Press DOWN to stop animation (wave freezes in place)
Modules Used
console, dma, sprite, input, hdma
See also
hdma.h, input.h, video.h

Macro Definition Documentation

◆ AMP_DEFAULT

#define AMP_DEFAULT   3

Default amplitude index (amplitude level 12 pixels)

◆ AMP_LEVELS

#define AMP_LEVELS   7

Number of amplitude levels (0, 4, 8, 12, 16, 20, 24 pixels)

◆ SINE_PERIOD

#define SINE_PERIOD   112

Sine wave period in scanlines (half the visible screen height)

◆ TABLE_ENTRIES

#define TABLE_ENTRIES   335

Entries per table: 224 visible scanlines + 111 wrap entries for smooth animation

◆ TABLE_SIZE

#define TABLE_SIZE   1006

Bytes per amplitude table: 335 entries x 3 bytes + 1 end marker (0x00)

Function Documentation

◆ main()

int main ( void  )

Entry point – HDMA-driven sinusoidal wave distortion on background.

Sets up a simple striped background using bare-metal VRAM and CGRAM writes (no library DMA helpers), then configures HDMA channel 6 to apply per-scanline horizontal scroll offsets from pre-computed sine tables.

Controls:

  • A: toggle wave on/off
  • LEFT/RIGHT: decrease/increase amplitude
  • UP: start animation (wave scrolls vertically)
  • DOWN: stop animation (wave freezes)
Returns
Does not return (infinite loop).

< Default amplitude index (amplitude level 12 pixels)

Variable Documentation

◆ amp_idx

u8 amp_idx
static

Current amplitude index (0-6, selects which table to use)

◆ amp_offsets

const u16 amp_offsets[7]
static
Initial value:
= {
0, 1006, 2012, 3018, 4024, 5030, 6036
}

Pre-computed byte offsets into hdma_tables[] for each amplitude level.

Since each amplitude table is TABLE_SIZE (1006) bytes, the offset for level N is N * 1006. These are pre-computed to avoid runtime multiplication (the 65816 has no hardware multiply for 16-bit values, so amp_idx * 1006 would require an expensive software multiply routine).

◆ animating

u8 animating
static

Animation enabled flag (0=frozen, 1=scrolling)

◆ hdma_tables

const u8 hdma_tables[7 * 1006]
static

Pre-computed HDMA sine wave tables for 7 amplitude levels.

Each amplitude level has TABLE_SIZE (1006) bytes containing 335 HDMA entries plus a 0x00 terminator. Each entry is 3 bytes:

  • Byte 0: 0x81 = repeat flag (bit 7) + 1 scanline count (bits 6-0). The repeat flag tells HDMA to re-read data bytes for every scanline in the group (here, just 1 scanline), which is required for smooth per-line distortion.
  • Bytes 1-2: BG1HOFS low byte and high byte (16-bit scroll offset). Positive values shift the BG right, negative (two's complement, e.g. 0xFF,0xFF = -1) shift left.

The 335 entries cover 224 visible scanlines plus 111 extra entries. By advancing the HDMA start pointer by 3 bytes (one entry) per frame, the wave pattern appears to scroll vertically. After 112 entries (one full sine period), the pattern repeats seamlessly due to the wrap region.

Amplitude levels: 0, 4, 8, 12, 16, 20, 24 pixels peak displacement.

◆ phase

u8 phase
static

Current animation phase (0-111, index into sine period)

◆ tiles

const u8 tiles[]
static
Initial value:
= {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}

Minimal 4bpp tile data: one empty tile and one solid tile.

SNES 4bpp tiles are 32 bytes each (8x8 pixels, 4 bitplanes). The first 16 bytes contain interleaved bitplanes 0 and 1, the next 16 contain bitplanes 2 and 3. For a "solid color 1" tile, only bitplane 0 needs to be set (all 0xFF), with all other bitplanes zero. The alternating empty/solid pattern in the tilemap creates vertical stripes that make the wave distortion clearly visible.

◆ wave_on

u8 wave_on
static

Wave effect enabled flag (0=off, 1=on)