Stop pattern-matching RAM: follow UpdateCamera_6 from lvl.camvtbl

Two more frustum searches, both unproductive, then the lookup that should have come
first.

Non-orthonormal 4x4 matrices within 4 KB of the camera, reasoning that the
projection must live nearby: 79 candidates, every one a sliding window over data
rather than a matrix. The filter does not discriminate and the region has no
obvious projection.

Then: the decomp names the camera. include/engine.h and
docs/AUG6-RETAIL-ANCHORS.md reference UpdateCamera_6, InitCamera_24 and
Camera_CollPrimTest, and docs/COMMUNITY-ENGINE-REFERENCE.md places lvl.camvtbl at
0x0026E900. The camera dispatch table is already characterised -- 217 records, 14
distinct ids on level 0, handlers in the overlay .text.

That is the right way in. The camera writes its matrices at 0x18aa70; the function
that does so is reachable from camvtbl, and the frustum is whatever that same
function writes nearby. Reading it would confirm m4 by finding the write site, and
pick up the frustum constants beside it, without guessing at float patterns.

The caveat that applies first, and why this was not done first: the decomp's
function addresses have already failed once here. PROVENANCE.md records that they
do not resolve for the moby class loader, while struct layouts transcribed from the
decomp were usable. So UpdateCamera_6's address must be verified against the
overlay before following it, not trusted from the name.

Resuming here is a different kind of task from the three searches above: follow a
known call site instead of pattern-matching a 32 MiB heap.

294 passing, clippy clean.
This commit is contained in:
2026-10-15 03:32:18 +02:00
parent ca42793e48
commit 20655c7744
+35
View File
@@ -2951,3 +2951,38 @@ planes, is not among them. If it is stored as `near`/`far`/`tan` scalars -- whic
is what `guard_band`'s signature suggests, since it takes `Frustum { near, far, tan }` is what `guard_band`'s signature suggests, since it takes `Frustum { near, far, tan }`
rather than six planes -- then the search should be for a stable float pair with a rather than six planes -- then the search should be for a stable float pair with a
plausible ratio, not for normals at all. That is the next search, and it is cheap. plausible ratio, not for normals at all. That is the next search, and it is cheap.
### Stop scanning RAM: the camera function is the anchor
Two more RAM searches for the frustum, both unproductive, and then the thing that
should have been looked up first.
**Non-orthonormal 4x4 matrices within 4 KB of the camera**, on the reasoning that
the projection must live nearby: 79 candidates, and every one of them is a sliding
window over data rather than a matrix -- `m23` and `m32` landing on the translation
and unrelated neighbours. The filter is not discriminating and the region does not
contain an obvious projection.
**The decomp names the camera.** `include/engine.h` and
`docs/AUG6-RETAIL-ANCHORS.md` reference **`UpdateCamera_6`**, **`InitCamera_24`**
and `Camera_CollPrimTest`, and `docs/COMMUNITY-ENGINE-REFERENCE.md` places
`lvl.camvtbl` -- the camera vtable -- at `0x0026E900`. The camera dispatch table is
already characterised: **217 records, 14 distinct ids** on level 0, handler
addresses in the overlay's `.text`.
That is the right way in. The camera writes its matrices at `0x18aa70`; the
function that does so is reachable from `camvtbl`, and the frustum will be whatever
that same function writes nearby. **Reading the camera function finds both the
write site that confirms `m4` and the frustum constants beside it**, without
guessing at float patterns.
**Caveat that applies before starting**, and is the reason this was not done first:
the decomp's function addresses have already failed once in this project --
`PROVENANCE.md` records that the decomp's addresses do not resolve for the moby
class loader, and that struct layouts transcribed from the decomp were usable while
addresses were not. So `UpdateCamera_6`'s address has to be **verified against the
overlay** before following it, not trusted from the name.
**This is where the frustum hunt should resume**, and it is a different kind of
task from the three searches above: follow a known call site rather than pattern-
match a 32 MiB heap.