re: sub_8226E458 is a splice, but not shown to touch the trigger queue
Chasing which of sub_8226EAB8's 16 callers grows the trigger count: sub_8226E458 decrements a count at 8(r30) then calls the insert helper -- a splice -- and has exactly one caller, inside sub_8226D740, the per-frame engine->script drain. That suggests the engine moves records into the phase queue each frame. But the call site refutes the neat reading: at 0x8226D780 the argument is lwz r4, 324(r29), the UNIT ARRAY, not the trigger container. So I have not shown sub_8226E458 touches the trigger queue at all, and 'the engine feeds triggers each frame' is my inference rather than the disassembly's. Recorded unresolved. Taking a function's shape for its purpose is what produced the 'push' mislabel on sub_8226E3B8 and the ADN110-for-null pretty-print, each of which cost an iteration. Unaffected and solid: sub_8226EAB8 increments a count at +8 of its container, the trigger container embeds its list at +12, so the watched word at phase+272+20 is that inner list's count, and the guest was inside sub_8226EAB8 at the write. Next: instead of guessing among 16 callers, re-run the watchpoint and read the guest LR from the context -- the technique that named the writer will name its caller.
This commit is contained in:
@@ -442,3 +442,39 @@ from the context block** at the moment of the write. Reading the right offset ou
|
||||
of `$rsi` would name the guest instruction. That needs Xenia's context layout —
|
||||
which is in the xenia-rs sources on this box — and is a separate, tractable
|
||||
piece of work rather than another blind run.
|
||||
|
||||
## 🟡 `sub_8226E458` is a splice — but I have not shown it touches the trigger queue
|
||||
|
||||
Chasing which of `sub_8226EAB8`'s 16 callers grows the trigger count, the
|
||||
promising one is `sub_8226E458`:
|
||||
|
||||
```
|
||||
8226e504 lwz r11, 8(r30) ; source count
|
||||
8226e508 subi r11, r11, 1
|
||||
8226e50c stw r11, 8(r30) ; source -= 1
|
||||
8226e51c bl 0x8226EAB8 ; ... then insert into the destination (+1)
|
||||
```
|
||||
|
||||
Remove from one list, insert into another — a **splice**. And it has exactly one
|
||||
caller, `0x8226D780`, **inside `sub_8226D740`**, the per-frame engine→script
|
||||
drain. That is a tidy story: the engine moves records into the phase's queue each
|
||||
frame, and the count I watched rises as it does.
|
||||
|
||||
🔴 **The tidy story is not supported by the call site.** At `0x8226D780` the
|
||||
argument is `lwz r4, 324(r29)` — `[ScriptPhase+324]`, the **unit array**, not the
|
||||
trigger container. So whatever `sub_8226E458` splices between, I have **not**
|
||||
shown it is the trigger queue, and the "engine feeds triggers each frame"
|
||||
reading is mine rather than the disassembly's.
|
||||
|
||||
Recording it unresolved. The same over-reach — taking a function's shape as its
|
||||
purpose — produced the "push" mislabel on `sub_8226E3B8` and the
|
||||
`ADN110`-for-null pretty-print, both of which cost an iteration to undo.
|
||||
|
||||
**What is solid** and does not depend on this: `sub_8226EAB8` increments a count
|
||||
at `+8` of the container it is handed; the trigger container embeds its list at
|
||||
`+12`; and the watched word at `phase+272+20` is therefore that inner list's
|
||||
count. The guest was executing inside `sub_8226EAB8` at the moment of the write.
|
||||
|
||||
**Next:** rather than guessing among 16 callers, set the watchpoint again and
|
||||
read the **guest LR** out of the context (`%rsi`) at the hit — the same technique
|
||||
that named `sub_8226EAB8` will name its caller.
|
||||
|
||||
Reference in New Issue
Block a user