Three results, two of them against my own earlier claims: - REFUTED: position = instance - 0x12c. The corpus anchors on position (def ptr at +0x130, orientation at -0x70, hull at +0x154) and name_of reads the def ptr at instance+4, which predicts -0x12c. Measured over all 42 named instances: almost every read is (0,0,0), three are garbage, and 0/42 move. The vtable object and the position block are different structures. - WITHDRAWN: last iteration's claim that entities2.py's ENT_VA window is aimed at the definitions rather than the instances. entities2 does not look for vtable objects at all -- it hunts moving position triples and checks +0x130, the documented anchor -- and it had worked minutes earlier (6914 movers, +0x130 voted 92x; then 6634/138x). I built the defect report on the single sample in between that returned zero. The +0x29d0 position candidate falls with it. - FOUND: sampling 64 spots across the 505 extents (357 MB) twice, 2.5s apart, with the mission visibly running, only 5 change. The megabyte holding all 42 instances is byte-identical over seconds, as is its primary-VA counterpart. The mapping IS live (5 regions prove it); what is undetermined is whether the entity records are simply static or whether writes land in a different alias. Either way: verify a region changes before measuring through it.
4.2 KiB
❌ Two of my own claims, refuted — and a live-memory trap behind both
Measured 2026-08-26, Canary on the retail disc, save slot 01, Stage 01, in
flight with a live HUD (TIME 00:28.42, speed 350, target on radar, dialogue
mid-render — the game was unambiguously running throughout).
❌ Refuted: position = instance − 0x12c
The corpus anchors the entity layout on position:
autopilot-memory-driven.md gives the definition
pointer at position + 0x130, orientation at position − 0x70, hull at
position + 0x154. gworld.py's name_of() reads the definition pointer at
instance + 4. If those name the same field, instance + 4 = position + 0x130,
so position = instance − 0x12c.
They do not. Read at instance − 0x12c for all 42 named instances:
UN_f001_TCAF_DeltaSaber_T_Player ( 0.0, 0.9, 0.1) moved 0.00
UN_e106_ADAN_Destroyer ( -48.9, 0.0, 0.0) moved 0.00
UN_S01_Asteroid_cmesh_01a (2.07e11, 0.0, 0.0) moved 0.00
...
moved in 0.8 s : 0/42
Almost every read is (0, 0, 0), three are garbage, and nothing moves. The
vtable-bearing object and the position block are two different structures that
merely name the same units. The prediction was clean and it was wrong.
❌ Withdrawn: "entities2.py's VA window is aimed at the wrong region"
Last iteration I recorded ENT_VA_LO/HI = 0xBD000000–0xBE000000 as a defect, on the grounds that the live instances sit at
0xBC384CE0–0xBC9BAC20 and the window "covers the definitions instead".
That reasoning was wrong. It assumed the thing the window should contain is the
vtable-bearing instance — but entities2.py does not look for those. It hunts
moving position triples and checks +0x130 for a definition pointer, exactly
the documented anchor. And in the run where I called it broken it had worked
moments earlier: 6914 movers, +0x130 voted 92×, then 6634 and 138× on a
re-run. I built a defect report on the one sample in between that returned zero —
the same single-sample error this corpus keeps logging.
The window may still be imperfect (it is hardcoded, and the heap moves). But it is not "aimed at the definitions", and nothing here shows it needs changing.
🟡→❌ The +0x29d0 position candidate is not trustworthy either
It was read through the same region that is shown below not to be updating, so what it captured is load-time data, not a live position. Withdrawn pending a re-measurement through a region that demonstrably changes.
✅ The trap: most of guest memory is not changing while the game runs
Sampling 64 spots of 64 KB spread across the mapping's 505 extents (357 MB), twice, 2.5 s apart, with the mission visibly running:
CHANGING: 5 / 64
0x007006f000 0x00704db000 0x0070557b000 0x00705df000 0x0080240000
Everything else — including the megabyte containing all 42 live instances
(0x11c37d780), and that region's primary-VA counterpart at 0x00bc300000 — is
byte-identical over seconds. So:
- The mapping is live. Five regions prove it, so "the shm view is stale" as a blanket claim is refuted.
- The entity-object region genuinely does not change on a seconds timescale.
- ❔ Not determined: whether that is because those records are static
metadata and the moving state lives elsewhere, or because the guest physical
page is aliased at several file offsets and writes land in a different one.
Both fit the evidence.
gmem.primary_va(0x11c384ce0) = 0xbc384ce0shows the alias relationship exists; it does not show which copy the guest writes.
Consequence for anyone reading guest memory here: verify the specific region you are sampling actually changes before drawing conclusions from it. A scan that finds correct, name-resolving records can still be reading a snapshot.
Still open
- Where the live position blocks are. The five changing offsets above are the
place to start, but
moving()takes VAs and converts withgmem.va_to_off, while those five are file offsets — they are not the same number and must be converted before they can be scanned. - Whether
entities2.py's window needs any change at all.