acdream/docs/research/2026-08-30-cathedral-review-decomp.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

7.3 KiB

Cathedral review — retail interior-root frame reconstruction (companion report)

Delivered 2026-08-30 by the decomp-reconstruction agent (BN pseudo-C + live Ghidra arbitration on 8081 + acclient.h + symbols.json). THE retail mechanism reference for the synthesis. Condensed; all pc:/address citations preserved.

Frame skeleton (interior root)

  1. SceneTool::BeginScene @0x0043dad0: full Clear(7) — COLOR+depth+ stencil — every frame (pc:68673-68686). Flip bumps m_nFrameStamp at frame end (pc:428642).
  2. RenderNormalMode @0x00453aa0: interior camera → optional LScape::update_viewpoint (only when viewer_cell->seen_outside, pc:92667-71) → DrawInside(viewer_cell) → unconditional final drain FlushAlphaList(0f) (pc:92687).
  3. TWO PView singletons (pc:427800/427813): indoor_pview (draw_landscape =1) for the root; outdoor_pview (0) for building look-ins — look-in floods can never re-trigger landscape/clear/seals (their outside_view.view_count is always 0; ClipPortals never raises it when draw_landscape=0, pc:433666-84).
  4. PView::DrawInside @0x005a5860: push root view (full viewport) → ConstructView(root, 0xffff) — PURE CPU flood, draws nothing; exit portals merge clipped apertures into outside_view (pc:433662-76, cliplandscape=1 @0x00820f4c).

PView::DrawCells @0x005a4840 — ALL of this inside ov > 0 (pc:432715):

  1. Render::PortalList = &outside_view; LScape::draw (pc:432718-19).
  2. Full outdoor alpha drain FlushAlphaList(0f) (pc:432720).
  3. m_nFrameStamp += 1 (pc:432722) — re-arms part dedupe so a part can draw in BOTH the outdoor and interior passes of one frame (straddlers draw twice; "emit once" is anti-retail).
  4. Gated z-only clear (pc:432725-32, Ghidra-verified): forceClear(const 0) || portalsDrawnCount != 0 — the counter is incremented ONLY by own-depth portal stamps (seals, arg2==0, pc:424569-70) → a ONE-FRAME LATCH: last frame's seals arm this frame's clear. Steady-state vista frames clear every frame; the FIRST such frame does not.
  5. Exit seals (pc:432737-807): per flooded cell (far→near), per view, EVERY portal with other_cell 0xffffffff: DrawPortalPolyInternal(poly, 0) — REAL projected depth, DEPTHTEST_ALWAYS + z-write ON (pc:424584), invisible (vertex alpha 0, pc:424686), CULL_NONE, CPU-clipped to the current view (pc:424577). (Sibling mode arg2==1 = the far-Z PUNCH z≈0.999999, look-ins only; does not increment the counter.)

Then UNCONDITIONALLY (even when ov==0): 6. Lighting restore (pc:432811-12). 7. Cell shells far→near: DrawEnvCell dedupes per frame stamp — the shell draws ONCE, WHOLE; the per-view loop is vestigial for it; no view planes applied; correctness = pure z-test (pc:427885-88). 8. Cell objects far→near: PortalList = the cell's views → DrawObjCellForDummies → shadow parts sorted by CYpt (viewer distance to scaled sort_center, insertion_sort @pc:701156-75) → CPhysicsPart::Draw — statics, dynamics, AND particle-emitter parts through ONE machinery. 9. Final drain (pc:92687) vs interior depth + seal-stamped apertures.

Clip vs cull (the definitive table)

  • CPU polygon-clipped: ONLY portal-chain polys during the flood (GetClip @0x005a4320) and seal/punch fans at draw (their own polyClipFinish vs the current view, pc:424577, + a ±12 local-XY trivial reject pc:424506-50).
  • Sphere-vs-view CULLED, whole-drawn: all meshes (statics, dynamics, particles' parts) — DrawMesh per view: viewconeCheck(sphere) (pc:429295-96); PARTIAL draws WHOLE under that view; a mesh in N views submits N times. Building PORTAL pass is cone-exempt (punches always attempted; GetClip <3 points is the real stop, pc:429302-10).
  • Cached-flag culled: terrain cells via in_view stamped by draw_check_blocks @0x00505f80 iterating EVERY view of PortalList (blocks wholly outside every exit view skip at pc:267936). Terrain polys then draw whole + immediate (landPolysDraw @0x006b7040 — no view clip, no alpha list).
  • No test at all: EnvCell shell geometry; seal z-behavior (ALWAYS).
  • alwaysDrawObjects = 1 (@0x00820ed4): DrawSortCell runs for EVERY cell of a drawn block — the per-part per-view cone check is the real object gate (no pixel leak, just CPU).

The alpha lists (retail)

TWO static FIFO lists, 3000 entries each (Clip @0x00871b10, Alpha @0x008af370). NO depth key stored, NO sort at flush — order = submission order; far-to-near correctness comes from the cell walk + per-cell CYpt insertion sort. Overflow DROPS the subset (pc:424983). Entry routing: s_AlphaDelayMask (default 0xE) vs the surface mask; bit3 → Clip list.

Flush sites (grep-complete):

# Site Arg Depth in place
1 DrawBuilding @0x0059f30b 0f FULL outdoor-so-far (pre-punch)
2 DrawBlock @0x005a1a07 0.75 valve, fires per outdoor cell (BN's flush>1 guard is a MISREAD — Ghidra: fires when flush<=1.0) mid-landscape
3 DrawCells @0x005a4872 0f FULL complete outdoor depth (pre-clear)
4 RenderNormalMode @0x00453b8b 0f FULL (final) interior + seals
5 CreatureMode::Render (chargen only) 0f its own viewport

Depth at final drain (interior root)

  • Aperture/vista pixels: the SEAL's portal-plane depth (outdoor per-pixel depth NO LONGER EXISTS — cleared; outdoor COLOR survives under the stamp). Interior alpha fragments behind the portal plane FAIL there.
  • Outdoor particles (falls): drawn in the landscape pass, drained at site #3 vs outdoor depth. Cone-PARTIAL spill outside the aperture is buried because EVERY interior pixel paints after every outdoor drain point — protection is pure ORDERING, not depth.

ShouldDrawParticles @0x0050fe60 — an UPDATE-time gate

Called per emitter from ParticleEmitter::UpdateParticles (physics-side), NOT during rendering: ExaminationObject → 1; CYpt > degrade_distance → 0; cell NULL → 0; cell->IsInView()==0 → 0. On false: SetNoDraw(1), degraded_out=1 (particles stop updating AND drawing).

  • CLandCell::IsInView @0x00532cb0 = the PREVIOUS frame's stamped in_view (one-frame-stale gate).
  • CEnvCell does NOT override it — the slot resolves to the ICF-folded constant @0x005269f0 return 1 (PARTIALLY_INSIDE, PDB-verified): for interior emitters the cell test is VACUOUS; distance is the only update-time gate; their draw is flood-gated instead.

Can content outside the flood/exit views draw? NO.

Interior: pure flood membership. Outdoor blocks/cells: in_view under ≥1 exit view. Outdoor parts: per-exit-view sphere-cone in DrawMesh. Building portal pass cone-exempt but clip-stopped. No distance bypass exists.

Corrections to campaign docs

  1. DrawBlock per-cell flush polarity RESOLVED (fires; 0.75 pressure valve) — BN misread.
  2. The m_nFrameStamp bump separates the landscape and interior passes of ONE interior-root frame; look-ins NEVER bump (outdoor_pview ov==0).
  3. NEW: CEnvCell::IsInView = constant PARTIALLY_INSIDE (ICF fold, symbols.json 19-name cluster) — not in any FW doc.

UNVERIFIED (the agent's own list)

The 0xF418 falls emitters' owner (land cell vs EnvCell static — dat question; note the DAT-geometry companion resolves this: landblock object-list stabs); z-write during alpha drains; insertion_sort direction byte-proof; the ±12 reject polarity; GameSky depth behavior.