An interactive course · the S-PPU1 & S-PPU2

How the Super NES drew its worlds.

We start from the very beginning — what a digital picture even is — assuming you know nothing about computer graphics. Once the vocabulary is solid, we follow a frame through the Super Nintendo's two picture-processing chips and out to the electron beam. Sixteen modules — fourteen of them with live, procedurally-rendered labs — so you can drag, paint and break every idea, not just read it. No game artwork ships with this page; every pixel is drawn in your browser.

Part I

2D graphics from zero

This first part is pure fundamentals — nothing about any specific chip yet. It's the toolkit that every tile-based 2D machine is built from, from arcade boards to the Game Boy to the console we meet in Part II. We build the vocabulary one word at a time — pixel, palette, tile, bitplane, tilemap, sprite, layer, scanline — and each idea has a live lab you can poke. If a term is ever used before it's explained, that's a bug. Everything in Parts II and III is just these ideas wired together in silicon.

Modules 01–07Difficulty Absolute beginnerLabs 7 interactive
Module 01 · Part I

Pixels & the framebuffer

GoalUnderstand, from scratch, how a picture on a screen becomes a grid of numbers a computer can store and change — and how small that grid was on the SNES.

Lean in close to any display — a phone, or the family CRT the Super Nintendo was plugged into — and the image falls apart into a grid of tiny glowing dots. Each dot is a pixel (from “picture element”), and it can show exactly one colour at a time. Step back and your eye fuses the grid into a smooth image. That's all a digital picture is: a rectangular grid of single-colour dots.

The whole grid of colour numbers, held in memory, is the framebuffer. The number of dots across and down is the resolution. And here is the first genuinely Super-Nintendo fact: its standard picture is a mere 256 × 224 pixels. That is tiny — about a thirty-sixth of a modern 1080p frame. The console could also switch to a 512-pixel-wide hi-res width, output 239 tall, or run interlace to reach 448/478 tall, but the everyday canvas artists worked on was those 256 × 224 dots. Every trick in this course exists to make that small grid look rich. And here's a twist to file away right now: the SNES famously does not store this grid — there is no big framebuffer of finished pixels inside the console. Part II shows how it fakes one, a line at a time.

Analogy · A mosaic

A mosaic portrait is thousands of small single-colour tiles. Up close: coloured squares. Across the room: a face. A pixel grid is a mosaic your machine repaints sixty times a second — and the framebuffer is the numbered order sheet saying which tile goes where. On the SNES that sheet was small enough to matter: every pixel had to earn its place.

index → palette 256 × 224 an 8 × 8 patch of the frame one pixel, magnified …is one small number the whole SNES frame the everyday SNES canvas is only 256 × 224 = 57,344 pixels
Pictures as numbers. An image is a grid of pixels. On the SNES a pixel is not stored as red/green/blue directly — it's stored as a small index that looks up a colour in a palette (Module 02). Change the numbers in the framebuffer and dots on screen change.

Play with the idea below. Pick a colour, drag across the grid, and watch a picture become a list of numbers. Shrink the grid and every dot gets chunkier; the byte count in the readout is the size of this little framebuffer. A grid-of-pixels image like this is called a raster image — remember the word, because Module 07 is all about how the beam rasterises one line at a time.

Pixel lab — paint a tiny framebufferCanvas · live
Key takeaways
  • A digital image is a grid of pixels; each pixel shows one colour.
  • The framebuffer is the memory holding those numbers — change it and the screen changes.
  • The SNES standard resolution is a small 256 × 224 (also 512-wide hi-res, 239 tall, and interlaced 448/478).
  • On the SNES a pixel is stored as an index, not raw RGB — the next module explains why.
Module 02 · Part I

Colour & palettes

GoalSee why the SNES stores colours in a lookup table, how one colour is packed into 15 bits of BGR, and how many colours the machine can show.

Storing three full bytes of red/green/blue for every one of 57,344 pixels would have been ruinously expensive in 1990. So the SNES — like almost every machine of its era — uses indexed colour. Each pixel holds a small index (a 4-bit number 0–15 is typical), and a separate table turns that index into a real colour. That table lives in a dedicated 512-byte memory called CGRAM, and it holds 256 entries.

01

Reading binary and hex — a 60-second detour. A bit is a single 0-or-1; a group of n bits can count from 0 up to 2n−1, so 5 bits reach 31 and 8 bits reach 255. Hardware people write binary with a % prefix and hexadecimal (base 16, digits 0–9 then A–F) with a $ prefix. One worked conversion: %11111 is 16+8+4+2+1 = 31, which in hex is $1F (one 16 plus fifteen 1s). That's all the notation this course ever uses.

Each CGRAM entry is a 15-bit BGR value: five bits of blue, five of green, five of red, packed into one 16-bit word (the top bit is unused). Five bits per channel means 32 shades each, so the SNES's total palette — the set of colours it can choose from — is 32 × 32 × 32 = 32,768 colours. It can display up to 256 of them at once (before the colour-math trickery of Module 12). Note the channel order: hardware people write it BGR because blue occupies the high bits — a colour word looks like 0bbbbbgggggrrrrr. (To the CPU, CGRAM is a little port: you pick an entry number at $2121, then send the 15-bit word as two writes to $2122 — low byte first, then high.)

One more idea completes the picture: sub-palettes. A pixel's index is usually only 4 bits (0–15), yet CGRAM holds 256 colours. The bridge is slicing: CGRAM is carved into sixteen 16-colour blocks, and every tile or sprite is told (by its tilemap entry or OAM attributes — Modules 04 and 05) which block its 0–15 indices point into. By convention the first eight blocks serve the backgrounds and the last eight serve sprites. Module 03's tiles will produce exactly those 0–15 numbers — now you know what they index into.

one CGRAM colour word · %0BBBBBGGGGGRRRRR · written to $2122 twice, low byte first high byte (second write) 0 B B B B B G G low byte (first write) G G G R R R R R ① write low byte ($2122) ② write high byte ($2122) all 256 entries · sixteen 16-colour sub-palettes row 0 row 7 row 8 row 15 one row = one 16-entry sub-palette · a tile's 0–15 index picks a column within its row rows 0–7 backgrounds rows 8–15 sprites (OBJ) entries 128–255
CGRAM, twice over. Top: one colour is a 15-bit BGR word, delivered to $2122 as two byte writes — low half first. Bottom: the 256 entries behave as sixteen 16-colour sub-palettes; a 4bpp tile's pixel indices (0–15) only choose a column, while its tilemap entry or OAM attribute chooses the row. Backgrounds use the first eight rows, sprites the last eight.
Analogy · Paint-by-numbers

A paint-by-numbers kit gives you a canvas full of little numbered regions and a legend: “3 = sky blue, 7 = grass green.” The canvas never stores paint — just numbers. Swap the legend and the whole picture recolours without touching the canvas. That legend is CGRAM, and swapping it is exactly how SNES games flash, fade to white, or cycle waterfalls — change the palette, not the pixels.

The lab below is a colour mixer over one 16-entry sub-palette. Drag the R/G/B sliders (each 0–31) to build a colour and read its 15-bit word live; click any swatch to select and edit that entry. This is, almost exactly, what a game's palette editor showed an artist in 1991.

Palette lab — mix a 15-bit BGR colourLive
Selected colour
Sub-palette · click to select an entry
Key takeaways
  • Pixels store an index; CGRAM (512 bytes, 256 entries) turns each index into a colour.
  • Each entry is 15-bit BGR — 5 bits per channel — so the master palette is 32,768 colours.
  • CGRAM is sliced into sixteen 16-colour sub-palettes: a tile's 0–15 indices pick a column, its tilemap/OAM entry picks the row.
  • Up to 256 colours on screen at once from that palette (more with colour math).
  • Recolouring the whole scene = rewriting CGRAM, not the pixels — the source of countless SNES effects.
Module 03 · Part I

Tiles & bitplanes

GoalLearn why the SNES draws everything from 8×8 tiles, and how a tile's pixels are stored as stacked 1-bit bitplanes.

The SNES almost never draws individual pixels. It draws tiles: fixed 8 × 8 blocks of pixels, stored once and reused all over the screen. A brick wall is one brick tile repeated; a font is a tile per glyph. Reuse is the whole point — it slashes memory and lets the hardware fetch a known-size block on a predictable schedule.

Now, how is one tile's colour data laid out? Not as “index, index, index” pixel by pixel. Instead the SNES uses planar bitplanes. Think of a pixel's index in binary. A 4-bit index has bits 0,1,2,3. The hardware stores all the bit-0s of every pixel as one 8 × 8 one-bit image (plane 0), all the bit-1s as another (plane 1), and so on. Stack the planes and read the same pixel out of each: those bits, combined, are that pixel's palette index. The number of planes sets the bit depth: 2bpp (2 planes → 4 colours), 4bpp (4 planes → 16 colours), or 8bpp (8 planes → 256 colours). Why so roundabout? Because it matched the silicon of the day: a one-bit-wide shift register per plane was about the cheapest circuit a 1980s chip designer could lay down, so spitting out one bit from each plane per pixel cost almost nothing.

Try one row by hand to make it concrete. Suppose a 2bpp row's two plane bytes are $3C and $66 — in binary, plane 0 = %00111100 and plane 1 = %01100110. Read each column top to bottom (plane 1's bit is the twos place, plane 0's the ones place) and the eight pixels come out as indices 0, 2, 3, 1, 1, 3, 2, 0 — which, via Module 02, are eight colours from the tile's sub-palette. One exception to file away for Module 10: Mode 7's tiles are not planar at all — they're stored linear, one whole byte per pixel.

Analogy · Transparent overlays

Imagine four sheets of clear acetate, each stamped with a pattern of dots. Lay them on top of one another over a lightbox: where sheets 1 and 3 both have a dot, you read the binary number 0101 = 5, and pixel 5's colour appears. Toggle one sheet and every pixel's number shifts. That's a bitplane tile — and it's exactly what the lab lets you do.

four 1-bit planes stack into one 4-bit index plane 0 (bit 0) plane 1 (bit 1) plane 2 (bit 2) plane 3 (bit 3) composited tile index 0–15 4 planes = 4 bits = 16 colours = 32 bytes
Planar storage. A 4bpp tile is four 8×8 one-bit planes. Read one pixel out of all four planes, combine the bits, and you have its 0–15 palette index. In SNES memory the planes are interleaved a specific way: planes 0/1 by row first (16 bytes), then planes 2/3 (16 bytes) — 32 bytes per 4bpp tile.

In the lab, paint palette indices onto the 8 × 8 tile, then switch individual planes off. Watch the composited colours jump as a bit is forced to zero everywhere — and watch the raw 32-byte layout update underneath. This is the exact byte order a real SNES tile occupies in VRAM.

Bitplane lab — build a 4bpp tileCanvas · live
Key takeaways
  • Everything is built from reusable 8×8 tiles — huge memory savings.
  • Tiles are stored as planar bitplanes: one 1-bit layer per index bit, stacked.
  • Bit depth = number of planes: 2bpp/4bpp/8bpp → 4/16/256 colours.
  • A 4bpp tile is 32 bytes, with planes 0/1 interleaved by row, then 2/3.
Module 04 · Part I

Tilemaps & scrolling

GoalAssemble a full background from a grid of tile references, and scroll it smoothly with a single pair of registers.

A tile is 8 × 8; the screen is far bigger. The bridge is the tilemap: a grid of small entries, one per tile-sized cell of the background. A SNES tilemap screen is 32 × 32 entries (256 × 256 pixels), and layers can stitch several of these together for scrolling room — each background chooses one, two or four screens, arranged 32×32, 64×32, 32×64 or 64×64 tiles. Each entry is a 16-bit word that packs more than just a tile number: a tile index, a palette number (which of the sub-palettes to use), a priority bit, and horizontal & vertical flip flags — so one tile can face four ways and wear different colours across the map for free.

one tilemap entry · 16 bits · %vhopppcc cccccccc bit 15 bit 0 v h o p p p c c c c c c c c c c v / h flip mirror the tile vertically / horizontally priority promote this tile above other layers (Module 06) palette 0–7 which 16-colour sub-palette row (Module 02) this tile uses character number 0–1023 which 8×8 tile to draw, 10 bits = 1,024 choices
Anatomy of a map entry. Sixteen bits, five jobs: a 10-bit character number picks one of 1,024 tiles, three palette bits pick a sub-palette row, one priority bit can lift the tile above other layers, and the v/h bits flip it. One tile, four orientations, eight colour schemes — for free.

Scrolling is where tiles earn their keep. To move the whole background, the SNES doesn't shuffle pixels — it just changes two numbers: the background's horizontal and vertical scroll offsets (BGnHOFS / BGnVOFS). The PPU adds those offsets when it decides which tile and pixel to fetch, and the map wraps around at its edge, so a small map can scroll forever. Increment the offset each frame and the world glides past.

Analogy · A window over wallpaper

Picture a long roll of patterned wallpaper behind a wall with a small window cut in it. You never move the paper's pattern pixel by pixel — you just slide the whole roll left or right behind the window, and different parts show through. The scroll registers slide the roll; the window is your 256 × 224 screen.

Below, a 32 × 32 map built from four procedural tiles scrolls behind a viewport. Drag the scroll sliders or hit auto-scroll and watch the wrap-around: the map is only 256 pixels wide, yet it never runs out.

Tilemap lab — scroll a backgroundCanvas · live
Key takeaways
  • A tilemap is a 32×32 grid of entries; each entry names a tile plus palette, priority and H/V flip.
  • One tile can be reused in four orientations and several palettes across the map.
  • Scrolling is just two registers per layer — the PPU offsets its fetches; nothing moves in memory.
  • Maps wrap around, so a 256-pixel map scrolls endlessly.
Module 05 · Part I

Sprites / OBJ

GoalMeet the moving objects — sprites — that float freely over the fixed backgrounds, and the tiny table that positions them.

Backgrounds are locked to their tile grid. But Mario, a fireball, a coin — these need to move to any pixel, independent of the grid. Those are sprites, which the SNES calls OBJ. A sprite is still made of tiles, but it isn't pinned to a tilemap cell: it carries its own (x, y) position and is composited on top of the backgrounds wherever you place it.

Everything the PPU needs to draw the sprites lives in a small dedicated memory called OAM. Per sprite it stores the X and Y position, the starting tile number, a palette selection, a priority (which lets a sprite sit in front of or behind particular backgrounds), and horizontal/vertical flip flags — the same attribute vocabulary as a tilemap entry, but now free-floating. Change a sprite's X in OAM and it slides across the screen without a single pixel being redrawn by hand.

one sprite in OAM · 4 bytes in the main table + 2 bits in the high table byte 0 · X position, low 8 bits byte 1 · Y position byte 2 · tile starting tile number byte 3 · attributes flip · priority · palette +2 bits high table bit A — ninth X bit (positions 0–511, so sprites can slide off either edge) bit B — size: is this sprite the frame's small or large size? 128 sprites × 4 bytes = 512 B · 128 sprites × 2 bits = 256 bits = 32 B · 512 + 32 = 544 B of OAM
Why OAM is 544 bytes. Each of the 128 sprites gets a tidy 4-byte record — X, Y, tile, attributes. But 8 bits of X only reach 255, and a 9th bit wouldn't fit, so the two overflow bits (X bit 8 and the size flag) live in a separate 32-byte high table: 512 + 32 = 544.
Analogy · Felt figures on a storyboard

Old TV animation used a painted background and separate felt or cel figures laid on top, nudged frame by frame. The background never changed; only the little figures moved. Sprites are those figures, and OAM is the director's list of where each one sits this frame.

In the lab, sprites bounce over a tiled background. Add more with the slider, and flip the priority so the OBJ layer ducks behind the ground — a trick games use constantly for grass, doorways and water.

Sprite lab — composite OBJs over a backgroundCanvas · live
Key takeaways
  • Sprites (OBJ) are tile-built objects placed at any pixel, over the backgrounds.
  • OAM (544 bytes) holds each sprite's position, tile, palette, priority and flip.
  • Moving a sprite = editing a couple of OAM bytes; no pixels are pushed around.
  • Priority lets sprites weave in front of or behind chosen background layers.
Module 06 · Part I

Layers & priority

GoalStack multiple backgrounds and the sprite layer into one image, and understand transparency and priority ordering.

A SNES scene is several background layers plus the sprite layer, composited front-to-back into the final picture. Depending on the mode (Module 09) there can be up to four backgrounds — BG1, BG2, BG3, BG4 — and each can scroll independently. Parallax skies, foreground bushes, a HUD that stays put: all just separate layers moving at different speeds.

Two rules turn a stack of layers into a picture. First, transparency: in every layer, palette colour 0 is transparent, so lower layers show through wherever an upper layer's pixel is index 0. Second, priority: beyond the base layer order, individual tiles and sprites carry priority bits that can promote them above layers that would otherwise cover them. That's how a sprite can pass behind a pillar (low priority) and then in front of the floor (high priority) in the same scene.

One refinement worth getting right: the sprite layer isn't a single sheet that always sits on top. Each sprite carries a priority of 0–3, and those four levels are interleaved with the background priorities — a priority-0 sprite slips behind every background, and a middling one can hide behind BG1 while still covering BG2. In our pillar scene, the pillar is a BG1 tile with its priority bit set; the hero at OBJ priority 2 ducks behind it, while the floor is BG1 with priority clear, so the same hero walks in front of that. And one famous special case: in Mode 1 (Module 09), BG3 tiles with their priority bit set jump in front of everything, sprites included — that's how games kept HUDs and text boxes unbudgeable on top of the action.

the frame, exploded · colour 0 = a hole you see through BG3 — sky, far hills BG2 — mid hills · holes = colour 0 BG1 — ground · the pillar tile has its priority bit set OBJ — sprites, each at priority 0–3 levels interleave with the BG priorities: a priority-0 sprite hides behind every BG back → front: base order + per-tile / per-sprite priority bits
Stacked sheets with holes. Layers composite back to front; wherever a layer's pixel is colour 0, the sheet behind shows through. The final order is not fixed, though — per-tile priority bits and the four OBJ priority levels interleave, so a single sprite can sit behind the pillar yet in front of the floor of the very same layer.
Analogy · A pop-up book

A pop-up book is cut sheets standing at different depths: sky at the back, hills in the middle, characters up front, with holes where you see through to the layer behind. The SNES builds each frame the same way — stacked sheets with transparent gaps — except it can re-shuffle which sheet stands in front, tile by tile.

Toggle the four layers below and watch the composite rebuild. Turn off BG1 and the ground vanishes to reveal the hills behind; turn off the OBJ layer and the hero disappears. Colour 0 in each layer is the see-through ink that makes it all fit together.

Layer lab — toggle the stackCanvas · live
Key takeaways
  • A frame is several background layers plus sprites, composited front-to-back.
  • Colour index 0 in a layer is transparent — lower layers show through.
  • Priority decides who wins where layers overlap: base order, per-tile bits, and four OBJ levels interleaved with the BGs — Mode 1's promoted BG3 beats everything (the HUD trick).
  • Independent per-layer scrolling gives parallax and stationary HUDs.
Module 07 · Part I

Raster timing

GoalFollow the electron beam across a frame, understand H-blank and V-blank, and see why VRAM is only safely written during blanking.

The SNES doesn't compute a whole frame and then show it. It feeds a CRT, where a single electron beam sweeps left-to-right along one scanline, then snaps back and drops to the next line, top to bottom. The PPU produces the picture the same way — one scanline at a time, in lockstep with the beam. An NTSC frame is 262 scanlines of which 224 are visible, each line lasting 341 dot-clocks of which 256 are visible; the machine repeats it roughly 60 times a second.

Between the useful parts are two pauses. After each visible line the beam races back to the left — the horizontal blank (H-blank). After the last visible line the beam returns to the top — the longer vertical blank (V-blank): on NTSC that's lines 224–261, about 38 lines ≈ 2.4 ms of every 16.7 ms frame. These gaps matter enormously, because the PPU is reading VRAM the entire time it's drawing. If the CPU writes VRAM mid-line, the PPU owns the memory and the write is simply lost, or lands at the wrong address — your data never arrives, or corrupts a spot you didn't aim at. So the rule, burned into every SNES programmer's brain, is: touch VRAM, CGRAM and OAM only during blanking — mostly the roomy V-blank. (There is one escape hatch: forced blank, a register bit that turns the display off entirely, making every moment safe — it's how the very first screenful of graphics gets loaded behind a black screen.)

Analogy · Repainting a stage between scenes

A theatre crew can't repaint the set while the actors are performing under the lights — they wait for the blackout between scenes. V-blank is that blackout: the one moment the “stage” (VRAM) is dark and the crew (the CPU) can rush in and change things before the lights come back up for the next frame.

the whole NTSC frame · 341 dots × 262 lines · shaded areas = safe write windows active display 256 × 224 visible pixels PPU is reading VRAM — CPU writes lost / misplaced H-blank dots 256–340 ≈85 dots, every line room for a few writes (HDMA lives here — M13) V-blank · lines 224–261 38 lines ≈ 2.4 ms per frame — the big window for bulk VRAM/CGRAM/OAM updates (M14) still blank dot 0 256 340 line 0 224 261 ← the beam sweeps each line left to right, then rests in H-blank this one map anchors Modules 13 (HDMA fires per H-blank), 14 (V-blank budget) and 15 (what emulators must time)
The frame at a glance. Only the cyan-bordered 256 × 224 region ever reaches the glass. Everything else is blanking: an ≈85-dot H-blank tail on every one of the 262 lines, and a 38-line V-blank band at the bottom. The shaded regions are the only times video memory may safely be written — remember this map, because Modules 13, 14 and 15 all live on it.

The lab runs a beam across a full raster. The shaded right margin and bottom band are H-blank and V-blank; the readout tells you, at every moment, whether it's safe to write video memory. Slow it down to watch a single line being painted dot by dot.

Beam lab — watch a frame get drawnCanvas · live
H-blank / V-blank (safe to write) beam position
Key takeaways
  • The picture is produced scanline by scanline, in step with a CRT's electron beam.
  • H-blank follows each line; V-blank follows the frame — the gaps between drawing.
  • The PPU reads VRAM while drawing, so the CPU must write VRAM/CGRAM/OAM only during blanking.
  • V-blank is the main window for bulk video-memory updates — and at 38 lines (≈2.4 ms) per NTSC frame, it's short.
  • Forced blank ($2100 bit 7) switches the display off and makes writes safe any time — how the first screenful ever loads.
Part II

The SNES PPU

Now we open the box. The Super Nintendo's graphics are produced by two chips working as one — the S-PPU1 and S-PPU2 — reading from three small memories on a strict per-scanline schedule. In this part we map the pipeline, walk the eight background modes, unpack Mode 7's rotating floor, hit the real sprite limits, blend the main and sub screens with colour math, and abuse HDMA to change registers mid-frame. Everything from Part I is about to become a register.

Modules 08–14Focus Real hardwareLabs 6 interactive
Module 08 · Part II

The two PPUs & the pipeline

GoalMeet the S-PPU1/S-PPU2 pair, the three memories they own, and the per-scanline pipeline that turns tiles into a line of colour.

The SNES splits picture generation across two chips. The S-PPU1 is the renderer: it contains the background and OBJ engines, fetching tiles from VRAM and evaluating OAM to decide which sprites appear on each scanline. The S-PPU2 is the finisher: it applies windows and colour math, looks the winning pixel up in CGRAM, and drives the final video output. They pass pixel data between them every dot; to a programmer they behave like one unit addressed through a bank of registers at $2100–$213F.

A word on what those “registers” physically are, because every module from here on names them. $2100–$213F are memory-mapped I/O: addresses that are wired straight to the PPU chips rather than to any RAM. When the CPU writes to $2105, no memory cell changes — the value lands on the PPU's control lines and the chip changes behaviour, instantly. A register write is a command, not a stored byte. That's why when you write one (this dot, this line, this frame) matters as much as what you write.

Between them the pair owns three dedicated memories, and their sizes are worth memorising because every later module bumps into them: VRAM 64 KB (tiles and tilemaps), CGRAM 512 B (the 256-colour palette), and OAM 544 B (the 128 sprites' attributes). None is large. Fitting a game's graphics into 64 KB of VRAM, streamed in during those short blanking windows, was the central art of SNES development.

VRAM
64 KB
tiles + tilemaps
CGRAM
512 B
256 × 15-bit colour
OAM
544 B
128 sprites
Registers
$2100
…through $213F
one scanline, left to right through the pipeline VRAM OAM CGRAM S-PPU1 BG + OBJ engines tile fetch · OAM eval S-PPU2 windows · colour math CGRAM lookup · output colours → S-PPU2 final pixel → beam CRT scanline 256 × 224 the pair reads the three memories and emits one pixel per dot, 256 dots per visible line, 224 lines per frame
Two chips, one pipeline. S-PPU1 does the rendering: its BG and OBJ engines fetch tiles from VRAM and evaluate OAM each scanline. S-PPU2 does the finishing: windows, colour math, the CGRAM colour lookup, and the final video output — one pixel handed to the beam per dot, line by line.

Because the pipeline runs per dot with no frame buffer of finished pixels to fall back on, everything that changes the picture must be timed against the beam. That single fact powers Modules 10, 12 and 13 — and makes accurate emulation (Part III) genuinely hard.

Key takeaways
  • Two chips: S-PPU1 (the BG and OBJ rendering engines, VRAM/OAM fetch) and S-PPU2 (windows, colour math, CGRAM lookup, video output).
  • Three small memories: VRAM 64 KB, CGRAM 512 B, OAM 544 B.
  • Programmed through registers $2100–$213F; they behave as one unit.
  • The pipeline emits one pixel per dot with no finished-frame buffer — timing is everything.
Module 09 · Part II

The background modes

GoalLearn the eight background modes (0–7) and the trade they all make: more layers, or richer colour, but never both.

The PPU's background engine — it lives in S-PPU1, and register $2105 drives it — offers eight background modes, numbered 0–7. A mode decides how many BG layers you get and how deep each one's colour is. There is no free lunch: bits spent on more colours are bits not spent on more layers.

Mode 0 gives the most layers — four BGs, but each only 2bpp (4 colours). Mode 1 is the workhorse the vast majority of games use: BG1 and BG2 at 4bpp (16 colours) plus a 2bpp BG3, a great balance of colour and layer count — and BG3 tiles with their priority bit set jump in front of everything, which is why Mode 1's “spare” layer so often carries the HUD (Module 06). Mode 3 trades layers for a single 8bpp (256-colour) BG1. Modes 5 and 6 switch to true 512-pixel hi-res — the PPU genuinely fetches and outputs double the horizontal detail. (Don't confuse that with pseudo-hi-res, a separate $2133 trick that interleaves the main and sub screens in any mode.) True hi-res stayed rare: fetching twice the pixels eats twice the VRAM bandwidth, and on a blurry consumer CRT the extra columns mostly smeared away. Modes 2, 4 and 6 add offset-per-tile, letting columns scroll independently. And Mode 7 is a special case entirely — one layer you can rotate and scale — so it gets its own module next.

ModeLayersDepthsNotable for
0BG1–42·2·2·2 bppMost layers, 4 colours each
1BG1–34·4·2 bppThe workhorse — most games
2BG1–24·4 bppOffset-per-tile
3BG1–28·4 bpp256-colour BG1
4BG1–28·2 bpp256-colour + offset-per-tile
5BG1–24·2 bpp512-wide hi-res
6BG14 bppHi-res + offset-per-tile
7BG18 bppRotation / scaling (Module 10)
Analogy · A fixed art budget

Imagine a fixed jar of coins to split between “number of layers” and “colours per layer.” Mode 0 buys four thin layers; Mode 3 blows most of the jar on one gorgeous layer. Choosing a mode is choosing how to spend the jar for this screen — and games switch modes between screens, or even mid-frame, to spend it differently.

Pick a mode below to see its layer line-up and colour budget. The bar width hints at each layer's colour count; OBJ (always 4bpp, 16 colours per palette) rides on top in every mode.

Mode lab — layers & colour per modeLive
Key takeaways
  • Eight modes (0–7) trade layer count against colour depth; register $2105 selects one.
  • Mode 0 = four 2bpp layers; Mode 1 (4/4/2 bpp) is the everyday choice; Mode 3 = one 8bpp layer.
  • Modes 5/6 are true 512-wide hi-res (pseudo-hi-res is a separate $2133 trick); modes 2/4/6 add offset-per-tile.
  • Mode 7 is the odd one out — a single rotatable/scalable layer.
Module 10 · Part II

Mode 7

GoalUnderstand the single rotatable/scalable layer: its 2×2 affine matrix, its fixed-point registers, and the HDMA trick that fakes 3D perspective.

Mode 7 is the effect that defined the SNES. It gives up every other background to grant one layer a superpower: the hardware can rotate and scale it per pixel. That's the spinning racetrack of F-Zero, the tilting world map of Super Mario World, the swooping intro of countless games.

The magic is an affine transform. For every screen pixel, the PPU asks “which pixel of my map lands here?” and answers with a tiny matrix multiply. Don't let the word scare you: multiplying a coordinate pair by a 2×2 matrix just means applying one fixed scale-and-rotate recipe — map x = A·x + B·y, map y = C·x + D·y — to every pixel's coordinates. The four numbers live in registers $211B$211E — call them A, B, C, D — stored as 1.7.8 fixed-point (a signed value times 1/256), and a centre pivot (X0, Y0) lives in $211F/$2120 (M7X/M7Y).

Mind the direction, because it trips everyone up: the matrix maps screen → map, not the other way round. For each screen dot it computes where to sample the map — so bigger matrix values stride across the map faster, which zooms out. To magnify, you make the values smaller: a rotation by θ at a given zoom is A=cos·θ ÷ zoom, B=−sin·θ ÷ zoom, C=sin·θ ÷ zoom, D=cos·θ ÷ zoom. A worked fixed-point example: at θ = 0° and zoom 1×, A is exactly 1.0, which in 1.7.8 form (1 sign bit, 7 integer bits, 8 fraction bits) is 1 × 256 = 256 = $0100 — the value games write for “no zoom”. Housekeeping details: each Mode 7 register is fed its 16 bits as two 8-bit writes, low byte then high; the map is 128×128 tiles of 8×8 pixels = 1024×1024 px, and its tiles are stored linear, one byte per pixel — not planar like Module 03's; and when the sampling point runs off the map's edge, $211A decides the screen-over behaviour — wrap around, go transparent, or fill with tile 0. That's the whole trick: four numbers, updated once per frame, spin an entire world.

Analogy · A photo on a lazy-Susan

Lay a big printed map on a turntable and look down at a fixed window cut in a card above it. Spin the turntable and the map rotates under your window; slide it closer and it magnifies. Mode 7's matrix is the turntable's angle and zoom — and because it recomputes per pixel, the window can look at the map from any angle without ever redrawing it.

screen → map · the matrix answers “where do I sample?” for every dot screen pixels (x, y) — a straight grid × matrix A B C D $211B–$211E · 1.7.8 the same grid, rotated + scaled, laid over the 1024×1024 map bigger A/D = sample points stride farther apart = more map per screen = zoom OUT to magnify, write smaller values (A = cos ÷ zoom)
The multiply runs screen → map. The PPU walks the straight screen grid and, for each dot, uses A/B/C/D to compute a sampling point on the map. Larger matrix values make those sampling points stride across the map faster — more map squeezed onto the screen, i.e. zoom out. Magnification means writing values smaller than $0100.

Now the famous part. Rotation and scaling alone give a flat, top-down spin. To get the F-Zero floor receding to a horizon, games rewrite the matrix on every scanline using HDMA (Module 13): lines near the bottom use a larger scale (close), lines near the top a smaller one (far). The flat map bends into a perspective plane — a 3D illusion from a strictly 2D chip. Flip the perspective toggle in the lab to see it snap into place.

Mode 7 lab — spin the matrixCanvas · live
Key takeaways
  • Mode 7 is one background the PPU can rotate and scale per pixel via a 2×2 affine matrix.
  • Matrix A/B/C/D live at $211B–$211E as 1.7.8 fixed-point (each fed as two writes, low byte then high); the centre pivot M7X/M7Y is at $211F/$2120.
  • The matrix maps screen → map, so bigger values zoom out; magnifying means writing values below $0100 (A = cos ÷ zoom).
  • The map is 128×128 tiles (1024×1024 px), stored linear at 1 byte/pixel — not planar; $211A picks the off-map behaviour (wrap, transparent, or tile 0).
  • Rewriting the matrix per scanline with HDMA fakes perspective — the racing-floor effect.
Module 11 · Part II

Sprites on hardware

GoalMeet the real OBJ limits: 128 sprites total, two sizes per frame, and the brutal 32-sprites / 34-tiles-per-scanline ceiling.

Module 05 introduced sprites conceptually; here are the hardware numbers. The SNES can track 128 sprites at once in OAM. Each frame you pick two sizes from the size table (say 8 × 8 and 16 × 16, or 16 × 16 and 32 × 32) via register OBSEL ($2101), and each sprite is flagged as the small or large one. Sprites are always 4bpp — sixteen colours — and always draw from the top half of the palette, CGRAM entries 128–255 (the eight OBJ sub-palettes from Module 02). So far so generous.

The catch is per-scanline. As the beam draws each line, the S-PPU1 has only so much time to fetch sprite data, and the limits are hard: at most 32 sprites may appear on any one scanline, and at most 34 tiles' worth (8 × 8 slices) of sprite pixels can be fetched for it. Exceed the sprite count and the PPU raises the range-over flag and drops the extras; exceed the tile budget and the time-over flag fires and sprites lose slices. The visible result is the classic SNES flicker — sprites winking out when too many crowd one line. Why two limits? They guard two different resources: the 32 is evaluation slots (how many OAM entries the PPU can even consider for a line), the 34 is fetch slivers (how many 8-pixel slices of tile data it has time to read from VRAM). Bigger sprites burn slivers faster — a 32-pixel-wide sprite costs 4 slivers per line, so just eight of them side by side exhaust the sliver budget while using only a quarter of the evaluation slots.

one scanline meets a pile of 16×16 sprites (2 slivers each) 1 7 14 18th the beam's current line — every sprite it crosses needs its slivers fetched sliver budget · 34 fetches of 8 px per line 17 sprites × 2 slivers = 34 — the bar is exactly full the 18th sprite's slivers don't fit → its slices vanish on this line time-over flag set ($213E bit 7) — sliver budget blown range-over ($213E bit 6) fires at the other wall: >32 sprites
Two walls, one line. Here eighteen 16×16 sprites share a scanline. Eighteen is well under the 32-sprite evaluation limit — but at 2 slivers each they'd need 36 of the 34 fetch slots, so the 18th sprite is cut and the time-over flag fires. Wider sprites hit this wall even sooner: 32-wide sprites cost 4 slivers each.
Analogy · A narrow doorway

You can invite 128 guests to the party (OAM), but only 32 fit through the doorway at once (per scanline). Send more and the ones at the back get turned away this trip. Games manage the crowd by cycling which sprites get priority each frame — that's why old flicker shimmers rather than simply vanishing.

The lab piles sprites onto the screen and enforces the real limits line by line. Dropped sprites are shown faint so you can see exactly where the beam ran out of budget. Hit “pile on one line” to force the ceiling.

OBJ limit lab — 32 per scanlineCanvas · live
drawn dropped (over limit)
Key takeaways
  • 128 sprites total in OAM; two selectable sizes per frame (OBSEL $2101); always 4bpp, from CGRAM entries 128–255.
  • Per scanline: 32 evaluation slots and 34 fetch slivers — wider sprites eat slivers faster (a 32-wide sprite is 4 per line).
  • Over the limit raises range-over / time-over flags and drops sprites — visible as flicker.
  • Games rotate sprite priority each frame to spread the flicker out.
Module 12 · Part II

Colour math

GoalBlend two versions of the screen — main and sub — to get transparency, glows, spotlights and fades the SNES couldn't otherwise draw.

The SNES has no per-pixel alpha channel. It gets translucency a cleverer way: it composes the scene twice. Layers are each assigned to the main screen or the sub screen, producing two pictures, and then colour math combines them pixel by pixel. The assignment is just two bitmask registers: $212C enables layers on the main screen, $212D on the sub screen. Concretely, a game wanting a translucent waterfall sets the bits so BG1 (the level) and OBJ (the hero) land on the main screen while BG2 (the waterfall) goes to the sub screen — then asks for add-half wherever the waterfall's pixels are.

The operation is simple arithmetic per channel: add (main + sub, clamped to 31) or subtract (main − sub, clamped to 0), each with an optional half that divides the result by two. Two registers steer it all: CGWSEL ($2130) decides where math may happen, and CGADSUB ($2131) picks add/subtract, the half option, and which layers join in. Add-half of a bright layer over the scene gives a soft glow; subtract darkens for shadow; a plain add of a coloured pane makes stained glass. When there's no sub-screen layer behind a pixel, a fixed colour stands in — perfect for fading the whole frame to black or white. And windows can restrict where the math happens, carving spotlights and iris wipes.

One concrete blend, worked in numbers. A brick-red wall pixel on the main screen is (R,G,B) = (20, 10, 8); a pane of blue glass on the sub screen is (6, 14, 28). Choose add-half and the S-PPU2 computes each channel as (main + sub) ÷ 2: R = (20+6)/2 = 13, G = (10+14)/2 = 12, B = (8+28)/2 = 18 — a dusty blue-grey (13, 12, 18), exactly what bricks seen through 50% blue glass should look like. Dial those same six numbers into the lab below and watch the result swatch agree.

the pixel pipeline of Module 12 · two screens in, one colour out layers BG1 · BG2 · BG3 BG4 · OBJ backdrop every layer is flagged main, sub, or both MAIN screen $212C picks layers SUB screen $212D picks layers CGWSEL $2130 where may math apply? fixed colour or sub screen? CGADSUB $2131 add or subtract? half? which layers join in? + / − (÷2) fixed colour $2132 stands in when sub is empty windows $2123–$212B carve rectangles where math is switched off/on final pixel → the beam
Follow one pixel. Every layer is dealt onto the main screen ($212C), the sub screen ($212D), or both. CGWSEL ($2130) decides where math is allowed and whether the second operand is the sub screen or the fixed colour; CGADSUB ($2131) picks add/subtract/half and which layers participate; windows can veto regions entirely. One arithmetic node, endless SNES atmosphere.
Analogy · Two projectors on one screen

Shine two slide projectors at the same screen. Where both land, the light adds and you get a brighter blend; dim one and the mix shifts. Colour math is that second projector — the sub screen — and the “add / subtract / half” knobs decide how the two images combine.

Mix a main and a sub colour below, choose an operation, and read the resulting 15-bit word. This is precisely the per-channel maths the S-PPU2 runs for every pixel where colour math is enabled.

Colour-math lab — main + sub → resultLive
Main screen
op
Sub screen
=
Result
Key takeaways
  • No alpha channel — the SNES composes a main screen ($212C) and a sub screen ($212D) and blends them.
  • Colour math adds or subtracts per channel, optionally halved, clamped to 0–31 — steered by CGWSEL ($2130) and CGADSUB ($2131).
  • A fixed colour substitutes for the sub screen where no sub layer exists — used for full-frame fades.
  • Windows restrict where the math applies, giving spotlights and shaped transitions.
Module 13 · Part II

HDMA raster tricks

GoalChange PPU registers on individual scanlines — automatically — to paint gradients, ripples, mosaics and perspective floors.

A PPU register normally holds one value for the whole frame. But the beam draws the frame one line at a time, and between lines there's an H-blank. What if a register held a different value on every line? HDMA — horizontal-blank DMA — does exactly that. You hand it a small table, and the hardware feeds one entry to a chosen register during each line's H-blank, all frame, with the CPU free to do other work.

That one capability is behind a startling number of SNES effects. Feed the backdrop colour register a new value each line and you get a smooth sky gradient from a machine with no gradient hardware. Feed a BG scroll register a wobbling offset and flat water ripples. Step the mosaic register and the screen pixelates from top to bottom for a dissolve. And, as we saw, feed the Mode 7 matrix a new scale each line and a flat plane bends into a 3D floor. HDMA is how the SNES turned strict per-scanline timing from a constraint into a paintbrush.

Analogy · A player piano roll

A player piano reads a punched roll: at each moment the roll tells the keys what to do, no pianist needed. An HDMA table is that roll, and the “moment” is each scanline's H-blank. You punch the pattern once; the hardware plays it down the whole frame, line after line.

the piano roll · one table entry fires per H-blank, all the way down the frame HDMA table (in work RAM) line 0 · $1D40 line 1 · $1D61 line 2 · $1D82 line 3 · $1DA3 ⋮ one entry per line ⋮ line 223 · $7FFF H-blank the frame, drawn line by line each arrow = the hardware writing one table value to a PPU register, during that line's H-blank, no CPU involved
A punched roll for registers. The HDMA channel walks its table one entry per scanline, delivering each value to the chosen register during that line's H-blank — here a rising backdrop colour becomes a smooth gradient. Punch the roll once; the hardware plays it every frame.

The studio below applies a per-scanline effect to a canvas. Switch between a gradient backdrop, a per-line scroll ripple and a growing mosaic — each is one register being rewritten ~200 times a frame, exactly as HDMA would.

HDMA lab — one register, per lineCanvas · live
Key takeaways
  • HDMA writes a table of values to PPU registers, one entry per scanline, during H-blank.
  • Per-line backdrop colour → gradients; per-line scroll → ripples; per-line mosaic → dissolves.
  • Per-line Mode 7 matrix → the perspective racing floor.
  • It runs autonomously, freeing the CPU — the SNES's signature source of “how did they do that?”.
Module 14 · Part II

VRAM, CGRAM, OAM & the port bottleneck

GoalSee how the CPU reaches the PPU's private memories through a handful of I/O ports — and why the blanking-only rule makes DMA essential.

The three PPU memories aren't on the CPU's address bus — the CPU can't just write VRAM location 5,000 directly. It goes through ports: special registers you poke in sequence. (Two units first, since we'll count in both: a byte is 8 bits, and a word here means 16 bits — two bytes. VRAM is organised as 32,768 words.) To fill VRAM you first set the word address with $2116/$2117 (low/high byte), choose how the address should auto-increment (by 1, 32, or 128 words, via $2115, which can also remap the address bits for bitmap-style uploads), then stream data through $2118/$2119. Those are one-byte ports: $2118 carries a word's low byte and $2119 its high byte, so a pair of writes delivers one 16-bit word — and bit 7 of $2115 selects which of the two ports' writes actually bumps the address pointer. CGRAM has its own pair ($2121 address, $2122 data — Module 02); OAM uses $2102–$2104.

Here's the squeeze. Writing through a port is one value at a time, and (Module 07) you may only do it during blanking. An NTSC V-blank is 37–38 lines — roughly 6,300–8,600 CPU cycles depending on speed — which sounds roomy until you price it out: it's enough to push only about 6 KB into VRAM per frame, and far less if the CPU hand-writes each byte in a loop. The answer is DMA: a hardware block-copier that streams bytes to the data port at bus speed. On the SNES, DMA into VRAM during V-blank isn't a luxury — it's the only way to get graphics in on time; a full 64 KB VRAM still takes a dozen frames of V-blanks. (Its per-scanline cousin HDMA powered Module 13. And when a game can afford a black screen — a loading moment, a scene change — it flips on forced blank, $2100 bit 7, and loads everything at leisure with the display off.)

the only road into VRAM · address, mode, then data — one byte per knock CPU (or DMA unit) $2116/$2117 — set word address low byte, high byte $2115 — increment mode +1 / +32 / +128 · which port bumps · remap $2118/$2119 — data, one byte each a pair of writes = one 16-bit word VRAM · 32,768 words pointer auto-steps after each word one V-blank's budget vs one tileset ≈6 KB / V-blank via DMA a 32 KB 4bpp tileset = ~6 frames of V-blanks forced blank ($2100 bit 7) opens the whole frame: screen goes black, budget goes unlimited — how title screens load
Plumbing with a meter on it. Address in at $2116/7, behaviour set at $2115, bytes knocked in one at a time through $2118/9 while the pointer auto-steps. The bar underneath is the real constraint: one V-blank's worth of DMA moves only ~6 KB, so streaming a big tileset is a multi-frame project — unless you switch the display off entirely.

The simulator below is the VRAM port in miniature. Set the address, pick an increment, then write bytes or auto-fill a burst and watch the pointer march through VRAM. Change the increment to 32 and see the writes stride down a column instead of along a row — exactly how you'd load a tall strip of tiles.

VRAM-port lab — stream data through $2118/9Canvas · live
$2116/7 addr
$0000
$2115 increment
+1
words written
0
showing the first 1,024 of 32,768 VRAM words · the cyan box is the current write pointer
Key takeaways
  • The CPU reaches VRAM/CGRAM/OAM only through I/O ports, not directly.
  • VRAM: set $2116/7 address, choose increment on $2115, stream data via the one-byte ports $2118/9 — a pair of writes per 16-bit word, $2115 bit 7 picking which port bumps the pointer.
  • CGRAM uses $2121/$2122; OAM uses $2102–$2104.
  • Blanking-only writes plus a ~6 KB-per-V-blank ceiling make DMA the essential way to load graphics; forced blank ($2100 bit 7) lifts the ceiling by switching the display off.
Part III

Emulating in bsnes

You now know how a real SNES makes a picture. This final part asks the reverse question: how do you rebuild that behaviour in software, faithfully? The answer turns on a single decision — how finely you simulate the beam — and it's the fault line between an emulator that runs almost everything and one that also nails the last few CPU-timed, mid-scanline stunts. Then we point you at the debug tools that let you watch a live PPU think.

Modules 15–16Tools bsnes · Mesen2Lab 1 interactive
Module 15 · Part III

Per-scanline vs per-dot

GoalUnderstand what per-scanline emulation already gets right (all of HDMA), and which effects — CPU-timed mid-display writes — genuinely demand per-dot rendering.

An emulator has to decide how often to re-check the PPU's registers. Per-scanline rendering reads the registers once per line and draws all 256 dots with those values. Here's the part people get wrong: that is enough for HDMA. Module 13's writes land in H-blank, between lines — so a per-scanline renderer that applies HDMA at each line boundary reproduces gradients, ripples and Mode 7 perspective floors perfectly. That's exactly why the fast approach works for the overwhelming majority of games.

What it can't see is a register change landing in the middle of the visible line — a CPU-timed mid-display write. The canonical example is Air Strike Patrol, which redraws its runway shadow by poking the PPU partway across specific scanlines: a per-scanline renderer already committed those lines, so the shadow simply vanishes. Add a handful of fine latching quirks (exactly which dot a scroll or window value is sampled at) and you have the genuine case for per-dot rendering: advance the PPU one pixel-clock at a time, applying every write at the precise dot it occurred. The cost is speed — many more checks per frame. The landscape today: bsnes defaults to a fast scanline PPU, with per-dot cycle rendering as higan / bsnes's accuracy option, while Mesen2 renders per-dot outright.

one scanline, dot 0 → 340 · where writes land, and who sees them active display · dots 0–255 H-blank · dots 256–340 dot 0 256 340 HDMA write → lands here, BETWEEN lines CPU write at dot ~140 (Air Strike Patrol) per-scanline renderer samples registers… once, at the start of the line → sees every H-blank/HDMA change · misses the dot-140 write per-dot renderer samples… every dot → catches the mid-display write at exactly dot 140 — at many times the cost
The whole Module 15 argument in one line. HDMA fires in H-blank, so a renderer that re-reads registers at each line boundary gets every Module 13 effect right. Only a write landing inside the visible line — the magenta arrow — distinguishes the two strategies, and that's precisely what per-dot rendering exists for.
Analogy · Reading a sign from a moving train

Glance once as your carriage passes a sign and you catch a single word; read it continuously and you get the whole message. Per-scanline emulation glances once per line; per-dot reads the sign the whole way past. If the sign only changes between carriages (HDMA in H-blank), one glance per carriage is plenty — but for a sign repainted mid-carriage, a CPU write in mid-display, only the continuous reader gets it right.

Both panels below run the same raster stunt: a CPU hammering a colour register repeatedly during each visible line (this is deliberately not HDMA — HDMA would look identical in both panels). The per-dot panel applies every write at the exact dot it lands, revealing slanted bands the writes paint across the frame. The per-scanline panel only samples the register once at each line's start, so the mid-line detail collapses into a single wavy edge. That residue is the whole argument for per-dot accuracy.

Accuracy lab — the same effect, two renderersCanvas · live
per-dot (accurate)
per-scanline (fast)
Key takeaways
  • Per-scanline rendering reads registers once per line; per-dot reads them every pixel.
  • HDMA lands in H-blank, between lines — per-scanline rendering reproduces it correctly; only CPU-timed mid-display writes (Air Strike Patrol's runway shadow) and fine latching quirks need per-dot.
  • Modern bsnes defaults to a fast scanline PPU; per-dot cycle rendering is higan / bsnes's accuracy option, and Mesen2 renders per-dot.
  • The trade is accuracy versus speed — and it's only visible the moment a game changes a register mid-line.
Module 16 · Part III

Accuracy & try it

GoalTurn the whole course into a hands-on habit: open a real PPU debugger and watch every concept you've learned, live.

The best way to make all of this permanent is to watch a real game's PPU state while it runs. Modern accuracy-focused emulators ship debuggers that expose exactly the structures this course built up. In Mesen2 or bsnes-plus, open the PPU tools and you'll find one window per module:

  • Tile / VRAM viewer — the raw 8×8 tiles from Modules 03–04, decoded from bitplanes at the bit depth you choose.
  • Tilemap viewer — the 32×32 maps of Module 04, with the scroll registers and per-tile flip/priority laid bare.
  • CGRAM / palette viewer — the 256 entries of Module 02, updating live as the game fades and cycles colours.
  • OAM / sprite viewer — the 128 sprites of Modules 05 and 11, with their sizes and the per-scanline count that triggers flicker.
  • Event / timing viewer — the beam of Module 07 and the HDMA writes of Module 13, plotted against the scanline where they land.
Analogy · An X-ray of a magician

You've learned every trick in the act; the debugger is the X-ray that shows the hands doing them. Load a Mode 7 game and scrub a frame: you'll see the matrix registers change line by line (Module 10 + 13), the palette shift for a fade (Module 12), and sprites drop off a crowded scanline (Module 11) — all the theory, caught in the act.

Two great closing experiments. First, open Mesen2's event viewer on a Mode 7 racer and pause a frame: you'll see the HDMA writes plotted as a neat column landing in the H-blank of every line — Module 13's piano roll and Module 15's timing argument, photographed in the wild. Second, if you can find Air Strike Patrol, run it in bsnes under the default fast PPU and then under the accuracy profile (or in per-dot Mesen2): the runway shadow — drawn by a CPU write in mid-scanline — vanishes in one and appears in the other. You're no longer watching a mystery; you're reading a pipeline you know stage by stage.

Getting the tools is easy: Mesen2 is at mesen.ca, and bsnes at github.com/bsnes-emu/bsnes, both free. For something to inspect, homebrew and hardware test ROMs (widely published by their authors, and by the emudev community) give you plenty of PPU activity to explore while steering well clear of any legal gray areas around commercial game copies.

Course complete ✦
  • You can follow a picture from an 8×8 bitplane tile, through palettes, layers and colour math, to a scanline on a CRT — the whole SNES PPU.
  • You know the numbers that shaped every SNES game: 256×224, 15-bit BGR, 8 modes, Mode 7's matrix, 128 sprites / 32-per-line, VRAM 64 KB.
  • You can read a PPU debugger as a live map of the S-PPU1/S-PPU2 — and know exactly which effects demand per-dot emulation.
  • Come full circle: the little framebuffer you painted in Module 01 is exactly what the beam is still drawing, one dot at a time.

An interactive course on the Super Nintendo's picture-processing units, companion to the other Inside the Super Nintendo teardowns. Every picture on this page is drawn procedurally in your browser — the labs are little software PPUs implementing the very algorithms they teach. This page contains no game artwork. Hardware details are grounded in public documentation and accuracy-focused emulator source; where exact figures vary by source, the text says so.

Source of truth · registers $2100–$213F · VRAM 64 KB · CGRAM 512 B · OAM 544 B · Mode 7 matrix $211B–$211E