From c5d685ba1564ad7fe0a0371e1cd1bb4dc7861c56 Mon Sep 17 00:00:00 2001 From: sylph-decoder Date: Sun, 30 Aug 2026 19:52:15 +0000 Subject: [PATCH] re: the sweep IS drawn on the JP title -- and my gate was phase-locking the shutter The occlusion hypothesis is refuted: build 7 draws the same three ROT strips at higher alpha than English, so there was never an absence to explain. The 0.32-vs-11.9 tension that motivated it was an artefact of my own instrument. Both JP captures were shuttered on the plate pulse, and the plate's pulse is part of the animation -- so the gate synchronises the shutter to the animation's phase. Measured at the shutter instant, the sweep sits 25-26 px apart across two runs in different locales and different sessions: 1.6 % of a ~1600 px traverse. So the 0.32 I recorded as between-session capture noise measures my trigger's repeatability, and I read it as evidence the title is still when it is evidence the gate works. The era adjudication is unaffected -- margin 16.72 clears even the un-locked 11.9 -- and unaffected for the reason that file already gave: correlated noise cancels in a margin. Refutation attempt on sylpheed-port's positional-mechanism rejection: FAILED, the claim stands. Its residual sits inside lit logos, and the logo ROI is byte-identical across five differently-phased frames in two sessions. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v --- docs/port/HANDOFF.md | 21 ++++++ docs/re/INDEX.md | 1 + docs/re/METHOD.md | 24 +++++++ docs/re/REFUTED.md | 40 +++++++++++ docs/re/data/jp-title-at-rest.txt | 26 ++++++++ docs/re/data/title-sweep-drawn-at-rest.txt | 13 ++++ docs/re/data/title-sweep-jp-draw-capture.txt | 45 +++++++++++++ docs/re/structures/plate-pulse-phase-lock.md | 70 ++++++++++++++++++++ tools/re-capture/jp_draw_capture.sh | 48 ++++++++++++++ 9 files changed, 288 insertions(+) create mode 100644 docs/re/data/title-sweep-jp-draw-capture.txt create mode 100644 docs/re/structures/plate-pulse-phase-lock.md create mode 100755 tools/re-capture/jp_draw_capture.sh diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 701c27ba..26dec60d 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -103,6 +103,27 @@ messages. Detail and data: [`data/title-sweep-drawn-at-rest.txt`](../re/data/title-sweep-drawn-at-rest.txt), [`data/ptloop-leaf-extent.txt`](../re/data/ptloop-leaf-extent.txt). +๐Ÿ”ด **UPDATE 2026-08-30 โ€” one number you may have taken from me is not a noise +floor.** If anything of yours cites **RMSE 0.32** as *between-session capture +noise* in the title's era box, drop it. Both captures behind it were shuttered on +the plate pulse, and the plate's pulse is part of the animation, so the gate +**phase-locks the shutter**: measured, the sweep sits 25โ€“26 px apart across two +runs in different locales and different sessions โ€” 1.6 % of a ~1600 px traverse. +0.32 measures my trigger's repeatability. The honest figure at an arbitrary phase +is **11.9**. โœ… **Your era adjudication is unaffected** โ€” its margin is 16.72, +which clears even 11.9 โ€” and it is unaffected *for the reason that file already +gave*: correlated noise moves both candidates together and cancels in a margin. +Prefer margins to absolute scores wherever the shutter is gated. +[`structures/plate-pulse-phase-lock.md`](../re/structures/plate-pulse-phase-lock.md) + +โœ… **And the leaves ARE drawn on the JP title** โ€” same three ROT strips, same +dimensions, at *higher* alpha than English (180/188/194 vs 160/168/166). The +occlusion idea I floated is dead. +[`data/title-sweep-jp-draw-capture.txt`](../re/data/title-sweep-jp-draw-capture.txt) +โš ๏ธ Do not take the strips' ยฑ7.1 px/frame from that log as a rate โ€” every fit +fails the linearity gate (rms ~30 px, residual sign-changes 2/81); it is the +chord of an arc. + โœ… **The game draws `pteff03` / `pteff03a` on a settled title, and they free-run.** A draw capture of the settled title, plate-pulse gated, shows two quads taller than the screen in every one of 132 frames, sweeping in opposite directions. So a diff --git a/docs/re/INDEX.md b/docs/re/INDEX.md index 207cd2ef..bebc3f8e 100644 --- a/docs/re/INDEX.md +++ b/docs/re/INDEX.md @@ -182,4 +182,5 @@ files, which is how the same ground got covered twice. | [`structures/ui-forced-backdrop.md`](structures/ui-forced-backdrop.md) *(colour census + self-refutation)* | What colour a keyless element is, and which forced verdicts the argument actually supports | โœ… **decoded, disc-wide**: every full-screen `*eff00*` **primitive** is **pure black** at its various alphas (`ff000000`, `7f000000`, `40000000`, `b2000000`, `cc000000`, `d4000000`, `00000000`) โ€” exactly an alpha-over dim or fade, and an *additive* black quad would be a no-op nobody would author. The **only** non-black primitive on the disc is `pbafc.prm`, RGB `00e8e0` cyan at alphas to `ff`, and it is **844ร—600, not full-screen**, so outside the backdrop rule's geometry guard โ€” โ” it is now the sole additive candidate. ๐Ÿ”ด **Self-refutation: of the 80 forced-first instances only 42 are `.prm`; 38 are `.tbm` carrying fade `ffffffff`.** A *solid* white quad painted first would make the screen white and no screen is white, so a `.tbm` is a white **modulation on a texture** โ€” and element alpha does not establish its coverage. That is the `.t32` error one extension further out: I had fixed the symptom (`el.sprite.is_some()`) not the cause, **an element's alpha is not its texture's opacity, and only an untextured primitive makes the two the same fact**. So 42 verdicts stay **decoded**, 38 drop to ๐ŸŸก (still almost certainly right โ€” all named `*base*`, full-screen, and `pfbase.tbm`'s first position is *measured* โ€” but on a name-and-role argument this page elsewhere calls the weaker kind). โš ๏ธ Code deliberately unchanged: restricting to `.prm` would send eleven screens' backgrounds back to last, the blank-screen bug the rule fixed. Split pinned by a test | | [`structures/ui-prm-blend-mode.md`](structures/ui-prm-blend-mode.md) | Whether a primitive blends additively or alpha-over | โ” **undecodable, with reach** โ€” but the consequence is closed. Looked in **the bundle** (no field: the declaration words are constant and a primitive has no RATC child at all), **the colour census** (every full-screen `*eff00*` primitive is **pure black**; the only non-black primitive on the disc is `pbafc.prm`, cyan `00e8e0`), **the occlusion constraint** (inapplicable โ€” `pbafc.prm` strobes 255/124 every 2 units, travels, and is scaled **2 %ร—3 %**, so it draws ~**17ร—18 px**, not its declared 844ร—600), and **the oracle** (`GP_READY_ROOM` is a recorded no-go and gameplay needs the โ’ถ that faults the guest). โœ… **Why it stopped mattering:** for a *black* quad the hypotheses differ only in whether it hides what is beneath โ€” drawn **first** it is correct under **both**, drawn **last** only under additive. So `forced_backdrop`'s verdict is robust to the open question, and the port's original "layerless sorts last" was wrong under alpha-over and merely pointless under additive. โš ๏ธ This is not evidence *for* alpha-over. ๐Ÿ”ด The investigation found `forced_backdrop` judged coverage from the **pivot alone**, ignoring scale; checked first, **all 80 forced instances are at 100 %**, so no verdict moved and the added guard is defensive | | [`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` 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 | diff --git a/docs/re/METHOD.md b/docs/re/METHOD.md index 36b8cc21..33d53aca 100644 --- a/docs/re/METHOD.md +++ b/docs/re/METHOD.md @@ -2208,3 +2208,27 @@ well-formed output for the wrong object.** This project has now been bitten twic from opposite directions, and both times "everything still validates". When a counter-example arrives that overturns a gradient, check *what it is a measurement of* before you believe it โ€” the same scrutiny the gradient got. + +## A gate that detects a settled state can phase-lock your shutter + +`wait_plate_pulse.py` was adopted to answer *"has the screen settled?"*, and it +answers it. But the plate's pulse **is part of the animation**, so gating on it +also synchronises the shutter to the animation's phase. Two runs gated this way +are **not** two samples of a free-running clock โ€” measured, the sweep sits 25โ€“26 +px apart across two sessions in different locales, 1.6 % of its traverse. + +The damage is that between-run agreement then reads as *the game is stable* when +it means *my trigger is repeatable*. I recorded a 0.32 as "between-session +capture noise" and drew the first conclusion; the honest figure at an arbitrary +phase was 11.9, a factor of 37. + +โš ๏ธ **The general form: a trigger conditioned on a moving quantity makes every +capture correlated, and correlated captures understate variance.** Ask of any +"reproducible across runs" result *what fired the shutter* โ€” if the trigger +watches something that moves with the thing you are measuring, reproducibility is +a property of the instrument. The escape is a shutter deliberately offset from +the gate, and it is cheap: fire at gate + k frames for a few k. + +Note which results survive this and why: a **margin between two candidates scored +on one capture** was unaffected, because correlated noise moves both scores +together and cancels. Prefer margins to absolute scores when the shutter is gated. diff --git a/docs/re/REFUTED.md b/docs/re/REFUTED.md index 2d86e678..3a36c898 100644 --- a/docs/re/REFUTED.md +++ b/docs/re/REFUTED.md @@ -715,3 +715,43 @@ reachable by the person about to repeat it. twice.** The same origin gives 0 and 1 to different destinations; every repeated *pair* is identical across five replicates. The pair determines; the origin only constrains. [`data/fade-four-transitions.txt`](data/fade-four-transitions.txt) + +### The JP title might not draw the sweep leaves at rest โ€” โŒ REFUTED (2026-08-30, mine) + +I hypothesised that build 7's denser logo stack (katakana + crystalline burst) +**occludes** the two sweep leaves, to explain why two JP title captures differ by +RMSE 0.32 inside the adjudication box while two EN captures a plateau-phase apart +differ by 11.9. A draw capture in `ja` (control: the same extraction on the EN +title log) shows the **same three tall ROT strips, same dimensions, at HIGHER +alpha than English** โ€” 180/188/194 vs 160/168/166. There is no absence to +explain. [data](data/title-sweep-jp-draw-capture.txt) + +The 0.32 had a different cause: **my own gate**. See below. + +### "Two sessions sample a free-running clock" โ€” โŒ REFUTED (2026-08-30, mine) + +`jp-title-at-rest.txt` justified a second capture as probing the between-run axis +"where a free-running clock lands somewhere else on a fresh boot", and reported +its in-box **0.32 as capture noise**. Measured 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. The plate pulse *is* part of the +animation, so gating on it phase-locks the shutter. **0.32 is a lower bound +produced by the instrument, not a property of the game**; the honest figure at an +arbitrary phase is 11.9. The era adjudication is unaffected โ€” its margin, 16.72, +clears even 11.9. [details](structures/plate-pulse-phase-lock.md) + +### Refutation attempt on `sylpheed-port` โ€” โœ… THE CLAIM SURVIVED (2026-08-30) + +**Target:** the port's rejection of a positional mechanism, resting on 98 % of +off-edge area matching exactly with a residual of ยฑ1โ€“2 levels *inside lit logos*. + +**My attempt:** if the sweep leaves' ink crosses the logos, that residual could +be sweep ink our renderer omits โ€” and phase-locking would have made it look +stable across sessions rather than exposing it. + +**Result: refuted, the claim stands.** `jp-title-at-rest.txt` has five frames +~1.5 s apart *within* a run โ€” not gated individually, so genuinely different +sweep phases โ€” and the 350ร—396 logo ROI is **byte-identical across all of them +(0 / 138 600 px differing, max |d| 0), reproduced in two independent sessions**, +while 5โ€“8 % of the whole frame moves as a contrast control. The sweep ink does +not land on the logos. The ยฑ1โ€“2 residual is not sweep. diff --git a/docs/re/data/jp-title-at-rest.txt b/docs/re/data/jp-title-at-rest.txt index ab8f7a68..dabe49d4 100644 --- a/docs/re/data/jp-title-at-rest.txt +++ b/docs/re/data/jp-title-at-rest.txt @@ -74,3 +74,29 @@ # scores moved 0.001-0.002 between sessions and the margin moved 0.001, against # an in-box capture noise of 0.32. A margin between two renders scored on one # capture is far more robust than either score is. + +################################################################################ +# ๐Ÿ”ด CORRECTION -- 2026-08-30, same day. The BETWEEN-SESSIONS block above rests +# on a premise I have now measured and it is FALSE. +# +# It reasons that a second session probes a new axis, "where a free-running +# clock lands somewhere else on a fresh boot". It does not. Both captures were +# shuttered on the plate pulse, and the plate's pulse is PART of the title +# animation, so the gate synchronises the shutter to the animation's phase. +# +# Measured (structures/plate-pulse-phase-lock.md): at the shutter instant, the +# sweep strips sit 25-26 px apart between two runs in DIFFERENT locales and +# different sessions -- 1.6 % of a ~1600 px traverse. +# +# CONSEQUENCES: +# * "in-box capture noise of 0.32" is a PHASE-LOCKED LOWER BOUND, not capture +# noise. At an arbitrary phase the figure is 11.9 (two EN captures a +# plateau-phase apart). Do not reuse 0.32 as a noise floor. +# * I read 0.32 as showing the JP title is still. It shows the GATE works. +# +# WHAT SURVIVES UNCHANGED: +# * The margin 16.72 exceeds even the un-locked 11.9, so the era adjudication +# holds either way -- and holds FOR THE REASON THIS FILE GIVES: noise moves +# both candidates together and nearly cancels in a margin. +# * The five-frames-per-run at-rest result, which is not gated per frame and +# therefore does sample different phases. diff --git a/docs/re/data/title-sweep-drawn-at-rest.txt b/docs/re/data/title-sweep-drawn-at-rest.txt index 93625a29..2c1fb47f 100644 --- a/docs/re/data/title-sweep-drawn-at-rest.txt +++ b/docs/re/data/title-sweep-drawn-at-rest.txt @@ -196,3 +196,16 @@ # slightly non-uniform one (-4.0667 then -4.0625), and it PASSES. So the curvature # is in the strip whose source data is exactly straight: it is not in the disc, and # it is either in the measurement or in how the game advances the record. + +################################################################################ +# โœ… SETTLED 2026-08-30 -- and the hypothesis in this file is REFUTED. +# See data/title-sweep-jp-draw-capture.txt and structures/plate-pulse-phase-lock.md. +# +# The leaves ARE drawn on the JP title -- same three ROT strips, same +# dimensions, at HIGHER alpha than English. There is no occlusion and no +# absence. +# +# The 0.32-vs-11.9 tension that motivated the hypothesis was not a fact about +# the game at all: both JP captures were shuttered on the plate pulse, which +# phase-locks the shutter to the animation (25-26 px apart on a ~1600 px +# traverse). 11.9 is the honest number; 0.32 is the gate. diff --git a/docs/re/data/title-sweep-jp-draw-capture.txt b/docs/re/data/title-sweep-jp-draw-capture.txt new file mode 100644 index 00000000..68827be7 --- /dev/null +++ b/docs/re/data/title-sweep-jp-draw-capture.txt @@ -0,0 +1,45 @@ +# Are the sweep leaves DRAWN on the Japanese title? -- 2026-08-30 +# +# THE TENSION THIS WAS RUN TO SETTLE (from title-sweep-drawn-at-rest.txt): +# two EN title captures a plateau-phase apart differ by RMSE 11.9 inside the +# adjudication box, while two JP title captures from different SESSIONS differ +# by 0.32 there. I hypothesised the game might not draw the leaves at rest on +# the JP title -- build 7's denser logo stack (katakana + crystalline burst) +# occluding them. +# +# INSTRUMENT: tools/re-capture/jp_draw_capture.sh -- sets console language ja +# (trap-restores en on ANY exit), ensure_single_emulator, boots with +# --log_ui_draws --ui_draw_capture_frames=150, arms F10 on the plate pulse. +# Locale restore VERIFIED: language back at 1 after the run. +# +# CONTROL: the same extraction run against the ENGLISH title draw log +# (/sylph-home/re/titledraw2), where the leaves are known to be drawn. +# +# TALL ROT STRIPS (h > w, h > 720) -- alpha is the vertex colour's high byte: +# +# EN title: 1299x1303 n=112 alpha 139..181 mean 160.0 rot=ROT +# 883x1134 n= 77 alpha 142..193 mean 168.1 rot=ROT +# 890x1134 n= 55 alpha 142..193 mean 165.9 rot=ROT +# +# JP title: 1299x1303 n= 82 alpha 141..212 mean 179.9 rot=ROT +# 883x1134 n= 76 alpha 144..231 mean 187.9 rot=ROT +# 890x1134 n= 33 alpha 149..229 mean 193.5 rot=ROT +# +# โœ… THE LEAVES ARE DRAWN ON THE JP TITLE. Same three strips, same dimensions, +# and at HIGHER alpha than English (mean 180/188/194 vs 160/168/166). The +# occlusion hypothesis is dead: there is no absence to explain. +# +# โš ๏ธ WHAT THIS LOG CANNOT SAY. These are ROT quads: the logged w x h is the +# AXIS-ALIGNED BOUNDING BOX of a rotated strip, and the ink is a narrow diagonal +# band inside it. The x spans (-634..992) cross the adjudication box's x range +# (389..776), but a bounding box crossing a box does NOT mean ink does. I made +# that inference first and it does not hold. +# +# โŒ AND THE SLOPES ARE NOT RATES. Least-squares over the captured frames gives +# 1299x1303 slope -7.193 px/frame rms 30.98 sign-changes 2/81 +# 883x1134 slope +7.141 px/frame rms 29.49 sign-changes 4/75 +# 890x1134 slope +6.962 px/frame rms 29.03 sign-changes 2/32 +# Every fit FAILS the linearity gate (residual sign-changes far below ~30 %, +# rms ~30 px against a ~1600 px traverse): the motion is curved over the capture +# window, so +-7.1 is the chord of an arc, not a velocity. Do not quote it. +# This is the SAME failure the "6-7 px/frame" eyeball made -- see METHOD.md. diff --git a/docs/re/structures/plate-pulse-phase-lock.md b/docs/re/structures/plate-pulse-phase-lock.md new file mode 100644 index 00000000..1bdd6b6b --- /dev/null +++ b/docs/re/structures/plate-pulse-phase-lock.md @@ -0,0 +1,70 @@ +# The plate-pulse gate phase-locks the shutter to the title animation + +**measured** โ€” 2026-08-30 ยท [data](../data/title-sweep-jp-draw-capture.txt) ยท +instrument `tools/re-capture/jp_draw_capture.sh`, control the English title +draw log + +## The claim + +`wait_plate_pulse.py` waits for the title plate's glyph count to sit in +[500, 2500] for 12 samples, and every title capture in this corpus shutters on +it. It was adopted to answer *"has the screen settled?"* โ€” and it does. + +But the plate's pulse **is** part of the title's animation, so gating on it does +not only wait for settling: it **synchronises the shutter to the animation's +phase**. Two runs gated this way are not two samples of a free-running clock. + +## The measurement + +The x of each tall ROT strip at the **first captured frame** โ€” the shutter +instant โ€” in two independent runs, different sessions, *different locales*: + +| strip | EN run | JP run | apart | +|---|---|---|---| +| 883ร—1134 | x = โˆ’109 | x = โˆ’83 | **26 px** | +| 1299ร—1303 | x = 486 | x = 461 | **25 px** | + +Against a traverse of ~1600 px, that is **1.6 %**. Two boots, two locales, two +sessions, and the sweep is in essentially the same place both times. + +## What it invalidates โ€” my own reading + +[`jp-title-at-rest.txt`](../data/jp-title-at-rest.txt) reasons that its second +capture probes a new axis, *"BETWEEN runs, where a free-running clock lands +somewhere else on a fresh boot"*, and reports **RMSE 0.32** in the era box as +the between-session **capture noise**. + +๐Ÿ”ด **The clock does not land somewhere else.** The gate puts it back in the same +place. So: + +* **0.32 is a phase-locked LOWER BOUND on capture noise, not capture noise.** + At an arbitrary phase the in-box figure is the **11.9** measured between two + EN captures a plateau-phase apart. Anything reusing 0.32 as "the noise floor" + is quoting the gate, not the game. +* I read the 0.32 as evidence the JP title is **still**. It is not. It is + evidence the **gate works**. I had it backwards. +* The whole-frame 116 492 px that *do* differ between those two sessions are + consistent with exactly this: ~25 px of residual jitter displacing two large + bright diagonal strips moves a lot of pixels globally while barely clipping + the era box. + +## What it does NOT invalidate + +โœ… **The era adjudication stands.** Its margin is **16.72** (41.69 fixed vs +58.41 stale), which exceeds even the un-locked **11.9** figure โ€” so it survives +whichever noise number is correct. And the file's own key insight is untouched +and is the reason it survives: capture noise moves both candidates together and +**nearly cancels in a margin** (absolute scores moved 0.001โ€“0.002 between +sessions; the margin moved 0.001). + +โœ… **The within-run at-rest result stands** โ€” five frames ~1.5 s apart are *not* +gated individually, so they sample different phases, and the logo ROI is +byte-identical across them in **both** sessions while 5โ€“8 % of the frame moves. + +## Reach of the negative + +This says the gate locks phase; it does not say by what mechanism. Both runs +boot the same ISO from the same state, so the pulse may simply occur at a fixed +offset from a deterministic boot rather than the gate doing the locking. **Two +runs deliberately shuttered at different phases would separate those** and were +not run. diff --git a/tools/re-capture/jp_draw_capture.sh b/tools/re-capture/jp_draw_capture.sh new file mode 100755 index 00000000..6c496608 --- /dev/null +++ b/tools/re-capture/jp_draw_capture.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Does the game DRAW the sweep leaves on the JAPANESE title, and do they cross +# the adjudication box? +# +# ui-resting-pose.md carries an unresolved tension. On the EN title the leaves are +# drawn and free-run: two strips taller than the screen, sweeping in opposite +# directions at ~4.3 px/frame. Two renders one plateau-phase apart differ by RMSE +# 11.9 INSIDE the box the ptlogo_eff3 adjudication uses. Yet two JP captures from +# different sessions differ by only 0.32 there. Two candidates, neither tested: +# the two JP shutters fell at similar phases (~1 % coincidence on a 600-unit +# cycle), or build 7's denser logo stack -- the katakana plus the crystalline +# burst the English title lacks -- OCCLUDES the sweep inside that box. +# +# A draw capture of the JP title distinguishes them: if the strips are present and +# crossing the box, the 0.32 was luck; if absent or clipped there, it is occlusion. +# +# Locale is set and ALWAYS restored, as in jp_title_session.sh. +set -u +export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 +SD="$(cd "$(dirname "$0")" && pwd)" +OUT="${1:-/sylph-home/re/jpdraw}"; mkdir -p "$OUT"; rm -f "$OUT"/xenia_re_ui_draws_*.log +restore() { echo "-- restoring locale --" + python3 "$SD/set_console_language.py" en || echo "RESTORE FAILED โ€” check by hand" + python3 "$SD/set_console_language.py" --show; } +trap restore EXIT INT TERM +. "$SD/ensure_single_emulator.sh"; ensure_single_emulator || exit 3 +python3 "$SD/set_console_language.py" ja +python3 "$SD/set_console_language.py" --show +( cd "$OUT" && nohup run-canary --mem_watch=false --log_ui_draws=true \ + --ui_draw_capture_frames=150 --ui_draw_capture_max=400000 \ + --logged_profile_slot_0_xuid=B13EBABEBABEBABE \ + >"$OUT/canary.stdout" 2>"$OUT/canary.stderr" & ) +sleep 10 +ps -C xenia_canary >/dev/null 2>&1 || { echo "EMULATOR DID NOT START:"; tail -3 "$OUT/canary.stderr"; exit 4; } +echo "โ”€โ”€ EFFECTIVE CONFIG โ”€โ”€" +echo " locale = ja (restored on exit)" +echo " emulator = $(ps -C xenia_canary --no-headers | wc -l) instance(s)" +echo " capture = log_ui_draws, 150 frames, armed by F10 at the plate pulse" +until xdotool search --name "Xenia-canary" >/dev/null 2>&1; do sleep 1; done +win="$(xdotool search --name "Xenia-canary" | tail -1)" +python3 "$SD/wait_plate_pulse.py" 900 || exit 1 +xdotool windowactivate --sync "$win"; sleep 1 +xdotool key F10; sleep 0.6 +xdotool mousemove 900 400 click 1 +sleep 12 +grep -i "UI-CAP" "$OUT/canary.stdout" | tail -2 +ls -l "$OUT"/xenia_re_ui_draws_*.log 2>/dev/null || echo "NO CAPTURE LOG" +echo "JP DRAW CAPTURE DONE"