re: an ISL symbol operand is a (tag, index) pair — and two more names withdrawn

Verified rather than adopted: a subagent proposed that every even operand
slot is a type tag. Measured, the strong form is false and a precise form is
true.

TRUE: a SYMBOL operand is two words, a tag holding the constant 1 followed
by the index. Slot 0 is the integer 1 in 19899/19899 calls whose slot 4 is a
unit; slot 8 is tag-shaped in 100% of calls for every built-in taking a
second unit; slot 16 is 1 in 152/152 for built-in 128, the only one taking a
third. The 24 built-ins whose slot 0 is NOT the constant are exactly those
taking no symbol there. This explains the unit slots 4/12/20 rather than
replacing them.

FALSE as stated: slot 8 is a bare double for built-ins 4, 20, 24, 26, 28,
29, 90, 106 and 127, and built-in 75 carries five bare indices at 0/4/8/12/16
with no tags at all. Each built-in has a fixed signature and is 100%
self-consistent; none of the 34 with >=20 sites mixes the two.

Symbol table 1 has three types -- 1 routes (1362), 6 messages (2247), 7
effects (81) -- and its operand slots are type-pure, measured the same way.
Resolving them makes listings say what the script means:
`request_script_message(MSG_VOICE_D_257, ...)`, a fourth independent
confirmation of that name. Slots 24@4, 46@12 and 114@4 resolve 100% but MIX
types 6 and 1, so they are left unresolved rather than guessed.

Two more names withdrawn, neither replaced:
* 88 `camera_at` -- ZERO call sites in all 28 stages; never testable.
* 90 `camera_at_route` -- 8 sites, all Stage 02 phase 3, first operand is
  symtab-1 type 7 `eff_n0071`, an EFFECT name, in 8/8, with a per-missile
  Route_ADT301..308_p3M at slot 20. Not aimed at a camera.

Left unnamed on purpose: replacing a guessed name with another guess is how
the three names corrected earlier today went wrong.

Also flagged: 115 `named_event`'s only symbol operand is an eff_* name in
84/84 sites, so that name is suspect too. Not renamed pending a handler read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Sylpheed RE agent
2026-08-25 22:51:07 +00:00
parent cb1b634adf
commit 009bca880e
4 changed files with 124 additions and 11 deletions

View File

@@ -110,7 +110,6 @@ Generated by `tools/re-capture/isl_report.py calls`.
115 named_event 9
48 squadron_escort 8
39 MARK_LAST_PHASE 8
90 camera_at_route 8
17 wait_frames 6
10 random 6
123 timer_resume 5
@@ -140,7 +139,7 @@ resync from 0x5058
0050CC: 02030C00 set.i len=12 k=02,03 00000010 00000000 local[16] = special[0]
0050D8: 01021001 set.f len=16 k=01,02 00000000 BFF00000 00000000 special[0] = imm -1
0050E8: 02030C01 set.f len=12 k=02,03 00000018 00000000 local[24] = special[0]
0050F4: 00000C13 call len=12 k=00,00 00000040 00000245 request_script_message(0x42, 0x2, 0x1, 0x9, 0x1, -1)
0050F4: 00000C13 call len=12 k=00,00 00000040 00000245 request_script_message(MSG_VOICE_D_257, 0x2, 0x1, 0x9, 0x1, -1)
005100: 0000080C jmp len=8 k=00,00 0000507C -> code+0x507C (file 0x50A0)
005108: 0000080C jmp len=8 k=00,00 0000507C -> code+0x507C (file 0x50A0)
005110: 01020C0A op10 len=12 k=01,02 00000000 00000000
@@ -167,7 +166,7 @@ resync from 0x5058
005208: 01030C00 set.i len=12 k=01,03 00000004 00000056 local[4] = imm 0x56
005214: 01021001 set.f len=16 k=01,02 00000000 00000000 00000000 special[0] = imm 0
005224: 02030C01 set.f len=12 k=02,03 00000008 00000000 local[8] = special[0]
005230: 00000C13 call len=12 k=00,00 00000014 00000252 hp_pct_test(0x1, TCN004, 0)
005230: 00000C13 call len=12 k=00,00 00000014 00000252 hp_pct_test(TCN004, 0)
00523C: 01020C0A op10 len=12 k=01,02 00000000 00000001
005248: 0000080E op14 len=8 k=00,00 0000575C
005250: 01020C00 set.i len=12 k=01,02 00000000 00000000 special[0] = imm 0x0

View File

@@ -140,6 +140,67 @@ 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.
### ✅ A symbol operand is a two-word pair: a **tag**, then the index
This is why the unit indices sit at slots 4/12/20 and never at 0/8/16 — the even
slot in front of each is a tag word holding the constant **1**, and it is not an
argument. Measured over all 28 stages:
* slot 0 is the integer **1 in 19 899 / 19 899** calls whose slot 4 is a unit;
* slot 8 is tag-shaped in **100 %** of calls for every built-in taking a second
unit, and slot 16 is the constant 1 in **152/152** for built-in 128, the only
one taking a third;
* **24 built-ins have a slot 0 that is not the constant** — and every one of them
takes no symbol there (`start_coroutine` a code offset, `wait_s` a double,
`set_flag` an index). The tag appears exactly where a symbol does.
⚠️ It does **not** generalise to "every even slot is a tag". Slot 8 is a *bare
double* for built-ins 4, 20, 24, 26, 28, 29, 90, 106 and 127, and built-in 75
carries five bare symbol indices at 0/4/8/12/16 with no tags at all. Each
built-in has a fixed signature and is **100 % consistent with itself** — not one
of the 34 built-ins with ≥20 sites mixes the two shapes. The disassembler now
drops the tag word, so `hp_pct_test(0x1, TCN004, 0)` reads `hp_pct_test(TCN004, 0)`.
### ✅ Symbol table 1 has three types, and its slots are type-pure
| type | entries (28 stages) | what |
|---|---|---|
| 1 | 1362 | `Route_*` names |
| 6 | 2247 | message / objective names |
| 7 | 81 | `eff_*` effect names |
Measured the same way as the unit slots — every observed value resolves, ≥5
distinct values, resolved type pure:
* **type 1** — 2@12, 3@12, 7@12, 16@12, 19@12, 25@12, 48@24, 90@20, 108@12,
128@28, 136@4, 143@12
* **type 6** — 64@0 (2683 sites), 75@0/4/8/12/16
* **type 7** — 115@0 (84/84)
Built-ins **24@4, 46@12 and 114@4** resolve 100 % but **mix type 6 and type 1**,
so the slot does not mean one thing; they are deliberately left unresolved.
Resolving these makes the listings say what the script means:
`request_script_message(MSG_VOICE_D_257, …)` — which is a fourth, independent
confirmation of that name, since its first operand is literally a `MSG_VOICE_*`.
🟡 **`115 named_event` is now suspect.** Its only symbol operand is an `eff_*`
**effect** name in 84/84 sites. The name is left alone pending a handler read,
but "named event" is probably not what it does.
### ❌ `camera_at` and `camera_at_route` WITHDRAWN
`isl.py` named built-ins 88 and 90. Both names are unsupported:
* **88 has zero call sites** in all 28 stages, so the name was never testable.
* **90 has exactly 8**, all in Stage 02 phase 3 — the nine-cruise-missile act —
and its first operand resolves to symbol-table-1 **type 7, `eff_n0071`, an
effect name**, in 8/8, with a per-missile `Route_ADT301..308_p3M` at slot 20.
Whatever 90 does, it is not aimed at a camera. Both are left **unnamed** rather
than renamed: replacing one guessed name with another is how the three names
above got wrong in the first place.
**New, unexplained:** symbol table 2 holds **two types**, 2 (1160 entries
disc-wide) and 8 (249), and they are not interchangeable. Built-ins **95** and
**128** take a type-2 unit at slot 4 and, at slot 12, an operand that is type 8