From 4b5ac88f0ae5bd5e85cedabb4806b04f1cb66a95 Mon Sep 17 00:00:00 2001 From: sylph-decoder Date: Tue, 1 Sep 2026 17:19:59 +0000 Subject: [PATCH] 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. --- docs/re/INDEX.md | 1 + docs/re/data/splash-declared-timeline.txt | 57 ++++++++++ docs/re/splash-declared-vs-captured.md | 125 ++++++++++++++++++++++ docs/re/units-per-second-measured.md | 25 +++++ 4 files changed, 208 insertions(+) create mode 100644 docs/re/data/splash-declared-timeline.txt create mode 100644 docs/re/splash-declared-vs-captured.md diff --git a/docs/re/INDEX.md b/docs/re/INDEX.md index 7492dbda..f518f03f 100644 --- a/docs/re/INDEX.md +++ b/docs/re/INDEX.md @@ -137,6 +137,7 @@ files, which is how the same ground got covered twice. | [`structures/stage-mission-tables.md`](structures/stage-mission-tables.md) | The stage table set — phases, routes, sub-objectives and AI parameters | ✅ the table set and how the stage record reaches it, validated across; **`AIParams` disc-wide: 23 objects, one shared 34-profile roster (782 records), loader `sub_8233C368`; `Type`→field-count holds except the two `_Test` templates** | | [`structures/texture-color-k8888.md`](structures/texture-color-k8888.md) | Texture colour interpretation — `k_8_8_8_8` (32bpp UI/HUD textures) | — | | [`ui-keyframe-time-unit.md`](ui-keyframe-time-unit.md) | What a keyframe time is worth, and what shape the ramp has | ✅ CONFIRMED from the running game's own draw stream — the ramp is **linear** (a declared 15-unit fade lands on `round(255·k/15)` for all seven samples) and the animation clock advances **2 time units per submitted frame**. 🟡 the seconds conversion (`1 unit = 1/60 s`) rests on a measured 27.6 present-frames/second | +| [`splash-declared-vs-captured.md`](splash-declared-vs-captured.md) | Does the declared keyframe timeline reproduce the captured splash, and is the unit rate global? | ✅ **YES, to ONE alpha level, 2026-09-01** — settles the R1-re-opened 🟡 `⟨our-reader⟩` entry with a disc-table-vs-vertex-stream comparison, **no renderer in the chain**. 50 captured alphas: 39 exact under truncation (30 under rounding), **max error 1 level in 255 (0.39 %)**, and all 11 non-exact are low by exactly 1 on falling segments. The old ❌ rested on an `a=32` that the fixed record layout puts at t=206, four units from the end. 🔴 **AND: the unit→seconds rate is PER-GAMEPART.** Title ~**57** units/guest-second; splash **~35–40**, confirmed two ways sharing no algebra — a 15-unit ramp *and* a **160-unit hold**, which has no `T` in it. The near-equal α/s across all four elements (650–679) is a coincidence: `T` 22-vs-15 and rate 57-vs-37 nearly cancel. ⚠️ A single `keyframe_units_per_second` is wrong; a splash played at 60 runs **1.5–1.7× too fast**. Classified **measured** — nothing on the disc states a rate. | | [`units-per-second-measured.md`](units-per-second-measured.md) + [pre-reg](units-per-second-preregistration.md) | Is the animation clock frame-counted or time-integrated, and at what rate | 🟡 **half-answered, 2026-09-01, one prediction HELD and one FAILED.** ✅ **The clock is NOT frame-counted**: the same animation takes 21 labels in one capture and 33 in another, and splash A's logo steps `+136,+34` in one and `+17,+51,+34,+34,+17,+17` in the other. Steps are always integer multiples of **17** (255/15 = one unit), so the clock advances in whole units at a rate set by frame duration. 📌 **This retires "2 units per submitted frame" as a MECHANISM** — 2 was that run's frame pacing, so `units = 2 × frames` computes an emulator artefact. ✅ **RESOLVED later the same iteration: 56.8 units per guest second**, on `ptbtn00`'s ramp with the clamped final step excluded, `T=22` attested by two readers with no clock in the chain — **inside the pre-registered 55–65 band; 30 and 120 both excluded**. Control passed at **1.15 %**: `ptcopyright` gives 650.4 α/s against the plate's 657.9, implying its own `T=22.25`. The earlier 29.9 was a borrowed `T=15` that does not apply to those elements (implied `T` there is 23–34). ⚠️ `60` is **not** refuted — 5.6 % away against ~5 % quantisation — so the port keeps it; but the unit constant is eliminated as a cause of a late plate (t=236 → 4.15 s vs the port's 3.93 s, i.e. fractionally *early*). Instrument: guest timebase (50 MHz, scalar 1.0), control passed — 123.24 guest s over ~118 wall s. | | [`h3-units-per-frame-measured.md`](h3-units-per-frame-measured.md) | How many keyframe units elapse per guest frame, and which declared time the title's settle anchor is | ✅ **measured against a pre-registration, 2026-09-01. 2 units per guest frame**, on `ptbtn00`'s own declared ramp (`t=214→236`, T=22): three consecutive gap-free steps of **exactly 23** = 255×2/22, ramp span 10 labels against a predicted 11 (±1). The Port's inferred **5 is excluded by >2×**. 🔴 Why 5 appeared: **an alpha step is not a clock rate** — `Δα/frame = 255·(units/frame)/T`, so splash B's 34-with-T=15 and the plate's 23-with-T=22 are ONE clock. Also: the **title settle anchor is t≈160**, not t=118 — it is `ptcopyright`, the last build-in element and the only glyph one, full at label 5350 → t≈168–176. 🔴 **units/SECOND is NOT settled** and two of my own captures disagree ~2.9× on it; the gap is in frames→seconds, not units→frames. | | [`h3-units-per-frame-preregistration.md`](h3-units-per-frame-preregistration.md) | The prediction, committed before the capture was read | ✅ kept as the control on the row above | diff --git a/docs/re/data/splash-declared-timeline.txt b/docs/re/data/splash-declared-timeline.txt new file mode 100644 index 00000000..787eaf98 --- /dev/null +++ b/docs/re/data/splash-declared-timeline.txt @@ -0,0 +1,57 @@ +# The developer splash's DECLARED keyframe timeline, off the disc, under the FIXED +# record layout (ui-keyframe-record-layout.md). Reader: sylpheed-cli screen info +# --all --build 11 --geometry, built from this checkout. + +build [11] 1280x720 7 elements 6 sprites +# element parent kind pivot kf rest / keyframes +0 palogo_eff0.prm - 0x10 (640,360) 1 (0,0) +1 palogo_gamearts.t32 - 0x0 (250,36) 7 rest (390,164) t=30 [0:390,164 15:390,164 30:390,164 190:390,164 194:390,164 206:390,164 210:390,164] +2 palogo_gamearts_eff.t32 - 0x0 (260,46) 4 rest (379,154) t=15 [0:379,154 15:379,154 30:379,154 45:379,154] +3 palogo_seta.t32 - 0x0 (120,44) 7 rest (521,316) t=30 [0:521,316 15:521,316 30:521,316 190:521,316 194:521,316 206:521,316 210:521,316] +4 palogo_seta_eff.t32 - 0x0 (130,55) 4 rest (511,305) t=15 [0:511,305 15:511,305 30:511,305 45:511,305] +5 palogo_anima.t32 - 0x0 (194,68) 7 rest (446,449) t=30 [0:446,449 15:446,449 30:446,449 190:446,449 194:446,449 206:446,449 210:446,449] +6 palogo_anima_eff.t32 - 0x0 (204,78) 4 rest (435,440) t=30 [0:435,440 15:435,440 30:435,440 45:435,440] + +placement-region group order: [0, 1, 2, 3, 4, 5, 6] (== declaration order) +RATC child order: ["T8aD:palogo_gamearts.t32", "T8aD:palogo_gamearts_eff.t32", "T8aD:palogo_seta.t32", "T8aD:palogo_seta_eff.t32", "T8aD:palogo_anima.t32", "T8aD:palogo_anima_eff.t32"] + +geometry — decoded sprite size vs the declared pivot, and every keyframe +# sprite decoded pivot*2 same keyframes t: x,y sx%,sy% a=alpha r=rot° +0 — — 1280x720 - 0: 0,0 100%,100% a=255 +1 palogo_gamearts.t32 500x71 500x72 NO 0: 390,164 100%,100% a=0 15: 390,164 100%,100% a=0 30: 390,164 100%,100% a=255 190: 390,164 100%,100% a=255 194: 390,164 100%,100% a=232 206: 390,164 100%,100% a=32 210: 390,164 100%,100% a=0 +2 palogo_gamearts_eff.t32 521x91 520x92 NO 0: 379,154 100%,100% a=0 15: 379,154 100%,100% a=255 30: 379,154 100%,100% a=255 45: 379,154 100%,100% a=0 +3 palogo_seta.t32 240x89 240x88 NO 0: 521,316 100%,100% a=0 15: 521,316 100%,100% a=0 30: 521,316 100%,100% a=255 190: 521,316 100%,100% a=255 194: 521,316 100%,100% a=232 206: 521,316 100%,100% a=32 210: 521,316 100%,100% a=0 +4 palogo_seta_eff.t32 261x110 260x110 NO 0: 511,305 100%,100% a=0 15: 511,305 100%,100% a=255 30: 511,305 100%,100% a=255 45: 511,305 100%,100% a=0 +5 palogo_anima.t32 388x136 388x136 yes 0: 446,449 100%,100% a=0 15: 446,449 100%,100% a=0 30: 446,449 100%,100% a=255 190: 446,449 100%,100% a=255 194: 446,449 100%,100% a=232 206: 446,449 100%,100% a=32 210: 446,449 100%,100% a=0 +6 palogo_anima_eff.t32 407x156 408x156 NO 0: 435,440 100%,100% a=0 15: 435,440 100%,100% a=255 30: 435,440 100%,100% a=212 45: 435,440 100%,100% a=0 + +# ---- and the PRESS (A) plate, build 2, for the T=22 the rate rests on ---- + +build [2] 1280x720 1 elements 2 sprites +# element parent kind pivot kf rest / keyframes +0 ptbtn00.rat - 0x73002 (256,25) 5 rest (383,550) t=236 [0:383,560 214:383,550 236:383,550 238:383,550 244:383,550] + → focus ptbtn00f.rat + +placement-region group order: [0] (== declaration order) +RATC child order: ["T8aD:ptbtn00.t32", "T8aD:ptbtn00f.t32", "RATC:ptbtn00.rat", "RATC:ptbtn00f.rat"] + +geometry — decoded sprite size vs the declared pivot, and every keyframe +# sprite decoded pivot*2 same keyframes t: x,y sx%,sy% a=alpha r=rot° +0 ptbtn00.t32 513x50 512x50 NO 0: 383,560 100%,100% a=0 214: 383,550 100%,100% a=0 236: 383,550 100%,100% a=255 238: 383,550 100%,100% a=255 244: 383,550 100%,100% a=0 + +# ---- publisher splash, build 10 ---- + +build [10] 1280x720 3 elements 2 sprites +# element parent kind pivot kf rest / keyframes +0 palogo_eff0.prm - 0x10 (640,360) 1 (0,0) +1 palogo_sqex.t32 - 0x0 (330,30) 7 rest (309,330) t=30 [0:309,330 15:309,330 30:309,330 235:309,330 239:309,330 251:309,330 255:309,330] +2 palogo_sqex_eff.t32 1 0x1 (341,41) 4 rest (299,319) t=30 [0:299,319 15:299,319 30:299,319 45:299,319] + +placement-region group order: [0, 1, 2] (== declaration order) +RATC child order: ["T8aD:palogo_sqex.t32", "T8aD:palogo_sqex_eff.t32"] + +geometry — decoded sprite size vs the declared pivot, and every keyframe +# sprite decoded pivot*2 same keyframes t: x,y sx%,sy% a=alpha r=rot° +0 — — 1280x720 - 0: 0,0 100%,100% a=255 +1 palogo_sqex.t32 666x68 660x60 NO 0: 309,330 100%,100% a=0 15: 309,330 100%,100% a=0 30: 309,330 100%,100% a=255 235: 309,330 100%,100% a=255 239: 309,330 100%,100% a=232 251: 309,330 100%,100% a=32 255: 309,330 100%,100% a=0 +2 palogo_sqex_eff.t32 686x89 682x82 NO 0: 299,319 100%,100% a=0 15: 299,319 100%,100% a=255 30: 299,319 100%,100% a=212 45: 299,319 100%,100% a=0 diff --git a/docs/re/splash-declared-vs-captured.md b/docs/re/splash-declared-vs-captured.md new file mode 100644 index 00000000..72a86ba0 --- /dev/null +++ b/docs/re/splash-declared-vs-captured.md @@ -0,0 +1,125 @@ +# 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. diff --git a/docs/re/units-per-second-measured.md b/docs/re/units-per-second-measured.md index 9231a9ba..8a3d6373 100644 --- a/docs/re/units-per-second-measured.md +++ b/docs/re/units-per-second-measured.md @@ -210,3 +210,28 @@ if you already know the step is one unit, and nothing said it was. splash elements is the way to close that, and it is static work. * 🟡 The **structured residual** — long frames advancing less than a constant rate predicts — is untouched and still unexplained. + +--- + +# 🔴 CORRECTED the next iteration — the rate is **per-GamePart**, and this page's `T` reasoning was backwards + +[`splash-declared-vs-captured.md`](splash-declared-vs-captured.md) reads the +splash's declared `T` **off the disc** instead of inferring it: + +* `palogo_gamearts` ramps `t=15 → t=30`. **`T = 15`, plainly.** This page's + *"the splash elements' implied `T` is 23–34, none of them 15"* is **wrong** — + it was derived by assuming one global rate, which is the premise that failed, + not the `T`. +* Measured on the splash: **~35–40 units/guest-second**, against the title's + 56.8. Confirmed two ways that share no algebra — a 15-unit ramp *and* a + **160-unit hold**, which contains no `T` at all. + +**So `56.8` is the title's rate, not the game's.** Everything on this page about +*method* stands — the clock is time-integrated, the clamped final step must be +dropped, the guest timebase is the right instrument. The **number** has a +narrower reach than this page claims. + +⚠️ And the near-equality of α/s across all four elements (650–679, ±2 %) is a +**coincidence** that reads exactly like one clock: `T` differs 22 vs 15 and the +rates differ 57 vs 37, and the two ratios nearly cancel. +