Skip to content

duysqubix/gobc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

260 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Build Status Coverage Go Report Card Go Reference Latest Release

πŸ¦€ Curious what happens when you hand the same project to an AI team? Check out rubc β€” a sister Game Boy / Game Boy Color emulator written in Rust, built almost entirely by an AI as an experiment. It went a good bit further on hardware accuracy than this one did. gobc is the hand-written, human original that started it all.

gobc is a Game Boy / Game Boy Color emulator written in Go. Standing on the shoulders of giants β€” Pan Docs, SameBoy, PyBoy, mooneye, gbdev β€” it aims to be a fast, hackable, hardware-accurate emulator with a real focus on passing the canonical test suites (Blargg, Mooneye) rather than just "running games".

πŸ“‹ Tests passing β†’ Β Β  🎡 Audio setup β†’ Β Β  πŸ’¬ Discord β†’ Β Β  πŸ“¦ Latest release β†’

Feature matrix

Legend: βœ… = full hardware accuracy (regression-guarded in CI) Β Β·Β  🟑 = partial / WIP Β Β·Β  ❌ = not started

Subsystem Status Notes
SM83 CPU βœ… All 245 implemented opcodes + CB-prefix; passes Blargg cpu_instrs 11/11 + instr_timing. Atomic-instruction model β€” sub-instruction T-cycle timing is #18.
Interrupts βœ… EI 1-instruction delay, HALT bug, peripherals ticked during ISR. Passes interrupt_time and halt_bug.
Joypad βœ… All 8 buttons, D-pad + face buttons + Start/Select.
Timers (DIV/TIMA) βœ… Including CGB double-speed scaling.
LCD / PPU βœ… Tile + sprite render, STAT interrupts, mode 0/1/2/3 transitions, BG-OBJ priority. Pixel-FIFO accuracy and cycle-accurate mode 2 timing tracked in #19.
APU (sound) βœ… NEW in v2.0. Full 4-channel emulation on gopxl/beep/v2. Square Γ— 2 with NR10 sweep, wave with 32-sample wave RAM, noise with 7/15-bit LFSR, frame sequencer at 512 Hz. Passes all 12/12 Blargg dmg_sound AND all 12/12 cgb_sound. Setup guide: docs/audio_tests.md.
CGB mode βœ… BG / OBJ palette RAM, VRAM bank switching, double-speed switching via STOP + KEY1, APU scaling.
Serial port ❌ Output captured for test ROMs; full serial transfers / link cable: #11.
Save / load states βœ… Snapshot the full Motherboard (CPU + memory + cart + APU + PPU).
Debugger βœ… VRAM viewer, tile data + tilemap, CPU registers, IO regs, cart RAM browser, breakpoints, single-step.
Shaders ❌ CRT / LCD / GBC palette post-processing: #17.

Cartridge MBC support

MBC Status Issue
ROM_ONLY (no MBC) βœ… β€”
MBC1 (+ RAM + BATTERY) βœ… β€”
MBC2 ❌ #3
MBC3 (+ RTC + RAM + BATTERY) βœ… β€”
MBC5 (+ RAM + BATTERY + RUMBLE) βœ… β€”
MMM01 (multi-game compilations) ❌ #14
HuC1 (Hudson IR) ❌ #12
HuC3 (Hudson IR + RTC + speaker) ❌ #13
Pocket Camera ($FC) ❌ #15
Bandai TAMA5 ($FD) ❌ #16

Blargg test ROM scorecard (regression-guarded in CI)

Suite gobc v2.2 Notes
cpu_instrs βœ… PASS All 11 sub-tests.
instr_timing βœ… PASS
halt_bug βœ… PASS
interrupt_time βœ… PASS Both DMG and CGB double-speed iterations.
dmg_sound βœ… 12/12 All 6 DMG quirks (length-clock-on-trigger, NR41 power-off, wave RAM bus contention, wave retrigger corruption, etc.).
cgb_sound βœ… 12/12 DMG-vs-CGB-aware quirks; same code paths gated on mb.Cgb.
oam_bug 🟑 6/8 with --force-dmg Sub-tests 2–7 PASS. Sub-test 1 (LCD-on cycle sync) + sub-test 8 (POP CRC under cumulative delay-loop corruption) tracked in #19. Use gobc --no-gui --force-dmg oam_bug.gb β€” the test ROM's header is CGB-flagged but it exercises DMG-only hardware quirks.
mem_timing / mem_timing-2 ❌ Requires sub-instruction T-cycle accurate CPU. Tracked in #18.

Installing

You need:

# Option 1 β€” pre-built release binary (Linux x86_64)
curl -L https://github.com/duysqubix/gobc/releases/latest/download/gobc-v2.0-linux-x86_64 -o gobc
chmod +x gobc

# Option 2 β€” go install
go install github.com/duysqubix/gobc/cmd/gobc@latest

# Option 3 β€” build from source
git clone https://github.com/duysqubix/gobc && cd gobc
cargo install just                # or: brew install just / apt install just
just bootstrap                    # installs Go (if missing) + gopls + staticcheck + dlv + goimports
just install-hooks                # wires the repo pre-commit hook (gofmt + vet + staticcheck)
just build                        # vet + race-test + compile to bin/gobc + bin/cartdump
just build-release                # stripped (-trimpath -s -w) release binary

The project uses just as its task runner. Run just with no arguments to list every recipe. Useful environment overrides:

Env Effect
GO_VERSION=1.27.0 just bootstrap Pin a specific Go release.
GO_INSTALL_DIR=$HOME/.local just bootstrap Install Go to a user-local prefix (no sudo).
COVER_MIN=70 just test-cover-check Fail if line coverage drops below 70 %.

Usage

gobc exposes two subcommands plus a shorthand:

Command Purpose
gobc run ROM_File [options] Boot the emulator and run a ROM.
gobc cartdump ROM_File [options] Dump cartridge header (and optional opcode disassembly).
gobc ROM_File [options] Shorthand for gobc run.
# Run a ROM
gobc run roms/cpu_instrs.gb
gobc run roms/zelda.gb              --debug --breakpoints 0x100,0x200,0x300
gobc run roms/pokemon.gb            --force-cgb        # force CGB on a DMG ROM
gobc run roms/blargg.gb             --no-gui           # headless (CI / test ROMs)
LOG_LEVEL=debug gobc run roms/zelda.gb

# Audio (new in v2.0)
gobc run roms/crystal.gbc           --audio-rate 32000 # match host throughput on slow CPUs
gobc run roms/crystal.gbc           --audio-smooth     # calibrate to host (5% pitch trade-off)
gobc run roms/crystal.gbc           --no-audio         # silent run

# Inspect a cartridge
gobc cartdump roms/pokemon.gb                                     # writes cartdump.txt
gobc cartdump --raw roms/pokemon.gb                               # raw header to stdout
gobc cartdump --instruction-set --include-nop -o dump.txt roms/pokemon.gb

Run gobc --help for the full flag reference and gobc <command> --help for per-subcommand help.

Key bindings

Main window

Key Action
F1 Toggle gridlines
F2 Toggle debug viewer windows (VRAM / Memory / Cart / CPU / IO)
F3 Cycle DMG palette
F4 Save cartridge SRAM to <rom>.sav
F5 Save state to <rom>.state
F6 Load state from <rom>.state
A Game Boy B button
S Game Boy A button
Enter Start
Shift Select
Arrow keys D-pad
Space (debug on) Pause / resume emulation
N (debug on) Step N CPU cycles
M / B (debug on) Increase / decrease cycles-per-frame 10Γ—
F (debug on) Step one frame

Debug viewers

Window Keys
VRAM T toggle tile addressing Β· B toggle tilemap addressing Β· G toggle grid Β· V toggle VRAM bank 0/1
Memory Arrow keys page/scroll Β· mouse wheel scrolls
Cart Arrow keys page/scroll Β· [ / ] switch RAM bank

Testing

Unit tests use the stdlib testing package + testify. ROM integration tests under default_rom/ run gobc --no-gui against Blargg ROMs and grep the serial output (or cart-RAM .sav for the newer dmg_sound/cgb_sound/oam_bug suites).

just test                            # go test -race ./...
just test-cover                      # writes coverage.out + summary
just test-cover-html                 # generates coverage.html
COVER_MIN=70 just test-cover-check   # fail if coverage drops below threshold
just bench                           # benchmarks
just test-rom-audio                  # runs the full 12-ROM dmg_sound matrix

Every push runs the full test pipeline + ROM integration suite on GitHub Actions; coverage is uploaded to Codecov.

Known game bugs

Game Symptom Issue
Link's Awakening (DMG) Main menu doesn't render #5
PokΓ©mon Crystal Battle scene doesn't animate #4
PokΓ©mon Crystal Character sprite split entering battle #4

Project layout

gobc/
β”œβ”€β”€ cmd/
β”‚   β”œβ”€β”€ gobc/             # main binary; urfave/cli/v2 app with run + cartdump subcommands
β”‚   └── cartdump/         # standalone cart-dump binary (same logic as gobc cartdump)
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ motherboard/      # CPU + opcodes + memory + timer + interrupts + PPU + APU
β”‚   β”œβ”€β”€ cartridge/        # header parser + ROM_ONLY / MBC1 / MBC3+RTC / MBC5
β”‚   β”œβ”€β”€ windows/          # Pixel/GLFW GUI: 1 main + 5 viewer windows
β”‚   β”œβ”€β”€ bootrom/          # DMG + CGB boot ROMs as hex blobs
β”‚   └── root.go           # shared utilities: Logger, constants, bit-ops, state save/load
β”œβ”€β”€ default_rom/          # Blargg + Mooneye test ROMs
β”œβ”€β”€ docs/                 # audio_tests.md and project docs
β”œβ”€β”€ .githooks/            # repo-tracked pre-commit hook
β”œβ”€β”€ .github/workflows/    # CI: unit tests + coverage + ROM integration
└── justfile              # task runner (run `just` to list recipes)

Each subdirectory has its own AGENTS.md with conventions, anti-patterns, and quirks. Start with AGENTS.md (root) before contributing.

Contributing

The known problems are tracked in the Issues tab β€” grab anything that looks interesting! For substantial new features, open an issue first to align on the approach. We follow the existing per-package conventions (see each subdirectory's AGENTS.md) and the pre-commit hook enforces gofmt, vet, and staticcheck. Tests must stay green.

Contributors

References

  • Pan Docs β€” canonical Game Boy hardware reference
  • GBEDG β€” Game Boy emulator development guide
  • pastraiser opcode table
  • SameBoy β€” cycle-accurate reference emulator (consulted heavily for v2.0 APU + interrupt timing)
  • PyBoy β€” Python reference + huge inspiration; the v2.0 adaptive frame limiter is adapted from PyBoy's
  • Test ROMs Archive

About

No description, website, or topics provided.

Resources

License

Stars

94 stars

Watchers

2 watching

Forks

Packages

 
 
 

Contributors

Languages