From 679812f1c9bfc30636df9fd4943b65b7b16a442b Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 26 Aug 2026 01:31:39 +0000 Subject: [PATCH] =?UTF-8?q?re:=20built-in=20108=20is=20deploy=5Fsquadron?= =?UTF-8?q?=5Fex=20=E2=80=94=20deploy=20plus=20a=201< Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE --- docs/re/data/isl-stage02.txt | 1 + docs/re/structures/isl-builtins.md | 37 ++++++++++++++++++++++++++++++ tools/re-capture/isl.py | 3 ++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/re/data/isl-stage02.txt b/docs/re/data/isl-stage02.txt index 38a362a..bf295ea 100644 --- a/docs/re/data/isl-stage02.txt +++ b/docs/re/data/isl-stage02.txt @@ -92,6 +92,7 @@ Generated by `tools/re-capture/isl_report.py calls`. 20 hp_pct_test 167 47 squadron_attack 137 15 set_group_speed 127 + 108 deploy_squadron_ex 117 18 dist_lt 92 12 activate_unit 86 5 kill_coroutine 83 diff --git a/docs/re/structures/isl-builtins.md b/docs/re/structures/isl-builtins.md index 0e920f8..779ffee 100644 --- a/docs/re/structures/isl-builtins.md +++ b/docs/re/structures/isl-builtins.md @@ -140,6 +140,43 @@ 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-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 +(`sub_822646B8`, vtable slot 300) and built-in 2's (`sub_822642E0`, slot 12) are +190 and 199 instructions and **differ in one block**. Diffed instruction by +instruction, 108 adds: + +``` +lwz r11, 16(r29) ; the blob's slot-16 int +cmpwi cr6, r11, 0 +blt cr6, … ; n < 0 -> default +cmpwi cr6, r11, 31 +bgt cr6, … ; n > 31 -> default +li r25, 1 +slw r21, r25, r11 ; r21 = 1 << n <- a 32-bit selector +b … +li r25, 1 +mr r21, r25 ; default: 1 +``` + +Everywhere built-in 2 passes its `r21`, 108 passes `r20` and reserves `r21` for +the mask — so the bit is an **extra argument to the same call**, not a +replacement. And both post the identical command word **`AB0100BA`, opcode 256**. + +#### ✅ The operand is always a valid bit index + +Over all 1146 sites the slot-16 value is in **[0, 31] — 1146 / 1146, none +outside**, so the out-of-range default never fires in shipped content. Fifteen +distinct values, clustered at 16 (531×), 31 (165×), 20 (161×) and 2 (90×); +21 of the 22 stages use more than one. + +❔ **What the bit selects is not established.** There is a 32-bit space here — +built-in 92 reportedly allocates a *free* bit by OR-ing over live units, which +would make 108 the "place this squadron in a named slot" counterpart — but I have +not verified that, so the name says only what is proven: the same deploy as +built-in 2, with an extra selector. + ### ✅ Built-in 12 is `activate_unit` — 1197 sites, all 28 stages The highest-traffic unnamed built-in. `sub_822659F0`, read directly: diff --git a/tools/re-capture/isl.py b/tools/re-capture/isl.py index eec1518..0b5e642 100755 --- a/tools/re-capture/isl.py +++ b/tools/re-capture/isl.py @@ -101,7 +101,8 @@ BUILTIN = { 81: 'banner_objective_update', 82: 'banner_mission_failed', 135: 'banner_mission_restart', 93: 'clear_flag', 94: 'is_engaged', 95: 'unit_hp_pct', 100: 'reset_phase_threads', - 102: 'prompt_yes_no', 109: 'set_unit_flags', 115: 'named_event', + 102: 'prompt_yes_no', 108: 'deploy_squadron_ex', + 109: 'set_unit_flags', 115: 'named_event', 120: 'wait_cmds_drained', 123: 'timer_resume', 124: 'timer_stop', 125: 'timer_reset', 126: 'timer_elapsed', 127: 'timer_set', 132: 'player_gauge0_test', 133: 'player_gauge1_test', 134: 'player_byte',