From 2afdb32baf4dbd8beddb5ee2b5a3369c44e2e125 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 19 Aug 2026 01:46:00 +0000 Subject: [PATCH] =?UTF-8?q?docs/re:=20SOLVED=20=E2=80=94=20the=20paint=20o?= =?UTF-8?q?rder=20is=20the=20screen=20object's=20child=20array=20at=20+0x3?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The screen object holds a SECOND list of its elements, a reordering built at load time, and that list is the paint order. It is 24 pointers at +0x30, each the +0x00 field of one of the 48-byte element records, so both arrays hold the same objects in different orders. Checked against the draw capture rather than asserted: the seven elements the capture can name sit at child slots 0, 6, 7, 13, 16, 17, 22 — strictly ascending, in exactly the captured submission order. It also resolves the one sub-order no static field could explain, the pair that decodes to the same 1133x280: slot 6 is element 20 and slot 7 is element 19, so they paint 20-then-19, DESCENDING in declaration terms. And the kind=0x4 repeat instances sit immediately after their template, where the declaration table interleaves them. Stated as unsolved, because the port cannot read a runtime array: deriving this order from the bundle. The order is clearly structured rather than arbitrary — elements sharing a sprite are adjacent and the full-screen effects lead — so it is worth attacking, but it is not attacked here. --- docs/re/structures/ui-screen-runtime.md | 61 +++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/docs/re/structures/ui-screen-runtime.md b/docs/re/structures/ui-screen-runtime.md index 9bbf8d96..ac5cb2da 100644 --- a/docs/re/structures/ui-screen-runtime.md +++ b/docs/re/structures/ui-screen-runtime.md @@ -85,3 +85,64 @@ not small integers), so the obvious "draw order table" reading is already out. structure that can be dumped in seconds, rather than a code-reading exercise. The next probe is to dump `+0x24` and `+0x30` on the title build and see whether either is 24 entries in a non-declaration order. + +## ✅ The paint order is the screen object's CHILD array at `+0x30` + +**Status: `CONFIRMED`.** The question this project has carried since the first +capture — *what orders the elements, given that the declaration table does not* — +is answered: the screen object holds a **second list**, a reordering of the +elements built at load time, and that list is the paint order. + +`+0x30` is `{ptr, count, capacity}` → an array of **24 pointers** (not 12-byte +records like `+0x14`). Each pointer is the `+0x00` field of one of the 48-byte +element records, so the two arrays hold the same objects in different orders. The +permutation, read live off the title screen: + +| child slot | element | | child slot | element | +|---|---|---|---|---| +| 0 | 9 `ptbase2` | | 12 | 17 `back2eff4` | +| 1 | 11 `ptloop01` | | 13 | **0 `ptlogo1`** | +| 2 | 12 `ptloop02` | | 14 | 2 `ptlogo1` (copy) | +| 3 | 10 `pteff04` | | 15 | 4 `ptlogo1` (copy) | +| 4 | 13 `pteff02.prm` | | 16 | **7 `ptlogo_tm`** | +| 5 | 6 `pteff01` | | 17 | **1 `ptlogo2`** | +| 6 | **20 `ptlogo_back2eff`** | | 18 | 3 `ptlogo2` (copy) | +| 7 | **19 `ptlogo_back2`** | | 19 | 5 `ptlogo2` (copy) | +| 8 | 14 `back2eff1` | | 20 | 22 `ptlogoall_eff` | +| 9 | 15 `back2eff2` | | 21 | 23 `ptlogoall_eff2` | +| 10 | 18 `back2eff5` | | 22 | **21 `ptcopyright`** | +| 11 | 16 `back2eff3` | | 23 | 8 `pteff00.prm` | + +### Checked against the capture, not merely plausible + +The seven elements the draw capture can name occupy child slots + +``` +ptbase2 0 back2eff 6 back2 7 ptlogo1 13 tm 16 ptlogo2 17 copyright 22 +``` + +— **strictly ascending, in exactly the captured submission order**. Two details +make this more than a coincidence of a short list: + +* it **resolves the ambiguity** that no static field could: slot 6 is element + **20** (`ptlogo_back2eff`), slot 7 is element 19, so the pair paints + 20-then-19 — *descending* in declaration terms. Nothing in the file predicts + that, and the runtime list states it; +* the three `kind = 0x4` repeat instances of each logo sit **immediately after + their template** (slots 13,14,15 and 17,18,19), which the declaration table + interleaves (0,1,2,3,4,5). They draw at α=0 and so never appeared in the + capture, but their placement in the list is consistent with the grouping. + +### What this means for the port, stated carefully + +The reimplementation cannot read a runtime array — it has to *derive* this order +from the bundle. **That derivation is not solved.** What the order shows is +structure worth attacking: elements sharing a sprite are adjacent +(`ptlogo1`×3 together, `ptlogo2`×3 together, the `back2eff*` family together), +and the full-screen/effect elements lead. So the load-time build is doing some +grouping, not an arbitrary shuffle. + +Until it is derived, a reimplementation has two honest options: hard-code the +captured order for the screens that have been captured, or paint in declaration +order and accept that the title screen composites wrongly. The first is what the +evidence supports; the second is what the viewer does today.