handoff: Q2 enumerated six of eight screens and mis-paired the splashes
sylpheed-port caught that a reader counting the Q2 row gets twelve entries with no slot for the boot splashes -- in a row already corrected once for an ordinal-versus-entry error. Verified off the disc: the splashes are 10/13 (palogo_sqex, publisher) and 11/14 (palogo_gamearts/seta/anima, developer). The row said 'in entry space 10/11 are the publisher and developer splashes', which names one half of each of two different pairs rather than a pair. All eight screens now enumerated, with the per-entry names committed as reference data. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
14
crates/sylpheed-formats/examples/gp_title_entry_names.rs
Normal file
14
crates/sylpheed-formats/examples/gp_title_entry_names.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
||||
use std::path::PathBuf;
|
||||
fn main(){
|
||||
let root=PathBuf::from(std::env::var("SYLPHEED_DISC").unwrap());
|
||||
let ar=PakArchive::open(root.join("dat/GP_TITLE.pak")).unwrap();
|
||||
for (i,e) in ar.entries().iter().enumerate(){
|
||||
let Ok(by)=ar.read(e) else { println!("{i:2} <unreadable>"); continue };
|
||||
let names: Vec<String> = ui_layout::parse_build(&by)
|
||||
.map(|b| b.sprites.keys().take(2).cloned().collect()).unwrap_or_default();
|
||||
let rec: Vec<String> = ui_layout::parse_build(&by)
|
||||
.map(|b| b.records.keys().take(2).cloned().collect()).unwrap_or_default();
|
||||
println!("{i:2} {} B sprites {:?} records {:?}", by.len(), names, rec);
|
||||
}
|
||||
}
|
||||
@@ -1599,7 +1599,7 @@ discovered it after re-exporting. ❔ The sweeps may simply be a small term, and
|
||||
| | Question | State | Answer / link |
|
||||
|---|---|---|---|
|
||||
| Q1 | keyframe time unit + ramp shape | ✅ answered | ramp is **linear**; **2 units per rendered frame**; **`1 unit = 1/60 s` — measured**, 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). ✅ **The group timeline is now DECODED too (2026-08-29) and the gap is closed**: a placement group is `frames` records of `{u32 time; 36-byte pose}` after an 8-byte header, so a pose's time is the word **before** it, pose 0's time is the group's lead-in word, and **every** pose is timed — including the last, which nothing could time before. Disc-wide over 13 991 groups with controls; the old reading makes **0 of 1 042** multi-segment alpha ramps constant-rate against 857 of 1 540. `SYLPHEED_KF_TIME_SHIFT` is retired (it had the association right but left pose 0 untimed, which is the whole reason it appeared to cost 13.1 % of build 7). Static renders are byte-identical — [`ui-keyframe-record-layout.md`](../re/ui-keyframe-record-layout.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`, and ✅ **pak entries 0/1 and 12/15 are the LOADING screen** — two variants, plain and dressed, decoded from their `pgloading_*` element names (2026-08-29). ⚠️ **Read that in ENTRY space.** This row said "0/1 and 10/11" until 2026-08-29; that is true only of `screen list`'s ordinals, where 10→entry 12 and 11→entry 15. In entry space 10/11 are the **publisher and developer splashes** (`palogo_sqex`, `palogo_gamearts`). The port caught it; see [METHOD](../re/METHOD.md#mechanics-that-have-bitten). 🟡 which of the two is `LOADING` vs `LOADING2` is undecided; 🟡 the English member of a pair is the one in the first half of the data segment — [`ui-title-build-map.md`](../re/ui-title-build-map.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`, and ✅ **pak entries 0/1 and 12/15 are the LOADING screen** — two variants, plain and dressed, decoded from their `pgloading_*` element names (2026-08-29). ⚠️ **Read that in ENTRY space.** This row said "0/1 and 10/11" until 2026-08-29; that is true only of `screen list`'s ordinals, where 10→entry 12 and 11→entry 15. In entry space the splashes are **10/13** (`palogo_sqex`, publisher) and **11/14** (`palogo_gamearts`/`palogo_seta`/`palogo_anima`, developer) — ~~"in entry space 10/11 are the publisher and developer splashes"~~ was **wrong** (2026-08-30): 10 and 11 are one half each of two *different* pairs, not a pair. 🔴 **And this row enumerated only six of the eight screens** — `sylpheed-port` caught that a reader counting it gets twelve entries with no slot for the splashes, in a row already corrected once for an ordinal-versus-entry error. **All eight, verified off the disc** (`examples/gp_title_entry_names.rs`): 0/1 loading plain, 2/3 the plate, 4/7 title art, 5/8 main menu, 6/9 `EXTRAS`, **10/13 publisher splash**, **11/14 developer splash**, 12/15 loading dressed = 8 × 2 = 16. The port caught it; see [METHOD](../re/METHOD.md#mechanics-that-have-bitten). 🟡 which of the two is `LOADING` vs `LOADING2` is undecided; 🟡 the English member of a pair is the one in the first half of the data segment — [`ui-title-build-map.md`](../re/ui-title-build-map.md) |
|
||||
| Q3 | paint order for the six screens | ✅ answered, ❔ tie-break | **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). ⚠️ **The key does not fully order a screen**: elements sharing a key are tied, and the tie-break is ❔ **undecodable from the bundle** — declaration table, `T8aD` header (exhaustive: every offset 0x00–0x7f at u8/u16/u32, both directions, **0** fields match the measured order against **64** for the control) and the RATC child order all give the same order the game does *not* use. ✅ **Your exposure is now measured at ZERO PIXELS (2026-08-29).** The 2 overlapping tied pairs on `EXTRAS` are `ptframe3`×`ptframe4` (the other is a `loop*` you never draw), and rendering the screen with that pair swapped changes **0 px** — because the two sprites put ink on ~3 600 pixels each and **share none of them**; the 102×132 "overlap" was a bounding-box artefact. Same on the main menu's `ptframe1`×`ptframe2`. This is blend-independent: layers that never touch the same pixel cannot be ordered wrongly. **Nothing about the tie-break can change a pixel on any of your five screens** — [`structures/ui-paint-order-derived-check.md`](../re/structures/ui-paint-order-derived-check.md) |
|
||||
| Q4 | button → GamePart | ✅ answered | **measured** which screen all **5** buttons open, by pressing each one and reading the screen's own title off the framebuffer. ✅ **In the form you need it: exactly ONE main-menu button opens a `GP_TITLE` entry.** `EXTRAS` → **entry 6** (EN) / **9** (JP). The other four leave the archive: `NEW GAME` → `DIFFICULTY` → `SELECT DATA`; `LOAD GAME` → the save-slot list; `TUTORIAL` → the lesson list; `OPTIONS` → GAME/CONTROL/SOUND/SCREEN SETTINGS. None of those four is a `GP_TITLE` build — so a menu→submenu→back cycle inside this archive is `main menu ↔ EXTRAS` and nothing else. The **GamePart id is still a name match**, not a measurement, and 🔴 the "cheap way to measure it" this page used to point at is a dead route (the guest words are monotonic counters, not a screen id) — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
|
||||
| Q5 | navigation semantics | ✅ answered, ⚠️ **per clause** | 🔴 **This row used to open with a single `**measured**` covering six clauses of different strength, and the port's `authored/flow.json` copied that word into a `MEASURED` provenance stamp for a clause whose evidence cell reads `none`. A bundled label is exactly as strong as its weakest cell.** Split: ✅ **measured** — initial focus varies boot to boot (2× `TUTORIAL`, 2× `NEW GAME`); ⬆⬇ move **one item per press** (indirect: the 4-press wrap count only works if each press moves one) and **wrap both ends**; ⬅➡ do nothing; Ⓑ on a submenu returns to the parent **with focus restored** (4/4); Ⓑ on the main menu → **title**, ≤ 0.4 s, no loading screen (2026-08-30). ✅ **AND BOTH WEAK CLAUSES ARE NOW MEASURED (2026-08-30, later)** — you can stamp them: **no auto-repeat** (a 2.0 s held ⬇ moves the cursor exactly **once**; the counter passes its control, a single tap giving exactly 1 spike) and **Ⓑ on the title → nothing** (20 s after a delivery-confirmed Ⓑ the screen is still the title with `PRESS Ⓐ BUTTON` up — and that run waited for the **plate pulse**, the title's own settled signature, which is what the confounded earlier attempt did not). ✅ The plate **is** re-drawn after Ⓑ from the menu, ~7 s later — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
|
||||
|
||||
23
docs/re/data/gp-title-entry-names.txt
Normal file
23
docs/re/data/gp-title-entry-names.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# GP_TITLE.pak, all 16 entries, read off the disc 2026-08-30.
|
||||
# examples/gp_title_entry_names.rs -- first two sprite and record names per entry.
|
||||
# 8 screens x 2 languages: 0/1 loading plain, 2/3 the PRESS (A) plate, 4/7 title
|
||||
# art, 5/8 main menu, 6/9 EXTRAS, 10/13 publisher splash, 11/14 developer splash,
|
||||
# 12/15 loading dressed. Written because HANDOFF Q2 enumerated only six of the
|
||||
# eight and mis-paired the splashes as 10/11.
|
||||
|
||||
0 483958 B sprites ["pgloading_eff02.t32", "pgloading_processing.t32"] records ["pgloading_loop3.rat", "pgloading_loop1.rat"]
|
||||
1 483958 B sprites ["pgloading_str.t32", "pgloading_circle1.t32"] records ["pgloading_loop4.rat", "pgloading_loop3.rat"]
|
||||
2 267014 B sprites ["ptbtn00.t32", "ptbtn00f.t32"] records ["ptbtn00f.rat", "ptbtn00.rat"]
|
||||
3 267014 B sprites ["ptbtn00f.t32", "ptbtn00.t32"] records ["ptbtn00f.rat", "ptbtn00.rat"]
|
||||
4 12278666 B sprites ["ptbase2.t32", "ptlogo_back2eff4.t32"] records ["ptloop02.rat", "ptloop01.rat"]
|
||||
5 6977437 B sprites ["ptmsg.t32", "ptbtn01.t32"] records ["ptbtn02f.rat", "ptbtn01f.rat"]
|
||||
6 6549126 B sprites ["pteff22.t32", "pteff03.t32"] records ["ptbtn12.rat", "ptbtn13.rat"]
|
||||
7 13363328 B sprites ["ptlogo_eff3.t32", "ptlogo_back2.t32"] records ["ptloop01.rat", "ptlogo_eff2.rat"]
|
||||
8 6931653 B sprites ["ptframe2.t32", "ptbtn04.t32"] records ["ptbtn03f.rat", "ptbtn02f.rat"]
|
||||
9 6548438 B sprites ["ptbase.t32", "ptbtn13f.t32"] records ["ptbtn13.rat", "ptbtn11.rat"]
|
||||
10 426473 B sprites ["palogo_sqex.t32", "palogo_sqex_eff.t32"] records []
|
||||
11 999643 B sprites ["palogo_seta.t32", "palogo_gamearts_eff.t32"] records []
|
||||
12 1774639 B sprites ["pgloading_processing.t32", "pgloading_circle1.t32"] records ["pgloading_loop5.rat", "pgloading_loop3.rat"]
|
||||
13 423333 B sprites ["palogo_sqex.t32", "palogo_sqex_eff.t32"] records []
|
||||
14 999643 B sprites ["palogo_gamearts.t32", "palogo_gamearts_eff.t32"] records []
|
||||
15 1774639 B sprites ["pgloading_baseeff.t32", "pgloading_ring.t32"] records ["pgloading_loop1.rat", "pgloading_loop4.rat"]
|
||||
Reference in New Issue
Block a user