05. Palettes

A little more about the NES palette.


There are 64 choices (0-$3f), but many of those are black. The neslib forces you to use $0f for black and $30 for white. Don’t use the xD colors, especially $0D (it glitches some TVs, see YouTube videos of “Immortal” glitched title screen). Well, you can’t anyway, since the neslib converts it to $0f.

Background uses the PPU addresses $3f00-3f0f for palettes. Color index #0 (position $3f00 in the PPU) is the universal BG color. All 4 of the bg palettes will reuse that same color as their 0th color.

There are 4 BG palettes (and 4 Sprite palettes), with 4 sub-palettes.
U = universal color
U123 U123 U123 U123
That makes 13 unique BG colors on screen.

Sprites can only use 3 colors per tile. The 0th color index is transparent. Sprites use the $3f10-3f1f area of the PPU for palettes. You can use 12 unique sprite colors.


So far, we have been working with only 1 palette (4 colors), so let’s make something using all the bg palettes.

You can change an entire palette (32 bytes) with pal_all(), or change the 16 byte bg palette with pal_bg() and the 16 byte sprite palette with pal_spr(). Just pass it an array of 16 bytes. And you can change just 1 color with pal_col(index, color), where index is 0-$1f. These will be an example of pal_col in the next page (sprite collisions).

On a side note, the palette is in the PPU, and it can’t be written while the PPU is rendering, but all the neslib palette functions write to a buffer, which is copied to the PPU only during v-blank (in the nmi code). So, feel free to use these functions anytime, with the screen on or off.

Background Attribute Table

In the PPU, at the end of each nametable (tilemap), is the attribute table. For map#0, thats $23c0-$23ff. The only “attribute” they can have is palette selection, so, you can think of it as the palette table.

A nametable only has 64 bytes to work with for palette choices, so that makes an 8×8 grid. Each byte represents a 32×32 chunk of the BG. Each byte is further divided into 2 bit segments, and each 2 bits represents a 16×16 chunk of the background.


So, each tile doesn’t get it’s own palette choice. You can only define a palette choice for a block of 4 (2×2) tiles.

Try NES screen tool and try changing palettes, and you can see this right away.

Most games just design their games in blocks of 16×16. I do this too.


Notice how the floor blocks and the window blocks are exactly 16×16 pixels. The columns are exactly 32 pixels wide. The curtain area is exactly 32 pixels wide.

Again, 1 attribute byte affects a 2×2 set of 16×16 blocks. 2 bits per block. So, the layout of an attribute byte go like this, bitwise…

44332211 bits in attribute byte

11 22
11 22
33 44
33 44

So if bits 44 goes 00, that block will use the 0th palette. If 22 goes 01, it will use the next palette, etc.

So, I made a background in NES screen tool. The entire picture was gray, using palette #0, but the code is writing to the Attribute table with fills, changing the palette choices. Notice I used get_at_addr(0,0,0) to calculate an address in the attribute table.


The attribute table is fairly hard to modify mid game…involving bit shifting and masking. Many games just avoid changing it, except as part of the scrolling engine. You could design the game as 32×32 blocks, and you would just change a full byte, rather than worry about bit shifting.

I wrote 1 put statement to change 1 lower attribute byte, so you can see it’s size and abilities.

vram_put(0xe4); // push 1 byte 11 10 01 00

For now, if make the background in NES screen tool, just save the nametable with the attribute bytes as a compressed rle, and it will copy those when your game loads them.




Part of my library is a metatile system, which can handle attribute bytes for you.
For another time.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s