Video summary

Gameboy Emulator Development - Part 08

Main summary

Key takeaways

Technology

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 Z in code and matches the referenced “and section” behavior).
  • 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).
  • OR (OR A, n)

    • Operation: A = fetched_data | A
    • Flags: similar behavior to the other logical operations.
  • 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 type lookup for mapping opcode bits → register or (HL) memory access
  • A decode reg function 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:

  1. BIT b, r

    • Checks whether bit b is set in the target register (or in memory at HL)
    • Flags, especially Z:
      • Z = 0 if the bit is set
      • Z = 1 if the bit is not set
  2. RES b, r

    • Clears bit b in the target register/memory byte
    • Updates using masking with ~(1 << bit)
  3. SET b, r

    • Sets bit b in the target register/memory byte
    • Updates using masking with (1 << bit)
  4. 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 result is 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 roms folder.

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”.

Original video