OpenSNES
Modern Open-Source SNES Development SDK
Loading...
Searching...
No Matches
Mode 7 -- Rotation and Scaling
Demo
Screenshot

What This Example Shows

How to use the SNES Mode 7 – a special background mode that applies an affine transformation (rotation + scaling) to a single 128x128 tile layer. This is the same technique behind F-Zero's ground, Mario Kart's tracks, and Pilotwings' maps.

Prerequisites

Read backgrounds/mode1 first (basic background setup). Mode 7 is fundamentally different from tile-based modes but the initialization flow is similar.

Controls

Button Action
A Rotate clockwise
B Rotate counter-clockwise
D-PAD Up Zoom out (see more of the plane)
D-PAD Down Zoom in (magnify)

Build & Run

cd $OPENSNES_HOME
make -C examples/mode7/rotate_scale

Then open mode7.sfc in your emulator (Mesen2 recommended).

How It Works

1. Mode 7 VRAM format

Mode 7 uses a special interleaved VRAM format:

  • Even bytes: tilemap entries (128x128 = 16,384 tiles)
  • Odd bytes: pixel data (256 tiles, 8x8, 256 colors each)

This is completely different from Modes 0-3 where tilemap and tile data are in separate VRAM regions. main.c calls dmaCopyVramMode7(), which writes the tilemap and the tile data into the interleaved format the PPU expects (two DMAs with different VMAIN settings), then dmaCopyCGram() for the palette.

2. Initialize the transformation

mode7SetScale(0x0100, 0x0100);
#define BG_MODE7
Definition video.h:41
void mode7SetScale(u16 scale_x, u16 scale_y)
Set Mode 7 scale factors.
void mode7SetAngle(u8 angle)
Set Mode 7 rotation angle.
void mode7Init(void)
Initialize Mode 7.
void setMode(u8 mode, u8 flags)
Set background mode.

mode7Init() sets the rotation center to the screen center (128, 128). Scale 0x0100 is 1:1 (one texel per pixel).

3. Update the matrix every frame

if (pad0 & KEY_A) {
angle++;
}
static u16 pad0
Definition main.c:166
#define KEY_A
Definition input.h:84
static u16 angle
Mode 7 ground: 9-tile prefab track (original art).
Definition main.c:46

mode7SetAngle() recalculates the 2x2 transformation matrix (registers M7A-M7D at $211B-$211E) using the current angle and scale. The angle is 0-255, mapping to 0-360 degrees.

4. Zoom control

if (pad0 & KEY_UP) {
if (zscale < 0x0780) zscale += 8;
mode7SetScale(zscale, zscale);
}
#define KEY_UP
Definition input.h:78

After changing the scale, you must call mode7SetAngle() again because the matrix depends on both angle and scale. The scale range is clamped to 0x0008-0x0780 – values outside this range produce extreme distortion.

SNES Concepts

Affine Transformation

Mode 7 applies a 2x2 matrix to BG1. The matrix encodes rotation, scaling, and skew. The hardware computes the transform per-scanline using four registers:

Register Address Purpose
M7A $211B Matrix element A (cosine * scale)
M7B $211C Matrix element B (sine * scale)
M7C $211D Matrix element C (-sine * scale)
M7D $211E Matrix element D (cosine * scale)

One Layer Only

Mode 7 supports exactly one background (BG1). No BG2/BG3/BG4. Sprites still work normally on top, which is how F-Zero renders its cars.

256-Color Palette

Each Mode 7 tile uses 256 colors (8bpp), unlike Modes 0-3 which use 2/4/8 colors per palette. This gives richer visuals but limits you to 256 unique tiles total.

8.8 Fixed-Point Scale

0x0100 = 1:1, 0x0200 = shrunk twice (shows more area), 0x0080 = magnified twice. The integer part is the high byte, the fractional part is the low byte.

Project Structure

File Purpose
main.c Input handling, rotation/zoom logic
res/mode7bg.png.toml the import settings of the Mode 7 picture (opensnes-tileset, mode = 7); the build converts and links it, res/mode7bg.inc declares the symbols
res/mode7bg.png Source image for Mode 7 ground
Makefile LIB_MODULES := console dma background sprite input mode7

Going Further

  • Add scrolling: Use mode7SetPos() to pan across the Mode 7 plane with the D-pad while rotating. This is how F-Zero navigates its tracks.
  • Add sprites on top: Load sprite tiles and place an OAM sprite over the rotating background. Mode 7 supports full sprite rendering.
  • Explore related examples:
    • mode7/perspective – Per-scanline scaling for pseudo-3D (F-Zero style)
    • effects/hdma_wave – HDMA can modify Mode 7 parameters per scanline

Modules Used

console, dma, background, sprite, input, mode7 (LIB_MODULES in the Makefile).