Worker w-matpipe-a1; task matpipe; research/implement.
Read .agent-cache/WORKER.md. Bus: python "%USERPROFILE%/.claude/skills/agent-cache-orchestrator/scripts/acbus.py"
Parallel: w-meshfmt-a1, w-cmfmt-a1, w-entitypipe-a1, w-mapmanifest-a1.
You own surfaces: material -> image -> texdb, end to end.
Objective
Close the visual loop: put a texture we authored onto a surface in a TNC map.
1462 image and 388 material entries per map, and the lookup key that used to block this was solved today.
Answer and deliver:
- The
materialpayload format - how a material names its images and which slot is the albedo/diffuse. - The TNC
imagepayload (.bimage,BIM\x0e): can we author one, and in which pixel formats? Round-trip a retail image first. - The full chain: author an image, write the matching
.texdbrows, bind it through a material, so a named surface in a map would use our pixels.
What is already solved - do not redo it
- The TexDB key is solved and master-verified today:
key = ((entry+0x60 & 0x0FFF_FFFF_FFFF_FFFF) << 4) | (mip_base - mip_level), 25930/25930 across all 28.texdb. The asset NAME does not enter the key. Readre_probes/agent_reports/texdbkey.mdin full before you start - it also decoded the.bimagemip table (header 0x32 bytes, then 32-byte records: level, 0, w, h, raw_size, streamed/inline, stored_size, offset), and it establishes thatMountDatabasechecks only the magic and that a newchunk_N.resourcesauto-mounts itschunk_N.texdb. - Crucially it also says:
entry+0x60for images is assigned by the build tool and no reader recomputes it, so we may choose it freely - and 570 retail hashes are shared between image names, i.e. the engine itself deduplicates. Reusing a retail key gives retail pixels; own pixels need own texdb rows, written SORTED or the binary search fails. - Container writing is finished:
wolfsdk/idclwrite.py, byte-exact round-trip. - Part 1 image code exists and is read-only for you:
wolfsdk/bim.py,wolfsdk/image.py(BIM decode/encode, PNG in/out),tools/probe_texdb.py,tools/verify_image.py. Part 1 is BIM of a different version - check, do not assume.
Sources / starting points
re_probes/runtime_87400/module.bin- read-only capture of the RUNNING, unpacked executable (file offset == RVA, sections in manifest.json). The image/material loaders are in there; today's five wins all came from reading loaders rather than sweeping data.docs/texdb.md,docs/virtualtextures.md,docs/ui-assets.md(part 1 image replacement already works there,image-export/image-import).- Retail corpus READ ONLY:
/steamapps/common/Wolfenstein.II.The.New.Colossus - capstone 5.0.7 vendored: PYTHONPATH=re_probes/python_deps
Ownership
tools/probe_matpipe.py (new), re_probes/matpipe/ (new dir), re_probes/agent_reports/matpipe.md (new). Everything else read-only, including other workers' tools and dirs.
Forbidden / do not touch
No game launch, no process attach, no writes under the Steam install or "%USERPROFILE%/Saved Games". Do not edit wolfsdk/, docs/, config.json, tools/probe_texdbkey.py or any other worker's file. No pip install.
Hard constraints
Python 3.11, stdlib only (plus vendored capstone for disassembly). Reuse wolfsdk/oodle.py. No new image library - if a block-compressed format needs an encoder we do not have, say so rather than adding a dependency.
Acceptance criteria
materialparser with a byte-exact round-trip, n/n over at least 200 retail materials across 3 archives.imagepayload round-trip, n/n over at least 200 retail images, and the mip table cross-checked against the sizes the.texdbactually stores.- End-to-end demo: an authored image (a flat, unmistakable colour is ideal - it
is obvious on screen and trivially verifiable) plus its texdb rows plus a
material that points at it, all inside a container that passes
probe_datahashn/n andprobe_idclhashOK. - Negative controls: unsorted texdb rows, a key with the top nibble left unmasked, and a mip count that disagrees with the bimage header must each be caught by your checker.
Verification expectations
Nothing offline shows that a pixel reaches the screen. Say "structurally valid by these checks, rendering unconfirmed". Keep "the lookup will find our block" and "the GPU will decode it" strictly apart - the second depends on the pixel format, which is NOT yet established (texdbkey.md says so explicitly).
Failure honesty
If the pixel format turns out to be a block-compressed form we cannot encode without a new dependency, that is the answer: report which formats appear, with counts, and whether any uncompressed form is accepted. Part 1 has exactly this limitation documented - do not repeat its mistake of shipping an encoder whose output nobody ever looked at.
Coordination / deliverable
Checkpoint at milestones. Publish a bus fact when the image round-trip works - w-meshfmt-a1 needs materials for any authored geometry. Concise German report in re_probes/agent_reports/matpipe.md. Finish the bus task.