Files
psxrecomp/runtime/include
Matthew Stanley 7c5b766fd5 overlay: ABI v22 game_text_native_ok shim (107 shards failed to link)
The emitter emits a direct psx_game_text_native_ok() stale-static guard at block
entry (code_generator.cpp:115) and before every direct jal (:2402). That function
is DEFINED IN THE GENERATED DISPATCH SHARD (main_psx.cpp:1620), which links into
the executable. An overlay DLL is a separate module and cannot resolve it, and
overlay_dispatch_preamble.c.inc had no shim for it.

Found by bumping Tomba 2 from a 254-commit-old pin to master and regenerating its
shard cache against the identical vault:

  before bump : built OK 2799, FAILED 1
  after bump  : built OK 2233, FAILED 109

107 of the 109 were the same error:

  ld.exe: undefined reference to `psx_game_text_native_ok'
  collect2.exe: error: ld returned 1 exit status

This is the fifth instance of one class, and overlay_api.h's own version history
records the previous four:

  v9  faithful-timing callbacks  overlay code failed to link
  v10 gte_read_ctrl              GTE-heavy overlays failed to LINK without shims,
                                 silently blocking new coverage
  v12 rfe_mark_escape            without the shim any rfe-containing overlay
                                 fails to LINK
  v14 gte_precision_store_word   the rfe / gte_read_ctrl class again

Every time the shape is identical: an emitter gains a runtime call, the overlay
ABI does not gain the shim, and the only symptom is shards that quietly fail to
build. The affected code then runs interpreted forever and nothing at runtime
says so. Severity is coverage, not correctness -- but that is exactly the defect
that let Ape Escape ship 100% interpreted without anyone noticing.

Fix follows the v10/v12/v14 pattern exactly:
  - overlay_api.h: append game_text_native_ok to OverlayCallbacks, bump
    PSX_OVERLAY_ABI_VERSION 21 -> 22, add the version-history note
  - overlay_dispatch_preamble.c.inc: shim forwarding to g_cbs
  - overlay_loader.c init_callbacks: host populates it from the dispatch shard

The NULL guard deliberately returns 0, not 1. Returning 0 routes the guest
through the dispatcher -- slower, never wrong. Returning 1 would let an overlay
run native code the guard was explicitly trying to reject.

Follow-up worth doing, tracked as beads-eio.3.97: five instances of one class
means the process is the bug, not the symbol. The emitter knows every helper name
it can emit and the preamble enumerates every shim; a test comparing those two
sets would have caught v9, v10, v12, v14 and this one at authoring time instead
of at some future title's link step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 00:37:44 -07:00
..
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-08-31 09:15:39 +03:00
ok
2026-08-07 22:14:26 -04:00
2026-08-07 16:42:43 -04:00
2026-07-29 03:18:10 -04:00
2026-08-03 05:26:37 -04:00
2026-08-06 20:34:50 -04:00
2026-08-09 22:24:48 -04:00
2026-08-07 18:11:35 -04:00
2026-08-03 05:26:37 -04:00
2026-08-03 05:26:37 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-08-06 00:52:14 -04:00
2026-07-31 17:14:35 -04:00
2026-08-13 17:38:22 -04:00
2026-07-31 17:14:35 -04:00
2026-07-29 03:18:10 -04:00
2026-07-31 17:14:35 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00