09 January, 2009

Game Boy Colo[u]r: the scene is nearly completely dead :(

If you're doing any game-boy development, you will probably come across a file called GBSPEC.TXT. This tells you everything that you need to know... about the classic Game Boy. But what if you wanted to know about the Game Boy Colo[u]r? The only information I could find was on the website about the "Lush Engine". This thing is a goldmine of information... there's gold there, but you have to mine for it, and pan it out. Sadly, the only trace of this website is in the WayBack Machine.

There's a list of registers that can come in handy if you know what they do, a tutorial on how to edit the GBC palettes, and some source code to show you how to put a coloured tile onto the screen.

Remember to thank me for this, because the only alternative to that is to tell everyone to fuck themselves and die for losing such information. I would rather thank someone than wish that on anyone.

So, here's all the vital information which isn't already out there and isn't only stored in an archive. Spread it like wildfire or watch the scene die completely - I mark it as public domain.

My code examples will be in the same format as the WLA-GB compiler, one of the several compilers in WLA-DX. Because, let's face it, RGBDS is bullshit.

Here are all the extra GBC registers AFAIK, according to the Lush archive:
  • FF4D (KEY 1) - Speed switching
  • FF4F (VBK) - VRAM bank select
  • FF51 (HDMA1) - Horizontal Blanking, General Purpose DMA Control
  • FF52 (HDMA2) - Horizontal Blanking, General Purpose DMA Control
  • FF53 (HDMA3) - Horizontal Blanking, General Purpose DMA Control
  • FF54 (HDMA4) - Horizontal Blanking, General Purpose DMA Control
  • FF55 (HDMA5) - Horizontal Blanking, General Purpose DMA Control
  • FF56 (RP) - Infrared Communications Port
  • FF68 (BCPS) - Colour Palette BG Write Specification
  • FF69 (BCPD) - Colour Palette BG Write Data
  • FF6A (OCPS) - Colour Palette Object Write Specification
  • FF6B (OCPD) - Colour Palette Object Write Data
  • FF70 (SVBK) - WRAM Bank Specification
I can't tell you about any of the HDMA ones or the SVBK register. I can only speculate on KEY1 (you write something to double the speed and zero it to go back to normal) and RP (you treat it just like the serial port). But I can tell you about the rest.

On a GBC, video memory is banked, and there are two banks. The first bank (vbank0, not an official naming scheme) acts just like your normal Game Boy. But the second bank (vbank1) is what makes it special.

There are 8 background palettes, and 8 sprite palettes. You set them by filling in the palette registers, which look a little like this:

H = XRRRRRGG
L = GGGBBBBB

R is red, G is green, B is blue, X is unused. You fill in the registers by using a set of I/O registers. BCPS and BCPD (or OCPS and OCPD for sprites). And you access them like this:

BCPS = IXPPPEEB
I = if set, move onto the next palette entry automatically after writing the data
X = unused
P = palette select
E = palette entry
B = byte (0 = low, 1 = high)

You write to BCPS first, then write the data into BCPD. Here's an example on how to write the colour magenta into palette 5, index 2:
LD a,101100
LD ($FF68),a
LD a,011111
LD ($FF69),a
LD a,101101
LD ($FF68),a
LD a,%01111100
LD ($FF69),a

But how do we use them? We need the help of the second bank (vbank1). Generally, you write your tile data to vbank0, and then your colour / bank select data to vbank1.

Hang on, bank select data?

Yes, you can write tiles to vbank1 in the tile space, and they will be accessible with this magic write :D

The format of the tile space bytes in vbank1:
ATTR = ????BPPP
B = bank
P = palette

Let's say that we had the ASCII set loaded into vbank0 and we wanted to put an exclamation mark in the top-left corner which used palette 5, we would use the VBK register, like so:
LD a,$00
LD ($FF42),a
LD a,"!"
LD ($9800),a
LD a,$01
LD ($FF42),a
LD a,%0101
LD ($9800),a

But how do you handle sprites?
For some weird reason, you can only use 3 of the 4 colours of the object palettes, even though you can set all 4. So, ignore entry 0.

To write the object palettes, you do it the same way as you would with the background palettes, except you write to OCPS and OCPD. And you don't fill in entry 0, as that is pointless.

So how do we use them? If BGB is correct, you fill in your sprite flag byte like this, as opposed to the Game Boy:

FLAGS = ?YX??PPP
? = unused / unknown
Y = y flip
X = x flip
P = palette

And it should work... that is, if you've filled in the correct bit in the LCDC.

So, there you have it, a crash tutorial on how to use the most anticipated feature in the Game Boy Colo[u]r: colour.

Because, quite frankly, there's no fucking information left.

No comments: