From f3adef75ed17d285f91c28212f2005bc380b3151 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 4 Apr 2026 16:31:15 +0200 Subject: [PATCH] Core: Raise PI interrupt when accessing unmapped memory Unmapped on the physical level, not the MMU level. Fixes booting Game Boy Interface. Previously, Game Boy Interface thought it was running on a Wii because accessing MEM2 didn't raise a PI interrupt, and as a result tried to exit to the Homebrew Channel in a way Dolphin's HLE doesn't recognize. (Dolphin's HLE catches jumps to 0x80001800, but GBI is running without address translation at this point and therefore jumps to 0x00001800 instead.) --- Source/Core/Core/PowerPC/MMU.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp index 934956a224..940e93c7ea 100644 --- a/Source/Core/Core/PowerPC/MMU.cpp +++ b/Source/Core/Core/PowerPC/MMU.cpp @@ -302,12 +302,21 @@ T MMU::ReadFromHardware(u32 em_address) return bswap(value); } - PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, m_ppc_state.pc); - if (m_system.IsPauseOnPanicMode()) + // Memory access error. Game Boy Interface relies on this to confirm that MEM2 isn't present. + // TODO: This interrupt is supposed to have associated cause and address registers. + m_system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_PI); + + // Don't show a panic alert for the specific access Game Boy Interface does. + if (em_address != 0x10000000 || (m_ppc_state.pc >> 28) != 0) { - m_system.GetCPU().Break(); - m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + PanicAlertFmt("Unable to resolve read address {:x} PC {:x}", em_address, m_ppc_state.pc); + if (m_system.IsPauseOnPanicMode()) + { + m_system.GetCPU().Break(); + m_ppc_state.Exceptions |= EXCEPTION_DSI | EXCEPTION_FAKE_MEMCHECK_HIT; + } } + return 0; } @@ -492,6 +501,10 @@ void MMU::WriteToHardware(u32 em_address, const u32 data, const u32 size) return; } + // Memory access error. + // TODO: This interrupt is supposed to have associated cause and address registers. + m_system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_PI); + PanicAlertFmt("Unable to resolve write address {:x} PC {:x}", em_address, m_ppc_state.pc); if (m_system.IsPauseOnPanicMode()) {