Sio: Migrate to StateWrapper

Also fixes the crash due to serializing pointers.

[SAVEVERSION+] and actually bump the save version.
This commit is contained in:
Stenzek 2023-07-26 02:12:04 +10:00 committed by refractionpcsx2
parent ab5c03b1d9
commit 1edca6235c
7 changed files with 114 additions and 109 deletions

View File

@ -15,17 +15,16 @@
#include "PrecompiledHeader.h"
#include "SIO/Sio0.h"
#include "SIO/Sio.h"
#include "Common.h"
#include "IopDma.h"
#include "IopHw.h"
#include "R3000A.h"
#include "SIO/Memcard/MemoryCardProtocol.h"
#include "SIO/Pad/Pad.h"
#include "SIO/Pad/PadBase.h"
#include "SIO/Memcard/MemoryCardProtocol.h"
#include "Common.h"
#include "IopHw.h"
#include "IopDma.h"
#include "R3000A.h"
#include "SIO/Sio.h"
#include "SIO/Sio0.h"
#include "StateWrapper.h"
#define SIO0LOG_ENABLE 0
#define Sio0Log if (SIO0LOG_ENABLE) DevCon
@ -316,9 +315,25 @@ u8 Sio0::Memcard(u8 value)
return 0xff;
}
bool SaveStateBase::Sio0Freeze()
bool Sio0::DoState(StateWrapper& sw)
{
FreezeTag("sio0");
Freeze(g_Sio0);
return true;
if (!sw.DoMarker("Sio0"))
return false;
sw.Do(&txData);
sw.Do(&rxData);
sw.Do(&stat);
sw.Do(&mode);
sw.Do(&ctrl);
sw.Do(&baud);
sw.Do(&flag);
sw.Do(&sioStage);
sw.Do(&sioMode);
sw.Do(&sioCommand);
sw.Do(&padStarted);
sw.Do(&rxDataSet);
sw.Do(&port);
sw.Do(&slot);
return sw.IsGood();
}

View File

@ -17,6 +17,8 @@
#include "SIO/SioTypes.h"
class StateWrapper;
class Sio0
{
private:
@ -48,6 +50,7 @@ public:
bool Shutdown();
void SoftReset();
bool DoState(StateWrapper& sw);
void SetAcknowledge(bool ack);
void Interrupt(Sio0Interrupt sio0Interrupt);

View File

@ -15,19 +15,18 @@
#include "PrecompiledHeader.h"
#include "SIO/Sio2.h"
#include "SIO/Sio.h"
#include "SIO/SioTypes.h"
#include "SIO/Pad/Pad.h"
#include "SIO/Pad/PadBase.h"
#include "SIO/Memcard/MemoryCardProtocol.h"
#include "SIO/Multitap/MultitapProtocol.h"
#include "Common.h"
#include "Host.h"
#include "IopDma.h"
#include "Recording/InputRecording.h"
#include "Host.h"
#include "SIO/Memcard/MemoryCardProtocol.h"
#include "SIO/Multitap/MultitapProtocol.h"
#include "SIO/Pad/Pad.h"
#include "SIO/Pad/PadBase.h"
#include "SIO/Sio.h"
#include "SIO/Sio2.h"
#include "SIO/SioTypes.h"
#include "StateWrapper.h"
#define SIO2LOG_ENABLE 0
#define Sio2Log if (SIO2LOG_ENABLE) DevCon
@ -451,62 +450,39 @@ u8 Sio2::Read()
return ret;
}
bool SaveStateBase::Sio2Freeze()
bool Sio2::DoState(StateWrapper& sw)
{
FreezeTag("sio2");
if (!sw.DoMarker("Sio2"))
return false;
if (IsSaving())
{
std::deque<u8>::iterator iter;
size_t backupSize;
sw.Do(&send3);
sw.Do(&send1);
sw.Do(&send2);
sw.Do(&dataIn);
sw.Do(&dataOut);
sw.Do(&ctrl);
sw.Do(&recv1);
sw.Do(&recv2);
sw.Do(&recv3);
sw.Do(&unknown1);
sw.Do(&unknown2);
sw.Do(&iStat);
sw.Do(&port);
sw.Do(&slot);
sw.Do(&send3Read);
sw.Do(&send3Position);
sw.Do(&commandLength);
sw.Do(&processedLength);
sw.Do(&dmaBlockSize);
sw.Do(&send3Complete);
// Copy g_Sio2FifoIn
if (g_Sio2FifoIn.size())
{
g_Sio2.fifoInBackup = std::make_unique<u8[]>(g_Sio2FifoIn.size());
iter = g_Sio2FifoIn.begin();
backupSize = 0;
while (iter != g_Sio2FifoIn.end())
{
const u8 val = *iter++;
g_Sio2.fifoInBackup.get()[backupSize++] = val;
}
g_Sio2.fifoInBackupSize = backupSize;
}
else
{
g_Sio2.fifoInBackupSize = 0;
}
// Copy g_Sio2FifoOut
if (g_Sio2FifoOut.size())
{
g_Sio2.fifoOutBackup = std::make_unique<u8[]>(g_Sio2FifoOut.size());
iter = g_Sio2FifoOut.begin();
backupSize = 0;
while (iter != g_Sio2FifoOut.end())
{
const u8 val = *iter++;
g_Sio2.fifoOutBackup.get()[backupSize++] = val;
}
g_Sio2.fifoOutBackupSize = backupSize;
}
else
{
g_Sio2.fifoOutBackupSize = 0;
}
}
Freeze(g_Sio2);
sw.Do(&g_Sio2FifoIn);
sw.Do(&g_Sio2FifoOut);
// CRCs for memory cards.
// If the memory card hasn't changed when loading state, we can safely skip ejecting it.
u64 mcdCrcs[SIO::PORTS][SIO::SLOTS];
if (IsSaving())
if (sw.IsWriting())
{
for (u32 port = 0; port < SIO::PORTS; port++)
{
@ -514,9 +490,9 @@ bool SaveStateBase::Sio2Freeze()
mcdCrcs[port][slot] = mcds[port][slot].GetChecksum();
}
}
Freeze(mcdCrcs);
sw.DoBytes(mcdCrcs, sizeof(mcdCrcs));
if (IsLoading())
if (sw.IsReading())
{
bool ejected = false;
for (u32 port = 0; port < SIO::PORTS && !ejected; port++)
@ -531,29 +507,7 @@ bool SaveStateBase::Sio2Freeze()
}
}
}
// Restore g_Sio2FifoIn
g_Sio2FifoIn.clear();
if (g_Sio2.fifoInBackupSize)
{
for (size_t i = 0; i < g_Sio2.fifoInBackupSize; i++)
{
g_Sio2FifoIn.push_back(g_Sio2.fifoInBackup.get()[i]);
}
}
// Restore g_Sio2FifoOut
g_Sio2FifoOut.clear();
if (g_Sio2.fifoOutBackupSize)
{
for (size_t j = 0; j < g_Sio2.fifoOutBackupSize; j++)
{
g_Sio2FifoOut.push_back(g_Sio2.fifoOutBackup.get()[j]);
}
}
}
return true;
return sw.IsGood();
}

View File

@ -17,6 +17,8 @@
#include <array>
class StateWrapper;
class Sio2
{
public:
@ -53,11 +55,6 @@ public:
size_t dmaBlockSize = 0;
bool send3Complete = false;
std::unique_ptr<u8[]> fifoInBackup;
size_t fifoInBackupSize;
std::unique_ptr<u8[]> fifoOutBackup;
size_t fifoOutBackupSize;
Sio2();
~Sio2();
@ -65,6 +62,7 @@ public:
bool Shutdown();
void SoftReset();
bool DoState(StateWrapper& sw);
void Interrupt();

View File

@ -31,6 +31,8 @@
#include "SIO/Pad/Pad.h"
#include "Patch.h"
#include "R3000A.h"
#include "SIO/Sio0.h"
#include "SIO/Sio2.h"
#include "SPU2/spu2.h"
#include "SaveState.h"
#include "StateWrapper.h"
@ -237,8 +239,42 @@ bool SaveStateBase::FreezeInternals()
FreezeMem(iopMem->Sif, sizeof(iopMem->Sif)); // iop's sif memory (not really needed, but oh well)
okay = okay && psxRcntFreeze();
okay = okay && Sio0Freeze();
okay = okay && Sio2Freeze();
// TODO: move all the others over to StateWrapper too...
if (!okay)
return false;
{
// This is horrible. We need to move the rest over...
std::optional<StateWrapper::VectorMemoryStream> save_stream;
std::optional<StateWrapper::ReadOnlyMemoryStream> load_stream;
if (IsSaving())
save_stream.emplace();
else
load_stream.emplace(&m_memory[m_idx], static_cast<int>(m_memory.size()) - m_idx);
StateWrapper sw(IsSaving() ? static_cast<StateWrapper::IStream*>(&save_stream.value()) :
static_cast<StateWrapper::IStream*>(&load_stream.value()),
IsSaving() ? StateWrapper::Mode::Write : StateWrapper::Mode::Read, g_SaveVersion);
okay = okay && g_Sio0.DoState(sw);
okay = okay && g_Sio2.DoState(sw);
if (!okay || !sw.IsGood())
return false;
if (IsSaving())
{
FreezeMem(const_cast<u8*>(save_stream->GetBuffer().data()), save_stream->GetPosition());
}
else
{
const int new_idx = m_idx + static_cast<int>(load_stream->GetPosition());
if (static_cast<size_t>(new_idx) >= m_memory.size())
return false;
m_idx = new_idx;
}
}
okay = okay && cdrFreeze();
okay = okay && cdvdFreeze();

View File

@ -37,7 +37,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.
static const u32 g_SaveVersion = (0x9A3A << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A3B << 16) | 0x0000;
// the freezing data between submodules and core
@ -222,8 +222,6 @@ protected:
bool cdvdFreeze();
bool psxRcntFreeze();
bool deci2Freeze();
bool Sio0Freeze();
bool Sio2Freeze();
// Save or load PCSX2's global frame counter (g_FrameCount) along with each savestate
//

View File

@ -107,6 +107,7 @@ public:
IStream* GetStream() const { return m_stream; }
bool HasError() const { return m_error; }
bool IsGood() const { return !m_error; }
bool IsReading() const { return (m_mode == Mode::Read); }
bool IsWriting() const { return (m_mode == Mode::Write); }
Mode GetMode() const { return m_mode; }
@ -226,8 +227,8 @@ public:
}
else
{
for (u32 i = 0; i < length; i++)
Do(&data[i]);
for (T& ch : *data)
Do(&ch);
}
}