Palette LUT — NTSC / PAL switching
What the LUT stores
Section titled “What the LUT stores”hdl/palette_lut.sv is a 256-entry × 24-bit RAM. The address is the
8-bit Atari hue:luma value coming out of color_resolver
(bits[7:4] = hue 0..15, bits[3:0] = luma 0..15). The data is straight
RGB888.
All sixteen luminances are distinct. A colour register has no bit 0 —
gtia_reg_file masks it on the write, where the hardware drops it — so
register colours only ever reach the eight even entries. GTIA mode 9 does
not go through a register: the screen nibble lands straight in the
luminance field, which is why that mode gives sixteen shades where the
registers give eight, and why the odd entries have to exist.
The TMDS / DVI scan-out path reads palette_lut[resolved_color] once
per pixel-clock and feeds the 24-bit result into the encoder.
Why two reference palettes
Section titled “Why two reference palettes”Atari’s NTSC and PAL hardware encode the colour-burst phase differently. The hue → carrier-phase mapping is rotated, the saturation is slightly different, and PAL’s alternating-line phase reversal kills the chroma-distortion issue NTSC has. Result: the same hue:luma byte produces visibly different colours on a real NTSC vs PAL Atari. Programs that target one region picked their hue values to look right under that region’s palette.
To stay colour-accurate, we need both reference palettes available.
Two ways to load
Section titled “Two ways to load”The LUT is fully writeable at runtime via the chiplet-ext registers:
$D483 PAL_R write red byte$D484 PAL_G write green byte$D485 PAL_B write blue byte$D486 PAL_IDX write 8-bit Atari index — commits {R,G,B} into entry IDXTwo delivery options for the boot defaults:
-
Synth-time bake-in. Pass
INIT_FILEtopalette_lut:palette_lut #(.INIT_FILE("hdl/palette/atari_ntsc.hex")) u_lut (...);Two reference tables ship in the repo:
hdl/palette/atari_ntsc.hex— NTSC-shaped colour wheelhdl/palette/atari_pal.hex— PAL-shaped colour wheel
Pick whichever matches the dominant target region. The other one ships in firmware as a 768-byte blob and gets paged in via the chiplet-ext writes when the user toggles region.
-
Pure firmware-driven. Leave
INIT_FILEempty (LUT comes up black at /G_RST), and have the PS-side boot firmware push 256 entries via writes to $D483-$D486 during the cold-boot sequence. Region toggle = re-push the other table (≈ 1 ms at 1.79 MHz bus).
We default to the synth-time bake-in since it gives a sensible power-on display before any firmware has run.
File format
Section titled “File format”atari_ntsc.hex / atari_pal.hex are plain $readmemh-compatible
hex files: 256 lines, one 24-bit RGB888 per line, MSB = R, LSB = B.
Header lines (//) are tolerated by $readmemh so the files are
self-documenting.
The two reference tables in this repo are derived approximations based on the NTSC and PAL hue-rotation tables widely quoted in the Atari hardware manuals + Altirra. They aren’t claimed to be pixel-exact reproductions of any specific real silicon’s analogue colour-burst output — the chiplet-ext write path lets you replace them with whatever your favourite reference says.