Shortcuts: Allow "Run Single Frame" to auto-repeat after being held for over half a second

This commit is contained in:
Sour 2019-01-13 14:10:46 -05:00
parent e090f01642
commit 8027cd0c26
4 changed files with 69 additions and 30 deletions

View file

@ -785,7 +785,13 @@ void Console::Run()
_runLock.Acquire(); _runLock.Acquire();
} }
if(_pauseOnNextFrameRequested) {
//Used by "Run Single Frame" option
_settings->SetFlags(EmulationFlags::Paused);
_pauseOnNextFrameRequested = false;
}
bool pausedRequired = _settings->NeedsPause(); bool pausedRequired = _settings->NeedsPause();
if(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) { if(pausedRequired && !_stop && !_settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) {
_notificationManager->SendNotification(ConsoleNotificationType::GamePaused); _notificationManager->SendNotification(ConsoleNotificationType::GamePaused);
@ -914,6 +920,11 @@ bool Console::IsPaused()
} }
} }
void Console::PauseOnNextFrame()
{
_pauseOnNextFrameRequested = true;
}
void Console::UpdateNesModel(bool sendNotification) void Console::UpdateNesModel(bool sendNotification)
{ {
bool configChanged = false; bool configChanged = false;

View file

@ -90,6 +90,7 @@ private:
bool _running = false; bool _running = false;
int32_t _stopCode = 0; int32_t _stopCode = 0;
bool _pauseOnNextFrameRequested = false;
bool _resetRunTimers = false; bool _resetRunTimers = false;
bool _disableOcNextFrame = false; bool _disableOcNextFrame = false;
@ -206,6 +207,7 @@ public:
bool IsExecutionStopped(); bool IsExecutionStopped();
bool IsPaused(); bool IsPaused();
void PauseOnNextFrame();
void SetNextFrameOverclockStatus(bool disabled); void SetNextFrameOverclockStatus(bool disabled);

View file

@ -20,6 +20,7 @@ ShortcutKeyHandler::ShortcutKeyHandler(shared_ptr<Console> console)
_keySetIndex = 0; _keySetIndex = 0;
_isKeyUp = false; _isKeyUp = false;
_keyboardMode = false; _keyboardMode = false;
_repeatStarted = false;
_stopThread = false; _stopThread = false;
_thread = std::thread([=]() { _thread = std::thread([=]() {
@ -96,6 +97,25 @@ bool ShortcutKeyHandler::DetectKeyRelease(EmulatorShortcut shortcut)
return false; 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> debugger = _console->GetDebugger(false);
if(debugger) {
debugger->BreakOnScanline(241);
}
} else {
_console->PauseOnNextFrame();
settings->ClearFlags(EmulationFlags::Paused);
}
}
void ShortcutKeyHandler::CheckMappedKeys() void ShortcutKeyHandler::CheckMappedKeys()
{ {
EmulationSettings* settings = _console->GetSettings(); EmulationSettings* settings = _console->GetSettings();
@ -185,22 +205,12 @@ void ShortcutKeyHandler::CheckMappedKeys()
} }
if(DetectKeyPress(EmulatorShortcut::RunSingleFrame)) { if(DetectKeyPress(EmulatorShortcut::RunSingleFrame)) {
if(settings->CheckFlag(EmulationFlags::DebuggerWindowEnabled)) { ProcessRunSingleFrame();
shared_ptr<Debugger> debugger = _console->GetDebugger(false); }
if(debugger) {
debugger->BreakOnScanline(241); if(DetectKeyRelease(EmulatorShortcut::RunSingleFrame)) {
} _runSingleFrameRepeatTimer.reset();
} else { _repeatStarted = false;
if(settings->CheckFlag(EmulationFlags::Paused)) {
settings->ClearFlags(EmulationFlags::Paused);
_console->Pause();
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(50));
settings->SetFlags(EmulationFlags::Paused);
_console->Resume();
} else {
settings->SetFlags(EmulationFlags::Paused);
}
}
} }
if(!isNetplayClient && !MovieManager::Recording()) { if(!isNetplayClient && !MovieManager::Recording()) {
@ -239,26 +249,36 @@ void ShortcutKeyHandler::ProcessKeys()
_pressedKeys = KeyManager::GetPressedKeys(); _pressedKeys = KeyManager::GetPressedKeys();
_isKeyUp = _pressedKeys.size() < _lastPressedKeys.size(); _isKeyUp = _pressedKeys.size() < _lastPressedKeys.size();
bool noChange = false;
if(_pressedKeys.size() == _lastPressedKeys.size()) { if(_pressedKeys.size() == _lastPressedKeys.size()) {
bool noChange = true; noChange = true;
for(size_t i = 0; i < _pressedKeys.size(); i++) { for(size_t i = 0; i < _pressedKeys.size(); i++) {
if(_pressedKeys[i] != _lastPressedKeys[i]) { if(_pressedKeys[i] != _lastPressedKeys[i]) {
noChange = false; noChange = false;
break; 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;
} }

View file

@ -3,6 +3,7 @@
#include <thread> #include <thread>
#include <unordered_set> #include <unordered_set>
#include "../Utilities/SimpleLock.h" #include "../Utilities/SimpleLock.h"
#include "../Utilities/Timer.h"
#include "EmulationSettings.h" #include "EmulationSettings.h"
class Console; class Console;
@ -22,6 +23,9 @@ private:
bool _isKeyUp; bool _isKeyUp;
bool _keyboardMode; bool _keyboardMode;
shared_ptr<Timer> _runSingleFrameRepeatTimer;
bool _repeatStarted;
std::unordered_set<uint32_t> _keysDown[2]; std::unordered_set<uint32_t> _keysDown[2];
std::unordered_set<uint32_t> _prevKeysDown[2]; std::unordered_set<uint32_t> _prevKeysDown[2];
@ -34,6 +38,8 @@ private:
bool DetectKeyPress(EmulatorShortcut key); bool DetectKeyPress(EmulatorShortcut key);
bool DetectKeyRelease(EmulatorShortcut key); bool DetectKeyRelease(EmulatorShortcut key);
void ProcessRunSingleFrame();
public: public:
ShortcutKeyHandler(shared_ptr<Console> console); ShortcutKeyHandler(shared_ptr<Console> console);
~ShortcutKeyHandler(); ~ShortcutKeyHandler();