A triangle-shaped window mask driven by HDMA, showing how per-scanline window boundary updates create non-rectangular shapes. Press A, X, or B to apply the window to different background layers.
Ported from PVSnesLib "Window" example.
| Button | Action |
|---|---|
| A | Window on BG1 only |
| X | Window on BG2 only |
| B | Window on both BG1 and BG2 |
Then open window.sfc in your emulator (Mesen2 recommended).
The SNES PPU has two hardware windows – rectangular regions defined by left and right X coordinates. These windows can mask (hide) portions of any background layer or sprite layer. Window operations cost zero CPU time because they are handled entirely by the PPU.
A single window is always a horizontal band. But by changing the left/right boundaries every scanline using HDMA, you can create any shape – circles, triangles, or custom silhouettes.
This example uses two HDMA channels:
The HDMA tables define a diamond/triangle shape centered on screen:
The tables use repeat mode (bit 7 set in the line count) because each scanline needs a different value. Non-repeat mode would write once and hold, which does not work when the shape changes per line.
By default, TMW (main screen window at $212E) hides pixels inside the window. The code sets the invert flag in W12SEL ($2123) so that pixels outside the window are hidden instead – revealing only the triangle-shaped area.
When you press A/X/B, the code:
windowInit()This register controls Window 1 enable and inversion for BG1 and BG2:
| Bit | Purpose |
|---|---|
| 0 | BG1 Window 1 Invert |
| 1 | BG1 Window 1 Enable |
| 4 | BG2 Window 1 Invert |
| 5 | BG2 Window 1 Enable |
Setting both the enable and invert bits for a BG makes pixels outside the window invisible, revealing only the windowed region.
This technique was used extensively: spotlight effects in Mega Man X, the title screen reveal in Donkey Kong Country, and dialog box cutouts in RPGs. Any shape that can be described as a left-right boundary pair per scanline can be rendered as a window.
| Region | Content |
|---|---|
| $0000 | BG1 tilemap (32x32) |
| $1000 | BG2 tilemap (32x32) |
| $4000 | BG1 tiles (4bpp, 16 colors) |
| $6000 | BG2 tiles (4bpp, 16 colors) |
| File | Purpose |
|---|---|
main.c | HDMA triangle tables, window setup, input loop |
data.asm | Two backgrounds (BG1 + BG2) graphics data |
res/bg1.png | Background 1 (palette slot 0) |
res/bg2.png | Background 2 (palette slot 1) |
Makefile | LIB_MODULES := console sprite dma input background window hdma math |
x = sqrt(r^2 - y^2).effects/transparent_window – Window + color math for semi-transparent overlayseffects/hdma_wave – Another HDMA-driven per-scanline effect