docs/re: the hull anchor is class-wide — the escort objective is scoreable live
own_state.py found hull = position + 0x154 for the PLAYER. Stage 02 is an escort and is lost when the ACROPOLIS sinks, so scoring it needs someone else's hull. Measured over 240 s of Stage 02: at t=0 pos+0x154 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). Nothing read above its HP; the five that read slightly below were already under fire when the player launched. It falls with damage (780 events), goes negative at death, and the object then leaves the heap. UN_f101_TCAF_Acropolis: HP 25000, radius 1400, measured 25000 -> 23038 over 240 s with the attack starting only at t~170 s (~600 HP/min) — so the earlier GAME OVER was not a fast loss, it was an undefended one. Also: REMAINING OB reads 012 while 118 ADAN entities are alive, so it counts objectives, not hostiles; its address is still unknown.
This commit is contained in:
@@ -32,6 +32,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 ❔ |
|
||||
| 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 |
|
||||
|
||||
## Functions / code paths
|
||||
|
||||
Reference in New Issue
Block a user