{"id":21988986,"url":"https://github.com/duysqubix/gobc","last_synced_at":"2026-05-18T04:16:48.844Z","repository":{"id":188134350,"uuid":"677509743","full_name":"duysqubix/gobc","owner":"duysqubix","description":null,"archived":false,"fork":false,"pushed_at":"2024-08-18T04:55:45.000Z","size":88462,"stargazers_count":95,"open_issues_count":7,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-07T14:08:48.323Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/duysqubix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-11T18:57:54.000Z","updated_at":"2025-02-07T11:13:36.000Z","dependencies_parsed_at":"2024-12-20T07:05:33.731Z","dependency_job_id":"043df991-c9a6-4897-9b2c-e66dade66f41","html_url":"https://github.com/duysqubix/gobc","commit_stats":null,"previous_names":["duysqubix/gobc"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duysqubix%2Fgobc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duysqubix%2Fgobc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duysqubix%2Fgobc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duysqubix%2Fgobc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duysqubix","download_url":"https://codeload.github.com/duysqubix/gobc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238856603,"owners_count":19542246,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T19:27:10.201Z","updated_at":"2026-05-18T04:16:48.836Z","avatar_url":"https://github.com/duysqubix.png","language":"Go","funding_links":[],"categories":["Handheld game console emulators","Nintendo Game Boy/Game Boy Color"],"sub_categories":["Nintendo Handhelds"],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"docs/gobc_logo.png\" width=\"480\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/duysqubix/gobc/actions/workflows/go.yml\"\u003e\u003cimg src=\"https://github.com/duysqubix/gobc/actions/workflows/go.yml/badge.svg\" alt=\"Build Status\"\u003e\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/duysqubix/gobc\"\u003e\u003cimg src=\"https://codecov.io/gh/duysqubix/gobc/branch/master/graph/badge.svg\" alt=\"Coverage\"\u003e\u003c/a\u003e\n\u003ca href=\"https://goreportcard.com/report/github.com/duysqubix/gobc\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/duysqubix/gobc\" alt=\"Go Report Card\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pkg.go.dev/github.com/duysqubix/gobc\"\u003e\u003cimg src=\"https://pkg.go.dev/badge/github.com/duysqubix/gobc.svg\" alt=\"Go Reference\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/duysqubix/gobc/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/duysqubix/gobc\" alt=\"Latest Release\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n**gobc** is a Game Boy / Game Boy Color emulator written in Go. Standing on the\nshoulders of giants — Pan Docs, SameBoy, PyBoy, mooneye, gbdev — it aims to be\na fast, hackable, hardware-accurate emulator with a real focus on passing the\ncanonical test suites (Blargg, Mooneye) rather than just \"running games\".\n\n[**📋 Tests passing →**](TESTS.md) \u0026nbsp;\u0026nbsp;\n[**🎵 Audio setup →**](docs/audio_tests.md) \u0026nbsp;\u0026nbsp;\n[**💬 Discord →**](https://discord.gg/EVCX5X3A) \u0026nbsp;\u0026nbsp;\n[**📦 Latest release →**](https://github.com/duysqubix/gobc/releases/latest)\n\n\u003c!---\nGenerate GIF with the layout and captions\n--\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\n        \u003cimg src=\"docs/crystal.gif\" width=\"200\"\u003e\n      \u003c/td\u003e\n      \u003ctd align=\"center\"\u003e\n        \u003cimg src=\"docs/blue.gif\" width=\"200\"\u003e\n      \u003c/td\u003e\n            \u003ctd align=\"center\"\u003e\n        \u003cimg src=\"docs/tetris.gif\" width=\"200\"\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n      \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\n        \u003cimg src=\"docs/dr_mario.png\" width=\"200\"\u003e\n      \u003c/td\u003e\n          \u003ctd align=\"center\"\u003e\n        \u003cimg src=\"docs/bgb.gif\" width=\"200\"\u003e\n      \u003c/td\u003e\n          \u003ctd align=\"center\"\u003e\n        \u003cimg src=\"docs/loz.gif\" width=\"200\"\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Feature matrix\n\nLegend: ✅ = full hardware accuracy (regression-guarded in CI) \u0026nbsp;·\u0026nbsp; 🟡 = partial / WIP \u0026nbsp;·\u0026nbsp; ❌ = not started\n\n| Subsystem | Status | Notes |\n|---|:-:|---|\n| 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](https://github.com/duysqubix/gobc/issues/18). |\n| Interrupts | ✅ | EI 1-instruction delay, HALT bug, peripherals ticked during ISR. Passes `interrupt_time` and `halt_bug`. |\n| Joypad | ✅ | All 8 buttons, D-pad + face buttons + Start/Select. |\n| Timers (DIV/TIMA) | ✅ | Including CGB double-speed scaling. |\n| 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](https://github.com/duysqubix/gobc/issues/19). |\n| **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`](docs/audio_tests.md). |\n| CGB mode | ✅ | BG / OBJ palette RAM, VRAM bank switching, double-speed switching via STOP + KEY1, APU scaling. |\n| Serial port | ❌ | Output captured for test ROMs; full serial transfers / link cable: [#11](https://github.com/duysqubix/gobc/issues/11). |\n| Save / load states | ✅ | Snapshot the full Motherboard (CPU + memory + cart + APU + PPU). |\n| Debugger | ✅ | VRAM viewer, tile data + tilemap, CPU registers, IO regs, cart RAM browser, breakpoints, single-step. |\n| Shaders | ❌ | CRT / LCD / GBC palette post-processing: [#17](https://github.com/duysqubix/gobc/issues/17). |\n\n### Cartridge MBC support\n\n| MBC | Status | Issue |\n|---|:-:|---|\n| ROM_ONLY (no MBC) | ✅ | — |\n| MBC1 (+ RAM + BATTERY) | ✅ | — |\n| **MBC2** | ❌ | [#3](https://github.com/duysqubix/gobc/issues/3) |\n| MBC3 (+ RTC + RAM + BATTERY) | ✅ | — |\n| MBC5 (+ RAM + BATTERY + RUMBLE) | ✅ | — |\n| **MMM01** (multi-game compilations) | ❌ | [#14](https://github.com/duysqubix/gobc/issues/14) |\n| **HuC1** (Hudson IR) | ❌ | [#12](https://github.com/duysqubix/gobc/issues/12) |\n| **HuC3** (Hudson IR + RTC + speaker) | ❌ | [#13](https://github.com/duysqubix/gobc/issues/13) |\n| **Pocket Camera** ($FC) | ❌ | [#15](https://github.com/duysqubix/gobc/issues/15) |\n| **Bandai TAMA5** ($FD) | ❌ | [#16](https://github.com/duysqubix/gobc/issues/16) |\n\n### Blargg test ROM scorecard (regression-guarded in CI)\n\n| Suite | gobc v2.2 | Notes |\n|---|:-:|---|\n| `cpu_instrs` | ✅ PASS | All 11 sub-tests. |\n| `instr_timing` | ✅ PASS | |\n| `halt_bug` | ✅ PASS | |\n| `interrupt_time` | ✅ PASS | Both DMG and CGB double-speed iterations. |\n| `dmg_sound` | ✅ **12/12** | All 6 DMG quirks (length-clock-on-trigger, NR41 power-off, wave RAM bus contention, wave retrigger corruption, etc.). |\n| `cgb_sound` | ✅ **12/12** | DMG-vs-CGB-aware quirks; same code paths gated on `mb.Cgb`. |\n| `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](https://github.com/duysqubix/gobc/issues/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. |\n| `mem_timing` / `mem_timing-2` | ❌ | Requires sub-instruction T-cycle accurate CPU. Tracked in [#18](https://github.com/duysqubix/gobc/issues/18). |\n\n## Installing\n\nYou need:\n- [Go 1.26+](https://golang.org/doc/install)\n- [OpenGL + GLFW](https://github.com/gopxl/pixel#requirements) (`libgl1-mesa-dev xorg-dev` on Debian/Ubuntu)\n- Audio (optional): on WSL2, follow the one-time setup in [`docs/audio_tests.md`](docs/audio_tests.md#wsl2-setup-one-time)\n\n```bash\n# Option 1 — pre-built release binary (Linux x86_64)\ncurl -L https://github.com/duysqubix/gobc/releases/latest/download/gobc-v2.0-linux-x86_64 -o gobc\nchmod +x gobc\n\n# Option 2 — go install\ngo install github.com/duysqubix/gobc/cmd/gobc@latest\n\n# Option 3 — build from source\ngit clone https://github.com/duysqubix/gobc \u0026\u0026 cd gobc\ncargo install just                # or: brew install just / apt install just\njust bootstrap                    # installs Go (if missing) + gopls + staticcheck + dlv + goimports\njust install-hooks                # wires the repo pre-commit hook (gofmt + vet + staticcheck)\njust build                        # vet + race-test + compile to bin/gobc + bin/cartdump\njust build-release                # stripped (-trimpath -s -w) release binary\n```\n\nThe project uses [`just`](https://github.com/casey/just) as its task runner. Run `just` with no\narguments to list every recipe. Useful environment overrides:\n\n| Env | Effect |\n|---|---|\n| `GO_VERSION=1.27.0 just bootstrap` | Pin a specific Go release. |\n| `GO_INSTALL_DIR=$HOME/.local just bootstrap` | Install Go to a user-local prefix (no sudo). |\n| `COVER_MIN=70 just test-cover-check` | Fail if line coverage drops below 70 %. |\n\n## Usage\n\n`gobc` exposes two subcommands plus a shorthand:\n\n| Command | Purpose |\n|---|---|\n| `gobc run ROM_File [options]` | Boot the emulator and run a ROM. |\n| `gobc cartdump ROM_File [options]` | Dump cartridge header (and optional opcode disassembly). |\n| `gobc ROM_File [options]` | Shorthand for `gobc run`. |\n\n```bash\n# Run a ROM\ngobc run roms/cpu_instrs.gb\ngobc run roms/zelda.gb              --debug --breakpoints 0x100,0x200,0x300\ngobc run roms/pokemon.gb            --force-cgb        # force CGB on a DMG ROM\ngobc run roms/blargg.gb             --no-gui           # headless (CI / test ROMs)\nLOG_LEVEL=debug gobc run roms/zelda.gb\n\n# Audio (new in v2.0)\ngobc run roms/crystal.gbc           --audio-rate 32000 # match host throughput on slow CPUs\ngobc run roms/crystal.gbc           --audio-smooth     # calibrate to host (5% pitch trade-off)\ngobc run roms/crystal.gbc           --no-audio         # silent run\n\n# Inspect a cartridge\ngobc cartdump roms/pokemon.gb                                     # writes cartdump.txt\ngobc cartdump --raw roms/pokemon.gb                               # raw header to stdout\ngobc cartdump --instruction-set --include-nop -o dump.txt roms/pokemon.gb\n```\n\nRun `gobc --help` for the full flag reference and `gobc \u003ccommand\u003e --help` for per-subcommand help.\n\n## Key bindings\n\n### Main window\n\n| Key | Action |\n|---|---|\n| `F1` | Toggle gridlines |\n| `F2` | Toggle debug viewer windows (VRAM / Memory / Cart / CPU / IO) |\n| `F3` | Cycle DMG palette |\n| `F4` | Save cartridge SRAM to `\u003crom\u003e.sav` |\n| `F5` | Save state to `\u003crom\u003e.state` |\n| `F6` | Load state from `\u003crom\u003e.state` |\n| `A` | Game Boy B button |\n| `S` | Game Boy A button |\n| `Enter` | Start |\n| `Shift` | Select |\n| Arrow keys | D-pad |\n| `Space` *(debug on)* | Pause / resume emulation |\n| `N` *(debug on)* | Step **N** CPU cycles |\n| `M` / `B` *(debug on)* | Increase / decrease cycles-per-frame 10× |\n| `F` *(debug on)* | Step one frame |\n\n### Debug viewers\n\n| Window | Keys |\n|---|---|\n| VRAM | `T` toggle tile addressing · `B` toggle tilemap addressing · `G` toggle grid · `V` toggle VRAM bank 0/1 |\n| Memory | Arrow keys page/scroll · mouse wheel scrolls |\n| Cart | Arrow keys page/scroll · `[` / `]` switch RAM bank |\n\n## Testing\n\nUnit tests use the stdlib `testing` package + `testify`. ROM integration tests under\n`default_rom/` run `gobc --no-gui` against Blargg ROMs and grep the serial output (or\ncart-RAM `.sav` for the newer `dmg_sound`/`cgb_sound`/`oam_bug` suites).\n\n```bash\njust test                            # go test -race ./...\njust test-cover                      # writes coverage.out + summary\njust test-cover-html                 # generates coverage.html\nCOVER_MIN=70 just test-cover-check   # fail if coverage drops below threshold\njust bench                           # benchmarks\njust test-rom-audio                  # runs the full 12-ROM dmg_sound matrix\n```\n\nEvery push runs the full test pipeline + ROM integration suite on GitHub Actions; coverage\nis uploaded to [Codecov](https://codecov.io/gh/duysqubix/gobc).\n\n## Known game bugs\n\n| Game | Symptom | Issue |\n|---|---|---|\n| Link's Awakening (DMG) | Main menu doesn't render | [#5](https://github.com/duysqubix/gobc/issues/5) |\n| Pokémon Crystal | Battle scene doesn't animate | [#4](https://github.com/duysqubix/gobc/issues/4) |\n| Pokémon Crystal | Character sprite split entering battle | [#4](https://github.com/duysqubix/gobc/issues/4) |\n\n## Project layout\n\n```\ngobc/\n├── cmd/\n│   ├── gobc/             # main binary; urfave/cli/v2 app with run + cartdump subcommands\n│   └── cartdump/         # standalone cart-dump binary (same logic as gobc cartdump)\n├── internal/\n│   ├── motherboard/      # CPU + opcodes + memory + timer + interrupts + PPU + APU\n│   ├── cartridge/        # header parser + ROM_ONLY / MBC1 / MBC3+RTC / MBC5\n│   ├── windows/          # Pixel/GLFW GUI: 1 main + 5 viewer windows\n│   ├── bootrom/          # DMG + CGB boot ROMs as hex blobs\n│   └── root.go           # shared utilities: Logger, constants, bit-ops, state save/load\n├── default_rom/          # Blargg + Mooneye test ROMs\n├── docs/                 # audio_tests.md and project docs\n├── .githooks/            # repo-tracked pre-commit hook\n├── .github/workflows/    # CI: unit tests + coverage + ROM integration\n└── justfile              # task runner (run `just` to list recipes)\n```\n\nEach subdirectory has its own `AGENTS.md` with conventions, anti-patterns, and quirks. Start\nwith [`AGENTS.md`](AGENTS.md) (root) before contributing.\n\n## Contributing\n\nThe known problems are tracked in the Issues tab — grab anything that looks interesting!\nFor substantial new features, open an issue first to align on the approach. We follow the\nexisting per-package conventions (see each subdirectory's `AGENTS.md`) and the pre-commit\nhook enforces `gofmt`, `vet`, and `staticcheck`. Tests must stay green.\n\n### Contributors\n\n- Duan Uys — [@duysqubix](https://github.com/duysqubix)\n\n## References\n\n- [Pan Docs](https://gbdev.io/pandocs/About.html) — canonical Game Boy hardware reference\n- [GBEDG](https://hacktix.github.io/GBEDG/) — Game Boy emulator development guide\n- [pastraiser opcode table](https://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html)\n- [SameBoy](https://github.com/LIJI32/SameBoy) — cycle-accurate reference emulator (consulted heavily for v2.0 APU + interrupt timing)\n- [PyBoy](https://github.com/Baekalfen/PyBoy) — Python reference + huge inspiration; the v2.0 adaptive frame limiter is adapted from PyBoy's\n- [Test ROMs Archive](https://gbdev.gg8.se/wiki/articles/Test_ROMs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduysqubix%2Fgobc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduysqubix%2Fgobc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduysqubix%2Fgobc/lists"}