How to combine Mode 7 with HDMA to create a perspective ground plane – the same technique used in F-Zero, Mario Kart, and Pilotwings. The screen is split in two: a static sky on top and a scaled ground that recedes into the distance.
Read backgrounds/mode7 first (Mode 7 basics), then effects/hdma_wave (HDMA per-scanline programming).
| Button | Action |
|---|---|
| D-PAD | Scroll the ground plane |
Then open mode7_perspective.sfc in your emulator (Mesen2 recommended).
The screen is divided by 4 HDMA channels running every frame:
| Channel | Target | Effect |
|---|---|---|
| Ch1 | BGMODE ($2105) | Switches from Mode 3 (sky) to Mode 7 (ground) |
| Ch2 | TM ($212C) | Switches from BG2 (sky tiles) to BG1 (Mode 7 ground) |
| Ch3 | M7A ($211B) | Per-scanline horizontal scale (perspective) |
| Ch4 | M7D ($211E) | Per-scanline vertical scale (perspective) |
Top 96 scanlines: Mode 3 displays a static sky background on BG2. Bottom 128 scanlines: Mode 7 displays the ground with per-scanline scaling.
The key to the 3D illusion: scanlines near the top of the ground area (the "horizon") use a large scale value (small objects = far away), while scanlines near the bottom use a small scale value (large objects = close up).
This is a pre-computed table in the assembly data – each of the 128 ground scanlines has its own M7A/M7D scale pair.
The scroll values are passed to the assembly helper, which writes them to the Mode 7 scroll registers (M7HOFS/M7VOFS at $210D/$210E) and re-enables the HDMA channels each frame.
The SNES allows changing the BGMODE register ($2105) via HDMA between scanlines. This is how one screen shows two completely different video modes – Mode 3 for the sky portion and Mode 7 for the ground portion. The switch happens during HBlank, so there is no visible glitch.
By writing M7A/M7D every scanline via HDMA repeat mode, each horizontal line of the ground has a different scale factor. Lines near the horizon are scaled way down (far away), lines at the bottom are close to 1:1 (nearby). This creates the depth illusion without any 3D math at runtime – it is all pre-computed tables.
4 simultaneous HDMA channels is feasible but uses significant bus time per scanline. Each HDMA transfer needs ~18 master cycles per byte during HBlank. Adding more channels risks running out of HBlank time (1364 master cycles per scanline).
| File | Purpose |
|---|---|
main.c | Input handling, scroll updates, HDMA initialization |
data.asm | Mode 7 ground data, sky tiles, HDMA perspective tables, assembly helpers |
res/ground.png | Mode 7 ground texture source |
res/sky.png | Sky background source |
Makefile | LIB_MODULES := console dma background sprite input mode7 |
effects/gradient_colors – Another HDMA technique (color gradients)games/likemario – Scrolling backgrounds with sprites (different approach)