re: the title presents at 28.5 fps idle -- the keyframe unit is settled at

1/60 s, and the 60 Hz reading is excluded

ui-keyframe-time-unit.md named its own re-test and nobody had run it: time
300 submitted frames on the IDLE title, where nothing is streaming from
the ISO. Reaching the title is cheap now that one A skips the intro, so
this cost one boot.

Two clean trials: 300 frames in 10.40 s and 10.60 s, i.e. 28.8 and 28.3
fps. That is the same rate as the 27.6 fps measured during the loading
splash, which is exactly the page's own criterion for "the game is 30 Hz
and the unit is 1/60 s". The 60 Hz alternative is now excluded rather
than disfavoured: it needs the emulator at 47% of real time while sitting
idle on a screen the capture says costs 1526 draws over 300 frames, about
five per frame. Nothing there halves an emulator.

So the durations stand as written -- title 4.2 s, main menu 1.1 s, EXTRAS
0.87 s -- and Q1 leaves the handoff's open-residue table. It stays
MEASURED, not decoded: no field on the disc says sixtieths of a second.

One trap, and it nearly cost the conclusion. My first attempt reported
39.5 fps, which sits between the two hypotheses and would have left the
question open. It was a harness bug: I polled the log for a "done" line
rather than for the COUNT of them increasing, so it matched a capture
that had already completed and timed 0.1 s of nothing. METHOD gets the
general form -- a log-polling probe must compare a count, not test for
presence.
This commit is contained in:
Sylpheed RE agent
2026-08-28 19:11:11 +00:00
parent 2c4005795b
commit bc6354dce0
3 changed files with 61 additions and 24 deletions

View File

@@ -27,7 +27,7 @@ authored version can be deleted.
| | Question | State | Answer / link |
|---|---|---|---|
| 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) |
| Q1 | keyframe time unit + ramp shape | ✅ answered | ramp is **linear**; **2 units per rendered frame**; **`1 unit = 1/60 s` — settled**, the idle title presents at 28.5 fps so the game is 30 Hz — [`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 | ✅ 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 | ✅ answered | **measured** which screen all **5** buttons open — `NEW GAME``DIFFICULTY``SELECT DATA`, not a hang. The **GamePart id is still a name match**, not a measurement — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
@@ -76,19 +76,18 @@ authored version can be deleted.
declared 15-unit fade lands on `round(255·k/15)` for all seven of its samples,
with `k` stepping 2, 4, 6, 8, 10, 12, 14 on seven consecutive submitted frames.
**measured**, not decoded — the disc says `t=30`, it does not say what a `t` is.
The seconds conversion (`1 unit = 1/60 s`, so a 30 fps screen) rests on a
measured 27.6 present-frames/second; [`ui-keyframe-time-unit.md`](../re/ui-keyframe-time-unit.md)
names the re-test. 🟡 **A second, independent measurement now supports it**: the
transition quad is declared black from `t=0` to `t=12` — 12 units, i.e. 0.20 s
under this conversion — and a 30 fps capture measured the pure-black plateau at
**0.170.23 s** ([`screen-transitions.md`](../re/screen-transitions.md)). That
is corroboration and not proof: the plateau spans the outgoing screen's
fade-out tail as well as the incoming screen's black, and this measurement
cannot separate them.
⚠️ If the game turns out to present at 60 Hz, **every duration on this page
derived from keyframe units halves** — including Q7's declared fade-in lengths
(0.87 s / 0.97 s / 4.08 s). The wall-clock numbers measured off a capture (the
~0.4 s fade-out, the black hold, the attract timings) do not move.
**The seconds conversion is settled: `1 unit = 1/60 s`, a 30 Hz title.** The
re-test this page used to name has been run — 300 submitted frames timed on the
**idle** title (nothing loading) came out at **28.8 and 28.3 fps**, the same
rate as the 27.6 fps measured during the loading splash. The competing 60 Hz
reading is excluded: it needs the emulator at 47 % of real time while idling on
a screen that costs ~5 draws per frame.
A second, independent line agrees — the transition quad is declared black for
12 units (0.20 s under this conversion) and a capture measured the pure-black
plateau at 0.170.23 s
([`screen-transitions.md`](../re/screen-transitions.md)).
⚠️ Still **measured, not decoded**: no field on the disc says "sixtieths of a
second".
* **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,
@@ -247,7 +246,8 @@ authored version can be deleted.
## What is still open
Every question above is answered, so this is the honest residue rather than a
work queue. **None of it blocks the five screens.**
work queue. **None of it blocks the five screens.** (Q1's seconds conversion was
here until 2026-08-28 and is now settled.)
| | what | why it is stuck |
|---|---|---|
@@ -255,7 +255,6 @@ work queue. **None of it blocks the five screens.**
| ❔ | **the wave index into `Static.slb`** (Q8) | same instrumentation. This container runs `--mute=true` against an SDL dummy device, so it cannot watch the audio path at all |
| 🟡 | **the paint-order tie-break** (Q3) | eight candidates refuted; costs one element's blend on one screen |
| 🟡 | **GamePart ids behind the buttons** (Q4) | the *screens* are measured; the ids are a name match onto the executable's class names |
| 🟡 | **`1 unit = 1/60 s`** (Q1) | two independent measurements agree, neither is proof; if it is 60 Hz every keyframe-derived duration halves |
| ❔ | **the boot transitions in code** (Q6) | bounded as code-not-data, not proven. `sub_821C6458` — the substantial function in `GamePart_Title`'s neighbourhood — has **not been read** |
| ❔ | **`MS00A``S00A.wmv` never watched** (Q9) | decoded from the manifest; the one run that reached it crashed at `SELECT DATA` first |
| ❔ | **builds 0/1 and 10/11**, the `DELTASABER` plates (Q2) | never seen on screen anywhere in the boot path, the title-side screens or the attract loop |

View File

@@ -184,3 +184,9 @@ agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the
XACT string at all. The names came from the authoring tool and survived into the
shipped data. Check for the magic before committing to a parser for the format
the extension advertises.
* **A log-polling probe must compare a COUNT, not test for presence.** Timing an
operation by waiting for its "done" line in a log gives an instant false
positive if any earlier run left one there. This produced a confident
"39.5 fps" that was really 0.1 s of matching a stale line — and it disagreed
with the true 28.5 fps by enough to have flipped a conclusion. Snapshot
`log.count(marker)` before starting and wait for it to *increase*.

View File

@@ -109,14 +109,46 @@ fit are:
t = 16 … 269) is then **4.2 s**, and the main menu build (build 5, t = 12 … 80)
**1.1 s**.
**The reach of this negative:** the present rate was measured *during the boot
splash*, where the guest is also streaming from the ISO, so it is a lower bound on
the emulator's speed and cannot by itself exclude the 60 Hz reading. What would
settle it is the same 300-frame timing taken on the **idle title screen**, where
nothing is loading — if that also comes out near 28 fps the game is 30 Hz and the
unit is 1/60 s; if it doubles to ~55 fps the game is 60 Hz and every duration on
this page halves. Until then the port should treat **2 units per rendered frame**
as the measured fact and `1/60 s` as the working conversion.
**The reach of this negative** *(as written before the test below — kept for the
reasoning)*: the present rate was measured *during the boot splash*, where the
guest is also streaming from the ISO, so it is a lower bound on the emulator's
speed and cannot by itself exclude the 60 Hz reading. What would settle it is the
same 300-frame timing taken on the **idle title screen**, where nothing is
loading — if that also comes out near 28 fps the game is 30 Hz and the unit is
1/60 s; if it doubles to ~55 fps the game is 60 Hz and every duration on this page
halves.
## ✅ That test was run — 2026-08-28. The game is 30 Hz; `1 unit = 1/60 s`
Reached the title with a single Ⓐ to skip the intro
([`movie-binding.md`](movie-binding.md)), let it settle 12 s so nothing was
loading, then armed the bounded 300-frame capture and timed it to its own
`[UI-CAP] done` line:
| | 300 frames in | rate |
|---|---|---|
| idle title, trial 1 | 10.40 s | **28.8 fps** |
| idle title, trial 2 | *arm produced no capture* | — |
| idle title, trial 3 | 10.60 s | **28.3 fps** |
| *(prior)* boot splash | 10.87 s | 27.6 fps |
**~28.5 fps on an idle title — the same rate as the loading splash.** By this
page's own criterion that settles it: the title presents at **30 Hz**, the
timeline ticks at **60 units/second**, and **`1 unit = 1/60 s`**.
**The 60 Hz reading is now excluded, not merely disfavoured.** It would require
the emulator to be running at 47 % of real time *while sitting idle on a static
title* — and the capture says that screen costs **1 526 draws over 300 frames,
about 5 draws per frame**. Nothing there is expensive enough to halve the
emulator's speed, and the splash and the idle title returning the same rate is
exactly what a constant ~95 %-of-real-time emulator looks like.
So the durations on this page stand as written: title build 4 ≈ **4.2 s**, main
menu build 5 ≈ **1.1 s**, and `EXTRAS` build 6's declared fade-in ≈ **0.87 s**.
⚠️ Still **measured, not decoded** — no field on the disc says "sixtieths of a
second". What changed is that the measurement now has an idle-state control and
the competing reading is ruled out.
## What this does not say