Skip to content

Latest commit

 

History

History
240 lines (190 loc) · 7.24 KB

File metadata and controls

240 lines (190 loc) · 7.24 KB

zig-gbc

A Game Boy Color emulator written in Zig with DMG (original Game Boy) backward compatibility.

Architecture

This emulator uses a clean architecture with the following design principles:

  • Single Source of Truth: All I/O state lives in IoRegisters - no duplication
  • Typed References: Components hold typed pointers (*IoRegisters, *Mmu) - no callbacks or *anyopaque
  • Complete Initialization: Factory function returns a fully-valid GameBoy instance
  • Variable PPU Timing: Mode 3 duration calculated per-scanline based on sprites/scroll/window

Features

CPU

  • Full Sharp SM83 (LR35902) instruction set implementation
  • All 256 main opcodes and 256 CB-prefixed opcodes
  • Accurate cycle timing
  • HALT and STOP mode support
  • Interrupt handling (V-Blank, LCD STAT, Timer, Serial, Joypad)
  • HALT bug emulation

Graphics (PPU)

  • Scanline-based renderer (160x144 resolution)
  • Background and window layer rendering
  • Sprite rendering (40 sprites, 10 per scanline limit)
  • DMG 4-shade palette support
  • GBC color palettes (8 background + 8 sprite palettes, 32,768 colors)
  • GBC VRAM banking (2 banks)
  • Variable Mode 3 timing based on:
    • Number of sprites on scanline
    • SCX scroll position
    • Window activation

Audio (APU)

  • 4 audio channels:
    • Channel 1: Square wave with frequency sweep
    • Channel 2: Square wave
    • Channel 3: Programmable wave
    • Channel 4: Noise (LFSR-based)
  • Frame sequencer for length, envelope, and sweep clocking
  • Stereo output with per-channel panning
  • 44.1 kHz sample rate

Memory & Cartridge

  • Full 64KB address space emulation
  • Memory Bank Controllers:
    • ROM only (no MBC)
    • MBC1 (with RAM/ROM banking modes)
    • MBC2
    • MBC3 (with RTC support)
    • MBC5
  • Battery-backed save RAM (.sav files)
  • GBC WRAM banking (8 banks)

Timer

  • DIV counter (16-bit internal, 8-bit exposed)
  • TIMA/TMA/TAC with falling-edge detection
  • TAC glitch emulation

Input

  • Keyboard-based joypad emulation
  • Joypad interrupt support

GBC Features

  • Double-speed CPU mode (8.38 MHz)
  • HDMA and General Purpose DMA
  • VRAM bank switching
  • WRAM bank switching
  • Color palettes (background and sprite)
  • Speed switch via STOP instruction

Building

Prerequisites

  • Zig 0.13.0 or later
  • SDL3 development libraries

macOS (Homebrew)

brew install sdl3

Compile

zig build

Run

zig build run -- path/to/rom.gb

Or run the compiled binary directly:

./zig-out/bin/zig-gbc path/to/rom.gb

Run Tests

zig build test

Controls

Action Keys
D-Pad Up Arrow Up, W
D-Pad Down Arrow Down, S
D-Pad Left Arrow Left, A
D-Pad Right Arrow Right, D
A Button Z, J
B Button X, K
Start Enter
Select Backspace, Right Shift
Quit Escape

File Types

Extension Description
.gb Game Boy ROM
.gbc Game Boy Color ROM
.sav Battery-backed save file (created automatically)

Compatibility

Tested Games

The emulator aims to be compatible with most commercial Game Boy and Game Boy Color games. Compatibility can be validated using test ROMs:

  • blargg's cpu_instrs: CPU instruction tests
  • blargg's instr_timing: Instruction timing tests
  • mooneye-gb: Timer accuracy tests

Project Structure

zig-gbc/
├── build.zig              # Build configuration
├── build.zig.zon          # Dependencies
├── src/
│   ├── main.zig           # Entry point, SDL event loop
│   ├── gameboy.zig        # Top-level orchestrator
│   ├── core/              # CPU implementation
│   │   ├── cpu.zig        # SM83 CPU core
│   │   ├── opcodes.zig    # All instructions (main + CB)
│   │   └── registers.zig  # CPU register file
│   ├── memory/            # Memory subsystem
│   │   ├── mmu.zig        # Memory Management Unit
│   │   ├── io_registers.zig # Central I/O state (KEY FILE)
│   │   └── cartridge.zig  # ROM/MBC handling
│   ├── graphics/          # Graphics
│   │   └── ppu.zig        # PPU with variable Mode 3 timing
│   ├── audio/             # Audio
│   │   ├── apu.zig        # Audio Processing Unit
│   │   └── channels.zig   # Sound channels 1-4
│   ├── peripherals/       # I/O devices
│   │   ├── timer.zig      # DIV/TIMA with falling-edge
│   │   └── joypad.zig     # Input handling
│   └── platform/          # Frontend
│       └── sdl.zig        # SDL3 wrapper
└── tests/
    └── cpu_tests.zig      # CPU unit tests

Key Files

  • io_registers.zig: Central I/O state - single source of truth for all hardware registers
  • gameboy.zig: Factory function creates fully-initialized emulator with all components wired
  • mmu.zig: Memory routing with typed references to PPU, APU, Cartridge
  • ppu.zig: Variable Mode 3 timing calculated per-scanline

Technical Details

Memory Map

Address Range Description
0x0000-0x3FFF ROM Bank 0 (16 KB)
0x4000-0x7FFF ROM Bank N (switchable, 16 KB)
0x8000-0x9FFF VRAM (8 KB, 2 banks on GBC)
0xA000-0xBFFF External RAM (8 KB)
0xC000-0xCFFF WRAM Bank 0 (4 KB)
0xD000-0xDFFF WRAM Bank 1-7 (4 KB, switchable on GBC)
0xE000-0xFDFF Echo RAM
0xFE00-0xFE9F OAM (160 bytes)
0xFEA0-0xFEFF Unusable
0xFF00-0xFF7F I/O Registers
0xFF80-0xFFFE HRAM (127 bytes)
0xFFFF Interrupt Enable

Timing

  • CPU Clock: 4.194304 MHz (DMG) / 8.388608 MHz (GBC double speed)
  • Frame Rate: ~59.7 FPS
  • Dots per Scanline: 456
  • Scanlines per Frame: 154 (144 visible + 10 V-blank)
  • Mode 3 Duration: 172-289 dots (variable based on sprites/scroll/window)

PPU Mode Timing

Mode Duration Description
Mode 2 (OAM Scan) 80 dots Scanning OAM for sprites
Mode 3 (Drawing) 172-289 dots Rendering pixels to LCD
Mode 0 (H-Blank) 87-204 dots Horizontal blanking
Mode 1 (V-Blank) 4560 dots Vertical blanking (10 lines)

Limitations

Not Implemented

  • Save States: Save/load state functionality
  • Super Game Boy (SGB): SGB borders and enhanced features
  • Game Boy Camera/Printer: Peripherals not emulated
  • Link Cable: Serial communication not functional
  • MBC6, MBC7, HuC1, HuC3: Uncommon memory bank controllers
  • Rumble: MBC5 rumble motor feature

Accuracy Limitations

  • Scanline-based rendering: Not pixel-accurate; some mid-scanline effects may not work
  • Audio timing: Minor timing differences may cause subtle audio artifacts
  • STOP instruction: Speed switching works, but some edge cases may differ from hardware

License

This project is provided as-is for educational purposes.

References