mirror of https://github.com/SourMesen/Mesen2
Debugger: Lua - Support small arrays in getState/setState
This is needed to e.g have access to the GBA CPU's registers, etc. Also hid some internal GBA state from getState to improve performance
This commit is contained in:
parent
fb2a9c7f6f
commit
a17a97fb7b
|
|
@ -1075,7 +1075,7 @@ int LuaApi::GetState(lua_State *lua)
|
|||
|
||||
Serializer s(0, true, SerializeFormat::Map);
|
||||
s.Stream(*_emu->GetConsole().get(), "", -1);
|
||||
|
||||
|
||||
//Add some more Lua-specific values
|
||||
uint32_t frameCount = _emu->GetFrameCount();
|
||||
uint32_t masterClock = _emu->GetMasterClock();
|
||||
|
|
@ -1093,12 +1093,12 @@ int LuaApi::GetState(lua_State *lua)
|
|||
|
||||
lua_newtable(lua);
|
||||
for(auto& kvp : values) {
|
||||
lua_pushstring(lua, kvp.first.c_str());
|
||||
lua_pushlstring(lua, kvp.first.c_str(), kvp.first.size());
|
||||
switch(kvp.second.Format) {
|
||||
case SerializeMapValueFormat::Integer: lua_pushinteger(lua, kvp.second.Value.Integer); break;
|
||||
case SerializeMapValueFormat::Double: lua_pushnumber(lua, kvp.second.Value.Double); break;
|
||||
case SerializeMapValueFormat::Bool: lua_pushboolean(lua, kvp.second.Value.Bool); break;
|
||||
case SerializeMapValueFormat::String: lua_pushstring(lua, kvp.second.StringValue.c_str()); break;
|
||||
case SerializeMapValueFormat::String: lua_pushlstring(lua, kvp.second.StringValue.c_str(), kvp.second.StringValue.size()); break;
|
||||
}
|
||||
lua_settable(lua, -3);
|
||||
}
|
||||
|
|
@ -1107,7 +1107,6 @@ int LuaApi::GetState(lua_State *lua)
|
|||
|
||||
int LuaApi::SetState(lua_State* lua)
|
||||
{
|
||||
LuaCallHelper l(lua);
|
||||
lua_settop(lua, 1);
|
||||
luaL_checktype(lua, -1, LUA_TTABLE);
|
||||
|
||||
|
|
@ -1146,17 +1145,5 @@ int LuaApi::SetState(lua_State* lua)
|
|||
s.LoadFromMap(map);
|
||||
|
||||
s.Stream(*_emu->GetConsole().get(), "", -1);
|
||||
unordered_map<string, SerializeMapValue>& values = s.GetMapValues();
|
||||
|
||||
lua_newtable(lua);
|
||||
for(auto& kvp : values) {
|
||||
lua_pushstring(lua, kvp.first.c_str());
|
||||
switch(kvp.second.Format) {
|
||||
case SerializeMapValueFormat::Integer: lua_pushinteger(lua, kvp.second.Value.Integer); break;
|
||||
case SerializeMapValueFormat::Double: lua_pushnumber(lua, kvp.second.Value.Double); break;
|
||||
case SerializeMapValueFormat::Bool: lua_pushboolean(lua, kvp.second.Value.Bool); break;
|
||||
}
|
||||
lua_settable(lua, -3);
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -552,17 +552,19 @@ void GbaApu::Serialize(Serializer& s)
|
|||
SV(_state.Bias);
|
||||
SV(_state.SamplingRate);
|
||||
|
||||
SV(_prevClockCount);
|
||||
SV(_enabledChannels);
|
||||
SV(_leftSample);
|
||||
SV(_rightSample);
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SV(_prevClockCount);
|
||||
SV(_enabledChannels);
|
||||
SV(_leftSample);
|
||||
SV(_rightSample);
|
||||
|
||||
SV(_fifo[0]);
|
||||
SV(_fifo[1]);
|
||||
SV(_filterL);
|
||||
SV(_filterR);
|
||||
SV(_fifo[0]);
|
||||
SV(_fifo[1]);
|
||||
SV(_filterL);
|
||||
SV(_filterR);
|
||||
|
||||
SV(_powerOnCycle);
|
||||
SV(_powerOnCycle);
|
||||
}
|
||||
|
||||
SV(_square1);
|
||||
SV(_square2);
|
||||
|
|
|
|||
|
|
@ -331,35 +331,39 @@ void GbaDmaController::WriteRegister(uint32_t addr, uint8_t value)
|
|||
void GbaDmaController::Serialize(Serializer& s)
|
||||
{
|
||||
for(int i = 0; i < 4; i++) {
|
||||
SVI(_state.Ch[i].ReadValue);
|
||||
SVI(_state.Ch[i].Control);
|
||||
|
||||
SVI(_state.Ch[i].Destination);
|
||||
SVI(_state.Ch[i].Source);
|
||||
SVI(_state.Ch[i].Length);
|
||||
|
||||
SVI(_state.Ch[i].DestLatch);
|
||||
SVI(_state.Ch[i].SrcLatch);
|
||||
SVI(_state.Ch[i].LenLatch);
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SVI(_state.Ch[i].DestLatch);
|
||||
SVI(_state.Ch[i].SrcLatch);
|
||||
SVI(_state.Ch[i].LenLatch);
|
||||
|
||||
SVI(_state.Ch[i].Control);
|
||||
SVI(_state.Ch[i].ReadValue);
|
||||
|
||||
SVI(_state.Ch[i].DestMode);
|
||||
SVI(_state.Ch[i].SrcMode);
|
||||
SVI(_state.Ch[i].DestMode);
|
||||
SVI(_state.Ch[i].SrcMode);
|
||||
|
||||
SVI(_state.Ch[i].Repeat);
|
||||
SVI(_state.Ch[i].WordTransfer);
|
||||
SVI(_state.Ch[i].DrqMode);
|
||||
SVI(_state.Ch[i].Repeat);
|
||||
SVI(_state.Ch[i].WordTransfer);
|
||||
SVI(_state.Ch[i].DrqMode);
|
||||
|
||||
SVI(_state.Ch[i].Trigger);
|
||||
SVI(_state.Ch[i].IrqEnabled);
|
||||
SVI(_state.Ch[i].Enabled);
|
||||
SVI(_state.Ch[i].Active);
|
||||
SVI(_state.Ch[i].Trigger);
|
||||
SVI(_state.Ch[i].IrqEnabled);
|
||||
SVI(_state.Ch[i].Enabled);
|
||||
SVI(_state.Ch[i].Active);
|
||||
|
||||
SVI(_state.Ch[i].Pending);
|
||||
SVI(_state.Ch[i].Pending);
|
||||
}
|
||||
}
|
||||
|
||||
SV(_dmaRunning);
|
||||
SV(_dmaPending);
|
||||
SV(_dmaActiveChannel);
|
||||
SV(_dmaStartDelay);
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SV(_dmaRunning);
|
||||
SV(_dmaPending);
|
||||
SV(_dmaActiveChannel);
|
||||
SV(_dmaStartDelay);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -867,36 +867,42 @@ int64_t GbaMemoryManager::GetRelativeAddress(AddressInfo& absAddress)
|
|||
void GbaMemoryManager::Serialize(Serializer& s)
|
||||
{
|
||||
SV(_masterClock);
|
||||
SV(_hasPendingUpdates);
|
||||
SV(_hasPendingLateUpdates);
|
||||
SV(_pendingIrqSource);
|
||||
SV(_pendingIrqSourceDelay);
|
||||
SV(_haltModeUsed);
|
||||
SV(_biosLocked);
|
||||
|
||||
SV(_state.IE);
|
||||
SV(_state.IF);
|
||||
SV(_state.IME);
|
||||
|
||||
SV(_state.NewIE);
|
||||
SV(_state.NewIF);
|
||||
SV(_state.NewIME);
|
||||
|
||||
SV(_state.WaitControl);
|
||||
SVArray(_state.PrgWaitStates0, 2);
|
||||
SVArray(_state.PrgWaitStates1, 2);
|
||||
SVArray(_state.PrgWaitStates2, 2);
|
||||
SV(_state.SramWaitStates);
|
||||
SV(_state.PrefetchEnabled);
|
||||
SV(_state.IME);
|
||||
SV(_state.IrqUpdateCounter);
|
||||
SV(_state.IrqPending);
|
||||
SV(_state.IrqLine);
|
||||
SV(_state.BusLocked);
|
||||
SV(_state.StopMode);
|
||||
SV(_state.PostBootFlag);
|
||||
|
||||
SVArray(_state.BootRomOpenBus, 4);
|
||||
SVArray(_state.InternalOpenBus, 4);
|
||||
SVArray(_state.IwramOpenBus, 4);
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SV(_hasPendingUpdates);
|
||||
SV(_hasPendingLateUpdates);
|
||||
SV(_pendingIrqSource);
|
||||
SV(_pendingIrqSourceDelay);
|
||||
SV(_haltModeUsed);
|
||||
SV(_biosLocked);
|
||||
|
||||
SVArray(_state.BootRomOpenBus, 4);
|
||||
SVArray(_state.InternalOpenBus, 4);
|
||||
SVArray(_state.IwramOpenBus, 4);
|
||||
|
||||
SVArray(_state.PrgWaitStates0, 2);
|
||||
SVArray(_state.PrgWaitStates1, 2);
|
||||
SVArray(_state.PrgWaitStates2, 2);
|
||||
SV(_state.SramWaitStates);
|
||||
|
||||
SV(_state.IrqUpdateCounter);
|
||||
SV(_state.IrqPending);
|
||||
SV(_state.IrqLine);
|
||||
SV(_state.BusLocked);
|
||||
SV(_state.StopMode);
|
||||
SV(_state.PostBootFlag);
|
||||
}
|
||||
|
||||
if(!s.IsSaving()) {
|
||||
GenerateWaitStateLut();
|
||||
|
|
|
|||
|
|
@ -226,6 +226,10 @@ public:
|
|||
|
||||
void Serialize(Serializer& s) override
|
||||
{
|
||||
if(s.GetFormat() == SerializeFormat::Map) {
|
||||
return;
|
||||
}
|
||||
|
||||
SV(_state.ClockCounter);
|
||||
SV(_state.ReadAddr);
|
||||
SV(_state.PrefetchAddr);
|
||||
|
|
|
|||
|
|
@ -177,18 +177,8 @@ public:
|
|||
|
||||
void Serialize(Serializer& s) override
|
||||
{
|
||||
SV(_state.StartMasterClock);
|
||||
SV(_state.EndMasterClock);
|
||||
SV(_state.IrqMasterClock);
|
||||
|
||||
SVArray(_state.Data, 4);
|
||||
|
||||
SV(_state.Control);
|
||||
SV(_state.InternalShiftClock);
|
||||
SV(_state.InternalShiftClockSpeed2MHz);
|
||||
SV(_state.Active);
|
||||
SV(_state.TransferWord);
|
||||
SV(_state.IrqEnabled);
|
||||
SVArray(_state.Data, 4);
|
||||
|
||||
SV(_state.SendData);
|
||||
SV(_state.Mode);
|
||||
|
|
@ -196,5 +186,17 @@ public:
|
|||
SV(_state.JoyReceive);
|
||||
SV(_state.JoySend);
|
||||
SV(_state.JoyStatus);
|
||||
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SV(_state.StartMasterClock);
|
||||
SV(_state.EndMasterClock);
|
||||
SV(_state.IrqMasterClock);
|
||||
|
||||
SV(_state.InternalShiftClock);
|
||||
SV(_state.InternalShiftClockSpeed2MHz);
|
||||
SV(_state.Active);
|
||||
SV(_state.TransferWord);
|
||||
SV(_state.IrqEnabled);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -140,16 +140,22 @@ void GbaTimer::Serialize(Serializer& s)
|
|||
{
|
||||
for(int i = 0; i < 4; i++) {
|
||||
SVI(_state.Timer[i].ReloadValue);
|
||||
SVI(_state.Timer[i].NewReloadValue);
|
||||
SVI(_state.Timer[i].Control);
|
||||
SVI(_state.Timer[i].PrescaleMask);
|
||||
SVI(_state.Timer[i].Timer);
|
||||
SVI(_state.Timer[i].EnableDelay);
|
||||
SVI(_state.Timer[i].WritePending);
|
||||
SVI(_state.Timer[i].Mode);
|
||||
SVI(_state.Timer[i].IrqEnabled);
|
||||
SVI(_state.Timer[i].Enabled);
|
||||
SVI(_state.Timer[i].ProcessTimer);
|
||||
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SVI(_state.Timer[i].PrescaleMask);
|
||||
SVI(_state.Timer[i].Mode);
|
||||
SVI(_state.Timer[i].IrqEnabled);
|
||||
SVI(_state.Timer[i].Enabled);
|
||||
SVI(_state.Timer[i].ProcessTimer);
|
||||
SVI(_state.Timer[i].NewReloadValue);
|
||||
SVI(_state.Timer[i].WritePending);
|
||||
SVI(_state.Timer[i].EnableDelay);
|
||||
}
|
||||
}
|
||||
|
||||
if(s.GetFormat() != SerializeFormat::Map) {
|
||||
SV(_hasPendingTimers);
|
||||
}
|
||||
SV(_hasPendingTimers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ private:
|
|||
_mapValues.try_emplace(key, SerializeMapValueFormat::Double, (double)value);
|
||||
} else if constexpr(std::is_same<T, string>::value) {
|
||||
_mapValues.try_emplace(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -206,7 +206,7 @@ private:
|
|||
|
||||
__forceinline void CheckDuplicateKey(string& key)
|
||||
{
|
||||
#ifndef MESENRELEASE
|
||||
#ifdef DEBUG
|
||||
if(!_usedKeys.emplace(key).second) {
|
||||
throw std::runtime_error("Duplicate key");
|
||||
}
|
||||
|
|
@ -345,14 +345,25 @@ public:
|
|||
|
||||
template<typename T> void StreamArray(T* arrayValues, uint32_t elementCount, const char* name)
|
||||
{
|
||||
if(_format == SerializeFormat::Map) {
|
||||
return;
|
||||
}
|
||||
|
||||
string key = GetKey(name, -1);
|
||||
|
||||
CheckDuplicateKey(key);
|
||||
|
||||
if(_format == SerializeFormat::Map) {
|
||||
if(elementCount <= 64) {
|
||||
//Only save/load small arrays (otherwise this would end up serializing work/save ram, etc.)
|
||||
for(uint32_t i = 0; i < elementCount; i++) {
|
||||
string elemKey = key + std::to_string(i);
|
||||
if(_saving) {
|
||||
WriteMapFormat(elemKey, arrayValues[i]);
|
||||
} else {
|
||||
ReadMapFormat(elemKey, arrayValues[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO detect big vs little endian
|
||||
constexpr bool isBigEndian = false;
|
||||
if(_saving) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue