Skip to content

Research Report Custom Save Registration

LopeKinz edited this page Sep 26, 2026 · 1 revision

TNC custom-save registration investigation

Correction: Which DLC is loaded

The live save created from Freedom Chronicles / Volume 1 / Gestapo Office is not c3v1. Its on-disk save is SLOT0/FC2-* and game.details records:

mapName=game/dlc/c02/c2v1   # FC2-WOLF0
mapName=game/dlc/c02/c2v2   # FC2-AUTOSAVE0/1

Retail mapspec confirms DLC 2 uses chunkid: 22 and maps c2v1..c2v3. DLC 3 (chunkid: 24) is the separate c3v1..c3v3 package. Therefore a c3v1_custom mapspec cannot be exercised with the user's current Gestapo Office save; it needs a real DLC 3 save first.

Save structure

checkpoint_mapstart.dat contains the map and layer strings three times in fixed-size NUL-padded fields. The first four bytes are the idTech MD5-fold checksum documented by tools/savehash.py. game.details is ASCII text and contains a plain mapName= field plus a separate integer checksum. The associated .verify files are 40 bytes and their signing algorithm is not identified; they must not be regenerated by guesswork.

Safe candidate builder

tools/build_custom_save_candidate.py copies a complete existing save folder to a new directory under re_probes/custom_save_candidates, rewrites only checkpoint_mapstart.dat and game.details, recomputes the DAT checksum, and copies .verify files unchanged. It refuses output inside savegame.user or over an existing destination.

Generated candidate (not installed):

re_probes/custom_save_candidates/FC2-WOLF0-c2v1_custom
map: game/dlc/c02/c2v1 -> game/dlc/c02/c2v1_custom
layer: layer/dlc/c2v1 -> layer/dlc/c2v1_custom
checkpoint_mapstart.dat: 325 -> 367 bytes; 3+3 replacements
checksum: verified with tools/savehash.py

Runtime blocker / route

The candidate cannot be tested without temporarily copying it into a spare live slot (or a separate Windows user profile), which was intentionally not done. The game's retail menu does not enumerate arbitrary map names; the custom map must first be present in a packagemapspec.json using the same map path and its full chunk bundle. A malformed candidate with unchanged .verify is expected to trigger the documented "Loading Dev Mode or corrupted save game" path, not silently register a menu entry. This is the safe next runtime experiment only after the chunk/map bundle is complete.

Negative checks performed

  • Live save tree was never written by the builder.
  • Existing FC2-WOLF0 remains unchanged.
  • New DAT checksum equals recomputed checksum.
  • Candidate contains the new path in all three map/layer records and in game.details.

File-Corrupt diagnosis (follow-up)

The first candidate was incomplete. checkpoint.dat itself contains one length-prefixed game/dlc/c02/c2v1 field at byte offset 227. Leaving that field unchanged while changing checkpoint_mapstart.dat produces the runtime File Corrupt result because the serialized checkpoint and map-start metadata disagree. The corrected builder now rewrites this field and its little-endian length (0x11 -> 0x18) and recomputes the DAT header.

Corrected artifact:

re_probes/custom_save_candidates/FC2-WOLF0-c2v1_custom_v2
checkpoint.dat: 476224 -> 476231 bytes, one length-prefixed map-path change
checkpoint_mapstart.dat: 3 map + 3 layer changes
all .dat MD5-fold headers: verified

The .verify files are intentionally copied unchanged. They are encrypted AES blobs with a per-write nonce; the existing research shows they trigger developer/corrupted-save handling rather than rejecting the save. No runtime copy of v2 was installed.

Runtime follow-up: v2 still reports File Corrupt

The corrected candidate was tested in a separate slot and still displayed File Corrupt. A byte-for-byte comparison shows exactly three changed files:

checkpoint.dat          476224 -> 476231
checkpoint_mapstart.dat      325 -> 367
game.details                 411 -> 418

All six associated .verify files retain their retail values. Each .verify file is 40 bytes: an 8-byte per-write nonce followed by 32 bytes of AES ciphertext. The key/signing input is not available in the workspace. Therefore, the offline candidate cannot become a valid retail-signed save merely by fixing the DAT MD5-fold headers. The game.details integer checksum is also not a known CRC/MD5/SHA fold (tested across the live corpus).

Conclusion: A new map ID cannot currently be registered by editing a save offline. The safe playable route is to leave the save unchanged and override the existing game/dlc/c02/c2v1 bundle with custom entities/geometry, or to make the game itself generate a save after an in-engine transition to the new map. Do not call v2 runtime-valid.

Runtime command and full-bundle checks

Both map and devmap return unknown command in the TNC retail commandset, even when com_enableDeveloperMode=1, devMode_enable=1, and g_demoDevMode=1 are supplied at launch. A full-retail alias probe was also tested: all 6,985 chunk-22 resource entries and the retail TexDB were hard-linked into dlc_4, with the correct DLC2 patchlevel: 3 and refchunks: [9, 13]. This removes the reduced-bundle/missing-dependency hypothesis, but does not make the offline custom save loadable.

The real SLOT0/FC2-WOLF0 was restored from re_probes/save_backups/SLOT0_before_c2custom after each runtime attempt.

Clone this wiki locally