From 8027cd0c26d4e28ee40c560a6040f433ce9ea7d0 Mon Sep 17 00:00:00 2001 From: Sour Date: Sun, 13 Jan 2019 14:10:46 -0500 Subject: [PATCH] Shortcuts: Allow "Run Single Frame" to auto-repeat after being held for over half a second --- Core/Console.cpp | 13 ++++++- Core/Console.h | 2 + Core/ShortcutKeyHandler.cpp | 78 +++++++++++++++++++++++-------------- Core/ShortcutKeyHandler.h | 6 +++ 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Core/Console.cpp b/Core/Console.cpp index 77cf7877..b73b8421 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -785,7 +785,13 @@ void Console::Run() _runLock.Acquire(); } - + + if(_pauseOnNextFrameRequested) { + //Used by "Run Single Frame" option + _settings->SetFlags(EmulationFlags::Paused); + _pauseOnNextFrameRequested = false; + } + bool pausedRequired = _settings->NeedsPause(); if(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) { _notificationManager->SendNotification(ConsoleNotificationType::GamePaused); @@ -914,6 +920,11 @@ bool Console::IsPaused() } } +void Console::PauseOnNextFrame() +{ + _pauseOnNextFrameRequested = true; +} + void Console::UpdateNesModel(bool sendNotification) { bool configChanged = false; diff --git a/Core/Console.h b/Core/Console.h index 3109658c..183fd106 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -90,6 +90,7 @@ private: bool _running = false; int32_t _stopCode = 0; + bool _pauseOnNextFrameRequested = false; bool _resetRunTimers = false; bool _disableOcNextFrame = false; @@ -206,6 +207,7 @@ public: bool IsExecutionStopped(); bool IsPaused(); + void PauseOnNextFrame(); void SetNextFrameOverclockStatus(bool disabled); diff --git a/Core/ShortcutKeyHandler.cpp b/Core/ShortcutKeyHandler.cpp index cef74c82..c22f9540 100644 --- a/Core/ShortcutKeyHandler.cpp +++ b/Core/ShortcutKeyHandler.cpp @@ -20,6 +20,7 @@ ShortcutKeyHandler::ShortcutKeyHandler(shared_ptr console) _keySetIndex = 0; _isKeyUp = false; _keyboardMode = false; + _repeatStarted = false; _stopThread = false; _thread = std::thread([=]() { @@ -96,6 +97,25 @@ bool ShortcutKeyHandler::DetectKeyRelease(EmulatorShortcut shortcut) return false; } +void ShortcutKeyHandler::ProcessRunSingleFrame() +{ + EmulationSettings* settings = _console->GetSettings(); + if(!_runSingleFrameRepeatTimer) { + _runSingleFrameRepeatTimer.reset(new Timer()); + } + _runSingleFrameRepeatTimer->Reset(); + + if(settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) { + shared_ptr debugger = _console->GetDebugger(false); + if(debugger) { + debugger->BreakOnScanline(241); + } + } else { + _console->PauseOnNextFrame(); + settings->ClearFlags(EmulationFlags::Paused); + } +} + void ShortcutKeyHandler::CheckMappedKeys() { EmulationSettings* settings = _console->GetSettings(); @@ -185,22 +205,12 @@ void ShortcutKeyHandler::CheckMappedKeys() } if(DetectKeyPress(EmulatorShortcut::RunSingleFrame)) { - if(settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) { - shared_ptr debugger = _console->GetDebugger(false); - if(debugger) { - debugger->BreakOnScanline(241); - } - } else { - if(settings->CheckFlag(EmulationFlags::Paused)) { - settings->ClearFlags(EmulationFlags::Paused); - _console->Pause(); - std::this_thread::sleep_for(std::chrono::duration(50)); - settings->SetFlags(EmulationFlags::Paused); - _console->Resume(); - } else { - settings->SetFlags(EmulationFlags::Paused); - } - } + ProcessRunSingleFrame(); + } + + if(DetectKeyRelease(EmulatorShortcut::RunSingleFrame)) { + _runSingleFrameRepeatTimer.reset(); + _repeatStarted = false; } if(!isNetplayClient && !MovieManager::Recording()) { @@ -239,26 +249,36 @@ void ShortcutKeyHandler::ProcessKeys() _pressedKeys = KeyManager::GetPressedKeys(); _isKeyUp = _pressedKeys.size() < _lastPressedKeys.size(); + bool noChange = false; if(_pressedKeys.size() == _lastPressedKeys.size()) { - bool noChange = true; + noChange = true; for(size_t i = 0; i < _pressedKeys.size(); i++) { if(_pressedKeys[i] != _lastPressedKeys[i]) { noChange = false; break; } } - if(noChange) { - //Same keys as before, nothing to do - return; + } + + if(!noChange) { + //Only run this if the keys have changed + for(int i = 0; i < 2; i++) { + _keysDown[i].clear(); + _keySetIndex = i; + CheckMappedKeys(); + _prevKeysDown[i] = _keysDown[i]; + } + + _lastPressedKeys = _pressedKeys; + } + + if(_runSingleFrameRepeatTimer) { + double elapsedMs = _runSingleFrameRepeatTimer->GetElapsedMS(); + if(_repeatStarted && elapsedMs >= 50 || !_repeatStarted && elapsedMs >= 500) { + //Over 500ms has elapsed since the key was first pressed, or over 50ms since repeat mode started (20fps) + //In this case, run another frame and pause again. + _repeatStarted = true; + ProcessRunSingleFrame(); } } - - for(int i = 0; i < 2; i++) { - _keysDown[i].clear(); - _keySetIndex = i; - CheckMappedKeys(); - _prevKeysDown[i] = _keysDown[i]; - } - - _lastPressedKeys = _pressedKeys; } \ No newline at end of file diff --git a/Core/ShortcutKeyHandler.h b/Core/ShortcutKeyHandler.h index 498d9e1f..ad49d357 100644 --- a/Core/ShortcutKeyHandler.h +++ b/Core/ShortcutKeyHandler.h @@ -3,6 +3,7 @@ #include #include #include "../Utilities/SimpleLock.h" +#include "../Utilities/Timer.h" #include "EmulationSettings.h" class Console; @@ -22,6 +23,9 @@ private: bool _isKeyUp; bool _keyboardMode; + shared_ptr _runSingleFrameRepeatTimer; + bool _repeatStarted; + std::unordered_set _keysDown[2]; std::unordered_set _prevKeysDown[2]; @@ -34,6 +38,8 @@ private: bool DetectKeyPress(EmulatorShortcut key); bool DetectKeyRelease(EmulatorShortcut key); + void ProcessRunSingleFrame(); + public: ShortcutKeyHandler(shared_ptr console); ~ShortcutKeyHandler();