Day 4 - Making and Loading a Palette

Published: 2005-07-22
Updated: 2010-12-19
Author: Mike Huber

WHAT!?!

That's right, today we create and load a palette. To create the palette, we'll use the program PAL.exe which I gave you in that zip file in Day 1. Run it, you will see a window with 32 gray boxes which you can fill in by drawing colors from the colored boxes on the bottom. Make sure when you make your palette that you make the first color on each row black or you'll get some funky results when we make backgrounds and sprites.

Save the palette as our.pal, to save click the only menu and click the option with the word save in it. Good. If you didn't do all that and got pissed that I made you run a program that wasn't the assembler itself, click here to download my palette that I made for you. :)

What a palette is, plain and simple

If I say something contradictory to this paragraph later in this file, ignore it.

A palette is basically a bunch of colors to pick from. Our palette is 32 colors /bytes (1 color = 1 byte) long. 16 colors for the sprite palette, 16 colors for the BG palette. Even though you can pick from 16 you can only use 4 per sprite or 4 per 16x16 piece of BG. Doing this is a little more complicated that what we've done so far, so I won't cover it yet. OK, actually I just haven't done it yet, so how am I supposed to teach you how to do it?

How We Load The Pallete?

To load the palette, we write to 2 memory registers, $2006 twice to give it the full address ($3F00) that we are going to load the palette to. And then we just keep giving $2007 byte after byte of our palette until we've given it all of the palette.

However, before we load the palette, we need to learn a few other things.

Indexed Addressing

Maybe you remember in Day 1 or 2, when I said that X and Y registers can be involved in Indexed Addressing. So this is how it works, k? :

;Assume X is 6.

lda $2002, x    ; loads A with value at memory location ($2002+6) so
; memory location read is $2008.

;Assume Y is 9;

lda $2000, y    ; loads A with value at memory location ($2000+9) so
; memory location read is $2009. </code>

Note that you can load any register and use indexed addressing, not just A.

The Other Thing.

The other thing you need to know (and should have figured out already) is that load (and maybe store) instructions can take a label as the base address. here's some code to illustrate:

somelabel: .incbin "our.pal" ; include a pal file and label it's location.

lda somelabel, x  ; load A with value from location (somelabel's address+X register's
                  ; value). </code>

Please remember that unless I say otherwise, examples that just load A with something are just as applicable to loading X or Y. You should already know how label's work, if you don't you shouldn't be reading this. Go read my Intel ASM Tutor or other basic assembly book/article. Like I said before, you should already know some kind of assembly language and label's are basic to ALL of them. So there.

Loading The Pallete

Instead of me blabing my keyboard off, how 'bout we let the code explain it? :

lda #$3F ; these 4 lines tell $2006 that we sta $2006 ; want the stuff we load $2007 with lda #$00 ; to start at memory location $3F00 sta $2006 ; . Note that since we can only store a byte at a time we store twice ; to get the whole address in there.

ldx #$00   ; load X with 0. loadpal:   ; note that labels are followed by a ':' and aren't tabbed in.
lda ourpal, x   ; load A with palette value at location ourpal + x.

sta $2007       ; store the next palette value into $2007 which will put it in
; the right place for us.

inx    ; you've never seen this instruction before but it stands for INcrement X.
; it adds 1 to X.

cpx #32   ; ComPare X with 32 which is how many palette values we need to load.

bne loadpal  ; bne stands for Branch on Not Equal, so this will branch to loadpal
; if X wasn't equal to 32. If X is 32, then the loop will stop and were done
; loading the palette. </code>

Assume ourpal is a label that is defined later in the source file that looks something like this:

ourpal: .incbin "our.pal" ; label our palette for use in the loading code.

We will put together a complete code file when we get a sprite displayed tomorrow.

Here's that again without the comments:

lda #$3F sta $2006 lda #$00 sta $2006

ldx #$00 loadpal:
lda ourpal, x
sta $2007
inx
cpx #32
bne loadpal </code>

The New Instructions

You may have noticed the 3 new instructions in the loading code. They are

INX
- Adds 1 to X. There is also INY which adds 1 to Y. There is NO INA I heard that the designers of the 6502 just forgot it. There is a INA on the next version of the 6502 (the 65c02) that is used on the SNES.
CPX
- Compares a value with X. There is also CPY and CPA which compare things with Y and A respectively. You can only use immediate values here. NO MEMORY ADDRESSES ALLOWED.
BNE
- Jumps to a label if the result of the last CPk (k is A or X or Y) instruction was Not Equal. There is also BEQ which jumps if the result was EQual. There are a few more that I'll explain when they come up.

This Day In Review

Loading the palette is EXTREMELY important as a background or a sprite is NOTHING without it's palette. Loading a palette is basically all you need to do to it as once it's there, it does it's job without any help from you. Tomorrow a sprite.

All hail the NES! Good-night,
-Mike H a.k.a GbaGuy