diff --git a/src/AcDream.App/Rendering/Walk/RetailFrameWalk.cs b/src/AcDream.App/Rendering/Walk/RetailFrameWalk.cs
index 94213e52..8ee37b49 100644
--- a/src/AcDream.App/Rendering/Walk/RetailFrameWalk.cs
+++ b/src/AcDream.App/Rendering/Walk/RetailFrameWalk.cs
@@ -50,6 +50,11 @@ public sealed class RetailFrameWalk
public WalkPView InteriorPView => _interiorPView;
public WalkPView OutdoorPView => _outdoorPView;
+ /// Retail global alwaysDrawObjects (.data default 1
+ /// @0x00820ed4): cell contents draw for every cell of an in-view block
+ /// regardless of per-cell visibility.
+ public bool AlwaysDrawObjects = true;
+
/// The per-frame root (SmartBox::RenderNormalMode).
/// may be null only when the camera is
/// outdoors.
@@ -115,10 +120,15 @@ public sealed class RetailFrameWalk
for (int k = 0; k < cellCount; k++)
{
int cellIndex = block.DrawArray[k];
- // DrawSortCell runs for in-view cells (alwaysDrawObjects
- // default 0); terrain (DrawLandCell) emits no walk event.
- if (block.CellInView[cellIndex] == WalkBoundingType.Outside)
+ // RenderDeviceD3D::DrawBlock @0x005a19d9: DrawSortCell runs
+ // when alwaysDrawObjects != 0 (retail .data default 1
+ // @0x00820ed4) OR the cell IsInView; terrain (DrawLandCell)
+ // emits no walk event.
+ if (!AlwaysDrawObjects
+ && block.CellInView[cellIndex] == WalkBoundingType.Outside)
+ {
continue;
+ }
if (block.CellBuildings[cellIndex] is WalkBuilding building)
DrawBuilding(building, activeViews, ctx, sink);
}
diff --git a/tests/AcDream.App.Tests/Rendering/Walk/WalkLookInGateSweepTests.cs b/tests/AcDream.App.Tests/Rendering/Walk/WalkLookInGateSweepTests.cs
index 2cc18a8b..f8cbf2b6 100644
--- a/tests/AcDream.App.Tests/Rendering/Walk/WalkLookInGateSweepTests.cs
+++ b/tests/AcDream.App.Tests/Rendering/Walk/WalkLookInGateSweepTests.cs
@@ -24,14 +24,11 @@ public sealed class WalkLookInGateSweepTests
public void Emit(in WalkEvent walkEvent) => Events.Add(walkEvent);
}
- [Fact(Skip = "FW1 adjudication driver (2026-08-30 final state): with the "
- + "exact get_degrade rule (slack 100, ideal thresholds, sort-center "
- + "distance) the level-0 set is correct — the residual divergence is "
- + "the per-portal side/clip gate: my arms punch {0017,001e,0026,0036}, "
- + "retail punched exactly {001a,0022} — a near-complement suggesting "
- + "one more polarity at the building-portal gate. Next instrument: "
- + "per-portal dump for 001a (retail punches) vs 001e (retail doesn't): "
- + "side values, plane orientation, eye side, clip result per arm.")]
+ [Fact(Skip = "FW1 near-win state (2026-08-30): with +Y-forward, alwaysDrawObjects, "
+ + "the exact degrade rule and side mode 1, the street fixture matches retail "
+ + "EXCEPT look-in flood depth (mine D[16e]/D[164]; retail D[16e,16a,16c]/"
+ + "D[164,162,167,169]) - adjudicate the interior flood propagation next "
+ + "(the doorway-still fixture tests it in isolation).")]
public void Sweep_the_lookin_gate_decodes_against_the_street_fixture()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
diff --git a/tests/AcDream.App.Tests/Rendering/Walk/WalkTraceReplay.cs b/tests/AcDream.App.Tests/Rendering/Walk/WalkTraceReplay.cs
index 0b7f3300..30763590 100644
--- a/tests/AcDream.App.Tests/Rendering/Walk/WalkTraceReplay.cs
+++ b/tests/AcDream.App.Tests/Rendering/Walk/WalkTraceReplay.cs
@@ -53,14 +53,16 @@ public sealed class WalkTraceReplayContext : IWalkFrameContext, IRetailFrameWalk
_cells = cells;
WorldViewpoint = pose.Origin;
var rotation = new Quaternion(pose.Q1, pose.Q2, pose.Q3, pose.Q0);
- // Convention pinned against the moving fixtures (2026-08-30 sweep:
- // storage w,x,y,z; the facing direction is the rotated +X axis —
- // mean 20.8° vs motion headings, every alternative ≥52°). The
- // consistent right-handed triple is then right = −rot(+Y),
- // forward = rot(+X), up = rot(+Z).
- Vector3 forward = Vector3.Transform(Vector3.UnitX, rotation);
+ // Basis convention RE-pinned 2026-08-30 (second pass): storage
+ // w,x,y,z; forward = rotated +Y — the retail Frame convention. The
+ // motion sweep briefly favored +X, but the walkabout camera was
+ // mouse-turned off the run direction; the terrace-edge fixture's
+ // EXTERNAL ground truth (the ledge faces the F518 vista, east)
+ // decodes east ONLY under +Y-forward, and +Y makes the street
+ // fixture's punch on/off-screen pattern match retail 4-for-4.
+ Vector3 forward = Vector3.Transform(Vector3.UnitY, rotation);
Vector3 up = Vector3.Transform(Vector3.UnitZ, rotation);
- Vector3 right = -Vector3.Transform(Vector3.UnitY, rotation);
+ Vector3 right = Vector3.Transform(Vector3.UnitX, rotation);
// The exact retail frustum: tan(halfFovY) = ty/vdst, aspect = tx/ty.
float fovY = 2f * MathF.Atan(RetailTy / RetailVdst);
diff --git a/tests/AcDream.App.Tests/Rendering/Walk/WalkWorldDatAdapter.cs b/tests/AcDream.App.Tests/Rendering/Walk/WalkWorldDatAdapter.cs
index 469b349c..88b46fe3 100644
--- a/tests/AcDream.App.Tests/Rendering/Walk/WalkWorldDatAdapter.cs
+++ b/tests/AcDream.App.Tests/Rendering/Walk/WalkWorldDatAdapter.cs
@@ -242,7 +242,9 @@ public static class WalkWorldDatAdapter
/// Adjudication toggle: the BuildingPortal side-flag decode.
/// 0 = (Flags & 0x2), 1 = inverted 0x2, 2 = (Flags & 0x1),
/// 3 = inverted 0x1.
- public static int BuildingSideMode;
+ public static int BuildingSideMode = 1; // data-pinned 2026-08-30: building
+ // portal_side = the INVERSE of the cell decode's 0x2 bit (the sweep's
+ // winning arm - punches land at retail's exact buildings/cells with it).
private static int DecodeBuildingSide(ushort flags) => BuildingSideMode switch
{