Skip to content

Repository files navigation

SMB

Play it online

Static recompilation of Super Mario Bros. using doppelganger's disassembly

SMB C port running in the browser

Controls

  • D-Pad: WASD
  • B: K
  • A: L
  • start: Enter
  • select: Space
  • z: Save state
  • x: Load state

Checkpoints

  • Static translation of the disassembly to low-level C
  • PPU & APU emulation layers
  • Convert subroutines to C functions
  • Convert most gotos to if statements
  • Remove unused flag updates
  • Replace PPU with direct draw calls
  • Manually rewrite portions of the code to higher level C

Building

Linux & MacOS

  1. Fetch the submodules:
$ git submodule update --init --recursive
  1. Build raylib, follow the instructions here

  2. Run make build in the root folder:

$ make build
  1. Place a legally obtained dump/ROM of SMB called smb.nes in the root folder to extract graphics data from
  2. You can now run ./smb

WebAssembly

  1. Install a recent version of clang with support for the wasm32 target
  2. Run make wasm
  3. Run an HTTP server in the web/ folder and open index.html in your browser
  4. Select a legally obtained dump/ROM of SMB to extract graphics data from

Codegen

The output of the code generator is in the codegen/ folder. To regenerate it:

  1. Install Moonbit:
$ curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s '0.10.9+6e6c44045'
  1. Run make codegen

The generator accepts the original, unmodified disassembly. It assembles an original-address PRG image, recovers reachable instructions and callable regions, and emits structured C with the source comments. See the analysis and migration notes for techniques, validation, and current NROM limitations.

Run python3 tests/check_codegen.py for the ROM-free regression suite, or append --rom with a local smb.nes to compare PRG bytes and replay the recorded 7,987 frames. These checks do not require Raylib.

Calls are emitted as CALL(routine, return_address) and keep the original return addresses on the guest stack. Add EXTRA_CFLAGS=-DNATIVE_CALLS to any make target to compile them as plain C calls instead.

To compile another compatible assembly input into a separate directory:

moon run src/main -- --input tests/nrom128.asm --output /tmp/nrom-codegen

References & Resources

About

Super Mario Bros. static recompilation in C

Resources

Stars

12 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages