Make fastmem memory exceptions report the exceptions to Core correctly.

This commit is contained in:
Henrik Rydgård 2020-07-05 11:40:58 +02:00
parent 465367bf1b
commit a56f391713
4 changed files with 22 additions and 7 deletions

View File

@ -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() {

View File

@ -80,6 +80,7 @@ void Core_SetPowerSaving(bool mode);
bool Core_GetPowerSaving();
enum class MemoryExceptionType {
NONE,
READ_WORD,
WRITE_WORD,
READ_BLOCK,

View File

@ -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);

View File

@ -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);
}