docs/re: re-refute the time orderings on the right build, and kill a Y-sort

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.
This commit is contained in:
Sylpheed RE agent
2026-08-18 21:05:39 +00:00
parent ab8a0d9e6d
commit d521c802ad
2 changed files with 72 additions and 0 deletions

View File

@@ -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<T> 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

View File

@@ -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.