Wolfenstein Modloader Buy me a coffeeKaffee spendieren

In plain wordsIn einfachen Worten

This is the assignment given to a research worker, not a result. An edited save game for Wolfenstein II: The New Colossus, with a renamed map, was rejected by the game as 'File Corrupt'. Earlier work had ruled out the .verify files and the 4-byte header, so the brief suspects that some part of the save still carries an old length. The worker must name the exact faulty byte, build a corrected copy and show a checker that rejects the known-bad version, without starting the game or touching the real saves.

  • Known before the task: .verify files do not block loading, and all 4-byte headers of the candidates are correct.
  • Main lead: checkpoint.dat grew from 476,224 to 476,231 bytes when the map name got longer.
  • The worker must name the file, byte offset, current value and correct value of the defect.
  • Required negative control: the checker must reject the known-bad v2 and accept the untouched original.
  • The honest goal is 'structurally consistent, runtime unconfirmed'; loading in the game cannot be proven offline.

Dies ist der Auftrag an einen Forschungs-Worker, kein Ergebnis. Ein bearbeiteter Spielstand für Wolfenstein II: The New Colossus mit umbenannter Karte wurde vom Spiel als 'File Corrupt' abgelehnt. Frühere Arbeit hatte die .verify-Dateien und den 4-Byte-Header ausgeschlossen; der Auftrag vermutet daher, dass ein Teil des Spielstands noch eine alte Länge enthält. Der Worker soll das genaue fehlerhafte Byte benennen, eine korrigierte Kopie bauen und einen Prüfer zeigen, der die bekannt fehlerhafte Version ablehnt, ohne das Spiel zu starten oder echte Spielstände anzufassen.

  • Vorher bekannt: .verify-Dateien blockieren das Laden nicht, und alle 4-Byte-Header der Kandidaten stimmen.
  • Hauptspur: checkpoint.dat wuchs von 476.224 auf 476.231 Bytes, als der Kartenname länger wurde.
  • Der Worker muss Datei, Byte-Position, aktuellen und richtigen Wert des Fehlers benennen.
  • Pflicht-Gegenprobe: Der Prüfer muss die bekannt fehlerhafte v2 ablehnen und das unveränderte Original annehmen.
  • Ehrliches Ziel ist 'strukturell stimmig, im Spiel unbestätigt'; das Laden lässt sich offline nicht beweisen.

Technical detailsTechnische Details

Der technische Teil ist auf Englisch – so, wie er im Wiki steht. Unterstrichene Begriffe haben eine Erklärung auf Deutsch.

Worker w-savestructure-a1; task savestructure; research/implement. Read .agent-cache/WORKER.md. Bus: python "%USERPROFILE%/.claude/skills/agent-cache-orchestrator/scripts/acbus.py" Parallel: w-texdbkey-a1, w-cvartable-a1, w-idclwriter-a1. The other master (codex/Astra) owned the earlier save work and is at its host session limit.

Objective

Find, offline, why an edited Wolfenstein II savegame is rejected as "File Corrupt" - and fix the candidate so it is structurally correct.

These are the user's own single-player saves on their own machine. The task is a file-format one, and the search space is now small.

What is established - this is why the task is tractable now

re_probes/agent_reports/saveverify.md read the load path out of the runtime image and pinned SAVEGAME_E_CORRUPTED (the "File Corrupt" message) to exactly three set sites, all AFTER the .verify check:

(a) 0x8b47c4 Read(body) != Length - 4 (b) 0x8b4831 MD5_BlockChecksum(body) != be32(4-byte head) (c) 0x8b462d only for encrypted *.bin

.verify does NOT block loading: a mismatch only sets a flag that prints "Loading Dev Mode or corrupted save game" and loading continues. So the sidecars can stay untouched.

The master then checked (b) offline over BOTH existing candidates, v2 and v3: every .dat passes - checkpoint.dat, checkpoint_alt.dat, checkpoint_mapstart.dat, game_duration.dat, level_duration.dat, level_duration_alt.dat, head == fold everywhere. (game.details is plain ASCII with no 4-byte head; (b) does not apply to it, it carries the separate CRC32 over sorted key/value bytes, already solved.)

v2 was rejected at runtime with a clean (b). Therefore the cause is (a): the deserializer consumes a different number of bytes than the file provides.

Concrete lead: checkpoint.dat grew 476224 -> 476231 bytes when the map path went from game/dlc/c02/c2v1 (0x11) to game/dlc/c02/c2v1_custom (0x18). Something else in the stream very likely still carries the OLD total - a section length, a block size, a trailing offset table, or a count of bytes that was written before the rename. Find it.

Sources / starting points

  • Originals, READ ONLY: re_probes/save_backups/SLOT0_before_c2custom and SLOT2_before_c2custom (14 files each).
  • Candidates, READ ONLY: re_probes/custom_save_candidates/FC2-WOLF0-c2v1_custom (v1), *_v2, *_v3. v3 is the newest and has the details CRC and the length prefixes repaired.
  • tools/savehash.py (the MD5-fold head), tools/probe_savegame.py, tools/probe_saveverify.py (struktur subcommand), docs/spielstaende.md. All read-only for you.
  • re_probes/agent_reports/{saveverify,custom_save_registration,save_integrity_v3}.md
  • The method that works: diff the ORIGINAL against the CANDIDATE byte by byte and account for EVERY difference. There are only a handful. One of them, or one thing that did NOT change and should have, is the bug.
  • If you need the serialization grammar, re_probes/runtime_87400/module.bin is the read-only capture of the running, unpacked executable (virtual RVA layout, file offset == RVA, sections in manifest.json); the deserializer around 0x8b3f40-0x8b4900 is mapped in saveverify.md. capstone 5.0.7 is vendored: PYTHONPATH=re_probes/python_deps.

Ownership

tools/probe_save_structure.py (new), re_probes/save_structure/ (new dir, your corrected candidate goes here as a full copy), re_probes/agent_reports/savestructure.md.

Do NOT modify re_probes/custom_save_candidates/ or re_probes/save_backups/ - they belong to the other master and the backups are the user's only copy of their real saves. Read them, write your own copy.

Forbidden / do not touch

Never write to "%USERPROFILE%/Saved Games" or the Steam install. No game launch, no process attach. Do not touch tools/build_custom_save_candidate.py, tools/probe_details_checksum.py, tools/verify_custom_save_candidate.py, tools/probe_saveverify.py, tools/savehash.py, or any other worker's files; no docs/, no wolfsdk/, no config.json. No pip install. Do not touch any *.bin in a candidate - profile/progression .bin are encrypted with a key derived from a runtime user value and must stay as they are.

Hard constraints

Python 3.11, stdlib plus vendored capstone. Reproducible from the command line, no running game required.

Acceptance criteria

  • A named, located structural defect: file, byte offset, what it says, what it should say, and why. Not "probably a length field somewhere".
  • A corrected candidate under re_probes/save_structure/ where, demonstrably: every .dat satisfies branch (b); the map/layer strings are consistent in checkpoint.dat, checkpoint_mapstart.dat and game.details; the .verify files are copied unchanged; and the byte count the deserializer would consume matches Length-4 by your own parse.
  • A parser that can state, for a given .dat, how many bytes the deserializer consumes - because that is the only way to check branch (a) offline.
  • Negative control: your checker must REJECT the v2 candidate (known rejected at runtime) and ACCEPT the untouched original. If it accepts both, it does not measure anything.

Verification expectations

Every important assurance needs a check that fails if it is false. Be careful with one thing in particular: you cannot observe "File Corrupt" offline, so do not claim the candidate is now loadable. The honest claim is "structurally consistent by these checks, runtime unconfirmed". The runtime test needs the user's PC and is not available.

Failure honesty

If the serialization does not yield a definite answer, the valuable deliverable is the offline branch-(a) checker plus the exact list of unaccounted-for differences. A clean negative beats a plausible story. Say which hypotheses died.

Coordination / deliverable

Checkpoint at milestones. Publish a bus fact when the defect is located - the other master's save task is parked on exactly this question. Concise German report in re_probes/agent_reports/savestructure.md. Finish the bus task.