Atari 2600
| Spec | Value |
|---|---|
| Resolution | 160x192 (NTSC) / 160x228 (PAL) |
| Total colors | 128 (NTSC) / 104 (PAL) |
| Simultaneous | 4 per scanline |
| Constraint | Scanline color limit |
| Display | CRT composite (NTSC/PAL) |
| Year | 1977 |
| Maker | Atari |
Color palette
The Atari 2600’s TIA chip uses a 7-bit color register to generate color via NTSC composite encoding. The register format is CCCC_LLL0 — 4 bits select one of 16 hues, 3 bits select one of 8 luminance levels, and bit 0 is unused. This gives 16 hues x 8 luminances = 128 unique colors in NTSC mode. The PAL version uses a different color encoding that produces only 104 colors (13 hues x 8 luminances).
Here are the first 8 hue rows (64 of 128 NTSC colors), showing the luminance ramp for each hue:
The full NTSC palette contains 128 colors across 16 hue rows. The remaining 8 hues continue through blues, teals, greens, and yellow-greens. The PAL palette is a subset with 13 hues (104 colors) due to the different color encoding standard.
The key constraint: scanline color limits
The TIA has no framebuffer — it renders one scanline at a time from a handful of hardware registers. Each scanline can display at most 4 colors: the background, the playfield, and two player/missile objects. There is no way to exceed this limit on a single line of pixels.
Games achieve more color variety by reprogramming the TIA’s color registers between scanlines, a technique called “racing the beam”. The CPU must update registers in the narrow window between the end of one scanline and the start of the next. This is why Atari 2600 games often feature horizontal bands of color — each row can have a completely different set of 4 colors, but within a row the limit is strict.
bitmapped’s per-scanline constraint solver enforces the 4-color-per-scanline limit, selecting the optimal set of colors for each row to minimize overall color error.
Interactive demo
Code example
import { process } from 'bitmapped';
import { getPreset } from 'bitmapped/presets';
const atari = getPreset('atari-2600-ntsc')!;
const result = process(imageData, {
blockSize: 4,
palette: atari.palette!,
dithering: 'bayer',
distanceAlgorithm: 'redmean',
constraintType: 'per-scanline',
scanlineConfig: {
maxColorsPerLine: 4,
},
});Presets
bitmapped includes two Atari 2600 presets:
atari-2600-ntsc— 128-color NTSC TIA palette (16 hues x 8 luminances), 160x192 resolutionatari-2600-pal— 104-color PAL TIA palette (13 hues x 8 luminances), 160x228 resolution
Hardware notes
The TIA (Television Interface Adapter) was designed by Jay Miner, who would later go on to design the Amiga’s custom chipsets. It is one of the most constrained graphics chips ever put into a home console.
No framebuffer. The TIA has no video RAM at all. The CPU must “race the beam” — updating the TIA’s registers in real time as the electron beam scans across the CRT. The entire system has only 128 bytes of RAM.
Asymmetric playfield. The playfield is 20 “pixels” wide (at 4x the player sprite resolution), stored in three registers (PF0, PF1, PF2). The right half of the screen can either mirror the left half or repeat it, allowing asymmetric layouts at the cost of CPU time to rewrite registers mid-scanline.
Player sprites. Each of the two player objects is only 8 pixels wide, stored in a single byte (GRP0, GRP1). They can be stretched to 2x or 4x width and duplicated or triplicated at fixed intervals across the scanline using the NUSIZ registers.
HMOVE artifacts. Repositioning sprites horizontally requires a hardware operation (HMOVE) that produces visible black lines at the left edge of the screen — a well-known visual artifact in many 2600 games.
Pixel aspect ratio. The TIA’s 160-pixel horizontal resolution uses wide pixels with a 2:1 pixel aspect ratio (PAR), so the actual display fills a standard 4:3 CRT.