NES Images

The NES background is not a bitmap. It is a grid of 8×8 tiles chosen from a pattern table, arranged by a nametable, and coloured by an attribute table. A full screen is 32×30 tiles, and the picture changes by editing the small table of tile numbers rather than pixels. This is what makes NES scrolling and animation so cheap.

NES Images

Overview

The screen shows 256×240 pixels, laid out as 32×30 tiles of 8×8. Each tile’s shape comes from a pattern table and each tile’s position comes from a nametable entry, one byte per tile. Colour is set coarsely by an attribute table, one byte per 2×2 block of tiles. All of this lives in the PPU’s own address space, separate from the CPU’s RAM.

PropertyValue
Resolution256 × 240 pixels
Tiles32 × 30, each 8 × 8 pixels
Nametable size1024 bytes (960 tiles + 64 attribute)
Tile depth2 bits per pixel (4 colours)
Colour sourcePalette memory at $3F00

Nametables

A nametable is a 960-byte grid of 32×30 tile indices followed by a 64-byte attribute table, 1024 bytes in all. The PPU has room for four nametables at $2000–$2FFF, but the console only wires two physical 1KB pages; the other two are mirrors. A mirroring mode, fixed by the cartridge or set by its mapper, decides how the four logical nametables map onto the two real ones.

AddressNametable
$2000–$23FFNametable 0 (960 tiles + attributes)
$2400–$27FFNametable 1
$2800–$2BFFNametable 2
$2C00–$2FFFNametable 3

The tile at column cx, row cy is byte cy × 32 + cx of the nametable. That byte is an index into the background pattern table.

Pattern tables

Pattern tables hold the actual pixels. There are two, at $0000 and $1000 in PPU space, each 4KB and holding 256 tiles. A tile is 16 bytes storing 8×8 pixels at 2 bits per pixel, but the two bits are stored planar, not packed together. The first 8 bytes are the low bit of each pixel, one byte per row; the next 8 bytes are the high bit of each pixel. The PPU combines the two planes to make a 2-bit value 0 to 3 for each pixel.

BytePlaneMeaning
0–7Low bit-planeBit 0 of each pixel, one byte per row, MSB left.
8–15High bit-planeBit 1 of each pixel, one byte per row.

For a given pixel the low-plane bit and the high-plane bit combine into a value 0 to 3. Value 0 is the shared background colour; values 1 to 3 pick colours from the tile’s palette, chosen by the attribute table. Which pattern table supplies background tiles is set by bit 4 of PPUCTRL ($2000).

Attribute tables

The 64-byte attribute table at the end of each nametable colours the tiles. One attribute byte covers a 32×32 pixel region, a 4×4 block of tiles, and splits it into four 16×16 quadrants. Two bits of the byte give the palette number (0 to 3) for each quadrant, so a single byte sets the palette for four 2×2 tile groups.

Bits7–65–43–21–0
QuadrantBottom-rightBottom-leftTop-rightTop-left

Because colour is set per 16×16 pixels while shape is set per 8×8, background art is designed so that each 2×2 tile group shares one four-colour palette. This is the NES equivalent of the Spectrum’s attribute grid, only two bits deep and covering a larger block.

Palettes and scrolling

Palette memory sits at $3F00–$3F1F. The first 16 bytes are the four background palettes, the next 16 the four sprite palettes. Each palette is four entries, but the first entry of every background palette mirrors the universal background colour at $3F00, so each palette gives one shared colour plus three of its own. Each entry is an index into the fixed 64-colour system palette.

AddressContents
$3F00Universal background colour
$3F01–$3F0FFour background palettes (3 colours each)
$3F10–$3F1FFour sprite palettes

Scrolling is set by PPUSCROLL ($2005), written twice for the fine X and Y offset, together with two bits of PPUCTRL ($2000) that pick the base nametable. As the offset crosses a nametable edge the picture wraps into the neighbouring nametable, so a game keeps drawing fresh tile columns just off-screen to scroll smoothly through a large map.