diff --git a/port/scripts/boot.gd b/port/scripts/boot.gd index 70037e1b..e111acaa 100644 --- a/port/scripts/boot.gd +++ b/port/scripts/boot.gd @@ -180,6 +180,18 @@ func _ready() -> void: if args.has("script"): _script = args["script"].split(",", false) _skip_at = float(args.get("skip-at", "0")) + # `--press-at=S[,S…]` presses Ⓐ at wall-clock moments ANYWHERE in a boot. + # `--skip-at` cannot do it: it lives inside the movie branch and fires once, + # so it can skip the intro and nothing after. Needed to exercise the second + # of the three Ⓐ presses (the plate snap), which lands on the title. + # + # ⚠️ Wall-clock, and therefore fragile by construction -- the Decoder found + # blind delays cannot reliably hit a window when pacing varies. It is a + # DIAGNOSTIC for a deterministic local boot, not an instrument to assert with. + if args.has("press-at"): + for part in String(args["press-at"]).split(",", false): + _press_at.append(float(part)) + _press_at.sort() # `--focus=` draws a button's focus record in a `--screen` run, # which otherwise focuses nothing. A diagnostic: the spinning ring is only # drawn on a FOCUSED button, so without this the ring can only be observed in @@ -487,6 +499,9 @@ var _black_hold := 0.0 ## `--focus=`: draw this element's focus record in a `--screen` run. var _force_focus := "" var _skip_sent := false + +## Pending `--press-at` moments, ascending. See where it is parsed. +var _press_at: Array = [] var _script_started := false var _sequence: Array[Dictionary] = [] var _player: VideoStreamPlayer = null @@ -560,6 +575,10 @@ func _process(delta: float) -> void: _screen_frames += 1 _worst_gap = maxf(_worst_gap, delta) view.queue_redraw() + while not _press_at.is_empty() and _elapsed >= float(_press_at[0]): + _press_at.pop_front() + print(" --press-at: pressing (A) at %.2f s" % _elapsed) + _press("ui_accept") _overlay_process(delta) _menu_repeat(delta) @@ -942,6 +961,45 @@ func _unhandled_input(event: InputEvent) -> void: _player.stop() _video_finished() return + # F5, MEASURED: Ⓐ during the title's build-in is a CUT, not an acceleration. + # The plate goes to alpha 255 in ONE frame against about eleven frames of ramp + # with no input, and the sweep enters at 255 with no ramp at all where an + # untouched run takes its parent's declared `t=70…100` gate + # (`docs/re/f5-a-press-snaps-the-plate.md`). + # + # 📌 IT ADVANCES THE ONE SHARED CLOCK, which is why `authored/flow.json`'s + # `clock: "shared"` stands. Both agents briefly had the opposite: a first pass + # reported the artwork animating across the press, which would have meant two + # clocks and an overlay-only jump. That rested on a 5-frame window which sat + # entirely inside the 11-12 frame lag between a scripted press and its effect, + # so it compared frames where the input had not been acted on yet. A wider + # pre-registered test refuted it: three elements mid-fade vanish in a single + # frame. I had implemented the overlay-only version; it is reverted here. + # + # ⚠️ The target is BOUNDED, not pinned. The capture puts it inside [100, 238] + # -- past the sweep's gate at 100, and not past 250 or `ptloop01`'s exit ramp + # would have taken the sweep back to alpha 0. `settle_time()` is 236 for this + # overlay, which is inside that bound and is where the plate reaches full + # alpha. If the game turns out to snap somewhere else in the window, this is + # the line to move and nothing else changes. + # + # 🔴 NOT `settle_instant`: the first version of this used it and NEVER FIRED, + # silently. `press_start` declares a 22-unit settle window against a 30-unit + # minimum, so `settle_instant` is -1 for this screen. The boot has always + # printed "settles at t=236" from `settle_time()`, a different quantity, and I + # read the printed number as evidence for the field I was testing. + # + # It is the SECOND of three presses from the logos to the menu -- skip movie, + # reveal plate, activate it. Consuming the press keeps the second and third + # distinct. + if overlay != null and event.is_action_pressed("ui_accept"): + var snap_to := overlay.settle_time() + if snap_to > 0.0 and view.time_units < snap_to: + print(" (A) snaps the title: shared clock %.1f -> %.1f" % [view.time_units, snap_to]) + view.time_units = snap_to + view.queue_redraw() + _overlay_process(0.0) + return if _menu == null or _menu.stack.is_empty(): return # AUTHORED, not measured: a press during a screen's fade-out is dropped.