Files
Sylpheed/docs/re/splash-declared-vs-captured.md
sylph-decoder 43a57379f1 re: the declared timeline DOES reproduce the splash -- and the unit rate is per-GamePart
Two results, one of which corrects me.

1. The R1-re-opened 'declared keyframe timeline reproduces the captured
splash' resolves in FAVOUR of the declared timeline. Instrument is a disc
keyframe table against the guest's vertex stream -- no renderer in the chain,
which is what the 'our-reader' tag demanded. Calibration-free test: is each
captured alpha an exact member of the declared piecewise-linear value set at
integer t? 39/50 exact under truncation, 30/50 under rounding, and the worst
error under either rule is ONE alpha level in 255. All 11 non-exact samples
are low by exactly 1 and all are on falling segments. The old refutation
rested on 'still at a=255 nine frames after its declared a=32' -- under the
fixed layout a=32 is at t=206, four units from the end of a 210-unit
timeline. That was the off-by-one association.

2. The unit->seconds rate is PER-GAMEPART, which corrects what I told the
port an hour ago. Title ~57 units/guest-second; splash ~35-40. The splash
figure is confirmed two ways that share no algebra: a 15-unit ramp (T read
off the disc, not borrowed) and a 160-unit HOLD, which is a declared
duration with no T, no alpha slope and no interpolation in it.

And my 'the borrowed T=15 does not apply' was wrong in the other direction:
the disc says T=15 plainly. What failed was the premise of a single global
rate, not the T. Noted at the foot of that page rather than by editing it.

The trap worth recording: all four elements give 650-679 alpha/s, agreeing
to 2%, which reads exactly like one clock. It is a coincidence -- T differs
22 vs 15 and the rates differ 57 vs 37, and the ratios nearly cancel. A
quantity that looks constant across screens is not evidence of one clock
when the thing that would vary is inside it. The hold breaks the tie.

For the port: a single keyframe_units_per_second cannot be right, and a
splash played at 60 runs 1.5-1.7x too fast -- shorter, sharper fades than
the game's, which is the direction the play-test reported.
2026-09-01 17:19:59 +00:00

126 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The declared timeline **does** reproduce the captured splash — and the unit rate is **per-GamePart**
**Status: ✅ two results, one of which corrects me.** 2026-09-01.
Instrument: ⟨disc⟩ for the declared side, ⟨capture⟩ for the observed side.
**No renderer is anywhere in this comparison** — it is a keyframe table against a
vertex stream.
Settles the R1-re-opened entry *"the declared keyframe timeline reproduces the
captured splash"*, 🟡 `⟨our-reader⟩`, whose stated condition was *"re-derive the
declared timeline under the fixed record layout and re-compare against the same
frames."*
---
## 1 ✅ The declared timeline reproduces the capture to **one alpha level**
Declared, off the disc ([`data/splash-declared-timeline.txt`](data/splash-declared-timeline.txt)),
`GP_TITLE` build 11:
| family | declared keyframes |
|---|---|
| logos (`palogo_gamearts`, `_seta`, `_anima`) | `0:a=0 15:a=0 30:a=255 190:a=255 194:a=232 206:a=32 210:a=0` |
| glows (`_gamearts_eff`, `_seta_eff`) | `0:a=0 15:a=255 30:a=255 45:a=0` |
| `palogo_anima_eff` | `0:a=0 15:a=255 **30:a=212** 45:a=0` |
Captured: the per-quad vertex alphas from the draw stream
([`data/splash-quad-timeline.txt`](data/splash-quad-timeline.txt)).
**Test — deliberately calibration-free.** No fitting, no clock, no lag search:
*is each captured alpha an exact member of the declared value set*, i.e. equal to
the declared piecewise-linear α(t) at some integer t?
| | |
|---|---|
| samples | **50** |
| exact members under **truncation** | **39 / 50** |
| exact members under **rounding** | 30 / 50 |
| **worst error under either rule** | **1 alpha level out of 255 — 0.39 %** |
| samples off by more than one level | **0** |
**Every one of the 11 non-exact samples is low by exactly 1**, and every one of
them is on a *falling* segment. Truncation fits better than rounding by 9
samples, which is what an integer interpolator that floors rather than rounds
looks like.
📌 **So the entry resolves in favour of the declared timeline.** The old ❌ rested
on *"`palogo_gamearts` is still at `a=255` nine frames after its declared
`a=32`"* — under the fixed record layout `a=32` is at **t=206**, four units from
the end of a 210-unit timeline, not early. That was the off-by-one association,
exactly as the R1 note suspected.
🟡 **What is not settled:** *why* 11 samples floor one low while 39 do not. The
residual is one level and is named, not hidden. A candidate is that the clock is
fractional and α is floored, so a sample lands one low whenever the fraction is
small — untested.
## 2 🔴 The unit→seconds rate is **per-GamePart**, and I told the port otherwise
This is the correction, and it matters more than the first result.
An hour ago I reported **56.8 units per guest second** off the plate and wrote
that the reach was the title. The splash now has its own measurement, from the
disc-declared `T` rather than a borrowed one, and **it is a different number.**
| screen | element | declared | measured | **units / guest second** |
|---|---|---|---|---|
| title | `ptbtn00` ramp | `T = 22` (`t=214→236`, ⟨disc⟩) | 657.9 α/s | **56.8** |
| title | `ptcopyright` ramp | implied `T = 22.25` | 650.4 α/s | 56.8 (control, 1.15 %) |
| splash | `palogo_gamearts` ramp | `T = 15` (`t=15→30`, ⟨disc⟩) | 664.8 α/s | **39.1** |
| splash | publisher logo ramp | `T = 15` ⟨disc⟩ | 679.4 α/s | **40.0** |
| **splash** | **`palogo_gamearts` HOLD** | **160 units (`t=30→190`) ⟨disc⟩** | 4.514 guest s | **35.4** |
### The hold is what makes this safe to say
A ramp rate is `(Δα/Δt) × T/255` and therefore depends on `T`. **The hold does
not.** It is a declared *duration* — 160 units of plateau — measured directly in
guest seconds, with no alpha slope, no interpolation and no `T` in the
arithmetic. It gives **35.4 units/s** against the same screen's ramp at 39.1, and
the two share none of their algebra.
⚠️ The hold figure is a **lower bound on the rate**: it is measured between the
first and last labels at α=255, and the true plateau extends slightly past both.
So the splash sits at **~35–40 units/s** and the title at **~57**.
### Why I nearly missed it — recorded because it is a good trap
All four elements give **650–679 α/s**, agreeing to ±2 %, which reads exactly
like one clock. It is a coincidence: `T` differs 22 vs 15 (ratio 1.47) and the
rates differ 57 vs 37 (ratio 1.54), and those two ratios nearly cancel in
`Δα/Δt`. **A quantity that looks constant across screens is not evidence of one
clock when the thing that would vary is inside it.** The hold breaks the tie
because `T` is not in it.
### And my "borrowed `T=15` does not apply" was wrong
[`units-per-second-measured.md`](units-per-second-measured.md) says the splash
elements' implied `T` is 23–34, *"none of them 15"*, derived by assuming one
rate. **The disc says `T = 15`, plainly.** The premise was the single rate, not
the `T`. Both halves of that page's arithmetic were right and its conclusion
about which term was unknown was wrong.
## What this means for the port
🔴 **A single `keyframe_units_per_second` cannot be right.** The two splashes and
the title run their timelines at rates ~1.5× apart, and the splashes are exactly
the screens the play-test called *"close but not right"*.
* title: **~57 units/s** — the port's 60 is 5 % away and stands.
* splashes: **~35–40 units/s** — a port running them at 60 plays them **1.5–1.7×
too fast**, which would make every splash fade look shorter and sharper than
the game's. That is the direction of *"the fade is more pronounced in the
game"*.
**Classified: measured**, not decoded. Nothing on the disc has been found that
*states* a rate; these are two numbers off the running game. The port authors
them and must know it is authoring.
## Reach
Two `GamePart`s, one boot each. It establishes that the rate is **not global**,
which is a negative with wide reach — one counter-example is enough. It does
**not** establish the rate for the main menu, `EXTRAS`, or any submenu, and those
must not inherit either number. ❔ Where the rate comes from — a per-`GamePart`
field, a constant in the driver, or a frame-rate target — is **not decoded**, and
that is the next question.