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.
3.4 KiB
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)thenget 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.