How to write a Game Boy emulator – Part 2: Registers and flags
This post is part of a blog series about writing a Game Boy emulator.
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 AF as an example. AF is a 16-bit register, but it's also two 8-bit registers: A and F namely. If AF = 0x1234, that means that A = 0x12 and F = 0x34. If you change the value of A to 0x22, that means that AF 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 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
---|---|---|---|---|---|---|---|
F (the Flag register) | |||||||
Z | N | H | C |
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.
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.