docs/re: find the guest's UI quad class from the layout the capture measured

The capture pinned the UI vertex exactly — prim 13, stride 24, float3 position at
+0, k_8_8_8_8 colour at +12, float2 UV at +16 — so the binary was searched for
code that writes that shape. Fifteen candidates; the tightest, sub_82250138, is
unambiguous: it asks a renderer for 4 vertices of primitive type 13, then writes
x/y/z, colour 0xFFFFFFFF at +12, u/v at +16/+20, stepping by 24. Every constant
matches something measured rather than assumed.

Its caller is a constructor that installs vtable 0x820A7264
(ANON_Class_AAFDBF89, 2 slots) — the UI quad/sprite class.

Recorded with equal weight: this is NOT what the search was for. The chain up
from it ends at sub_821A8578, which turns out to be an unrolled run of ~30
identical call triplets — a fixed subsystem sequence, not an element walk. No
function that iterates screen elements has been found, and nothing here bears on
the paint order yet.
This commit is contained in:
Sylpheed RE agent
2026-08-19 01:16:14 +00:00
parent cbdf09bd90
commit 20b1a734de

View File

@@ -0,0 +1,78 @@
# The guest's UI quad class — a foothold found from the capture's vertex layout
**Status:** 🟡 `PROBABLE` for the identification below (it is a static read, but
the layout it matches was *measured* first). ❔ the element walk that decides
paint order is **not** in this note — that is what the search was for, and it was
not reached.
## How it was found
The runtime capture says exactly what a UI vertex looks like:
`prim = 13` (quad list), stride **24**, attributes `57@0` (`k_32_32_32_FLOAT`
position), `6@12` (`k_8_8_8_8` colour), `37@16` (`k_32_32_FLOAT` UV). That is a
fingerprint a store sequence in the guest must match, so the binary was searched
for functions that write floats at +0/+4/+8, a word at +12, floats at +16/+20,
and advance a pointer by 24 (`sylpheed.db`, 15 candidates ranked by how many of
each they contain).
The tightest match is **`sub_82250138`** (288 B, three of each store, two
`addi …, 24`), and it is unambiguous:
```
82250150 addi r5, r0, 13 ; primitive type 13 = QUAD LIST
82250154 addi r4, r0, 4 ; 4 vertices
82250158 lwz r11, 0(r31) … ; renderer->slot0(4, 13) -> allocate
82250170 lwz r11, 8(r11) … ; renderer->slot2() -> vertex pointer
82250188 addi r10, r0, -1 ; colour = 0xFFFFFFFF
82250194 stfs f13, 0(r3) ; x
82250198 stw r10, 12(r3) ; colour ← +12, as the capture says
822501A0 stfs f13, 4(r3) ; y
822501A4 addi r11, r3, 24 ; next vertex ← stride 24, as the capture says
822501AC stfs f0, 8(r3) ; z
822501B0 stfs f0, 20(r3) ; v
822501B4 stfs f0, 16(r3) ; u
```
`prim = 13`, four vertices, colour `0xFFFFFFFF` and stride 24 all match what the
title screen was measured drawing.
## What it is (and what it is not)
Its only caller, `sub_8224FB78` (752 B), is a **constructor**: it stores a vtable
pointer into `0(r29)`, zeroes a run of fields, sets a colour, and has the emitter
lay down a default quad. So `sub_82250138` builds an object's *initial* geometry
rather than drawing a frame.
The vtable it installs is **`0x820A7264`** — class `ANON_Class_AAFDBF89`, **2
slots** (`sub_8224FF98`, `sub_8224FB18`). That is the UI quad/sprite class.
**It is not the element walk.** Following the callers upward:
```
sub_82250138 (quad emitter)
└ sub_8224FB78 (constructor, installs vtable 0x820A7264)
└ sub_82222E70 (2 260 B)
└ sub_821A5F10 (756 B)
└ sub_821A8578 (3 120 B) ← a top-level render function
└ sub_821A8428 (284 B)
```
`sub_821A8578` is not data-driven: it is an **unrolled** run of about thirty
identical `bl 8217FA08 / bl 821AC450 / bl 82454918` triplets. So it sequences a
fixed list of subsystems, not a list of screen elements. The element order this
project is chasing is somewhere else — most likely behind one of those three
repeated calls, or behind the sprite class's own two vtable slots.
## Why this is worth keeping
Two reasons, neither of which is "it looks right":
* the identification is anchored to a **measurement** — the vertex layout came
from the running game first, and the search was for code that matches it;
* it names a concrete class (`0x820A7264`) and a concrete API shape
(`allocate(count, prim)` then `get vertex pointer`), which is the thing to
instrument or trace next.
**Not settled:** everything the search was actually for. No function that
iterates screen elements has been found, and nothing here bears on the paint
order yet.