re: decode CollisionSet_*.bin -- the per-object collision-mesh library

All 18 blobs are byte-identical: the per-stage naming is nominal, and every
stage points at one shared 1675148-byte library stored eighteen times.  That
identical size was the reason to open the item, and it turned out to be the
answer to it.

Record layout: {u32 size, u32 name_len, char name[name_len], u32 nv, u32 nt,
f32[3] x nv, u32[3] x nt}, next record at off + 8 + size.  The indices are u32
here where MCOL uses u16 -- two different serialisers in one archive.

What makes this a decode rather than a plausible reading: the walk consumes the
file to the byte over 158 variable-length records, with the size word predicted
from the two counts 158/158.  A wrong field would desynchronise within a few
records and could not land exactly on the end.  All indices in range 158/158;
98.24% of edges shared by exactly two triangles; 147/158 fully manifold.

158 meshes, 90 836 triangles: per-part ship proxies (_bdy/_brg/_eng/_wep/_sld,
the XBG7 sub-part vocabulary) plus 46 stage asteroid meshes whose prefixes are
exactly the stages that have an _AsteroidVolume_wp MCOL.

Two things this file makes me walk back:

  * The "1 unit = 1 metre" reading from mapmesh_box_500km is downgraded to
    amber.  The 500000 arithmetic stands, but it implies that a craft the game's
    own tables call "small" is 133 m and that rob_f002 is 447 km -- 89% of the
    arena width.  The format check survives; the interpretation has no
    independent support.
  * The _cmesh <-> render-model name link is recorded as UNTESTED, not
    confirmed: only one .xbg build manifest survives on the disc, so matching
    stems against object names covers 4 of 158, which is no coverage at all.
This commit is contained in:
Sylpheed RE agent
2026-08-26 09:31:22 +00:00
parent 80ae860e19
commit d677bcfd80
5 changed files with 430 additions and 5 deletions

View File

@@ -425,8 +425,25 @@ search cannot find a *schedule*.
use that bare box; `_AsteroidVolume_` names the rest.
`tools/re-capture/miscbin_names.py <root> [--pairs]`
([`data/miscbin-names.txt`](data/miscbin-names.txt)).
❔ Still open: the 18 `CollisionSet_*.bin` are named but **not decoded** (magic
`0x00000810`, all exactly 1 675 148 bytes). The runtime consumer now has a
**`CollisionSet_*.bin` decoded (2026-08-26) — the per-*object* library.**
All 18 are **byte-identical**, so the per-stage naming is nominal: one shared
1 675 148-byte library stored eighteen times. Record =
`{u32 size, u32 name_len, char name[], u32 nv, u32 nt, f32[3]×nv, u32[3]×nt}`
(note `u32` indices, where `MCOL` uses `u16`), next at `off + 8 + size`. The
walk **consumes the file exactly** over 158 variable-length records with the
size word predicted from the counts **158/158**, all indices in range
**158/158**, and 98.24 % of edges shared by two triangles (**147/158** fully
manifold). 158 meshes / 90 836 triangles: `rou_`/`mob_`/`rob_` per-part ship
proxies (`_bdy`/`_brg`/`_eng`/`_wep`/`_sld`) plus 46 stage asteroids.
⚠️ **This downgraded the "1 unit = 1 m" claim to 🟡** — it implies a craft the
tables call *small* is 133 m and the largest object 447 km (89 % of the arena).
🟡 The `_cmesh`↔render-model name link is **untested, not confirmed**: only one
`.xbg` build manifest survives, so the check covers 4/158.
`tools/re-capture/collisionset.py verify|list|obj`
([`data/collisionset.txt`](data/collisionset.txt)).
❔ Still open: no material/surface-type field exists in the record, and the
library is not indexed — name lookup from the unit tables is untraced.
The runtime consumer now has a
name — `CMapColliderBridge` in the `.pe` RTTI at 9 044 264 — but has not been
followed into the code.
See [`structures/mcol-collision.md`](structures/mcol-collision.md).