2026-10-31 13:00:20 -05:00
2026-10-31 13:00:20 -05:00
2026-10-31 13:00:20 -05:00
2026-10-31 13:00:20 -05:00
2026-10-31 13:00:20 -05:00
2026-10-31 13:00:20 -05:00

Daedalian Opus — recompiled to Rust

A proof of concept: the Game Boy game's code, statically translated from the disassembly into Rust, running on a tiny hand-written hardware layer.

cargo run --release

Controls: arrows = D-pad, Z = A, X = B, Enter = Start, Right Shift/Backspace = Select, Esc = quit.

How it works

  • src/game.rs is generated by ../recompile.py from the traced disassembly: every SM83 instruction becomes Rust statements, grouped into basic blocks (match m.pc { 0x0164 => { ... } }), each commented with the original assembly. No SM83 code is decoded at runtime. The game's stack lives in emulated memory because the game manipulates return addresses itself.
  • assets/rom_data.bin is the ROM with every code byte zeroed — only the data (levels, graphics, music, text) is used. The runtime warns if the game ever reads a code byte as data.
  • src/machine.rs: registers/flags/ALU, memory map, joypad, OAM DMA, the vblank interrupt, and a once-per-frame LCD renderer.
  • src/apu.rs: the four sound channels, synthesized in step with the recompiled code; played through cpal.
  • src/main.rs: winit window + pixels framebuffer, 59.73 Hz pacing.

Regenerate after changing the recompiler:

python3 ../recompile.py "../Daedalian Opus (USA).gb" src/game.rs assets/rom_data.bin

Headless testing

cargo run -- --headless OUT_DIR 120 start:3 90 shot:title peek:C0A1:2 goto:44:54

Tokens: N run N frames, BUTTON:N hold a button N frames, shot:NAME save a PNG, peek:ADDR:N print memory, goto:YY:XX steer the puzzle cursor. All audio is written to OUT_DIR/audio.wav.

S
Description
No description provided
Readme
122 KiB
Languages
Rust 100%