gbemurust

API Endpoint
Leaderboard
Loading leaderboard...
README

gbemurust

⭐ OpenReward Environment

Description

gbemurust is a long-horizon coding environment that tasks an agent with building a clean-room Game Boy (DMG) emulator in Rust from scratch. Correctness is graded by running the standard community test-ROM corpus (Blargg, Mooneye, dmg-acid2 / cgb-acid2) against the agent's emulator and checking each suite's canonical pass/fail signal. Reward is the change in how many ROMs a single build of the agent's emulator passes, relative to its previous build, giving a smooth, dense signal over a long-horizon task with a well-defined "done" condition.

This environment is structurally a sibling of sqliterust: same CLIEnvironment + bubblewrap-sandboxed agent binary + idempotent per-record reward, but the artifact is an emulator and the verifier is a custom Rust harness (rom-runner) that drives the agent's clonemboy binary over a stdin/stdout line protocol.

Capabilities

  • Implementing a complete SM83 CPU core (~500 opcodes including the CB-prefixed set)
  • Implementing the DMG memory map, MBC1/MBC2/MBC3 cartridge mappers, interrupt controller, timer/DIV, serial port
  • Implementing a cycle-accurate PPU (4 modes, sprite/window/background priorities, STAT interrupts)
  • Producing output to a contract (stdin/stdout line protocol, defined in build/PROTOCOL.md)
  • Long-horizon multi-turn execution (100s/1000s of tool calls; the typical successful rollout will incrementally pass ROMs as features come online)

Compute Requirements

Agents in gbemurust are given a sandbox with 8GB of RAM and 4 CPUs. Game Boy emulation is single-threaded; the extra cores are useful for parallel cargo build and the agent's own tooling.

License

ORLv1. The bundled test ROMs are redistributed under their respective licenses: Blargg's ROMs are freely redistributable freeware, Mooneye Test Suite is MIT-licensed (Joonas Javanainen), and the acid2 ROMs are by Matt Currie under MIT. The aggregator we clone at build time (c-sp/game-boy-test-roms) is itself MIT-licensed.

Tasks

There is a single training task: gbemurust-train. The task ends when the agent's emulator passes every ROM in the curated corpus. The corpus is 160 ROMs covering CPU correctness (Blargg cpu_instrs, instr_timing, mem_timing, halt_bug, oam_bug), timer / interrupt / OAM-DMA / PPU edge cases (Mooneye acceptance/), and pixel-perfect PPU correctness (dmg-acid2, cgb-acid2).

The agent has a Cargo workspace at /workspace/ pre-initialised as a git repo on main. The test corpus is mounted read-only at /srv/roms/; the agent's shell can read it freely for development. There are no expected outputs there to peek at — they live in the env-server container (see Data), which the sandbox cannot reach. clonemboy additionally runs as an unprivileged user in a jail with no access to /srv/roms/ or /workspace, so it cannot even read the ROM corpus at grade time; ROM bytes arrive on stdin.

Reward Structure

Dense, verifiable, per-ROM:

Reward is the change in how many ROMs a single build of the agent's
clonemboy binary passes, relative to its previous build:

  • +1 for each ROM the current build passes that the previous build did not.
  • −1 for each ROM the previous build passed that the current build now fails,
    so a build that breaks more than it fixes is net negative.
  • 0 for a build that fails to compile, and 0 for a grading run that
    wall-times-out before the whole corpus has run — neither changes the baseline.

finished=True only when one build passes every ROM in the corpus at once.

Because reward tracks the current binary rather than a historical union of
everything ever passed, total trajectory reward telescopes to the pass count of
the build the agent finishes with. Every scored run grades the full corpus,
which is what makes that delta coherent; run_tests(roms=...) only narrows which
failures are listed back to the agent and cannot change the score.

Per-suite pass criteria (chosen by the harness based on the ROM):

  • Blargg (serial mode): the emulator's serial-port buffer ends up containing the literal string "Passed" (Blargg's terminator convention; writes to $FF02 == $81 shift the byte in $FF01 out).
  • Mooneye (mooneye mode): on the first LD B,B instruction (opcode $40, Mooneye's debug-breakpoint convention), registers B,C,D,E,H,L equal the Fibonacci sequence (3, 5, 8, 13, 21, 34).
  • acid2 (framehash mode): after a fixed frame count, the SHA-256 of the 160×144×3 RGB framebuffer (DMG palette 0xFF/0xAA/0x55/0x00, row-major) matches a pre-computed reference hash generated by SameBoy's headless tester. The comparison happens in the env server, which is the only place that holds the hash.

We do not use LLM graders. Every reward decision is a deterministic comparison against a ground-truth signal.

Data

The ROM corpus is fetched at image-build time from c-sp/game-boy-test-roms at a pinned commit. Reference values — framebuffer hashes, serial transcripts and Mooneye register snapshots — are generated once by SameBoy's headless tester (LIJI32/SameBoy, pinned release) via build/gen_expected.Dockerfile, and committed as build/expected/expected_by_rom.jsonl, guaranteeing every answer is bit-identical to a known-good reference emulator.

Grading is server-side, so the two halves live in different places:

  • The agent's sandbox gets INPUTS only — the ROMs under /srv/roms/roms/ and the public manifest (path, mode, cycle/frame budget) at /srv/roms/manifests/. No answers, and SameBoy itself is not present.
  • The env server gets the ANSWERS only, at /srv/roms/expected/expected_by_rom.jsonl, which the sandbox cannot reach. rom-runner in the sandbox is a producer: it runs the agent's emulator and reports raw output, grading nothing.

Both halves come from one generation run, so the ROM set the agent is tested on is exactly the set the server holds answers for. Only ROMs with a reference answer are included, which is why the corpus is 160 rather than the 161 the curation step yields.

Tools

Agents are given the standard CLI toolkit (bash, glob, grep, ls, read, write, edit, multi_edit, todo_write) plus two environment-specific tools:

  • run_tests(roms=None, timeout_s=1800) — builds /workspace/bin/clonemboy, runs anti-cheat + tamper checks, invokes the harness against the full corpus (always, regardless of roms), and returns a bounded failure sample plus the delta reward; every ROM's result is written to /tmp/run_tests/last.tsv (previous build: prev.tsv). roms (a ROM or directory prefix under /srv/roms/roms/) only filters which failures are listed back, so a narrow call cannot change the score.
  • progress() — returns the current pass count and cumulative reward without rebuilding. Emits no reward event (reward=None), since it cannot score anything; run_tests is the only tool that can move the score.

Time Horizon

gbemurust is an open-ended, long-horizon environment. A naive "scaffold to passing" rollout for the very first Blargg CPU subtest typically requires hundreds of tool calls (implementing the SM83 ISA + a minimal MMU + the serial port). Completing the full corpus is a multi-day to multi-week effort for a single agent in the simplest case.

[Statistics on average tool calls here]

[How long for a human to do it?]

Environment Difficulty

[Statistics on environment difficulty here]

Other Environment Requirements

There are no further environment requirements; gbemurust works out of the box with the OpenReward endpoint without any external secrets.

Safety

The agent is sandboxed: network is blocked, and the only registry crates are a fixed vendored set (rom-runner's own dependencies, e.g. sha2, serde, clap; no Game-Boy-emulator crates). "Written in Rust from scratch" is checked at build time: every run_tests does a clean, controlled build (fresh CARGO_HOME and target dir, pinned toolchain, -F unsafe_code, static CRT), and blocks a build whose cargo metadata shows a non-vendored crate, a local build script, proc-macro or links, whose link line adds any library or object, or whose binary links exec/fork/spawn symbols (std::process). The toolchain, the vendored crates, rom-runner and the graded ROMs are fingerprinted at session start; leftover processes are swept before each build. At grade time the binary runs as an unprivileged user in a bubblewrap jail with per-ROM memory and CPU limits; the image ships no interpreter. Every block scores 0 and leaves the baseline unchanged. The redistributed test ROMs are open-source freeware / MIT-licensed and contain no proprietary game code.

Citations

The environment is from the General Reasoning team. The test ROMs are from their respective authors:

@dataset{GRgbemurust,
  author    = {General Reasoning Inc. Team},
  title     = {gbemurust},
  year      = {2026},
  publisher = {OpenReward},
  url       = {https://openreward.ai/GeneralReasoning/gbemurust}
}

@misc{blargg_gb_test_roms,
  author = {Shay Green (blargg)},
  title  = {Game Boy CPU and hardware test ROMs},
  url    = {https://github.com/retrio/gb-test-roms}
}

@misc{mooneye_test_suite,
  author = {Joonas Javanainen},
  title  = {Mooneye Test Suite},
  url    = {https://github.com/Gekkio/mooneye-test-suite}
}

@misc{dmg_acid2,
  author = {Matt Currie},
  title  = {dmg-acid2: Game Boy rendering acid test},
  url    = {https://github.com/mattcurrie/dmg-acid2}
}

@misc{sameboy,
  author = {Lior Halphon},
  title  = {SameBoy},
  url    = {https://github.com/LIJI32/SameBoy}
}
GeneralReasoning/gbemurust | OpenReward