diff --git a/Common/ExceptionHandlerSetup.cpp b/Common/ExceptionHandlerSetup.cpp index 37913774af..7c8d64b1eb 100644 --- a/Common/ExceptionHandlerSetup.cpp +++ b/Common/ExceptionHandlerSetup.cpp @@ -40,7 +40,7 @@ static BadAccessHandler g_badAccessHandler; static PVOID g_vectoredExceptionHandle; -static LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) { +static LONG NTAPI GlobalExceptionHandler(PEXCEPTION_POINTERS pPtrs) { switch (pPtrs->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: { @@ -96,7 +96,7 @@ void InstallExceptionHandler(BadAccessHandler badAccessHandler) { INFO_LOG(SYSTEM, "Installing exception handler"); g_badAccessHandler = badAccessHandler; - g_vectoredExceptionHandle = AddVectoredExceptionHandler(TRUE, Handler); + g_vectoredExceptionHandle = AddVectoredExceptionHandler(TRUE, GlobalExceptionHandler); } void UninstallExceptionHandler() { diff --git a/Core/Core.h b/Core/Core.h index 6cb8004cf4..e7bdb5a462 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -80,6 +80,7 @@ void Core_SetPowerSaving(bool mode); bool Core_GetPowerSaving(); enum class MemoryExceptionType { + NONE, READ_WORD, WRITE_WORD, READ_BLOCK, diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index fa1e3d96b5..9e8968fd8c 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -513,28 +513,38 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) { // TODO: Share the struct between the various analyzers, that will allow us to share most of // the implementations here. + bool success = false; + + MemoryExceptionType type = MemoryExceptionType::NONE; #if PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(X86) // X86, X86-64. Variable instruction size so need to analyze the mov instruction in detail. // To ignore the access, we need to disassemble the instruction and modify context->CTX_PC LSInstructionInfo info; - X86AnalyzeMOV(codePtr, info); + success = X86AnalyzeMOV(codePtr, info); #elif PPSSPP_ARCH(ARM64) uint32_t word; memcpy(&word, codePtr, 4); // To ignore the access, we need to disassemble the instruction and modify context->CTX_PC Arm64LSInstructionInfo info; - Arm64AnalyzeLoadStore((uint64_t)codePtr, word, &info); + success = Arm64AnalyzeLoadStore((uint64_t)codePtr, word, &info); #elif PPSSPP_ARCH(ARM) uint32_t word; memcpy(&word, codePtr, 4); // To ignore the access, we need to disassemble the instruction and modify context->CTX_PC ArmLSInstructionInfo info; - ArmAnalyzeLoadStore((uint32_t)codePtr, word, &info); + success = ArmAnalyzeLoadStore((uint32_t)codePtr, word, &info); #endif + if (success) { + if (info.isMemoryWrite) { + type = MemoryExceptionType::WRITE_WORD; + } else { + type = MemoryExceptionType::READ_WORD; + } + } - if (g_Config.bIgnoreBadMemAccess) { + if (success && g_Config.bIgnoreBadMemAccess) { if (!info.isMemoryWrite) { // It was a read. Fill the destination register with 0. // TODO @@ -546,6 +556,10 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) { ERROR_LOG(MEMMAP, "Bad memory access detected and ignored: %08x (%p)", guestAddress, (void *)hostAddress); } } else { + // Either bIgnoreBadMemAccess is off, or we failed recovery analysis. + uint32_t approximatePC = currentMIPS->pc; + Core_MemoryException(guestAddress, currentMIPS->pc, type); + // Redirect execution to a crash handler that will exit the game. context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler(); ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation.", guestAddress, (void *)hostAddress); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index b624dd6186..7992aeab31 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1158,7 +1158,7 @@ void EmuScreen::update() { PSP_CoreParameter().pixelHeight = pixel_yres * bounds.h / dp_yres; #endif - if (!invalid_) { + if (!invalid_ && coreState != CORE_RUNTIME_ERROR) { UpdateUIState(UISTATE_INGAME); }