diff --git a/docs/re/structures/isl-builtins.md b/docs/re/structures/isl-builtins.md index 779ffee1..fa2cc8b6 100644 --- a/docs/re/structures/isl-builtins.md +++ b/docs/re/structures/isl-builtins.md @@ -140,6 +140,51 @@ and spread checks but its maximum *exceeds* the table — flag indices run 0..31 against symbol tables as small as 40 — so it is excluded, and the disassembler now declines to resolve it rather than printing an invented name. +### 🟡 Built-ins 26 / 28 / 29 are one family — and `damage_unit` looks mis-named + +Method-diffing put the structure beyond doubt but did not reach the semantics. + +| built-in | vtable slot | method | opcode | sites | +|---|---|---|---|---| +| 26 `damage_unit` | 76 | `sub_8226ACD0` (67) | **800** | 97 | +| **28** | 84 | `sub_82268F98` (69) | **801** | 410 | +| **29** | 88 | `sub_822690B0` (69) | **802** | 164 | +| 101 | 276 | `sub_822691C8` (78) | 802 (broadcast) | 133 | + +**28 and 29 differ in two words only** — the opcode (`0x21BA` vs `0x22BA`) and a +descriptor pointer 8 bytes apart. Otherwise instruction-identical. All three take +`(unit, double)`. + +26 differs from both by one guard: it rejects only state 3, while **28 and 29 +reject states 1 and 3** (2 = active, 1/3/4 = gone/dead/invalid). + +#### The operand distributions separate them + +| built-in | n | distinct | range | most common | +|---|---|---|---|---| +| 26 | 97 | 7 | **[0, 100]** | **0 ×69**, 80 ×10, 100 ×6 | +| 28 | 410 | 13 | **[0, 2000]** | 200 ×116, 120 ×76, 300 ×74 | +| 29 | 164 | 6 | **[0, 100]** | **0 ×64**, 100 ×53, 50 ×38 | + +26 and 29 are percentage-shaped; 28 is an absolute quantity an order of magnitude +larger. + +#### 🟡 `damage_unit` (26) is doubtful + +**69 of its 97 calls pass 0.** Dealing zero damage is a no-op, so 71 % of the +call sites would do nothing. *Setting* a percentage-valued property to 0 is a +perfectly natural thing to do 69 times, and 29 has the same shape (0 ×64 of 164). +The existing name predates this session and is not withdrawn, but it should not +be relied on. + +#### ❌ Where this stopped + +The three commands' descriptors sit at `0x820A8D10` / `+8` / `+16`. Following +them lands on data pointing into `0x8210E5xx`, which is **below the disassembly +DB's range** (it starts at `0x82150000`) and contains no code — so that route +does not reach an execute method. Reaching opcodes 800–802's semantics needs the +interpreter's command table, not the command objects. + ### ✅ Built-in 108 is `deploy_squadron_ex` — `deploy_squadron` plus a `1 << n` selector 1146 sites in 22 stages, the second-largest unnamed built-in. Its method