KB: document the searchlight fog-swap latent bug (task #63, left as-is by decision)
Investigation (workflow) found the searchlight-driven fog swap never worked in the ORIGINAL 1995 binary either -- it's a latent bug, not a port regression: SearchlightSimulation (@004b841c) reads requestedOn@0x1E0 (never written) while ToggleLamp (@004b860c) toggles commandedOn@0x1DC; no bridge exists, so lightState @0x1D8 is perpetually 0 (lamp never lights). The self-consistent sibling ThermalSight reads the field it toggles (0x1DC) -- the tell. The port reproduces the bug faithfully (searchlight.cpp:189). Additionally the port never constructs PullFogRenderable, so even absent the bug the swap wouldn't fire. Decision: LEAVE AS-IS + document (faithful to the buggy original); the port keeps the static lights-ON fog= values. A working swap would DEVIATE from the shipped binary (repair the sim to read commandedOn + construct PullFogRenderable at the btl4vid MakeMechRenderables inside pass + a toggle input) -- fully scoped in the KB if ever wanted. No code change this commit. Documented in rendering.md (fog section), open-questions.md (deferred subsystems), subsystems.md (Searchlight). Core per-map/time/weather fog (task #63) is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
225fa5951b
commit
c0a0ec5e69
@@ -59,6 +59,22 @@ register. ⚠ The audit also flags the damage-economy item as SELF-CONTRADICTOR
|
||||
(task #8 "landed" vs the kShotDamage=12 bring-up residue) — audit before reworking.
|
||||
|
||||
## Deferred subsystems / feeds (authentic path scoped, marked in code)
|
||||
- **Searchlight-driven fog swap — DEFERRED, and it is an ORIGINAL 1995 LATENT BUG (task #63,
|
||||
2026-07-13) [T1 decomp].** The arcade swaps fog between `fog=` (lights on) and `nosearchlightfog=`
|
||||
(off) via `PullFogRenderable` watching the Searchlight's `lightState`. It never fires — in the PORT
|
||||
because `PullFogRenderable` is never constructed, AND in the BINARY ITSELF because the Searchlight
|
||||
never lights: `ToggleLamp` (@004b860c) toggles `commandedOn` @0x1DC but `SearchlightSimulation`
|
||||
(@004b841c) reads `requestedOn` @0x1E0, which is zeroed by the ctor and never written — no
|
||||
0x1DC→0x1E0 bridge exists (self-consistent sibling ThermalSight reads the field it toggles, 0x1DC).
|
||||
So `lightState` is perpetually 0. The port reproduces this faithfully (searchlight.cpp:189).
|
||||
**DECISION: left as-is + documented (faithful to the buggy original); port keeps the static
|
||||
lights-ON `fog=`.** A working swap is a DESIGNER-INTENT deviation, fully scoped if ever wanted:
|
||||
(1) sim reads `commandedOn` (mirror ThermalSight); (2) construct `PullFogRenderable` at
|
||||
btl4vid.cpp `MakeMechRenderables` reticle-build/inside pass (== arcade part_014.c:5173, Dynamic,
|
||||
bound per Searchlight `lightState` via a new `LightStatePtr()` accessor); (3) a toggle input (the
|
||||
authentic cockpit button-5→`ToggleLamp` dispatch is a controls-family reconstruction; a dev key
|
||||
stands in). Also flags a deferred **`Mech::ControlsAllowLights()`** (searchlight.hpp:158 stub).
|
||||
See [[rendering]] fog section. Verified inert live: BT_FOG_LOG shows zero `SetFogStyle(2/3)`.
|
||||
- **Factory capability-roster loops 2-4 are STILL DEAD (task #57 discovery).** mech.cpp's
|
||||
post-roster loops add to `heatableSubsystems`(0x51155c)/`weaponRoster`(0x511830)/
|
||||
`damageableSubsystems`(0x50e4fc) through the local `SubProxy` stub whose `IsDerivedFrom`
|
||||
|
||||
+18
-9
@@ -67,15 +67,24 @@ DECLOUDS must stay in the sky pass). Authored TEXTURE **SCROLL** (BMF TEXTURE ta
|
||||
arcade. Night fog is dark BY DESIGN (distance→murk, not light haze); day pages author light haze. Env:
|
||||
`BT_FOGMODE=table|vertex|off`, `BT_WEATHER=clear|fog|soup`, `BT_FOG="near far r g b"` (all branches);
|
||||
`[fog] resolved`/`[fog] model`/`[fogstyle]` (BT_FOG_LOG) log lines. [T1 pipeline / T0 arcade model / T2 fix]
|
||||
**⚠ SEARCHLIGHT SWAP IS INERT [T1, verified 2026-07-13].** The arcade swaps the active fog between
|
||||
`fog=` (headlight ON) and `nosearchlightfog=` (OFF, darker/tighter) via `PullFogRenderable::Execute`
|
||||
(L4VIDRND.cpp:4601, edge-triggered on two light attrs → `SetFogStyle(searchLightOn/OffFogStyle)`). In
|
||||
the port **`PullFogRenderable` is NEVER CONSTRUCTED** (grep: only its .h decl + .cpp def; no `new`), and
|
||||
`searchLightOn/Off` is called from nowhere else — so the swap never fires (BT_FOG_LOG: over 22s only
|
||||
`SetFogStyle(0)`, zero style 2/3). Fog is STATIC at the searchlight-ON (`fog=`) values; the
|
||||
`nosearchlightfog=` variant is dead. Reconstruction gap: wiring needs the mech's headlight/searchlight
|
||||
state (Searchlight subsys 3032) bound to a `PullFogRenderable` constructed at viewpoint/mech setup.
|
||||
Core per-map/time/weather fog is unaffected (uses the lights-ON set, the normal play state).
|
||||
**⚠ SEARCHLIGHT SWAP IS INERT — and it was inert in the ARCADE too (task #63 workflow, 2026-07-13).**
|
||||
The arcade swaps the active fog between `fog=` (headlight ON) and `nosearchlightfog=` (OFF,
|
||||
darker/tighter) via `PullFogRenderable::Execute` (L4VIDRND.cpp:4601, edge-triggered on two light attrs →
|
||||
`SetFogStyle(searchLightOn/OffFogStyle)`). TWO independent reasons it never fires:
|
||||
(1) **Port:** `PullFogRenderable` is NEVER CONSTRUCTED (grep: only its .h decl + .cpp def; no `new`);
|
||||
`searchLightOn/Off` is called from nowhere else (BT_FOG_LOG: over 22s only `SetFogStyle(0)`, zero 2/3).
|
||||
(2) **Original 1995 LATENT BUG [T1, decomp]:** even if wired, the Searchlight never lights —
|
||||
`ToggleLamp` (@004b860c) toggles `commandedOn` @0x1DC (part_013.c:6087) but `SearchlightSimulation`
|
||||
(@004b841c) reads `requestedOn` @0x1E0 (part_013.c:5978), which the ctor zeroes and NOTHING ever writes;
|
||||
no bridge 0x1DC→0x1E0 exists anywhere in the binary. So `lightState`@0x1D8 is perpetually 0. The
|
||||
self-consistent sibling **ThermalSight** reads the SAME field it toggles (0x1DC) — the tell that
|
||||
Searchlight's sim reads the wrong slot. The port reproduces this faithfully (searchlight.cpp:189 reads
|
||||
requestedOn). **DECISION (2026-07-13): left as-is + documented** (faithful to the buggy original); the
|
||||
port keeps the static lights-ON `fog=` values. To make the swap WORK is a DESIGNER-INTENT fix that
|
||||
DEVIATES from the shipped binary — repair the sim to read `commandedOn` (mirror ThermalSight) + construct
|
||||
`PullFogRenderable` at btl4vid.cpp `MakeMechRenderables` (the reticle-build/inside pass, == arcade
|
||||
part_014.c:5173, ExecutionType Dynamic, bound to each Searchlight `lightState`) + a toggle input. See
|
||||
[[open-questions]]. Core per-map/time/weather fog is unaffected.
|
||||
- **Projection / stencil (task #55):** the BTDPL.INI `viewangle=60` is the **HORIZONTAL** FOV —
|
||||
authentic 60×47 frustum at 4:3; fovY derived via `BTFovYFromHorizontal` (L4VIDEO.cpp), applied at
|
||||
all 5 projection sites (it was mis-applied as vertical). The device depth-stencil is now
|
||||
|
||||
@@ -41,6 +41,11 @@ Making a base byte-exact GROWS every subclass — they must be re-based TOGETHER
|
||||
- **WAVE 3** — power bus (Generator/PoweredSubsystem) + Emitter/PPC fire-path (end-to-end fire; heat
|
||||
conducts to the central sink via the linked-sink roster).
|
||||
- **WAVE 4** — standalone readouts: Sensor/Searchlight/ThermalSight/AmmoBin (de-shim, gate fixes).
|
||||
- ⚠ **Searchlight has an ORIGINAL latent bug [T1, task #63]:** `SearchlightSimulation` (@004b841c)
|
||||
reads `requestedOn`@0x1E0 (never written) while `ToggleLamp` (@004b860c) toggles `commandedOn`@0x1DC
|
||||
— no bridge, so `lightState`@0x1D8 is perpetually 0 (lamp never lights). Present in the 1995 binary
|
||||
(sibling ThermalSight reads the field it toggles, 0x1DC); the port reproduces it faithfully. Left
|
||||
as-is by decision; it makes the searchlight→fog swap inert. See [[open-questions]] + [[rendering]] fog.
|
||||
- **WAVE 5** — Torso (aim twist/elevation; joint-I/O reconstructed; the BLH record disables torso →
|
||||
faithfully no visible twist).
|
||||
- **WAVE 6** — Myomers (mover-coupled; structural un-stub is INERT — no live mover/heat coupling).
|
||||
|
||||
Reference in New Issue
Block a user