Differential compression requires passing relative positions for differential and reference data

This commit is contained in:
Sergio Martin 2024-02-08 07:44:08 +01:00
parent 770e8659bd
commit 633173ba4d
6 changed files with 136 additions and 95 deletions

View File

@ -98,8 +98,8 @@ class NESInstanceBase
virtual void deserializeState(const uint8_t *state) = 0; virtual void deserializeState(const uint8_t *state) = 0;
virtual size_t getStateSize() const = 0; virtual size_t getStateSize() const = 0;
virtual size_t serializeDifferentialState(uint8_t *differentialData, const uint8_t* referenceData, const size_t maxSize, const bool useZlib) const = 0; virtual void serializeDifferentialState(uint8_t *differentialData, size_t* differentialDataPos, const uint8_t* referenceData, size_t* referenceDataPos, const size_t maxSize, const bool useZlib) const = 0;
virtual void deserializeDifferentialState(const uint8_t *differentialData, const uint8_t* referenceData, const bool useZlib) = 0; virtual void deserializeDifferentialState(const uint8_t *differentialData, size_t* differentialDataPos, const uint8_t* referenceData, size_t* referenceDataPos, const bool useZlib) = 0;
virtual size_t getDifferentialStateSize() const = 0; virtual size_t getDifferentialStateSize() const = 0;
virtual void doSoftReset() = 0; virtual void doSoftReset() = 0;

View File

@ -50,10 +50,10 @@ class NESInstance final : public NESInstanceBase
return w.size(); return w.size();
} }
size_t serializeDifferentialState(uint8_t *differentialData, const uint8_t* referenceData, const size_t maxSize, const bool useZlib) const override void serializeDifferentialState(uint8_t *differentialData, size_t* differentialDataPos, const uint8_t* referenceData, size_t* referenceDataPos, const size_t maxSize, const bool useZlib) const override
{ serializeState(differentialData); return 0; } { serializeState(differentialData); }
void deserializeDifferentialState(const uint8_t *differentialData, const uint8_t* referenceData, const bool useZlib) override void deserializeDifferentialState(const uint8_t *differentialData, size_t* differentialDataPos, const uint8_t* referenceData, size_t* referenceDataPos, const bool useZlib) override
{ deserializeState(differentialData); } { deserializeState(differentialData); }
size_t getDifferentialStateSize() const override size_t getDifferentialStateSize() const override

View File

@ -160,7 +160,7 @@ class Core : private Cpu
// Moving pointer positions // Moving pointer positions
*outputDataPos += inputDataSize; *outputDataPos += inputDataSize;
*referenceDataPos += inputDataSize; if (referenceDataPos != nullptr) *referenceDataPos += inputDataSize;
} }
static inline void deserializeContiguousData(uint8_t* __restrict__ outputData, const size_t outputDataSize, const uint8_t* __restrict__ inputData, size_t* inputDataPos, size_t* referenceDataPos) static inline void deserializeContiguousData(uint8_t* __restrict__ outputData, const size_t outputDataSize, const uint8_t* __restrict__ inputData, size_t* inputDataPos, size_t* referenceDataPos)
@ -170,22 +170,31 @@ class Core : private Cpu
// Moving pointer positions // Moving pointer positions
*inputDataPos += outputDataSize; *inputDataPos += outputDataSize;
*referenceDataPos += outputDataSize; if (referenceDataPos != nullptr) *referenceDataPos += outputDataSize;
} }
static inline void serializeBlockHead(uint8_t* __restrict__ outputData, size_t* outputDataPos, size_t* referenceDataPos, const char* blockTag, const uint32_t blockSize) static inline void serializeBlockHead(
uint8_t* __restrict__ outputData,
size_t* outputDataPos,
const char* blockTag,
const uint32_t blockSize,
size_t* referenceDataPos = nullptr)
{ {
if (outputData != nullptr) memcpy(&outputData[*outputDataPos], blockTag, 4); if (outputData != nullptr) memcpy(&outputData[*outputDataPos], blockTag, 4);
*outputDataPos += 4; *referenceDataPos += 4; *outputDataPos += 4;
if (referenceDataPos != nullptr) *referenceDataPos += 4;
if (outputData != nullptr) memcpy(&outputData[*outputDataPos], &blockSize, 4); if (outputData != nullptr) memcpy(&outputData[*outputDataPos], &blockSize, 4);
*outputDataPos += 4; *referenceDataPos += 4; *outputDataPos += 4;
if (referenceDataPos != nullptr) *referenceDataPos += 4;
} }
static inline void deserializeBlockHead(size_t* inputDataPos, size_t* referenceDataPos) static inline void deserializeBlockHead(
size_t* inputDataPos,
size_t* referenceDataPos = nullptr)
{ {
*inputDataPos += 8; *inputDataPos += 8;
*referenceDataPos += 8; if (referenceDataPos != nullptr) *referenceDataPos += 8;
} }
static inline void serializeDifferentialData( static inline void serializeDifferentialData(
@ -294,18 +303,19 @@ class Core : private Cpu
} }
size_t serializeState( inline void serializeState(
uint8_t* __restrict__ outputData, uint8_t* __restrict__ outputData,
const bool useDifferentialCompression = false, size_t* outputDataPos = nullptr,
const uint8_t* __restrict__ referenceData = nullptr, const uint8_t* __restrict__ referenceData = nullptr,
size_t* referenceDataPos = nullptr,
const size_t outputMaxSize = 0, const size_t outputMaxSize = 0,
const bool useZlib = false) const const bool useZlib = false) const
{ {
size_t outputDataPos = 0; size_t tmpIOutputDataPos = 0;
size_t referenceDataPos = 0; if (outputDataPos == nullptr) outputDataPos = &tmpIOutputDataPos;
// NESS Block // NESS Block
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "NESS", 0xFFFFFFFF); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "NESS", 0xFFFFFFFF, referenceDataPos);
// TIME Block // TIME Block
if (TIMEBlockEnabled == true) if (TIMEBlockEnabled == true)
@ -316,8 +326,8 @@ class Core : private Cpu
const auto inputDataSize = sizeof(nes_state_t); const auto inputDataSize = sizeof(nes_state_t);
const auto inputData = (uint8_t *)&state; const auto inputData = (uint8_t *)&state;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "TIME", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "TIME", inputDataSize, referenceDataPos);
serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
} }
// CPUR Block // CPUR Block
@ -335,8 +345,8 @@ class Core : private Cpu
const auto inputDataSize = sizeof(cpu_state_t); const auto inputDataSize = sizeof(cpu_state_t);
const auto inputData = (uint8_t *)&s; const auto inputData = (uint8_t *)&s;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "CPUR", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "CPUR", inputDataSize, referenceDataPos);
serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
} }
if (PPURBlockEnabled == true) if (PPURBlockEnabled == true)
@ -344,8 +354,8 @@ class Core : private Cpu
const auto inputDataSize = sizeof(ppu_state_t); const auto inputDataSize = sizeof(ppu_state_t);
const auto inputData = (const uint8_t *)&ppu; const auto inputData = (const uint8_t *)&ppu;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "PPUR", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "PPUR", inputDataSize, referenceDataPos);
serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
} }
// APUR Block // APUR Block
@ -357,8 +367,8 @@ class Core : private Cpu
const auto inputDataSize = sizeof(Apu::apu_state_t); const auto inputDataSize = sizeof(Apu::apu_state_t);
const auto inputData = (uint8_t *)&apuState; const auto inputData = (uint8_t *)&apuState;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "APUR", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "APUR", inputDataSize, referenceDataPos);
serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
} }
// CTRL Block // CTRL Block
@ -367,8 +377,8 @@ class Core : private Cpu
const auto inputDataSize = sizeof(joypad_state_t); const auto inputDataSize = sizeof(joypad_state_t);
const auto inputData = (uint8_t *)&joypad; const auto inputData = (uint8_t *)&joypad;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "CTRL", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "CTRL", inputDataSize, referenceDataPos);
serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
} }
// MAPR Block // MAPR Block
@ -377,8 +387,8 @@ class Core : private Cpu
const auto inputDataSize = mapper->state_size; const auto inputDataSize = mapper->state_size;
const auto inputData = (uint8_t *)mapper->state; const auto inputData = (uint8_t *)mapper->state;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "MAPR", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "MAPR", inputDataSize, referenceDataPos);
serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
} }
// LRAM Block // LRAM Block
@ -387,9 +397,9 @@ class Core : private Cpu
const auto inputDataSize = low_ram_size; const auto inputDataSize = low_ram_size;
const auto inputData = (uint8_t *)low_mem; const auto inputData = (uint8_t *)low_mem;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "LRAM", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "LRAM", inputDataSize, referenceDataPos);
if (useDifferentialCompression == false) serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
if (useDifferentialCompression == true) serializeDifferentialData(inputData, inputDataSize, outputData, &outputDataPos, referenceData, &referenceDataPos, outputMaxSize, useZlib); if (referenceDataPos != nullptr) serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, referenceData, referenceDataPos, outputMaxSize, useZlib);
} }
// SPRT Block // SPRT Block
@ -398,9 +408,9 @@ class Core : private Cpu
const auto inputDataSize = Ppu::spr_ram_size; const auto inputDataSize = Ppu::spr_ram_size;
const auto inputData = (uint8_t *)ppu.spr_ram; const auto inputData = (uint8_t *)ppu.spr_ram;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "SPRT", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "SPRT", inputDataSize, referenceDataPos);
if (useDifferentialCompression == false) serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
if (useDifferentialCompression == true) serializeDifferentialData(inputData, inputDataSize, outputData, &outputDataPos, referenceData, &referenceDataPos, outputMaxSize, useZlib); if (referenceDataPos != nullptr) serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, referenceData, referenceDataPos, outputMaxSize, useZlib);
} }
// NTAB Block // NTAB Block
@ -412,9 +422,9 @@ class Core : private Cpu
const auto inputDataSize = nametable_size; const auto inputDataSize = nametable_size;
const auto inputData = (uint8_t *)ppu.impl->nt_ram; const auto inputData = (uint8_t *)ppu.impl->nt_ram;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "NTAB", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "NTAB", inputDataSize, referenceDataPos);
if (useDifferentialCompression == false) serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
if (useDifferentialCompression == true) serializeDifferentialData(inputData, inputDataSize, outputData, &outputDataPos, referenceData, &referenceDataPos, outputMaxSize, useZlib); if (referenceDataPos != nullptr) serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, referenceData, referenceDataPos, outputMaxSize, useZlib);
} }
// CHRR Block // CHRR Block
@ -425,9 +435,9 @@ class Core : private Cpu
const auto inputDataSize = ppu.chr_size; const auto inputDataSize = ppu.chr_size;
const auto inputData = (uint8_t *)ppu.impl->chr_ram; const auto inputData = (uint8_t *)ppu.impl->chr_ram;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "CHRR", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "CHRR", inputDataSize, referenceDataPos);
if (useDifferentialCompression == false) serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
if (useDifferentialCompression == true) serializeDifferentialData(inputData, inputDataSize, outputData, &outputDataPos, referenceData, &referenceDataPos, outputMaxSize, useZlib); if (referenceDataPos != nullptr) serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, referenceData, referenceDataPos, outputMaxSize, useZlib);
} }
} }
@ -439,29 +449,32 @@ class Core : private Cpu
const auto inputDataSize = impl->sram_size; const auto inputDataSize = impl->sram_size;
const auto inputData = (uint8_t *)impl->sram; const auto inputData = (uint8_t *)impl->sram;
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "SRAM", inputDataSize); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "SRAM", inputDataSize, referenceDataPos);
if (useDifferentialCompression == false) serializeContiguousData(inputData, inputDataSize, outputData, &outputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, referenceDataPos);
if (useDifferentialCompression == true) serializeDifferentialData(inputData, inputDataSize, outputData, &outputDataPos, referenceData, &referenceDataPos, outputMaxSize, useZlib); if (referenceDataPos != nullptr) serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, referenceData, referenceDataPos, outputMaxSize, useZlib);
} }
} }
// gend Block // gend Block
if (HEADBlockEnabled == true) serializeBlockHead(outputData, &outputDataPos, &referenceDataPos, "gend", 0); if (HEADBlockEnabled == true) serializeBlockHead(outputData, outputDataPos, "gend", 0, referenceDataPos);
return outputDataPos; // Bytes written
} }
size_t deserializeState(const uint8_t* __restrict__ inputData, const bool useDifferentialCompression = false, const uint8_t* __restrict__ referenceData = nullptr, const bool useZlib = false) inline void deserializeState(
const uint8_t* __restrict__ inputData,
size_t* inputDataPos = nullptr,
const uint8_t* __restrict__ referenceData = nullptr,
size_t* referenceDataPos = nullptr,
const bool useZlib = false)
{ {
disable_rendering(); disable_rendering();
error_count = 0; error_count = 0;
ppu.burst_phase = 0; // avoids shimmer when seeking to same time over and over ppu.burst_phase = 0; // avoids shimmer when seeking to same time over and over
size_t inputDataPos = 0; size_t tmpInputDataPos = 0;
size_t referenceDataPos = 0; if (inputDataPos == nullptr) inputDataPos = &tmpInputDataPos;
// NESS Block // NESS Block
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
// TIME Block // TIME Block
if (TIMEBlockEnabled == true) if (TIMEBlockEnabled == true)
@ -471,8 +484,8 @@ class Core : private Cpu
const auto outputData = (uint8_t*) &nesState; const auto outputData = (uint8_t*) &nesState;
const auto inputDataSize = sizeof(nes_state_t); const auto inputDataSize = sizeof(nes_state_t);
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
nes = nesState; nes = nesState;
nes.timestamp /= 5; nes.timestamp /= 5;
@ -486,8 +499,8 @@ class Core : private Cpu
const auto outputData = (uint8_t*) &s; const auto outputData = (uint8_t*) &s;
const auto inputDataSize = sizeof(cpu_state_t); const auto inputDataSize = sizeof(cpu_state_t);
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
r.pc = s.pc; r.pc = s.pc;
r.sp = s.s; r.sp = s.s;
@ -503,8 +516,8 @@ class Core : private Cpu
const auto outputData = (uint8_t*) &ppu; const auto outputData = (uint8_t*) &ppu;
const auto inputDataSize = sizeof(ppu_state_t); const auto inputDataSize = sizeof(ppu_state_t);
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
} }
// APUR Block // APUR Block
@ -515,8 +528,8 @@ class Core : private Cpu
const auto outputData = (uint8_t*) &apuState; const auto outputData = (uint8_t*) &apuState;
const auto inputDataSize = sizeof(Apu::apu_state_t); const auto inputDataSize = sizeof(Apu::apu_state_t);
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
impl->apu.load_state(apuState); impl->apu.load_state(apuState);
impl->apu.end_frame(-(int)nes.timestamp / ppu_overclock); impl->apu.end_frame(-(int)nes.timestamp / ppu_overclock);
@ -528,8 +541,8 @@ class Core : private Cpu
const auto outputData = (uint8_t*) &joypad; const auto outputData = (uint8_t*) &joypad;
const auto inputDataSize = sizeof(joypad_state_t); const auto inputDataSize = sizeof(joypad_state_t);
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
} }
// MAPR Block // MAPR Block
@ -540,8 +553,8 @@ class Core : private Cpu
const auto outputData = (uint8_t*) mapper->state; const auto outputData = (uint8_t*) mapper->state;
const auto inputDataSize = mapper->state_size; const auto inputDataSize = mapper->state_size;
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
mapper->apply_mapping(); mapper->apply_mapping();
} }
@ -552,9 +565,9 @@ class Core : private Cpu
const auto outputData = (uint8_t*) low_mem; const auto outputData = (uint8_t*) low_mem;
const auto inputDataSize = low_ram_size; const auto inputDataSize = low_ram_size;
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
if (useDifferentialCompression == false) deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
if (useDifferentialCompression == true) deserializeDifferentialData(outputData, inputDataSize, inputData, &inputDataPos, referenceData, &referenceDataPos, useZlib); if (referenceDataPos != nullptr) deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, referenceData, referenceDataPos, useZlib);
} }
// SPRT Block // SPRT Block
@ -563,9 +576,9 @@ class Core : private Cpu
const auto outputData = (uint8_t*) ppu.spr_ram; const auto outputData = (uint8_t*) ppu.spr_ram;
const auto inputDataSize = Ppu::spr_ram_size; const auto inputDataSize = Ppu::spr_ram_size;
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
if (useDifferentialCompression == false) deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
if (useDifferentialCompression == true) deserializeDifferentialData(outputData, inputDataSize, inputData, &inputDataPos, referenceData, &referenceDataPos, useZlib); if (referenceDataPos != nullptr) deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, referenceData, referenceDataPos, useZlib);
} }
// NTAB Block // NTAB Block
@ -577,9 +590,9 @@ class Core : private Cpu
const auto outputData = (uint8_t*) ppu.impl->nt_ram; const auto outputData = (uint8_t*) ppu.impl->nt_ram;
const auto inputDataSize = nametable_size; const auto inputDataSize = nametable_size;
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
if (useDifferentialCompression == false) deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
if (useDifferentialCompression == true) deserializeDifferentialData(outputData, inputDataSize, inputData, &inputDataPos, referenceData, &referenceDataPos, useZlib); if (referenceDataPos != nullptr) deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, referenceData, referenceDataPos, useZlib);
} }
// CHRR Block // CHRR Block
@ -590,9 +603,9 @@ class Core : private Cpu
const auto outputData = (uint8_t*) ppu.impl->chr_ram; const auto outputData = (uint8_t*) ppu.impl->chr_ram;
const auto inputDataSize = ppu.chr_size; const auto inputDataSize = ppu.chr_size;
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
if (useDifferentialCompression == false) deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
if (useDifferentialCompression == true) deserializeDifferentialData(outputData, inputDataSize, inputData, &inputDataPos, referenceData, &referenceDataPos, useZlib); if (referenceDataPos != nullptr) deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, referenceData, referenceDataPos, useZlib);
ppu.all_tiles_modified(); ppu.all_tiles_modified();
} }
@ -606,18 +619,16 @@ class Core : private Cpu
const auto outputData = (uint8_t*) impl->sram; const auto outputData = (uint8_t*) impl->sram;
const auto inputDataSize = impl->sram_size; const auto inputDataSize = impl->sram_size;
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
if (useDifferentialCompression == false) deserializeContiguousData(outputData, inputDataSize, inputData, &inputDataPos, &referenceDataPos); if (referenceDataPos == nullptr) deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, referenceDataPos);
if (useDifferentialCompression == true) deserializeDifferentialData(outputData, inputDataSize, inputData, &inputDataPos, referenceData, &referenceDataPos, useZlib); if (referenceDataPos != nullptr) deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, referenceData, referenceDataPos, useZlib);
} }
} }
if (sram_present) enable_sram(true); if (sram_present) enable_sram(true);
// gend Block // gend Block
if (HEADBlockEnabled == true) deserializeBlockHead(&inputDataPos, &referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos);
return inputDataPos; // Bytes read
} }
void enableStateBlock(const std::string& block) void enableStateBlock(const std::string& block)

View File

@ -45,13 +45,27 @@ class Emu
const uint8_t *getHostPixels() const { return emu.ppu.host_pixels; } const uint8_t *getHostPixels() const { return emu.ppu.host_pixels; }
// Save emulator state variants // Save emulator state variants
size_t serializeState(uint8_t *buffer) const { return emu.serializeState(buffer, false); } void serializeState(uint8_t *buffer) const { emu.serializeState(buffer); }
size_t deserializeState(const uint8_t *buffer) { return emu.deserializeState(buffer, false); } void deserializeState(const uint8_t *buffer) { emu.deserializeState(buffer); }
size_t getStateSize() const { return emu.serializeState(nullptr, false); } size_t getStateSize() const { size_t outputDataPos = 0; emu.serializeState(nullptr, &outputDataPos); return outputDataPos; }
size_t serializeDifferentialState(uint8_t* __restrict__ outputData, const uint8_t* __restrict__ referenceData, const size_t outputMaxSize, const bool useZlib) const { return emu.serializeState(outputData, true, referenceData, outputMaxSize, useZlib); } void serializeDifferentialState(uint8_t* __restrict__ outputData, size_t* outputDataPos, const uint8_t* __restrict__ referenceData, size_t* referenceDataPos, const size_t outputMaxSize, const bool useZlib) const
size_t deserializeDifferentialState(const uint8_t* __restrict__ inputStateData, const uint8_t* __restrict__ referenceData, const bool useZlib) { return emu.deserializeState(inputStateData, true, referenceData, useZlib); } {
size_t getDifferentialStateSize() const { return emu.serializeState(nullptr, true, nullptr, 0, false); } emu.serializeState(outputData, outputDataPos, referenceData, referenceDataPos, outputMaxSize, useZlib);
}
void deserializeDifferentialState(const uint8_t* __restrict__ inputData, size_t* inputDataPos, const uint8_t* __restrict__ referenceData, size_t* referenceDataPos, const bool useZlib)
{
emu.deserializeState(inputData, inputDataPos, referenceData, referenceDataPos, useZlib);
}
size_t getDifferentialStateSize() const
{
size_t outputDataPos = 0;
size_t referenceDataPos = 0;
emu.serializeState(nullptr, &outputDataPos, nullptr, &referenceDataPos, 0, false);
return outputDataPos;
}
void enableStateBlock(const std::string& block) { emu.enableStateBlock(block); }; void enableStateBlock(const std::string& block) { emu.enableStateBlock(block); };
void disableStateBlock(const std::string& block) { emu.disableStateBlock(block); }; void disableStateBlock(const std::string& block) { emu.disableStateBlock(block); };

View File

@ -28,11 +28,11 @@ class NESInstance final : public NESInstanceBase
void deserializeState(const uint8_t *state) override { _nes.deserializeState(state); } void deserializeState(const uint8_t *state) override { _nes.deserializeState(state); }
size_t getStateSize() const override { return _nes.getStateSize(); } size_t getStateSize() const override { return _nes.getStateSize(); }
size_t serializeDifferentialState(uint8_t *differentialData, const uint8_t* referenceData, const size_t maxSize, const bool useZlib) const override void serializeDifferentialState(uint8_t *differentialData, size_t* differentialDataPos, const uint8_t* referenceData, size_t* referenceDataPos, const size_t maxSize, const bool useZlib) const override
{ return _nes.serializeDifferentialState(differentialData, referenceData, maxSize, useZlib); } { _nes.serializeDifferentialState(differentialData, differentialDataPos, referenceData, referenceDataPos, maxSize, useZlib); }
void deserializeDifferentialState(const uint8_t *differentialData, const uint8_t* referenceData, const bool useZlib) override void deserializeDifferentialState(const uint8_t *differentialData, size_t* differentialDataPos, const uint8_t* referenceData, size_t* referenceDataPos, const bool useZlib) override
{ _nes.deserializeDifferentialState(differentialData, referenceData, useZlib); } { _nes.deserializeDifferentialState(differentialData, differentialDataPos, referenceData, referenceDataPos, useZlib); }
size_t getDifferentialStateSize() const override size_t getDifferentialStateSize() const override
{ return _nes.getDifferentialStateSize(); } { return _nes.getDifferentialStateSize(); }

View File

@ -195,7 +195,10 @@ int main(int argc, char *argv[])
if (differentialCompressionEnabled == true) if (differentialCompressionEnabled == true)
{ {
differentialStateData = (uint8_t *)malloc(fullDifferentialStateSize); differentialStateData = (uint8_t *)malloc(fullDifferentialStateSize);
differentialStateMaxSizeDetected = e.serializeDifferentialState(differentialStateData, currentState, fullDifferentialStateSize, differentialCompressionUseZlib); size_t differentialDataPos = 0;
size_t referenceDataPos = 0;
e.serializeDifferentialState(differentialStateData, &differentialDataPos, currentState, &referenceDataPos, fullDifferentialStateSize, differentialCompressionUseZlib);
differentialStateMaxSizeDetected = differentialDataPos;
} }
// Check whether to perform each action // Check whether to perform each action
@ -211,7 +214,13 @@ int main(int argc, char *argv[])
if (doDeserialize == true) if (doDeserialize == true)
{ {
if (differentialCompressionEnabled == true) e.deserializeDifferentialState(differentialStateData, currentState, differentialCompressionUseZlib); if (differentialCompressionEnabled == true)
{
size_t differentialDataPos = 0;
size_t referenceDataPos = 0;
e.deserializeDifferentialState(differentialStateData, &differentialDataPos, currentState, &referenceDataPos, differentialCompressionUseZlib);
}
if (differentialCompressionEnabled == false) e.deserializeState(currentState); if (differentialCompressionEnabled == false) e.deserializeState(currentState);
} }
@ -219,7 +228,14 @@ int main(int argc, char *argv[])
if (doSerialize == true) if (doSerialize == true)
{ {
if (differentialCompressionEnabled == true) differentialStateMaxSizeDetected = std::max(differentialStateMaxSizeDetected, e.serializeDifferentialState(differentialStateData, currentState, fullDifferentialStateSize, differentialCompressionUseZlib)); if (differentialCompressionEnabled == true)
{
size_t differentialDataPos = 0;
size_t referenceDataPos = 0;
e.serializeDifferentialState(differentialStateData, &differentialDataPos, currentState, &referenceDataPos, fullDifferentialStateSize, differentialCompressionUseZlib);
differentialStateMaxSizeDetected = std::max(differentialStateMaxSizeDetected, differentialDataPos);
}
if (differentialCompressionEnabled == false) e.serializeState(currentState); if (differentialCompressionEnabled == false) e.serializeState(currentState);
} }
} }