From 2477d17885ee420a8fa686005bfc2984039ca8d7 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Tue, 18 Aug 2026 21:05:39 +0000 Subject: [PATCH] docs/re: re-refute the time orderings on the right build, and kill a Y-sort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two of the paint-order refutations were computed with build 7's keyframe times, and build 7 is not the build the game runs. Re-checked on build 4: both still fail, on the same element (ptlogo1 paints after ptlogo_back2 though it starts at t=26 against t=66, and rests at t=42 against t=80). A new candidate is recorded and refuted rather than left implicit, because it is the kind that gets adopted on partial agreement: painter's order by resting Y reproduces the captured order to within a single transposition — and is wrong twice, on ptlogo_tm (drawn before a sprite 63 px higher) and on the background (drawn first, though its resting Y would sort it fourth). Also scoped, not walked: the guest-code avenue. The splash item vtable 0x820b30b4 is real (25 slots, three construction sites); RTTI carries no class names anywhere in the binary; the format tags are fourcc immediates behind a virtual call, not strings; and the obvious shortcut — searching for the 60-byte declaration stride — leads to a time-string parser, not the table. --- docs/re/BACKLOG.md | 21 ++++++++++ docs/re/ui-title-paint-order-capture.md | 51 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 6711e59f..2c83b8f3 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -175,6 +175,27 @@ had to be cleared to establish that much — see [`canary-scripted-input-traps.md`](canary-scripted-input-traps.md), which also carries the reproduction and the fix for two of them. +### 2026-08-18 (fourth pass) — the crash is named, and the code avenue is scoped + +The crash PC resolves to an MSVC `std::map`/`set` erase that throws +`'invalid map/set iterator'` — a 40-second reproduction of the Ready-Room +crash, in [`title-crash-stl-tree.md`](title-crash-stl-tree.md). That is a +by-product of this item, and it belongs to whoever picks up the crash bisection. + +For the ordering itself, three more negatives, all recorded in +[`ui-title-paint-order-capture.md`](ui-title-paint-order-capture.md): the two +time-based orderings were re-checked against **build 4** (the previous pass used +build 7's numbers, and build 7 is not what runs) and both still fail on the same +element; and a fresh candidate — painter's order by resting **Y** — reproduces +the capture to within a single transposition but is refuted by `ptlogo_tm` and by +the background, so it is not the rule either. + +The code avenue is scoped rather than walked: the splash item vtable +`0x820b30b4` is real (25 slots, three construction sites), RTTI carries **no** +class names disc-wide, and the format tags are fourcc immediates behind a virtual +call rather than strings — so this needs a deliberate read of the UI engine, not +a keyword search. + ## Capital ships assemble wrong in the viewer diff --git a/docs/re/ui-title-paint-order-capture.md b/docs/re/ui-title-paint-order-capture.md index d1c51b45..0e7275d1 100644 --- a/docs/re/ui-title-paint-order-capture.md +++ b/docs/re/ui-title-paint-order-capture.md @@ -213,3 +213,54 @@ sequence across frames, no bound-texture identity, and de-dups on a key that happens not to collide here only because the game rebuilds its UI vertex buffer every frame. But "it cannot see UI draws" was wrong, and the cost of the new hook was justified with a wrong reason. + +--- + +## The refutations, re-checked against the build the game actually runs + +The two time-based orderings were first refuted with build 7's numbers, and build +7 is not what runs. Re-checked on **build 4**, both still fail, and by the same +element: + +| ordering | build 4 values, in the observed paint order | verdict | +|---|---|---| +| first keyframe time | bg 0, `back2eff5` 62, `back2` 66, **`logo1` 26**, `tm` 98, **`logo2` 26**, `copyright` 138 | not monotonic — refuted | +| resting keyframe time | `back2eff5` 74 / `back2eff` 66, `back2` 80, **`logo1` 42**, `tm` 116, **`logo2` 42**, `copyright` 160 | not monotonic — refuted | + +**A new candidate, and its counterexamples.** Painter's order by *screen depth* +would be the obvious runtime rule, and sorting the identified sprites by resting +**Y** very nearly reproduces the capture: + +``` +sorted by rest Y : back2eff5 117, back2 126, logo1 186, logo2 315, tm 378, copyright 655 +captured order : back2eff5, back2, logo1, tm, logo2, copyright +``` + +— one transposition away. It is still **refuted**, twice over: `ptlogo_tm` +(y 378) is painted before `ptlogo2` (y 315), and the full-screen background is +painted *first* although `ptbase2`'s resting Y (180) would sort it after both +`back2` elements. Recorded because "nearly sorted by Y" is the kind of result +that gets adopted as a rule if only the agreeing five are counted. + +## A foothold in the guest code, and what it is not + +The remaining avenue is the code, and `xenia-rs/sylpheed.db` is in the container. +What is established so far is small, and stated so it is not mistaken for more: + +* **The item class from the splash-era work is real.** Vtable `0x820b30b4` is + class `ANON_Class_03A0925F` with **25 slots**, constructed at three sites + (`sub_823CB2A0`, `sub_823CB558`, `sub_823CBB90`, each with a single caller). +* **RTTI carries no names.** All 851 classes in the database are + `ANON_Class_########`; the retail binary has the RTTI structure but not the + type names, so nothing can be found by searching for "screen" or "sprite". +* **The format tags are immediates, not strings.** `RATC` appears as + `addis 0x5241` / `ori 0x5443` in ~10 functions in the `0x82188`–`0x821B1` + range, always loaded into `r4` before a **virtual** call — e.g. `sub_821881D8` + does `obj->slot1('RATC', &out)`, then passes the result to `sub_82187B78`. So + the container walk is behind an interface, and a plain string search for + `.rat` / `.t32` finds nothing (2 hits disc-wide, both unrelated). +* **A dead end worth recording:** searching for the declaration table's 60-byte + stride (`mulli rX, rY, 60`) finds 49 sites, and the most promising, + `sub_821B4498`, turns out to be a **time-string parser** (`MM:SS.mmm` — it + splits on `:` and `.` and multiplies by 60, then 100). The guest does not + necessarily index that table with a multiply at all.