Merge pull request #2384 from LukeUsher/allow-skipping-faulty-instructions

EmuException: allow skipping of instructions that trigger unhandled exceptions
This commit is contained in:
PatrickvL 2022-07-08 13:21:15 +02:00 committed by GitHub
commit 16ffe3a80f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 16 deletions

View File

@ -313,7 +313,7 @@ PopupReturn PopupCustomEx(const void* hwnd, const CXBXR_MODULE cxbxr_module, con
uType |= MB_OKCANCEL;
break;
case PopupButtons::AbortRetryIgnore:
uType |= MB_RETRYCANCEL;
uType |= MB_ABORTRETRYIGNORE;
break;
case PopupButtons::YesNoCancel:
uType |= MB_YESNOCANCEL;

View File

@ -124,7 +124,7 @@ bool EmuExceptionBreakpointAsk(LPEXCEPTION_POINTERS e)
// We can skip Xbox as long as they are logged so we know about them
// There's no need to prevent emulation, we can just pretend we have a debugger attached and continue
// This is because some games (such as Crash Bandicoot) spam exceptions;
e->ContextRecord->Eip += EmuX86_OpcodeSize((uint8_t*)e->ContextRecord->Eip); // Skip 1 size bytes
e->ContextRecord->Eip += EmuX86_OpcodeSize((uint8_t*)e->ContextRecord->Eip); // Skip 1 instruction
return true;
#if 1
@ -157,19 +157,26 @@ bool EmuExceptionBreakpointAsk(LPEXCEPTION_POINTERS e)
#endif
}
void EmuExceptionNonBreakpointUnhandledShow(LPEXCEPTION_POINTERS e)
bool EmuExceptionNonBreakpointUnhandledShow(LPEXCEPTION_POINTERS e)
{
EmuExceptionPrintDebugInformation(e, /*IsBreakpointException=*/false);
if (PopupFatalEx(nullptr, PopupButtons::OkCancel, PopupReturn::Ok,
auto result = PopupFatalEx(nullptr, PopupButtons::AbortRetryIgnore, PopupReturn::Abort,
" The running xbe has encountered an unhandled exception (Code := 0x%.8X) at address 0x%.08X.\n"
"\n"
" Press \"OK\" to terminate emulation.\n"
" Press \"Cancel\" to debug.",
e->ExceptionRecord->ExceptionCode, e->ContextRecord->Eip) == PopupReturn::Ok)
{
" Press \"Abort\" to terminate emulation.\n"
" Press \"Retry\" to debug.\n"
" Press \"Ignore\" to attempt to continue emulation.",
e->ExceptionRecord->ExceptionCode, e->ContextRecord->Eip);
if (result == PopupReturn::Abort) {
EmuExceptionExitProcess();
} else if (result == PopupReturn::Ignore) {
e->ContextRecord->Eip += EmuX86_OpcodeSize((uint8_t*)e->ContextRecord->Eip); // Skip 1 instruction
return true;
}
return false;
}
// Returns weither the given address is part of an Xbox managed memory region
@ -185,7 +192,8 @@ bool IsXboxCodeAddress(xbox::addr_xt addr)
#include "distorm.h"
bool EmuX86_DecodeOpcode(const uint8_t* Eip, _DInst& info);
void EmuX86_DistormLogInstruction(const uint8_t* Eip, _DInst& info, LOG_LEVEL log_level);
void genericException(EXCEPTION_POINTERS *e) {
bool genericException(EXCEPTION_POINTERS *e)
{
_DInst info;
if (EmuX86_DecodeOpcode((uint8_t*)e->ContextRecord->Eip, info)) {
EmuX86_DistormLogInstruction((uint8_t*)e->ContextRecord->Eip, info, LOG_LEVEL::FATAL);
@ -200,11 +208,14 @@ void genericException(EXCEPTION_POINTERS *e) {
}
// Bypass exception
return false;
}
else {
// notify user
EmuExceptionNonBreakpointUnhandledShow(e);
return EmuExceptionNonBreakpointUnhandledShow(e);
}
return false;
}
bool IsRdtscInstruction(xbox::addr_xt addr); // Implemented in CxbxKrnl.cpp
@ -270,8 +281,7 @@ bool EmuTryHandleException(EXCEPTION_POINTERS *e)
// Check if lle exception is already called first before emu exception.
if (bOverrideEmuException) {
genericException(e);
return false;
return genericException(e);
}
if (e->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) {
@ -309,10 +319,7 @@ bool EmuTryHandleException(EXCEPTION_POINTERS *e)
}
}
genericException(e);
// Unhandled exception :
return false;
return genericException(e);
}
long WINAPI EmuException(struct _EXCEPTION_POINTERS* e)