349b498 reported that 0x3a7c30 has no jal callers. That was wrong and the bug was
mine: the scan built J-type targets as ((instr & 0x03ffffff) << 2) | 0x0c000000
without masking to the upper nibble, adding 0x0c000000 to every target so nothing
matched.
Corrected: exactly one jal caller, at 0x3a3d84. Still no j tail-calls, still not a
vtbl handler, still not a pointer in any level-0 data file.
Tracing back, r2 is never written between the call and the use:
0x3a3ce4 lw r3, 0x1500(r2)
0x3a3d70 jal 0x2ee178
0x3a3d84 jal 0x3a7c30
so r2 is the return value of 0x2ee178, passed through as the first argument. The
chain is now 0x2ee178 returns a pointer -> 0x3a7c30 -> 0x3a8060 -> addiu r17, r18,
0xc0.
Next question is one function: does 0x2ee178 return core_data + moby_classes.offset?
If so the reading is confirmed and the loader is located; if not, the 0xc0 in
0x3a8060 is an unrelated struct member.
Also recorded in docs: a negative from a hand-rolled decoder is worth nothing
until checked against a known case. jal 0x3a8060 decoded correctly under a
different constant in the same probe and I did not notice.
284 passing with the disc present, clippy clean.