Skip to content

mitchellcairns/snes-native

Repository files navigation

snes-native

Research-quality static recompilation framework for the Super Nintendo / Super Famicom.

Input: a standard .sfc SNES ROM
Output: a portable C11 project whose generated code executes the game on the host CPU

Byte-identical output is not a goal. 100% functional compatibility is.

Philosophy

  • True static recompilation — not a JIT, not a dynamic translator, not an interpreter for game CPUs
  • Every instruction-stream processor becomes native C in the end (65816, SPC700, coprocessors)
  • PPU, DSP mix path, DMA/HDMA, carts, and the scheduler remain hardware implementations
  • CPU interpreters exist only as temporary verify-build oracles, never in release architecture
  • Correctness first, maintainability second, performance third

Desktop end goals (Steam)

Beyond accurate single-player execution, desktop builds aim to:

  • Import user-owned .sfc / .smc files (ROMs are never redistributed)
  • Invite Steam friends (lobbies / overlay), using SpaceWar (App ID 480) during development
  • Offer Steam Remote Play for streamed sessions
  • Offer synced P2P netplay where peers run the game locally and stay aligned via input lockstep plus WRAM/state checksums and occasional snapshot resync (SNES state is small enough for low-latency recovery)

Steam code stays in platform/steam/; the runtime only exposes snapshot/checksum APIs. See ADR-005.

Tooling end goal (live debug MCP)

Support agent-assisted game-specific patches and mods via a live connection to a running session:

  • Optional runtime debug bridge (pause, frame-step, memory/register R/W, snapshots)
  • MCP server (host-side) so Cursor and other agents can drive that bridge
  • Patch apply at safe boundaries; reuse traces/snapshots from the verification ladder

Runtime stays free of MCP dependencies. See ADR-006.

Layout

Path Role
frontend/ Python: ROM loading, mapping, symbols
analysis/ Python: CFG, M/X, jump tables, data/code
recompiler/ Python: translation and C emission
runtime/ C11: scheduler, bus, DMA, PPU, SPC hardware, IRQ, snapshots
platform/ SDL3 desktop, Steam (stub), RP2040 (later)
generated/ Emitted C (local; usually gitignored)
tools/verify/ Trace diff, frame/audio compare harnesses
tools/extract_spc/ ARAM / SPC image capture for static SPC recomp
docs/ ADRs, hardware notes, verification docs

Generated code depends on the runtime. The runtime never depends on generated code.

Quick start

# Python host tools
python -m venv .venv
# Windows: .venv\Scripts\activate
pip install -r requirements.txt

# Disassemble / emit a tiny C stub from a local ROM
python -m recompiler --rom path/to/game.sfc --out generated/

# Load .sfc/.smc → recompile → run N frames → JSONL + report
python tools/run_rom.py --rom path/to/game.sfc --frames 2

# Community 65816 test ROM (gilyon/snes-tests cputest-basic)
python tools/run_cputest.py --frames 2

# Playable MVP (SDL3 window + keyboard/gamepad → $4218)
python tools/run_play.py

# Kirby Super Star local gate (ROM in tests/roms/local/, gitignored)
python tools/run_kirby.py

# Build runtime (CMake 3.20+)
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build

Optional verify (shadow lockstep) build:

cmake -B build -DSNESN_VERIFY_SHADOW=ON
cmake --build build

Documentation

Start here:

Status

Phase 2 — system silicon. DMA/HDMA, BG1 renderer, frame hashes, SPC image recomp emitter, Layer 1 trace export/diff.

python tools/regen_cpu_smoke.py
cmake -B build -DSNESN_BUILD_TESTS=ON
cmake --build build --config Debug
ctest --test-dir build -C Debug --output-on-failure

License

See LICENSE (to be chosen by the project owner). Copyrighted ROMs and commercial game assets must not be committed to this repository.

About

Static SNES recompiler: .sfc to portable C11

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors