I will also be cross-referencing a lot of terms and concepts from the "Nerdy Nights" tutorials with info from the NesDev Wiki. As these tutorials are meant to sort of get you programming fairly quickly, they gloss over a lot of the details as to the inner workings of the hardware. Hopefully my posts will be able to help make a bridge between the code samples and the interactions with the processors and memory.
- There are essentially 2 groupings of color palettes, one for the background and one for sprites.
- These 2 groupings each contain 8 separate color palettes (4 bytes in size). Although each palette is 4 bytes in size, only 3 different colors could be stored in each palette, as you will see in the table below.
- The PPU addresses start at $3F00 (background) and $3F10 (sprites). The table of these values are listed below. Note that some addresses (like $3F04, $3F09, etc.) are skipped. These addresses contain either a) the common background color, shared in each background palette or b) transparency, used for sprites in each sprite palette
Courtesy of wiki.nesdev.com
- The NES PPU had a total of 64 colors you could choose from, but was limited to only displaying 25 different colors on the screen at any one time.
- This 25 color limit is broken up "4 palettes x 3 colors = 12 for sprites, 4 palettes x 3 colors = 12 for background tiles, 1 for background" (thanks Noel Berry).
Moving over to the programming...
Courtesy of Nerdy Nights - Week 4. Each hex value represents one of the usable 64 colors in the PPU.
- When writing colors into the background/sprite palettes, the appropriate address must be set into the PPU address $2006. For example, passing $3F00 to $2006 would allow you to add colors to the background palette. Each port must be written into $2006 twice, writing the high byte first, then for the low byte. This can best be demonstrated by the Nerdy Nights code snippet below.
LDA $2002 ; read PPU status to reset the high/low latch to high
STA $2006 ; write the high byte of $3F10 address
STA $2006 ; write the low byte of $3F10 address
In this case, the tutorial will be setting the color palette for sprites ($3F10).
- AT this point, the PPU is set to start taking color values for its sprite palette. As pointed out in the tutorial, you can load them one by one into $2007, where the PPU will automatically increment the palette address after each write to $2007.
LDA #$32 ;code for light blueish STA $2007 ;write to PPU $3F10 LDA #$14 ;code for pinkish STA $2007 ;write to PPU $3F11 LDA #$2A ;code for greenish STA $2007 ;write to PPU $3F12 LDA #$16 ;code for redish STA $2007 ;write to PPU $3F13
PaletteData: .db $0F,$31,$32,$33,$0F,$35,$36,$37,$0F,$39,$3A,$3B,$0F,$3D,$3E,$0F ;background palette data .db $0F,$1C,$15,$14,$0F,$02,$38,$3C,$0F,$1C,$15,$14,$0F,$02,$38,$3C ;sprite palette data
A .db directive essentially works like the arrays of modern day programming, storing a large group of values into one place. This can be combined with the use of the X Index register, which allows the program to step through each byte of data individually.
LDX #$00 ; start out at 0 LoadPalettesLoop: LDA PaletteData, x ; load data from address (PaletteData + the value in x) ; 1st time through loop it will load PaletteData+0 ; 2nd time through loop it will load PaletteData+1 ; 3rd time through loop it will load PaletteData+2 ; etc STA $2007 ; write to PPU INX ; X = X + 1 CPX #$20 ; Compare X to hex $20, decimal 32 BNE LoadPalettesLoop ; Branch to LoadPalettesLoop if compare was Not Equal to zero ; if compare was equal to 32, keep going down
Once the above code finishes its application, the color palette is set up and ready to go.
The next post will go into more detail about the second part of "Nerdy Nights - Week 4": Sprites. Seeing as how much information was put into a single post for color palettes, I may save the Sprites post for a later day this week.