acdream/docs/research/2026-08-30-cathedral-review-datformat.md
Erik 6d990d38b3 docs: the cathedral seven-report synthesis + adjudicated FW4 plan
Files the independent review corpus (fable/opus/external + audit,
DAT-format, F418 DAT-geometry, retail decomp reconstruction) and the
synthesis that adjudicates their disagreements: retail roots INTERIOR
at the posed terrace defect pose with a ONE-CELL flood and ov=1 (the
free captures rooted outdoor - both were real); the falls are outdoor
landblock emitters 0xCF418000-13; the "thin seam bands" claim is
DAT-refuted (full-size exits; the seam is a coincident double
exit-to-outside plane at y=48); clear+seals live inside retail''s ov>0
block with a one-frame seal latch. Carries the instrument-first plan
(falls-owner trace, depth checkpoints, pose conformance) and the
decomp-pinned repair sequence toward FW4''s single-owner goal.

Also sweeps in the probe scaffolding slice 5''s path-limited add had
missed (RenderingDiagnostics field + the launch-options row wording).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 20:52:14 +02:00

93 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Cathedral review — DAT-format facts (companion report)
Delivered 2026-08-30 by the DAT-format verification agent (decompiled the
actual `Chorizite.DatReaderWriter 2.1.7` NuGet binary with ilspycmd and
cross-checked against `docs/research/named-retail/acclient.h`). Key facts
for the cathedral synthesis; flagged caveats preserved.
## Sourcing caveats
- Our DAT parser is the CONSUMED NuGet `Chorizite.DatReaderWriter 2.1.7`
(no vendored source; facts below come from decompiling the exact linked
DLL).
- `references/WorldBuilder` is an uninitialized submodule in THIS worktree
(read from the main worktree at a different SHA — flagged).
- `references/ACViewer` does not exist in either worktree (claims about
ACViewer: UNVERIFIED).
## EnvCell record (read order, decompiled Unpack)
Flags (int) → self-Id (uint, duplicate) → NumSurfaces (byte) → NumPortals
(byte) → NumVisibleCells (ushort) → Surfaces[]ushort) → EnvironmentId
(ushort) → CellStructure (ushort) → Position (Frame) → CellPortals[] →
VisibleCells[] (ushort) → [HasStaticObjs 0x2] StaticObjects (count +
Stab{Id,Frame}[]) → [HasRestrictionObj 0x8] RestrictionObj.
`EnvCellFlags`: SeenOutside=0x1, HasStaticObjs=0x2, HasRestrictionObj=0x8.
**0x4 is unclaimed.**
Retail cross-check: `CEnvCell : CObjCell` (acclient.h:32072-32091) maps
1:1; retail's `stab_list` lives on the BASE `CObjCell`
(acclient.h:30914-30932) and is the **PVS list of CELL IDS** — NOT placed
objects. The DatReaderWriter `Stab{Id,Frame}` placed-object struct is a
coincidental homonym (zero matches for `Stab` in the named-retail header).
## CellPortal / BuildingPortal
`CellPortal { PortalFlags Flags; ushort PolygonId; ushort OtherCellId;
ushort OtherPortalId; }``PortalFlags: ExactMatch=1, PortalSide=2`.
**No 0x4 member anywhere** (package, our code, WorldBuilder, and retail's
own `CCellPortal` decode exactly two semantic fields: portal_side,
exact_match). NOTE: this contradicts the earlier campaign note
"CCellPortal DAT flag 0x4 = leads outside" — the outside link is the
`OtherCellId == 0xFFFF` sentinel, not a flag bit.
- ExactMatch consumers: `PortalVisibilityBuilder.cs:1168-1183` (skips
reciprocal clip — decomp:433689), Walk factories
(`WalkBuildingFactory.cs:76`, `WalkCellFactory.cs:94`).
- PortalSide convention: `(Flags & 0x2) == 0 → normal points INTO the
owning cell` (`CellPortal.cs:23-24`, `PortalInfo.cs:22-44`);
`WalkCellFactory.cs:93`: `PortalSide = (Flags & 0x2) != 0 ? 0 : 1`.
- `OtherCellId == 0xFFFF` = the outdoor-exit sentinel (18+ consumers);
the walk world remaps it to `0xFFFFFFFFu`.
`BuildingPortal` (BuildingInfo.Portals) is a DISTINCT dat type — carries
its own **packed StabList of cell ids** (retail `CBldPortal` with
num_stabs/stab_list + `sidedness`). The walk's `WalkBuildingFactory.cs:81`
reads it directly; the older `Wb.BuildingLoader` path DISCARDS it and
recomputes by BFS.
## LandBlockInfo
`NumCells → Objects[Stab] → Buildings[BuildingInfo{ModelId, Frame,
NumLeaves, Portals[BuildingPortal]}] → [flag] RestrictionTable`.
Confirmed field-for-field; consumer `LandblockLoader.cs:69-103`.
## Water / waterfall (part d)
- `LandDefs::WaterType` is COMPUTED client-side from terrain paint (types
0x10-0x14 WaterRunning..WaterDeepSea); AcDream already computes it for
physics (`TerrainSurface.cs:92-128`). It is NOT packed in the records.
- `SurfaceTexture.Textures` is a multi-frame list (the structural shape of
a flip-book animation) but EVERY consumer in both repos freezes one
fixed index (`Textures[0]`, WB `[^1]`) — **no water/texture animation is
implemented anywhere**; whether retail animates via this list is
UNVERIFIED.
- Which object IS "the waterfall" near the cathedral: UNVERIFIED from
source — two old bug comments treat it as OUTDOOR landscape-alpha
content (`PortalVisibilityBuilder.cs:730-736`,
`RetailPViewRenderer.cs:714-726`), consistent with a translucent stab —
but note the live probes identified the terrace falls PARTICLE owners as
EnvCell StaticObjects of cell 0xF4180106 (ids 4f418012-15), which is
the `HasStaticObjs` list above; both can be true (mesh stab outdoors +
emitter stabs in cells).
## Notable corrections this report makes to campaign lore
1. "DAT flag 0x4 = leads outside" (PV campaign memory) — REFUTED: no 0x4
exists; outside = OtherCellId 0xFFFF.
2. "stab list" ambiguity — retail stab_list = PVS cell ids on CObjCell;
placed objects are a different structure; docs/comments conflating the
two should be read carefully.
3. Building portals carry authored per-portal cell StabLists in the dat —
the old Wb path recomputes what the dat already provides.