Skip to content

feat(saves): the resolver answers where a save lives and what it consists of #1858

Description

@danielcopper

Which files make up a game's save is a hand-maintained table in this repo (domain/save_extensions.py), keyed by system, written from a one-pass core audit. The vendored resolver answers the same question per emulator, from the machine, with provenance. This cut hands the question over and deletes the table.

Pins emu-atlas 0.13.0 as the first commit.

What the table gets wrong today

Measured on a stock RetroDECK against the resolver, for the systems the table has entries for:

system the table the machine
Neo Geo Pocket .flash, from a desk audit .flash, read out of the core
Amiga .nvr no separate save file at all — the writes go into the disk image
Amiga CD32 .nvr .nvr
3DO the three default extensions <rom>.<n>.srm, with a version digit the table never had
Saturn three extensions, all treated as progress two are progress, one is console configuration

So for Amiga the plugin searches forever for a file that cannot exist, and for 3DO it searches for a name no core writes. Neither is visible: the search simply finds nothing.

What lands

A new adapter behind a Protocol answers, per ROM and per the emulator that would launch it: the directory, the file set, the granularity, any hole left in the names, the caveats, and the link-resolved backing directory. Services see a domain value object and never a resolver type, as the firmware seam already does.

The save search and the download target take their file set from that answer. A file whose role is configuration rather than progress is not synced — the resolver states the role, and on a stock RetroDECK that is the Saturn console-settings file and MAME's per-game settings file.

The answer also classifies the save into one of five states, and the sync refuses in four of them rather than probing for a file that cannot be there:

  1. one file per game — sync as today, any number of files
  2. shared card — one file many games write, so per-game sync would overwrite other games' progress
  3. the save is inside the game file — there is nothing separate to sync
  4. names known, an identifier missing — the resolver names the files but one part of the name comes from the game's own id, which nothing here supplies
  5. nothing established — the core was never audited, the emulator has no card, or the directory is known and its file names are not

The state's scope is the emulator, never the platform: PS2 is not unsupported, the standalone PCSX2 is, and the libretro core for the same platform can answer differently.

The states reach the game-detail payload in this cut. Rendering them is the next cut, so nothing about the tab changes yet — what changes is that the sync stops looking where it cannot find anything.

What dies

domain/save_extensions.py and its tests. Nothing replaces it: for the systems it covered, the resolver's answer is at least as good and in four cases better.

Decisions this cut carries

  • The question goes to the catalogue entry that would launch the ROM, not to a bare core, so a standalone emulator answers for itself.
  • Answers may be cached for display; every sync path asks live, because the user changes core options in the emulator's own quick menu between a launch and the next sync.
  • Reads and writes use the path the emulator opens. The link-resolved path is for identity questions only.
  • Saves are not zipped. One row per file stays the interoperable shape for the flat sibling files this plugin syncs; the reasoning and the ecosystem measurement are on feat(saves): store multi-file saves as a single zip asset where supported (RomM-native integrity) #1235.

Tests

  • The five states, each from a real resolver answer over a fixture machine, including the two shapes inside state 5 (never audited, versus directory known and names not).
  • A configuration-role file is offered by the answer and excluded from the synced set.
  • A refusal in states 2 to 5 leaves no probe and writes no state.
  • The systems the deleted table covered each keep or improve their answer, pinned per system.
  • The plugin's platform map produces only systems the resolver knows, minus the two no ES-DE system declares.

Acceptance on the reference machine

A Game Boy Advance game syncs exactly as before. A Saturn game syncs its two progress files and no longer syncs the console-settings file, which is the configuration-role rule above doing its job — the file stays on disk and on the server, it stops being managed. The Neo Geo Pocket file is still found. Nothing is probed for Amiga any more. No game-detail page changes visibly.

Out of scope

Rendering the states (next cut). The stored save directory and the retirement of the path math (the cut after). Offering to switch a core off its shared card (#1645). Zipped saves (#1235). Identity from ROM binaries (#1462). Carrying a save when the emulator changes (#1857). Saves inside the game file (#1856).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions