An open API service indexing awesome lists of open source software.

https://github.com/gingerbeardman/snes-memory-maps

Generate SNES memory maps as SVG and/or CSV, with lots of options
https://github.com/gingerbeardman/snes-memory-maps

data-visualisation memory-map sfc snes treemap

Last synced: 10 days ago
JSON representation

Generate SNES memory maps as SVG and/or CSV, with lots of options

Awesome Lists containing this project

README

          

# SNES Memory Maps

Generate zoomable SVG maps of SNES ROM and WRAM from linker map files, with
optional machine-readable CSV output.

Supports [llvm-mos](https://github.com/llvm-mos/llvm-mos) (ld.lld),
[vbcc65816](http://www.compilers.de/vbcc.html) (vlink), [cc65](https://cc65.github.io/)
(ca65/ld65), [wla-dx](https://github.com/vhelin/wla-dx), and
[asar](https://github.com/RPGHacker/asar); the input format is auto-detected.
Linker maps carry exact sizes; assembler symbol files (wla-dx, asar) carry only
addresses, so their sizes are inferred (see below).

The repository provides two command-line scripts:

- `rommap.py` creates a physical-bank ROM treemap.
- `rammap.py` creates an address-preserving WRAM overview with low-WRAM and
direct-page zooms.

Both are thin entry points to `snesmap.py`, the shared engine that does the map
parsing, layout, and rendering; they simply preset ROM or RAM mode. Keeping one
engine means the ~95% of logic the two maps share lives in a single place, while
you still get the two commands you'd expect. (`snesmap.py` is not meant to be run
directly.)

All three use only the Python 3 standard library. Their SVG output supports
light and dark colour schemes, browser zooming, and per-allocation tooltips.

## Examples

### ROM

![Example SNES ROM map](examples/rommap.svg)

### RAM

![Example SNES RAM map](examples/rammap.svg)

## Quick start

Run the scripts from the directory containing your linker script:

```sh
python3 /path/to/rommap.py build/game.map \
--linker-script game.ld \
-o build/rommap

python3 /path/to/rammap.py build/game.map \
-o build/rammap
```

Each command writes an SVG by default:

```text
build/rommap.svg
build/rammap.svg
```

Pass `--csv` to also write the machine-readable CSV (`build/rommap.csv`,
`build/rammap.csv`).

The format is auto-detected. Override detection with `--format`, one of `lld`,
`vlink`, `ca65`, `wla`, or `asar`.

## ROM map

The ROM map displays sixteen physical 32 KiB banks in SNES reading order. Bank
headers show allocated bytes and a right-aligned percentage. Symbol rectangles
are proportional within each bank; transparent rectangles are free space.

For llvm-mos/ld.lld builds, ROM region names, origins, and capacities come from
the linker script's `MEMORY` block. Regions below `$00:8000` and WRAM banks
`$7E/$7F` are excluded.

The RAM script derives its fixed WRAM ranges directly and does not require a
linker script.

The existing `rom_bank_fixed` convention is recognised: its contents are shown
in every `code_bank_*` physical bank. Other linker-region names have no special
meaning.

## RAM map

The RAM map separates static linker allocation from runtime usage:

- A true-scale overview displays the full 128 KiB WRAM.
- A magnified panel displays `$7E:0100–1FFF`.
- A second magnified panel displays the default direct page,
`$7E:0000–00FF` with `D=$0000`.
- Allocation order and address gaps are preserved.

RAM colours identify initialized `.data`, zero-filled `.bss`, `.noinit`,
hardware stack reservation, compiler direct-page registers, and other
allocations. Unallocated space is transparent by default.

When present in an ld.lld map, `__rcN` and `__stack` linker symbols are used to
account for compiler direct-page registers and the page-$01 hardware stack.
Dynamic stack and heap high-water usage cannot be inferred from a static linker
map.

## Display options

Options apply independently to either script:

```sh
--checkerboard
--colour-key # alias: --color-key
--coloured-percentages # alias: --colored-percentages
```

- `--checkerboard` uses a Photoshop-style pattern for free space.
- `--colour-key` adds the colour legend.
- `--coloured-percentages` shows 75–89.9% in amber and 90%+ in red.

All three are off by default.

Use `--compiler "toolchain name"` to override the compiler/linker label embedded
in the SVG footer.

Use `--delimiter` to change the field separator used throughout the SVG — headers,
tooltips, captions, and the footer (e.g. `$00 / 31,333 B / 95.6% full`). It is
space-padded, and the default is a bullet (`·`), e.g. `--delimiter "/"`.

## Supported linker maps

- llvm-mos/ld.lld map output, with ROM regions read from a GNU-style `MEMORY`
block.
- vbcc65816/vlink section mappings.
- vlink LoROM, plus the vlink HiROM address projection used by `vlink-hi`.
- cc65 ca65/ld65: the `ld65 --mapfile` **Segment list** for exact per-segment
sizes. Optionally pass your cc65 linker config (the same `.cfg` you build with,
`cl65 -C` / `ld65 -C`) as `--linker-script` to name the ROM regions; without it
the map falls back to physical banks.
- wla-dx / asar symbol files (`wlalink` `.sym`, `asar --symbols=wla|nocash`):
label→address only, so LoROM physical banks are assumed and sizes are
**inferred** from label gaps (the last label in a bank runs to the bank end).
Trailing free space inside a bank is therefore invisible; the footer marks
these maps `(approx sizes)`.

See [docs/linker-map-support.md](docs/linker-map-support.md) for assumptions and
known limitations.

## Development

Run the test suite:

```sh
python3 -m unittest discover -s tests -v
```

The tests invoke both scripts against small checked-in fixtures for each
supported format (ld.lld, vlink, ca65/ld65, wla-dx, and asar) and validate their
CSV and SVG output.

## Acknowledgements

The physical-bank ROM view was inspired by Pin Eight's
[Homebrew ROM maps and treemaps](https://pineight.com/retrotainment/home_treemaps.html).

## License

MIT. See [LICENSE](LICENSE).