SaveState: Partial migration to StateWrapper for USB

This commit is contained in:
Stenzek 2022-12-26 13:56:28 +10:00 committed by refractionpcsx2
parent 8abe5b42e5
commit a8faf2eb6e
4 changed files with 69 additions and 47 deletions

View File

@ -40,6 +40,7 @@
#include "GS.h"
#include "GS/GS.h"
#include "SPU2/spu2.h"
#include "StateWrapper.h"
#include "PAD/Gamepad.h"
#include "USB/USB.h"
#include "VMManager.h"
@ -355,7 +356,6 @@ static int SysState_MTGSFreeze(FreezeAction mode, freezeData* fP)
static constexpr SysState_Component SPU2{ "SPU2", SPU2freeze };
static constexpr SysState_Component PAD_{ "PAD", PADfreeze };
static constexpr SysState_Component USB_{ "USB", USBfreeze };
static constexpr SysState_Component GS{ "GS", SysState_MTGSFreeze };
@ -404,6 +404,43 @@ static void SysState_ComponentFreezeOut(SaveStateBase& writer, SysState_Componen
return;
}
static void SysState_ComponentFreezeInNew(zip_file_t* zf, const char* name, bool(*do_state_func)(StateWrapper&))
{
// TODO: We could decompress on the fly here for a little bit more speed.
std::vector<u8> data;
if (zf)
{
std::optional<std::vector<u8>> optdata(ReadBinaryFileInZip(zf));
if (optdata.has_value())
data = std::move(optdata.value());
}
StateWrapper::ReadOnlyMemoryStream stream(data.empty() ? nullptr : data.data(), data.size());
StateWrapper sw(&stream, StateWrapper::Mode::Read, g_SaveVersion);
// TODO: Get rid of the bloody exceptions.
if (!do_state_func(sw))
throw std::runtime_error(fmt::format(" * {}: Error loading state!", name));
}
static void SysState_ComponentFreezeOutNew(SaveStateBase& writer, const char* name, u32 reserve, bool (*do_state_func)(StateWrapper&))
{
StateWrapper::VectorMemoryStream stream(reserve);
StateWrapper sw(&stream, StateWrapper::Mode::Write, g_SaveVersion);
// TODO: Get rid of the bloody exceptions.
if (!do_state_func(sw))
throw std::runtime_error(fmt::format(" * {}: Error saving state!", name));
const int size = static_cast<int>(stream.GetBuffer().size());
if (size > 0)
{
writer.PrepBlock(size);
std::memcpy(writer.GetBlockPtr(), stream.GetBuffer().data(), size);
writer.CommitBlock(size);
}
}
// --------------------------------------------------------------------------------------
// BaseSavestateEntry
// --------------------------------------------------------------------------------------
@ -575,8 +612,8 @@ public:
virtual ~SavestateEntry_USB() = default;
const char* GetFilename() const { return "USB.bin"; }
void FreezeIn(zip_file_t* zf) const { return SysState_ComponentFreezeIn(zf, USB_); }
void FreezeOut(SaveStateBase& writer) const { return SysState_ComponentFreezeOut(writer, USB_); }
void FreezeIn(zip_file_t* zf) const { return SysState_ComponentFreezeInNew(zf, "USB", &USB::DoState); }
void FreezeOut(SaveStateBase& writer) const { return SysState_ComponentFreezeOutNew(writer, "USB", 16 * 1024, &USB::DoState); }
bool IsRequired() const { return false; }
};

View File

@ -85,6 +85,8 @@ public:
VectorMemoryStream();
VectorMemoryStream(u32 reserve);
const std::vector<u8>& GetBuffer() const { return m_buf; }
u32 Read(void* buf, u32 count) override;
u32 Write(const void* buf, u32 count) override;
u32 GetPosition() override;

View File

@ -41,7 +41,7 @@ namespace USB
static void DestroyDevice(u32 port);
static void UpdateDevice(u32 port);
static void DoOHCIState(StateWrapper& sw);
static bool DoOHCIState(StateWrapper& sw);
static void DoEndpointState(USBEndpoint* ep, StateWrapper& sw);
static void DoDeviceState(USBDevice* dev, StateWrapper& sw);
static void DoPacketState(USBPacket* p, StateWrapper& sw, const std::array<bool, 2>& valid_devices);
@ -199,10 +199,10 @@ void USBwrite32(u32 addr, u32 value)
ohci_mem_write(s_qemu_ohci, addr, value);
}
void USB::DoOHCIState(StateWrapper& sw)
bool USB::DoOHCIState(StateWrapper& sw)
{
if (!sw.DoMarker("USBOHCI"))
return;
return false;
sw.Do(&g_usb_last_cycle);
sw.Do(&s_usb_clocks);
@ -243,6 +243,7 @@ void USB::DoOHCIState(StateWrapper& sw)
sw.DoArray(s_qemu_ohci->usb_buf, sizeof(s_qemu_ohci->usb_buf));
sw.Do(&s_qemu_ohci->async_td);
sw.Do(&s_qemu_ohci->async_complete);
return true;
}
void USB::DoDeviceState(USBDevice* dev, StateWrapper& sw)
@ -378,24 +379,19 @@ void USB::DoPacketState(USBPacket* p, StateWrapper& sw, const std::array<bool, 2
}
}
s32 USBfreeze(FreezeAction mode, freezeData* data)
bool USB::DoState(StateWrapper& sw)
{
std::array<bool, 2> valid_devices = {};
if (mode == FreezeAction::Load)
if (!sw.DoMarker("USB") || !USB::DoOHCIState(sw))
{
StateWrapper::ReadOnlyMemoryStream swstream(data->data, data->size);
StateWrapper sw(&swstream, StateWrapper::Mode::Read, g_SaveVersion);
if (!sw.DoMarker("USB"))
{
Console.Error("USB state is invalid, resetting.");
USBreset();
return 0;
}
USB::DoOHCIState(sw);
Console.Error("USB state is invalid, resetting.");
USBreset();
return false;
}
if (sw.IsReading())
{
for (u32 port = 0; port < USB::NUM_PORTS; port++)
{
s32 state_devtype;
@ -443,21 +439,11 @@ s32 USBfreeze(FreezeAction mode, freezeData* data)
{
Console.WriteLn("Failed to read USB packet, resetting all devices.");
USBreset();
return 0;
return true;
}
}
else if (mode == FreezeAction::Save)
else
{
std::memset(data->data, 0, data->size);
StateWrapper::MemoryStream swstream(data->data, data->size);
StateWrapper sw(&swstream, StateWrapper::Mode::Write, g_SaveVersion);
if (!sw.DoMarker("USB"))
return -1;
USB::DoOHCIState(sw);
for (u32 port = 0; port < USB::NUM_PORTS; port++)
{
s32 state_devtype = EmuConfig.USB.Ports[port].DeviceType;
@ -465,12 +451,12 @@ s32 USBfreeze(FreezeAction mode, freezeData* data)
sw.Do(&state_devtype);
sw.Do(&state_devsubtype);
const u32 size_pos = swstream.GetPosition();
const u32 size_pos = sw.GetStream()->GetPosition();
u32 state_size = 0;
sw.Do(&state_size);
if (sw.HasError())
return -1;
return false;
if (!s_usb_device[port])
{
@ -478,33 +464,28 @@ s32 USBfreeze(FreezeAction mode, freezeData* data)
continue;
}
const u32 start_pos = swstream.GetPosition();
const u32 start_pos = sw.GetStream()->GetPosition();
USB::DoDeviceState(s_usb_device[port], sw);
if (!s_usb_device_proxy[port]->Freeze(s_usb_device[port], sw) || sw.HasError())
{
Console.Error("Failed to serialize USB port %u.", port);
return -1;
return false;
}
const u32 end_pos = swstream.GetPosition();
const u32 end_pos = sw.GetStream()->GetPosition();
state_size = end_pos - start_pos;
if (!swstream.SeekAbsolute(size_pos) || (sw.Do(&state_size), sw.HasError()) || !swstream.SeekAbsolute(end_pos))
return -1;
if (!sw.GetStream()->SeekAbsolute(size_pos) || (sw.Do(&state_size), sw.HasError()) || !sw.GetStream()->SeekAbsolute(end_pos))
return false;
valid_devices[port] = true;
}
USB::DoPacketState(&s_qemu_ohci->usb_packet, sw, valid_devices);
if (sw.HasError())
return -1;
}
else if (mode == FreezeAction::Size)
{
// I don't like this, but until we move everything over to state wrapper, it'll have to do.
data->size = 0x10000;
return false;
}
return 0;
return true;
}
void USBasync(u32 cycles)

View File

@ -24,9 +24,9 @@
#include "gsl/span"
#include "Config.h"
#include "SaveState.h"
class SettingsInterface;
class StateWrapper;
namespace USB
{
@ -84,6 +84,9 @@ namespace USB
/// Reads a device-specific configuration string.
std::string GetConfigString(SettingsInterface& si, u32 port, const char* devname, const char* key, const char* default_value = "");
/// Handles loading/saving save state.
bool DoState(StateWrapper& sw);
} // namespace USB
struct WindowInfo;
@ -96,7 +99,6 @@ void USBshutdown();
void USBclose();
bool USBopen();
void USBreset();
s32 USBfreeze(FreezeAction mode, freezeData* data);
u8 USBread8(u32 addr);
u16 USBread16(u32 addr);