The previous test only tried section-1 targets. Closing that gap: the payload's three index-shaped u32s, followed into the point list and the plane list and checked for the target lying inside the referencing cell, all sit at the 0.203% random control. Two cells read 0.81%, 4x the baseline. I am not treating that as a lead: across this and the previous iteration roughly twenty such tests have been run, and at that count a single 4x enrichment on ~8000 trials is what noise looks like. Calling it a signal would be the multiple-comparisons error a long hypothesis sweep invites. So REGN's header, grid, points, planes and cell index are decoded, section 1's slot regions are censused, and the link between the grid and the geometry is not reachable by any static test I can construct. The honest next step is the PE code that reads a REGN object -- the same kind of work that cracked the .slb packing phase -- rather than a twenty-first correlation.
376 lines
17 KiB
Markdown
376 lines
17 KiB
Markdown
# `REGN` — a per-map spatial grid (and `MCOL` beside it)
|
||
|
||
**Status: ✅ `CONFIRMED` for the header**, which self-checks on all 11 objects on
|
||
the disc. ❔ the four data sections are undecoded. **New to this corpus** — no
|
||
document mentioned `REGN`, `MCOL` or `hidden/MiscBin.pak` before 2026-08-24.
|
||
|
||
## Where it is
|
||
|
||
`hidden/MiscBin.pak` — 40 entries, **none** name-resolved, in three groups:
|
||
|
||
| magic | count | sizes |
|
||
|---|---|---|
|
||
| `REGN` | **11** | 49 KB … 3.1 MB |
|
||
| `MCOL` | **11** | 37 KB … 81 KB |
|
||
| (other) | 18 | — |
|
||
|
||
Eleven of each, which pairs them: one `REGN` and one `MCOL` per map. `MCOL` is
|
||
untouched here; the name and the size range read like mesh collision.
|
||
|
||
## The header, and why it is believable
|
||
|
||
```
|
||
0x00 char[4] 'REGN'
|
||
0x04 u32 size of the data area (the POF0 table starts at 0x04-value + 16)
|
||
0x10 f32[4] bbox min (x, y, z, 1.0)
|
||
0x20 f32[4] bbox max (x, y, z, 1.0)
|
||
0x30 f32[4] extent (max - min)
|
||
0x40 f32[4] cell size
|
||
0x50 u32[4] grid dimensions
|
||
0x60 u16[6] six counts
|
||
0x70 u32[4] four section offsets (the first is always 0x80)
|
||
```
|
||
|
||
**The check that makes this a decode rather than a guess** — over all 11 objects:
|
||
|
||
* `extent == cell × dims` holds **11 of 11**, exactly;
|
||
* `counts[3]` equals the **cell count**: `1000` on every 10×10×10 map and `125`
|
||
on every 5×5×5 one.
|
||
|
||
Two independent fields reproducing the grid is what rules out coincidence.
|
||
|
||
## The three map sizes on the disc
|
||
|
||
| half-extent | cell | dims | objects |
|
||
|---|---|---|---|
|
||
| 250 000 | 50 000 | 10×10×10 | 2 |
|
||
| 50 000 | 10 000 | 10×10×10 | 6 |
|
||
| 25 000 | 10 000 | 5×5×5 | 3 |
|
||
|
||
So every map is a cube partitioned into 125 or 1 000 uniform cells — 10 km cells
|
||
in a 100 km cube for the common case, and one pair of maps five times larger.
|
||
|
||
## ✅ Section 3 is the cell index — and it self-checks 11/11
|
||
|
||
The fourth section is a **one entry per cell** table of 8-byte records
|
||
`(count, offset)`, immediately followed by the records those offsets point at:
|
||
|
||
```
|
||
index = offsets[3] .. offsets[3] + cells*8
|
||
payload = align16(index end) ..
|
||
record = 32 bytes (offsets step by 0x20)
|
||
```
|
||
|
||
Checked over all 11 objects: the lowest offset any cell refers to equals
|
||
**`align16(offsets[3] + cells × 8)` — 11 of 11**. On the six 10×10×10 maps
|
||
`cells × 8` is already 16-aligned and the payload butts straight up against the
|
||
index; on the three 5×5×5 maps `125 × 8 = 1000` is not, and the payload starts
|
||
8 bytes later, which is what makes the alignment rule visible rather than assumed.
|
||
|
||
Two more invariants from the same sweep:
|
||
|
||
* every occupied cell has count **exactly 1** — total items equals occupied cells
|
||
on all 11 objects, so this is "one record per cell", not a bucket list;
|
||
* **`counts[4] = occupied cells + 2`**, exactly, on all 11 (e.g. 997/995,
|
||
880/878, 125/123). The `+2` is unexplained — two sentinels, or two cells
|
||
counted differently.
|
||
|
||
Most cells are occupied: 878–998 of 1 000, 123 of 125.
|
||
|
||
## ✅ It is a serialised object graph with a `POF0` fixup table
|
||
|
||
Every one of the 11 objects contains the tag **`POF0`**, always near the tail,
|
||
and its position is exactly **`header[0x04] + 16`** — on **11 of 11**:
|
||
|
||
```
|
||
e993b93e header +0x04 = 0x0b100 POF0 at 45328 = 45312 + 16
|
||
e4155d94 header +0x04 = 0x235d70 POF0 at 2317696 = 2317680 + 16
|
||
… 11 of 11 identical relation
|
||
```
|
||
|
||
`POF0` is a **pointer-offset (fixup) table**: the file is a serialised C++ object
|
||
graph, and the loader patches the recorded slots into real pointers. That
|
||
explains a detail that would otherwise be odd — the "offsets" inside the cell
|
||
index are absolute **file** offsets, because that is what a fixup table rewrites.
|
||
|
||
So `header[0x04]` is the size of the data area, and everything past
|
||
`header[0x04] + 16` is relocation bookkeeping rather than content.
|
||
|
||
## 🔴 Two readings of the cell payload, both refuted by generalising
|
||
|
||
Both came from the smallest object and both died the moment they were checked
|
||
against the other ten — recorded because the temptation to keep them was real:
|
||
|
||
* **"the `f32` at record `+0x1c` is the grid's bounding-sphere radius."** On
|
||
`e993b93e` it is 86 689 against `√3 × 50 000 = 86 603`, a ratio of **1.001**.
|
||
On the other ten the ratio runs **0.13 – 0.27**. Fitted to one sample.
|
||
* **"a record's `(count, offset)` pairs point at leaf arrays of `count × 4`
|
||
bytes."** True for the first record of `e993b93e`; across the objects the
|
||
offset deltas fail that rule on **every** object checked (0 of 11 clean).
|
||
|
||
What survives is only descriptive: the payload area is dominated by **float
|
||
data** — the "strings" a printable-run scan finds are all byte patterns like
|
||
`0x46`/`0x47` high bytes, i.e. medium-magnitude floats, not text.
|
||
|
||
## ❔ The other three sections
|
||
|
||
Their offsets scale with the object, and `counts[0..2]` scale with them —
|
||
`(318, 1172, 2584)` for the 350 KB map against `(2936, 14967, 31155)` for the
|
||
3.1 MB one, a roughly `1 : 4.5 : 10` ratio that holds across all eleven. The
|
||
smallest object (49 KB) is nearly empty by comparison — `(8, 6, 18)` — which
|
||
makes it the cheapest one to decode first.
|
||
|
||
## Why this matters, stated without overclaiming
|
||
|
||
A mission's enemy count **rises and falls** as waves arrive and are destroyed, so
|
||
somewhere there is a scheduler with parameters — what spawns, where, and on what
|
||
trigger. A per-map uniform grid indexed by cell is exactly the structure such a
|
||
thing is indexed *by*.
|
||
|
||
🔴 **But nothing here shows spawn parameters yet.** The header is a spatial
|
||
partition and no more; the sections are unread. Treat this as the location of the
|
||
world's spatial data, not as the wave table.
|
||
|
||
## ✅ Update: `REGN` is a stage's **MapPath**
|
||
|
||
The per-stage definition record (see
|
||
[stage-definition-table.md](stage-definition-table.md)) has a field
|
||
`MapPath = test.rgn`, and `name_hash("test.rgn") = 0x3506e972`, which is one of
|
||
the `REGN` objects in `MiscBin.pak`. The sibling field `MapMesh = test.col`
|
||
hashes to `0x2cf7eb47`, an `MCOL` object in the same pak.
|
||
|
||
So `.rgn`/`REGN` is stage navigation/path data referenced by the stage record,
|
||
and `.col`/`MCOL` is the stage collision mesh. This does not by itself validate
|
||
either of the two refuted cell-payload readings recorded above, but it does
|
||
explain why the payload looks like a grid of route data.
|
||
|
||
|
||
## ✅ Sections 0, 1 and 2 have record strides — and section 2 is a PLANE list
|
||
|
||
**2026-08-26.** The three sections the page called undecoded are fixed-stride
|
||
record arrays, and `counts[0..2]` are their record counts. Dividing each
|
||
section's byte span by its count over all 11 objects:
|
||
|
||
| section | stride | evidence |
|
||
|---|---|---|
|
||
| 0 | **12 bytes** | `count × 12` fits with a remainder of 0–12 in **11 / 11** |
|
||
| 1 | **96 bytes** | `count × 96` fits with a remainder of **exactly 0 in 11 / 11** |
|
||
| 2 | **48 bytes** | `count × 48` fits with a remainder of **exactly 96 in 11 / 11** |
|
||
|
||
Section 1 landing on a zero remainder in every object, and section 2 on the same
|
||
96-byte tail in every object, is what makes these strides rather than a
|
||
coincidence of division.
|
||
|
||
### ✅ Section 0 is a point list
|
||
|
||
12 bytes is three `f32`. Over **13 467** records across all 11 objects, **every
|
||
one lies inside that object's own header bounding box — 13 467 / 13 467 (100 %)**.
|
||
Values land on the box corners (`±250 000`) and inside.
|
||
|
||
### ✅ Section 2 is a plane list — 48 bytes, and the plane equation closes
|
||
|
||
Read as twelve `f32`:
|
||
|
||
[0..3] zero
|
||
[4..6] unit normal |n| = 1 ± 0.02 in 133 573 / 133 573 (100 %)
|
||
[7] signed distance d
|
||
[8..10] a point on the plane, inside the bbox in 133 573 / 133 573 (100 %)
|
||
[11] 1.0 exactly in 133 573 / 133 573 (100 %)
|
||
|
||
**The check that makes this a decode**: for a genuine plane, `n·p + d` must be
|
||
zero. Over all **133 573** records:
|
||
|
||
|n·p + d| / scale : median 2.29e-08 p90 6.78e-08 max 2.15e-07
|
||
|
||
That is float round-off, not a fit — the relation holds to the last bits of a
|
||
32-bit float in **every record on the disc**. Three independent 100 % properties
|
||
(unit normal, point in bbox, trailing 1.0) and an exact algebraic identity are
|
||
well past what a wrong reading survives.
|
||
|
||
So a `REGN` object carries, alongside its uniform grid, a **point list** and a
|
||
**plane list** — which is the shape of collision or region-boundary geometry,
|
||
and consistent with `MCOL` sitting beside it.
|
||
|
||
### ❔ Still open
|
||
|
||
* **Section 1** (96 bytes/record, **63 410** records disc-wide) — a per-slot
|
||
census is below, but what the record *means* is still ❔.
|
||
* **What the planes are for.** "Collision or region boundary" is a reading of the
|
||
shape; nothing here shows what queries them.
|
||
* The **zeros at `[0..3]`** of every plane record, and the constant `96`-byte
|
||
tail after section 2, are unexplained.
|
||
|
||
|
||
## 🟡 Section 1, slot by slot — measured, but not read
|
||
|
||
**2026-08-26.** 96 bytes is 24 slots. Censusing every one of the **63 410**
|
||
records across all 11 objects gives a clear regional structure, even though the
|
||
record's purpose is not settled:
|
||
|
||
| slots | what the values are | reading |
|
||
|---|---|---|
|
||
| 0–3 | slots 2 and 3 are zero in ~100 %; 0 and 1 mostly small | ❔ |
|
||
| **4–6** | 96 % have \|v\| > 1 000, range **±250 000** — the header bbox range | 🟡 a **position** |
|
||
| **7** | 99.9 % > 1 000, always positive, 519 … 107 600 | 🟡 a **radius or extent** |
|
||
| 8–11 | as `f32` these are **denormals** (1.4 × 10⁻⁴⁵ upward) — i.e. they are **integers**, not floats | ✅ integer fields |
|
||
| 12–23 | six **pairs**: the even slot 200 … 67 000 and never zero, the odd 0 … 212 000 and zero in 7–13 % | ❔ |
|
||
|
||
The denormal signature in slots 8–11 is worth stating plainly: a float field
|
||
never holds `1.4e-45`, so those four words are integers that a float reader
|
||
would silently turn into near-zero garbage.
|
||
|
||
A position plus a positive scalar plus integer links is the shape of a
|
||
**bounding-volume hierarchy node**, which would fit a file that also carries a
|
||
point list and a plane list. That is a reading of the shape and nothing more.
|
||
|
||
### ❌ The index test has no discriminating power
|
||
|
||
I tried to confirm the integer slots are indices by splitting each into two
|
||
`u16`s and checking them against each section's record count. The result is
|
||
useless, and the reason is worth recording:
|
||
|
||
| slot | halves valid for section 0 | section 1 | section 2 |
|
||
|---|---|---|---|
|
||
| 8 | 100.00 % | 100.00 % | 100.00 % |
|
||
| 9 | 100.00 % | 99.99 % | 100.00 % |
|
||
| 10 | 8.78 % | 44.19 % | 100.00 % |
|
||
| 11 | 8.76 % | 44.16 % | 100.00 % |
|
||
|
||
**A test that accepts every hypothesis rejects none.** Section 2 has tens of
|
||
thousands of records, so "is this `u16` below the plane count" is satisfied by
|
||
almost any small number — it measures the size of the section, not the meaning
|
||
of the field. Only slots 10 and 11 discriminate at all, and they merely rule
|
||
*out* section 0.
|
||
|
||
`slot 11`'s halves are consecutive (`n`, `n+1`) in 54 % of records and slot 10's
|
||
in 12 % — suggestive of paired links, but 54 % is not a rule and I am not
|
||
promoting it.
|
||
|
||
❔ So section 1 stays open. What would settle it is a test with power: pick a
|
||
record, follow a candidate index, and check that the thing it lands on is
|
||
spatially consistent with that record's own position and radius. That needs the
|
||
tree walked, not the fields counted.
|
||
|
||
## ❌ The BVH reading is refuted — and slot 7 is a *local* scale
|
||
|
||
**2026-08-26.** Last iteration I wrote that "position + positive scalar +
|
||
integer links is the shape of a bounding-volume hierarchy node", explicitly as a
|
||
reading of the shape. Tested with a design that has power, it fails.
|
||
|
||
**The containment test.** If slots 8–11 hold child indices, a child's sphere
|
||
should sit inside its parent's. Following every `u16` half of every integer slot
|
||
and checking `|C_child − C_parent| + R_child ≤ R_parent` (2 % slack):
|
||
|
||
RANDOM control 0 of 126 787 = 0.00 %
|
||
slot 8 half 0 63 389 tried 0.00 %
|
||
slot 8 half 1 63 395 tried 0.00 %
|
||
…every candidate… 0.00 %
|
||
|
||
**The random control is the informative row.** It is also 0.00 %, which means no
|
||
node's sphere contains any other node's sphere *anywhere in the file* — so there
|
||
is no nesting for an index to point at, whatever the indices mean. The
|
||
hypothesis fails before the indices are even in question.
|
||
|
||
**Why**: slot 7 is far too small to bound neighbours.
|
||
|
||
| | median | p10 | p90 |
|
||
|---|---|---|---|
|
||
| slot 7 | **3 139** | 1 965 | 9 275 |
|
||
| pairwise centre distance | **45 457** | 19 071 | 126 295 |
|
||
|
||
Slot 7 is **14× smaller** than the typical distance between nodes, and a random
|
||
other centre falls within it only **0.40 %** of the time. It is also smaller
|
||
than the smallest grid cell on any map (10 000).
|
||
|
||
So ✅ **slot 7 is a local scale, not a hierarchy radius** — sub-cell sized, with a
|
||
narrow spread. Together with 63 410 scattered centres across a 500 km cube, that
|
||
is the shape of **many small independent volumes**, not a tree.
|
||
|
||
🟡 That fits per-object collision volumes — a map's asteroids and debris, which
|
||
the mission `Route` tables independently show as `Frame_S<NN>_Asteroid` records.
|
||
Stated as a reading, not a measurement; nothing here counts objects.
|
||
|
||
❔ Still open: what slots 8–11 index, and what the six pairs in 12–23 are. What
|
||
this iteration removed is a wrong frame — the file is not a tree, so tree-shaped
|
||
tests will keep returning nothing.
|
||
|
||
## ❌ The cell index does not reference section 1 — two powered tests, both negative
|
||
|
||
**2026-08-26.** The obvious coupling in a file with a uniform grid and a list of
|
||
small volumes is that the grid indexes the volumes. It does not, by the only
|
||
test that could show it: **spatial agreement**.
|
||
|
||
**Test 1 — the cell payload as indices.** For every occupied cell, read its
|
||
32-byte payload record and try each `u16` in it as a section-1 index, then check
|
||
whether that node's centre lies **inside the cell that referenced it**:
|
||
|
||
RANDOM control 0.138 %
|
||
+0 0.08 % +2 0.18 % +4 0.11 % +8 0.08 %
|
||
+10 0.10 % +12 0.08 % +14 0.08 % …
|
||
|
||
Every field sits at the chance rate. **Nothing points at section 1.**
|
||
|
||
**Test 2 — the cell payload as coordinates.** 32 bytes is eight floats, so a
|
||
position could be in there. Trying every float triple and asking whether it lies
|
||
inside its own cell:
|
||
|
||
+0 0.81 % +4 0.81 % +8 0.15 % +12 0.16 % +16 0.26 % +20 0.78 %
|
||
|
||
Also chance.
|
||
|
||
### ⚠️ And the tempting number in that table is worthless
|
||
|
||
The same run reported those triples lie **inside the object's bounding box in
|
||
100.00 %** of cases, at five different offsets. That looks like a decode and is
|
||
not: the bbox spans the entire 500 km map, so *any* mid-range float triple
|
||
passes, and overlapping windows starting at +0 and +4 both scoring 100 % is the
|
||
tell — a real field would not survive being read at a four-byte shift. It
|
||
measures the size of the box, not the meaning of the bytes. This is the third
|
||
time in this file's investigation that a containment test against something
|
||
large has produced a meaningless 100 %, so it is recorded rather than quietly
|
||
dropped.
|
||
|
||
❔ So the grid and section 1 have no demonstrated link, and how a cell reaches
|
||
its geometry is unknown. What is now excluded: the cell payload holding
|
||
section-1 indices, and holding cell-local coordinates.
|
||
|
||
✅ Incidental, from the same sweep: `u32` slots at **+0, +8 and +12** of the
|
||
payload record are below `0x10000` in **100 %** of records, while +4, +16, +20
|
||
and +24 are in only 11 % and +28 never — so the record has three index-shaped
|
||
fields and four wide ones, whatever they refer to.
|
||
|
||
## ❌ …nor the point list, nor the plane list — the static coupling search is exhausted
|
||
|
||
**2026-08-26.** The previous test only tried section-1 targets, which left the
|
||
obvious gap: the payload's three index-shaped `u32`s might address the **points**
|
||
or the **planes** instead. Tested the same way — follow the index, ask whether
|
||
the target lies inside the cell that referenced it:
|
||
|
||
RANDOM control 0.203 %
|
||
+0 -> points 0.17 % planes 0.16 %
|
||
+8 -> points 0.81 % planes 0.09 %
|
||
+12 -> points 0.81 % planes 0.09 %
|
||
|
||
All at the control rate. The two 0.81 % cells are 4× the baseline, and I am
|
||
**not** treating that as a signal: across this and the previous iteration I have
|
||
now run on the order of twenty of these tests (three index fields × three
|
||
sections × two readings × several offsets), and at that count a single 4×
|
||
enrichment on ~8 000 trials is what noise looks like. Reporting it as a lead
|
||
would be exactly the multiple-comparisons error that a long hypothesis sweep
|
||
invites.
|
||
|
||
### Where this leaves `REGN`
|
||
|
||
✅ Decoded: the header and grid, section 0 (points), section 2 (planes), section
|
||
3 (the cell index), and the strides and field regions of section 1.
|
||
|
||
❌ Not decoded, and **not reachable by the tests available statically**: any link
|
||
between the grid and the geometry. Every index-shaped field has been followed
|
||
into every section and checked for spatial agreement, against controls, and
|
||
nothing rises above chance.
|
||
|
||
❔ **What would actually settle it** is the code — find what reads a `REGN`
|
||
object in the executable and watch which fields it dereferences. That is static
|
||
PE work (`/work/*.pe`, offset = VA − 0x82000000) of the same kind that cracked
|
||
the `.slb` packing phase, and it is the honest next step rather than a
|
||
twenty-first correlation. |