From 3b2fed472e8306e8745a12e6aca1002e3fe89b63 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 14 Jun 2014 23:55:16 +0200 Subject: [PATCH] Correct timing on resume, avoids small speed burst when resuming gameplay from pause --- Core/HLE/sceDisplay.cpp | 17 ++++++++++++----- Core/HLE/sceDisplay.h | 5 ++++- Core/SaveState.cpp | 5 +++++ UI/MainScreen.cpp | 2 ++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index f353336fd5..4f55804d8e 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -103,6 +103,8 @@ static int brightnessLevel; static int mode; static int width; static int height; +static int wasPaused; + // Don't include this in the state, time increases regardless of state. static double curFrameTime; static double nextFrameTime; @@ -182,6 +184,7 @@ void __DisplayInit() { framebuf.pspFramebufLinesize = 480; // ?? lastFlipCycles = 0; lastFlipsTooFrequent = 0; + wasPaused = 0; enterVblankEvent = CoreTiming::RegisterEvent("EnterVBlank", &hleEnterVblank); leaveVblankEvent = CoreTiming::RegisterEvent("LeaveVBlank", &hleLeaveVblank); @@ -484,6 +487,10 @@ static float CalculateSmoothTimestep(float lastTimestep) { return summed / (float)ARRAY_SIZE(timestepSmooth); } +void __DisplaySetWasPaused() { + wasPaused = true; +} + // Let's collect all the throttling and frameskipping logic here. void DoFrameTiming(bool &throttle, bool &skipFrame, float lastTimestep) { float timestep = CalculateSmoothTimestep(lastTimestep); @@ -496,9 +503,7 @@ void DoFrameTiming(bool &throttle, bool &skipFrame, float lastTimestep) { // Check if the frameskipping code should be enabled. If neither throttling or frameskipping is on, // we have nothing to do here. bool doFrameSkip = g_Config.iFrameSkip != 0; - - if (!throttle && g_Config.bFrameSkipUnthrottle) { doFrameSkip = true; skipFrame = true; @@ -515,14 +520,16 @@ void DoFrameTiming(bool &throttle, bool &skipFrame, float lastTimestep) { time_update(); curFrameTime = time_now_d(); - if (nextFrameTime == 0.0) + if (nextFrameTime == 0.0 || wasPaused) { nextFrameTime = time_now_d() + timestep; + if (wasPaused) + wasPaused = false; + } - // Argh, we are falling behind! Let's skip a frame and see if we catch up. - // Auto-frameskip automatically if speed limit is set differently than the default. if (g_Config.bAutoFrameSkip || (g_Config.iFrameSkip == 0 && fpsLimiter == FPS_LIMIT_CUSTOM && g_Config.iFpsLimit > 60)) { // autoframeskip + // Argh, we are falling behind! Let's skip a frame and see if we catch up. if (curFrameTime > nextFrameTime && doFrameSkip) { skipFrame = true; } diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index 8c7336805c..ae270845bf 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -40,4 +40,7 @@ void __DisplayGetAveragedFPS(float *out_vps, float *out_fps); int __DisplayGetVCount(); int __DisplayGetFlipCount(); -void Register_sceDisplay_driver(); +// Call this when resuming to avoid a small speedup burst +void __DisplaySetWasPaused(); + +void Register_sceDisplay_driver(); \ No newline at end of file diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index f288d0a3af..33c438b285 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -33,6 +33,7 @@ #include "Core/FileSystems/MetaFileSystem.h" #include "Core/ELF/ParamSFO.h" #include "Core/HLE/HLE.h" +#include "Core/HLE/sceDisplay.h" #include "Core/HLE/ReplaceTables.h" #include "Core/HLE/sceKernel.h" #include "Core/MemMap.h" @@ -550,6 +551,10 @@ namespace SaveState if (op.callback) op.callback(callbackResult, op.cbUserData); } + if (operations.size()) { + // Avoid triggering frame skipping due to slowdown + __DisplaySetWasPaused(); + } } void Init() diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 1cb1afbe0a..c1b1bacc6c 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -49,6 +49,7 @@ #include "GPU/GPUInterface.h" #include "i18n/i18n.h" +#include "Core/HLE/sceDisplay.h" #include "Core/HLE/sceUmd.h" #ifdef _WIN32 @@ -984,6 +985,7 @@ GamePauseScreen::~GamePauseScreen() { g_Config.iCurrentStateSlot = saveSlots_->GetSelection(); g_Config.Save(); } + __DisplaySetWasPaused(); } void GamePauseScreen::CreateViews() {