Skip to content

Commit eedf7ad

Browse files
committed
lib: advance N64ModernRuntime to dc4592a (overlay swap mapping fix)
Keeps both ports on the same fork commit: dc4592a adds table-driven rom lookup + registered-address filtering to the overlay swap path (pi.cpp + overlays.cpp), needed by the sister Revenge port and a no-op for this game's overlay layout. Patch record refreshed via lib-patches/export.ps1.
1 parent 0f8cd56 commit eedf7ad

2 files changed

Lines changed: 40 additions & 15 deletions

File tree

lib-patches/N64ModernRuntime.patch

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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(&sections_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(&sections_info.code_sections[0], it), load_addr);
109+
}
110+
}
111+
87112
diff --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

Comments
 (0)