mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Safety: Make sure we're not executing game code while waiting for RetroAchievements identification.
This commit is contained in:
parent
cff13d56d1
commit
bebc3feee1
3 changed files with 55 additions and 39 deletions
|
@ -104,6 +104,8 @@ std::string s_game_hash;
|
|||
|
||||
bool g_challengeMode = true;
|
||||
|
||||
bool g_isIdentifying = false;
|
||||
|
||||
// rc_client implementation
|
||||
static rc_client_t *g_rcClient;
|
||||
|
||||
|
@ -132,6 +134,10 @@ bool IsActive() {
|
|||
return GetGameID() != 0;
|
||||
}
|
||||
|
||||
bool IsBlockingExecution() {
|
||||
return g_isIdentifying;
|
||||
}
|
||||
|
||||
u32 GetGameID() {
|
||||
if (!g_rcClient) {
|
||||
return 0;
|
||||
|
@ -561,6 +567,8 @@ void identify_and_load_callback(int result, const char *error_message, rc_client
|
|||
ERROR_LOG(ACHIEVEMENTS, "Failed to identify/load game: %d (%s)", result, error_message);
|
||||
break;
|
||||
}
|
||||
|
||||
g_isIdentifying = false;
|
||||
}
|
||||
|
||||
void SetGame(const Path &path) {
|
||||
|
@ -580,6 +588,9 @@ void SetGame(const Path &path) {
|
|||
rc_filereader.read = [](void *file_handle, void *buffer, size_t requested_bytes) -> size_t { return fread(buffer, 1, requested_bytes, (FILE *)file_handle); };
|
||||
rc_filereader.close = [](void *file_handle) { fclose((FILE *)file_handle); };
|
||||
|
||||
// The caller should hold off on executing game code until this turns false, checking with IsBlockingExecution()
|
||||
g_isIdentifying = true;
|
||||
|
||||
// Apply pre-load settings.
|
||||
rc_client_set_encore_mode_enabled(g_rcClient, g_Config.bAchievementsEncoreMode ? 1 : 0);
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ bool IsLoggedIn();
|
|||
// Returns true if in a game, and achievements are active in the current game.
|
||||
bool IsActive();
|
||||
|
||||
// Returns true if the emulator should hold off on executing game code, such as during game identification.
|
||||
bool IsBlockingExecution();
|
||||
|
||||
/// Returns true if features such as save states should be disabled.
|
||||
bool ChallengeModeActive();
|
||||
|
||||
|
|
|
@ -1495,50 +1495,52 @@ void EmuScreen::render() {
|
|||
|
||||
Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops);
|
||||
|
||||
PSP_BeginHostFrame();
|
||||
bool blockedExecution = Achievements::IsBlockingExecution();
|
||||
if (!blockedExecution) {
|
||||
PSP_BeginHostFrame();
|
||||
PSP_RunLoopWhileState();
|
||||
|
||||
PSP_RunLoopWhileState();
|
||||
|
||||
// Hopefully coreState is now CORE_NEXTFRAME
|
||||
switch (coreState) {
|
||||
case CORE_NEXTFRAME:
|
||||
// Reached the end of the frame, all good. Set back to running for the next frame
|
||||
coreState = CORE_RUNNING;
|
||||
break;
|
||||
case CORE_STEPPING:
|
||||
case CORE_RUNTIME_ERROR:
|
||||
{
|
||||
// If there's an exception, display information.
|
||||
const MIPSExceptionInfo &info = Core_GetExceptionInfo();
|
||||
if (info.type != MIPSExceptionType::NONE) {
|
||||
// Clear to blue background screen
|
||||
bool dangerousSettings = !Reporting::IsSupported();
|
||||
uint32_t color = dangerousSettings ? 0xFF900050 : 0xFF900000;
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, color }, "EmuScreen_RuntimeError");
|
||||
// The info is drawn later in renderUI
|
||||
} 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);
|
||||
// Hopefully coreState is now CORE_NEXTFRAME
|
||||
switch (coreState) {
|
||||
case CORE_NEXTFRAME:
|
||||
// Reached the end of the frame, all good. Set back to running for the next frame
|
||||
coreState = CORE_RUNNING;
|
||||
break;
|
||||
case CORE_STEPPING:
|
||||
case CORE_RUNTIME_ERROR:
|
||||
{
|
||||
// If there's an exception, display information.
|
||||
const MIPSExceptionInfo &info = Core_GetExceptionInfo();
|
||||
if (info.type != MIPSExceptionType::NONE) {
|
||||
// Clear to blue background screen
|
||||
bool dangerousSettings = !Reporting::IsSupported();
|
||||
uint32_t color = dangerousSettings ? 0xFF900050 : 0xFF900000;
|
||||
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, color }, "EmuScreen_RuntimeError");
|
||||
// The info is drawn later in renderUI
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
PSP_EndHostFrame();
|
||||
PSP_EndHostFrame();
|
||||
|
||||
// This must happen after PSP_EndHostFrame so that things like push buffers are end-frame'd before we start destroying stuff.
|
||||
checkPowerDown();
|
||||
// This must happen after PSP_EndHostFrame so that things like push buffers are end-frame'd before we start destroying stuff.
|
||||
checkPowerDown();
|
||||
}
|
||||
|
||||
if (invalid_)
|
||||
return;
|
||||
|
|
Loading…
Add table
Reference in a new issue