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.
- Overview
- OAM and the sprite entry
- The attribute byte
- Sprite sizes and patterns
- Scanline limit and sprite 0
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.
| Property | Value |
|---|---|
| Sprites | 64 |
| Sprite size | 8 × 8 or 8 × 16 pixels |
| Bytes per sprite | 4 |
| OAM size | 256 bytes |
| Colours per sprite | 3 plus transparent, from one of 4 sprite palettes |
| Per scanline | 8 (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.
| Byte | Field | Meaning |
|---|---|---|
| 0 | Y | Top pixel row minus 1; the sprite is drawn one line below this value. |
| 1 | Tile index | Which pattern-table tile to use. |
| 2 | Attributes | Palette, priority and flip flags (see below). |
| 3 | X | Left pixel column. |
| Register | Role |
|---|---|
| $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.
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Meaning | V flip | H flip | Priority | — | — | — | Palette (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 bit | Name | Effect |
|---|---|---|
| 5 | Sprite size | 0 = 8×8, 1 = 8×16. |
| 3 | Sprite pattern | In 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 bit | Flag | Meaning |
|---|---|---|
| 6 | Sprite 0 hit | Set when sprite 0 overlaps the background. |
| 5 | Sprite overflow | Set when more than 8 sprites fall on a scanline. |