binjgb emulates the Game Boy in C and compiles the same core to WebAssembly
Gameboy emulator implemented in C, that also runs in the browser
At a glance
- What is it?
- binjgb is a small C emulator for Game Boy, Game Boy Color and Super Game Boy titles that builds a native SDL2 binary and a WebAssembly module from one source tree. Its rewind buffer, cycle accurate timing and hash based test harness make it a researcher's tool rather than a polished player, and the last tagged release dates from 2021.
- Who is it for?
- binjgb suits an engineer who wants a readable C emulator to read, extend or embed, and who needs the same core to run in a browser page, since the WebAssembly build and the configurable simple.js page cover that case directly.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 28 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One C core, two targets, native and WebAssembly
binjgb is a Game Boy emulator written in C, and the interesting decision is not the console support but the deployment shape. The same source tree produces a native desktop binary linked against SDL2 and a WebAssembly module that runs in a browser. The project ships both the native build and a hosted demo page at binji.github.io/binjgb, and the README documents how to copy a small set of files onto your own server.
For a browser build you need an Emscripten toolchain, and the Makefile expects a symlink to it in the emscripten directory:
$ ln -s ${PATH_TO_EMSCRIPTEN} emscripten
$ make wasmThe alternative is to point the build at Emscripten from the command line instead:
$ make wasm EMSCRIPTEN_CMAKE="/path/to/Emscripten.cmake"That build target exists because the Makefile models Debug, Release, a plain JavaScript Emscripten build and a WebAssembly build, each in its own out/ subdirectory with warnings treated as errors. It is a build system set up by someone who expects the project to be compiled, not just downloaded.
Rewind and seek, because the emulator keeps state dumps
The feature list is where binjgb distinguishes itself from a minimal emulator. It supports fast-forward, pause, stepping a single frame, and rewinding to a specific cycle. Each of those needs history, which is where the rewind configuration comes in.
The INI file controls this. binjgb reads binjgb.ini on startup, and the rewind keys are explicit about the trade-off:
# The number of video frames to display before storing a full dump of
# the emulator state in the rewind buffer. Probably best to leave this
# alone
rewind-frames-per-base-state=45
# The number of megabytes to allocate to the rewind buffer.
# lower=less memory usage, less rewind time
# higher=more memory usage, more rewind time
rewind-buffer-capacity-megabytes=32
# The speed at which to rewind the game, as a scale.
# 1=rewind at 1x
# 2=rewind at 2x
# etc.
rewind-scale=1.5So the default configuration reserves 32 megabytes for rewind and stores a full emulator state every 45 frames. That is the real cost of the feature, and it is configurable rather than hidden. The INI file also carries audio settings, with a note that lower audio frame counts mean better latency and more pops and clicks, a built-in palette index, a force-dmg switch for running a colour cartridge in original Game Boy mode, and a render scale of 4 applied to the emulator window at startup.
The same INI can autoload a ROM at startup, which matters when you are running the emulator unattended in a test harness.
Cycle accuracy and a hash based Python test harness
binjgb claims cycle accurate emulation that passes many timing tests, and the way that claim is checked is more interesting than the claim itself. The README lists a convenient Python test harness using hashes to validate, and the repository contains a test directory, a scripts directory and a test_results.md file.
The design implied by that is that each test ROM produces a deterministic output hash, so a change to the emulator's timing or PPU behaviour changes the hash and the harness fails. That is a regression approach, and it is the reason a project can honestly say it passes many timing tests without publishing a cycle count table.
The same infrastructure explains the rewind and step features. Stepping one frame is only meaningful if a frame boundary is a well defined point in the emulation, and rewinding to a specific cycle only makes sense if the emulator state at any cycle can be captured and restored. The author states that the emulator passes many timing tests, and the test_results.md file in the repository is the record of that effort.
For anyone modifying the core, that harness is the asset. Without it you are changing timing code with no signal about whether the change was correct.
Bugs in the debugging tools, not just the games
The emulator ships a separate debugger binary with its own visualisations: an object window, a map window, a tile data window and a breakpoint view. It is marked work in progress in the feature list, and the build section notes that the debugger uses dear imgui, which is pulled in as a git submodule.
That submodule detail is why the clone instruction is recursive.
$ git clone --recursive https://github.com/binji/binjgbIf you have already cloned without initialising submodules, the README gives the recovery command:
$ git submodule update --initThe debugger is a separate executable, listed alongside the main one in the running section, and it is the reason the project needs imgui in the tree at all. The other debugger features are about inspecting the machine rather than playing it: object windows for sprites, a map view of the tile grid, tile data and breakpoints.
The other debugging aids are runtime toggles rather than separate views. Audio channels 1 through 4 can be disabled individually, the background, window and object layers can each be switched off, and the main key table maps F6 to save state, F9 to load state, N to step one frame, Space to pause, Backspace to rewind, Lshift to fast-forward, and Esc to quit.
MBC support and a palette that borrows from other emulators
Cartridge support covers MBC1, MBC1M, MMM01, MBC2, MBC3, MBC5 and HuC1, with battery backup save and load, and the ability to save and load emulator state to a file. Colour and Super Game Boy support exist as well, but the author's own wording is worth repeating in spirit: CGB support is hacky but passable, and Super GB support is mostly there.
The web build is configured through simple.js, and the configuration table is unusually well documented. ROM_FILENAME points at your .gb or .gbc file, ENABLE_REWIND toggles rewinding with the backspace key, ENABLE_PAUSE toggles the space bar, ENABLE_SWITCH_PALETTES toggles the bracket keys, and OSGP_DEADZONE sets the on-screen gamepad deadzone as a decimal between 0 and 1. The emulator also shows an on-screen gamepad when the device reports touch events, which is what makes the hosted page usable on a phone.
Two palette settings show the project's lineage. CGB_COLOR_CURVE tints the colour output, with option 0 meaning no tint, option 1 using Sameboy's "Emulate Hardware" colors and option 2 using Gambatte and Gameboy Online colors. DEFAULT_PALETTE_IDX selects a default from the built-in PALETTES array, whose entries are indices between 0 and 83.
That reference to Sameboy and Gambatte is the clearest signal of where the alternatives sit. binjgb does not try to be the most accurate emulator in every respect. It tries to be a readable C implementation that happens to be accurate on timing, rewindable, and embeddable in a web page.
Building from source on Linux, macOS and Windows
The native build needs CMake and SDL2. On Linux and macOS a plain make is enough, because the Makefile shells out to CMake and drops the result in bin/:
$ make
$ bin/binjgb foo.gbYou can also drive CMake directly:
$ mkdir build
$ cd build
$ cmake ..
$ makeOn Windows the README expects you to point CMake at an SDL2 directory and pick a generator:
> mkdir build
> cd build
> cmake .. -G "Visual Studio 15 2017" -DSDL2_ROOT_DIR="C:\path\to\SDL\"After that you load the solution into Visual Studio and build, and the README notes you should build the INSTALL target so the executables land in the bin directory. That note matters because the runtime invocation expects a specific layout, with the emulator and the debugger as separate executables in bin/.
One recurring papercut is documented: if you change the build configuration, for example after updating submodules, you may need to run CMake again, and the simplest fix is to remove the out directory and rebuild.
$ rm -rf out/
$ makeRepository activity since the last 0.1.x tag
The repository is not archived, and the last push was on 2026-09-25. The release tags tell a different story: v0.1.9 and v0.1.10 both date from 2021-04-04, and v0.1.11 is the most recent listed release at 2021-08-21. So the code has moved for years without a new tag.
That is normal for a project whose main consumption path is a git clone with submodules, and the CI badge in the README points at a GitHub Actions workflow. It does mean there is no versioned artefact to pin: you track main, and you get whatever the tree contains, which for a research tool is usually what you want anyway.
The licence is MIT, which is about as permissive as it gets. The emulator core, the debugger and the web demo can be reused in a closed product without copyleft obligations, provided the copyright notice travels with it.
There is no homepage beyond the hosted demo and no published package index, no API surface to speak of, and no configuration beyond the INI file and the simple.js constants. For a small emulator that is a sensible amount of surface area.
Editorial conclusion
binjgb suits an engineer who wants a readable C emulator to read, extend or embed, and who needs the same core to run in a browser page, since the WebAssembly build and the configurable simple.js page cover that case directly. It does not suit someone wanting a polished consumer emulator with a wide release history, because the last tagged release is v0.1.11 from 2021 while the last push was on 2026-09-25, and the Super GB and CGB support is described by the author as hacky but passable and mostly there. Before adopting it, run make and pass the Python hash harness on your target ROM set, check that CMake and SDL2 are present on your build machine, and read binjgb.ini for the rewind buffer defaults, since those defaults decide how much memory the emulator reserves.
Frequently asked questions
How do I build binjgb on Linux or macOS?
Install CMake and SDL2, then run make, which invokes CMake and puts the binaries in bin/. You can then start the emulator with bin/binjgb followed by the name of a ROM file.
What does the rewind buffer cost in memory in binjgb?
The default configuration allocates 32 megabytes to the rewind buffer and stores a full emulator state every 45 video frames. Both values are set in binjgb.ini, and the file notes that a smaller buffer means less memory use and less rewind time.
Can binjgb run in a web page?
Yes. The README documents copying docs/binjgb.js, docs/binjgb.wasm, docs/simple.html, docs/simple.js and docs/simple.css to your webserver along with your .gb or .gbc file, and simple.html fills the whole page unless you place it in an iframe.
Does binjgb support Game Boy Color and Super Game Boy games?
It supports both, with the author describing CGB support as hacky but passable and Super GB support as mostly there. The colour output can be tinted with the CGB_COLOR_CURVE setting, which offers no tint, Sameboy's "Emulate Hardware" colors, or Gambatte and Gameboy Online colors.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/binji-binjgb)Was this useful?