Video summary
Gameboy Emulator Development - Part 08
Main summary
Key takeaways
Overview (Part 08)
This episode continues building a Game Boy emulator, focusing on bitwise logic and the CB-prefixed instruction set.
Bitwise / Logic Instructions (non-CB, acting on register A)
The speaker implements and wires up instruction handlers for operations on the A register, including:
-
AND (
AND A, n)- Operation:
A = fetched_data & A - Flags: updates a Z flag pattern consistent with the tutorial’s mapping (explicitly sets
Zin code and matches the referenced “and section” behavior).
- Operation:
-
XOR (
XOR A, n)- Operation:
A = fetched_data ^ A(with attention to masking to “bottom bits”) - Flags: sets such that Z becomes 1 only when the result is zero (noted as
z 0 0 0).
- Operation:
-
OR (
OR A, n)- Operation:
A = fetched_data | A - Flags: similar behavior to the other logical operations.
- Operation:
-
CP (
CP A, n)- Purpose: a compare that does not modify registers
- Internal behavior: effectively performs a subtraction (
A - fetched_data) but only updates flags - Flags:
- Z: set if values are equal
- H: based on nibble borrow (
(A & 0x0F) - (n & 0x0F)) - N: set (subtraction-style operation)
- Carry: based on whether subtraction borrows (
A < fetched_data)
- Emphasis: the “purpose of this cp function is… not actually changing any registers, it’s just changing these flags.”
These handlers are then added to the instruction map, reflecting the tutorial’s mechanical opcode-to-function wiring updates.
CB-Prefix Instruction Set (0xCB): rotate / shift / bit operations
The video then implements CB-prefixed opcodes, which use a second-byte opcode decoding scheme.
Decoding strategy
After fetching 0xCB, the emulator reads the next byte and determines:
- A register selector from the opcode (e.g.,
B, C, D, E, H, L, (HL), A) - An operation group based on bitfields in the opcode
To support this, the speaker creates helper logic:
- A
reg typelookup for mapping opcode bits → register or(HL)memory access - A
decode regfunction that extracts register selection bits and returns the correct target
Additional CPU helpers required
They note the need for bus read/write support because (HL) operations require memory access (reads/writes), not just register manipulation.
Instruction groups handled
The CB decoder supports several categories:
-
BIT b, r
- Checks whether bit
bis set in the target register (or in memory atHL) - Flags, especially Z:
- Z = 0 if the bit is set
- Z = 1 if the bit is not set
- Checks whether bit
-
RES b, r
- Clears bit
bin the target register/memory byte - Updates using masking with
~(1 << bit)
- Clears bit
-
SET b, r
- Sets bit
bin the target register/memory byte - Updates using masking with
(1 << bit)
- Sets bit
-
Rotate/shift family (selected by opcode subfields), implemented via a switch-style structure:
- RLC: rotate left; old bit 7 → carry
- RRC: rotate right; old bit 0 → carry
- RL: rotate left through carry
- RR: rotate right through carry
- SLA: shift left; carry from old bit 7
- SRA: arithmetic shift right; MSB preserved
- SWAP: swap high/low nibbles
- SRL: logical shift right; MSB becomes 0
For each operation:
- Compute
result - Set/clear carry based on shifted-out bit behavior
- Set Z based on whether
resultis zero - Set other flags consistently using explicit flag-setting patterns (e.g.,
cpu set flags(result == 0, false, false, carry))
Special cycle behavior for (HL)
The tutorial notes that when the target is (HL), extra cycles are required:
If the register is equal to
hl, add two emulation cycles.
Debugging / Sanity checks mentioned
The speaker runs build/tests and fixes issues, including:
- Removing duplicate or incorrect implementations (e.g., accidentally having two XOR functions)
- Ensuring correct opcode mapping and addressing-mode handling
- Adding missing opcode “fetch byte” behavior needed for CB-prefixed immediate-byte decoding (mentions something like
amd8/ immediate byte retrieval for the prefix) - Confirming the execution path works:
- “we’re getting called… we see one error proc… remove that… remove duplicates… then CB instructions are invoked”
They also mention:
- They don’t validate CB opcodes yet, but the basic wiring and execution path is functioning.
What’s next
- Only a few CPU instructions remain untouched.
- After that, they’ll implement interrupts.
- Then they’ll start running CPU test ROMs placed in the
romsfolder.
Main sources / speakers
- Primary speaker: the YouTube channel host (referred to as “low level dev(il) / low level devil channels”) presenting “Gameboy Emulator Development - Part 08”.