port: census every layerless full-screen element; the forced-backdrop quantifier misses nothing in GP_TITLE

Tries to refute the rule by SUFFICIENCY rather than correctness: a strict
'all others visible' quantifier fails quietly, so the question is whether any
full-screen opaque backdrop misses the bar and keeps hiding its screen.

None does. Everything that fires is at 100% of others; everything that does not
is at 13-47%, and pteff02 never reaches alpha 255 at all. No borderline case.

Reproduces the Decoder's second control exactly (pteff00 forced below 3 of 23)
and shows their palogo_eff0 span gap is not a constant offset -- 211 is the
number our developer_logos row does reproduce.

Also retires the 'loading screen fade quad rests OPAQUE BLACK' row: resolved by
the rule, and it recorded rest.t as 38 where it is 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
Sylpheed port agent
2026-08-29 21:14:51 +00:00
parent b2373284c6
commit ad634bd79c
2 changed files with 43 additions and 1 deletions

View File

@@ -124,7 +124,7 @@ HANDOFF.
| P7 / naming — the four unnamed builds | **which locale and variant is each of `GP_TITLE` entries 0, 1, 12, 15?** | — | 🟢 **found by the port, not blocking, and handed over.** All four are **loading screens**: every element in all four is named `pgloading_*` (`pgloading_processing.png`, `pgloading_circle1`, `pgloading_delta`, `pgloading_ring`), and `LOADING` is one of the three screen names the Decoder read out of `sub_821C6458`. They export today as `build_00`, `build_01`, `build_12`, `build_15`. Two variants: 0/1 carry 7 elements, 12/15 carry 10 (adding `pgloading_eff00`, `pgloading_loop5`, `pgloading_baseeff`). The archive's own pairing — adjacent for 2/3, `+3` for 4…9 and 10/13, 11/14 — suggests 0 is the twin of 1 and 12 the twin of 15, but **which member is which locale is an inference and the port has not named them on it**. Naming is cheap for the Decoder and a guess for the port. |
| P7 — what fills the 4.5 s before `S00A` | **is the LOADING screen what appears between the save slot and the new-game movie?** | Q4 + Q9 | ❔ **not observed, and the port has not assumed it.** Q9 measures `S00A.wmv` starting ~4.5 s after Ⓐ on the save slot. The run that would have shown what is on screen for those 4.5 s hit the documented `sub_823070B0` cache crash after `SELECT DATA`. `GP_TITLE` carries a loading screen (row above) and 4.5 s is about the right shape for one, and that is **exactly why it is written here and not in `flow.json`**. Settled by one run that reaches the movie without crashing. |
| P3 — a second `rest.t` casualty | **the loading screen's fade quad rests OPAQUE BLACK** | — | 🔴 **noted, not fixed.** `pgloading_eff00.prm` on entries 12/15 is a 1280×720 black quad whose group is `0xff000000` at t=38, `0xff000000` at t=48, then `0x00000000` on the untimed final — black, held, *then* clear. Its `rest.t` is **38**, where it is fully opaque. So a port that draws this screen at its `rest` draws **a black rectangle over the whole loading screen**. This is the same `settle_time()`/`rest.t` problem as the row below, in a form where it hides the entire screen rather than dimming it — and it will bite whoever first draws a loading screen. |
| ~~P3 — a second `rest.t` casualty~~ | ~~the loading screen's fade quad rests OPAQUE BLACK~~ | — | **resolved 2026-08-29 by the forced-backdrop rule, and this row carried a stale number.** The quad still rests opaque — that part was right — but it no longer *hides* anything: it is a layerless full-screen element opaque across a span containing all 9 others, so it is **forced to paint first** and the loading screen draws over it. At `--pose=rest`, `build_12`/`build_15` went from **mean 0, the whole screen black** to mean 1.95 with **59 530 non-black pixels**. ⚠️ Two corrections to what this row said. Its `rest.t` is **0, not 38** — stale since the keyframe-layout correction (`formats-pin-2026-08-29c`) timed every pose; the group is `0xff000000` at t=0 **and** t=38, then `0x00000000` at t=48, so the conclusion held while the number did not. And the general `rest.t` complaint is **not** resolved: an opaque element at its rest instant is still opaque, and this one stopped mattering only because it is a full-screen backdrop. **The row below still stands for anything that is not.**
| ~~P6 — runtime headroom~~ | ~~the Master bus clips~~ | — | 🟢 **withdrawn by the port, 2026-08-29 — it was my own overstatement.** Filed 🔴 twice on a peak reading of 0.0 dBFS. Measured properly: **43 samples at full scale in 5.9 s and 24 in 98.5 s, longest clamped run 0.25 ms** — the disc's own `confirm` cue touching the ceiling on a transient, possibly only in the recording's 16-bit conversion since Godot mixes in float. Not a defect, and nothing is changed: attenuating to buy headroom would be an unmeasured level decision of exactly the kind this port refused for the BGM loop point. **A peak reading is not a clipping measurement** — one sample at 0 dBFS and two seconds of square wave give the same number. |
| Modding — rule 4 | ~~base-and-overrides is unimplemented~~ | — | ✅ **implemented 2026-08-29, and it was not blocked on anybody.** `MODDING.md` calls it a constraint on the exporter *today*; nothing read `data/mods/` for eight milestones. `ExportTree.resolve` now shadows by path for every asset kind, each replacement is logged as it is read, and `.gitignore` excludes the directory's contents — a mod is usually an edited game asset, and that directory was the one place git would have taken one. ⚠️ The `export/` vs `data/base/` naming split between `PORT-MISSION.md` §3 and `MODDING.md` is **raised, not resolved**: only the human changes a mission. |

View File

@@ -4993,3 +4993,45 @@ hold directly: the frame is constant from t=30 to t=60 with the timeline running
It also explains 36 builds the Decoder had filed as "coming out one colour":
`pzeff00.prm` is forced first in 32 of 32 of them. Those were wiped by our own
sort.
## Refutation attempt — the forced-backdrop rule's quantifier, and whether it misses a case
The rule fires only when **all** other elements are visible during the opaque
span. That is a strict quantifier, and a strict quantifier fails quietly: an
element that is a full-screen opaque backdrop but misses the bar by one dark
element would keep its layer-key position and go on hiding the screen, exactly
the defect the rule was written to fix. So the question worth asking of somebody
else's rule is not "is it right" but **"is it enough"** — and that one I can test
without an oracle, over every layerless full-screen element in `GP_TITLE`.
| screen | element | opaque instants | others visible | forced |
|---|---|---|---|---|
| `build_12`, `build_15` | `pgloading_eff00` | 39 | **9 / 9** | ✅ |
| `developer_logos` ×2 | `palogo_eff0` | 211 | **6 / 6** | ✅ |
| `publisher_logo` ×2 | `palogo_eff0` | 256 | **2 / 2** | ✅ |
| `title`, `title_jp` | `pteff00` | 2 | 3 / 23 | — |
| `main_menu` ×2 | `pteff00` | 2 | 7 / 15 | — |
| `extras` ×2 | `pteff00` | 2 | 5 / 17 | — |
| every screen | `pteff02` | **0** | — | — |
**The rule survives, and the margin is the reason.** Nothing sits near the
boundary. Every element that fires does so at **100 %** of the others; every
element that does not is at 1347 %, and `pteff02` never reaches alpha 255 at all,
so no quantifier could fire on it. There is no borderline case in this archive
for a stricter or looser reading to disagree about — which is the answer I could
not have gotten by re-checking the six screens where it already fired.
It also reproduces the Decoder's **second** control number exactly: they report
`pteff00.prm` forced below **3 of 23**, and `title` measures 3 of 23 here. With
their opaque-instant count of 2 already matched, two of their three published
figures for that control now come out of an independent implementation
unchanged. The third — `palogo_eff0`'s 211 against our 256 — remains the span
disagreement filed in `BLOCKED.md`, and note that the 211 is the number our
`developer_logos` row *does* reproduce. That is worth saying plainly: **the
disagreement is not a constant offset**, so "they stop 45 instants early" is not
the explanation, and whatever it is differs per screen.
⚠️ What this does **not** test: whether the rule is right about the 50 elements it
calls constrained-but-not-forced, and whether alpha-over is the blend mode. Both
are the Decoder's to settle. It tests completeness within one archive, which is
the half I can reach.