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) | FA == AF >> 8F == AF & 0x00FFBC == (B << 8) | CB == BC >> 8C == BC & 0x00FFDE == (D << 8) | ED == DE >> 8E == DE & 0x00FFHL == (H << 8) | LH == HL >> 8L == 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.