diff --git a/Core/Console.cpp b/Core/Console.cpp
index e5b0baa..67d57c5 100644
--- a/Core/Console.cpp
+++ b/Core/Console.cpp
@@ -13,9 +13,11 @@
#include "VideoDecoder.h"
#include "VideoRenderer.h"
#include "DebugHud.h"
+#include "FrameLimiter.h"
#include "MessageManager.h"
#include "../Utilities/Timer.h"
#include "../Utilities/VirtualFile.h"
+#include "../Utilities/PlatformUtilities.h"
void Console::Initialize()
{
@@ -49,11 +51,24 @@ void Console::Run()
}
_stopFlag = false;
+ uint32_t previousFrameCount = 0;
+
+ FrameLimiter frameLimiter(16.63926405550947);
+
+ PlatformUtilities::EnableHighResolutionTimer();
auto lock = _runLock.AcquireSafe();
while(!_stopFlag) {
_cpu->Exec();
+
+ if(previousFrameCount != _ppu->GetFrameCount()) {
+ frameLimiter.ProcessFrame();
+ frameLimiter.WaitForNextFrame();
+ previousFrameCount = _ppu->GetFrameCount();
+ }
}
+
+ PlatformUtilities::RestoreTimerResolution();
}
void Console::Stop()
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 8bec523..b6b2c63 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -70,6 +70,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index fdc2901..3878ada 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -170,6 +170,9 @@
SNES\Input
+
+ SNES
+
diff --git a/Core/FrameLimiter.h b/Core/FrameLimiter.h
new file mode 100644
index 0000000..0d0bcc9
--- /dev/null
+++ b/Core/FrameLimiter.h
@@ -0,0 +1,45 @@
+#pragma once
+#include "../Utilities/Timer.h"
+
+class FrameLimiter
+{
+private:
+ Timer _clockTimer;
+ double _targetTime;
+ double _delay;
+ bool _resetRunTimers;
+
+public:
+ FrameLimiter(double delay)
+ {
+ _delay = delay;
+ _targetTime = _delay;
+ }
+
+ void SetDelay(double delay)
+ {
+ _delay = delay;
+ _resetRunTimers = true;
+ }
+
+ void ProcessFrame()
+ {
+ if(_resetRunTimers || (_clockTimer.GetElapsedMS() - _targetTime) > 300) {
+ //Reset the timers, this can happen in 3 scenarios:
+ //1) Target frame rate changed
+ //2) The console was reset/power cycled or the emulation was paused (with or without the debugger)
+ //3) As a satefy net, if we overshoot our target by over 300 milliseconds, the timer is reset, too.
+ // This can happen when something slows the emulator down severely (or when breaking execution in VS when debugging Mesen itself, etc.)
+ _clockTimer.Reset();
+ _targetTime = 0;
+ _resetRunTimers = false;
+ }
+
+ _targetTime += _delay;
+ }
+
+ void WaitForNextFrame()
+ {
+ _clockTimer.WaitUntil(_targetTime);
+ }
+};
\ No newline at end of file