re: MCOL array B decoded -- {count, u16 index array}, and the chain closes

Two corrections got there. MCOL has 9020 relocated words and only 4488 are
A-record pointers; I assumed the rest sat at B+8 mirroring A, refuted 0/4488.
Measuring their offset from the nearest preceding B record gives B+4 for 4488
(99.0%) and 44 before the first B -- exactly the four header pointers times 11
objects. Nothing unaccounted for.

So B is {u32 count, pointer at +4}. The pointers advance by exactly twice the
count: 4477/4477 (100.00%) over all 11 objects. That is a packed u16 array with
no padding, and it is the load-bearing evidence -- an exact arithmetic identity
over 4477 consecutive pairs. The companion check that those u16s are valid point
indices is the same weak bound-check flagged earlier and is recorded as
consistent rather than as evidence.

Chain: position -> cell -> A {cell index, count 1, ->B, sphere} -> B {count n,
->u16[n]} -> n indices into the point block. Same shape as REGN's cell -> item
-> refs -> geometry.

Open: the 0x54 and 0x58 blocks, which this chain never reaches, and what the
indexed points form.
This commit is contained in:
Sylpheed RE agent
2026-08-26 08:45:58 +00:00
parent 25ccb6723a
commit 8c57c0e621

View File

@@ -188,4 +188,52 @@ ways worth recording rather than retrying:
occupied cells and A already carries the cell's bounding sphere, so a candidate
field in B can be tested by whether it is spatially consistent with *that
specific cell* — the same design that worked for `REGN`'s faces, and the same
design that these two bound-checks lack.
design that these two bound-checks lack.
## ✅ Array B decoded — `{count, u16 index array}`, and the chain closes
**2026-08-26.** Two corrections got there.
**Where the other relocations live.** `MCOL` has 9 020 relocated words and only
4 488 are A-record pointers. I assumed the rest sat at `B+8`, mirroring A —
**refuted, 0 / 4 488**. Measuring their offset from the nearest preceding B
record instead:
at B + 4 4 488 (99.0 %)
before the first B 44 (1.0 %)
and those 44 are exactly the four header pointers × 11 objects. **Nothing
unaccounted for.**
**So B is `{u32 count, pointer}`** — pointer at `+4`, not `+8`. Read that way:
B@0x7720 count 0x2B ptr 0x84D0
B@0x7740 count 0x1C ptr 0x8526 0x8526 0x84D0 = 0x56 = 2 × 0x2B
B@0x7760 count 0x02 ptr 0x855E 0x855E 0x8526 = 0x38 = 2 × 0x1C
B@0x7780 count 0x02 ptr 0x8562 = 2 × 2
The pointers advance by exactly twice the count — a **packed `u16` array**, no
padding. Over all 11 objects:
| | |
|---|---|
| consecutive B pointers differ by **exactly `2 × count`** | **4 477 / 4 477 (100.00 %)** |
| the `u16` entries are valid `0x5C` point indices | 18 379 / 18 379 |
The first row is the load-bearing one: an exact arithmetic identity over 4 477
consecutive pairs. (The second is the same weak bound-check flagged above — the
point block is large, so almost any `u16` passes. It is consistent, not
evidence.)
### The chain
position → cell → A record {cell index, count 1, →B, bounding sphere}
→ B record {count n, →u16[n]}
→ n indices into the 0x5C point block
which is the same shape as `REGN`'s `cell → item → refs → geometry`, as the two
formats' shared header and shared count-1 convention already suggested.
❔ Still open: the `0x54` and `0x58` blocks (neither is reached by this chain),
what the indexed points form — triangles would want n divisible by 3 — and the
44-vs-4 488 accounting is exact, so there is no second pointer species to find.