CORRECTION FIRST: a row in name-block-bases.txt is a (function, REGISTER) pair,
not a function. Every one-line label I carried for these blocks quoted one of
two rows, and the other row of the same function is an unrelated schema:
sub_822E3EC8 r11 = 29 shader constants + techniques, r10 = 15 material map slots;
sub_822AFA50 r11 = XDK shader-compiler tokens, r10 = 13 menu camera tags;
sub_823AE908 r11 = the 43-name S16 boss collision table, r31 = 33 shader tokens
(the dense-block false positive). Quote the register.
The engine's material vocabulary (into xbg7-mesh.md, which owns the
_col/_spc/_gls/_lum suffixes): nine base map slots -- ColorMap, LuminosityMap,
SpecularityMap, GlossinessMap, ReflectionMap, TransparencyMap, NormalMap,
FresnelMap, EdgeTransparencyMap -- and seven *MapArray twins; 9 - 7 = 2, and the
two without a twin are FresnelMap and EdgeTransparencyMap. Four of the nine are
exactly the four documented suffixes; the other five have no suffix in the
shipped meshes, so the engine supports more channels than the assets use. Plus
17 g_* shader constants, three cube samplers, and DepthOnly / MotionVector /
Transparent techniques -- the ...Last matrices with the motion-vector technique
say the renderer keeps the previous frame's per-object transform.
The S16 boss's collision parts (into collisionset.md): sub_823AE908 r11 is an
interleaved (mesh, logical-part) table -- rou_e901_body_02_c ->
Boss16CollisionBody02, five wing pairs, both tails, barrier, rou_e910_core_cmesh
-> Boss16CollisionCore, and mob_n900{,_b01,_b02,_gear}_cmesh -> Room00/01/02 +
Gear00/01/02. 23 logical parts + 20 meshes = 43, differing by exactly three:
Body01 opens with no mesh and the one gear mesh carries three gear names. Cross-
links the S16 Guardian/Core object found during the PlayerParams work.
Not settled: whether those meshes are CollisionSet entries, why Body01 has no
mesh, and no shader slot was traced to a shipped shader.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
9.1 KiB
CollisionSet_*.bin — the per-object collision-mesh library
✅ Decoded 2026-08-26. The 18 remaining hidden/MiscBin.pak entries, named
in the previous iteration as CollisionSet_S01…S16.bin,
CollisionSet_Tutorial.bin and CollisionSet_test.bin from the StageResource
objects' CollisionMeshes field. See
mcol-collision.md for the naming and for MCOL, which is
the map hull; this is the per-object library.
✅ All 18 are byte-identical
CollisionSet blobs: 18 distinct contents: 1
The per-stage naming is nominal. Every stage points at the same 1 675 148-byte library, stored eighteen times — which is why the sizes were identical, the observation that made this worth opening.
✅ The record layout
u32 size bytes following this word's own 8-byte prefix
u32 name_len 16, 24 or 32 — the name field, padded to a multiple of 8
char name[name_len]
u32 vertex_count
u32 triangle_count
f32 vertex[3] × vertex_count
u32 index[3] × triangle_count
and the next record starts at offset + 8 + size. Note the indices are u32
here, where MCOL uses u16 — these are two different serialisers.
| records | 158 |
| bytes consumed | 1 675 148 / 1 675 148 — exact |
size == 16 + name_len + 12·nv + 12·nt − 8 |
158 / 158 |
every triangle index < vertex count |
158 / 158 |
The walk consuming the file to the byte over 158 variable-length records, with the size word predicted from the two counts every time, is what makes this a decode rather than a plausible reading — a wrong field would desynchronise the walk within a few records and could not land exactly on the end.
✅ And they are meshes
| edges shared by exactly two triangles | 132 167 / 134 529 = 98.24 % |
| fully manifold meshes (every edge shared by two) | 147 / 158 |
92 of the 158 have Euler characteristic 2 — a single closed surface. The
remainder are multi-component (χ = 4, 6, 8) or open shells, which is expected
for parts like rou_e901_wing_01_L that are one piece of a larger hull.
✅ What is in it
158 meshes, 48 241 vertices and 90 836 triangles, in four families:
| prefix | count | what the names look like |
|---|---|---|
rou_ |
78 | rou_e101_bdy, rou_e101_brg_01, rou_e106_eng, rou_f104_sld_02 |
mob_ |
30 | mob_n040, mob_n110_bdy, mob_n900_gear |
rob_ |
4 | rob_e001, rob_e005_bdy, rob_f001_bdy, rob_f002 |
| stage asteroids | 46 | S01_Asteroid_cmesh_01a, S14_p1_Asteroid_cmesh_05 |
The _bdy / _brg / _eng / _wep / _sld suffixes are body, bridge, engine,
weapon and shield — the same sub-part vocabulary as the XBG7 render models, so
these are per-part collision proxies. The asteroid meshes carry exactly the
stage prefixes that have an _AsteroidVolume_wp MCOL.
✅ The names are the game's own resource ids (upgraded from 🟡 the same day)
The previous write-up recorded this link as untested, because matching
_cmesh stems against .xbg object names covered only 4 of 158 — the disc keeps
just one build manifest (machines\rou_e104\…), so that test had no power in
either direction.
The right corpus is not the manifests, it is the GameResourceID field of
the DefTables / GP_MAIN_GAME records — 480 distinct values, e.g.
GameResourceID = 'rou_e010'. Against those, with a control that shuffles the
characters of each stem:
ship / mob stems prefixed by a real GameResourceID |
108 / 112 = 96.4 % (55 exact) |
| same stems, characters shuffled (control) | 0 / 112 = 0.0 % |
| asteroid stems prefixed (expected none — they are not resources) | 0 / 46 |
So a CollisionSet entry is <GameResourceID>[_<part>]_cmesh: the collision
proxy for one part of one game resource. The four unmatched stems are
rou_e303_wep, rou_f301_body, rou_f302, rou_f303_body.
The 0 / 46 on asteroids is worth keeping: a test that fires on everything would be the bound-check hazard again. It separates the two families correctly.
🟡 The world unit — the metre reading does not survive this file
mcol-collision.md inferred 1 unit = 1 metre from
mapmesh_box_500km.col spanning exactly 500 000 units. The arithmetic is exact,
but this library is the first chance to check what that scale implies, and the
implications are large:
| mesh | bbox diagonal, if 1 unit = 1 m |
|---|---|
rou_e010 (e010_ADAN_Attacker_S — an "attacker, small") |
133 m |
rou_e106_bdy |
2 368 m |
rou_e101_bdy |
9 371 m |
rob_f001_bdy |
50 179 m |
S04_Asteroid_cmesh_04 |
84 714 m |
rob_f002 |
447 522 m — 89 % of the arena's width |
A craft the game's own tables call small would be 133 m, and the largest object
would nearly span the arena. That is not impossible for the genre, but it is not
the corroboration I claimed. Downgrading the scale claim to 🟡: either the
game's units really are metres and its ships are kilometre-scale, or 500km in
that filename names something other than the box's span. The 500 000 arithmetic
stands; the interpretation does not have independent support.
And there is no second instance of the convention to check against. Sweeping
every .pak on the disc for a name carrying a kilometre figure returns
mapmesh_box_500km.col / .rgn and nothing else — 162 references, all to that
one pair. So the reading rests on a single filename, with no corroborating
example anywhere in the data. That is not a refutation; it is the absence of any
static way to settle it.
My objection's own premise did survive its check: rou_e010 is a real
GameResourceID, and e010_ADAN_Attacker_S appears in the stage tables, so the
133-unit mesh does belong to a craft the game calls an attacker. (Whether the
trailing _S means "small" is a further guess — there are _EX4, _HF and
_HF_Wayne variants of the same unit — so it is suggestive, not evidence.)
🟡 Not blocked — just not run yet. An earlier version of this line said
"🔴 blocked on the oracle", and that was a mislabel. 🔴 is for what the container
cannot do; run-canary works here, and measuring the game is what it is for.
What the sweep above actually established is narrower and worth keeping: no
static test can settle this, because the disc contains exactly one
size-bearing asset name.
The experiment is well-supported by tooling that already exists:
findplayer.pyrecovers the player craft's live position triple from guest RAM by its motion, so a mission run yields positions in world units.- The HUD prints a distance to the selected target in the game's own units of measure.
- The same separation read both ways — Euclidean distance between the two position triples, against the number the HUD displays — is the conversion, measured rather than inferred from a filename.
pad.py scripts the target-select input (Ⓐ pressed twice, per AGENT.md),
and screenshot crops to the game surface. Nothing here needs anything the box
lacks. It is the next run.
Reproduce with tools/re-capture/collisionset.py verify / list
(../data/collisionset.txt); collisionset.py obj
exports any named mesh.
❔ Still open: the meshes carry no material, flag or surface-type field — the record is exactly counts, positions and indices — so whatever distinguishes a hull hit from a shield hit is not stored here. And the library is not indexed: lookup is presumably by name from the unit tables, which has not been traced.
✅ The Stage 16 boss's collision parts, named in the executable (2026-08-27)
Found by the base-solver (player-tuning-tables): sub_823AE908, r11,
43 names, and the list is an interleaved (mesh, logical-part) table:
rou_e901_body_02_c → Boss16CollisionBody02 rou_e901_wing_0N_{L,R}_c → …Wing0N{L,R}
rou_e901_tail_{L,R}_c→ Boss16CollisionTail{L,R} rou_e901_barrier_cmesh → …Barrier
rou_e910_core_cmesh → Boss16CollisionCore mob_n900_cmesh → …Room00
mob_n900_b01_cmesh → …Room01 mob_n900_b02_cmesh → …Room02
mob_n900_gear_cmesh → …Gear00 / …Gear01 / …Gear02
23 logical parts + 20 meshes = 43, and the two counts differ by exactly
three: Boss16CollisionBody01 opens the list with no mesh before it, and
mob_n900_gear_cmesh is followed by three gear names. A second row
(sub_823C0260, 15 names) lists the hull parts alone — Body01…03, TailL/R,
Wing01L…Wing05R — with no meshes.
🔑 This is the same boss the PlayerParams work turned up: the S16
Guardian / Core object (player-tuning-tables) names its weapons
Shell_S16Boss_*, and here rou_e910_core_cmesh → Boss16CollisionCore gives the
Core record a collision hull. rou_e901 is the boss craft; mob_n900 is the
station/room structure it sits in, whose three Gear parts share one mesh.
🟡 Not settled: whether these meshes are entries of the CollisionSet library
above (all 18 blobs are byte-identical, so a name-level join was not attempted),
and why Body01 has no mesh in the list.