re: index F6 unit 9, which closes the sweeps' unmeasured period
ui-clock-freezes-at-settle.md left the sweep period ❔ because a validated estimator disagreed between two dwells (515 vs 452 frames). The cause is now measured: captured frame counts are not comparable across runs at all -- 1.947x between two captures of the same animation, with the baseline moving 1.953x alongside. As a ratio the period reproduces to 0.35%. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
This commit is contained in:
@@ -196,3 +196,4 @@ files, which is how the same ground got covered twice.
|
||||
| [`structures/title-a-press-fault.md`](structures/title-a-press-fault.md) | Why a single Ⓐ on the title faults the guest — the blocker on all menu-side dynamic RE | ✅ **SOLVED 2026-08-30, and it is the emulator, not the game.** Xenia returns `X_ERROR_SUCCESS` with a *zeroed* keystroke on every `XamInputGetKeystrokeEx` while a XAM dialog is up (`xam_input.cc:197`, upstream); the game's pump is an **unbounded** `while (GetKeystrokeEx()==SUCCESS) queue.push_back()`, so it queued **8 388 608** empty keystrokes, grew its vector to 64 MB, asked for 128 MB, got a failed allocation back **unchecked** and copied off the top of the guest thread stack. ✅ **The number is the argument**: the Canary counter reports **8 388 601** swallowed calls at the last report before the crash, the dump's `r29` says the vector held **8 388 608** — two independent instruments, 7 apart, inside the 600-call reporting granularity. No new boot: the failing run's 326 MB log was still on disk. 🔴 **RETRACTED — "`r9` is a wild pointer above 4 GB"**. Xenia prints `si_addr`, a *host* address, and the guest is mapped at `0x100000000`: `0x1701D0000 − 0x100000000 = 0x701D0000`, which **is** `r9` in the dump — an ordinary guest heap address on an uncommitted page. Subtract `0x100000000` from every `Access Violation … at 0x1________` before reading it. ✅ **Decoded code path**, image-checked with **0 mismatches** over 586 instructions: `sub_824574C0` the input-manager singleton at `0x828F3888`, `sub_82457038` the keystroke pump, `sub_82457780` its `vector<X_INPUT_KEYSTROKE>` insert-with-grow. ✅ **It explains the earlier successes**: whether a XAM dialog is up is *emulator* state, so "reproduced 4/4" and "Q4/Q5 pressed Ⓐ fine" were both always true. 🟡 **Which** dialog is still open — `XamShowDeviceSelectorUI` is ruled out (`storage_selection_dialog = false` takes the headless path), `XamShowSigninUI` / `XamShowMessageBoxUIEx` are not; the settling experiment is one log line per `is_xam_dialog_present_.store(true)` site, not another blind boot. 🟡 Three untried routes out: dismiss the dialog, `--headless`, or return `X_ERROR_EMPTY` from the swallow. ✅ `frame_clock.sh`'s 300 MB guard killed the run as designed — keep it |
|
||||
| [`structures/plate-pulse-phase-lock.md`](structures/plate-pulse-phase-lock.md) | Does gating on the plate pulse bias what a title capture can show? | ✅ **measured — it PHASE-LOCKS the shutter.** The plate's pulse is part of the animation, so `wait_plate_pulse.py` does not only wait for settling, it synchronises the shutter to the animation's phase: at the shutter instant the sweep strips sit **25–26 px apart across two runs in different locales and different sessions** — **1.6 %** of a ~1600 px traverse. 🔴 **Consequence: the RMSE 0.32 recorded as "between-session capture noise" is a lower bound produced by the instrument, not a property of the game**; the honest figure at an arbitrary phase is **11.9**, a factor of 37, and I had read 0.32 as evidence the JP title is still when it is evidence the gate works. ✅ **The era adjudication survives** — margin **16.72** clears even 11.9 — and survives *for the reason its own file gave*: correlated noise moves both candidates together and cancels in a margin, so prefer margins to absolute scores under a gated shutter. ✅ The within-run at-rest result also survives (five frames ~1.5 s apart are not gated individually). ⚠️ Reach: this shows the lock, not its mechanism — both runs boot the same ISO from the same state, so a deterministic boot could produce it without the gate; **two runs deliberately shuttered at gate + k frames would separate those** and were not run |
|
||||
| [`structures/plate-pulse-measured.md`](structures/plate-pulse-measured.md) | Does the `PRESS Ⓐ` plate stay up, pulse, or blink once? | ✅ **measured** — it **PULSES**, continuously and without decay, on a title held with **no input**: two windows in one boot, 58 s and 57 s, ~23 cycles each, periods **2.530 / 2.540 s** agreeing to 0.4 %. ⚠️ **It never goes off** — the plate-absent floor is **159** green pixels (the title art's own, from `live-title-build4-no-plate.png`) and the pulse bottoms at **714**, 4.5× that. So the port's "flash and nothing after", reasoned from `ptbtn00` expiring at t=244, is wrong; `ptbtn00f`'s 120-unit cycle is what runs. 🔴 **Two estimators, one misspecified**: mid-crossings replicate to 0.4 %, a single-sinusoid fit does not (2.553 vs 2.413) because the waveform is fast-rise/slow-decay — and its own r² of 0.468/0.228 is the tell. Both were controlled on synthetics at 2.24/2.55/3.10 s laid on the real timestamps and recovered all three exactly. 🟡 wall-clock is **13 % longer** than the corpus's earlier 2.24 s mean — same declared 120 units, different pacing (×1.27 vs ×1.12), so **author the units**. ⚠️ Reach: one boot; does not distinguish the boot title from an attract-loop title; the glyph count is a thresholded pixel count and **not** an alpha, so no duty cycle can be read off it |
|
||||
| [`f6-unit9-sweep-period-and-onset.md`](f6-unit9-sweep-period-and-onset.md) | How long one sweep pass is, and whether it starts with the plate | ✅ **measured as ratios, two independent runs.** The sweep's cycle boundary is unambiguous in the draw stream — it enters at NDC `x=-1.540` and wraps from `x=+1.840` back to it — so first-appearance→wrap is a **whole period**. **Period / baseline = 13.905 vs 13.953 (0.35 % apart)**; **the sweep starts 0.798 vs 0.791 baselines BEFORE the plate appears (0.9 %)**, where the baseline is the long in-capture interval from the `x=-0.740` element appearing to the plate appearing. 🔴 **Why every earlier frame-count disagreed: captured frames are NOT comparable across runs.** The same animation took **1168** frames in one capture and **600** in the other, **1.947×** apart — and the baseline moved by **1.953×**, so the whole run is scaled and the runs simply presented at different rates. That is the mechanism behind [`ui-clock-freezes-at-settle.md`](structures/ui-clock-freezes-at-settle.md)'s unmeasured sweep period (515 vs 452 frames across two dwells), and it retires any rate quoted in frames from one capture and used in another. ✅ **Answers F6**: the sweep does **not** start at title `t=0` where the port starts it (~200 units early), nor exactly with the plate — it **leads the plate by ≈40 title units**, well under a second, which is why a human reports the two as simultaneous. 🟡 **Conflict surfaced, not smoothed**: in the *same* capture the title clock reads **1.0 units/frame** from `ptcopyright`'s 22-unit ramp but **0.571** from the plate's declared 12-unit ramp — 1.75× apart. Either a declared ramp is misread or **the two are not on one clock**, which is exactly the port's `clock: "shared"` premise; so the ratios are ✅ and every title-unit conversion here is 🟡 pending F4. ⚠️ Still **one wrap per capture** — the title exits first; `f6b` ran 504 frames past its wrap and the next was ~100 short. ⚠️ The moving quad is identified by texture-atlas page and position, not by name |
|
||||
|
||||
Reference in New Issue
Block a user