From fa091a4f762956f70d6c517d560470dee8ba3d74 Mon Sep 17 00:00:00 2001 From: Souryo Date: Thu, 5 Oct 2017 19:44:37 -0400 Subject: [PATCH] Debugger: Lua - Async savestate functions + isKeyPressed --- Core/Debugger.cpp | 18 +++++++- Core/Debugger.h | 2 + Core/LuaApi.cpp | 56 ++++++++++++++++++++++++ Core/LuaApi.h | 7 +++ Core/LuaScriptingContext.cpp | 2 +- Core/LuaScriptingContext.h | 6 ++- Core/ScriptHost.cpp | 8 ++++ Core/ScriptHost.h | 1 + Core/ScriptingContext.cpp | 83 ++++++++++++++++++++++++++++++++++++ Core/ScriptingContext.h | 20 +++++++-- Linux/LinuxKeyManager.cpp | 50 +++++++++++----------- 11 files changed, 220 insertions(+), 33 deletions(-) diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 107f9023..cd3d6001 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -416,6 +416,8 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad { OperationInfo operationInfo { addr, (int16_t)value, type }; + ProcessCpuOperation(addr, value, type); + if(type == MemoryOperationType::ExecOpCode) { if(_runToCycle == 0) { _rewindCache.clear(); @@ -448,6 +450,7 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad _cpu->SetDebugPC(addr); _needRewind = false; } + ProcessScriptSaveState(addr, value); _currentReadAddr = &addr; _currentReadValue = &value; @@ -553,8 +556,6 @@ bool Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad _currentReadAddr = nullptr; _currentReadValue = nullptr; - ProcessCpuOperation(addr, value, type); - if(type == MemoryOperationType::Write) { if(_frozenAddresses[addr]) { return false; @@ -1083,6 +1084,19 @@ const char* Debugger::GetScriptLog(int32_t scriptId) return ""; } +void Debugger::ProcessScriptSaveState(uint16_t &addr, uint8_t &value) +{ + if(_hasScript) { + for(shared_ptr &script : _scripts) { + if(script->ProcessSavestate()) { + addr = _cpu->GetState().PC; + value = _memoryManager->DebugRead(addr, false); + _cpu->SetDebugPC(addr); + } + } + } +} + void Debugger::ProcessCpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type) { if(_hasScript) { diff --git a/Core/Debugger.h b/Core/Debugger.h index ed462c98..949ebb36 100644 --- a/Core/Debugger.h +++ b/Core/Debugger.h @@ -226,6 +226,8 @@ public: int32_t LoadScript(string content, int32_t scriptId); void RemoveScript(int32_t scriptId); const char* GetScriptLog(int32_t scriptId); + + void ProcessScriptSaveState(uint16_t &addr, uint8_t &value); void ProcessCpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type); void ProcessPpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type); void ProcessEvent(EventType type); diff --git a/Core/LuaApi.cpp b/Core/LuaApi.cpp index ee55d1d7..a16aade4 100644 --- a/Core/LuaApi.cpp +++ b/Core/LuaApi.cpp @@ -85,6 +85,11 @@ int LuaApi::GetLibrary(lua_State *lua) { "takeScreenshot", LuaApi::TakeScreenshot }, { "saveSavestate", LuaApi::SaveSavestate }, { "loadSavestate", LuaApi::LoadSavestate }, + { "saveSavestateAsync", LuaApi::SaveSavestateAsync }, + { "loadSavestateAsync", LuaApi::LoadSavestateAsync }, + { "getSavestateData", LuaApi::GetSavestateData }, + { "clearSavestateData", LuaApi::ClearSavestateData }, + { "isKeyPressed", LuaApi::IsKeyPressed }, { "getInput", LuaApi::GetInput }, { "setInput", LuaApi::SetInput }, { "addCheat", LuaApi::AddCheat }, @@ -517,6 +522,57 @@ int LuaApi::LoadSavestate(lua_State *lua) return l.ReturnCount(); } +int LuaApi::SaveSavestateAsync(lua_State *lua) +{ + LuaCallHelper l(lua); + int32_t slot = l.ReadInteger(); + checkparams(); + errorCond(slot < 0, "Slot must be >= 0"); + _context->RequestSaveState(slot); + return l.ReturnCount(); +} + +int LuaApi::LoadSavestateAsync(lua_State *lua) +{ + LuaCallHelper l(lua); + int32_t slot = l.ReadInteger(); + checkparams(); + errorCond(slot < 0, "Slot must be >= 0"); + _context->RequestLoadState(slot); + return l.ReturnCount(); +} + +int LuaApi::GetSavestateData(lua_State *lua) +{ + LuaCallHelper l(lua); + int32_t slot = l.ReadInteger(); + checkparams(); + errorCond(slot < 0, "Slot must be >= 0"); + l.Return(_context->GetSavestateData(slot)); + return l.ReturnCount(); +} + +int LuaApi::ClearSavestateData(lua_State *lua) +{ + LuaCallHelper l(lua); + int32_t slot = l.ReadInteger(); + checkparams(); + errorCond(slot < 0, "Slot must be >= 0"); + _context->ClearSavestateData(slot); + return l.ReturnCount(); +} + +int LuaApi::IsKeyPressed(lua_State *lua) +{ + LuaCallHelper l(lua); + string keyName = l.ReadString(); + checkparams(); + uint32_t keyCode = ControlManager::GetKeyCode(keyName); + errorCond(keyCode == 0, "Invalid key name"); + l.Return(ControlManager::IsKeyPressed(keyCode)); + return l.ReturnCount(); +} + int LuaApi::GetInput(lua_State *lua) { LuaCallHelper l(lua); diff --git a/Core/LuaApi.h b/Core/LuaApi.h index 73af8252..0887da89 100644 --- a/Core/LuaApi.h +++ b/Core/LuaApi.h @@ -52,6 +52,13 @@ public: static int SaveSavestate(lua_State *lua); static int LoadSavestate(lua_State *lua); + static int SaveSavestateAsync(lua_State *lua); + static int LoadSavestateAsync(lua_State *lua); + static int GetSavestateData(lua_State *lua); + static int ClearSavestateData(lua_State *lua); + + static int IsKeyPressed(lua_State *lua); + static int GetInput(lua_State *lua); static int SetInput(lua_State *lua); diff --git a/Core/LuaScriptingContext.cpp b/Core/LuaScriptingContext.cpp index 6a914409..f89fd7ce 100644 --- a/Core/LuaScriptingContext.cpp +++ b/Core/LuaScriptingContext.cpp @@ -40,7 +40,7 @@ bool LuaScriptingContext::LoadScript(string scriptContent, Debugger* debugger) return false; } -void LuaScriptingContext::CallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type) +void LuaScriptingContext::InternalCallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type) { LuaApi::SetContext(this); for(int &ref : _callbacks[(int)type][addr]) { diff --git a/Core/LuaScriptingContext.h b/Core/LuaScriptingContext.h index db415dd5..00d147f5 100644 --- a/Core/LuaScriptingContext.h +++ b/Core/LuaScriptingContext.h @@ -10,11 +10,13 @@ class LuaScriptingContext : public ScriptingContext private: lua_State* _lua = nullptr; +protected: + void InternalCallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type); + int InternalCallEventCallback(EventType type); + public: LuaScriptingContext(); ~LuaScriptingContext(); bool LoadScript(string scriptContent, Debugger* debugger); - void CallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type); - int InternalCallEventCallback(EventType type); }; diff --git a/Core/ScriptHost.cpp b/Core/ScriptHost.cpp index aa7b00b5..da67415f 100644 --- a/Core/ScriptHost.cpp +++ b/Core/ScriptHost.cpp @@ -58,3 +58,11 @@ void ScriptHost::ProcessEvent(EventType eventType) _context->CallEventCallback(eventType); } } + +bool ScriptHost::ProcessSavestate() +{ + if(_context) { + return _context->ProcessSavestate(); + } + return false; +} diff --git a/Core/ScriptHost.h b/Core/ScriptHost.h index b14c7648..feac6a2c 100644 --- a/Core/ScriptHost.h +++ b/Core/ScriptHost.h @@ -22,4 +22,5 @@ public: void ProcessCpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type); void ProcessPpuOperation(uint16_t addr, uint8_t &value, MemoryOperationType type); void ProcessEvent(EventType eventType); + bool ProcessSavestate(); }; \ No newline at end of file diff --git a/Core/ScriptingContext.cpp b/Core/ScriptingContext.cpp index b3eae98d..14604314 100644 --- a/Core/ScriptingContext.cpp +++ b/Core/ScriptingContext.cpp @@ -2,6 +2,7 @@ #include #include "ScriptingContext.h" #include "DebuggerTypes.h" +#include "Console.h" string ScriptingContext::_log = ""; @@ -25,6 +26,13 @@ const char* ScriptingContext::GetLog() return _log.c_str(); } +void ScriptingContext::CallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type) +{ + _inExecOpEvent = type == CallbackType::CpuExec; + InternalCallMemoryCallback(addr, value, type); + _inExecOpEvent = false; +} + int ScriptingContext::CallEventCallback(EventType type) { _inStartFrameEvent = type == EventType::StartFrame; @@ -88,3 +96,78 @@ void ScriptingContext::UnregisterEventCallback(EventType type, int reference) vector &callbacks = _eventCallbacks[(int)type]; callbacks.erase(std::remove(callbacks.begin(), callbacks.end(), reference), callbacks.end()); } + +void ScriptingContext::RequestSaveState(int slot) +{ + _saveSlot = slot; + if(_inExecOpEvent) { + SaveState(); + } else { + _saveSlotData.erase(slot); + } +} + +bool ScriptingContext::RequestLoadState(int slot) +{ + if(_saveSlotData.find(slot) != _saveSlotData.end()) { + _loadSlot = slot; + if(_inExecOpEvent) { + return LoadState(); + } else { + return true; + } + } + return false; +} + +void ScriptingContext::SaveState() +{ + if(_saveSlot >= 0) { + stringstream ss; + Console::SaveState(ss); + + ss.seekg(0, std::ios::end); + uint32_t fileSize = (uint32_t)ss.tellg(); + ss.seekg(0, std::ios::beg); + + _saveSlotData[_saveSlot] = ss.str(); + _saveSlot = -1; + } +} + +bool ScriptingContext::LoadState() +{ + if(_loadSlot >= 0 && _saveSlotData.find(_loadSlot) != _saveSlotData.end()) { + stringstream ss; + ss << _saveSlotData[_loadSlot]; + Console::LoadState(ss); + _loadSlot = -1; + return true; + } + return false; +} + +bool ScriptingContext::ProcessSavestate() +{ + SaveState(); + return LoadState(); +} + +string ScriptingContext::GetSavestateData(int slot) +{ + if(slot >= 0) { + auto result = _saveSlotData.find(slot); + if(result != _saveSlotData.end()) { + return result->second; + } + } + + return ""; +} + +void ScriptingContext::ClearSavestateData(int slot) +{ + if(slot >= 0) { + _saveSlotData.erase(slot); + } +} \ No newline at end of file diff --git a/Core/ScriptingContext.h b/Core/ScriptingContext.h index 5ff9f352..a9cba77c 100644 --- a/Core/ScriptingContext.h +++ b/Core/ScriptingContext.h @@ -25,23 +25,37 @@ private: std::deque _logRows; SimpleLock _logLock; bool _inStartFrameEvent = false; + bool _inExecOpEvent = false; + + std::unordered_map _saveSlotData; + int32_t _saveSlot = -1; + int32_t _loadSlot = -1; protected: vector _callbacks[5][0x10000]; vector _eventCallbacks[7]; + virtual void InternalCallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type) = 0; + virtual int InternalCallEventCallback(EventType type) = 0; + public: virtual bool LoadScript(string scriptContent, Debugger* debugger) = 0; void Log(string message); const char* GetLog(); - virtual void CallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type) = 0; - virtual int InternalCallEventCallback(EventType type) = 0; + void RequestSaveState(int slot); + bool RequestLoadState(int slot); + void SaveState(); + bool LoadState(); + string GetSavestateData(int slot); + void ClearSavestateData(int slot); + bool ProcessSavestate(); + void CallMemoryCallback(uint16_t addr, uint8_t &value, CallbackType type); int CallEventCallback(EventType type); bool CheckInStartFrameEvent(); - + void RegisterMemoryCallback(CallbackType type, int startAddr, int endAddr, int reference); void UnregisterMemoryCallback(CallbackType type, int startAddr, int endAddr, int reference); void RegisterEventCallback(EventType type, int reference); diff --git a/Linux/LinuxKeyManager.cpp b/Linux/LinuxKeyManager.cpp index 5f068ac0..7468eb6d 100755 --- a/Linux/LinuxKeyManager.cpp +++ b/Linux/LinuxKeyManager.cpp @@ -18,7 +18,7 @@ static vector _keyDefinitions = { { "", 19, "0", "" }, { "", 20, "-", "" }, { "", 21, "=", "" }, - { "", 22, "BackSpace", "" }, + { "", 22, "Backspace", "" }, { "", 23, "Tab", "" }, { "", 24, "Q", "" }, { "", 25, "W", "" }, @@ -30,9 +30,9 @@ static vector _keyDefinitions = { { "", 31, "I", "" }, { "", 32, "O", "" }, { "", 33, "P", "" }, - { "", 34, "Left Bracket", "" }, - { "", 35, "Right Bracket", "" }, - { "", 36, "Return", "" }, + { "", 34, "[", "" }, + { "", 35, "]", "" }, + { "", 36, "Enter", "" }, { "", 37, "Ctrl", "" }, { "", 38, "A", "" }, { "", 39, "S", "" }, @@ -43,9 +43,9 @@ static vector _keyDefinitions = { { "", 44, "J", "" }, { "", 45, "K", "" }, { "", 46, "L", "" }, - { "", 47, "Semicolor", "" }, - { "", 48, "Apostrophe", "" }, - { "", 49, "Grave", "" }, + { "", 47, ";", "" }, + { "", 48, "'", "" }, + { "", 49, "`", "" }, { "", 50, "Shift", "" }, { "", 51, "\\", "" }, { "", 52, "Z", "" }, @@ -59,7 +59,7 @@ static vector _keyDefinitions = { { "", 60, ".", "" }, { "", 61, "/", "" }, { "", 62, "Right Shift", "" }, - { "", 63, "KP Multiply", "" }, + { "", 63, "Numpad *", "" }, { "", 64, "Alt", "" }, { "", 65, "Space", "" }, { "", 66, "Caps Lock", "" }, @@ -75,19 +75,19 @@ static vector _keyDefinitions = { { "", 76, "F10", "" }, { "", 77, "Num Lock", "" }, { "", 78, "Scroll Lock", "" }, - { "", 79, "KP Home", "" }, - { "", 80, "KP Up", "" }, - { "", 81, "KP Prior", "" }, - { "", 82, "KP Subtract", "" }, - { "", 83, "KP Left", "" }, - { "", 84, "KP Begin", "" }, - { "", 85, "KP Right", "" }, - { "", 86, "KP Add", "" }, - { "", 87, "KP End", "" }, - { "", 88, "KP Down", "" }, - { "", 89, "KP Next", "" }, - { "", 90, "KP Insert", "" }, - { "", 91, "KP Delete", "" }, + { "", 79, "Numpad 7", "" }, + { "", 80, "Numpad 8", "" }, + { "", 81, "Numpad 9", "" }, + { "", 82, "Numpad -", "" }, + { "", 83, "Numpad 4", "" }, + { "", 84, "Numpad 5", "" }, + { "", 85, "Numpad 6", "" }, + { "", 86, "Numpad +", "" }, + { "", 87, "Numpad 1", "" }, + { "", 88, "Numpad 2", "" }, + { "", 89, "Numpad 3", "" }, + { "", 90, "Numpad 0", "" }, + { "", 91, "Numpad .", "" }, { "", 92, "ISO_Level3_Shift", "" }, { "", 94, "Less", "" }, { "", 95, "F11", "" }, @@ -97,20 +97,20 @@ static vector _keyDefinitions = { { "", 100, "Henkan_Mode", "" }, { "", 101, "Hiragana_Katakana", "" }, { "", 102, "Muhenkan", "" }, - { "", 104, "KP_Enter", "" }, + { "", 104, "Numpad Enter", "" }, { "", 105, "Control_R", "" }, - { "", 106, "KP_Divide", "" }, + { "", 106, "Numpad /", "" }, { "", 107, "Print", "" }, { "", 108, "Right Alt", "" }, { "", 109, "Linefeed", "" }, { "", 110, "Home", "" }, { "", 111, "Up Arrow", "" }, - { "", 112, "Prior", "" }, + { "", 112, "Page Up", "" }, { "", 113, "Left Arrow", "" }, { "", 114, "Right Arrow", "" }, { "", 115, "End", "" }, { "", 116, "Down Arrow", "" }, - { "", 117, "Next", "" }, + { "", 117, "Page Down", "" }, { "", 118, "Ins", "" }, { "", 119, "Delete", "" }, { "", 121, "XF86AudioMute", "" },