PPU palettes

From NESdev Wiki
Revision as of 21:57, 8 December 2015 by Lidnariq (talk | contribs) (→‎2C04: include what these two colors are duplicates of)
Jump to navigationJump to search

Memory Map

The palette for the background runs from VRAM $3F00 to $3F0F; the palette for the sprites runs from $3F10 to $3F1F. Each color takes up one byte.

Address Purpose
$3F00 Universal background color
$3F01-$3F03 Background palette 0
$3F05-$3F07 Background palette 1
$3F09-$3F0B Background palette 2
$3F0D-$3F0F Background palette 3
$3F11-$3F13 Sprite palette 0
$3F15-$3F17 Sprite palette 1
$3F19-$3F1B Sprite palette 2
$3F1D-$3F1F Sprite palette 3

Each palette has three colors. Each 16x16 pixel area of the background can use the backdrop color and the three colors from one of the four background palettes. The choice of palette for each 16x16 pixel area is controlled by bits in the attribute table at the end of each nametable. Each sprite can use the three colors from one of the sprite palettes. The choice of palette is in attribute 2 of each sprite (see PPU OAM).

Addresses $3F04/$3F08/$3F0C can contain unique data, though these values are not used by the PPU when normally rendering (since the pattern values that would otherwise select those cells select the backdrop color instead). They can still be shown using the background palette hack, explained below.

Addresses $3F10/$3F14/$3F18/$3F1C are mirrors of $3F00/$3F04/$3F08/$3F0C. Note that this goes for writing as well as reading. A symptom of not having implemented this correctly in an emulator is the sky being black in Super Mario Bros., which writes the backdrop color through $3F10.

Thus, indices into the palette are formed as follows:

43210
|||||
|||++- Pixel value from tile data
|++--- Palette number from attribute table or OAM
+----- Background/Sprite select

As in some second-generation game consoles, values in the NES palette are based on hue and brightness:

76543210
||||||||
||||++++- Hue (phase, determines NTSC/PAL chroma)
||++----- Value (voltage, determines NTSC/PAL luma)
++------- Unimplemented, reads back as 0

Hue $0 is light gray, $1-$C are blue to red to green to cyan, $D is dark gray, and $E-$F are mirrors of $1D (black). The canonical code for "black" is $0F or $1D. $0D should not be used; it results in a "blacker than black" signal that may cause problems for some TVs. It works this way because of the way colors are represented in an NTSC or PAL signal, with the phase of a color subcarrier controlling the hue. For details, see NTSC video.

The 2C03 RGB PPU used in the PlayChoice-10 and Famicom Titler renders hue $D as black, not dark gray. The 2C04 PPUs used in many Vs. System arcade games have completely different palettes as a copy protection measure.

RGB PPU palettes

The 2C03, 2C04, and 2C05 all output RGBS, with each of the three video channels using a 3-bit DAC. Their look-up tables (one digit for each of red, green, and blue, in order) are given below:

2C03 and 2C05

This palette is intentionally similar to the NES's standard palette, but notably is missing the greys in entries $2D and $3D.

333,014,006,326,403,503,510,420,320,120,031,040,022,000,000,000
555,036,027,407,507,704,700,630,430,140,040,053,044,000,000,000
777,357,447,637,707,737,740,750,660,360,070,276,077,000,000,000
777,567,657,757,747,755,764,772,773,572,473,276,467,000,000,000
0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F
0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F

2C04

All four 2C04 PPUs contain the same master palette, but in different permutations. It's almost a superset of the 2C03/5 palette, adding four greys, six other colors, and making the bright yellow more pure.

No version of the 2C04 was ever made with the below ordering, but it shows the similarity to the 2C03:

333 014 006 326 403 503 510 420 320 120 031 dup of ↙ 022 111 003 020
555 036 027 407 507 704 700 630 430 140 040 053 044 222 200 310
777 357 447 637 707 737 740 750 660 360 070 dup of ↓ 077 444 000 000
777 567 657 757 747 755 764 770 773 572 473 276 467 666 653 760

The PPUMASK monochrome bit has the same implementation as on the 2C02, and so it has an unintuitive effect on the 2C04 CPUs. Rather than forcing colors to grayscale, it instead forces them to the first column.

RP2C04-0001
755,637,700,447,044,120,222,704,777,333,750,503,403,660,320,777
357,653,310,360,467,657,764,027,760,276,000,200,666,444,707,014
003,567,757,070,077,022,053,507,000,420,747,510,407,006,740,000
000,140,555,031,572,326,770,630,020,036,040,111,773,737,430,473
RP2C04-0002
000,750,430,572,473,737,044,567,700,407,773,747,777,637,467,040
020,357,510,666,053,360,200,447,222,707,003,276,657,320,000,326
403,764,740,757,036,310,555,006,507,760,333,120,027,000,660,777
653,111,070,630,022,014,704,140,000,077,420,770,755,503,031,444
RP2C04-0003
507,737,473,555,040,777,567,120,014,000,764,320,704,666,653,467
447,044,503,027,140,430,630,053,333,326,000,006,700,510,747,755
637,020,003,770,111,750,740,777,360,403,357,707,036,444,000,310
077,200,572,757,420,070,660,222,031,000,657,773,407,276,760,022
RP2C04-0004
430,326,044,660,000,755,014,630,555,310,070,003,764,770,040,572
737,200,027,747,000,222,510,740,653,053,447,140,403,000,473,357
503,031,420,006,407,507,333,704,022,666,036,020,111,773,444,707
757,777,320,700,760,276,777,467,000,750,637,567,360,657,077,120

Backdrop color (palette index 0) uses

During forced blanking, when neither background nor sprites are enabled in PPUMASK ($2001), the picture will show the backdrop color. If only the background or sprites are disabled, or if the left 8 pixels are clipped off, the PPU continues its normal video memory access pattern but uses the backdrop color for anything disabled.

The background palette hack

If the current VRAM address points in the range $3F00-$3FFF during forced blanking, the color indicated by this palette location will be shown on screen instead of the backdrop color. (Looking at the relevant circuitry in Visual 2C02, this is an intentional feature of the PPU and not merely a side effect of how rendering works.) This can be used to display colors from the normally unused $3F04/$3F08/$3F0C palette locations. A loop that fills the palette will cause each color in turn to be shown on the screen, so to avoid horizontal rainbow bar glitches while loading the palette, wait for a real vertical blank first using an NMI technique.

RGB palette values

The NES does not generate RGB video. Using this table will result in video that looks more like a PlayChoice than like an NES, and some games will look graphically sterile if quirks of the NES's video output are not emulated. However, sometimes people want something quick, dirty, and functional before they bother with adding correct NTSC video decoding, or they're making an emulator for a low-end device that cannot decode NTSC video in real time. In a predefined palette, such as one commonly stored in Classic VGA Palette format (.pal), each sRGB triplet represents the color that results from decoding a large flat area with a given palette value.

The following table was generated using blargg's Full Palette demo on Nestopia:

 84  84  84    0  30 116    8  16 144   48   0 136   68   0 100   92   0  48   84   4   0   60  24   0   32  42   0    8  58   0    0  64   0    0  60   0    0  50  60    0   0   0
152 150 152    8  76 196   48  50 236   92  30 228  136  20 176  160  20 100  152  34  32  120  60   0   84  90   0   40 114   0    8 124   0    0 118  40    0 102 120    0   0   0
236 238 236   76 154 236  120 124 236  176  98 236  228  84 236  236  88 180  236 106 100  212 136  32  160 170   0  116 196   0   76 208  32   56 204 108   56 180 204   60  60  60
236 238 236  168 204 236  188 188 236  212 178 236  236 174 236  236 174 212  236 180 176  228 196 144  204 210 120  180 222 120  168 226 144  152 226 180  160 214 228  160 162 160
NES palette generated with Bisqwit's tool

Other tools for generating a palette include one by Bisqwit and one by Drag.

Color names

When programmers and artists are communicating, it's often useful to have human-readable names for colors. Many graphic designers who have done web or game work will be familiar with HTML color names.

Luma

  • $0F: Black
  • $00: Dark gray
  • $10: Light gray or silver
  • $20: White
  • $01-$0C: Dark colors, medium mixed with black
  • $11-$1C: Medium colors, similar brightness to dark gray
  • $21-$2C: Light colors, similar brightness to light gray
  • $31-$3C: Pale colors, light mixed with white

Chroma

  • $x2: Blue
  • $x4: Magenta
  • $x6: Red
  • $x7: Orange
  • $x8: Yellow or olive
  • $xA: Green
  • $xC: Cyan

These NES colors approximate colors in the classic Windows or EGA palette, though the NES doesn't really have a good yellow:

  • $02: Navy
  • $06: Maroon
  • $12: Blue
  • $14: Purple
  • $16: Red
  • $17: Brown
  • $18: Olive
  • $1A: Green
  • $1C: Aqua
  • $24: Fuchsia/Magenta
  • $2A: Lime
  • $2C: Teal