The NES uses an Attribute Table (the last 64 bytes of a Nametable) to assign palettes to background tiles.
- One byte in the attribute table controls a 2x2 block of tiles (a 4x4 tile area, or 32x32 pixels).
- Each byte is split into four 2-bit blocks. Each block selects one of the four palettes available for that area.
- For background tiles, a value of
0b00 refers to the Universal background color stored at 0x3F00.
To find the palette for a specific tile, calculate the attribute table index based on the tile's column and row, then extract the correct 2-bit block.
fn bg_pallette(ppu: &NesPPU, tile_column: usize, tile_row : usize) -> [u8;4] {
let attr_table_idx = tile_row / 4 * 8 + tile_column / 4;
let attr_byte = ppu.vram[0x3c0 + attr_table_idx]; // note: still using hardcoded first nametable
let pallet_idx = match (tile_column %4 / 2, tile_row % 4 / 2) {
(0,0) => attr_byte & 0b11,
(1,0) => (attr_byte >> 2) & 0b11,
(0,1) => (attr_byte >> 4) & 0b11,
(1,1) => (attr_byte >> 6) & 0b11,
(_,_) => panic!("should not happen"),
};
let pallete_start: usize = 1 + (pallet_idx as usize)*4;
[ppu.palette_table[0], ppu.palette_table[pallete_start], ppu.palette_table[pallete_start+1], ppu.palette_table[pallete_start+2]]
}