Resolves the method-id gaps surfaced by the dispatch axis, all real switch-shape
edge cases rather than numbering bugs:
- default holes: ids the runner doesn't implement route to the `JA default` block
(tail-call to base CMC_Runner::run); capture that target and drop those cases
(was emitting false Sound 5/6, Scene 10-15, Array 26-31)
- sign-extension: high-base switches (CMC_NetPeer id 257+) encode the base as
`LEA/ADD idx, 0xFFFFFEFF` (-257); _s32 sign-extends on both the scalar and the
text path (Ghidra prints big displacements unsigned, small ones signed)
- two-level (byte-indexed) switches: sparse runners (Image) use
`MOVZX r,byte[i+byteTable]` (MSVC8) / `MOV rl,byte[i+byteTable]` (MSVC6) then
`JMP [r*4+ptrTable]`; decode target = ptrTable[byteTable[i]], taking base/count
from the byte-table's index register (differs from the JMP index reg on MSVC6)
- _executable() guard + id clamp: never emit a non-code "case"
Result: Piklib 500 rows / BlooMoo 561, garbage 0, dispatch<->methods consistent.
The lone genuinely-nameless method is CMC_Animo id 14 (a bool getter prepareMthHashSet
doesn't register) - a real engine property, correctly absent from the methods axis.
FUN_ ctor names are not recoverable (no symbols/mangled strings/RTTI in the binary
for FILTER/MOVIE/VECTOR/PATH/FIFO/LIFO/STATICFILTER); cpp_class=None stays.
Snapshots regenerated; 34/34 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>