diff --git a/docs/plan/level-assets.md b/docs/plan/level-assets.md index a3ab57b..9e0dfec 100644 --- a/docs/plan/level-assets.md +++ b/docs/plan/level-assets.md @@ -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 }` 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. + +### 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.