From 950db19f1b5d9b47ce08138838af56bc015ebc7f Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Thu, 27 Aug 2026 08:08:01 +0000 Subject: [PATCH] re: the kind-0 trigger condition is a point-to-segment proximity test sub_8226DAF8 past the route-name lookup: it resolves the name through sub_823012D8, requires the unit record's rec+100 != 0, pulls TWO three-double vectors out of that record -- rec+32/+40/+48 and rec+64/+72/+80 -- and then makes a virtual call: 8226DC1C lwz r11, 0(r30) ; the ScriptPhase vptr 8226DC28 lwz r11, 60(r11) ; vtable slot 60 8226DC30 bcctrl ; test(phase, A, B, P = the route, f1 = node+16) Slot 60 resolves to sub_82268068, which no built-in uses, so it is engine-internal. Its arithmetic leaves no room for interpretation: per-axis fsub, fmul plus two fmadd, fsqrt, giving |B - A|; reject if that is under 0.1 (the constant is literally 0.1, a degenerate-segment guard); reject if |P - A| > f1 or |P - B| > f1; then compute t = (P-A).(B-A) / |B-A|^2 and reject if t < 0. That is a point-to-segment distance test, and it makes the node's double -- built-in 19's local[24] -- a RADIUS. So a kind-0 trigger fires when a route point lies within that radius of the segment between two vectors from the unit's record. Recorded as unproven: WHAT A and B are. A previous/current position pair would make this the standard frame-rate-robust waypoint test, and it would be easy to write that down -- which is exactly why it is not written down. rec+64/72/80 and rec+32/40/48 are two positions and nothing here says which. All artefacts regenerate byte-identical; documentation only. Still unread: sub_8226DC80, the kind-1 condition, entirely; and slot 60 past the t < 0 rejection, where a second constant at 0x820B0000+25192 is loaded. --- docs/re/BACKLOG.md | 16 +++++++++ docs/re/structures/isl-trigger-node.md | 49 ++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index ca5bcc9a..74135f91 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -188,6 +188,22 @@ unknown, what evidence exists, and what the first step would be. Move an item in `payload+8` (a computed value passed to both testers — waypoint-index shaped, which is why it is not being called one). +* ✅ **(2026-08-27) THE KIND-0 TRIGGER CONDITION IS A POINT-TO-SEGMENT PROXIMITY + TEST. [structures/isl-trigger-node](structures/isl-trigger-node.md).** + `sub_8226DAF8` resolves the route name (`sub_823012D8`), requires the unit record's + `rec+100 != 0`, extracts **two 3-double vectors** — `rec+32/+40/+48` and + `rec+64/+72/+80` — and makes a VIRTUAL call to **ScriptPhase vtable slot 60 = + `sub_82268068`** (used by no built-in, so engine-internal) with those two vectors, + the route point, and the node's double. Slot 60's arithmetic is unambiguous: + per-axis `fsub`, `fmul` + two `fmadd`, `fsqrt` → `|B−A|`; **reject if `|B−A| < 0.1`** + (degenerate); **reject if `|P−A| > f1` or `|P−B| > f1`**; then + **`t = (P−A)·(B−A) / |B−A|²`, reject if `t < 0`**. So it is a point-to-segment + distance test and **the node's double (`local[24]`) is a RADIUS**. 🟡 **What A and + B are is NOT established** — a previous/current position pair would make this the + standard frame-rate-robust waypoint test, which is exactly the tidy reading this + corpus insists on proving. 🟡 Still unread: `sub_8226DC80` (kind 1) entirely, and + slot 60 past the `t < 0` rejection. + ## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26) `XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the diff --git a/docs/re/structures/isl-trigger-node.md b/docs/re/structures/isl-trigger-node.md index 9606cd44..f0bd5f4c 100644 --- a/docs/re/structures/isl-trigger-node.md +++ b/docs/re/structures/isl-trigger-node.md @@ -207,14 +207,57 @@ measured to rise **at a squadron's route arrival time**. Route triggers are the mechanism that would do that. 🟡 Stated as a connection, not a demonstration — nothing here traces a trigger to that counter. +## ✅ What the kind-0 condition TESTS — a point-to-segment proximity check + +`sub_8226DAF8` past the route-name lookup: + +``` +8226DB84 bl 0x823012D8 ; look the route name up -> a route object; bail if absent +8226DBB8 lwz r11, 324(r30) ; the unit array +8226DBBC rlwinm r10, r26, 2,0,29; r26 = payload+0, the unit index +8226DBC8 lwz r10, 100(r11) ; require rec+100 != 0, else return 0 +8226DBD4 lfd f0, 32(r11) … ; THREE doubles: rec+32, +40, +48 -> out vector B +8226DBF8 lfd f0, 64(r11) … ; THREE doubles: rec+64, +72, +80 -> out vector A +8226DBFC fmr f1, f31 ; the node's double (payload+16) +8226DC1C lwz r11, 0(r30) ; the ScriptPhase vptr +8226DC28 lwz r11, 60(r11) ; VTABLE SLOT 60 +8226DC30 bcctrl ; test(phase, A, B, P=the route, f1) +``` + +**Slot 60 → `sub_82268068`**, which no built-in uses — it is engine-internal — and +its arithmetic is unambiguous: + +``` +f29 = |B - A| ; fsub per axis, fmul + 2x fmadd, fsqrt +if |B - A| < 0.1 -> 0 ; degenerate segment (the constant is 0.1) +f28 = |P - A| ; if > f1 -> 0 + |P - B| ; if > f1 -> 0 +t = (P-A)·(B-A) / |B-A|² ; the projection parameter +if t < 0.0 -> 0 +``` + +Per-axis `fsub`, a sum of three squares, `fsqrt`, and a dot product divided by +the squared length: this is a **point-to-segment distance test**, and the node's +double is therefore a **RADIUS**. + +So a kind-0 trigger fires when a route point lies within `local[24]` of the +segment between two vectors taken from the unit's record. + +🟡 **What A and B are is not established.** `rec+64/72/80` and `rec+32/40/48` are +two positions; a previous/current pair would make this the standard +frame-rate-robust waypoint test, and that is exactly the kind of tidy reading +this corpus makes itself prove. Not proven here. + ## 🟡 Not settled * ~~What the drain actually spawns.~~ ✅ Resolved above: built-in 19's nodes carry a real routine offset at `+28`. * ~~Whether `+24` selects between the two node kinds~~ ✅ It does — see above. -* **What the conditions actually TEST.** Only `sub_8226DAF8`'s first ~34 - instructions are read — up to the route-name lookup. What it compares the route - against, and the whole of `sub_8226DC80` (kind 1), are unread. +* ~~What the kind-0 condition tests~~ ✅ Read above. **`sub_8226DC80` (kind 1) is + still unread entirely.** +* **Which unit-record fields A and B are** — `rec+64/72/80` vs `rec+32/40/48`. +* **The rest of slot 60** past the `t < 0` rejection (a second constant at + `0x820B0000+25192` is loaded next). * **`payload+8`** is a computed value in both appenders (`r29-1` in built-in 19) and is passed to both testers; a waypoint index would fit, which is exactly why it is not being called one.