Skip to content

Repository files navigation

===========

What it’s supposed to be

===========

smcdis is a disassembler and explorer for SNES ROM images.
Since ROM images are unformatted, it uses abstract interpretation
to find all possible function entry points and tell apart text and
data sections.

===========

What it actually does

===========

Figures out the ROM format and original dumper hardware for (most)
images, and prints out a lot of headers, with more accurate meanings
than all other SNES emulators I tried (including bsnes).

Maps LoROM and HiROM images, then traces every code path reachable
from the exception vectors — following branches and calls, and
tracking the E/M/X status flags so immediate operand sizes decode
correctly — and prints a labeled disassembly.

Build with `make` (or the Xcode project). `make sanitize` builds
with ASan/UBSan.

===========

TODO

===========

  1. More memory maps: Sufami Turbo…
  2. Tell apart code and data; find data referenced by instructions
  3. Code that games copy or decompress into WRAM and run there (Secret
    of Mana, FF5, Rudra, and parts of many others) needs a load-image
    analysis: model the copy loops/MVN/DMA and trace the materialized
    bytes.
  4. Flag tracking is per-state now: every (address, M, X) combination
    is traced, divergent decodes are listed as ~ alternates, subroutine
    exit states propagate to call sites, and interrupt handlers are tried
    both 8- and 16-bit. What’s left is flags that come from data (PLP of
    a computed value, task switchers) – real dataflow territory.
  5. Task schedulers that stash entry PCs in records and RTS into them
    (Mega Man 7) need the same dataflow.

===========

Architecture debts

===========

From a model design review of everything above, ranked; pay these
down before or during the WRAM-image and SPC700-upload work:

  1. Recovery passes communicate by mutating one shared decode database
    (including erasing instructions to mean “this is data”). Should be
    typed facts with provenance that rules subscribe to.
  2. The mapper knows one ROM backing and hands out raw pointers; WRAM
    images, SRAM and I/O need region identity (“what’s here and where
    did it come from”), not just a byte pointer.
  3. 65816 semantics and per-run state are file-static globals in
    disasm.cpp; an Isa + session split would have made SPC700 a plug-in
    (spc700.cpp dodges this by being its own little world, which is the
    cheap version of the same idea).
  4. The coverage benchmark checks addresses, not whether the listing
    picked the decode matching the runtime M/X state; traces should
    carry CPU + state + edges.
  5. Which decode is “primary” depends on traversal order; should be a
    stated rendering policy.
  6. Subroutine exit summaries are keyed only by callee; fine for M/X,
    too coarse once DBR/direct-page tracking arrives.
  7. The 2014 sketch’s known-bits idea (doc/2014-tracer-sketch.diff) is
    implemented: flags carry a known bitfield and the tracer forks both
    widths where an unknown one is used. Extending knownness to values
    (registers, cells) is the remaining half.

===========

Documentation

===========

See doc/.

A particularly useful file that was too large to include can be found
at http://www.romhacking.net/docs/226/.

About

Theoretically a disassembler and header printer for SNES files

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages