![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Gameboy Colour Palettes
Title :Gameboy Colour Palettes
Section 1 - IntroductionTo work with the colour palettes, you must understand how the BITs are arranged within a BYTE. If you are unsure, quickly read the number systems tutorial in the general assembler section.
Section 2 - OverviewThe Gameboy Colour can display 56 different colours on screen at once from a total of 32,768 different colours. With clever code, you can display more than that, but it takes some doing, and that kind of trick is beyond the scope of this tutorial. The magic number of 56 is due to the fact that there are eight separate palettes for the background (the window uses the same palettes), each of which has four colours (8 x 4 = 32), and there are also eight separate palettes for the objects (sprites) and although each palette has four colour entries, colour 0 is always transparent, leaving three useable colour entries (8 x 3 = 24). The total of 32,768 for the number of different colours is reached due to the fact that each colour is made up of 32 shades of red, green, and blue, with the shades ranging from 0 to 31 (0 being none of the colour, 31 being the highest amount of the colour). 32 x 32 x 32 = 32,768.
Section 3 - Colour Palette DataIn Binary, the number range 0-31 can be represented by five BITs. This means that a single palette entry requires fifteen BITs to specify which colour is being displayed (five BITs for the red part, five for the blue part, and five for the green part). Fifteen BITs fit nicely into two BYTEs with one BIT to spare, so two BYTEs are used for each palette entry. The two BYTEs are referred to as Colour Palette High and Colour Palette Low. The table below shows the two BYTEs, and what each BIT is used for.
Data Key
As the table above shows, the green data is split between the two bytes. This isn't a problem, you just need to remember that the high data BYTE holds the high BITs of the green data and the low data BYTE holds the low BITs of the green data.
Section 4 - Preparing the dataGetting the two data BYTEs ready for writing to a palette entry can be thought of as difficult. However, it isn't really. So long as you already have three colour values ranging from 0-31, the preparation of the colour data BYTEs is fairly straightforward. As a point of interest, if you have colour values ranging from 0-255 for the three colours, and you want to convert them to a 0-31 range, an easy method is to simply shift the data right three times (each shift right halves the data, losing any fractions, so three shifts right is halved, then quartered, then eighthed). The command in assembler to shift the data right is SRL. So, assuming that you bring the colour value into the accumulator, the commands would be: SRL A ; halves the data SRL A ; halves it again SRL A ; halves it one final timeAnyway, back to the data preparation. Let's assume that the red value is held in E, the green value is held in H, and the blue value is held in L. We will be storing the high data BYTE in E, and the low data BYTE in D. For this example, we will create the low data BYTE first, and then the high data BYTE. To start off with, we take the red data value and place it in the low data BYTE store. The code is as follows; LD A,E AND 31 LD D,AThe AND command is used to mask out any unwanted data, just in case we have a colour value that is greater than 31. That's the red part finished. Now the green. We need the right hand three BITs of the green data merged with the red data (placed in BITs 7, 6, and 5 of the low data BYTE). The easiest way to do this is to shift the green data left five times, which pushes the left five BITs off into oblivion, and leaves the remaining three BITs in the correct positions. The code is as follows; LD A,H SLA A SLA A SLA A SLA A SLA ANow we need to merge this with the red data already in the low data BYTE. A simple OR operation will do this for us, as follows; OR D LD D,AThat's the low data BYTE done, now the high BYTE. We'll start off by finishing off the green data. We want the left hand two BITs to form the right hand two BITs of the high data BYTE. To start off with, we mask out all the unwanted data, just in case we have a value higher than 31. The code is as follows; LD A,H AND 31Now we can shift the data to the right three times, throwing the data we don't want off the edge and keeping the two BITs we want in the right place. The code is as follows; SRL A SRL A SRL AThis gives us the start of the high BYTE, so we'll stick it in E. The code is as follows; LD E,AThe last colour to deal with now is blue. This value just needs masking and then shifting left two BITs. The code is as follows; LD A,L AND 31 SLA A SLA ANow we have the final colour value, we just merge it with the high data BYTE. The code is as follows; OR E Section 5 - Writing the dataWriting data to a palette is done by using the following Gameboy registers: the write specification register and the write data register. What you do is set up the write specification register to tell the gameboy what data you are sending, and then place the data in the write data register. The BITs of the write specification register are used for the following things.
A few examples of write specification entries follow:
You will notice that there is no way within the write specification register to state which type of palette is being written (background of object). This is because there are two write specification registers and two write data registers, one set for background palettes and one for object palettes. The addresses of these registers are shown in the table below:
The four letter acronyms in brackets in the table above are the shorthand names for the registers used by Nintendo. Their full names are:
An example follows to show how the two data BYTEs are written for a single colour of a background palette. The data bytes are stored in D and E (D being the low data BYTE and E being the high data BYTE as in the example in the previous section). LD HL,$FF68 ; set up a pointer to the BCPS LD C,%00001010 ; Colour 1 of Palette 1 LD A,C ; Load A with the write specification ; data LD [HLI],A ; place the data in the specification ; register and move the pointer to the ; BCPD LD A,D ; get the low data BYTE LD [HL],A ; send the low data BYTE to the register LD HL,$FF68 ; set the pointer back to the BCPS LD A,C ; Load A with the write specification ; data INC A ; Add 1 to the data, therefore setting ; BIT 0 which means we are now writing ; the high data BYTE LD [HLI],A ; place the data in the specification ; register ; and move the pointer to the BCPD LD A,E ; get the high data BYTE LD [HL],A ; send the high data BYTE to the register That's basically all there is to it. The example code is not the best code in the world, but it does show, with simple code, how it all works.
End of Tutorial |