Have gotten attribute tables and palettes to work. Was initially quite hard to work out how to apply the attribute table byte, particularly working out which quadrant I was in when drawing a pixel. I read a post from a couple of years ago that said to check v&2 for horizontal quadrant and v&64 for vertical quadrant. I could only get it to work via checking v&4 for vertical quadrant.
I think this part had the least amount of complete documentation on how to work this out for an emulator. So here is my code for it as I am a better coder than explainer:
Code: Select all
func drawPixel()
{
if cycle > 240 { return }
let x = cycle
let y = scanline
let highTile = UInt8(shiftRegisterTileA)
let lowTile = UInt8(shiftRegisterTileB)
let bit = (7 - (cycle-1)%8)
let index = UInt8((highTile.get( bit:bit) << 1) + lowTile.get( bit:bit))
// https://wiki.nesdev.com/w/index.php/Nestech.txt#Attribute_Tables
// +------------+------------+
// | Square 0 | Square 1 | #0-F represents an 8x8 tile
// | #0 #1 | #4 #5 |
// | #2 #3 | #6 #7 | Square [x] represents four (4) 8x8 tiles
// +------------+------------+ (i.e. a 16x16 pixel grid)
// | Square 2 | Square 3 |
// | #8 #9 | #C #D |
// | #A #B | #E #F |
// +------------+------------+
//
// 33221100
// ||||||++-- Upper two (2) colour bits for Square 0 (Tiles #0,1,2,3) Top Left
// ||||++---- Upper two (2) colour bits for Square 1 (Tiles #4,5,6,7) Top Right
// ||++------ Upper two (2) colour bits for Square 2 (Tiles #8,9,A,B) Bottom Left
// ++-------- Upper two (2) colour bits for Square 3 (Tiles #C,D,E,F) Bottom Right
//
// https://forums.nesdev.com/viewtopic.php?f=3&t=14795
// (v & 2) is the bit that decides horizontal quadrant.
// (v & 64) is the bit that decides vertical quadrant.
let right = (v & 2 == 2) ? 2 : 0
let bottom = (v & 4 == 4) ? 4 : 0 // v&64 doesn't work
let shift = right + bottom
let attributeIndex = UInt8((attributeTableByte >> shift) & 0x03)
let color = Palette.color( atIndex:Int(index | attributeIndex << 2))
Code: Select all
let paletteIndex = mapper!.readByte( atLocation:UInt16(0x3F00) + UInt16(index | attributeIndex << 2))
let color = Palette.color( atIndex:Int(paletteIndex))