Video summary

Gameboy Emulator Development - Part 07

Main summary

Key takeaways

Technology

Summary (Game Boy Emulator Development - Part 07)

This video continues building a Game Boy CPU emulator, focusing on implementing arithmetic and increment/decrement instructions, including accurate cycle timing and CPU flag behavior.


1) Instruction map updates (core work)

The developer rapidly adds new opcode handlers into the emulator’s instruction map, covering:

  • Increment/Decrement-style instructions (“inc” and “dec”, including variants for registers and memory destinations)
  • Add-family instructions: ADD, ADC (add with carry), SUB, and SBC (subtract with carry)

Note: Some decrement values are mentioned as being “revalidated later,” since opcodes were added quickly and mistakes may have occurred.


2) Increment (INC) implementation details

A new handler proc inc is added, with special care for:

  • 16-bit operand behavior
    • Introduces an is 16 bit(...)-style helper using the same pattern used earlier in LD to check whether the register is treated as 16-bit.
  • Extra cycle for 16-bit operations
    • Explicitly mentioned: “need to add one extra cycle.”
  • HL memory destination handling
    • If the destination is HL and the operand is memory ((HL)):
      • Read the byte at HL
      • Increment it
      • Write it back
    • Uses bottom-byte masking (& 0xff / 0xff) to ensure correct wrap-around.
  • Flag modification rules
    • For certain opcode variants (referenced as patterns ending like ...x3 and ...xB), the handler may skip flag updates because those cases do not modify CPU flags.
    • Otherwise it sets:
      • Z (zero flag) if the result is zero
      • N (subtract flag) forced to 0 for increment
      • H (half-carry) computed as required
      • Carry C is not modified (“don’t touch the carry flag”).

3) Decrement (DEC) implementation

  • A proc deck / proc dec is created similarly to INC.
  • Uses decrement opcode table expectations:
    • Result is decreased by 1
    • Flag behavior differs, notably setting N = 1 for decrement
    • Carry handling follows DEC rules
  • As with INC, memory/register variants require careful flag and wrap-around handling.

4) ADD implementation (proc add) is the most complex part

A new proc add handles multiple operand sizes and special cases:

  • Reads the operand from reg1 plus fetch data (using a wider type like u32 to avoid overflow issues during computation).
  • Uses the same is 16 bit logic to branch:

16-bit ADD instructions

  • Z flag is not modified
  • H and C logic uses different thresholds compared to 8-bit adds
    • The video explicitly distinguishes constants like 0x0fff / 0x1000-style logic.

8-bit ADD instructions

  • Sets Z, N, H, and C according to standard Game Boy rules:
    • Half-carry uses nibble carry logic
    • Carry uses full-byte overflow (>= 0x100)

Special handling when reg1 is SP

  • Uses a signed-like immediate behavior for the operand (so it subtracts because there is no subversion).
  • Flags derived from an SP + signed-immediate style computation:
    • Z cleared (set to 0)
    • N cleared (0)
    • H and C computed using bottom bits / byte overflow logic
  • Mentions stack-pointer variants may duplicate 8-bit patterns but are rewritten for readability.

5) ADC, SUB, SBC implementations (simpler)

ADC (proc adc)

  • Implemented as add with carry, operating primarily on accumulator A.
  • Computes:
    • A = A + value + C
    • Wraps to 8-bit (& 0xff)
  • Half-carry and carry are computed; N is cleared.

SUB and SBC (proc sub, proc sbc)

  • proc sub
    • reg = reg - fetched data
    • Sets Z, N=1, H, and C using nibble/buffer comparisons (with type-casting fixes noted).
  • proc sbc
    • Subtract with carry: A = A - fetched data - C
    • Similar flag logic to SUB, but includes the borrow term.
  • The developer corrects types/thresholds after initial implementation:
    • Fixes to sbc using u8
    • Adjustments to comparison constants like >= 0x100 and half-carry thresholds.

6) Sanity checks & timing verification

  • ROM tests are performed to validate behavior, including:
    • Example validation: correct auto-increment behavior for LD (HL+)-style instructions
      • Observes values jumping in memory/register as HL increments through HL+.
    • Timing checks:
      • Mentions memory timing / cycle behavior while testing interactions involving inc and ld.

7) Debug/logging improvements (for emulator development)

Before stopping, the video adds better visibility into CPU state:

  • In cpu.c, adds a flags display string:
    • Z, N, H, C shown as set or - (dash)
  • Adds logging for the current emulator tick / cycle count
    • Using a formatting width like ~8 characters
  • Helps track where execution stops (one ROM halted after reaching ~3032 ticks).

8) Next steps preview

  • The next video is expected to cover bit operations.
  • The series continues toward completing the remaining CPU instructions across subsequent episodes.

Main speakers / sources

  • Primary speaker/source: The video author (“low level dev / low level devil” channel host), narrating the Game Boy emulator development series.

Original video