The old delta-sweep matched export-table pointers against 0x27BD prologues,
but those pointers point at mid-function DISPATCH entries, not prologues
(measured: 0/29 hit a prologue at the true base). It scattered bases by
2-16KB and decoded data as code.
Fix: j/jal targets are BASE-INDEPENDENT (0x80000000 | (imm26<<2), since all
game code lives in 0x800xxxxx). At the true base, the maximum number of
intra-overlay jal targets land on a real prologue. recover_base() votes every
(jal-target, prologue-offset) pair for base t-o within the pointer-containment
window; the peak is unique and sharp (~2x margin). Records are emitted
page-aligned with a FILL prefix, because the runtime keys shards by a
page-aligned region_start and compile_overlays takes load_addr verbatim.
Weak-signal files are skipped (score<4 or <1.5x runner-up) -- safe coverage
loss under the per-function code_crc dispatch guard. Also dedup overlays by
content CRC (position-fixed BINs are reused across AREA folders).
Validation: generic output is byte-identical (base, region envelope, seed set)
to the live-proven tomba1_extract.py hand tool for ALL 22 Tomba 1 overlays,
with no hardcoded constants. Tomba 2's 21 A*.BIN overlays converge on a single
consistent base 0x80108F9C (region 0x80108000 +3996).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two provably-correct framework fixes (independent of the AOT work) plus the
play-free overlay-extraction spike tooling and design doc.
Framework fixes (accurate, safe, complete):
- ABI v14: add gte_precision_store_word to OverlayCallbacks + preamble shim +
runtime population. The emitter emits a direct call for every swc2 (GTE
store-word); it is stateful runtime code (gte.cpp) so overlay DLLs must
forward or fail to LINK (undefined reference). Play-captured shards rarely
compiled a swc2; fuller static coverage surfaced the gap. Same pattern as
the v13 ws_player_x_bound / v10 gte_read_ctrl shims.
- Gate splitgen OFF in overlay mode (main_psx.cpp): the current recompiler's
unconditional split-TU output deletes <stem>_full.c and emits only shards,
which broke ALL overlay compilation (compile_overlays.py reads _full.c).
Overlays are single small TUs with no parallel-compile benefit; emit the
monolith. Restores overlay compile on the current tree.
AOT spike (docs/AOT_OVERLAY_PLAN.md + tools/aot_overlay_spike/, WIP):
- Play-free static overlay extraction from the disc image. Validated:
Tomba 1 reproduces 90% of played functions + ~1964 unplayed, live-verified
in-game (Dwarf Village runs native, zero runtime compile). Tomba 2 yields
661 functions byte-identical to the shipped/played vault (provably real),
all from the self-describing MAIN.EXE producer; the header-table BIN
producer needs loader-table RE (base recovery unreliable). Generality is
producer-dependent. Spike scripts are Tomba-specific proofs of concept
with hardcoded paths, not a finished tool.
- Correctness is guaranteed by the existing per-function code_crc dispatch
guard: a mis-positioned shard fails audit at compile or never fires at
runtime -> coverage loss, never wrong execution. Autocompile self-heals gaps.
CROSS-CUTTING: the ABI v14 change is part of the overlay codegen-hash source
set, so it ROLLS the cg tag (1f2ad026 -> e8484213). On master + a fw bump,
every title's overlay cache invalidates and needs regen+reshard. Branch only;
NOT pushed; other games' caches untouched. Needs user validation before merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the reusable Gaussian interpolation slice from PR #16 while keeping its reverb engine on a separate branch.
Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Apply the PS1 1023x511 size rule to every polygon triangle, line, and polyline continuation before widescreen transforms while preserving textured-command state latching.
Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Admit post-EXE RAM to the dirty interpreter only after a real control transfer and an existing MIPS decodability check. Keep the already-merged overlay initialization guard out of this focused change.
Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>