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.
The background uses the PPU addresses $3f00-3f0f for palettes.
The sprites use PPU addresses $3f10-3f1f for palettes.
Color index #0 (at PPU address $3f00) is the universal BG color. All 4 of the bg palettes will reuse that same color as their 0th color.
There are 4 Background palettes.
U = universal color
U123 U123 U123 U123
That makes 13 unique BG colors on screen.
The 0 color index for each Sprite palette is transparent.
There are 4 Sprite palettes.
x = transparent
x123 x123 x123 x123
That makes 12 unique Sprite colors on screen.
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. There will be an example of pal_col in the next page (sprite collisions).
Although the palette is in the PPU, and usually it can’t be written while the screen is on… 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, that’s $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 pixel chunk of the BG. Each byte in the attribute table is further divided into 2 bit segments, and each 2 bits represents a 16×16 pixel chunk of the BG.
So, each tile doesn’t get its own palette choice. You can only define a palette choice for a 2×2 block of tiles.
Try NES Screen Tool and draw some simple graphics and place them on the map. Now unclick “Apply tiles” and choose a different palette and draw on the tilemap. It will only change the palette instead of applying tiles. You can easily see the limitations of the attribute table. You can also highlight the attribute grid by clicking on the 2x grid button.
Most games just design their games in blocks of 16×16 pixels. 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.
Having multiple palettes to choose from extends our tileset, since we can reuse the same tiles for different objects by changing its palette. Look at the clouds and the bushes. They are using the same tiles, but they are colored differently because they are assigned a different palette.
Again, 1 attribute byte is further divided into 2 bits per block. So, the layout of an attribute byte go like this, bitwise…
if you look at the byte in binary, these bits represent tiles like this… DDCCBBAA
So, AA is the top left tiles of that block. BB is the top right, etc. So if bits DD goes 00, the bottom right tiles in that block will use the #0 palette. If it goes 01, it will use the #1 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. Then I used vram_fill() to set the attribute bytes.
get_at_addr(char nt, char x, char y); — x and y are pixel positions 0-255
vram_fill(unsigned char n,unsigned int len); — n is the fill value
Palette 0 = grays, 1 = blues, 2 = reds, 3 = greens.
The attribute table is fairly hard to modify mid game…involving bit shifting and masking. You would keep a full copy of the attribute table as an array in the RAM, and modify 2 bits at a time, and copy the byte to the correct PPU address after it is modified. 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 vram_put() statement to change 1 attribute byte, so you can see it’s size and abilities. See that multi colored block on the lower left?
vram_put(0xe4); // push 1 byte (in binary, that’s 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.