How to write a Game Boy emulator - Part 2: Registers and flags
Prerequesites
Writing an emulator requires some knowledge of low-level programming. You should familiarize yourself with the following concepts because they’re going to be recurrent throughout this tutorial:
Registers
Registers are like super-fast memory, but available in very limited quantities. There are so few of them that we refer to each one by name. The Game Boy has six 16-bit registers, and eight 8-bit registers.
16-bit registers | 8-bit registers |
---|---|
|
|
A 16-bit register can store a number from 0 to 65 535 inclusively, while an 8-bit register can store a number from 0 to 255.
Minimum value | Maximum value | |
---|---|---|
16-bit register | 0 | 216 - 1 = 65 535 = 0xFFFF |
8-bit register | 0 | 28 - 1 = 255 = 0xFF |
There is one important thing to understand however. The 16-bit and 8-bit registers are not disjoint. Each 8-bit register is just one half of a 16-bit register.
What does this mean? Let’s take BC as an example. BC is a 16-bit register, but it’s also two 8-bit registers: B and C namely. If BC = 0x1234, that means that B = 0x12 and C = 0x34. If you change the value of B to 0x22, that means that BC now equals 0x2234.
Most Significant Byte (MSB) | Least Significant Byte (LSB) |
---|---|
A | F |
B | C |
D | E |
H | L |
PC | |
SP |
The following invariants are always true:
AF == (A << 8) | F
A == AF >> 8
F == AF & 0x00FF
BC == (B << 8) | C
B == BC >> 8
C == BC & 0x00FF
DE == (D << 8) | E
D == DE >> 8
E == DE & 0x00FF
HL == (H << 8) | L
H == HL >> 8
L == HL & 0x00FF
Flags
A flag is a boolean value represented as a bit. It has only two possible states: 0 and 1.
0 | 1 |
---|---|
false | true |
off | on |
reset | set |
The Game Boy has four flags:
- Z (the Zero flag)
- N (the Negative flag)
- H (the Half-carry flag)
- C (the Carry flag)
Each flag is represented as one bit inside the Flag register. Bit 7 is the most significant bit (msb) while bit 0 is the least significant bit (lsb).
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|
F (the Flag register) | |||||||
Z | N | H | C | 0 | 0 | 0 | 0 |
That means that if you change the value of a flag, you change the value of F. And if you change the value of F, you change the value of the flags.
Do note that bits 0,1,2,3 of F are always 0.
The code
Your registers and your flags should support two operations: get and set. There are many ways to achieve that, but in the end they should maintain the invariants discussed above.