Skip to content
TheColdVoid1337Public

About

Reverse‑engineering utilities and map renderer for Digital Devil Story: Megami Tensei (Nihon Telenet) on the NEC PC‑88. This repo contains three scripts and a set of CSV tables that together parse game data from RAM dumps and render readable, annotated PNG maps. Already rendered maps included.

Topics

Resources

Stars

3 stars

Watchers

2 watching

Forks

Repository files navigation

DDS_ex: Digital Devil Story: Exorcist

Reverse‑engineering utilities and map renderer for Digital Devil Story: Megami Tensei (Nihon Telenet) on the NEC PC‑88.
This repo contains three scripts and a set of CSV tables that together parse game data from RAM dumps and render readable, annotated PNG maps. Already rendered maps included.

Map preview

What’s inside

  • enemy_table_parser_0.1.8.py — parses the 512‑byte enemy table from RAM dumps and emits FULL and UNIQUE CSVs. Also optionally dumps the raw 64‑byte per‑map banks.
  • teleport_table_parser_0.1.3.py — extracts the teleport/exits table from RAM dumps and writes a normalized CSV (source/destination world/map + 64×64 coordinates).
  • ddsmt_map_dumper_0.3.py — renders 32×32 tile maps to PNG with overlays: exits/teleports (numbered), points of interest, items, and a right‑hand info block.

All three scripts are pure Python (3.8+) and have no third‑party dependencies.

Repository layout

data/
  DDSMT_enemies_table.csv      # Parsed enemy slots per map (FULL)
  DDSMT_enemy_ID.csv           # Enemy ID → name
  DDSMT_object_ID.csv          # Collision/object byte → name, class, color (for rendering)
  DDSMT_teleport_table.csv     # Normalized teleports/exits
  DDSMT_world_ID.csv           # World ID → name
  DSSMT_pointsofinterest.csv   # Optional POIs to overlay on maps
*.py                           # The three scripts

See docs/DUMP_FORMAT.md for the RAM dump structure, coordinate systems, and table formats.

Quick start

  1. Python: 3.8+ (no extra packages).
  2. Put your RAM dumps (*.bin) into a folder alongside script and your tables in "/data".
  3. Run the tools (examples below). Outputs go to CSV/PNG folders next to the scripts by default.
# 1) Enemy table → CSVs (FULL + UNIQUE), optional 64B bank dumps
python enemy_table_parser_0.1.8.py --glob "*.bin" --outdir-csv out_csv --outdir-banks enemy_table

# 2) Teleports/exits → CSV
python teleport_table_parser_0.1.3.py dumps/*.bin --out CSV --banks teleport_tables

# 3) Render maps (32×32) with teleports + POIs + items
python ddsmt_map_dumper_0.3.py --glob "*.bin" --teleport-csv data/DDSMT_teleport_table.csv --poi-csv data/DSSMT_pointsofinterest.csv --outdir-png map_pngs

If you have just a single dump file:

python ddsmt_map_dumper_0.3.py files w01_m01_malkuth.bin

Script summaries

enemy_table_parser_0.1.8.py

Enemy Table Parser for DDSMT (→ FULL & UNIQUE CSV + optional 64‑byte bank dumps)

What this script does

Parses an enemy table (512 bytes total) from one or many binary dumps of Digital Devil Story: Megami Tensei (PC‑88) and produces two CSV reports:

  1. FULL CSV — every slot on every map (bank) with raw hex attributes and an optional NAME lookup.
  2. UNIQUE CSV — de‑duplicated enemy variations (by the 4‑byte tuple ID/UNKNOWN/HP/SPEED), with counts and the list of levels (wXXmYY) where each variation appears. Additionally, it can dump the raw 64‑byte per‑map banks to a folder for archival / inspection.

Key assumptions

  • The enemy table occupies 512 bytes consisting of 8 banks × 64 bytes; each bank has 16 slots × 4 bytes.
  • The 4 bytes per slot are interpreted as: ID, UNKNOWN, HP, SPEED (all shown as two‑digit hex).
  • The table is located either:
    • exactly the file size (== 512 bytes), or
    • at offset 0xEE00 inside a larger dump (preferred), or
    • otherwise we fallback to the last 512 bytes of the file (when --no-offset-prefer is used).
  • The world index (1..20) is read from absolute byte 0x422 of the input file when available; otherwise it is inferred from a filename token like wNN (e.g., w03m02.bin).

Outputs

  • FULL CSV (default: DDSMT_enemies_table_candidate.csv) with columns:

    mob_ID, on W, on M, mob_slot_on_map, ID, UNKNOWN, HP, SPEED, NAME

    Notes:

    • mob_ID is an auto‑incremented label NNNN_mob_ID.
    • on W and on M are zero‑padded world/map indices (e.g., 01, 08).
    • mob_slot_on_map is 1..16 (human‑friendly slot number on the 64‑byte bank).
    • NAME is looked up from --names-csv (a simple NAME,ID mapping); empty if not found.
  • UNIQUE CSV (default: DDSMT_unique_enemies_candidate.csv) with columns:

    NAME, variations, ID, UNKNOWN, HP, SPEED, instances, exists on levels

    Notes:

    • variations prints the hex tuple as four space‑separated bytes.
    • instances is the total number of occurrences across all files/maps/slots.
    • exists on levels lists the levels like w01m01,w01m02,... sorted by world then map.
  • 64‑byte bank dumps (optional) saved as enemy_table/wXXmYY.bin for each map YY = 1..8 of world XX. Enable/disable via --no-save-banks (banks are saved by default).

Typical usage

Parse all *.bin in the current directory and write both CSVs (also dump 64B banks by default): python enemy_table_parser_0.1.8.py

Recurse into subfolders and include entries with ID==0: python enemy_table_parser_0.1.8.py --recursive --include-zero

Prefer the last 512 bytes instead of slicing at 0xEE00: python enemy_table_parser_0.1.8.py --no-offset-prefer

Use a custom names table and output locations: python enemy_table_parser_0.1.8.py --names-csv data/DDSMT_enemy_ID.csv --csv out_full.csv --unique-csv out_unique.csv

Only write CSVs without saving per‑map bank dumps: python enemy_table_parser_0.1.8.py --no-save-banks

Command‑line options (summary)

  • --glob "*.bin": glob for input files (default: *.bin).
  • --recursive: search subdirectories as well.
  • --include-zero: keep entries where ID == 0 (they are omitted by default).
  • --no-offset-prefer: do not prefer the 0xEE00 slice; when a file is larger than 512 bytes, take the last 512 bytes.
  • --csv PATH: FULL CSV output path (default: DDSMT_enemies_table_candidate.csv).
  • --unique-csv PATH: UNIQUE CSV output path (default: DDSMT_unique_enemies_candidate.csv).
  • --bank-outdir DIR: where to write wXXmYY.bin (default: enemy_table/).
  • --no-save-banks: disable saving 64‑byte banks.
  • --names-csv PATH: CSV for name lookups.

Logging

For each processed file the script prints how the world was determined:

  • dump@0x422 — read from absolute byte 0x422 of the file,
  • filename token — extracted from the file name (e.g., w12),
  • fallback — unknown (treated as 0).

Safety checks & errors

  • Raises on undersized files (smaller than 512 bytes when slicing).
  • Any other parsing problems are reported per‑file and do not stop batch processing.

Compatibility

  • Python 3.8+ recommended. No third‑party dependencies.

teleport_table_parser_0.1.3.py

DDSMT Teleport Table Parser (PC‑88) → One CSV (dumps raw 512‑byte blocks by default)

What this script does

Extracts a single 512‑byte teleport table (E3/E4 banks) from one or many binary dumps of Digital Devil Story: Megami Tensei (PC‑88) and writes one consolidated CSV with clean, minimal columns. By default, the raw 512‑byte blocks are also dumped to teleport_tables/wNN.ddstt for archival/verification. Use --nodump to skip writing these raw block files.

CSV schema

The output CSV contains the following columns (left‑to‑right):

tele_id, src_w, src_m, dest_w, dest_m, src_x_coords, src_y_coords, dest_x_coords, dest_y_coords

  • tele_id: auto‑incremented label per row, formatted NNNN_tele_id.
  • src_w: world index 1..20 inferred from the input file (prefer byte 0x422, fallback to filename token wNN).
  • src_m: level index 1..8 (partition order).
  • Coordinates are decimal 0..63; values outside this range raise an error.

Offset policy

  • If --offset is provided, it is used for all files.
  • If --offset is omitted and the file is exactly 512 bytes, offset 0 is used.
  • Otherwise, the default offset is 0xE300.

Usage examples

Single file (exactly 512 bytes; offset optional): python teleport_table_parser_0.1.3.py w1.bin --csv out.csv

Single file with explicit offset in a larger dump: python teleport_table_parser_0.1.3.py bigdump.bin --offset 0xE300 --csv out.csv

Batch mode over current directory (and subfolders with --recursive): python teleport_table_parser_0.1.3.py --glob "*.bin" --recursive --offset 0xE300 --csv out.csv

Default raw block dumps (512 bytes each) to teleport_tables/ next to the script: python teleport_table_parser_0.1.3.py

Skip dumping raw blocks: python teleport_table_parser_0.1.3.py --nodump

How it works (high level)

  • Partition header (first 16 bytes): 8 pairs of [ptr][bank]. For bank 0xE3 the address is ptr, for bank 0xE4 the address is ptr + 0x100.
  • At each address, block[addr] holds the count of 8‑byte entries that follow for that level.
  • Each 8‑byte teleport record encodes: dest_w, dest_m, src_x, src_y, dest_x, dest_y.
  • The script stitches all level partitions together into CSV rows in source level order src_m = 1..8.
  • src_w is determined from byte 0x422 when possible; otherwise from the file name token wNN.

Diagnostics & exit codes

  • Prints a [SRC_W] line for each file explaining how src_w was determined.
  • On structural problems (wrong size/offset, bad partition address, out‑of‑range coordinates), the script prints [ERROR] <file>: <reason> and continues to the next file.
  • Final line announces success with total rows written.

Compatibility

  • Python 3.8+ recommended. No third‑party dependencies.

ddsmt_map_dumper_0.3.py

DDS Megami Tensei — Map Dumper (v0.3)

Overview

This script renders maps for Digital Devil Story: Megami Tensei (PC-88) from RAM dumps. It produces PNG images with a three-part layout:

  1. Header: " - " and a gray subheader "wXXmYY".
  2. Map body: 32×32 collision-colored tiles, with overlays:
    • Red highlights for teleports, numbered 1..N (clustered or raw).
    • Colored squares for POIs (points of interest).
  3. Info block: Enemies (xN NAME), Items (colored square + "xN - NAME"), Exits ("→ wXXmYY (x, y)"), and optional POI list.

Inputs

  • RAM dumps (.bin). World/Map IDs are read from bytes 0x422/0x423 when available, with fallback to filename tokens (wNN, mNN).
  • CSV tables from the data/ folder (overridable via CLI flags):
    • DDSMT_object_ID.csv — object bytes → name, class, RGB (supports 0..1 or 0..255).
    • DDSMT_teleport_table.csv — teleport links (src/dest world, map, coords).
    • DDSMT_world_ID.csv — world_id → world_name.
    • DDSMT_enemies_table.csv — rows mapping enemies to maps (counted per row).
    • DSSMT_pointsofinterest.csv — optional POI entries (world,map,x,y,name).

Outputs

  • Normal mode: one PNG per dump into map_pngs/ (teleport numbers ON), plus optional BIN slices into map_dumps/.
  • Debug mode (--debug): two PNGs into map_debug_pngs/ — collision view and tilemap view — with grid + hex overlays.
  • PNGs may include coordinate grid (--coord) and uncluttered clustering can be disabled (--noclean).

Command-line usage

Examples: $ python ddsmt_map_dumper.py $ python ddsmt_map_dumper.py --coord --noclean $ python ddsmt_map_dumper.py --debug

Switches: --debug Produce debug PNGs (collision + tilemap). --coord Overlay 00..31 grid/coords in normal mode. --noclean Do not cluster adjacent teleports. --no-png Do not render PNGs. --no-bin Do not save BIN slices. --no-color Disable ANSI colors in console logs. --teleport-csv PATH Override teleport table CSV path. --world-csv PATH Override world names CSV path. --enemies-csv PATH Override enemies table CSV path. --poi-csv PATH Override POI CSV path. --outdir-png DIR PNG output directory (default: map_pngs). --outdir-bin DIR BIN output directory (default: map_dumps).

Notes

  • Teleport coordinates (64×64) are mapped to 32×32 tiles via ceil-division and axis swap.
  • Exits located on walls (0xC0) are skipped with a warning.
  • Adjacent door tiles 0x41/0x42 are merged into a single "Door" entry.
  • POI overlay colors are derived from object table rows where class == "POI".

Data tables

The data/ directory includes curated CSVs used by the tools:

  • DDSMT_enemy_ID.csv — two columns: enemy NAME, ID (hex without 0x).
  • DDSMT_world_ID.csv — ID, WorldName (e.g., 01,Malkuth .. 14).
  • DDSMT_object_ID.csv — byte,name,class,color used by the map renderer to color tiles/items and label the info block.
  • DSSMT_pointsofinterest.csv — POI rows (ID,class,on W,on M,x,y,Line1,Translation1,Line2,Translation2) that overlay onto rendered maps.
  • DDSMT_enemies_table.csv — FULL enemy slots per map emitted by the parser.
  • DDSMT_teleport_table.csv — normalized exits (src/dst world+map, 64×64 coords).

Details and column descriptions are in docs/DUMP_FORMAT.md.

Reproducibility

All important “magic numbers” (offsets, strides, table sizes, coordinate transforms) live in each script’s Config section and are documented in docs/DUMP_FORMAT.md.

Contributing

  • Found a mistake in IDs, offsets, or coordinates? Open an issue with a dump snippet and your reasoning.
  • PRs welcome for: new dumps, verified offsets, better color legends, or more POIs.

License

MIT (see LICENSE if included). The original game assets remain the property of their respective rights holders and are referenced here only for research and preservation purposes.

About

Reverse‑engineering utilities and map renderer for Digital Devil Story: Megami Tensei (Nihon Telenet) on the NEC PC‑88. This repo contains three scripts and a set of CSV tables that together parse game data from RAM dumps and render readable, annotated PNG maps. Already rendered maps included.

Topics

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages