diff --git a/authored/flow.json b/authored/flow.json index 48ffab9d..c07e6147 100644 --- a/authored/flow.json +++ b/authored/flow.json @@ -44,13 +44,32 @@ ], "dwell": { "_": [ - "DELIBERATELY EMPTY. Each screen's dwell is its own keyframe group -- the", - "publisher wordmark reaches its hold at t=235 (3.92 s) and the developer", - "logos at t=190 (3.17 s), both read from the disc. Holding beyond that would", - "be a number nobody has measured, so the sequencer holds for zero extra time", - "and the pacing is the disc's own.", + "NOT SET -- and the reason is no longer the one this key used to give.", "", - "When a capture times the real boot, the extra hold per screen goes here." + "🔴 It used to say \"a screen's dwell is its OWN keyframe group\". That is", + "REFUTED, measured in the draw stream by the Decoder on 2026-08-29", + "(docs/re/structures/ui-clock-freezes-at-settle.md): GP_TITLE build 4 declares", + "t = 0..269, about 120 presented frames at that capture's pacing, and the real", + "dwell lasted ~1100 -- roughly NINE TIMES its own timeline. The top-level clock", + "advances through the build-in, STOPS inside the settle window, and holds. The", + "exit ramp is not on a timer; it plays when something makes the screen leave.", + "", + "So the group is not the dwell, and a port that leaves when the group ends is", + "not reproducing the disc's pacing -- it is leaving at the moment the game", + "starts waiting.", + "", + "The DECISION is unchanged and still right: hold zero extra rather than invent", + "a number. What changes is what may be claimed for it. The boot is KNOWN TOO", + "FAST on every screen it plays out, by an amount nobody has measured. It is not", + "'the disc's own pacing'; that phrasing said the port was faithful here, and it", + "is not.", + "", + "⚠️ Only build 4 has been measured, and build 4 is the one screen where the port", + "is unaffected -- it is the boot's end state and holds indefinitely anyway. The", + "two screens this actually governs, publisher_logo and developer_logos, are", + "UNMEASURED. Nothing here may be read as a number for them.", + "", + "If a capture ever times the real boot, this is where that number goes." ] }, "navigation": { diff --git a/authored/timing.json b/authored/timing.json index a8bd6eca..70609246 100644 --- a/authored/timing.json +++ b/authored/timing.json @@ -26,11 +26,30 @@ ], "dwell_seconds": null, "dwell_why": [ - "NOT SET, and not needed. A screen's dwell is its OWN keyframe group: the", - "publisher wordmark reaches its hold at t=235 (3.92 s) and the developer logos", - "at t=190 (3.17 s), both read from the disc. Adding a hold on top of that would", - "be inventing a number nobody measured, so the sequencer holds for zero extra", - "time and the pacing you see is the disc's own.", + "NOT SET -- and the reason is no longer the one this key used to give.", + "", + "🔴 It used to say \"a screen's dwell is its OWN keyframe group\". That is", + "REFUTED, measured in the draw stream by the Decoder on 2026-08-29", + "(docs/re/structures/ui-clock-freezes-at-settle.md): GP_TITLE build 4 declares", + "t = 0..269, about 120 presented frames at that capture's pacing, and the real", + "dwell lasted ~1100 -- roughly NINE TIMES its own timeline. The top-level clock", + "advances through the build-in, STOPS inside the settle window, and holds. The", + "exit ramp is not on a timer; it plays when something makes the screen leave.", + "", + "So the group is not the dwell, and a port that leaves when the group ends is", + "not reproducing the disc's pacing -- it is leaving at the moment the game", + "starts waiting.", + "", + "The DECISION is unchanged and still right: hold zero extra rather than invent", + "a number. What changes is what may be claimed for it. The boot is KNOWN TOO", + "FAST on every screen it plays out, by an amount nobody has measured. It is not", + "'the disc's own pacing'; that phrasing said the port was faithful here, and it", + "is not.", + "", + "⚠️ Only build 4 has been measured, and build 4 is the one screen where the port", + "is unaffected -- it is the boot's end state and holds indefinitely anyway. The", + "two screens this actually governs, publisher_logo and developer_logos, are", + "UNMEASURED. Nothing here may be read as a number for them.", "", "If a capture ever times the real boot, this is where that number goes." ], diff --git a/docs/port/BLOCKED.md b/docs/port/BLOCKED.md index 1c8e4762..e9a33379 100644 --- a/docs/port/BLOCKED.md +++ b/docs/port/BLOCKED.md @@ -428,3 +428,34 @@ last keyframe, and `+0x08` and the elements' maximum are interchangeable disc-wi ⚠️ The hold is load-bearing: dropping it changes **72 of 130** verdicts (55 %), and `palogo_eff0` — one keyframe, opaque for one instant — is called *free* without it, against a measured order. See `DECISIONS.md`. + +--- + +## The two splash dwells, now known-wrong rather than merely unmeasured + +*Derived from HANDOFF `9ca1eb5`. Raised 2026-08-29 by the Decoder's clock-freeze +measurement on build 4.* + +The port advances from `publisher_logo` and `developer_logos` **the instant each +group settles** — t=235 (3.92 s) and t=190 (3.17 s). That was filed as "the +disc's own pacing". It is not: on the one screen anybody has measured, the game +held for roughly **nine times** the declared timeline, because the top-level +clock stops at the settle window and waits for something to make the screen +leave. + +⚠️ This does **not** license scaling the splashes by nine. Build 4 is the title, +and there is no reason a title's wait and a logo splash's wait are the same +quantity — the title's is plausibly "until the attract timer fires", which no +splash has. **A ratio measured on one screen is not a unit of pacing.** + +What would settle it: **a capture timing the real boot** — wall-clock from the +first frame of the publisher wordmark to the first frame of the developer logos, +and from there to the intro. Two timestamps answer it completely, and it needs no +frame analysis. The numbers go in `authored/flow.json` `dwell`, which has been +sitting empty and correctly shaped for this since P3. + +🔴 Bounded by the Decoder's own blocker: a single Ⓐ press on the title faults the +guest in their container, so **menu-side dynamic RE is unavailable there**. The +boot timing above needs no button press and should survive that — three runs in +the same session that pressed nothing all completed — but it is their call +whether it is safe to attempt. diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index abe35f0e..e887f3d4 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -5108,3 +5108,62 @@ Re-run after the reorder, since the rule changed the paint order of the first tw screens in the boot path: `publisher_logo` → `developer_logos` → `ADV` (skipped at 8.12 s) → `title` + `press_start` overlay, plate at full alpha at t=236, complete at 10.83 s holding on the title. No script errors. + +## The clock freezes at settle — the port's settle window, seen from the other side + +The Decoder measured `GP_TITLE` build 4 in the draw stream and found the +top-level clock **advances through the build-in, stops inside the settle window, +and holds**. The exit ramp is not on a timer; it plays when something makes the +screen leave. + +**Their interval is `[160, 236]`. The exporter computes `title`'s settle window as +`[160, 236, 198]`.** Those are the same two numbers, and they were not obtained +the same way: mine is the longest keyframe-free interval over top-level elements, +read out of the file with no game running; theirs is where a captured clock stops +advancing. A heuristic I adopted because it collapsed three pixel residuals at +once turns out to name the exact interval the game holds in. That is the first +evidence for the settle instant that does not come from the port's own renderer. + +The file agrees from a third direction: `ptcopyright` sits at alpha 255 from +t=160 to t=238 — it reaches full opacity precisely as the window opens. + +### Refutation attempt — their declared spans, checked against the file + +Their draw-stream argument cites what the file *declares*, which I can check +without a capture: + +| their claim | the file | | +|---|---|---| +| `ptlogo1` declares an exit at **t=264** | last keyframe t=264, alpha 0 | ✅ exact | +| `ptcopyright` alpha ≥ 1 for **106 units**, t=138…244 | keyframes at t=138 and t=244, alpha 0 at both | ✅ endpoints exact | + +Both survive. One quibble, and it is only that: the instants with alpha ≥ 1 number +**105**, t=139…243, not 106 — the endpoints they bracket with are themselves +alpha 0, so 106 is the keyframe span rather than the visible one. It changes +nothing in their argument, whose force comes from 1 050 frames against either +number. + +### What this costs the port, and it is not nothing + +`authored/timing.json` and `authored/flow.json` both said *"a screen's dwell is +its OWN keyframe group"* and *"the pacing is the disc's own"*. 🔴 **That is +refuted.** Build 4 declares about 120 presented frames and dwelled ~1 100 — nine +times its own timeline. The group is not the dwell. + +The **decision** is unchanged and still right: hold zero extra rather than invent +a number. What was wrong is what the port claimed for it. Leaving when the group +ends is not reproducing the disc's pacing — it is leaving at the moment the game +starts waiting. Both files now say so, and so does `boot.gd`, where the comment +had inherited the same claim. + +✅ The *structure* was already right, and this is the part the measurement +confirms: `_advance` is caused by the next screen arriving, never scheduled off a +timer, and the port's own comment already read *"a screen plays itself out because +something is taking its place"*. `exit_ramp_units` was deleted for an unrelated +reason and its absence is now doubly justified. + +⚠️ **Only build 4 is measured, and build 4 is the one screen where the port is +unaffected** — it is the boot's end state and holds indefinitely. The two screens +this actually governs, `publisher_logo` and `developer_logos`, have no measured +dwell at all. The port's boot is **known too fast on both, by an unmeasured +amount**. Nothing here is a number for them. diff --git a/port/scripts/boot.gd b/port/scripts/boot.gd index 831ae700..8208ea9e 100644 --- a/port/scripts/boot.gd +++ b/port/scripts/boot.gd @@ -350,8 +350,21 @@ func _process(delta: float) -> void: return # A screen holds at `rest` until it has arrived, then plays itself out and - # the next one begins. Nothing waits on a timer the disc does not carry: the - # pacing is each group's own timeline (authored/flow.json, `dwell`). + # the next one begins. Nothing waits on a timer the disc does not carry. + # + # 🔴 That is a choice made for lack of a number, NOT a reproduction of the + # game's pacing, and this comment used to claim otherwise. Measured in the + # draw stream (docs/port/DECISIONS.md, "The clock freezes at settle"): the + # top-level clock advances through the build-in, STOPS inside the settle + # window and holds -- build 4 declares ~120 presented frames and dwelled + # ~1100. The exit ramp is not on a timer; it plays when something makes the + # screen leave. Leaving AT settle, as the line below does, is leaving at the + # instant the real game starts waiting. + # + # The structure here is right and the duration is wrong: `_advance` is + # already caused by the next screen rather than scheduled, which is what the + # measurement says the game does. What is missing is the hold, and it goes + # in `authored/flow.json` `dwell` the day a capture times one. if view.holding and view.time_units >= view.settle_time(): # The LAST screen in the sequence keeps holding. A screen plays itself # out because something is taking its place; nothing is taking the