docs: P3 -- the boot runs unattended, and four answers taken as given
Gate: `godot --path port -- --boot --film=/tmp/boot` runs publisher_logo -> developer_logos (4.65 s) -> title (8.57 s), holding on the title after 13.05 s, each screen fading in, holding, and fading through black into the next. verify-screen now covers all 16 screens and passes `--all` to the reference renderer: the exporter addresses by pak entry index, which is the numbering `--all` uses, and without it `--build 10` would land on entry 12. The four new splash bundles come in at max 1-2/255. The three known differences are unchanged. Also recorded, taken from the RE agent rather than re-derived: * Focus stays "replace" -- over-vs-instead is unobservable (the focused sprite covers the base at 100 % of base-visible pixels; the two compositions differ by RMSE 1.1, under the gamma floor). The port guessed right for the wrong reason. The real gap is that ptbtn0Nf.rat declares TWO sprites -- a glowing ring, then the label -- where ptbtn0N.rat declares one. P5's, and the ring's placement is not decoded, so it will be authored from the capture and marked as such. * RMSE against captures has a FLOOR: capture ~ 255*(render/255)^g, g ~ 1.49 menu and EXTRAS, 1.34 title, and it is a ramp the GAME installed, not a capture-path artefact to subtract. Narrow reach (fitted on mostly-dark patches), so the port will not extrapolate it and will not apply it to rendered output. It is a comparison constant, not a rendering one. * Rotation is escalated to a human and the port has NOT acted. The RE half is answered -- about the declared pivot, measured -- and it has zero effect on the five screens at rest.
This commit is contained in:
@@ -563,3 +563,122 @@ the capture shows a ring marker beside `NEW GAME` that the port does not draw.
|
||||
|
||||
This is P5's, not P2's, and it is not being guessed at here. Raised in
|
||||
`docs/BLOCKED.md`.
|
||||
|
||||
---
|
||||
|
||||
## P3 — splash → title, unattended, 2026-08-29
|
||||
|
||||
### The splash is located by entry index, because no rule can find it
|
||||
|
||||
The RE agent looked for a content predicate and there is none: design size fails
|
||||
(every extra composable bundle sampled is 1280×720, the same as every screen) and
|
||||
element count fails (fragments run 2…15 elements in `GP_OPTIONS`/`GP_SAVE_LOAD`
|
||||
while the splash halves are 3 and 7 — the ranges overlap).
|
||||
|
||||
So `screen_builds` is now `is_build` **plus an authored allow-list of entry
|
||||
indices**, in `authored/screen_names.json` under `also_export`, each with a `why`
|
||||
that says it is a locator and not a claim. This is safe in `GP_TITLE` and would
|
||||
not be in general: there, widening adds exactly four bundles and all four are
|
||||
real screens with zero fragments. That is why it is an allow-list rather than a
|
||||
loosened predicate.
|
||||
|
||||
**There were two splash screens and the port had neither.** Entries 11/14 are the
|
||||
developer logos (GAME ARTS / SETA / studio anima); entries **10/13 are the SQUARE
|
||||
ENIX publisher wordmark, the first thing the boot shows**, and nothing in this
|
||||
project had noticed them. Both pairs are region twins — ™ on 10, ® on 13 — and
|
||||
the port shows one of each, not both.
|
||||
|
||||
### `authored/screen_names.json` is now keyed by pak entry, not by ordinal
|
||||
|
||||
Widening the enumeration renumbers the ordinals, and a name that moves when the
|
||||
enumeration rule changes is not a name. The file had always called the entry
|
||||
"the stronger locator"; it is now the only stable one. In `GP_TITLE` the two
|
||||
coincide across all 16 entries, which is also the numbering `sylpheed-cli screen
|
||||
--build N --all` takes — so `verify-screen` now passes `--all`, and without it
|
||||
`--build 10` would have landed on entry 12.
|
||||
|
||||
The two previously-unnamed plates therefore renamed `build_10`/`build_11` →
|
||||
`build_12`/`build_15`. Their names were always locators; now they locate the
|
||||
right thing.
|
||||
|
||||
### The exit is the group playing itself out, not a black rect over a freeze
|
||||
|
||||
HANDOFF's answer to ask 2 was (a), and it came with a test that discriminates
|
||||
rather than a plausibility argument. Under "a black quad over a frozen screen"
|
||||
every region is scaled by the same 1−α, so the button-region / background-region
|
||||
brightness **ratio** stays constant through the fade. Measured, it falls
|
||||
6.495 → 5.574 → 3.105 → 2.125 → 1.935 — a 3.4× monotonic drop. The screen plays
|
||||
out: `pteff00.prm` ramps to opaque black while the labels, `ptmsg`, `pteff10`
|
||||
and `pteff12` ramp to transparent, and `ptframe1`/`ptframe2` hold.
|
||||
|
||||
Implemented by giving the final untimed keyframe a **synthetic time**,
|
||||
`exit_ramp_units` after the last timed one, and then interpolating it like any
|
||||
other. One code path: the difference between arriving and leaving is only how far
|
||||
`t` is allowed to run, not a second kind of animation.
|
||||
|
||||
`exit_ramp_units = 24` (~0.4 s) is authored, and `authored/timing.json` carries
|
||||
the RE agent's own reach caveat rather than smoothing it: the filmstrip is
|
||||
downsampled and the button region contains some background, so this pins the
|
||||
**direction**, not 0.4 s to ±0.05 s, and it is one transition pair.
|
||||
|
||||
### Nothing waits on a timer the disc does not carry
|
||||
|
||||
`dwell` in `authored/flow.json` is deliberately empty. Each screen's dwell is its
|
||||
own keyframe group — the publisher wordmark reaches its hold at t=235 (3.92 s),
|
||||
the developer logos at t=190 (3.17 s), both read from the disc. Adding a hold on
|
||||
top would be inventing a number nobody measured. The pacing you see is the
|
||||
disc's own, and the file says where a measured number would go.
|
||||
|
||||
### The last screen holds
|
||||
|
||||
A screen plays itself out because something is taking its place. Nothing takes
|
||||
the title's place yet, so the sequencer holds there. A boot that ends by fading
|
||||
to black is a boot that looks like it crashed. P4 puts the intro video in front
|
||||
of the title and P5 gives the title somewhere to go.
|
||||
|
||||
### `flow.json` reproduces an observation and says so
|
||||
|
||||
Q6 closed with a negative: the order is in none of the four places it could have
|
||||
been, and a transition is a call with a name argument chosen by code. So this
|
||||
file is authored and its header says plainly that it reproduces what was watched,
|
||||
not what any file states. The intro video's place in the real boot is **named as
|
||||
a gap** rather than the order being quietly rewritten to hide it.
|
||||
|
||||
## P3 gate
|
||||
|
||||
`godot --path port -- --boot --film=/tmp/boot` runs unattended:
|
||||
|
||||
```
|
||||
publisher_logo → developer_logos at 4.65 s → title at 8.57 s
|
||||
boot sequence complete after 13.05 s, holding on title
|
||||
```
|
||||
|
||||
The filmstrip shows each screen fading in, holding, and fading through black into
|
||||
the next, and the title staying up. `verify-screen` covers all **16** screens
|
||||
now; the four new splash bundles come in at max 1–2/255 against the reference
|
||||
renderer. The three known differences are unchanged: `title` 6 (paint-order tie),
|
||||
`main_menu` 4, `title_jp` 155 (sampling phase at 125 % scale).
|
||||
|
||||
## Answers taken from the RE agent without re-deriving them
|
||||
|
||||
* **Focus stays "replace".** Over-vs-instead is unobservable: the focused sprite
|
||||
covers the base at 100 % of base-visible pixels, and the two compositions
|
||||
differ by RMSE 1.1 inside the button rect — under the gamma floor. The port's
|
||||
guess was right for the wrong reason, and the actual gap is that
|
||||
`ptbtn0Nf.rat` declares **two** sprites — `ptbtneff01.t32`, a glowing ring, and
|
||||
then the bright label — where `ptbtn0N.rat` declares one. The ring is P5's, and
|
||||
its placement inside the record is **not decoded**, so it will be authored from
|
||||
the capture and marked as such.
|
||||
* **RMSE against captures has a floor, so stop chasing it.** The capture is
|
||||
`≈ 255·(render/255)^γ` with γ ≈ 1.49 on the menu and `EXTRAS`, 1.34 on the
|
||||
title, and it is a ramp *the game installed* (`VdGetCurrentDisplayGamma` at
|
||||
video init), not a capture-path artefact to subtract. Its reach is narrow —
|
||||
the flat patches it was fitted on are almost all dark — so the port will not
|
||||
extrapolate it across the range, and will not apply it to rendered output on
|
||||
this evidence. It is a comparison constant, not a rendering one.
|
||||
* **Rotation is escalated to a human and the port has not acted.** The RE half is
|
||||
answered — rotate about the **declared pivot**, measured against the GPU
|
||||
capture — and it has zero effect on the five screens at rest. The port will
|
||||
carry `rotation_deg` in a future FORMAT v3 because carrying a decoded field the
|
||||
renderer ignores beats dropping it, but it will not draw it until the
|
||||
divergence question is settled.
|
||||
|
||||
Reference in New Issue
Block a user