Debugger: Lua - Async savestate functions + isKeyPressed

This commit is contained in:
Souryo 2017-10-05 19:44:37 -04:00
parent 37bda93008
commit fa091a4f76
11 changed files with 220 additions and 33 deletions

View file

@ -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<ScriptHost> &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) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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]) {

View file

@ -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);
};

View file

@ -58,3 +58,11 @@ void ScriptHost::ProcessEvent(EventType eventType)
_context->CallEventCallback(eventType);
}
}
bool ScriptHost::ProcessSavestate()
{
if(_context) {
return _context->ProcessSavestate();
}
return false;
}

View file

@ -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();
};

View file

@ -2,6 +2,7 @@
#include <algorithm>
#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<int> &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);
}
}

View file

@ -25,23 +25,37 @@ private:
std::deque<string> _logRows;
SimpleLock _logLock;
bool _inStartFrameEvent = false;
bool _inExecOpEvent = false;
std::unordered_map<int32_t, string> _saveSlotData;
int32_t _saveSlot = -1;
int32_t _loadSlot = -1;
protected:
vector<int> _callbacks[5][0x10000];
vector<int> _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);

View file

@ -18,7 +18,7 @@ static vector<KeyDefinition> _keyDefinitions = {
{ "", 19, "0", "" },
{ "", 20, "-", "" },
{ "", 21, "=", "" },
{ "", 22, "BackSpace", "" },
{ "", 22, "Backspace", "" },
{ "", 23, "Tab", "" },
{ "", 24, "Q", "" },
{ "", 25, "W", "" },
@ -30,9 +30,9 @@ static vector<KeyDefinition> _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<KeyDefinition> _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<KeyDefinition> _keyDefinitions = {
{ "", 60, ".", "" },
{ "", 61, "/", "" },
{ "", 62, "Right Shift", "" },
{ "", 63, "KP Multiply", "" },
{ "", 63, "Numpad *", "" },
{ "", 64, "Alt", "" },
{ "", 65, "Space", "" },
{ "", 66, "Caps Lock", "" },
@ -75,19 +75,19 @@ static vector<KeyDefinition> _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<KeyDefinition> _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", "" },