diff --git a/docs/re/f5-code-route-no-literal-target.md b/docs/re/f5-code-route-no-literal-target.md new file mode 100644 index 00000000..69d47d7d --- /dev/null +++ b/docs/re/f5-code-route-no-literal-target.md @@ -0,0 +1,63 @@ +# F5, the code route — ❔ not settled, with one bounded negative + +**Question:** does the code handling Ⓐ on the title assign a target time, or +raise a rate multiplier? + +**What the human looks at:** nothing directly — this is the cross-check the brief +asks for, that the capture's answer is right for the right reason. + +**What this does NOT cover:** F6, and the capture route, which is settled +([`f5-verified-with-full-quad-reader.md`](f5-verified-with-full-quad-reader.md)). + +**Instrument:** ⟨image⟩ via `tools/ppc-dis`. + +## ❔ I did not find the instruction + +The brief asks for two routes. The capture route is done; **this one is not**, and +I am recording that rather than dressing a partial result as an answer. + +Where I looked: the five `GamePart_Title` phase handlers +([`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md)) — +`sub_821C5690`, the inline phase 1, `sub_821C5818`, `sub_821C5EC0`, +`sub_821C6458`. Phases 2 and 3 dispatch through vtables (`mtspr`/`bctr`) on almost +every branch, so following the clock write statically means resolving indirect +calls, which this container's tooling does not do cheaply. + +## ✅ What the scan does establish + +**No literal time constant in the range exists.** Over `0x821C4000–0x821CD000`, +for every value 160…250: + +``` +li rN, for v in 160..250 : none +``` + +Control: the same scan finds **684** `li` instructions in that range, commonest +values 0, 1, small integers and address halves — so the scan sees `li` fine, and +the absence is about the values, not the method. + +**So the snap target is computed or read from the loaded bundle, not written as a +literal in the title's code.** + +## Refutation attempt — against my own capture result, and it survived + +[`f5-snap-target-undecodable-with-reach.md`](f5-snap-target-undecodable-with-reach.md) +says the target is somewhere in `[160,238)` and unpinnable from any capture. A +literal in the code would have **named** it and refuted the "unpinnable" framing +outright. There is none. + +That leaves the capture claim standing **and gives it a second reason**: a +data-derived target has no constant to find, which is consistent with it landing +inside the one window where nothing observable changes. + +⚠️ Reach of this negative: one address range, one instruction form, one tool. A +float in `.rdata`, a value computed at runtime, or a handler outside +`0x821C4000–0x821CD000` would all escape it. + +## What would settle it + +A **write-watch on the UI group's clock field** in Canary — `/canary` is +read-write and the draw logger already proves the pattern. That names every +writer, including the snap, and would also close the standing "which function +advances the clock" question. It is a real instrument, not a bigger search, and +it is the next thing to build here.