diff --git a/authored/timing.json b/authored/timing.json index 9270c214..c236c9ce 100644 --- a/authored/timing.json +++ b/authored/timing.json @@ -73,37 +73,50 @@ ], "looping_focus_records": { "_": [ - "WHICH focus records the port draws unconditionally, and loops.", + "WHICH focus records the port draws, unconditionally and on a loop, OVER the", + "element's own sprite rather than instead of it.", "", - "🔴 EMPTY AS OF 2026-08-30, and the deletion is the finding.", - "", - "The one entry here -- `press_start/ptbtn00`, period 120 -- was AUTHORED to", - "give the PRESS (A) plate a glow on a screen that has no buttons and focuses", - "nothing. Measured, it did the opposite: it made the plate INVISIBLE.", - "", - "`_draw` treats a looping focus record the way it treats a focused button --", - "it draws the focus record INSTEAD of the base sprite and moves on. For a", - "focused button that is right and measured (the focused sprite covers the", - "base at 100.0 % of base-visible pixels). For the plate it substituted a dim", - "glow at the wrong phase for the element's own bright sprite:", - "", - " with the entry without it", - " press_start t=236 max 0 max 252.5", - " press_start t=240 max 0 max 252.5", - " press_start t=250 max 15.3 max 252.5", - "", - "So the plate could not be seen at any instant, on the screen whose entire", - "content is the plate. The element's own fade is DECODED -- alpha 255 at", - "t=236-238 -- and this authored guess was overriding decoded data with a", - "worse answer. That is the wrong way round, and an authored entry that", - "suppresses a decode is deleted rather than tuned.", - "", - "⚠️ What is NOT claimed: that the plate has no glow. The focus record", - "`ptbtn00f.rat` exists and may well be drawn ON TOP of the base in the real", - "game. Drawing both would be a rendering rule nobody has measured, so the", - "port draws what the disc's own fade says and leaves the glow out. See", - "docs/port/BLOCKED.md -- a capture of the idle title settles it." - ] + "RESTORED 2026-08-30 on a MEASUREMENT, having been deleted on 2026-08-29 for", + "a real defect that was in the RENDERER, not in this table. The old entry made", + "`_draw` substitute the glow for the plate's own bright sprite, so the plate", + "was invisible at every instant (max 0 against max 252.5). `ScreenView` now", + "draws the base and the record over it, and the entry comes back." + ], + "press_start/ptbtn00": { + "record_element": "ptbtn00f", + "period_units": 120, + "kind": "measured", + "source": "docs/re/structures/plate-pulse-measured.md, RE agent 2026-08-30", + "why": [ + "MEASURED off the running game, held at the title with NO INPUT: the plate", + "oscillates continuously -- two windows in one boot of 58 s and 57 s, about", + "23 cycles each, with no decay and no settling.", + "", + "🔴 IT NEVER GOES OFF. The plate-absent floor is 159 thresholded green", + "pixels -- the title art's own, measured on live-title-build4-no-plate.png --", + "and the pulse bottoms at 714, four and a half times that. So `ptbtn00`", + "going transparent at t=244 is not the end of the plate; that is its EXIT", + "ramp, which plays when the screen leaves. While the screen is held the base", + "sits at its own hold (alpha 255 at t=238) and `ptbtn00f`'s cycle runs over", + "it. Base-only and base-plus-glow are what the 714 and the 1520 are.", + "", + "⚠️ 120 UNITS, NOT SECONDS, and that is the RE agent's own instruction. Their", + "run measured 2.530 and 2.540 s; an earlier corpus run measured 2.24 s. Same", + "declared number, different emulator pacing -- x1.27 and x1.12 against a", + "nominal 2.000 s, which IS 120 units at 60 units/s. Hardcoding 2.5 s would", + "author one loaded container's clock." + ], + "limits": [ + "ONE BOOT. Two windows inside it are not two boots.", + "It does NOT distinguish the boot title from an attract-loop title: run 1", + "opens at t~255 s against Q9's ~193 s no-input baseline, so it may already", + "be the attract title. Both are 'the title, held, no input' -- which is what", + "was asked -- but it is not proof about the first appearance.", + "🔴 714/1520 IS NOT AN ALPHA RATIO. The counter is thresholded pixels, so dim", + "pixels drop out first. No duty cycle and no ramp shape may be read off it;", + "the port draws the record's own declared alpha ramp and infers nothing." + ] + } }, "exit_ramp_deleted_why": [ "DELETED 2026-08-29, and the deletion is the point.", diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index 9d7bdb1a..e73370db 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -9,7 +9,7 @@ dies, which is what this file is for. -121 sections. Search this before re-deriving anything. +122 sections. Search this before re-deriving anything. * [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28) * [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28) @@ -132,6 +132,7 @@ dies, which is what this file is for. * [A withholding reason that was false, and the measurement beside it that was not](#a-withholding-reason-that-was-false-and-the-measurement-beside-it-that-was-not) * [The sweep discriminator resolves: different frames, and a sweep position cannot date one](#the-sweep-discriminator-resolves-different-frames-and-a-sweep-position-cannot-date-one) * [Their trap, run against my tree — and I found its mirror instead](#their-trap-run-against-my-tree--and-i-found-its-mirror-instead) +* [The plate pulses — measured, and the port was wrong on the boot's end state](#the-plate-pulses--measured-and-the-port-was-wrong-on-the-boots-end-state) ## P0 — the exporter, 2026-08-28 @@ -7120,3 +7121,60 @@ correlated-instrument shape I have been careful about all week and did not apply to my own message. The discriminator result is unaffected — 294.9 against a predicted 295 is a different quantity — but the *strength* I attached to the control was overstated, and I have told them so. + +## The plate pulses — measured, and the port was wrong on the boot's end state + +Ask #1 came back the other way. Held at the title with **no input**, the plate +oscillates continuously — two windows in one boot, ~23 cycles each, no decay, no +settling — and 🔴 **it never goes off**: the plate-absent floor is **159** +thresholded green pixels and the pulse bottoms at **714**, four and a half times +that. + +That reading is what makes the mechanism recoverable. A glow alone cannot do it: +`ptbtn00f` ramps 0 → 80 → 0. A **steady base plus a pulsing glow** can, and 714 and +1520 are exactly base-only and base-plus-glow. + +And the port already had the base right. `ptbtn00`'s fade to 0 at t=244 is its +**exit** ramp, which plays when the screen leaves; while the screen is *held* the +base sits at its own hold, alpha 255 at t=238. What was missing was the glow. + +### The defect was in the renderer, not in the deleted entry + +`_draw` treated a **looping** record like a **focused** one — drawing it *instead +of* the base sprite. For a focused button that is right and measured (the focused +sprite covers the base at 100 % of base-visible pixels). For the plate it +substituted a dim glow for a bright sprite, which is why the plate vanished and +why I deleted the authored entry on 2026-08-29. + +I deleted the right thing for the wrong reason. The entry was correct; the branch +it landed in was not. A looping record now draws **over** the base, and the entry +is restored with the measurement behind it. + +| | | +|---|---| +| plate region, base only | **95.68** | +| base + glow at peak | **115.52** | +| measured period over 10 cycles | **1.980 s** | +| declared 120 units at 60 u/s | 2.000 s — **ratio 0.990** | + +✅ The pulse appears on the **boot** path, where the overlay runs on the shared +clock. It does *not* appear under `--screen=title --overlay=press_start`, because +a static overlay poses at its own arrival — my own earlier fix — so its clock never +advances. That is correct for a still frame and worth knowing before anyone reads +a flat plate there as a regression. + +### What is authored, and what is refused + +**120 units, not seconds**, on the Decoder's own instruction: their run measured +2.530 and 2.540 s and an earlier corpus run 2.24 s — one declared number through +two emulator pacings (×1.27 and ×1.12 against a nominal 2.000 s). Hardcoding 2.5 s +would author a loaded container's clock. + +⚠️ Their three limits are carried into `authored/timing.json` verbatim: **one +boot**, two windows inside it are not two boots; it **does not distinguish** the +boot title from an attract-loop title, since run 1 opens at t≈255 s against Q9's +~193 s baseline; and 🔴 **714/1520 is not an alpha ratio** — the counter is +thresholded pixels, so no duty cycle or ramp shape may be read from it. The port +draws the record's own declared ramp and infers nothing about its shape. + +Oracle rows unmoved; every asserting check passes. diff --git a/port/scripts/screen_view.gd b/port/scripts/screen_view.gd index a6587cd7..d947af8e 100644 --- a/port/scripts/screen_view.gd +++ b/port/scripts/screen_view.gd @@ -638,13 +638,28 @@ func _draw() -> void: and draw_leaf_for.has(String(element.get("id", ""))) \ and _draw_leaf(element): continue - # A focused button draws its own record instead of its base sprite -- and - # so does an element the authored table says always shows it, which is - # how the PRESS (A) plate gets its glow on a screen that has no buttons - # and focuses nothing. - if (focused_id == id or looping_focus.has(id)) and element.has("focus"): + # A FOCUSED button draws its record INSTEAD of its base sprite -- measured, + # the focused sprite covers the base at 100.0 % of base-visible pixels. + if focused_id == id and element.has("focus"): _draw_focus(element) continue + # 🔴 A LOOPING record draws IN ADDITION to the base, not instead of it. + # + # This used to take the same branch as a focused button, and that is why + # the authored entry for the `PRESS (A)` plate had to be deleted: it + # substituted a dim glow for the plate's own bright sprite and the plate + # became invisible at every instant (max 0 against max 252.5). + # + # The Decoder has since MEASURED the real behaviour -- held at the title + # with no input, the plate oscillates continuously for ~23 cycles with no + # decay and NEVER GOES OFF, bottoming at 714 thresholded green pixels + # against a plate-absent floor of 159. A glow alone cannot do that: its + # record ramps 0 -> 80 -> 0. A steady base plus a pulsing glow can, and + # the two numbers line up with base-only and base-plus-glow. + # + # So the base is drawn first and the record over it. `_draw_focus` runs + # after, with no `continue`. + var loops_focus := looping_focus.has(id) and element.has("focus") var rel: String = element.get("sprite", "") if focused_id == id and element.get("focus_sprite", "") != "": rel = element["focus_sprite"] @@ -656,6 +671,8 @@ func _draw() -> void: continue _draw_quad(tex, placement(pose, pivot, tex.get_size()), colour, pivot, pos, rot) drawn.append(id) + if loops_focus: + _draw_focus(element) elif element.get("role", "") == "primitive" and element.has("size"): # A primitive has no texture; the quad is its declared size and its # colour is the pose's own modulate.