NES Sprites

The NES has true hardware sprites, called objects. The PPU keeps a 256-byte block of object memory (OAM) that describes up to 64 sprites, and draws them over the background every frame with no CPU work. Each sprite is a four-byte entry that picks a tile from a pattern table and places it on screen with its own palette and flip flags.

NES Sprites

Overview

Sprites are 8×8 or 8×16 pixel tiles drawn by the PPU over the background. Object memory holds 64 of them at once, each defined by four bytes: a Y position, a tile index, an attribute byte and an X position. The graphics themselves live in the pattern tables in CHR memory; the OAM entry only points at a tile and says where and how to draw it. The sprite palettes at $3F10–$3F1F give the colours.

PropertyValue
Sprites64
Sprite size8 × 8 or 8 × 16 pixels
Bytes per sprite4
OAM size256 bytes
Colours per sprite3 plus transparent, from one of 4 sprite palettes
Per scanline8 (extras drop)

OAM and the sprite entry

Object memory is 256 bytes, four per sprite, so sprite n starts at OAM offset n × 4. The CPU can write it a byte at a time through two PPU registers, or, far faster, copy a whole 256-byte page in one go with sprite DMA. Writing the high byte of a RAM page to $4014 stalls the CPU and streams that page into OAM, which is how nearly all games refresh their sprites each frame.

ByteFieldMeaning
0YTop pixel row minus 1; the sprite is drawn one line below this value.
1Tile indexWhich pattern-table tile to use.
2AttributesPalette, priority and flip flags (see below).
3XLeft pixel column.
RegisterRole
$2003 (OAMADDR)Sets the OAM byte address to write next.
$2004 (OAMDATA)Writes one byte to OAM and advances the address.
$4014 (OAMDMA)Copies a 256-byte CPU page into OAM in one transfer.

The attribute byte

Byte 2 of each sprite packs the palette choice, the priority against the background and the two flip flags. Bits 2 to 4 are unused. The palette bits pick one of four sprite palettes, whose colours are read from $3F11–$3F1F; colour index 0 is always transparent so the background shows through.

Bit76543210
MeaningV flipH flipPriorityPalette (0–3)

V flip mirrors the tile top to bottom, H flip left to right. Priority 0 draws the sprite in front of the background, priority 1 draws it behind any non-transparent background pixel, which lets sprites pass behind foreground scenery.

Sprite sizes and patterns

All sprites share one size at a time, chosen by bit 5 of PPUCTRL ($2000): clear for 8×8, set for 8×16. In 8×8 mode a further bit of PPUCTRL (bit 3) picks which pattern table, $0000 or $1000, holds all sprite tiles, and the tile index selects the tile directly.

In 8×16 mode a sprite is two stacked tiles. The tile index byte then carries the pattern table in its lowest bit and the top tile number in the rest: the top tile is the even value and the bottom tile the next one up. This lets tall objects be built from tile pairs and ignores the PPUCTRL sprite pattern bit.

PPUCTRL bitNameEffect
5Sprite size0 = 8×8, 1 = 8×16.
3Sprite patternIn 8×8 mode, 0 = $0000, 1 = $1000.

Scanline limit and sprite 0

The PPU can only fetch eight sprites per scanline. If a ninth sprite would appear on a line the PPU drops it, so rows of many objects flicker as games rotate which sprites are hidden. The overflow is reported in bit 5 of PPUSTATUS ($2002), though the real hardware flag is unreliable.

Sprite 0 hit is a timing tool. When a non-transparent pixel of sprite 0 overlaps a non-transparent background pixel, the PPU sets bit 6 of PPUSTATUS. Games poll this flag to learn the exact scanline a known pixel is drawn, then change scroll or switch pattern tables mid-frame, the classic way to hold a status bar still while the playfield scrolls beneath it.

PPUSTATUS bitFlagMeaning
6Sprite 0 hitSet when sprite 0 overlaps the background.
5Sprite overflowSet when more than 8 sprites fall on a scanline.