Skip to Content

NES / Famicom

SpecValue
Resolution256×240 (NTSC) / 256×239 (PAL)
Total colors54 unique (64-entry LUT with duplicates)
Simultaneous25 (4 bg palettes × 4 + backdrop + 4 sprite palettes × 3)
Constraint16×16 attribute blocks
DisplayCRT composite
Year1983
MakerNintendo

Color palette

The NES PPU generates color via NTSC composite video — there is no single “correct” RGB palette. bitmapped uses a 2C02 PPU reference palette. The 64-entry lookup table is organized as 4 rows of 16, encoding brightness × hue:

2C02 PPU Reference Palette (64 entries)

The key constraint: 16×16 attribute blocks

The NES nametable uses attribute bytes that assign one of four background palettes to each 16×16 pixel region (a 2×2 group of 8×8 tiles). Every pixel within that block must use colors from the same 4-color palette.

This forces color boundaries to align to a coarse grid — it’s why NES games have that distinctive blocky color look, where you can often see rectangular regions of different color sets.

bitmapped’s attribute-block constraint solver divides the image into 16×16 blocks and selects the optimal 4-color subpalette for each block, minimizing color error.

Interactive demo

Original
NES (NTSC)

Code example

import { process } from 'bitmapped'; import { getPreset } from 'bitmapped/presets'; const nes = getPreset('nes-ntsc')!; const result = process(imageData, { blockSize: 4, palette: nes.palette!, dithering: 'floyd-steinberg', distanceAlgorithm: 'redmean', constraintType: 'attribute-block', attributeBlockConfig: { width: 16, height: 16, maxColors: 4, }, });

Presets

bitmapped includes two NES presets:

  • nes-ntsc — NTSC timing (256×240), 2C02 PPU palette
  • nes-pal — PAL timing (256×239), same palette

Hardware notes

The NES PPU (2C02) doesn’t store RGB values — it generates NTSC composite video directly from a 6-bit color index (2 bits value × 4 bits hue). The signal is decoded by the TV’s NTSC decoder, which is why every CRT displays NES games slightly differently.

Color $0D generates a “blacker than black” signal that can damage some CRT monitors. It should always be mapped to pure black.

The PPU supports emphasis bits ($2001 bits 5-7) that tint the entire screen by dimming selected color channels ~20%. This is used in some games for fade effects.

The background palette is organized as 4 subpalettes of 4 colors each, with color 0 of all palettes sharing a single backdrop color. The attribute table assigns one of these four palettes to each 16×16 region.

Last updated on