docs: the timeline lands on rest -- except on six elements, where the game
agrees with the timeline P2's gate is the buttons sliding in, and `tools/screen-strip` renders the strip that shows it. But the useful result came out of checking where the animation settles. On 8 of 12 screens the settled timeline is BYTE-IDENTICAL to the declared `rest` pose -- the port walks the keyframes with an authored time unit and arrives, to the pixel, where the pinned decoders independently say the screen rests. On `main_menu` the two differ in exactly one region, 400x470 at (440,108): the bounding box of `ptframe1` and `ptframe2` and nothing else. `rest` puts both at their first keyframe, off-position and transparent. The capture of the running game shows them -- the bright circuit bracket around the menu. Cropping the same region from the capture and from both renders puts the ring and its elbow trace in the timeline render pixel-aligned with the game's, and absent from the rest render. Geometry, so it does not depend on the capture's gamma or on its having been taken with NEW GAME focused. `ui_layout::rest_plateau` excludes a trailing run of identical keyframes because it is normally the exit. On an element with NO exit animation the trailing run IS the hold. The condition that identifies these exactly, with no false positives here, is "the final untimed keyframe has the same pose as the last timed one" -- six elements, and `rest()` misses all six. Filed in BLOCKED.md for the RE agent: the decoders are pinned and are not this port's to fix, and `sylpheed-cli screen render` is missing the bracket too. Worth saying plainly what this does to P1: the port and the reference agreed on `main_menu` to 3/255 and BOTH were missing two elements the game draws. Two renderers reading one field through one decoder agreeing is not evidence the field is right. BLOCKED.md had already said that about the pivot; here it bit. The title is NOT settled and P2 does not claim it. `rest` and the timeline disagree there by 142-247/255, the only live title capture composites the PRESS A plate over build 4 so it cannot be diffed against the title alone, and both of the port's modes draw a cyan glow slab the game does not have -- a third problem, P3's. Recorded as an open question rather than resolved by tuning. Also reconciled against the RE agent's new work: Q8 is answered -- the SE waves are located in `Static.slb` (move/confirm/back), which unblocks P6's audio; and the title's transitions are a lookup by NAME, giving P3/P5 the game's own screen vocabulary as candidate `goto` targets, marked as the name match it is.
This commit is contained in:
@@ -272,3 +272,122 @@ Both renderers skip them. The bundle declares them and carries **zero** RATC
|
||||
children for either, so there is no texture on the disc to export — this is a
|
||||
property of the disc, not a gap in the exporter, and `ScreenView` reports it as
|
||||
`no sprite in the export` rather than dropping it silently.
|
||||
|
||||
---
|
||||
|
||||
## P2 — keyframe animation, 2026-08-28
|
||||
|
||||
### The time unit is authored, in one file, and says loudly that it is not on the disc
|
||||
|
||||
`authored/timing.json`. HANDOFF Q1 is answered — linear ramp, 2 units per
|
||||
rendered frame, 1 unit = 1/60 s — but that conversion is **measured off the
|
||||
running game**, not read from a file, which is exactly the case the
|
||||
derived/authored split exists for. It is expressed as
|
||||
`keyframe_units_per_second: 60` rather than seconds-per-unit so the value is
|
||||
exact instead of a repeating decimal, and it carries the two independent lines
|
||||
that support it. `t` stays raw everywhere in `export/`; seconds appear only
|
||||
where this file is applied, which is one line of `boot.gd`.
|
||||
|
||||
`exit_ramp_seconds` is deliberately **null**. See below.
|
||||
|
||||
### The timeline stops at the last *timed* keyframe, and never plays the exit
|
||||
|
||||
The last keyframe of every group carries **no `t`** — the disc has no time slot
|
||||
there. Across this export that final frame is an *exit* pose: for 116 of 134
|
||||
elements it differs from the last timed keyframe **in alpha only** (a fade-out),
|
||||
for 12 it is the loading splash's scale-and-slide exit, and for 6 it is
|
||||
identical (no exit animation at all).
|
||||
|
||||
So the group is `pre-roll → ramp in → hold → [exit]`, and the port plays it up to
|
||||
the hold and stops. Playing into the exit would mean **inventing how long the
|
||||
ramp takes**, because the disc does not say. That duration is the screen
|
||||
transition — HANDOFF Q7 measured it at ~0.4 s — and it belongs to P3, with its
|
||||
own evidence. This is why `exit_ramp_seconds` is null rather than 0.4: P2 has no
|
||||
business holding it.
|
||||
|
||||
### The interpolation is checked by where it lands, not by inspection
|
||||
|
||||
For **8 of the 12** screens the settled timeline is **byte-identical** to the
|
||||
`--pose=rest` render. That is the useful assertion: the port walks the keyframes
|
||||
with an authored time unit and arrives, to the pixel, at the pose the pinned
|
||||
decoders independently identify as the resting one. `tools/screen-strip` reports
|
||||
this per screen, so a change to the interpolation that drifts by one unit shows
|
||||
up as a diff rather than as nothing.
|
||||
|
||||
The four that differ do so for two distinct reasons, below.
|
||||
|
||||
## `rest` misidentifies six elements, and the running game says so
|
||||
|
||||
On `main_menu`, the settled timeline and `rest` differ in exactly one region:
|
||||
**400×470 at (440,108)** — the bounding box of `ptframe1` and `ptframe2`, and
|
||||
nothing else on the screen.
|
||||
|
||||
`rest` puts both at their **first** keyframe: off-position and fully
|
||||
transparent. The keyframes say they slide (620,108)→(440,108) and (403,267)→
|
||||
(583,267) while fading 0x00→0xff, and then hold that pose for their last three
|
||||
keyframes including the untimed one.
|
||||
|
||||
`/reborn/docs/re/captures/main-menu-oracle.png`, a capture of the running game,
|
||||
**shows them**: the bright circuit-frame bracket around the menu, with a ring at
|
||||
the bottom right. Cropping the same 250×180 region from the capture and from
|
||||
both renders puts the ring and its elbow trace in the port's timeline render
|
||||
**pixel-aligned with the game's**, and absent from the `rest` render. That is
|
||||
geometry, not luminance, so it does not depend on the capture's gamma or on the
|
||||
fact that it was taken with `NEW GAME` focused.
|
||||
|
||||
### Why the decoders get it wrong, precisely
|
||||
|
||||
`ui_layout::rest_plateau` excludes a run of identical keyframes that **ends the
|
||||
group**, because that run is normally the exit — the comment cites the pause
|
||||
menu, where taking the trailing run erased the word PAUSE. That exclusion is
|
||||
right in general and wrong for an element with **no exit animation**, where the
|
||||
trailing run *is* the hold. The rule then falls back to an earlier run, which
|
||||
for a slide-in is the invisible pre-roll.
|
||||
|
||||
The condition that identifies the affected elements exactly, with no false
|
||||
positives in this export, is:
|
||||
|
||||
> the final untimed keyframe has the **same pose** as the last timed keyframe
|
||||
|
||||
Six elements match it and `rest` misses all six: `ptframe1`/`ptframe2` on
|
||||
`main_menu` and `main_menu_jp`, and `pteff02` on `title` and `title_jp`. This is
|
||||
a **finding for the RE agent** about `sylpheed-formats`, not something this port
|
||||
fixes: the decoders are pinned and must not be reimplemented here. The port
|
||||
simply does not use `rest` — it derives the arrived pose from the keyframes,
|
||||
which needs no heuristic — and `verify-screen` still asks for `--pose=rest` so
|
||||
that renderer-vs-renderer diffing compares like with like.
|
||||
|
||||
Note what this says about P1: the port and the reference renderer **agreed** on
|
||||
`main_menu` to 3/255, and both were missing two elements the game draws. Two
|
||||
renderers reading the same field through the same decoder agreeing is not
|
||||
evidence that the field is right. `docs/BLOCKED.md` had already said that about
|
||||
the pivot; here it bit for real.
|
||||
|
||||
## The title is not settled, and P2 does not claim it
|
||||
|
||||
`title` and `title_jp` differ between the two modes by much more (max 142 and
|
||||
247), and there the disagreement is **not** the six-element bug alone. `rest`
|
||||
picks a mid-timeline hold for several glows (`pteff01`, `ptlogoall_eff`,
|
||||
`ptlogoall_eff2`, `ptlogo_back2eff5`) where the timeline runs on to a much
|
||||
brighter pose.
|
||||
|
||||
I could not settle which is right, and did not try to make the numbers agree:
|
||||
|
||||
* No element's alpha ever reverses direction anywhere in this export, so the
|
||||
title's 4.48 s timeline is a slow one-way ramp, not a pulse — which removes the
|
||||
obvious reason to expect a loop, but does not prove there is none.
|
||||
* The only live title capture composites the **`PRESS Ⓐ` plate (build 2) over
|
||||
the title (build 4)**, so it cannot be diffed against build 4 alone. Mean
|
||||
luminance is oracle 64.1, `rest` 62.8, timeline 80.0 — which looks like it
|
||||
favours `rest`, except that the plate *adds* brightness and `rest` is carrying
|
||||
a 25 % black dim quad (`pteff02`) that is itself one of the six misidentified
|
||||
elements. The comparison is confounded in both directions and settles nothing.
|
||||
* **Both modes are visibly wrong anyway.** Side by side with the capture, the
|
||||
port draws a washed-out cyan glow slab across the logo that the running game
|
||||
does not have — in `rest` mode too. That is a third problem, independent of
|
||||
this one, and it is P3's.
|
||||
|
||||
So: the timeline is the default because it is derived from the disc's own
|
||||
keyframes with one measured constant and no heuristic, and because it is proven
|
||||
right on the screen this milestone gates. On the title it is **unverified**, and
|
||||
P3 should not assume P2 settled it.
|
||||
|
||||
Reference in New Issue
Block a user