re: Q3 was already answered in docs/re -- deliver it, and test it on EXTRAS
The handoff had Q3 as "runtime-solved only". It is not: the layer key at +0x0A of the T8aD sprite header, stable-sorted, is a file-derivable paint order, already checked against five measured orders and already driving the compositor for every build on the disc. That answer had simply never reached the page the port agent reads. The new evidence is EXTRAS -- the first screen composited from the rule alone and scored against a framebuffer capture the rule had never seen. 0.9620 at zero shift, against a same-tooling control of 0.9657 on the screen the rule was fitted to. Written down with its limit rather than its headline: align_to_capture correlates edges, and a paint-order change moves blends, not edges, by =<45/255 on a few per cent of pixels. So the score is evidence for placement and only CONSISTENT with the order. The sharp A/B needs a rebuild and is named in the doc instead of being claimed.
This commit is contained in:
@@ -29,7 +29,7 @@ authored version can be deleted.
|
||||
|---|---|---|---|
|
||||
| Q1 | keyframe time unit + ramp shape | ✅ answered | ramp is **linear**; the clock advances **2 units per rendered frame**; working conversion **1 unit = 1/60 s** — [`ui-keyframe-time-unit.md`](../re/ui-keyframe-time-unit.md) |
|
||||
| Q2 | which build is which screen state | ✅ answered | `GP_TITLE` is **8 screens shipped twice, EN/JP**: 4/7 title art, 2/3 the `PRESS Ⓐ` plate, 5/8 main menu, 6/9 `EXTRAS`, 0/1 and 10/11 two unidentified `DELTASABER` plates — [`ui-title-build-map.md`](../re/ui-title-build-map.md) |
|
||||
| Q3 | paint order for the six screens | ❔ open | runtime-solved only; declaration table is refuted |
|
||||
| Q3 | paint order for the six screens | ✅ answered | **decoded**: a `u16` layer key at `+0x0A` of each `T8aD` sprite header, stable-sorted with declaration index; unkeyed elements get an implied key. Confirmed on 5 measured orders + `EXTRAS` vs a capture. One residual: the **tie-break** is unknown and bites on one element of the title — [`structures/ui-paint-order-key.md`](../re/structures/ui-paint-order-key.md) |
|
||||
| Q4 | button → GamePart | ❔ open | labels are baked into sprites |
|
||||
| Q5 | navigation semantics | ❔ open | |
|
||||
| Q6 | boot sequence + what drives it | 🟡 partial | order observed, and the **attract cycle is timed**: ~8–10 s idle on the title → fade to black → ~85 s of video → title again, plate and all. The driver is still not decoded |
|
||||
@@ -76,6 +76,24 @@ authored version can be deleted.
|
||||
[`ui-keyframe-time-unit.md`](../re/ui-keyframe-time-unit.md) names the test.
|
||||
If it turns out the game presents at 60 Hz, every duration halves — nothing
|
||||
else on this page changes.
|
||||
* **The paint order is derivable from the file.** Each `T8aD` sprite header
|
||||
carries a **`u16` layer key at `+0x0A`** (the upper half of the 32-bit word at
|
||||
`+0x08` is zero in all 21 184 sprites on the disc). Paint order is that key,
|
||||
**stable-sorted** so equal keys keep declaration order; elements with no sprite
|
||||
(`.prm` primitives, `.tbm`) have no key and take an implied one — the backdrop
|
||||
and dim quads sort early, the screen-transition fade (`pteff00.prm`,
|
||||
`pfeff00.prm`) sorts **last**. ✅ decoded. Checked against five paint orders read
|
||||
off the running game, one of them (`GP_SAVE_LOAD`'s slot-list header, 6
|
||||
instances) **exact and independent of the screens the rule was fitted to**, and
|
||||
against a fresh `EXTRAS` capture. It reorders 341 of the disc's 965 builds, so
|
||||
it is not a no-op dressed as a rule.
|
||||
🟡 **The one residual: ties.** Where two elements share a key the game
|
||||
sometimes paints them in an order nothing predicts — eight candidates refuted,
|
||||
including declaration order, RATC child order, keyframe times, resting X/Y and
|
||||
`kind`. Measured cost: on the three screens with ground truth it changes the
|
||||
blend of **one element on one screen** (a title glow). Take the stable sort and
|
||||
accept that.
|
||||
|
||||
* **The GamePart id table** — 29 entries at `.rdata 0x820A1630`, confirmed by the
|
||||
executable's own registration strings. ✅ This is the screen vocabulary; which
|
||||
button reaches which entry is Q4 and is *not* part of it.
|
||||
|
||||
@@ -395,3 +395,50 @@ Three published numbers on this page were wrong the same way: each was computed
|
||||
over a population I had not checked was the population in question — the six
|
||||
language copies, then the top-level-only sprites, then the size of that gap. The
|
||||
analysis was never the problem. **Check the sampling frame before the statistic.**
|
||||
|
||||
## `EXTRAS` — the derived order against a capture nobody had taken (2026-08-28)
|
||||
|
||||
The five orders above are all **measured**: the derived rule is checked against a
|
||||
live child list. This one is the other direction — a screen with **no measured
|
||||
order at all**, composited purely from the derived rule and scored against a
|
||||
framebuffer capture taken the same day
|
||||
([capture](../captures/title-builds/live-extras.png),
|
||||
[composite](../captures/ui-layout/extras-composited.png)).
|
||||
|
||||
`GP_TITLE.pak` build 6, 18 elements, two `.prm` primitives:
|
||||
|
||||
```
|
||||
sylpheed-cli screen render --build 6 --black --primitives GP_TITLE.pak extras.png
|
||||
align_to_capture.py live-extras.png extras.png --region 150 100 1150 600
|
||||
```
|
||||
|
||||
| composite | best shift | score |
|
||||
|---|---|---|
|
||||
| **build 6, `--black --primitives`** | **(0, 0)** | **0.9620** |
|
||||
| build 6, no primitives | (0, 0) | 0.9576 |
|
||||
| *control:* main menu vs `main-menu-oracle.png`, same tooling | (0, 0) | 0.9657 |
|
||||
|
||||
The control was run first and reproduces the screen this rule was fitted to, so
|
||||
the harness is known-good before the new screen is scored. `EXTRAS` lands within
|
||||
0.004 of it, at zero shift, with the primitives helping rather than hurting.
|
||||
|
||||
### ⚠️ What this does and does not show
|
||||
|
||||
**It does show** that every other part of the stack transfers to an unfitted
|
||||
screen: element enumeration, resting pose, pivots, `fade` alpha, and that the
|
||||
two primitives land somewhere harmless under the derived `implied_layer_key`.
|
||||
|
||||
**It does not show that the paint order is right.** `align_to_capture.py`
|
||||
correlates *gradient magnitude* — edges — and a paint-order change moves blend
|
||||
values, not edges. The earlier derived-vs-declaration A/B on the pause menu and
|
||||
main menu measured exactly that: 1.1–3.8 % of pixels differing by ≤45/255, in
|
||||
translucent overlaps. A score computed this way cannot see a difference that
|
||||
size, so **0.9620 is evidence for placement and only consistent with the order.**
|
||||
|
||||
**The sharp test, not run.** Composite build 6 twice — the committed derived
|
||||
order, and `compose` temporarily reverted to declaration order — and diff both
|
||||
against the capture over the pixels where they disagree. That needs a rebuild of
|
||||
`sylpheed-formats`, which is why it is named here rather than done; it is the
|
||||
same A/B this page already ran on the two screens that had oracles, and `EXTRAS`
|
||||
would be the first screen where the two orders can be judged against ground
|
||||
truth rather than declared indistinguishable.
|
||||
|
||||
Reference in New Issue
Block a user