mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-05 13:06:52 +00:00
Formalize "core excpetions" as a concept
This commit is contained in:
parent
7208cf6900
commit
a722dfe0fb
@ -97,6 +97,7 @@ public:
|
||||
|
||||
// Core
|
||||
bool bIgnoreBadMemAccess;
|
||||
|
||||
bool bFastMemory;
|
||||
int iCpuCore;
|
||||
bool bCheckForNewVersion;
|
||||
|
@ -64,6 +64,8 @@ static double lastKeepAwake = 0.0;
|
||||
static GraphicsContext *graphicsContext;
|
||||
static bool powerSaving = false;
|
||||
|
||||
static ExceptionInfo g_exceptionInfo;
|
||||
|
||||
void Core_SetGraphicsContext(GraphicsContext *ctx) {
|
||||
graphicsContext = ctx;
|
||||
PSP_CoreParameter().graphicsContext = graphicsContext;
|
||||
@ -366,19 +368,40 @@ void Core_EnableStepping(bool step) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Core_NextFrame() {
|
||||
if (coreState == CORE_RUNNING) {
|
||||
coreState = CORE_NEXTFRAME;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int Core_GetSteppingCounter() {
|
||||
return steppingCounter;
|
||||
}
|
||||
|
||||
void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
|
||||
const char *desc = "";
|
||||
const char *ExceptionTypeToString(ExceptionType type) {
|
||||
switch (type) {
|
||||
case MemoryExceptionType::READ_WORD: desc = "Read Word"; break;
|
||||
case MemoryExceptionType::WRITE_WORD: desc = "Write Word"; break;
|
||||
case MemoryExceptionType::READ_BLOCK: desc = "Read Block"; break;
|
||||
case MemoryExceptionType::WRITE_BLOCK: desc = "Read/Write Block"; break;
|
||||
case ExceptionType::MEMORY: return "Memory";
|
||||
case ExceptionType::BREAK: return "Break";
|
||||
default: return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
const char *MemoryExceptionTypeToString(MemoryExceptionType type) {
|
||||
switch (type) {
|
||||
case MemoryExceptionType::READ_WORD: return "Read Word";
|
||||
case MemoryExceptionType::WRITE_WORD: return "Write Word";
|
||||
case MemoryExceptionType::READ_BLOCK: return "Read Block";
|
||||
case MemoryExceptionType::WRITE_BLOCK: return "Read/Write Block";
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
|
||||
const char *desc = MemoryExceptionTypeToString(type);
|
||||
// In jit, we only flush PC when bIgnoreBadMemAccess is off.
|
||||
if (g_Config.iCpuCore == (int)CPUCore::JIT && g_Config.bIgnoreBadMemAccess) {
|
||||
WARN_LOG(MEMMAP, "%s: Invalid address %08x", desc, address);
|
||||
@ -386,6 +409,12 @@ void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
|
||||
WARN_LOG(MEMMAP, "%s: Invalid address %08x PC %08x LR %08x", desc, address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
}
|
||||
|
||||
ExceptionInfo &e = g_exceptionInfo;
|
||||
e = {};
|
||||
e.type = ExceptionType::MEMORY;
|
||||
e.info = "";
|
||||
e.memory_type = type;
|
||||
|
||||
if (!g_Config.bIgnoreBadMemAccess) {
|
||||
Core_EnableStepping(true);
|
||||
host->SetDebugMode(true);
|
||||
@ -394,8 +423,18 @@ void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type) {
|
||||
|
||||
void Core_Break() {
|
||||
ERROR_LOG(CPU, "BREAK!");
|
||||
|
||||
ExceptionInfo &e = g_exceptionInfo;
|
||||
e = {};
|
||||
e.type = ExceptionType::BREAK;
|
||||
e.info = "";
|
||||
|
||||
if (!g_Config.bIgnoreBadMemAccess) {
|
||||
Core_EnableStepping(true);
|
||||
host->SetDebugMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
ExceptionInfo Core_GetExceptionInfo() {
|
||||
return g_exceptionInfo;
|
||||
}
|
||||
|
18
Core/Core.h
18
Core/Core.h
@ -32,6 +32,8 @@ void Core_SetGraphicsContext(GraphicsContext *ctx);
|
||||
|
||||
// called from gui
|
||||
void Core_EnableStepping(bool step);
|
||||
|
||||
bool Core_NextFrame();
|
||||
void Core_DoSingleStep();
|
||||
void Core_UpdateSingleStep();
|
||||
void Core_ProcessStepping();
|
||||
@ -86,3 +88,19 @@ enum class MemoryExceptionType {
|
||||
|
||||
void Core_MemoryException(u32 address, u32 pc, MemoryExceptionType type);
|
||||
void Core_Break();
|
||||
|
||||
enum class ExceptionType {
|
||||
NONE,
|
||||
MEMORY,
|
||||
BREAK,
|
||||
};
|
||||
|
||||
struct ExceptionInfo {
|
||||
ExceptionType type;
|
||||
MemoryExceptionType memory_type;
|
||||
std::string info;
|
||||
};
|
||||
|
||||
ExceptionInfo Core_GetExceptionInfo();
|
||||
|
||||
const char *MemoryExceptionTypeToString(MemoryExceptionType type);
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "net/resolve.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "Core/CoreParameter.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
@ -791,8 +792,7 @@ void __DisplayFlip(int cyclesLate) {
|
||||
const bool fbReallyDirty = gpu->FramebufferReallyDirty();
|
||||
if (fbReallyDirty || noRecentFlip || postEffectRequiresFlip) {
|
||||
// Check first though, might've just quit / been paused.
|
||||
if (coreState == CORE_RUNNING) {
|
||||
coreState = CORE_NEXTFRAME;
|
||||
if (Core_NextFrame()) {
|
||||
gpu->CopyDisplayToOutput(fbReallyDirty);
|
||||
if (fbReallyDirty) {
|
||||
actualFlips++;
|
||||
|
@ -16,6 +16,7 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
void convert_frame(int inw, int inh, unsigned char *inData, AVPixelFormat inFormat,
|
||||
int outw, int outh, unsigned char **outData, int *outLen) {
|
||||
|
@ -18,7 +18,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
@ -28,10 +28,10 @@
|
||||
#include "Common/Common.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreParameter.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Common/PostShader.h"
|
||||
@ -831,7 +831,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) {
|
||||
currentRenderVfb_ = 0;
|
||||
|
||||
if (displayFramebufPtr_ == 0) {
|
||||
if (coreState == CORE_STEPPING)
|
||||
if (Core_IsStepping())
|
||||
VERBOSE_LOG(FRAMEBUF, "Display disabled, displaying only black");
|
||||
else
|
||||
DEBUG_LOG(FRAMEBUF, "Display disabled, displaying only black");
|
||||
@ -925,7 +925,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) {
|
||||
displayFramebuf_ = vfb;
|
||||
|
||||
if (vfb->fbo) {
|
||||
if (coreState == CORE_STEPPING)
|
||||
if (Core_IsStepping())
|
||||
VERBOSE_LOG(FRAMEBUF, "Displaying FBO %08x", vfb->fb_address);
|
||||
else
|
||||
DEBUG_LOG(FRAMEBUF, "Displaying FBO %08x", vfb->fb_address);
|
||||
|
@ -136,7 +136,9 @@ EmuScreen::EmuScreen(const std::string &filename)
|
||||
frameStep_ = false;
|
||||
lastNumFlips = gpuStats.numFlips;
|
||||
startDumping = false;
|
||||
|
||||
// Make sure we don't leave it at powerdown after the last game.
|
||||
// TODO: This really should be handled elsewhere if it isn't.
|
||||
if (coreState == CORE_POWERDOWN)
|
||||
coreState = CORE_STEPPING;
|
||||
|
||||
@ -1403,26 +1405,38 @@ void EmuScreen::render() {
|
||||
PSP_RunLoopWhileState();
|
||||
|
||||
// Hopefully coreState is now CORE_NEXTFRAME
|
||||
if (coreState == CORE_NEXTFRAME) {
|
||||
// set back to running for the next frame
|
||||
switch (coreState) {
|
||||
case CORE_NEXTFRAME:
|
||||
// Reached the end of the frame, all good. Set back to running for the next frame
|
||||
coreState = CORE_RUNNING;
|
||||
} else if (coreState == CORE_STEPPING) {
|
||||
// If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output.
|
||||
// This won't work in non-buffered, but that's fine.
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping");
|
||||
// Just to make sure.
|
||||
if (PSP_IsInited()) {
|
||||
gpu->CopyDisplayToOutput(true);
|
||||
break;
|
||||
case CORE_STEPPING:
|
||||
case CORE_RUNTIME_ERROR:
|
||||
{
|
||||
// If there's an exception, display information.
|
||||
ExceptionInfo info = Core_GetExceptionInfo();
|
||||
if (info.type != ExceptionType::NONE) {
|
||||
// Blue screen
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, 0xFF900000 }, "EmuScreen_RuntimeError");
|
||||
} else {
|
||||
// If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output.
|
||||
// This won't work in non-buffered, but that's fine.
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping");
|
||||
// Just to make sure.
|
||||
if (PSP_IsInited()) {
|
||||
gpu->CopyDisplayToOutput(true);
|
||||
}
|
||||
}
|
||||
} else if (coreState == CORE_RUNTIME_ERROR) {
|
||||
// Blue screen :)
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, 0xFF0000FF }, "EmuScreen_RuntimeError");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Didn't actually reach the end of the frame, ran out of the blockTicks cycles.
|
||||
// In this case we need to bind and wipe the backbuffer, at least.
|
||||
// It's possible we never ended up outputted anything - make sure we have the backbuffer cleared
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame");
|
||||
break;
|
||||
}
|
||||
|
||||
checkPowerDown();
|
||||
|
||||
PSP_EndHostFrame();
|
||||
|
Loading…
x
Reference in New Issue
Block a user