Lossless, round-trippable JSON for dm2-saves #308

Closed
opened 2026-07-31 22:31:54 +02:00 by jqueuniet · 0 comments
Owner

Summary

Give DM2 savegames a lossless, round-trippable JSON representation in dm2-saves:
implement the approved-but-unbuilt SaveDump schema (forward dump) and add public
reverse reconstruction so parse -> JSON -> parse JSON -> reconstruct reproduces the
original SkSave.dat byte-for-byte.

Design of record: docs/superpowers/specs/2026-07-31-save-json-roundtrip-design.md
(supersedes 2026-06-22-save-json-dump-design.md, which designed the schema but was never
implemented and shipped no public reverse).

Motivation

Underpins a save editor (GUI, #303) and the browser save editor behind #301. dm2-saves
has no serde today. A real JSON->bytes library API (not just a test helper) is required
so editing tools can write edits back, and a lossless form ensures no save state is
silently dropped.

Two lossless variants

  • Field-driven full — fully editable (incl. object record_stream); reload requires
    dungeon.dat + graphics.dat as inputs; smaller JSON.
  • Self-contained (escape-hatch) — embeds the full suppression bitstream verbatim;
    reload needs no external files either direction; gameplay-editable only (SGB /
    globals / champions / effects / timers). This is the lightweight web-editor path and the
    #307 self-contained form.

Scope / acceptance

  • Adopt the 2026-06-22 SaveDump schema (gameplay typed + base64 raw escape hatches;
    raw-numeric values; schema_version: 1), plus a full raw.bitstream escape hatch for
    the self-contained variant (mutually exclusive with raw.bitstream_pad).
  • Add serde/serde_json/base64 to dm2-saves; new json module with SaveDump
    (Serialize + Deserialize), three forward constructors (gameplay_only,
    self_contained, full), to_pretty_json, and two reverse methods:
    reconstruct(map_info, gdat) and reconstruct_self_contained().
  • Implement the forward dm2 dump saves CLI path: default gameplay-only, --self-contained,
    and --full (requires --gdat + --dungeon).
  • Acceptance: two losslessness gates via the public API over every DOS-EN slot and Mac
    fixture, byte-identical — field-driven (reconstruct with inputs) and self-contained
    (reconstruct_self_contained, no inputs) — plus a gameplay-edit-reflected test.
  • Out of scope: the JSON->save reload CLI command (follow-up), enum/name resolution,
    the web serialization scheme (#307), and the wasm exposure (#301).

Labels

type/feature, area/saves, priority/medium.

## Summary Give DM2 savegames a lossless, round-trippable JSON representation in `dm2-saves`: implement the approved-but-unbuilt `SaveDump` schema (forward dump) **and** add public reverse reconstruction so `parse -> JSON -> parse JSON -> reconstruct` reproduces the original `SkSave.dat` byte-for-byte. Design of record: `docs/superpowers/specs/2026-07-31-save-json-roundtrip-design.md` (supersedes `2026-06-22-save-json-dump-design.md`, which designed the schema but was never implemented and shipped no public reverse). ## Motivation Underpins a save editor (GUI, #303) and the browser save editor behind #301. `dm2-saves` has no `serde` today. A real JSON->bytes library API (not just a test helper) is required so editing tools can write edits back, and a lossless form ensures no save state is silently dropped. ## Two lossless variants - **Field-driven full** — fully editable (incl. object `record_stream`); reload requires `dungeon.dat` + `graphics.dat` as inputs; smaller JSON. - **Self-contained (escape-hatch)** — embeds the full suppression bitstream verbatim; reload needs **no external files** either direction; gameplay-editable only (SGB / globals / champions / effects / timers). This is the lightweight web-editor path and the #307 self-contained form. ## Scope / acceptance - Adopt the 2026-06-22 `SaveDump` schema (gameplay typed + base64 `raw` escape hatches; raw-numeric values; `schema_version: 1`), plus a full `raw.bitstream` escape hatch for the self-contained variant (mutually exclusive with `raw.bitstream_pad`). - Add `serde`/`serde_json`/`base64` to `dm2-saves`; new `json` module with `SaveDump` (Serialize + Deserialize), three forward constructors (`gameplay_only`, `self_contained`, `full`), `to_pretty_json`, and two reverse methods: `reconstruct(map_info, gdat)` and `reconstruct_self_contained()`. - Implement the forward `dm2 dump` saves CLI path: default gameplay-only, `--self-contained`, and `--full` (requires `--gdat` + `--dungeon`). - **Acceptance:** two losslessness gates via the public API over every DOS-EN slot and Mac fixture, byte-identical — field-driven (`reconstruct` with inputs) and self-contained (`reconstruct_self_contained`, no inputs) — plus a gameplay-edit-reflected test. - Out of scope: the JSON->save **reload CLI command** (follow-up), enum/name resolution, the web serialization scheme (#307), and the wasm exposure (#301). ## Labels `type/feature`, `area/saves`, `priority/medium`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jqueuniet/dm2-tools#308
No description provided.