2019-03-11 17:56:54 -04:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "ShortcutKeyHandler.h"
|
|
|
|
#include "EmuSettings.h"
|
|
|
|
#include "KeyManager.h"
|
|
|
|
#include "VideoDecoder.h"
|
|
|
|
#include "ControlManager.h"
|
|
|
|
#include "Console.h"
|
2019-03-12 12:06:42 -04:00
|
|
|
#include "RewindManager.h"
|
2019-03-11 17:56:54 -04:00
|
|
|
#include "NotificationManager.h"
|
2019-03-31 14:50:12 -04:00
|
|
|
#include "SaveStateManager.h"
|
2019-08-09 16:25:59 -04:00
|
|
|
#include "MovieManager.h"
|
2019-10-20 20:05:39 -04:00
|
|
|
#include "GameClient.h"
|
2019-03-11 17:56:54 -04:00
|
|
|
|
|
|
|
ShortcutKeyHandler::ShortcutKeyHandler(shared_ptr<Console> console)
|
|
|
|
{
|
|
|
|
_console = console;
|
|
|
|
_keySetIndex = 0;
|
|
|
|
_isKeyUp = false;
|
|
|
|
_repeatStarted = false;
|
|
|
|
|
|
|
|
_stopThread = false;
|
2021-03-10 11:13:28 -05:00
|
|
|
_thread = std::thread([=]() {
|
|
|
|
while(!_stopThread) {
|
2019-03-11 17:56:54 -04:00
|
|
|
ProcessKeys();
|
|
|
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(50));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ShortcutKeyHandler::~ShortcutKeyHandler()
|
|
|
|
{
|
|
|
|
_stopThread = true;
|
|
|
|
_thread.join();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShortcutKeyHandler::IsKeyPressed(EmulatorShortcut shortcut)
|
|
|
|
{
|
|
|
|
KeyCombination keyComb = _console->GetSettings()->GetShortcutKey(shortcut, _keySetIndex);
|
|
|
|
vector<KeyCombination> supersets = _console->GetSettings()->GetShortcutSupersets(shortcut, _keySetIndex);
|
2021-03-10 11:13:28 -05:00
|
|
|
for(KeyCombination &superset : supersets) {
|
|
|
|
if(IsKeyPressed(superset)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
//A superset is pressed, ignore this subset
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//No supersets are pressed, check if all matching keys are pressed
|
|
|
|
return IsKeyPressed(keyComb);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShortcutKeyHandler::IsKeyPressed(KeyCombination comb)
|
|
|
|
{
|
|
|
|
int keyCount = (comb.Key1 ? 1 : 0) + (comb.Key2 ? 1 : 0) + (comb.Key3 ? 1 : 0);
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(keyCount == 0 || _pressedKeys.empty()) {
|
2019-03-11 17:56:54 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsKeyPressed(comb.Key1) &&
|
|
|
|
(comb.Key2 == 0 || IsKeyPressed(comb.Key2)) &&
|
|
|
|
(comb.Key3 == 0 || IsKeyPressed(comb.Key3));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShortcutKeyHandler::IsKeyPressed(uint32_t keyCode)
|
|
|
|
{
|
2019-03-12 12:06:42 -04:00
|
|
|
return KeyManager::IsKeyPressed(keyCode);
|
2019-03-11 17:56:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ShortcutKeyHandler::DetectKeyPress(EmulatorShortcut shortcut)
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(IsKeyPressed(shortcut)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
bool newlyPressed = _prevKeysDown[_keySetIndex].find((uint32_t)shortcut) == _prevKeysDown[_keySetIndex].end();
|
|
|
|
_keysDown[_keySetIndex].emplace((uint32_t)shortcut);
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(newlyPressed && !_isKeyUp) {
|
2019-03-11 17:56:54 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShortcutKeyHandler::DetectKeyRelease(EmulatorShortcut shortcut)
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!IsKeyPressed(shortcut)) {
|
|
|
|
if(_prevKeysDown[_keySetIndex].find((uint32_t)shortcut) != _prevKeysDown[_keySetIndex].end()) {
|
2019-03-11 17:56:54 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShortcutKeyHandler::ProcessRunSingleFrame()
|
|
|
|
{
|
2020-05-08 22:15:27 -04:00
|
|
|
shared_ptr<Timer> timer = _runSingleFrameRepeatTimer;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!timer) {
|
2020-05-08 22:15:27 -04:00
|
|
|
timer.reset(new Timer());
|
|
|
|
_runSingleFrameRepeatTimer = timer;
|
2019-03-11 17:56:54 -04:00
|
|
|
}
|
2020-05-08 22:15:27 -04:00
|
|
|
timer->Reset();
|
2019-03-11 17:56:54 -04:00
|
|
|
|
2019-07-16 21:02:56 -04:00
|
|
|
_console->PauseOnNextFrame();
|
2019-03-11 17:56:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShortcutKeyHandler::CheckMappedKeys()
|
|
|
|
{
|
|
|
|
shared_ptr<EmuSettings> settings = _console->GetSettings();
|
2019-10-20 20:05:39 -04:00
|
|
|
bool isNetplayClient = GameClient::Connected();
|
|
|
|
bool isMovieActive = _console->GetMovieManager()->Playing() || _console->GetMovieManager()->Recording();
|
2019-10-16 20:22:45 -04:00
|
|
|
bool isMovieRecording = _console->GetMovieManager()->Recording();
|
2019-03-11 17:56:54 -04:00
|
|
|
|
|
|
|
//Let the UI handle these shortcuts
|
2021-03-10 11:13:28 -05:00
|
|
|
for(uint64_t i = (uint64_t)EmulatorShortcut::TakeScreenshot; i < (uint64_t)EmulatorShortcut::ShortcutCount; i++) {
|
|
|
|
if(DetectKeyPress((EmulatorShortcut)i)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
void* param = (void*)i;
|
|
|
|
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::ExecuteShortcut, param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::FastForward)) {
|
2019-03-12 12:06:42 -04:00
|
|
|
settings->SetFlag(EmulationFlags::Turbo);
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(DetectKeyRelease(EmulatorShortcut::FastForward)) {
|
2019-03-12 12:06:42 -04:00
|
|
|
settings->ClearFlag(EmulationFlags::Turbo);
|
2019-03-11 17:56:54 -04:00
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::ToggleFastForward)) {
|
|
|
|
if(settings->CheckFlag(EmulationFlags::Turbo)) {
|
2019-03-12 12:06:42 -04:00
|
|
|
settings->ClearFlag(EmulationFlags::Turbo);
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-03-12 12:06:42 -04:00
|
|
|
settings->SetFlag(EmulationFlags::Turbo);
|
2019-03-11 17:56:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
for(int i = 0; i < 10; i++) {
|
|
|
|
if(DetectKeyPress((EmulatorShortcut)((int)EmulatorShortcut::SelectSaveSlot1 + i))) {
|
2019-12-26 14:11:33 -05:00
|
|
|
_console->GetSaveStateManager()->SelectSaveSlot(i + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::MoveToNextStateSlot)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
_console->GetSaveStateManager()->MoveToNextSlot();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::MoveToPreviousStateSlot)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
_console->GetSaveStateManager()->MoveToPreviousSlot();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::SaveState)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
_console->GetSaveStateManager()->SaveState();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::LoadState)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
_console->GetSaveStateManager()->LoadState();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::ToggleCheats) && !isNetplayClient && !isMovieActive) {
|
|
|
|
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::ExecuteShortcut, (void*)EmulatorShortcut::ToggleCheats);
|
2019-10-20 20:05:39 -04:00
|
|
|
}
|
2019-03-11 17:56:54 -04:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::RunSingleFrame)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
ProcessRunSingleFrame();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyRelease(EmulatorShortcut::RunSingleFrame)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
_runSingleFrameRepeatTimer.reset();
|
|
|
|
_repeatStarted = false;
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!isNetplayClient && !isMovieRecording) {
|
2019-03-12 12:06:42 -04:00
|
|
|
shared_ptr<RewindManager> rewindManager = _console->GetRewindManager();
|
2021-03-10 11:13:28 -05:00
|
|
|
if(rewindManager) {
|
|
|
|
if(DetectKeyPress(EmulatorShortcut::ToggleRewind)) {
|
|
|
|
if(rewindManager->IsRewinding()) {
|
2019-03-11 17:56:54 -04:00
|
|
|
rewindManager->StopRewinding();
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2019-03-11 17:56:54 -04:00
|
|
|
rewindManager->StartRewinding();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(DetectKeyPress(EmulatorShortcut::Rewind)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
rewindManager->StartRewinding();
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(DetectKeyRelease(EmulatorShortcut::Rewind)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
rewindManager->StopRewinding();
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(DetectKeyPress(EmulatorShortcut::RewindTenSecs)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
rewindManager->RewindSeconds(10);
|
2021-03-10 11:13:28 -05:00
|
|
|
} else if(DetectKeyPress(EmulatorShortcut::RewindOneMin)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
rewindManager->RewindSeconds(60);
|
|
|
|
}
|
2019-03-12 12:06:42 -04:00
|
|
|
}
|
2019-03-11 17:56:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShortcutKeyHandler::ProcessKeys()
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!_console->GetSettings()->IsInputEnabled()) {
|
2019-03-11 17:56:54 -04:00
|
|
|
return;
|
2019-10-19 16:13:11 -04:00
|
|
|
}
|
2019-03-11 17:56:54 -04:00
|
|
|
|
|
|
|
auto lock = _lock.AcquireSafe();
|
|
|
|
KeyManager::RefreshKeyState();
|
|
|
|
|
|
|
|
_pressedKeys = KeyManager::GetPressedKeys();
|
|
|
|
_isKeyUp = _pressedKeys.size() < _lastPressedKeys.size();
|
|
|
|
|
|
|
|
bool noChange = false;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_pressedKeys.size() == _lastPressedKeys.size()) {
|
2019-03-11 17:56:54 -04:00
|
|
|
noChange = true;
|
2021-03-10 11:13:28 -05:00
|
|
|
for(size_t i = 0; i < _pressedKeys.size(); i++) {
|
|
|
|
if(_pressedKeys[i] != _lastPressedKeys[i]) {
|
2019-03-11 17:56:54 -04:00
|
|
|
noChange = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!noChange) {
|
2019-03-11 17:56:54 -04:00
|
|
|
//Only run this if the keys have changed
|
2021-03-10 11:13:28 -05:00
|
|
|
for(int i = 0; i < 2; i++) {
|
2019-03-11 17:56:54 -04:00
|
|
|
_keysDown[i].clear();
|
|
|
|
_keySetIndex = i;
|
|
|
|
CheckMappedKeys();
|
|
|
|
_prevKeysDown[i] = _keysDown[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
_lastPressedKeys = _pressedKeys;
|
|
|
|
}
|
|
|
|
|
2020-05-08 22:15:27 -04:00
|
|
|
shared_ptr<Timer> timer = _runSingleFrameRepeatTimer;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(timer) {
|
2020-05-08 22:15:27 -04:00
|
|
|
double elapsedMs = timer->GetElapsedMS();
|
2021-03-10 11:13:28 -05:00
|
|
|
if((_repeatStarted && elapsedMs >= 50) || (!_repeatStarted && elapsedMs >= 500)) {
|
2019-03-11 17:56:54 -04:00
|
|
|
//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();
|
|
|
|
}
|
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
}
|