diff --git a/docs/re/INDEX.md b/docs/re/INDEX.md index f730b82e..b9c6a1aa 100644 --- a/docs/re/INDEX.md +++ b/docs/re/INDEX.md @@ -39,7 +39,7 @@ Promote to a prose `structures/…md` file when a format needs behavioural notes | Live guest-memory read | ✅ | [`tools/re-capture/gmem.py`](../../tools/re-capture/gmem.py) | Canary backs the guest address space with `/dev/shm/xenia_memory_*`; guest VAs map in through Xenia's fixed table. Full-RAM search ~0.2 s (sparse, `SEEK_DATA`). No debugger, no emulator patch, game keeps running | | IDXD object layout solver | ✅ | [`tools/re-capture/weapon_runtime.py`](../../tools/re-capture/weapon_runtime.py) | Scan RAM for a class's vtable → enumerate its objects → brute-force `(field, offset, encoding)` against the disc records. Accepts a binding only on **zero** contradictions. Generalizes to any IDXD-backed definition | | Live entity state, anchored on the definition | ✅ | [`tools/re-capture/own_state.py`](../../tools/re-capture/own_state.py) · [autopilot](autopilot-memory-driven.md) | An undamaged craft holds its definition's own numbers, so a *solved definition field* locates the matching live field without a value scan: definition `HP` (1500) → **hull at `position+0x154`**, confirmed by a trace across a death (30/60/90 per hit, negative at 0). Reusable for any live counter whose maximum the definition carries | -| Mission / escort state, every entity's hull | ✅ | [`tools/re-capture/mission_state.py`](../../tools/re-capture/mission_state.py) · [escort state](mission-escort-state.md) | `hull = position + 0x154` is a property of the **entity class**, not of the player object: at t=0 it equals each entity's own definition `HP` across 7 classes and 5 distinct HP values (turret 100, fighter 500, destroyer 10000, cruiser 30000, **ACROPOLIS 25000**), falls under fire (780 damage events in 240 s), goes negative at death, and the object then leaves the heap. So an escort objective is scoreable live — `UN_f101_TCAF_Acropolis` measured at 25000 → 23038 over 240 s, attack starting only at t≈170 s. `REMAINING OB` counts objectives, not hostiles (012 on the HUD vs 118 live ADAN); its address is still ❔ | +| Mission / escort state, every entity's hull | ✅ | [`tools/re-capture/mission_state.py`](../../tools/re-capture/mission_state.py) · [escort state](mission-escort-state.md) | `hull = position + 0x154` is a property of the **entity class**, not of the player object: at t=0 it equals each entity's own definition `HP` across 7 classes and 5 distinct HP values (turret 100, fighter 500, destroyer 10000, cruiser 30000, **ACROPOLIS 25000**), falls under fire (780 damage events in 240 s), goes negative at death, and the object then leaves the heap. So an escort objective is scoreable live — `UN_f101_TCAF_Acropolis` measured at 25000 → 23038 over 240 s, attack starting only at t≈170 s. `REMAINING OB` counts objectives, not hostiles (012 on the HUD vs 118 live ADAN); its address **is found** — see [mission-objective-counter](structures/mission-objective-counter.md) — but it is **run-dependent** and must be re-derived per run (refuted as a constant 2026-08-26) | | In-flight control mapping | ✅/🟡 | [`tools/re-capture/fire_probe.sh`](../../tools/re-capture/fire_probe.sh) · [controls](flight-controls-runtime.md) | Measured by holding each pad input and photographing the HUD ammo counters: **`RB` = nose gun** (6000→5956 in 4 s, ~11 rounds/s, HEAT rises), **`Y` = main mount** (missiles, 300→299), d-pad = **tactical map** overlay, nothing else moves a counter. No target-cycle input exists — the `TARGET` marker is present with nothing pressed, so targeting is automatic and a missile lock is **time-on-target**. That, not target choice or ballistics, is what caps lethality at 2 kills per 98 missiles | | Throttle → speed law | ✅/🟡 | [flight-speed-law](flight-speed-law.md) | **The throttle selects a TARGET SPEED**, it does not add thrust: no input settles at ~420 (`CruisingVelocity` 350), `RT` at ~1 530 (`MaximumVelocity` 1200), `LT` at ~125 (`MinimumVelocity` 100), and releasing either returns to cruise. `Acceleration`/`Deceleration` govern the convergence rate (measured ~440–560 units/s² against 500/600). 🟡 measured world speeds run ≈1.2–1.3× the definition numbers while the HUD shows the definition value exactly, so world units are a constant (~1.25) multiple of the definition's velocity unit | | Input → dynamics calibration | ✅ | [`tools/re-capture/ctrl_probe.py`](../../tools/re-capture/ctrl_probe.py) · [`binq.py`](../../tools/re-capture/binq.py) | Hold each pad input in turn and measure the craft's speed as displacement/s of its own position triple — no speed field needed first. Settled the throttle: **`RT` accelerates, `LT` brakes, and the setting persists** (488 → 1510 → 174 units/s), overturning an earlier field-scan conclusion | diff --git a/docs/re/captures/remaining-ob-004-crossrun.png b/docs/re/captures/remaining-ob-004-crossrun.png new file mode 100644 index 00000000..b03e8910 Binary files /dev/null and b/docs/re/captures/remaining-ob-004-crossrun.png differ diff --git a/docs/re/structures/mission-objective-counter.md b/docs/re/structures/mission-objective-counter.md index 3f194416..86863af0 100644 --- a/docs/re/structures/mission-objective-counter.md +++ b/docs/re/structures/mission-objective-counter.md @@ -2,8 +2,33 @@ **Status:** ✅ `CONFIRMED` for one Stage 02 run: a **big-endian u32** whose value is exactly the HUD's `REMAINING OB`, verified across two transitions it was not -selected by. 🟡 the address itself is from one run — **cross-run stability is -untested**. ❔ what it counts, and whether objective-marked entities carry a flag. +selected by. ❌ **the ADDRESS is run-dependent — measured 2026-08-26, see below.** +❔ what it counts, and whether objective-marked entities carry a flag. + +> ## ❌ Cross-run stability: REFUTED (2026-08-26) +> +> The 🟡 above said cross-run stability was untested. It is now tested, and the +> address does **not** carry over. A fresh Stage 02 run (guarded route, stage +> asserted via `assert_stage.py UN_f101_TCAF_Acropolis`): +> +> | | | +> |---|---| +> | HUD | `Remaining OB : 004` ([capture](../captures/remaining-ob-004-crossrun.png)) | +> | RAM `0xbdb59668` | **95748078**, constant over four samples 12 s apart | +> +> Not 4, not near 4, and not moving while the mission ran. So `0xbdb59668` is a +> property of *that* run's heap, exactly as the corpus's own warning about the +> heap re-allocating between runs predicts. +> +> ❔ **No cheap constant shift either.** Looking for a BE u32 equal to the HUD's +> `4` near the old address gives **1654** candidates within ±1 MB and **11202** +> within ±16 MB — far too many to isolate without the transition filter. So there +> is no "old address + delta" shortcut to be had. +> +> **Practical consequence:** treat the address as *derived per run*, never as a +> constant. The method below (`ob_scan.py`: scan at one value, filter against +> live memory at a **different** value) is the durable result here — the number +> `0xbdb59668` is not. ## Why it matters