diff --git a/recompiler/src/config_loader.cpp b/recompiler/src/config_loader.cpp index b4ee4147..aa8f5202 100644 --- a/recompiler/src/config_loader.cpp +++ b/recompiler/src/config_loader.cpp @@ -517,18 +517,20 @@ static RuntimeConfig parse_runtime_block(const toml::value& cfg, const fs::path& if (raw < 0 || raw > 0xFFFFFFFFll) { throw std::runtime_error(fmt::format( "[runtime] overlay_region_floor out of range " - "(0x10000..0x1FFFFF physical, KSEG0/KSEG1 prefix allowed): {}", + "(0x10000..0x7FFFFF physical, KSEG0/KSEG1 prefix allowed): {}", raw)); } floor = static_cast(raw); } - // The floor names a main-RAM physical address above the kernel window; - // fail loud here instead of relying on the runtime clamp/mask. + // The floor names a main-RAM physical address above the kernel window, + // inside the 8 MiB decode window (the opt-in 8 MB map's text may end + // above 2 MiB; on retail RAM the runtime clamps it to the live end). + // Fail loud here instead of relying on the runtime clamp/mask. const uint32_t phys = floor & 0x1FFFFFFFu; - if (phys < 0x00010000u || phys >= 0x00200000u) { + if (phys < 0x00010000u || phys >= 0x00800000u) { throw std::runtime_error(fmt::format( "[runtime] overlay_region_floor out of range " - "(0x10000..0x1FFFFF physical, KSEG0/KSEG1 prefix allowed): 0x{:08X}", + "(0x10000..0x7FFFFF physical, KSEG0/KSEG1 prefix allowed): 0x{:08X}", floor)); } rt.overlay_region_floor = floor; diff --git a/runtime/src/memory.c b/runtime/src/memory.c index 7e8b7b32..3e2bf7ea 100644 --- a/runtime/src/memory.c +++ b/runtime/src/memory.c @@ -1290,7 +1290,9 @@ static void mmio_write32(uint32_t addr, uint32_t val) { if (addr == 0x1F801810u) { uint32_t src = addr; if (g_debug_last_store_pc == 0xBFC38B1Cu && debug_cpu_ptr) { - src = (debug_cpu_ptr->gpr[4] - 4u) & 0x1FFFFCu; + /* Word-aligned RAM key through the live geometry (retail: the + * 0x1FFFFC fold, identical to the DMA/GPU source keys). */ + src = psx_ram_canonical_offset(debug_cpu_ptr->gpr[4] - 4u) & ~3u; } gpu_set_gp0_source(src); gpu_write_gp0(val); diff --git a/runtime/tests/test_overlay_region_floor_config.py b/runtime/tests/test_overlay_region_floor_config.py index 3dde0df4..db514d16 100644 --- a/runtime/tests/test_overlay_region_floor_config.py +++ b/runtime/tests/test_overlay_region_floor_config.py @@ -19,7 +19,7 @@ assert 'parse_hex(v.as_string(), "runtime.overlay_region_floor")' in LOADER_CPP, # negative or >32-bit TOML integer must not wrap into a different address, and # the value must name main RAM above the kernel window. assert "raw < 0 || raw > 0xFFFFFFFFll" in LOADER_CPP, "integer form must reject wrap-around values" -assert "phys < 0x00010000u || phys >= 0x00200000u" in LOADER_CPP, "floor must be validated against main RAM" +assert "phys < 0x00010000u || phys >= 0x00800000u" in LOADER_CPP, "floor must be validated against the main-RAM decode window" assert LOADER_CPP.count("overlay_region_floor out of range") == 2, "both rejections must fail loud" cfg = MAIN.index("gc.runtime.has_overlay_region_floor") diff --git a/runtime/tests/test_sdl3_main_single_include.py b/runtime/tests/test_sdl3_main_single_include.py index 71a4ad2b..6b44eec8 100644 --- a/runtime/tests/test_sdl3_main_single_include.py +++ b/runtime/tests/test_sdl3_main_single_include.py @@ -12,11 +12,14 @@ SDL_MAIN_HEADER = "" def main() -> int: runtime = ROOT / "runtime" owners = [] - for pattern in ("*.c", "*.cpp", "*.h"): - for path in runtime.rglob(pattern): - source = path.read_text(encoding="utf-8") - if SDL_MAIN_HEADER in source: - owners.append(path.relative_to(ROOT).as_posix()) + # Sources only: a build tree under runtime/ (the documented runtime/build + # layout) holds generated binary-ish headers such as vk_shaders_spv.h. + for tree in ("src", "include", "tests"): + for pattern in ("*.c", "*.cpp", "*.h"): + for path in (runtime / tree).rglob(pattern): + source = path.read_text(encoding="utf-8") + if SDL_MAIN_HEADER in source: + owners.append(path.relative_to(ROOT).as_posix()) if owners != ["runtime/src/main.cpp"]: raise AssertionError(