Wolfenstein Modloader Buy me a coffeeKaffee spendieren

In plain wordsIn einfachen Worten

This page is the task description given to a research worker, not a result. For Wolfenstein II: The New Colossus, the archive header checks were already solved. Two per-entry fields, the data hash at +0x50 and the value at +0x60, were still unknown. The worker must find out how they are computed, whether the game checks them when loading, and so whether a self-built archive may contain modified or new content.

  • Four questions: how +0x50 is computed, whether and when it is checked, the same for +0x60, and what this means for custom archives.
  • The +0x60 value also decides whether a renamed or new image can find its texture.
  • Any proposed formula must reproduce stored values across at least three retail archives and fail on a single flipped byte.
  • "A hash is stored" and "a hash is checked" must be proven separately through the game's load path.
  • Read-only work only: no game launch and no writes to the install.

Diese Seite ist die Aufgabenstellung für einen Forschungs-Worker, kein Ergebnis. Für Wolfenstein II: The New Colossus waren die Prüfungen im Archiv-Header bereits gelöst. Zwei Felder pro Eintrag, der Daten-Hash bei +0x50 und der Wert bei +0x60, waren noch unbekannt. Der Worker soll herausfinden, wie sie berechnet werden, ob das Spiel sie beim Laden prüft und ob ein selbst gebautes Archiv damit veränderte oder neue Inhalte enthalten darf.

  • Vier Fragen: wie +0x50 berechnet wird, ob und wann es geprüft wird, dasselbe für +0x60 und was das für eigene Archive bedeutet.
  • Der Wert bei +0x60 entscheidet auch, ob ein umbenanntes oder neues Bild seine Textur findet.
  • Jede vorgeschlagene Formel muss gespeicherte Werte in mindestens drei Originalarchiven nachbilden und bei einem einzigen gekippten Byte scheitern.
  • „Ein Hash ist gespeichert“ und „ein Hash wird geprüft“ müssen getrennt über den Ladepfad des Spiels belegt werden.
  • Nur lesende Arbeit: kein Spielstart und kein Schreiben in die Installation.

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-datahash-a1; task datahash; research (read-only RE). Read .agent-cache/WORKER.md. Bus: python "%USERPROFILE%/.claude/skills/agent-cache-orchestrator/scripts/acbus.py" Parallel: astra-map-v3 (map bundle, other host), astra-save-v3, w-cmdtable-a1, w-saveverify-a1, w-vtrest-a3. Stay in your lane.

Objective

The container-identity blocker is gone: +0x08 and +0x20 are both solved and verified 28/28 (see re_probes/agent_reports/idclhash.md - read it first, it hands you the exact code region and the working tooling). What that unlocks is a self-built chunk whose PAYLOADS are carried over unchanged.

Your question is the one that decides whether a custom map may contain CHANGED content: the per-entry fields entry+0x50 (data_hash) and entry+0x60 (hash_0x60) are still unsolved.

Answer with code evidence:

  1. Is entry+0x50 computed over the payload bytes? Which algorithm, over the compressed or the uncompressed stream, and including what else?
  2. Is it VALIDATED on load - and if so, when: at mount, at first access of that entry, or never? What happens on mismatch?
  3. Same for entry+0x60. A prior worker established that the TexDB key is hash_0x60 << 4 | level (docs/texdb.md, re_probes/agent_reports/texdb_rewrite.md), so this field also decides whether a renamed or newly added image can ever resolve its texture. Is +0x60 derived from the name, the payload, or assigned by the build tool?
  4. Bottom line for the project: can a self-built chunk contain a MODIFIED or NEW payload and still mount and load? If yes, give the derivation. If no, name exactly which check stops it and where.

Sources / starting points

  • re_probes/agent_reports/idclhash.md and tools/probe_idclhash.py - READ FIRST, both read-only for you. They give you: the container parser idResourceStorage::OpenContainer .text RVA 0xACB780-0xACC441, the writer idResourceStorageGenerator::WriteContainer 0xAC9BD0-0xACADD4, the FarmHash64 function at 0x1363B80, and a working farmhash64 in Python (reused from tools/probe_tnc_hash.py). The entry table layout is 144 bytes per entry. The writer is your best entry point: whatever writes +0x50/+0x60 is in or near WriteContainer, and the reader side tells you whether anyone checks it.
  • re_probes/runtime_87400/module.bin - read-only capture of the RUNNING, SteamStub-unpacked NewColossus_x64vk.exe. Virtual RVA layout: file offset == RVA. Sections and image base in manifest.json. .pdata gives function bounds.
  • capstone 5.0.7 vendored: PYTHONPATH=re_probes/python_deps python ...
  • wolfsdk/idcl.py (our parser, read-only), tools/probe_tnc_hash.py (read-only), docs/texdb.md, re_probes/agent_reports/texdb_rewrite.md, docs/moddingflaeche-tnc.md.
  • Retail corpus, READ ONLY: /steamapps/common/Wolfenstein.II.The.New.Colossus

Ownership

tools/probe_datahash.py (new), re_probes/datahash/ (new dir), re_probes/agent_reports/datahash.md (new).

Forbidden / do not touch

No game launch, no process attach, no writes under the Steam install or "%USERPROFILE%/Saved Games". Do not touch files owned by others: tools/probe_idclhash.py, tools/probe_cmdtable.py, tools/probe_saveverify.py, tools/tnc_container_hash.py, tools/tnc_runtime*.py, tools/build_tnc_map_alias_v3.py, tools/verify_tnc_map_alias_v3.py, tools/build_custom_save_candidate.py, tools/probe_details_checksum.py, tools/verify_custom_save_candidate.py, tools/vtpixel.py, re_probes/idclhash/, re_probes/cmdtable/, re_probes/saveverify/, re_probes/map_alias_v3/, re_probes/custom_save_candidates/, docs/, wolfsdk/, config.json. No pip install.

Hard constraints

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

Acceptance criteria

  • Positive control, mandatory: whatever derivation you propose must reproduce the stored value for a large sample of real entries across at least three different retail archives - state the count, e.g. "n/n". The bar is the one probe_idclhash.py already cleared; do not fall below it.
  • Negative control: the derivation must FAIL on a payload with one flipped byte, and on a deliberately wrong offset or stream (compressed vs uncompressed).
  • The validation verdict (question 2) must rest on an xref chain into the load path, not on the field merely existing. "A hash is stored" and "a hash is checked" are different claims; keep them apart.
  • A plain answer to question 4 that a builder can act on.

Verification expectations

Every important assurance needs a check designed to fail if it is false. If you cannot find a reader for a field, say "no reader found, searched X and Y" rather than concluding it is unchecked - absence of evidence needs its own honest label.

Failure honesty

A clean negative is valuable: "modified payloads are impossible without solving Z" redirects the whole project immediately. Do not pad a hypothesis into a result. Report failed attempts with the offsets you tried.

Coordination / deliverable

Checkpoint at milestones. Publish a bus fact as soon as question 4 has an answer - astra-map-v3 is building a bundle right now and this decides what may go into it. Concise German report in re_probes/agent_reports/datahash.md. Finish the bus task when done.