TNC stores large normal-map mips using an undocumented "codec 2" tile-chain format whose inner pixel layout earlier research could not decode, having already ruled out raw planes, simple raster BC4/BC5 blocks, and a GPU-dispatcher explanation. This pass tested four more concrete layout hypotheses — two BC5-specific geometric splits, a BC4 bit-plane split, and "the high-entropy region is just top-anchored raster data" — and every one was rejected using the same derangement-plus-correlation negative-control discipline as earlier work. The most useful new result is structural, not a solved layout: every codec-2 tile has a short, higher-entropy "head" region followed by a long, nearly flat "tail" dominated by a single constant byte, a real and reproducible pattern that no tested hypothesis explains yet. This is pure static byte-level and disassembly research with no game launch; the practical modding workaround (write replacement textures using the simpler, understood "codec 1" format at any size) is unaffected either way.
What was ruled out this round
All four tested with real negative controls (a scrambled/derangement version of each hypothesis, which should score the same as the real hypothesis if the hypothesis is wrong — and did, every time):
- BC5 as two GPU-hardware-standard sparse tiles placed side by side (a genuinely new geometric idea, distinct from the already-rejected whole-tile raster reading).
- BC5 stored as two separate channel planes (all X-channel blocks, then all Y-channel blocks) instead of the normal interleaved format.
- BC4 stored as a structure-of-arrays split (all endpoint pairs, then all index data) instead of interleaved per block.
- The short high-entropy "head" region read as plain top-anchored raster BC4.
This brings the running total to 9 rejected pixel-layout/mechanism hypotheses across two research passes, all tested the same rigorous way.
The real structural finding
A byte-statistics scan (independent of any pixel-decoding assumption) shows every codec-2 tile has two clearly distinct regions: a short "head" (roughly the first 3–6% of the buffer, varying per tile rather than sitting at a fixed offset) at meaningfully higher entropy, followed by a long, nearly flat "tail" at very low entropy. The tail's single most common byte value is 0x7F in every one of 16 spot-checked tiles (42–95% share) — the tangent-space-neutral value for a normal-map channel, consistent with (not proof of) genuine but heavily redundant normal-map content. A follow-up test found a real but modest statistical link between how long the head region is and how much real visual detail the corresponding reference image has (weak positive correlation, stronger for BC5 than BC4) — consistent with a content-driven, variable-length payload rather than a fixed container field, though the effect is too small to use as a hard layout boundary by itself.
Two more candidate explanations for the head region were tested and rejected: it is not a second, nested compressed stream (a random-byte control "detected" a fake compressed stream more often than the real head bytes did), and it does not correspond to id Software's older, now-abandoned virtual-texture ("MegaTexture") format — an independent check of public community documentation confirmed TNC specifically dropped that older system in favor of the simpler streaming format this project already fully understands (unlike a contemporaneous sibling game on the same engine generation, which kept it) — a genuine engineering difference between the two games, not a property of the shared engine family.
Engine code trace
Disassembly of every place in the executable that reads the per-tile "codec" byte (four sites total now, up from two in earlier work) found every one of them to be bookkeeping — a logging/telemetry call, a lock-free queue push, and a flat struct copy forwarding the tile's metadata into what looks like a render-thread command buffer. None of the four branches on the codec value to do anything pixel-shaped. One newly found site (a large, only partially examined function that forwards the tile record toward a render-backend command buffer) is the single most promising remaining lead for static analysis, but has not yet been walked to its actual consumer.
For modders
Nothing changes the practical recommendation from earlier work: ship replacement textures/mips using the simpler, already-understood "codec 1" format, which the engine accepts at any size — codec 2 itself still has no known encoder and isn't needed for ordinary texture replacement.
Open questions
- What the head region actually contains.
- Whether the tail's near-constant content is genuine (if redundant) texture data or allocation padding — one cheap, still-untested check: compare tail bytes byte-for-byte across two unrelated, genuinely flat textures.
- Where the render-command buffer found this pass is ultimately consumed, and whether that code ever branches on the codec byte.
- A GPU-level trace (e.g. with a graphics debugger during an actual texture upload) remains the only lead that isn't more static guesswork, and was out of scope for this read-only track.