Combine this work, which is in a great state now, with the design scaffolding: https://github.com/dwallener/snes-builder
Create a user-facing app the leverages the design scaffolding into assets for the ROM generator.
This crate now includes a first-pass static SNES ROM disassembler and code mapper for LoROM 65816 games. The tracing and dissassemgly is used in the ROM generator to produce playabe SNES ROMs.
Yes, it works...this can now go from prompt to ROM that runs in any of the usual emulators.
Run:
cargo run -- disasm rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --out out/pockyOutputs:
out/pocky/disasm.txtout/pocky/report.jsonout/pocky/code_map.jsonout/pocky/cfg.jsonout/pocky/labels.json
Correlate structured runtime probe output back to those labels and the recovered CFG:
cargo run -- runtime-correlate --input trace.jsonl --labels out/pocky/labels.json --cfg out/pocky/cfg.json --out out/pocky/runtimeThis emits:
out/pocky/runtime/runtime_summary.txtout/pocky/runtime/runtime_report.jsonout/pocky/runtime/annotated_events.json
The runtime summary groups activity by routine and highlights DMA/VRAM/CGRAM/OAM-heavy code paths.
Collect a richer headless trace directly from local Mesen2 with a scripted input loop:
cargo run -- collect-trace --rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --out out/pocky-trace --frames 3600 --profile rich-title-loopThis writes:
out/pocky-trace/trace.jsonlout/pocky-trace/mesen_stdout.logout/pocky-trace/mesen2_headless_capture.luaout/pocky-trace/capture_report.json
Notes:
- this uses the local Mesen2 build at
/Users/damir00/Sandbox/Mesen2/bin/osx-arm64/Release/Mesenby default - it provisions a portable
settings.jsonbeside that binary so Lua file I/O is enabled in--testRunner - current built-in capture profiles are
rich-title-loopandboot-only
Overlay external usage-map or CDL-style evidence onto the static map:
cargo run -- usage-map-import --rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --input usage.bin --labels out/pocky/labels.json --code-map out/pocky/code_map.json --out out/pocky/usageThe current importer supports --format simple-bits:
- bit 0: observed execute
- bit 1: observed data/read
It also supports --format bizhawk-cdl-snes for BizHawk SNES CDL files by extracting the CARTROM block and mapping:
ExecFirst/ExecOperand-> observed executeCPUData/DMAData-> observed data
Outputs:
out/pocky/usage/usage_summary.txtout/pocky/usage/usage_report.jsonout/pocky/usage/merged_code_map.json
Combine runtime and usage evidence into one ranked routine report:
cargo run -- evidence-report --runtime-report out/pocky/runtime/runtime_report.json --usage-report out/pocky/usage/usage_report.json --out out/pocky/evidenceOutputs:
out/pocky/evidence/evidence_summary.txtout/pocky/evidence/evidence_report.json
Overlay that evidence onto the disassembly and emit a hot-routine index:
cargo run -- annotate-evidence --disasm out/pocky/disasm.txt --labels out/pocky/labels.json --evidence out/pocky/evidence/evidence_report.json --out out/pocky/annotatedDerive first-pass asset path candidates from runtime events plus combined evidence:
cargo run -- asset-paths --events out/pocky/runtime/annotated_events.json --evidence out/pocky/evidence/evidence_report.json --out out/pocky/asset-pathsThis now includes APU port activity as well, so sound-transfer routines can be surfaced alongside graphics-upload routines.
For the current Pocky player/sprite batch, decode the sub_80_A39A graphics commands into concrete ROM sources and raw 4bpp previews:
cargo run -- player-gfx-report --rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --disasm out/pocky-seeded-plan3h/disasm.txt --out out/pocky-player-gfxThis emits:
out/pocky-player-gfx/player_gfx_summary.txtout/pocky-player-gfx/player_gfx_report.jsonout/pocky-player-gfx/previews/*.png
Write a fixed-size proof patch directly into one decoded player graphics source region:
cargo run -- patch-player-gfx \
--rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc \
--disasm out/pocky-seeded-plan3h/disasm.txt \
--callsite '$80:BCB2' \
--png artwork/SNES-Pocky-Sayo-chan.png \
--out out/pocky-sayo-proof.sfcThis keeps the ROM size fixed and overwrites only the chosen decoded source window.
Attribute the decoded player batch against a supplied extracted character sheet:
cargo run -- match-player-gfx-sheet \
--rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc \
--disasm out/pocky-seeded-plan3h/disasm.txt \
--sheet artwork/SNES-Pocky-Sayo-chan.png \
--out out/player-match-sayoThis emits a ranked summary of which decoded player-batch regions overlap that sheet.
Or run the whole phase-2 pipeline in one shot:
cargo run -- phase2-analyze --rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --trace trace.jsonl --usage usage.cdl --usage-format bizhawk-cdl-snes --out out/pocky-phase2Practical rich-trace workflow:
cargo run -- collect-trace --rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --out out/pocky-trace
cargo run -- phase2-analyze --rom roms-original/Pocky-n-Rocky/Pocky-n-Rocky.sfc --trace out/pocky-trace/trace.jsonl --usage usage.cdl --usage-format bizhawk-cdl-snes --out out/pocky-phase2What v1 does:
- strips optional 512-byte copier headers
- scores and parses SNES headers
- recognizes LoROM vs HiROM headers
- decodes 65816 instructions with M/X-sensitive immediate widths
- recursively traverses code from vector-derived entry points
- builds a reachable code map and CFG
- marks unresolved indirect transfers instead of inventing targets
- records first-pass jump-table candidates
What v1 does not do:
- emulate execution
- recover semantics
- fully support HiROM traversal
- support enhancement chips
- guarantee perfect code/data separation
Run:
cargo testThe first PLAN_004 slice adds a generation-side template namespace.
Initialize a new single-screen-action project:
cargo run -- template init --kind single-screen-action --out /tmp/template-demoValidate the project layout:
cargo run -- template validate --project /tmp/template-demoPreview the current asset tree:
cargo run -- template preview-assets --project /tmp/template-demoEmit the current build scaffold and a minimal emulator-loadable .sfc:
cargo run -- template build --project /tmp/template-demo --out /tmp/template-demo-buildSimulate a gameplay scene with D-pad input and emit frame previews:
cargo run -- template simulate --project /tmp/template-demo --out /tmp/template-demo-sim --input RRRRDDLLUU..RRThe first PLAN_005 slice adds a minimal Streamlit designer app for the one-screen arena battle variant.
Install:
python3 -m pip install -r requirements-designer.txtRun:
streamlit run tools/designer_app.pyThe app currently:
- creates or opens a
single-screen-actionproject - edits title/arena, player, and NPC fields
- runs
template validate - runs
template build - runs
template simulate - shows the generated
.sfcpath when build emits a ROM - shows generated preview images and logs
This is scaffold-only for now:
- project manifest and folder conventions exist
- cartridge memory model and content contracts are emitted as
memory.tomlandcontracts.toml - validation exists
- build-plan emission exists
- runtime layout and engine stub emission exist under
engine/ - reset/NMI, joypad, DMA queue, and room-load contracts are described in the generated runtime files
- scene/entity/script TOML stubs are parsed and emitted as compiled manifest files under
content/ - asset TOML stubs are parsed into stable-id asset tables and resolved scene/entity references under
assets/ - placeholder binary asset packs and per-scene load packets are emitted for runtime consumption
- sprite assets can now be procedurally generated as animated “breathing ball” previews for player/NPC validation
- build output now includes composite title/gameplay scene preview PNGs generated from scene packets and asset bindings
template simulatenow verifies player D-pad motion and simple NPC patrol movement through generated frame sequencestemplate buildnow emits an engine-side frame-loop contract and pseudo-assembly tied to the same scene packets and movement rules- no engine/runtime ROM generation exists yet