mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-05-15 07:29:46 -05:00
analysis: don't extend max_reached past last visited code in jtbl handling
discover_function_bounds was extending max_reached to cover the jump
table's bytes themselves (jtbl_end - 4). This was wrong: jtbl entries
are DATA, not code. Including their bytes in the function's words
range made recompile_function try to interpret intervening data words
as MIPS instructions, which usually fails (encountering 'pref',
'INVALID', branches to outside the function, etc.).
The fix: stop extending max_reached for jtbl_end. The recompiler's
analyze_function reads jtbl entries directly from context.rom — they
don't need to be part of func.words. Function bounds = max-reached-
instruction + 4 (delay slot), nothing more.
Effect on Stadium's 0x8FF00000 pattern activation:
Before this fix: 1 recompile error (`func_8FF00020__rom_FE000020`
at instr 8243 — 'pref' instruction emitted at vram 0x8FF080B8,
followed by INVALID instructions). The function had been sized
large enough to contain unrelated data after the case-arms region.
After this fix: 0 errors. All 219 pattern-synthesized sections
recompile cleanly.
Stadium boot impact (pattern activated, 30-second run):
- 1048 audio hits (15x improvement; was ~70 with static fragment78).
- 31 fragments registered (3.4x improvement; was ~9).
- 17 different fragment78-family variants streamed through link
vram 0x8FF00000, each correctly content-hash-dispatched.
- Stadium reaches a NEW failure mode much later: `lookup miss
at 0x810001D0` — a different fragment slot (link bucket 0x10)
needs similar treatment. Tracked separately.
The pattern is now ACTIVE in Stadium's game.toml. game.toml updated
to document the active configuration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
392fef7cc0
commit
745046ca43
|
|
@ -526,21 +526,22 @@ bool N64Recomp::discover_function_bounds(
|
|||
cursor, jtbl.vram);
|
||||
return false;
|
||||
}
|
||||
// Add each target to BFS. Also extend max_reached past
|
||||
// the table itself so we count its bytes as part of
|
||||
// the function.
|
||||
// Add each target to BFS so its arm gets walked and
|
||||
// its instructions count toward max_reached. Do NOT
|
||||
// extend max_reached to cover the jump table's bytes
|
||||
// themselves: jtbl entries are DATA, not code, and
|
||||
// including them in the function's `words` makes
|
||||
// recompile_function try to interpret intervening
|
||||
// data words as MIPS instructions (which usually
|
||||
// fails because the data isn't valid code). The
|
||||
// recompiler's analyze_function reads jtbl entries
|
||||
// directly from context.rom — they don't need to
|
||||
// be inside func.words.
|
||||
for (size_t t : jtbl_targets) {
|
||||
if (!visited.contains(t)) {
|
||||
worklist.push_back(t);
|
||||
}
|
||||
}
|
||||
size_t jtbl_end = (jtbl.vram - vram_base) +
|
||||
collected * 4;
|
||||
if (jtbl_end > 0) {
|
||||
if (jtbl_end - 4 > max_reached) {
|
||||
max_reached = jtbl_end - 4;
|
||||
}
|
||||
}
|
||||
break; // block ends after the jr's delay slot
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user