Skip to content

Research Brief Datahash

LopeKinz edited this page Oct 1, 2026 · 2 revisions

Identity

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.

Clone this wiki locally