@@ -84,8 +84,33 @@ index 4d6a01d..9e2dc24 100644
8484+
8585+ ctx->f0.d = ret;
8686+ }
87+ diff --git a/librecomp/src/overlays.cpp b/librecomp/src/overlays.cpp
88+ index 8c8e5d1..e95ff7d 100644
89+ --- a/librecomp/src/overlays.cpp
90+ +++ b/librecomp/src/overlays.cpp
91+ @@ -200,7 +200,19 @@ extern "C" void load_overlays(uint32_t rom, int32_t ram_addr, uint32_t size) {
92+ );
93+ // Load the overlays that were found
94+ for (auto it = lower; it != upper; ++it) {
95+ - load_overlay(std::distance(§ions_info.code_sections[0], it), it->rom_addr - rom + ram_addr);
96+ + int32_t load_addr = it->rom_addr - rom + ram_addr;
97+ + // [wcw fix] Only map sections landing at their registered ram address. Revenge stores
98+ + // its two swap-overlays right after the fixed image (rom 0x3C770/0x834A0), INSIDE the
99+ + // boot DMA's 1MB window — the boot-time load_overlays(0x1000, entrypoint, 1MB) call in
100+ + // recomp.cpp would otherwise register them at bogus contiguous addresses (e.g. ovl_b at
101+ + // 0x800828A0), which later collides with the real swap-in at 0x80090000 ("Cannot
102+ + // partially unload section"). Every legitimate caller in this stack (boot fixed-segment
103+ + // map, the pi.cpp overlay-swap hook, WT's layout) loads sections at their registered
104+ + // address, so this filter is a no-op for them.
105+ + if (load_addr != it->ram_addr) {
106+ + continue;
107+ + }
108+ + load_overlay(std::distance(§ions_info.code_sections[0], it), load_addr);
109+ }
110+ }
111+
87112diff --git a/librecomp/src/pi.cpp b/librecomp/src/pi.cpp
88- index 62656ad..99b67eb 100644
113+ index 62656ad..3be27e2 100644
89114--- a/librecomp/src/pi.cpp
90115+++ b/librecomp/src/pi.cpp
91116@@ -8,6 +8,7 @@
@@ -135,27 +160,27 @@ index 62656ad..99b67eb 100644
135160 }
136161 }
137162
138- + // [wcw] WCW has two CPU overlays that both load to vram 0x80090000 (see disasm/README.md and
163+ + // [wcw] The AKI games (WCW World Tour rom 0xA21750/0xA69570, Revenge rom 0x3C770/0x834A0) have
164+ + // two CPU overlays that BOTH load to vram 0x80090000 (see each port's disasm docs and
139165+ // RecompiledFuncs/recomp_overlays.inl). The game DMAs the overlay code there and jumps to it;
140166+ // we must register the overlay's recompiled functions with the runtime (load_overlays) so
141167+ // get_function(0x80090000) resolves. Hook the cart-DMA path: when a transfer's destination is
142- + // the overlay base, map the matching overlay (unloading the previously-mapped one first).
168+ + // the overlay base and the source rom offset is a registered overlay section — looked up in the
169+ + // game's own registered section table instead of a per-game hardcoded list — map that overlay,
170+ + // unloading the previously-mapped one first. The 0x60000 window bounds section selection
171+ + // (load_overlays only loads sections fully inside it, and load_overlay uses the section's own
172+ + // size); it covers either game's largest overlay without reaching the next section.
143173+ static void wcw_maybe_load_overlay(gpr rdram_address, uint32_t physical_addr) {
144174+ if ((uint32_t)rdram_address != 0x80090000) {
145175+ return;
146176+ }
147- + static const struct { uint32_t rom; uint32_t size; } ovls[] = {
148- + { 0x00A21750, 0x00033BC0 }, // overlay A
149- + { 0x00A69570, 0x00055F70 }, // overlay B
150- + };
151177+ uint32_t rom_off = physical_addr - (uint32_t)recomp::rom_base;
152- + for (const auto& o : ovls) {
153- + if (rom_off == o.rom) {
154- + fprintf(stderr, "[wcw][ovl] map overlay rom=0x%06X -> 0x80090000 size=0x%X\n", o.rom, o.size);
155- + unload_overlays(0x80090000, 0x00056000); // cover the largest overlay
156- + load_overlays(o.rom, 0x80090000, o.size);
157- + return;
158- + }
178+ + const auto& vrom_map = recomp::overlays::get_vrom_to_section_map();
179+ + if (vrom_map.find(rom_off) != vrom_map.end()) {
180+ + fprintf(stderr, "[wcw][ovl] map overlay rom=0x%06X -> 0x80090000\n", rom_off);
181+ + unload_overlays(0x80090000, 0x00060000); // cover the largest overlay of either game
182+ + load_overlays(rom_off, 0x80090000, 0x00060000);
183+ + return;
159184+ }
160185+ fprintf(stderr, "[wcw][ovl] DMA to 0x80090000 from unrecognized rom 0x%X\n", rom_off);
161186+ }
0 commit comments