KB: full staleness audit + sweep -- 35 verified corrections across 16 topics, 15 new glossary terms

Adversarially-verified audit (18 agents) against the task #46-#56 landings:
MP/current-state understatements, superseded punch readings, retired env
gates, dead paths, line-cite drift; env-gate hub table completed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-11 10:56:51 -05:00
co-authored by Claude Fable 5
parent 2abfd51350
commit 3c34ae6de6
18 changed files with 253 additions and 103 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ spec is `docs/ASSET_PIPELINE.md`. Full list: `docs/PROGRESS_LOG.md §5`.
(`DIV-BSL2` — a BIT-SLICED container: w*h 32-bit texel words holding SIX independent 4-bit (`DIV-BSL2` — a BIT-SLICED container: w*h 32-bit texel words holding SIX independent 4-bit
GRAYSCALE sub-images (nibble pair-swapped, byte 0 pad) OR RGB444/RGBA4444 (sliceType 7/8). The BMF GRAYSCALE sub-images (nibble pair-swapped, byte 0 pad) OR RGB444/RGBA4444 (sliceType 7/8). The BMF
`0x18 BITSLICE` tag picks the slice, absent=0). Decoding BSL as RGB = the "rainbow/graffiti mech" `0x18 BITSLICE` tag picks the slice, absent=0). Decoding BSL as RGB = the "rainbow/graffiti mech"
bug. Reference reader: `DivLoader/VGCDivLoader.cpp:323-410`. [T2] bug. Reference reader: `DivLoader/VGCDivLoader.cpp:323-410`; archive-only — in-repo reimplementation: `engine/MUNGA_L4/image.cpp`. [T2]
- **`.VMF`** — `DIV-VIZ2` material SOURCE. Carries the `SCROLL` animation + `MAP{}` image binding for - **`.VMF`** — `DIV-VIZ2` material SOURCE. Carries the `SCROLL` animation + `MAP{}` image binding for
effects (beams/muzzle/smoke/sky). THE key effects asset ([[rendering]]). [T2] effects (beams/muzzle/smoke/sky). THE key effects asset ([[rendering]]). [T2]
- **[[material-ramp]]** — the IG board colours no-normal geometry by a 2-endpoint RAMP; details in - **[[material-ramp]]** — the IG board colours no-normal geometry by a 2-endpoint RAMP; details in
+2 -1
View File
@@ -15,7 +15,8 @@ open_questions:
spec (verified against all 1275 content `.BGF` files) lives in **`docs/BGF_FORMAT.md`** — this spec (verified against all 1275 content `.BGF` files) lives in **`docs/BGF_FORMAT.md`** — this
topic captures the structure + the hard-won gotchas that cost real debugging. Loader of record: topic captures the structure + the hard-won gotchas that cost real debugging. Loader of record:
`engine/MUNGA_L4/bgfload.cpp` (game-callable via `LoadBgfFile`); standalone reference reader `engine/MUNGA_L4/bgfload.cpp` (game-callable via `LoadBgfFile`); standalone reference reader
`DivLoader/VGCDivLoader.cpp`. Tag names: `dsys/PFBIZTAG.H`. `DivLoader/VGCDivLoader.cpp` (archive-only; in-repo reimplementation: `engine/MUNGA_L4/image.cpp`).
Tag names: `dsys/PFBIZTAG.H`.
## Structure ## Structure
`OBJECT → LOD → PATCH (geogroup) → PMESH`. Interleaved float32 verts; **QUAD faces (must `OBJECT → LOD → PATCH (geogroup) → PMESH`. Interleaved float32 verts; **QUAD faces (must
+27 -18
View File
@@ -5,13 +5,13 @@ status: living
source_sections: "task #55 (2026-07-10); reference/decomp part_007.c/part_013.c/part_014.c/part_011.c; engine/MUNGA_L4/bgfload.cpp, L4VIDRND.cpp; game/reconstructed/btl4vid.cpp" source_sections: "task #55 (2026-07-10); reference/decomp part_007.c/part_013.c/part_014.c/part_011.c; engine/MUNGA_L4/bgfload.cpp, L4VIDRND.cpp; game/reconstructed/btl4vid.cpp"
related_topics: [rendering, bgf-format, gauges-hud, subsystems, decomp-reference] related_topics: [rendering, bgf-format, gauges-hud, subsystems, decomp-reference]
key_terms: [material-ramp, siteeyepoint] key_terms: [material-ramp, siteeyepoint]
open_questions: ["gyro tail: gait jolt/rumble [T3 gates], sway model, torso-pitch eye writer, damageForce fill", "exact unlit ramp index for the frame colour (BT_COP_RAMP_L=0.08 is T3 tuned-to-footage)"] open_questions: ["gyro tail: gait jolt/rumble [T3 gates], sway model, torso-pitch eye writer, damageForce fill", "exact authored frame colour: the unlit constant (0.13,0.12,0.15) is T3 tuned-to-footage (BT_COP_FRAME overrides; the ramp-index approach + BT_COP_RAMP_L are RETIRED)"]
--- ---
# First-Person Cockpit: the *_cop Canopy + the Authentic Eyepoint # First-Person Cockpit: the *_cop Canopy + the Authentic Eyepoint
The pod's only view was the cockpit eyepoint looking out through a per-mech canopy shell. The pod's only view was the cockpit eyepoint looking out through a per-mech canopy shell.
Task #55 reconstructed both halves — the CANOPY rendering and the EYE camera — from the binary. Task #55 reconstructed both halves — the CANOPY rendering and the EYE camera — from the binary.
Verified in-game on the Madcat against gameplay footage. [T2] Verified in-game on all 8 mechs (Thor vs gameplay footage). [T2]
## The canopy shell (*_COP.BGF) ## The canopy shell (*_COP.BGF)
@@ -29,22 +29,27 @@ Verified in-game on the Madcat against gameplay footage. [T2]
38-59% across all 12). The struts ARE the frame; the openings ARE the windows. Beware the 38-59% across all 12). The struts ARE the frame; the openings ARE the windows. Beware the
edge-counting trap: counting edges across patches (patch-local indices collide) undercounts edge-counting trap: counting edges across patches (patch-local indices collide) undercounts
boundaries catastrophically (BLX "7%" wrong → 59% right). [T1] boundaries catastrophically (BLX "7%" wrong → 59% right). [T1]
- **Rendering (bgfload.cpp):** keyed by filename (`meshIsCop`, stem contains `_cop`): - **Rendering (FINAL treatment 2026-07-11; bgfload.cpp keyed by filename `meshIsCop`):**
1. **Single-sided** (emitTri): double-siding draws far struts through the near openings → the 1. **The PUNCH STENCIL-CUT kit** (see §FINAL below + [[bgf-format]]): the TAG_PATCH scan
"black box". `BT_COP_DOUBLE=1` restores (diag). hash-pairs the punch geogroup's chunks into mask / hull / twin roles; L4D3D executes the
2. **Per-face INWARD winding orientation** (finish()): the l/r torso patches are MIRRORED 3-step stencil cut (D24S8). `BT_COP_PLATES=1` disables (diag).
copies, so no global winding works — orient each face's kept winding toward the mesh 2. **Double-sided** like all no-normal geometry — the earlier single-siding + per-face inward
interior (where the pilot sits). `BT_COP_FLIP=1` flips (diag). winding existed solely to fight the solid-box look, which the un-cut PLATES caused, not the
3. **Dark `softer`-ramp frame colour**: texture-less ramp + no normals = unlit; evaluate the winding; both are REMOVED (bgfload.cpp:533 comment). `BT_COP_SINGLE=1` restores
ramp at a flat index, default `BT_COP_RAMP_L=0.08` (near the dark end — [T3] tuned to the single-siding, `BT_COP_FLIP=1` flips its winding (diag only).
near-black frame in footage; the board's exact unlit index is not in the code). 3. **UNLIT constant frame colour** (the map-lighting bug fix, 2026-07-11): the frame batch is
routed through the renderer's pure-emissive branch (black diffuse + emissive
`(0.13,0.12,0.15)` [T3 tuned-to-footage]; `BT_COP_FRAME="r g b"` overrides). The previous
lit path multiplied the colour by the MAP light — cavern-night `ambient=0.8` washed the
frame gray (user-reported). `BT_COP_RAMP_L` + the flat-ramp-index approach are RETIRED.
- The shell SHOWS by default in the inside view (btl4vid.cpp ApplyViewSkeleton); - The shell SHOWS by default in the inside view (btl4vid.cpp ApplyViewSkeleton);
`BT_HIDE_COCKPIT=1` hides it (diag). `BT_HIDE_COCKPIT=1` hides it (diag).
- **Wrong turns, recorded so they stay dead:** (a) "windows are punch texels" — no texel exists; - **Wrong turns, recorded so they stay dead:** (a) "windows are punch texels" — no texel exists;
(b) "the punch patch IS the visible frame / drop-punch removes the cockpit" — an artifact of (b) "the punch patch IS the visible frame / drop-punch removes the cockpit" — an artifact of
testing with the broken pre-inverse eye; with the authentic eye the punch patches are plainly testing with the broken pre-inverse eye; (c) a view-direction face-cut heuristic — not
the WINDOWS (see §resolved below) and dropping them is correct; (c) a view-direction face-cut data-derivable; (d) "drop the whole punch geogroup = the windows" and (e) "duplicate pairs =
heuristic — not data-derivable, superseded by the lattice + winding + punch-drop treatment. plates, hide both" — both superseded by the firmware-decoded STENCIL-CUT kit (§FINAL below),
which is the authentic mechanism.
## The authentic eyepoint (decomp-verified [T1]) ## The authentic eyepoint (decomp-verified [T1])
@@ -141,7 +146,8 @@ Some mechs have laterally OFFSET cockpits, and the data + our port agree exactly
center +1.13 (exact)**; loki 0.25/0.15; owens +0.19/+0.16; the other five ≈0/≈0. Our in-game center +1.13 (exact)**; loki 0.25/0.15; owens +0.19/+0.16; the other five ≈0/≈0. Our in-game
measured eye (`[EYECHK]`) reproduces the Thor offset to the hundredth (lateral 1.13 from the mech measured eye (`[EYECHK]`) reproduces the Thor offset to the hundredth (lateral 1.13 from the mech
origin). The eye chain (baseOffset + parent-segment DCS composition) is therefore CORRECT per-mech; origin). The eye chain (baseOffset + parent-segment DCS composition) is therefore CORRECT per-mech;
the still-blocked cockpit views are a canopy-RENDER question, not a camera one. the canopy-render question was subsequently resolved by the stencil-cut kit — all 8 render
authentically (see the FINAL paragraph above).
## The playable roster is 8, not 12 [T1] ## The playable roster is 8, not 12 [T1]
@@ -169,9 +175,12 @@ user-community report ("frames were never this revealed") + the resolution/FOV h
## Diagnostics / env gates ## Diagnostics / env gates
`BT_FORCE_MODEL=<name>` (force the player mech: madcat/owens/sunder/…; btl4mssn.cpp), `BT_FORCE_MODEL=<name>` (force the player mech: madcat/owens/sunder/…; btl4mssn.cpp),
`BT_HIDE_COCKPIT`, `BT_COP_DOUBLE`, `BT_COP_FLIP`, `BT_COP_RAMP_L`, `BT_COP_DEBUG` (paint the `BT_HIDE_COCKPIT`, `BT_COP_PLATES` (disable the stencil kit), `BT_COP_FRAME="r g b"` (frame
shell green), `BT_COP_DUMP` (per-batch punch/bbox), `BT_EYE_FWD=<f>` (push the eye forward — the colour override), `BT_COP_SINGLE` / `BT_COP_FLIP` (single-siding diag), `BT_COP_DEBUG` (paint
position probe), `[EYECHK]` log (eye world pos + look dir + entity pos, first frames). the shell green), `BT_COP_DUMP` (per-batch punch/bbox), `BT_EYE_FWD=<f>` (eye position probe),
`BT_GYRO_LOG` / `BT_GYRO_TRACE` (gyro bring-up log / per-frame integrator trace, gyro.cpp),
`[EYECHK]` log (eye world pos + look dir + entity pos, first frames).
(RETIRED: `BT_COP_DOUBLE`, `BT_COP_RAMP_L` — removed with the stencil-cut/unlit-frame landing.)
## Key Relationships ## Key Relationships
- Uses: [[bgf-format]] (PUNCH, vertex tags) · [[rendering]] (ramp model, skeleton branch) - Uses: [[bgf-format]] (PUNCH, vertex tags) · [[rendering]] (ramp model, skeleton branch)
+21 -15
View File
@@ -3,7 +3,7 @@ id: combat-damage
title: "Combat & Damage — targeting, firing, damage zones, death" title: "Combat & Damage — targeting, firing, damage zones, death"
status: established status: established
source_sections: "PROGRESS_LOG.md §10c; docs/HARD_PROBLEMS.md (P5)" source_sections: "PROGRESS_LOG.md §10c; docs/HARD_PROBLEMS.md (P5)"
related_topics: [subsystems, decomp-reference, reconstruction-gotchas, locomotion, rendering] related_topics: [subsystems, decomp-reference, reconstruction-gotchas, locomotion, rendering, translocation-warp, multiplayer]
key_terms: [damage-zone, TakeDamage, viewpoint-entity, master, replicant] key_terms: [damage-zone, TakeDamage, viewpoint-entity, master, replicant]
open_questions: open_questions:
- "Per-impact aim (cylinder lookup); collision damage application; DeathShutdown + collapse anim" - "Per-impact aim (cylinder lookup); collision damage application; DeathShutdown + collapse anim"
@@ -200,8 +200,10 @@ Built + runtime-verified. Changes:
the absorber bank — which stores NOTHING, so the whole unaimed path was inert until 2026-07-08 (the the absorber bank — which stores NOTHING, so the whole unaimed path was inert until 2026-07-08 (the
"can't kill the enemy" bug). See [[reconstruction-gotchas]] §2. [T2] "can't kill the enemy" bug). See [[reconstruction-gotchas]] §2. [T2]
- **`Mech::TakeDamageMessageHandler`** override registered (`MESSAGE_ENTRY(Mech, TakeDamage)`, overlays - **`Mech::TakeDamageMessageHandler`** override registered (`MESSAGE_ENTRY(Mech, TakeDamage)`, overlays
Entity's by ID): on `invalidDamageZone`, `msg->damageZone = table->ResolveHit(msg->damageData.impactPoint)`, Entity's by ID): the handler FIRST feeds the raw `Damage` to the Gyroscope hit-bounce (`GyroApplyDamage`,
clear the flag, then base-route. Aimed hits pass straight through. @0x4a0264 hub, task #56) before zone resolution; then on `invalidDamageZone`, `msg->damageZone =
table->ResolveHit(msg->damageData.impactPoint)`, clear the flag, then base-route. Aimed hits pass
straight through.
- **Named accessors (no databinding-trap raw reads):** `Mech::WorldToLocal` (`localToWorld.MultiplyByInverse`), - **Named accessors (no databinding-trap raw reads):** `Mech::WorldToLocal` (`localToWorld.MultiplyByInverse`),
`CylinderReferenceHeight` (`standingTemplateMaxY` = `collisionTemplate->maxY` = the binary `mech+0x2ec[+0xc]`), `CylinderReferenceHeight` (`standingTemplateMaxY` = `collisionTemplate->maxY` = the binary `mech+0x2ec[+0xc]`),
`TorsoHeading` (via the `BTGetTorsoTwist` bridge in `torso.cpp` → `Torso::CurrentTwist` = torso+0x1d8; `TorsoHeading` (via the `BTGetTorsoTwist` bridge in `torso.cpp` → `Torso::CurrentTwist` = torso+0x1d8;
@@ -220,7 +222,8 @@ Built + runtime-verified. Changes:
invisible 1-shot kills (internal zones are soft; the binary never aims them — they die only via the invisible 1-shot kills (internal zones are soft; the binary never aims them — they die only via the
destruction cascade `RecurseSegmentTable`/`SendSubsystemDamage`). On kill the wreck STAYS TARGETED destruction cascade `RecurseSegmentTable`/`SendSubsystemDamage`). On kill the wreck STAYS TARGETED
(`gEnemyMech` is NOT nulled) so beams keep terminating on it — nulling it made every later beam a (`gEnemyMech` is NOT nulled) so beams keep terminating on it — nulling it made every later beam a
"free" ray that visibly passed through the wreck; scoring latches off via `gEnemyDestroyed`. [T2] "free" ray that visibly passed through the wreck; scoring latches off via `gEnemyDestroyed` — until
the burial transition drops the lock (`gEnemyMech = 0` when the buried wreck goes INERT, mech4.cpp). [T2]
`Mech__DamageZone::TakeDamage` → engine armor model (`damageLevel `Mech__DamageZone::TakeDamage` → engine armor model (`damageLevel
+= damageAmount*damageScale[type]`) → 1.0 = zone destroyed → death. The Mech ctor populates the += damageAmount*damageScale[type]`) → 1.0 = zone destroyed → death. The Mech ctor populates the
inherited `damageZones[]` from the DamageZoneStream (type 0x14) resource. `class Damage{ damageType inherited `damageZones[]` from the DamageZoneStream (type 0x14) resource. `class Damage{ damageType
@@ -286,8 +289,9 @@ Full decomp map of the death path. Two tiers:
(mech+0x120[mech+0x11c]); as a subsystem's damage crosses a descriptor-table threshold (`FUN_0042a5f4` (mech+0x120[mech+0x11c]); as a subsystem's damage crosses a descriptor-table threshold (`FUN_0042a5f4`
detects the crossing, `FUN_0042a664` looks up the state) it applies the `GraphicState` ("Destroyed" = enum 1, detects the crossing, `FUN_0042a664` looks up the state) it applies the `GraphicState` ("Destroyed" = enum 1,
parsed @part_003.c:9099) to the subsystem graphic (`sub+0xd4`) AND dispatches an effect-creation message parsed @part_003.c:9099) to the subsystem graphic (`sub+0xd4`) AND dispatches an effect-creation message
(`FUN_0043663c`→`FUN_004364e4` to the effect mgr `app+0x38`). **Fully exported but a no-op STUB** in the (`FUN_0043663c`→`FUN_004364e4` to the effect mgr `app+0x38`). Fully exported; was a no-op stub
recon (mech.cpp:221). Gamedata `DeathSplashDamage`/`Radius`/`Effect` load into a descriptor @ +0x74/78/7c (mech.cpp:221) — now fully RECONSTRUCTED (mechdmg.cpp — ctor @0042a984 / Tick @0042aa2c; wired in the
Mech ctor, mech.cpp:1469) [T2]. Gamedata `DeathSplashDamage`/`Radius`/`Effect` load into a descriptor @ +0x74/78/7c
(`FUN_004a2da8`). Destroyed-skin variant set (`destroyed`, `destroyeds`…`destroyedd`) @part_003.c:5720. (`FUN_004a2da8`). Destroyed-skin variant set (`destroyed`, `destroyeds`…`destroyedd`) @part_003.c:5720.
**NOT EXPORTED (master-perf gap 0x4a9770-0x4ab188 + the un-exported TakeDamage) [T4]:** **NOT EXPORTED (master-perf gap 0x4a9770-0x4ab188 + the un-exported TakeDamage) [T4]:**
- The `movementMode` WRITER (sets 5-8 then 2/9 on death) + the fall-direction (5/6/7/8) selection. - The `movementMode` WRITER (sets 5-8 then 2/9 on death) + the fall-direction (5/6/7/8) selection.
@@ -302,19 +306,21 @@ the RP analog and wired into the active path (mech4.cpp `PerformAndWatch`).
### ✅ Death-STATE core DONE (2026-07-08) [T2] ### ✅ Death-STATE core DONE (2026-07-08) [T2]
`Mech::UpdateDeathState()` + `IsMechDestroyed()` (mech4.cpp) reconstruct the un-exported death branch from `Mech::UpdateDeathState()` + `IsMechDestroyed()` (mech4.cpp) reconstruct the un-exported death branch from
its exported consumers + the RP analog, called for EVERY mech early in `PerformAndWatch`: on `graphicAlarm its exported consumers + the RP analog, called for EVERY mech early in `PerformAndWatch`: on `graphicAlarm
>= 9` it (1) sets `movementMode = 5` → the collapse clip's latch in `AdvanceBodyAnimation` (fall direction >= 9` it (1) settles the death mode STRAIGHT to `movementMode = 9` (mech4.cpp:1183) — there is NO
5-8 un-exported → 5 [T3]); (2) loops the roster calling `Subsystem::DeathShutdown(1)` (RP `VTV::DeathShutdown` `movementMode = 5` collapse write (the only other writes are the drive's `= 1`, mech4.cpp:1044/1986); the
analog; base is a no-op virtual, a SHUTDOWN not teardown → safe, wreck STAYS); (3) next frame settles to fall latch 5-8 is never fired (task #32: no collapse anim exists in BT 4.11, see the VESTIGE proof above)
`movementMode = 9` → `IsDisabled` → locomotion frozen. The drive's lone `movementMode = 1` write (mech4.cpp [T1]; (2) loops the roster calling `Subsystem::DeathShutdown(1)` (RP `VTV::DeathShutdown`
analog; base is a no-op virtual, a SHUTDOWN not teardown → safe, wreck STAYS); (3) `movementMode` 9 →
`IsDisabled` → locomotion frozen. The drive's lone `movementMode = 1` write (mech4.cpp
~1309) is guarded on `!IsMechDestroyed` so the death state isn't clobbered. **Runtime-verified** (forced kill): ~1309) is guarded on `!IsMechDestroyed` so the death state isn't clobbered. **Runtime-verified** (forced kill):
`[death] … collapse + subsystem shutdown` → `[death] … settled -> disabled (IsDisabled=1, frozen wreck)`, `[death] … collapse + subsystem shutdown` → `[death] … settled -> disabled (IsDisabled=1, frozen wreck)`,
mech frozen in place (pos unchanged), subsystem tick + renderer keep running, **no crash, wreck stays**. mech frozen in place (pos unchanged), subsystem tick + renderer keep running, **no crash, wreck stays**.
Env gate `BT_DEATH_LOG=1`. Env gate `BT_DEATH_LOG=1`.
**Deferred (honest):** (a) the visible **collapse ANIMATION** may not latch through the active path — the **Deferred (honest):** (a) ✅ RESOLVED (task #32) — there IS no collapse animation to latch: the fall
gait SM showed `state=0` post-death (the clip trigger via `AdvanceBodyAnimation` needs the death `movementMode` latch is a VESTIGE (see the proof above); the authentic death visual is the wreck-hulk swap, and the death
to reach its latch; and spawned NON-player mechs don't advance their body anim at all). (b) **`MechDeathHandler`** mode settles straight to 9. (b) ✅ RESOLVED — **`MechDeathHandler`** is fully RECONSTRUCTED (mechdmg.cpp —
(the exported per-subsystem destroyed-skin + explosion engine, `FUN_0042a984`/`FUN_0042aa2c`) is still the ctor @0042a984 / Tick @0042aa2c; wired in the Mech ctor, mech.cpp:1469) [T2]; destroyed-skin swaps + zone
no-op stub → no death explosions/skin-swaps yet. (c) the whole-mech **DeathSplash** radius damage (un-exported). explosions verified live (see STEP 6 above). (c) the whole-mech **DeathSplash** radius damage (un-exported).
### ⚠ Death-latch correction (2026-07-09, task #52) [T1→T2] ### ⚠ Death-latch correction (2026-07-09, task #52) [T1→T2]
`IsMechDestroyed()` originally tested **`graphicAlarm >= 9` alone** — a bring-up shortcut that made a `IsMechDestroyed()` originally tested **`graphicAlarm >= 9` alone** — a bring-up shortcut that made a
+1 -1
View File
@@ -25,7 +25,7 @@ across archives. The bt411 `content/` dir is the assembled runtime tree. Full de
the source tree's `CONTENT/BT/ANIMS/`. All assembled into bt411 `content/`. [T2] the source tree's `CONTENT/BT/ANIMS/`. All assembled into bt411 `content/`. [T2]
## The runtime archive ## The runtime archive
`content/BTL4.RES` (3.23 MB, byte-identical to `reference/decomp/BTL4.RES`) contains the built `content/BTL4.RES` (3.23 MB; byte-identical to the pod-tree and decomp-extraction copies — provenance in `docs/PROGRESS_LOG.md §4`) contains the built
subset: models, materials, skeletons, animation clips, damage-zone/subsystem records, and **8 subset: models, materials, skeletons, animation clips, damage-zone/subsystem records, and **8
loadable maps**. Resolved by name/ID via `FindResourceDescription` (a missing map name null-derefs loadable maps**. Resolved by name/ID via `FindResourceDescription` (a missing map name null-derefs
at `MISSION.cpp:355`). [T1] at `MISSION.cpp:355`). [T1]
+14 -4
View File
@@ -141,14 +141,17 @@ From the weapon `.SUB` records + the charge-curve `.data` constants (PE-parsed a
## 6. Env-var gates (runtime; default OFF unless noted) ## 6. Env-var gates (runtime; default OFF unless noted)
The authentic stack is DEFAULT-ON (`BTEnvOn`, mechrecon.hpp): `BT_GAIT_CUTOVER`, `BT_GAIT_SM`, The authentic stack is DEFAULT-ON (`BTEnvOn`, mechrecon.hpp): `BT_GAIT_CUTOVER`, `BT_GAIT_SM`,
`BT_COLLISION`, `BT_REAL_CONTROLS` default ON — set `=0` to fall back. ⚠ Gates check `BT_COLLISION`, `BT_REAL_CONTROLS` default ON — set `=0` to fall back. ⚠ Most BOOLEAN gates check
`getenv(name) != NULL`, so `BT_X=""` (empty) still ENABLES; use `Remove-Item Env:\BT_X`. `getenv(name) != NULL` or first-char `!= '0'`, so `BT_X=""` (empty) still ENABLES; use
`Remove-Item Env:\BT_X`. Value-parsing gates are NOT empty-enabled: `BT_AUTOFIRE` and
`BT_KEY_NOFOCUS` require `'1'`, `BT_GOTO` requires a non-empty value, and `BT_WARP_MIP` is
default-ON (`'0'` disables).
| Var | Effect | | Var | Effect |
|---|---| |---|---|
| `BT_FORCE_THROTTLE` | auto-walk forward (no key) | | `BT_FORCE_THROTTLE` | auto-walk forward (no key) |
| `BT_SPAWN_ENEMY` | spawn a target mech 120u ahead along the spawn facing | | `BT_SPAWN_ENEMY` | spawn a target mech 120u ahead along the spawn facing |
| `BT_FORCE_FIRE` | auto-fire on cooldown | | `BT_AUTOFIRE=1` | hold the trigger (headless walk→fire→death harness; supersedes the dead `BT_FORCE_FIRE` — btl4main.cpp:310 set `fireForced` once at startup, but mech4.cpp:1567 unconditionally overwrites it every frame) |
| `BT_ASSERT_TO_DEBUGGER` | route CRT asserts to the debugger, not a modal box | | `BT_ASSERT_TO_DEBUGGER` | route CRT asserts to the debugger, not a modal box |
| `BT_HEAPCHECK` | whole-heap validation on every alloc/free (O(n²) at mission load — SLOW) | | `BT_HEAPCHECK` | whole-heap validation on every alloc/free (O(n²) at mission load — SLOW) |
| `BT_PROBE_BGF=<name\|ALL>` | boot-time BGF loader probe, exits after | | `BT_PROBE_BGF=<name\|ALL>` | boot-time BGF loader probe, exits after |
@@ -165,11 +168,18 @@ The authentic stack is DEFAULT-ON (`BTEnvOn`, mechrecon.hpp): `BT_GAIT_CUTOVER`,
| `BT_START_INSIDE` | begin in the cockpit view (V toggles) | | `BT_START_INSIDE` | begin in the cockpit view (V toggles) |
| `BT_FORCE_MODEL=<name>` | force the player mech (`madcat`/`owens`/…; btl4mssn.cpp — per-mech cockpit bring-up) | | `BT_FORCE_MODEL=<name>` | force the player mech (`madcat`/`owens`/…; btl4mssn.cpp — per-mech cockpit bring-up) |
| `BT_HIDE_COCKPIT` | hide the `*_cop` canopy shell (SHOWS by default — see [[cockpit-view]]) | | `BT_HIDE_COCKPIT` | hide the `*_cop` canopy shell (SHOWS by default — see [[cockpit-view]]) |
| `BT_COP_*` / `BT_EYE_FWD=<f>` | cockpit canopy + eye diagnostics (`DOUBLE`/`FLIP`/`RAMP_L`/`DEBUG`/`DUMP`; eye forward-push probe) — [[cockpit-view]] | | `BT_COP_*` / `BT_EYE_FWD=<f>` | cockpit canopy + eye diagnostics (`FRAME` (unlit frame colour override, default 0.13,0.12,0.15) / `SINGLE` (single-sided diag; double-sided is default) / `PLATES=1` (disable the punch stencil-cut kit) / `FLIP` / `DEBUG` / `DUMP`; eye forward-push probe) — [[cockpit-view]] |
| `BT_SHOT=<path.png>` | periodic backbuffer dump (every 90 frames) — non-disruptive visual verification | | `BT_SHOT=<path.png>` | periodic backbuffer dump (every 90 frames) — non-disruptive visual verification |
| `BT_TLOC_LOG` | translocation-warp lifecycle log (`[tloc] warp COLLAPSE/EXPAND/phase=…`) | | `BT_TLOC_LOG` | translocation-warp lifecycle log (`[tloc] warp COLLAPSE/EXPAND/phase=…`) |
| `BT_WARP_*` | translocation-warp visual tuning — all default to the verified values (see [[translocation-warp]]): `EYE_UP=8.25` (on-axis), `SPIN=4`, `TWIST=0`, `CONTRAST=1.0`, `LO_*/HI_*` (lavender ramp), `BLUR=0`, `TESS=3`, `MIP=1`, `CULL=cw`, `ANISO=0` | | `BT_WARP_*` | translocation-warp visual tuning — all default to the verified values (see [[translocation-warp]]): `EYE_UP=8.25` (on-axis), `SPIN=4`, `TWIST=0`, `CONTRAST=1.0`, `LO_*/HI_*` (lavender ramp), `BLUR=0`, `TESS=3`, `MIP=1`, `CULL=cw`, `ANISO=0` |
| `BT_WARP_SELFTEST` / `BT_WARP_SELFSHOT=<prefix>` | DIAG (off by default): force a held warp in a solo game / dump backbuffer frames to disk (visual-verification harness) | | `BT_WARP_SELFTEST` / `BT_WARP_SELFSHOT=<prefix>` | DIAG (off by default): force a held warp in a solo game / dump backbuffer frames to disk (visual-verification harness) |
| `BT_GYRO_LOG` | gyro bring-up log (gyro.cpp) |
| `BT_GYRO_TRACE` | per-frame hit-bounce integrator trace |
| `BT_REPL_LOG` | replicant/MP replication log (mech4.cpp) |
| `BT_GOTO="enemy"\|"x z"` / `BT_GOTO_LOG` | self-driving beeline (to the enemy or a map coordinate) + its log |
| `BT_MP_LOG` / `BT_MP_NET` / `BT_MP_FORCE_DMG` | MP diagnostics / forced cross-pod damage |
| `BT_AUTODRIVE=<0..1>` | headless throttle |
| `BT_KEY_NOFOCUS=1` | accept key input without window focus |
Full render/locomotion gates (BT_RAMP, BT_MATPRI, BT_CULL, BT_SHADOW_*, BT_LODSEL, BT_ADDLOD, Full render/locomotion gates (BT_RAMP, BT_MATPRI, BT_CULL, BT_SHADOW_*, BT_LODSEL, BT_ADDLOD,
BT_PUNCH, …) are catalogued in [[rendering]]. Warp visuals: [[translocation-warp]]. BT_PUNCH, …) are catalogued in [[rendering]]. Warp visuals: [[translocation-warp]].
+2 -3
View File
@@ -142,9 +142,8 @@ and every instrument is now live [T2]:**
the aim group translates by `reticlePosition` = the TORSO BORESIGHT (SetMatrix; NOT a free the aim group translates by `reticlePosition` = the TORSO BORESIGHT (SetMatrix; NOT a free
cursor — see [[combat-damage]] Targeting: the stick twists the torso, no mouse-aim exists). cursor — see [[combat-damage]] Targeting: the stick twists the torso, no mouse-aim exists).
This recovery also CONFIRMS the HUD attr-table ids 4/5/6/8/0xA/0xB/0xC/0xD name↔use pairings This recovery also CONFIRMS the HUD attr-table ids 4/5/6/8/0xA/0xB/0xC/0xD name↔use pairings
(hud.hpp had flagged them uncertain). Deferred: PNAME1-8.bgf 3D marker chain; the `blx_cop` (hud.hpp had flagged them uncertain). Deferred: PNAME1-8.bgf 3D marker chain. (The canopy shell
canopy shell renders black and is hidden by name filter (`BT_INSIDE_COCKPIT=1` shows it) — see is now authentic and shows by default — see [[cockpit-view]]; `BT_HIDE_COCKPIT=1` hides it.)
[[open-questions]].
## Key Relationships ## Key Relationships
- Full history: `docs/GAUGE_COMPOSITE.md`; reticle recovery: `phases/phase-02-dpl2d-reticle.md`. - Full history: `docs/GAUGE_COMPOSITE.md`; reticle recovery: `phases/phase-02-dpl2d-reticle.md`.
+6 -2
View File
@@ -7,7 +7,7 @@ related_topics: [asset-formats, decomp-reference, reconstruction-gotchas, combat
key_terms: [RootTranslation, ground-model, SequenceController, MechControlsMapper, SLD, joint] key_terms: [RootTranslation, ground-model, SequenceController, MechControlsMapper, SLD, joint]
open_questions: open_questions:
- "Authentic per-mech turn-rate constant (currently bring-up constant)" - "Authentic per-mech turn-rate constant (currently bring-up constant)"
- "Body-callback gimp handlers (states 16-19); airborne callbacks" - "Airborne clip callbacks (FUN_004a7970) deferred"
--- ---
# Locomotion # Locomotion
@@ -33,7 +33,9 @@ raw disasm** (both Advance fns had NO static decomp caller; found by byte-scanni
- **BODY channel = the replication PROJECTOR.** `IntegrateMotion` (0x4ab1c8; body advance @0x4ab312, - **BODY channel = the replication PROJECTOR.** `IntegrateMotion` (0x4ab1c8; body advance @0x4ab312,
from `FUN_004ab430`, the projected-origin/dead-reckon updater) stores `-dist/dt` into from `FUN_004ab430`, the projected-origin/dead-reckon updater) stores `-dist/dt` into
**projectedVelocity (+0x2a0)** — the dead-reckoning feed for update records. Its phase drift is **projectedVelocity (+0x2a0)** — the dead-reckoning feed for update records. Its phase drift is
locally INVISIBLE in the binary. (The recon does not yet wire this store — follow-up.) [T1] locally INVISIBLE in the binary. The literal projectedVelocity store is unwired, but the
update-record velocity feed is live via the localVelocity/worldLinearVelocity maintenance
(mech4.cpp VELOCITY STORAGE block) — replicant gait (task #50) runs off it. [T1]
**v5 (current): display == travel BY CONSTRUCTION through the LEG** (body advances first, leg last). **v5 (current): display == travel BY CONSTRUCTION through the LEG** (body advances first, leg last).
History: v3 (travel=leg, display=body) foot-slipped — two channels, different consumers; v4 unified History: v3 (travel=leg, display=body) foot-slipped — two channels, different consumers; v4 unified
BOTH on the body (mis-reading 0x4ab430 as the travel source) — feet planted, but whenever the two BOTH on the body (mis-reading 0x4ab430 as the travel source) — feet planted, but whenever the two
@@ -51,6 +53,8 @@ through walk/run caps (`LoadLocomotionClips`, mech3.cpp:326 — measures `walkSt
**Aliasing bug class (namedClip):** `namedClip[]`@0x5e0 == `animationClips[]`@0x5cc+0x14 (ONE array); **Aliasing bug class (namedClip):** `namedClip[]`@0x5e0 == `animationClips[]`@0x5cc+0x14 (ONE array);
`gimpBaseClip`@0x64c == `animationClips[0x20]`; `bodyAnimationState`@0x728 == `bodyStateAlarm.level`. `gimpBaseClip`@0x64c == `animationClips[0x20]`; `bodyAnimationState`@0x728 == `bodyStateAlarm.level`.
Declared-separate members don't see each other's writes — alias them. Declared-separate members don't see each other's writes — alias them.
Replicants (task #50): travel = engine DeadReckon; leg channel driven joints-only from the replicated
worldLinearVelocity -> speedDemand (mech4.cpp REPLICANT MOTION) — detail in [[multiplayer]]. [T2]
## The AUTHENTIC 1995 ground model (default-on, `BT_GROUND_REAL`) ## The AUTHENTIC 1995 ground model (default-on, `BT_GROUND_REAL`)
Decoded by the 10-agent `ground-model-decode` workflow (binary `FUN_004a9b5c` = the master perf). Decoded by the 10-agent `ground-model-decode` workflow (binary `FUN_004a9b5c` = the master perf).
+22 -19
View File
@@ -6,20 +6,22 @@ source_sections: "PROGRESS_LOG.md §7 (Phase 7), §8 (P6); docs/HARD_PROBLEMS.md
related_topics: [wintesla-port, combat-damage, locomotion, decomp-reference] related_topics: [wintesla-port, combat-damage, locomotion, decomp-reference]
key_terms: [master, replicant, EGG, dead-reckon] key_terms: [master, replicant, EGG, dead-reckon]
open_questions: open_questions:
- "Cross-pod combat (damage to a replicant's master); replicant gait; pod-LAN config" - "pod-LAN config (real IPs); update-record velocity from the body-channel projection; peer SimulationState/DropZoneLocation replication (authentic peer warp spheres); Mech-level update records @0x4a0c2c (in progress)"
--- ---
# Multiplayer # Multiplayer
Pod-to-pod networked play. The hard infrastructure exists (WinTesla replaced DOS `NETNUB` with a Pod-to-pod networked play. The hard infrastructure exists (WinTesla replaced DOS `NETNUB` with a
WinSock2 TCP stack); the work is integrating + smoke-testing it for BT. Full detail: WinSock2 TCP stack), and MP is now **substantially reconstructed + 2-node verified** — replication,
`docs/PROGRESS_LOG.md §7, §8`; the problem writeup: `docs/HARD_PROBLEMS.md` (P6). cross-pod combat, beam visuals, replicant gait, respawn (tasks #46-#52). Remaining: pod-LAN config,
fidelity nuances, and the Mech-level update records. Full detail: `docs/PROGRESS_LOG.md §7, §8`;
the problem writeup: `docs/HARD_PROBLEMS.md` (P6).
## The stack (already reconstructed) ## The stack (already reconstructed)
- WinTesla replaced `NETNUB` with a **3446-line WinSock2 TCP** reimplementation (`MUNGA_L4/L4NET.CPP`, - WinTesla replaced `NETNUB` with a **~3.5k-line WinSock2 TCP** reimplementation (`MUNGA_L4/L4NET.CPP`,
`SOCK_STREAM`/ReliableMode, zero SOCK_DGRAM); the master/replicant distributed-sim core `SOCK_STREAM`/ReliableMode, zero SOCK_DGRAM); the master/replicant distributed-sim core
(InterestManager/Entity/HostManager) is complete. So MP = integrate + smoke-test that stack (gated (InterestManager/Entity/HostManager) is complete. MP was integrated on that stack and verified
on P3 locomotion + P5 entity lifecycle + subsystem WAVEs). The rumored `L4NET.CPP:1853` send-size end-to-end 2-node. The rumored `L4NET.CPP:1853` send-size
bug is DEAD CODE (`#if MESSAGE_BUFFERING`==0). [T2] bug is DEAD CODE (`#if MESSAGE_BUFFERING`==0). [T2]
## Master / replicant model ## Master / replicant model
@@ -49,7 +51,7 @@ emulator** (⚠ `NotationFile::ReadText` expects NUL-SEPARATED lines). [T2]
via `MakeEntityRenderables`, which runs a TWO-STEP view sequence — inside skeleton + `COCKPIT via `MakeEntityRenderables`, which runs a TWO-STEP view sequence — inside skeleton + `COCKPIT
eyepoint`, then outside skeleton + `external chase` (`[view] …` logs, btl4vid.cpp:2158) — and the eyepoint`, then outside skeleton + `external chase` (`[view] …` logs, btl4vid.cpp:2158) — and the
external chase camera is NOT re-installed (only ONE `[BTrender] external debug chase camera external chase camera is NOT re-installed (only ONE `[BTrender] external debug chase camera
installed`, btl4vid.cpp:648, for the whole session despite multiple respawns). Plausible failure: installed`, btl4vid.cpp:647, for the whole session despite multiple respawns). Plausible failure:
if that two-step completes only to the COCKPIT step (raced/interrupted on the `-net` ladder), the if that two-step completes only to the COCKPIT step (raced/interrupted on the `-net` ladder), the
node is left stuck INSIDE — body hidden by the inside skeleton, shadow/reticle flagging with it = node is left stuck INSIDE — body hidden by the inside skeleton, shadow/reticle flagging with it =
the reported bundle. Camera + reticle + view + `tshd` shadow are all gated on `buildDebugChaseCamera the reported bundle. Camera + reticle + view + `tshd` shadow are all gated on `buildDebugChaseCamera
@@ -109,7 +111,7 @@ the change only ADDS `ValidFlag`).
2. Wire: `NetworkManager::Send` (L4NET.CPP:1062) → `send()` to host 3 (online). 2. Wire: `NetworkManager::Send` (L4NET.CPP:1062) → `send()` to host 3 (online).
3. B: `ReceiveNetworkPacket` (NTTMGR.cpp:107) → `GetEntityPointer(3:22)` = `entityIndexSocket.Find` 3. B: `ReceiveNetworkPacket` (NTTMGR.cpp:107) → `GetEntityPointer(3:22)` = `entityIndexSocket.Find`
(HOSTMGR.h:270) → resolves to B's **master mech (classID 3001=0xBB9)**`Post(EntityManagerEventPriority)`. (HOSTMGR.h:270) → resolves to B's **master mech (classID 3001=0xBB9)**`Post(EntityManagerEventPriority)`.
4. B: event drains → `Entity::Receive` (now `valid=1`) → `Mech::TakeDamageMessageHandler` (mech.cpp:548) 4. B: event drains → `Entity::Receive` (now `valid=1`) → `Mech::TakeDamageMessageHandler` (mech.cpp:584)
→ invalidZone (1) cylinder lookup → zone damage. ~36 hits × 12 → B's mech DESTROYED + death transition. → invalidZone (1) cylinder lookup → zone damage. ~36 hits × 12 → B's mech DESTROYED + death transition.
**Two prior mis-diagnoses corrected — both were the WRONG messageID.** `Entity::TakeDamageMessageID` is **Two prior mis-diagnoses corrected — both were the WRONG messageID.** `Entity::TakeDamageMessageID` is
@@ -124,7 +126,7 @@ on the wire" claim. Both are FALSE. The id is correct end-to-end (`3:22` = B's m
is corrupted. Lesson: when a message probe seems to see a wrong id, first confirm the numeric messageID. is corrupted. Lesson: when a message probe seems to see a wrong id, first confirm the numeric messageID.
Retained gated instrument: `[mp-force]` (BT_MP_FORCE_DMG + BT_MP_LOG) — the 2-node cross-pod reproducer, Retained gated instrument: `[mp-force]` (BT_MP_FORCE_DMG + BT_MP_LOG) — the 2-node cross-pod reproducer,
off in solo. `[mp-hdlr]` (BT_MP_NET, mech.cpp:554) logs each applied cross-pod hit. 2-node launch recipe + off in solo. `[mp-hdlr]` (BT_MP_NET, mech.cpp:591) logs each applied cross-pod hit. 2-node launch recipe +
`scratchpad/mp_test.sh`: A `-egg MP.EGG -net 1501`, B `-net 1601`, then `python tools/btconsole.py MP.EGG `scratchpad/mp_test.sh`: A `-egg MP.EGG -net 1501`, B `-net 1601`, then `python tools/btconsole.py MP.EGG
127.0.0.1:1501 127.0.0.1:1601` (MP.EGG `[pilots]` = game ports 1502/1602). 127.0.0.1:1501 127.0.0.1:1601` (MP.EGG `[pilots]` = game ports 1502/1602).
@@ -195,13 +197,13 @@ Re-ran the one-box smoke test on the current build (world-pick targeting, weapon
transition, HUD all landed since P6): console egg → mesh → RunningMission on BOTH instances, 174+ transition, HUD all landed since P6): console egg → mesh → RunningMission on BOTH instances, 174+
×144-byte update records EACH side (msgID=6), 2 mech trees per instance, 0 crashes over ~6 min. ×144-byte update records EACH side (msgID=6), 2 mech trees per instance, 0 crashes over ~6 min.
**Gap map to a first playable LAN fight** (in wiring order): **Gap map to a first playable LAN fight** (in wiring order):
1. **Enemy selection**: the world-pick tests only `gEnemyMech` (the solo dummy, btplayer.cpp:791). 1. **Enemy selection — DONE (task #46).** The world-pick used to test only `gEnemyMech` (the solo
MP: the pick must test every OTHER mech (the peer replicants) — generalize to a candidate walk dummy, btplayer.cpp:791); now generalized to the live-mech registry candidate walk
(mech entities != viewpoint). Small. (`BTGetTargetCandidates`, all mechs != shooter) — see "Cross-pod combat step 1+2" above.
2. **Cross-pod damage**: dispatch TakeDamage at the REPLICANT → verify the engine reroute carries 2. **Cross-pod damage — DONE (task #47).** TakeDamage dispatched at the REPLICANT reroutes to the
it to the owning master (the KB claims Dispatch reroutes; not yet exercised with our STEP-6 owning master (verified end-to-end: full cross-pod kill; the master takes real zone damage + runs
handler). The master takes real zone damage + runs its own death transition (task #42 placed the its own death transition; task #42 placed the death dispatch victim-side — MP-correct by
death dispatch victim-side — MP-correct by construction). construction). See "Cross-pod combat step 1+2" above.
3. **Victim visuals on the shooter's screen** — PARTIALLY resolved (user-observed 2026-07-09): the 3. **Victim visuals on the shooter's screen** — PARTIALLY resolved (user-observed 2026-07-09): the
wreck SWAP does appear on the killer's screen, but the death SINK/burial does not (the collapse+ wreck SWAP does appear on the killer's screen, but the death SINK/burial does not (the collapse+
burial runs only in the owning pod's death transition). Fix path: transcribe the recovered burial runs only in the owning pod's death transition). Fix path: transcribe the recovered
@@ -313,9 +315,10 @@ transition, HUD all landed since P6): console egg → mesh → RunningMission on
variants, 2 alarm, 3 leg-state+heat with body-channel write-through re-sync, 5 knockdown variants, 2 alarm, 3 leg-state+heat with body-channel write-through re-sync, 5 knockdown
(SetBodyAnimation(0x20) write-through), 6 death, 7 impact, 8 movementMode) — transcribing it (SetBodyAnimation(0x20) write-through), 6 death, 7 impact, 8 movementMode) — transcribing it
would replicate remote KNOCKDOWN/death/heat states; beams did not need it. would replicate remote KNOCKDOWN/death/heat states; beams did not need it.
5. **2-window driving**: input gates on window focus (alternate windows; `BT_KEY_NOFOCUS` for 5. **2-window driving — RESOLVED (tasks #48/#51).** Keyboard MP turning was restored at the root
harness). DEATHS scoring should light via the existing BTPostKillScore MP branch. Respawn = (the `pilotArray[1]` shrunk-span overrun fix, task #51); `BT_KEY_NOFOCUS` exists for automated
the P5 teardown debt (deferred until needed). harnesses. DEATHS scoring lights via the existing BTPostKillScore MP branch. Respawn is
reconstructed (task #52 — see item 3b).
## Key Relationships ## Key Relationships
- Base: [[wintesla-port]] (L4NET). Depends on: [[locomotion]] (update writer), [[combat-damage]] - Base: [[wintesla-port]] (L4NET). Depends on: [[locomotion]] (update writer), [[combat-damage]]
+18 -15
View File
@@ -60,25 +60,27 @@ authentic path scoped.
on mech+0x388, but 0x388 has 11 reads / 0 direct stores across CODE → set indirectly). Residue: on mech+0x388, but 0x388 has 11 reads / 0 direct stores across CODE → set indirectly). Residue:
(a) the binary's own per-frame reticle→mech copy + the AUTO-TARGET SELECTOR are still in an (a) the binary's own per-frame reticle→mech copy + the AUTO-TARGET SELECTOR are still in an
un-exported gap (a message/selector; our port auto-targets the single living enemy — for MP, un-exported gap (a message/selector; our port auto-targets the single living enemy — for MP,
reconstruct the real multi-target selection: nearest/most-aligned/cycle); (b) our cockpit view is body-mounted, so on a reconstruct the real multi-target selection: nearest/most-aligned/cycle); (b) the eyepoint now
TWIST-CAPABLE mech the crosshair should deflect with the torso twist (`BTTwistToReticleX` is rides the parent DCS (task #55 authentic eye), so torso pose reaches the view; on a
wired for it) AND the torso should visibly lead the legs — verify on a twist mech when one is TWIST-CAPABLE mech (selectable via `BT_FORCE_MODEL`) the crosshair should deflect with the
in play (the BLH is fixed-torso, boresight always centred); (c) pre-burial, the pick still torso twist (`BTTwistToReticleX` is wired for it) AND the torso should visibly lead the legs —
verify the reticle deflection on a twist mech (the BLH is fixed-torso, boresight always
centred); (c) pre-burial, the pick still
tests the sinking wreck's collision box at its parked position (pre-existing wreck-targeting tests the sinking wreck's collision box at its parked position (pre-existing wreck-targeting
behavior). behavior).
- **Cockpit HUD leftovers (tasks #35-#38 residue, 2026-07-08)** — the reticle + 7 weapon pips + - **Cockpit HUD leftovers (tasks #35-#38 residue, 2026-07-08)** — the reticle + 7 weapon pips +
ALL the instrument dynamics are LIVE (the Execute @004cdcf0 gap was RECOVERED via capstone ALL the instrument dynamics are LIVE (the Execute @004cdcf0 gap was RECOVERED via capstone
disasm, task #37; the authentic Lock producer + the simple-X mode landed in #38 — see disasm, task #37; the authentic Lock producer + the simple-X mode landed in #38 — see
[[gauges-hud]] for the full instrument map). Remaining: (a) the **`*_cop` canopy shell** — [[gauges-hud]] for the full instrument map). Remaining: (a) the **`*_cop` canopy shell** —
SOLVED for the Madcat (task #55, see [[cockpit-view]]): authentic eye (baseOffset + parent-DCS + SOLVED for all 8 (task #55): authentic eye + the PUNCH stencil-cut kit + double-sided cop
inverse view) + single-sided inward-wound lattice + dark `softer` ramp = the dark frame with the geometry + unlit constant frame colour (`BT_COP_FRAME`) — see [[cockpit-view]] Rendering/FINAL;
world through the openings, verified vs gameplay footage; shows by DEFAULT now shows by DEFAULT now (`BT_HIDE_COCKPIT=1` hides). NOTE the old claim here ("canopy windows are
(`BT_HIDE_COCKPIT=1` hides). NOTE the old claim here ("canopy windows are punch texels") was punch texels") was WRONG — the shell has no texture; the openings are geometry. ✅ RESOLVED
WRONG — the shell has no texture; the openings are geometry. ✅ RESOLVED (2026-07-11): the (2026-07-11): PUNCH = a 3-chunk STENCIL-CUT kit (mask/hull/twin, i860-firmware-decoded)
PUNCH patches are the transparent WINDOWS (dropped by the loader); the frame = the non-punch executed as a D24S8 stencil cut; visible canopy = hull-minus-apertures ([[cockpit-view]]
geometry only. All 8 mechs render their authentic canopy — madcat's dome, thor/owens/sunder's §FINAL). All 8 mechs render connected dark frames with clear viewports (the intermediate
brace/dash remnants, and the authentically FRAMELESS bhk1/loki/vulture/avatar. Eye placement "frameless bhk1/loki/vulture/avatar" reading was wrong); thor matches the pod footage exactly.
verified exact per-mech incl. Thor's +1.13 offset cockpit ([[cockpit-view]]). (b) the **3D marker Eye placement verified exact per-mech incl. Thor's +1.13 offset cockpit ([[cockpit-view]]). (b) the **3D marker
chain** ([0x31c]/[0x320] dpl objects + the PNAME1-8.bgf player-name meshes over the locked chain** ([0x31c]/[0x320] dpl objects + the PNAME1-8.bgf player-name meshes over the locked
target — matters for MP). (c) the compass rotation SIGN is derived-not-verified [T3] (turn target — matters for MP). (c) the compass rotation SIGN is derived-not-verified [T3] (turn
left → the stem should swing right; flip the sin sign in Draw if footage disagrees). left → the stem should swing right; flip the sin sign in Draw if footage disagrees).
@@ -198,8 +200,9 @@ authentic path scoped.
movementMode states don't reach the other pod (the wreck SWAP does appear). The writer's disasm is movementMode states don't reach the other pod (the wreck SWAP does appear). The writer's disasm is
recovered + 9 record types decoded (`reference/decomp/mech_writeupdate_004a0c2c.disasm.txt`); recovered + 9 record types decoded (`reference/decomp/mech_writeupdate_004a0c2c.disasm.txt`);
the read-side leg-state branches at mech.cpp:1511/:1613 are the dead Wword comparisons. the read-side leg-state branches at mech.cpp:1511/:1613 are the dead Wword comparisons.
- The pod-LAN config (real IPs, bare-IP pilot entries). The WinSock2 TCP stack (L4NET.CPP) is - The WinSock2 stack (L4NET.CPP) is 2-node verified end-to-end (cross-pod kills, beams,
reconstructed + smoke-tested on one box (two instances share a world, movement replicates). replicant gait — tasks #46-#51); remaining = the real pod-LAN config (real IPs, bare-IP
pilot entries).
## Rendering follow-ups (non-blocking) ## Rendering follow-ups (non-blocking)
- **.PFX effect-layer polish (deferred 2026-07-08; the layer itself is LIVE + verified).** The - **.PFX effect-layer polish (deferred 2026-07-08; the layer itself is LIVE + verified).** The
+8 -4
View File
@@ -37,10 +37,14 @@ they map into this repo (reconstructed BT → `game/reconstructed/`, engine →
content → `content/`, raw decomp → `reference/decomp/`). [T2] content → `content/`, raw decomp → `reference/decomp/`). [T2]
## Current state (2026-07) ## Current state (2026-07)
`btl4.exe` boots, renders the world + a skinned mech, and runs a **drive → animate → target → fire `btl4.exe` boots, renders the world + a skinned mech, and runs a full **drive → animate → target →
→ damage → destroy** single-player loop. The engine/renderer/HAL/audio are done (WinTesla); the fire → damage → destroy → respawn** single-player loop (task #52). **2-node MP is verified
active work is reconstructing each BT subsystem's authentic behavior from the binary. The **gauge end-to-end** — replication, cross-pod targeting/damage/kill, beam visuals, replicant gait (tasks
system is complete** ([[gauges-hud]]). [T2] #46-#51, [[multiplayer]]). All 8 cockpit canopies are authentic + the horizontal-FOV fix (task #55,
[[cockpit-view]]); the Gyroscope is live byte-exact with hit-bounce (task #56); the **gauge system
is complete** ([[gauges-hud]]). The engine/renderer/HAL/audio are done (WinTesla); the active work
is reconstructing each BT subsystem's authentic behavior from the binary. Remaining: pod-LAN
config, Mech-level update records, per-subsystem waves. [T2]
## Key Relationships ## Key Relationships
- Full detail: `docs/PROGRESS_LOG.md`. - Full detail: `docs/PROGRESS_LOG.md`.
+6 -4
View File
@@ -20,8 +20,9 @@ usually here, not in the logic.
> **The core rule (RULE: no stand-ins):** the full game logic IS in the pseudocode — a "gap" > **The core rule (RULE: no stand-ins):** the full game logic IS in the pseudocode — a "gap"
> is a reconstruction stub not yet filled, never a hole in the original. Never write > is a reconstruction stub not yet filled, never a hole in the original. Never write
> placeholder logic for an apparent gap; read the decomp. (User: "there are no gaps, just > placeholder logic for an apparent gap; read the decomp. (User: "there are no gaps, just
> work to be done.") Bring-up scaffolding (env-var paths, explosion-for-beam) is clearly > work to be done.") Bring-up scaffolding (the `BT_AUTOFIRE`/`BT_AUTODRIVE`/`BT_GOTO` env
> marked and meant to be REPLACED, never to substitute for reading the decomp. [T2] > harness; historically explosion-for-beam, since replaced by real per-weapon beams) is
> clearly marked and meant to be REPLACED, never to substitute for reading the decomp. [T2]
--- ---
@@ -52,8 +53,9 @@ and `BTVal` is the recon **absorber** type: `operator=` stores NOTHING, every re
check `mech.hpp`'s offset map first (the slot may already exist under a best-effort check `mech.hpp`'s offset map first (the slot may already exist under a best-effort
mislabel; 0x111 was mislabeled `ammoExpended`). mislabel; 0x111 was mislabeled `ammoExpended`).
- `if (Wword(a) != Wword(b))` and `if (Wword(a) == 2)` are BOTH always-false → the guarded - `if (Wword(a) != Wword(b))` and `if (Wword(a) == 2)` are BOTH always-false → the guarded
branch is dead code. Known dead sites: `mech.cpp:1511` + `mech.cpp:1613` (replicant branch is dead code. Known dead sites: `mech.cpp:1673` + `mech.cpp:1775` (replicant
leg-state / stability-alarm sync in ReadUpdateRecord — multiplayer-only, deferred). state sync in ReadUpdateRecord — MP is live; these are being revived by the in-progress
Mech Write/ReadUpdateRecord reconstruction, task #1).
- Any `Wword(N)` used for OBJECT access reads a shared global, not `this+i*4`; e.g. - Any `Wword(N)` used for OBJECT access reads a shared global, not `this+i*4`; e.g.
`(Mech*)Wword(3)` for a zone's owner → garbage; use `GetOwningSimulation()`. `(Mech*)Wword(3)` for a zone's owner → garbage; use `GetOwningSimulation()`.
+11 -6
View File
@@ -24,13 +24,18 @@ Full detail: `docs/PROGRESS_LOG.md §10b`; the systemic bug classes are [[recons
The full game logic IS in the pseudocode (the binary ran the game); a "gap" is a reconstruction The full game logic IS in the pseudocode (the binary ran the game); a "gap" is a reconstruction
stub not yet filled, not a hole in the original. **Never write stand-in/placeholder logic for an stub not yet filled, not a hole in the original. **Never write stand-in/placeholder logic for an
apparent gap — read the decomp.** (User: "there are no gaps, just work to be done.") Bring-up apparent gap — read the decomp.** (User: "there are no gaps, just work to be done.") Bring-up
scaffolding (env-var paths, explosion-for-beam, a player-gated drive) is clearly MARKED and meant scaffolding (the `BT_AUTOFIRE`/`BT_AUTODRIVE`/`BT_GOTO` env harness; historically
to be REPLACED by the real reconstructed system, never to substitute for reading the decomp. [T2] explosion-for-beam and a player-gated drive, since replaced by the real reconstructions) is
clearly MARKED and meant to be REPLACED by the real reconstructed system, never to substitute
for reading the decomp. [T2]
## Decompilation stack (Plan B — in progress) ## Decompilation stack (established)
- **Ghidra 12.1.2 + JDK21** installed under `tools/` (portable). `ExportBTSource.java` run headless - **Ghidra 12.1.2 + JDK21** are an EXTERNAL install (`tools/` holds only python utilities); the
on `BTL4OPT.EXE` → real decompiled C in `reference/decomp/recovered/`. The pass is headless scripts live in `reference/ghidra_scripts/` (`ExportBTSource.java`, `DecompVSS.java`,
**assert-anchored** (few funcs/file — anchored on the asserts that carry source paths). [T2] `ExportAll.java`). `ExportBTSource.java` run headless on `BTL4OPT.EXE` → decompiled C in
`reference/decomp/` (`bt_<src>.cpp.c` assert-anchored files; bulk pseudocode in
`reference/decomp/all/part_*.c`). The pass is **assert-anchored** (few funcs/file — anchored
on the asserts that carry source paths). [T2]
- For a `FUN_` the assert-anchored exporter skipped: **`tools/disas2.py <VA> [len]`** (capstone - For a `FUN_` the assert-anchored exporter skipped: **`tools/disas2.py <VA> [len]`** (capstone
disassembly of `BTL4OPT.EXE` — recovers x87 math Ghidra drops, folds known calls + float disassembly of `BTL4OPT.EXE` — recovers x87 math Ghidra drops, folds known calls + float
constants). Or `DecompVSS.java` (headless address-list decompiler). [T2] constants). Or `DecompVSS.java` (headless address-list decompiler). [T2]
+11 -2
View File
@@ -3,7 +3,7 @@ id: rendering
title: "Rendering — the D3D9 pipeline, materials, sky, beams, performance" title: "Rendering — the D3D9 pipeline, materials, sky, beams, performance"
status: established status: established
source_sections: "PROGRESS_LOG.md §10 (render-fidelity notes); docs/BGF_FORMAT.md" source_sections: "PROGRESS_LOG.md §10 (render-fidelity notes); docs/BGF_FORMAT.md"
related_topics: [bgf-format, asset-formats, wintesla-port, locomotion, pod-hardware] related_topics: [bgf-format, asset-formats, wintesla-port, locomotion, pod-hardware, cockpit-view]
key_terms: [L4D3D, material-ramp, BSL, LOD, DPL, beam] key_terms: [L4D3D, material-ramp, BSL, LOD, DPL, beam]
open_questions: open_questions:
- "Replacement-LOD for NON-additive multi-LOD models; day/night material path priority (BT_MATPRI)" - "Replacement-LOD for NON-additive multi-LOD models; day/night material path priority (BT_MATPRI)"
@@ -22,6 +22,9 @@ mech — WHITE baked verts) is UNLIT, colorized by the material's 2-endpoint **[
(`dpl_SetMaterialRamp` — texture luminance indexes a low→high gradient); **normal-bearing geometry** (`dpl_SetMaterialRamp` — texture luminance indexes a low→high gradient); **normal-bearing geometry**
(~150 vehicle/missile files) is LIT by the map light. Applying the ramp to lit geometry = the "dusty (~150 vehicle/missile files) is LIT by the map light. Applying the ramp to lit geometry = the "dusty
white blobs" bug (gate on `hasNormals`). [T2] white blobs" bug (gate on `hasNormals`). [T2]
Exception: cockpit-frame (`*_cop`) batches are pure-emissive constant colour (0.13,0.12,0.15),
`BT_COP_FRAME` overrides — see [[cockpit-view]] (task #55; the old `BT_COP_RAMP_L` ramp-index
approach is retired). [T2]
## The big render-fidelity fixes (dbase/desert matched to pod footage) ## The big render-fidelity fixes (dbase/desert matched to pod footage)
- **Geometry:** CONN is a flat trilist (not fan); CONN+PCONN coexist — see [[bgf-format]]. Malformed - **Geometry:** CONN is a flat trilist (not fan); CONN+PCONN coexist — see [[bgf-format]]. Malformed
@@ -37,10 +40,16 @@ white blobs" bug (gate on `hasNormals`). [T2]
`L4DPLCFG`): resolves map+time → clip/fog/ambient + a directional sun. Bring-up stubs `L4DPLCFG`): resolves map+time → clip/fog/ambient + a directional sun. Bring-up stubs
(EnsureValidProjection / per-frame ambient / uninit cloud colours) had clobbered it — now they (EnsureValidProjection / per-frame ambient / uninit cloud colours) had clobbered it — now they
RE-ASSERT the env values. Debug: copy BTDPL.INI → *DBG.INI with `debug=True`. [T2] RE-ASSERT the env values. Debug: copy BTDPL.INI → *DBG.INI with `debug=True`. [T2]
- **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
**`D3DFMT_D24S8`** for the cockpit punch stencil-cut (L4VIDEO.cpp:2799; sequence
L4D3D.cpp:1199-1248) — see [[cockpit-view]]. [T2]
## Backface culling (default CW, `BT_CULL`) ## Backface culling (default CW, `BT_CULL`)
The bring-up `D3DCULL_NONE` drew interior/back faces (the "dark wedge" shapes = mesh insides). CW is The bring-up `D3DCULL_NONE` drew interior/back faces (the "dark wedge" shapes = mesh insides). CW is
correct for the BGF quad triangulation `[a b c][a c d]`. [T2] correct for the BGF quad triangulation `[a b c][a c d]`. [T2] Exception: cockpit `*_cop` batches
default DOUBLE-SIDED (`BT_COP_SINGLE=1` restores single-siding, diag) — see [[cockpit-view]]. [T2]
## LODs (default: shipping-engine first-LOD + ADDITIVE_LODS; `BT_ADDLOD`/`BT_LOD_SCALE`/`BT_PUNCH`) ## LODs (default: shipping-engine first-LOD + ADDITIVE_LODS; `BT_ADDLOD`/`BT_LOD_SCALE`/`BT_PUNCH`)
See [[bgf-format]] for the √3 range decode, the ADDITIVE_LODS cumulative rule, PUNCH cutouts, and the See [[bgf-format]] for the √3 range decode, the ADDITIVE_LODS cumulative rule, PUNCH cutouts, and the
+6 -3
View File
@@ -6,7 +6,7 @@ source_sections: "PROGRESS_LOG.md §10d; docs/SUBSYS_PLAN.md; docs/VEHICLE_SUBSY
related_topics: [decomp-reference, reconstruction-gotchas, combat-damage, gauges-hud] related_topics: [decomp-reference, reconstruction-gotchas, combat-damage, gauges-hud]
key_terms: [subsystem, factory, ClassID, subsystem-roster, PoweredSubsystem, bridge] key_terms: [subsystem, factory, ClassID, subsystem-roster, PoweredSubsystem, bridge]
open_questions: open_questions:
- "Gyroscope (0xBC4) integrator; Myomers coupling (gates on owning-player @mech+0x190); 0xBD3 damage-hub untangle (WAVE 8)" - "Myomers coupling (gates on owning-player @mech+0x190); 0xBD3 damage-hub untangle (WAVE 8)"
--- ---
# Subsystems # Subsystems
@@ -35,7 +35,7 @@ Making a base byte-exact GROWS every subclass — they must be re-based TOGETHER
`static_assert`-locked (the P7 alarm-unification: HeatSink 0x1D0 → PoweredSubsystem 0x31C → MechWeapon `static_assert`-locked (the P7 alarm-unification: HeatSink 0x1D0 → PoweredSubsystem 0x31C → MechWeapon
0x3F0 → Emitter 0x478). [T2] 0x3F0 → Emitter 0x478). [T2]
## Reconstruction waves (state: ~18-19 of 20 factory cases wired to real classes) ## Reconstruction waves (state: 19 of 20 factory cases wired to real classes — only 0xBD3 remains, the MechControlsMapper squatter)
- **WAVE 1** — HeatableSubsystem re-based onto MechSubsystem (de-shadow cascade). - **WAVE 1** — HeatableSubsystem re-based onto MechSubsystem (de-shadow cascade).
- **WAVE 2** — heat family (Condenser/AggregateHeatSink/Reservoir) + HUD + MechTech (un-swap). - **WAVE 2** — heat family (Condenser/AggregateHeatSink/Reservoir) + HUD + MechTech (un-swap).
- **WAVE 3** — power bus (Generator/PoweredSubsystem) + Emitter/PPC fire-path (end-to-end fire; heat - **WAVE 3** — power bus (Generator/PoweredSubsystem) + Emitter/PPC fire-path (end-to-end fire; heat
@@ -46,7 +46,10 @@ Making a base byte-exact GROWS every subclass — they must be re-based TOGETHER
- **WAVE 6** — Myomers (mover-coupled; structural un-stub is INERT — no live mover/heat coupling). - **WAVE 6** — Myomers (mover-coupled; structural un-stub is INERT — no live mover/heat coupling).
- **WAVE 7** — projectile/missile weapons (byte-exact; flying projectiles are a PORT reconstruction — - **WAVE 7** — projectile/missile weapons (byte-exact; flying projectiles are a PORT reconstruction —
the 2007 Entity is 0x1BC vs the binary's 0x300, so raw base-offset reads fail). the 2007 Entity is 0x1BC vs the binary's 0x300, so raw base-offset reads fail).
- **DEFERRED** — Gyroscope 0xBC4 (NaN integrator); SubsystemMessageManager 0xBD3 (WAVE 8 — a - **TASK #56 (2026-07-11)** — Gyroscope LIVE byte-exact (ctor @004b3778, sizeof 0x3D0 locked;
integrators + `FUN_004b2980` damage fan-out; joint dispatch from the Mech performance tail
@0x4aaf74/83; `BT_GYRO_LOG`/`BT_GYRO_TRACE`) — see [[cockpit-view]].
- **DEFERRED** — SubsystemMessageManager 0xBD3 (WAVE 8 — a
**damage/explosion consolidation hub** cached to `Mech[0x10d]`=0x434; recon MISLABELS the slot **damage/explosion consolidation hub** cached to `Mech[0x10d]`=0x434; recon MISLABELS the slot
`controlsMapper` + the drive squats there while the real mapper is roster slot 0, so wiring it needs `controlsMapper` + the drive squats there while the real mapper is roster slot 0, so wiring it needs
an untangle. NOT the valve/advanced-damage gate — that's the owning **BTPlayer** @mech+0x190, see an untangle. NOT the valve/advanced-damage gate — that's the owning **BTPlayer** @mech+0x190, see
+5 -2
View File
@@ -138,8 +138,11 @@ the world-anchored `BTStartWarpEffect(x,y,z)` (mechdmg.cpp). The peer path is a
## Env gates (all default to the verified values) ## Env gates (all default to the verified values)
`BT_WARP_EYE_UP=8.25` · `BT_WARP_SPIN=4` · `BT_WARP_TWIST=0` · `BT_WARP_CONTRAST=1.0` · `BT_WARP_EYE_UP=8.25` · `BT_WARP_SPIN=4` · `BT_WARP_TWIST=0` · `BT_WARP_CONTRAST=1.0` ·
`BT_WARP_LO_R/G/B=0.15/0.12/0.35` · `BT_WARP_HI_R/G/B=0.98/0.94/1.0` · `BT_WARP_BLUR=0` · `BT_WARP_LO_R/G/B=0.15/0.12/0.35` · `BT_WARP_HI_R/G/B=0.98/0.94/1.0` · `BT_WARP_BLUR=0` ·
`BT_WARP_TESS=3` · `BT_WARP_MIP=1` · `BT_WARP_TILE_U=1` · `BT_WARP_RADFREQ=1` · `BT_WARP_ANISO=0` · `BT_WARP_TESS=3` · `BT_WARP_MIP=1` · `BT_WARP_TILE_U=1` · `BT_WARP_RADFREQ=1` (`BT_WARP_TILE_V` is an
`BT_WARP_CULL=cw` · `BT_WARP_TINT=0` · `BT_WARP_TILT=0` · `BT_TLOC_LOG` (lifecycle log) · accepted alias — bgfload.cpp:665) · `BT_WARP_ANISO=0` · `BT_WARP_CULL=cw` · `BT_WARP_TEXMOD=0`
(diag: =1 re-enables the TEXTURE×DIFFUSE modulate — double-tints; btl4vid.cpp:2640) · `BT_WARP_TILT=0` ·
`BT_WARP_SCALE` (btl4vid.cpp:2263-2266, collapse =v / expand =1.5·v) · `BT_WARP_NOSCROLL` (diag,
btl4vid.cpp:2373) · `BT_TLOC_LOG` (lifecycle log) ·
`BT_WARP_SELFTEST` / `BT_WARP_SELFSHOT` (DIAG capture harness — off by default; retained for visual verification of the open peer/collapse work). `BT_WARP_SELFTEST` / `BT_WARP_SELFSHOT` (DIAG capture harness — off by default; retained for visual verification of the open peer/collapse work).
## Key files ## Key files
+2 -3
View File
@@ -15,12 +15,11 @@ on top of it. Full detail: `docs/PROGRESS_LOG.md §5b, §8`.
## What WinTesla already did (do NOT rebuild) ## What WinTesla already did (do NOT rebuild)
- **Renderer bypass: DONE** — `MUNGA_L4/L4D3D.cpp` + `DXUtils` replace libDPL / the IG board with - **Renderer bypass: DONE** — `MUNGA_L4/L4D3D.cpp` + `DXUtils` replace libDPL / the IG board with
Direct3D9. No `libdpl.lib` in the tree. (Our from-scratch `port/` D3D9 viewer is now a Direct3D9. No `libdpl.lib` in the tree. (The early from-scratch D3D9 viewer was retired and removed.) [T1]
reference/sandbox, not the path.) [T1]
- **Audio: DONE** — OpenAL + libsndfile replacing the HMI "SOS" engine. [T1] - **Audio: DONE** — OpenAL + libsndfile replacing the HMI "SOS" engine. [T1]
- **L4 HAL on Windows + the VS build system: DONE.** [T1] - **L4 HAL on Windows + the VS build system: DONE.** [T1]
- **Red Planet game logic: COMPLETE & buildable** — `VTV/VTVMPPR/WEAPSYS/...`. RP is at/near playable. [T1] - **Red Planet game logic: COMPLETE & buildable** — `VTV/VTVMPPR/WEAPSYS/...`. RP is at/near playable. [T1]
- **Multiplayer: the DOS `NETNUB` driver is already replaced by a 3446-line WinSock2 TCP - **Multiplayer: the DOS `NETNUB` driver is already replaced by a ~3.5k-line WinSock2 TCP
reimplementation** (`MUNGA_L4/L4NET.CPP`) + the master/replicant distributed-sim core. See reimplementation** (`MUNGA_L4/L4NET.CPP`) + the master/replicant distributed-sim core. See
[[multiplayer]]. [T1] [[multiplayer]]. [T1]
+90
View File
@@ -126,6 +126,36 @@ DIV-BIZ2:
related_terms: [BGF, BMF, PFBIZTAG] related_terms: [BGF, BMF, PFBIZTAG]
related_topics: [bgf-format, asset-formats] related_topics: [bgf-format, asset-formats]
PMESH:
kind: format
definition: The BGF mesh-container chunk inside a PATCH (geogroup) — interleaved float32 vertices plus faces carried in CONN and/or PCONN lists.
related_terms: [BGF, CONN, PCONN]
related_topics: [bgf-format]
CONN:
kind: format
definition: BGF CONNECTION_LIST (0x0047) — a FLAT TRIANGLE LIST (3 indices/face; corpus-verified n%3==0), NOT "one polygon, fan-triangulate". COEXISTS with PCONN in one pmesh (370/841 GEO models mix them — dropping the CONN triangles was a real bug).
related_terms: [BGF, PMESH, PCONN]
related_topics: [bgf-format]
PCONN:
kind: format
definition: BGF PCONN_LIST — packed quad/hex faces of a PMESH (quads must be triangulated). Can coexist with loose CONN triangles in the same pmesh.
related_terms: [BGF, PMESH, CONN]
related_topics: [bgf-format]
LOD:
kind: concept
definition: Level-of-detail band selection in BGF models. Each LOD chunk's 0x2046 header = a [near..far) viewing band; the board drew the LOD whose band contains the camera distance. ADDITIVE_LODS models instead draw EVERY LOD with d < OutDist (near detail adds onto coarser massing).
related_terms: [BGF, SV_SPECIAL, DIV-BIZ2]
related_topics: [bgf-format]
SV_SPECIAL:
kind: format
definition: The BGF name-driven special-behavior token chunk (0x2037) — dz_* damage/articulation tokens, object-level ADDITIVE_LODS (draw-all-LODs arena structures), patch-level PUNCH (dpl_Punchize stencil-cut, e.g. the cockpit canopy windows).
related_terms: [BGF, DIV-BIZ2, LOD]
related_topics: [bgf-format]
BMF: BMF:
kind: format kind: format
definition: DIV-BIZ2 (FILETYPE=1) material+texture LIBRARY (no pixels). Material -> DIFFUSE color + MATERIAL_TEXTURE -> texture -> TEXTURE_MAP image basename. Tag 0x18 BITSLICE selects a BSL sub-image; 0x28 ramp ref; 0x26 emissive. definition: DIV-BIZ2 (FILETYPE=1) material+texture LIBRARY (no pixels). Material -> DIFFUSE color + MATERIAL_TEXTURE -> texture -> TEXTURE_MAP image basename. Tag 0x18 BITSLICE selects a BSL sub-image; 0x28 ramp ref; 0x26 emissive.
@@ -138,6 +168,12 @@ BSL:
related_terms: [BMF, VTX, TGA, material-ramp] related_terms: [BMF, VTX, TGA, material-ramp]
related_topics: [asset-formats, rendering] related_topics: [asset-formats, rendering]
VTX:
kind: format
definition: DIV-VTX2 — a small texture container with trailing raw RGB pixels (e.g. VIDEO/TEX/BINTA.VTX, 64x64 RGB, pixels at offset 57 — the translocation-warp gradient). One of the three texture-pixel sources alongside .tga and .bsl.
related_terms: [BSL, BMF]
related_topics: [asset-formats, translocation-warp]
SKL: SKL:
kind: format kind: format
definition: INI joint skeleton. [joint] parent=, Type=(hingex/y/z|ball|balltranslate), Object=part.bgf, dzone=, tranx/y/z, pitch/yaw/roll. Build a DCS tree; neutral pose ~ translations. definition: INI joint skeleton. [joint] parent=, Type=(hingex/y/z|ball|balltranslate), Object=part.bgf, dzone=, tranx/y/z, pitch/yaw/roll. Build a DCS tree; neutral pose ~ translations.
@@ -186,6 +222,12 @@ VMF:
related_terms: [BMF, BSL, beam] related_terms: [BMF, BSL, beam]
related_topics: [rendering] related_topics: [rendering]
beam:
kind: concept
definition: The weapon discharge visual drawn from the Emitter sim state (Emitter::FireWeapon builds a muzzle->target beam). The dpl_* beam renderable was never ported — the port draws it via BTPushBeam/BTDrawBeams (L4VIDEO), the ermlaser.bgf tube with the scrolling bexp grit (.VMF SCROLL); ER lasers red, PPC blue, standard yellow.
related_terms: [VMF, DPL, BGF]
related_topics: [rendering, combat-damage]
material-ramp: material-ramp:
kind: concept kind: concept
definition: The IG board colours no-normal geometry (terrain/mesas/sky/buildings/mech) by a material's 2-endpoint RAMP (dpl_SetMaterialRamp) — texture luminance indexes a low->high gradient. Normal-bearing geometry (vehicles) is LIT instead. Applying the ramp to lit geometry = the "white blobs" bug. definition: The IG board colours no-normal geometry (terrain/mesas/sky/buildings/mech) by a material's 2-endpoint RAMP (dpl_SetMaterialRamp) — texture luminance indexes a low->high gradient. Normal-bearing geometry (vehicles) is LIT instead. Applying the ramp to lit geometry = the "white blobs" bug.
@@ -213,6 +255,12 @@ EntitySegment:
related_terms: [joint, subsystem-roster, GetSegment] related_terms: [joint, subsystem-roster, GetSegment]
related_topics: [locomotion, combat-damage] related_topics: [locomotion, combat-damage]
siteeyepoint:
kind: concept
definition: The skeleton SITE segment naming the cockpit eye camera mount — a child of jointeye (WriteMechJoint drives jointeye - translation = the eye-position spring, rotation = the body-tip spring). The eye ctor caller (part_014.c:5525-66, BTL4VID.CPP) gates on this segment name and mounts the eye via the segment's GetBaseOffset() under its PARENT draw component.
related_terms: [EntitySegment, joint, SKL]
related_topics: [cockpit-view]
subsystem-roster: subsystem-roster:
kind: concept kind: concept
definition: subsystemArray @mech+0x128 (count @0x124) — the inherited Entity table of the mech's Subsystem* instances (heat/weapons/gyro/sensor/...). A +0x128-style owner offset in subsystem code is the ROSTER, NOT the segment table (a classic bug source). definition: subsystemArray @mech+0x128 (count @0x124) — the inherited Entity table of the mech's Subsystem* instances (heat/weapons/gyro/sensor/...). A +0x128-style owner offset in subsystem code is the ROSTER, NOT the segment table (a classic bug source).
@@ -225,6 +273,12 @@ subsystem:
related_terms: [subsystem-roster, factory, ClassID, PoweredSubsystem] related_terms: [subsystem-roster, factory, ClassID, PoweredSubsystem]
related_topics: [subsystems, decomp-reference] related_topics: [subsystems, decomp-reference]
PoweredSubsystem:
kind: class
definition: Subsystem base class drawing power from the generator chain (ClassID 0xBC2, ctor @004b0f74, sizeof 0x31C). The heat leaf chains PoweredSubsystem:HeatSink:HeatableSubsystem:MechSubsystem — Emitter/PPC/Sensor/Myomers/weapons descend here. Publishes InputVoltage to the gauge system.
related_terms: [subsystem, ClassID, gauge]
related_topics: [subsystems, decomp-reference]
factory: factory:
kind: concept kind: concept
definition: The Mech-ctor per-class subsystem factory (switch on resource ClassID). The case LABELS are systematically MISLABELED — the real class is the ctor-address comment reconciled via CLASSMAP.md, not the case name. Each real class wired via a Create<Class>Subsystem bridge. definition: The Mech-ctor per-class subsystem factory (switch on resource ClassID). The case LABELS are systematically MISLABELED — the real class is the ctor-address comment reconciled via CLASSMAP.md, not the case name. Each real class wired via a Create<Class>Subsystem bridge.
@@ -237,6 +291,18 @@ ClassID:
related_terms: [factory, subsystem, CLASSMAP] related_terms: [factory, subsystem, CLASSMAP]
related_topics: [subsystems, decomp-reference] related_topics: [subsystems, decomp-reference]
SequenceController:
kind: class
definition: The BT animation clip player driving a joint channel (seqctl.cpp; SelectSequence@004277a8, Advance@0042790c). Two embedded on the Mech, 0x60 bytes each — legAnimation@0x65c (the LOCAL sim - travel + the displayed pose) and bodyAnimation@0x6bc (the replication projector feeding update records).
related_terms: [ANI, RootTranslation, joint]
related_topics: [locomotion]
MechControlsMapper:
kind: class
definition: The roster slot 0 subsystem mapping pilot controls -> demands (mechmppr.cpp @004afbe0; btl4mppr.cpp mappers) — interprets input into speedDemand/turnDemand, the LEG channel's live source and the update-record speedDemand feed. NOTE recon MISLABELS Mech[0x10d] (+0x434) as controlsMapper; that cache is the SubsystemMessageManager — the real mapper is roster slot 0.
related_terms: [subsystem-roster, RIO, SequenceController]
related_topics: [locomotion, pod-hardware]
master: master:
kind: concept kind: concept
definition: A locally-simulated entity (the pod's own mech + spawned dummies). Ticks its full drive/subsystems and EMITS network update records. Contrast replicant. definition: A locally-simulated entity (the pod's own mech + spawned dummies). Ticks its full drive/subsystems and EMITS network update records. Contrast replicant.
@@ -249,6 +315,12 @@ replicant:
related_terms: [master, dead-reckon, multiplayer] related_terms: [master, dead-reckon, multiplayer]
related_topics: [multiplayer] related_topics: [multiplayer]
dead-reckon:
kind: concept
definition: The replicant motion model — extrapolate from the last network update record and converge toward the master's replicated origin (engine DeadReckon; velocity feed = projectedVelocity/worldLinearVelocity). Replicant TRAVEL stays DeadReckon; the leg channel animates joints only (task #50).
related_terms: [replicant, master, SequenceController]
related_topics: [multiplayer, locomotion]
viewpoint-entity: viewpoint-entity:
kind: concept kind: concept
definition: application->GetViewpointEntity() — the local pod's own mech (the cockpit view + player controls). Gate player-only logic on `this == GetViewpointEntity()` (Mech::PerformAndWatch runs for EVERY mech). definition: application->GetViewpointEntity() — the local pod's own mech (the cockpit view + player controls). Gate player-only logic on `this == GetViewpointEntity()` (Mech::PerformAndWatch runs for EVERY mech).
@@ -312,6 +384,12 @@ methodDescription:
related_terms: [gauge, attribute-pointer, GaugeRenderer] related_terms: [gauge, attribute-pointer, GaugeRenderer]
related_topics: [gauges-hud] related_topics: [gauges-hud]
gauge:
kind: concept
definition: A cockpit instrument (widget) rendered by the GaugeRenderer onto the pod's MFD surfaces. Built from gauge\l4gauge.cfg keywords (each resolving to a methodDescription) and bound to game state by NAME via the attribute-pointer system.
related_terms: [GaugeRenderer, methodDescription, attribute-pointer, MFD]
related_topics: [gauges-hud]
GaugeRenderer: GaugeRenderer:
kind: class kind: class
definition: The engine gauge system. BuildConfigurationFile parses gauge\l4gauge.cfg via GaugeInterpreter (Initialize->GetProcedureBody->ParsePrimitive). Builds LAZILY -> a too-early process kill shows a false "not built". Composites onto the pod's SVGA16 bit-plane surfaces. definition: The engine gauge system. BuildConfigurationFile parses gauge\l4gauge.cfg via GaugeInterpreter (Initialize->GetProcedureBody->ParsePrimitive). Builds LAZILY -> a too-early process kill shows a false "not built". Composites onto the pod's SVGA16 bit-plane surfaces.
@@ -324,12 +402,24 @@ MFD:
related_terms: [gauge, GaugeRenderer, SVGA16, pod] related_terms: [gauge, GaugeRenderer, SVGA16, pod]
related_topics: [gauges-hud, pod-hardware] related_topics: [gauges-hud, pod-hardware]
SVGA16:
kind: class
definition: The pod's 16-color SVGA gauge surface — ONE shared pixelBuffer the MFD bit-plane masks overlay. SVGA16::BuildWindows makes a fullscreen device + window per gauge/MFD surface on the pod's multi-adapter hardware; SVGA16::DrawDevSurface renders the off-pod dev composite (BT_DEV_GAUGES).
related_terms: [MFD, gauge, GaugeRenderer, pod]
related_topics: [pod-hardware, gauges-hud]
damage-zone: damage-zone:
kind: class kind: class
definition: Mech__DamageZone (engine DamageZone base). Armor model: damageLevel += damageAmount*damageScale[type], accumulates to 1.0 (destroyed). Built by the Mech ctor from the DamageZoneStreamResourceType (0x14) resource. Aimed hits route via Entity::TakeDamageMessage. definition: Mech__DamageZone (engine DamageZone base). Armor model: damageLevel += damageAmount*damageScale[type], accumulates to 1.0 (destroyed). Built by the Mech ctor from the DamageZoneStreamResourceType (0x14) resource. Aimed hits route via Entity::TakeDamageMessage.
related_terms: [DZM, TakeDamage, DZ] related_terms: [DZM, TakeDamage, DZ]
related_topics: [combat-damage] related_topics: [combat-damage]
TakeDamage:
kind: concept
definition: The Entity damage message — Entity::TakeDamageMessageID = 18 (NOT 21; runtime-confirmed). Entity::TakeDamageMessage(id, size, inflictingEntityID, zone, Damage&) -> target->Dispatch; the base handler IGNORES zone==-1, the Mech override (@0x4a037a) cylinder-maps unaimed hits and routes damageZones[zone]->TakeDamage.
related_terms: [damage-zone, replicant, master]
related_topics: [combat-damage, multiplayer]
ground-model: ground-model:
kind: concept kind: concept
definition: The authentic 1995 vertical-position model (FUN_004a9b5c). NO GRAVITY — an ABSOLUTE per-frame ground SNAP via the zone BoundingBoxTree (FindBoundingBoxUnder), lift = 5% of volume X-width. Walls block by FULL FRAME REJECTION; crushable props pass with a crunch. definition: The authentic 1995 vertical-position model (FUN_004a9b5c). NO GRAVITY — an ABSOLUTE per-frame ground SNAP via the zone BoundingBoxTree (FindBoundingBoxUnder), lift = 5% of volume X-width. Walls block by FULL FRAME REJECTION; crushable props pass with a crunch.