Experimental save state support
This commit is contained in:
@@ -12,6 +12,8 @@ struct BaseCPU {
|
||||
}
|
||||
virtual bool ShouldServiceInterrupt() = 0;
|
||||
virtual void CheckCompareInterrupt() = 0;
|
||||
virtual std::vector<u8> Serialize() = 0;
|
||||
virtual void Deserialize(const std::vector<u8>&) = 0;
|
||||
Registers regs;
|
||||
Mem mem;
|
||||
};
|
||||
|
||||
@@ -55,4 +55,18 @@ int Interpreter::Step() {
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<u8> Interpreter::Serialize() {
|
||||
std::vector<u8> res{};
|
||||
|
||||
res.resize(sizeof(Registers));
|
||||
|
||||
memcpy(res.data(), ®s, sizeof(Registers));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Interpreter::Deserialize(const std::vector<u8> &data) {
|
||||
memcpy(®s, data.data(), sizeof(Registers));
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ private:
|
||||
#define check_address_error(mask, vaddr) (((!regs.cop0.is_64bit_addressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
||||
bool ShouldServiceInterrupt() override;
|
||||
void CheckCompareInterrupt() override;
|
||||
std::vector<u8> Serialize() override;
|
||||
void Deserialize(const std::vector<u8>&) override;
|
||||
|
||||
void cop2Decode(u32);
|
||||
void special(u32);
|
||||
void regimm(u32);
|
||||
|
||||
@@ -101,6 +101,9 @@ private:
|
||||
return mem.Read8(regs, addr);
|
||||
}
|
||||
|
||||
std::vector<u8> Serialize() override { return {}; }
|
||||
void Deserialize(const std::vector<u8>&) override { }
|
||||
|
||||
void cop2Decode(u32);
|
||||
void special(u32);
|
||||
void regimm(u32);
|
||||
|
||||
@@ -44,4 +44,80 @@ void MMIO::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||
Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u8> MMIO::Serialize() {
|
||||
std::vector<u8> res{};
|
||||
|
||||
auto sPIF = si.pif.Serialize();
|
||||
constexpr u32 rdpSize = sizeof(DPC) +
|
||||
0xFFFFF +
|
||||
RDRAM_SIZE;
|
||||
res.resize(
|
||||
rdpSize +
|
||||
sizeof(RSP) +
|
||||
sizeof(MI) +
|
||||
sizeof(VI) +
|
||||
sizeof(SI) +
|
||||
sizeof(PI) +
|
||||
sizeof(RI) +
|
||||
sizeof(AI) +
|
||||
sizeof(u32)*2 +
|
||||
sizeof(SIStatus));
|
||||
|
||||
u32 index = 0;
|
||||
memcpy(res.data(), &rsp, sizeof(RSP));
|
||||
index += sizeof(RSP);
|
||||
memcpy(res.data() + index, &rdp.dpc, sizeof(DPC));
|
||||
index += sizeof(DPC);
|
||||
memcpy(res.data() + index, rdp.cmd_buf, 0xFFFFF);
|
||||
index += 0xFFFFF;
|
||||
memcpy(res.data() + index, rdp.rdram, RDRAM_SIZE);
|
||||
index += RDRAM_SIZE;
|
||||
memcpy(res.data() + index, &mi, sizeof(MI));
|
||||
index += sizeof(MI);
|
||||
memcpy(res.data() + index, &vi, sizeof(VI));
|
||||
index += sizeof(VI);
|
||||
memcpy(res.data() + index, &ai, sizeof(AI));
|
||||
index += sizeof(AI);
|
||||
memcpy(res.data() + index, &pi, sizeof(PI));
|
||||
index += sizeof(PI);
|
||||
memcpy(res.data() + index, &ri, sizeof(RI));
|
||||
index += sizeof(RI);
|
||||
memcpy(res.data() + index, &si.dramAddr, sizeof(u32));
|
||||
index += sizeof(u32);
|
||||
memcpy(res.data() + index, &si.pifAddr, sizeof(u32));
|
||||
index += sizeof(u32);
|
||||
memcpy(res.data() + index, &si.status, sizeof(SIStatus));
|
||||
|
||||
res.insert(res.end(), sPIF.begin(), sPIF.end());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void MMIO::Deserialize(const std::vector<u8> &data) {
|
||||
u32 index = 0;
|
||||
memcpy(&rsp, data.data(), sizeof(RSP));
|
||||
index += sizeof(RSP);
|
||||
memcpy(&rdp.dpc, data.data() + index, sizeof(DPC));
|
||||
index += sizeof(DPC);
|
||||
memcpy(rdp.cmd_buf, data.data() + index, 0xFFFFF);
|
||||
index += 0xFFFFF;
|
||||
memcpy(rdp.rdram, data.data() + index, RDRAM_SIZE);
|
||||
index += RDRAM_SIZE;
|
||||
memcpy(&mi, data.data() + index, sizeof(MI));
|
||||
index += sizeof(MI);
|
||||
memcpy(&vi, data.data() + index, sizeof(VI));
|
||||
index += sizeof(VI);
|
||||
memcpy(&ai, data.data() + index, sizeof(AI));
|
||||
index += sizeof(AI);
|
||||
memcpy(&pi, data.data() + index, sizeof(PI));
|
||||
index += sizeof(PI);
|
||||
memcpy(&ri, data.data() + index, sizeof(RI));
|
||||
index += sizeof(RI);
|
||||
memcpy(&si.dramAddr, data.data() + index, sizeof(u32));
|
||||
index += sizeof(u32);
|
||||
memcpy(&si.pifAddr, data.data() + index, sizeof(u32));
|
||||
index += sizeof(u32);
|
||||
memcpy(&si.status, data.data() + index, sizeof(SIStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,5 +27,7 @@ struct MMIO {
|
||||
|
||||
u32 Read(u32);
|
||||
void Write(Mem&, Registers&, u32, u32);
|
||||
std::vector<u8> Serialize();
|
||||
void Deserialize(const std::vector<u8>&);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -601,4 +601,25 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u8> Mem::Serialize() {
|
||||
std::vector<u8> res{};
|
||||
|
||||
auto sMMIO = mmio.Serialize();
|
||||
auto sFLASH = flash.Serialize();
|
||||
mmioSize = sMMIO.size();
|
||||
flashSize = sFLASH.size();
|
||||
|
||||
res.insert(res.begin(), sMMIO.begin(), sMMIO.end());
|
||||
res.insert(res.end(), sFLASH.begin(), sFLASH.end());
|
||||
res.insert(res.end(), sram.begin(), sram.end());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Mem::Deserialize(const std::vector<u8>& data) {
|
||||
mmio.Deserialize(std::vector<u8>(data.begin(), data.begin() + mmioSize));
|
||||
flash.Deserialize(std::vector<u8>(data.begin() + mmioSize, data.begin() + mmioSize + flashSize));
|
||||
memcpy(sram.data(), data.data() + mmioSize + flashSize, sram.size());
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,45 @@ struct Flash {
|
||||
void CommandWrite();
|
||||
void CommandRead();
|
||||
|
||||
FORCE_INLINE std::vector<u8> Serialize() {
|
||||
std::vector<u8> res{};
|
||||
|
||||
res.resize(
|
||||
sizeof(state) +
|
||||
sizeof(status) +
|
||||
sizeof(eraseOffs) +
|
||||
sizeof(writeOffs) +
|
||||
128);
|
||||
|
||||
u32 index = 0;
|
||||
memcpy(res.data() + index, &state, sizeof(state));
|
||||
index += sizeof(state);
|
||||
memcpy(res.data() + index, &status, sizeof(status));
|
||||
index += sizeof(status);
|
||||
memcpy(res.data() + index, &eraseOffs, sizeof(eraseOffs));
|
||||
index += sizeof(eraseOffs);
|
||||
memcpy(res.data() + index, &writeOffs, sizeof(writeOffs));
|
||||
index += sizeof(writeOffs);
|
||||
memcpy(res.data() + index, writeBuf, 128);
|
||||
|
||||
res.insert(res.begin(), flash.begin(), flash.end());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
FORCE_INLINE void Deserialize(const std::vector<u8>& data) {
|
||||
u32 index = 0;
|
||||
memcpy(&state, data.data() + index, sizeof(state));
|
||||
index += sizeof(state);
|
||||
memcpy(&status, data.data() + index, sizeof(status));
|
||||
index += sizeof(status);
|
||||
memcpy(&eraseOffs, data.data() + index, sizeof(eraseOffs));
|
||||
index += sizeof(eraseOffs);
|
||||
memcpy(&writeOffs, data.data() + index, sizeof(writeOffs));
|
||||
index += sizeof(writeOffs);
|
||||
memcpy(writeBuf, data.data() + index, 128);
|
||||
}
|
||||
|
||||
FORCE_INLINE void Write32(u32 index, u32 val) {
|
||||
if(index > 0) {
|
||||
u8 cmd = val >> 24;
|
||||
@@ -141,6 +180,9 @@ struct Mem {
|
||||
return mmio.rdp.rdram;
|
||||
}
|
||||
|
||||
std::vector<u8> Serialize();
|
||||
void Deserialize(const std::vector<u8>&);
|
||||
|
||||
u8 Read8(Registers&, u32);
|
||||
u16 Read16(Registers&, u32);
|
||||
u32 Read32(Registers&, u32);
|
||||
@@ -194,6 +236,7 @@ private:
|
||||
mio::mmap_sink sram;
|
||||
u8 isviewer[ISVIEWER_SIZE]{};
|
||||
std::string sramPath{};
|
||||
int mmioSize, flashSize;
|
||||
|
||||
FORCE_INLINE bool IsROMPAL() {
|
||||
static const char pal_codes[] = {'D', 'F', 'I', 'P', 'S', 'U', 'X', 'Y'};
|
||||
|
||||
@@ -988,5 +988,4 @@ void Interpreter::ctc2(u32) {
|
||||
void Interpreter::cfc2(u32) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -627,4 +627,30 @@ void PIF::ExecutePIF(Mem& mem, Registers& regs) {
|
||||
|
||||
DoPIFHLE(mem, regs, pal, cicType);
|
||||
}
|
||||
|
||||
std::vector<u8> PIF::Serialize() {
|
||||
std::vector<u8> res{};
|
||||
res.resize(
|
||||
6*sizeof(JoybusDevice) +
|
||||
PIF_BOOTROM_SIZE +
|
||||
PIF_RAM_SIZE +
|
||||
mempak.size() +
|
||||
eeprom.size() +
|
||||
sizeof(int));
|
||||
|
||||
u32 index = 0;
|
||||
memcpy(res.data() + index, joybusDevices, 6*sizeof(JoybusDevice));
|
||||
index += 6*sizeof(JoybusDevice);
|
||||
memcpy(res.data() + index, bootrom, PIF_BOOTROM_SIZE);
|
||||
index += PIF_BOOTROM_SIZE;
|
||||
memcpy(res.data() + index, ram, PIF_RAM_SIZE);
|
||||
index += PIF_RAM_SIZE;
|
||||
memcpy(res.data() + index, mempak.data(), mempak.size());
|
||||
index += mempak.size();
|
||||
memcpy(res.data() + index, eeprom.data(), eeprom.size());
|
||||
index += eeprom.size();
|
||||
memcpy(res.data() + index, &channel, sizeof(int));
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -122,6 +122,7 @@ struct PIF {
|
||||
void MempakWrite(u8*, u8*);
|
||||
void EepromRead(const u8*, u8*, const Mem&) const;
|
||||
void EepromWrite(const u8*, u8*, const Mem&);
|
||||
std::vector<u8> Serialize();
|
||||
|
||||
bool gamepadConnected = false, mempakOpen = false;
|
||||
SDL_GameController* gamepad{};
|
||||
|
||||
Reference in New Issue
Block a user