Using encapsulated serializators now

This commit is contained in:
Sergio Martin 2024-02-09 20:43:42 +01:00
parent 877d7a4052
commit 944046a78a
10 changed files with 143 additions and 240 deletions

2
extern/jaffarCommon vendored

@ -1 +1 @@
Subproject commit f15d231ead67f064ff6dc3b1aad07b20da088dab Subproject commit 900e829a650eff802db4423b89023fa4d1b545b9

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "jaffarCommon/include/serializers/contiguous.hpp"
#include "jaffarCommon/include/serializers/differential.hpp"
#include "jaffarCommon/include/logger.hpp" #include "jaffarCommon/include/logger.hpp"
#include "controller.hpp" #include "controller.hpp"
@ -65,7 +67,7 @@ class NESInstanceBase
auto status = loadROMImpl(romData, romSize); auto status = loadROMImpl(romData, romSize);
// Detecting full state size // Detecting full state size
_stateSize = getStateSize(); _stateSize = getFullStateSize();
// Returning status // Returning status
return status; return status;
@ -77,7 +79,7 @@ class NESInstanceBase
enableStateBlockImpl(block); enableStateBlockImpl(block);
// Recalculating State size // Recalculating State size
_stateSize = getStateSize(); _stateSize = getFullStateSize();
} }
void disableStateBlock(const std::string& block) void disableStateBlock(const std::string& block)
@ -86,37 +88,19 @@ class NESInstanceBase
disableStateBlockImpl(block); disableStateBlockImpl(block);
// Recalculating State Size // Recalculating State Size
_stateSize = getStateSize(); _stateSize = getFullStateSize();
} }
virtual size_t getFullStateSize() const = 0;
virtual size_t getDifferentialStateSize() const = 0;
// Virtual functions // Virtual functions
virtual uint8_t *getLowMem() const = 0; virtual uint8_t *getLowMem() const = 0;
virtual size_t getLowMemSize() const = 0; virtual size_t getLowMemSize() const = 0;
virtual void serializeState(uint8_t *state) const = 0; virtual void serializeState(jaffarCommon::serializer::Base& serializer) const = 0;
virtual void deserializeState(const uint8_t *state) = 0; virtual void deserializeState(jaffarCommon::deserializer::Base& deserializer) = 0;
virtual size_t getStateSize() const = 0;
virtual void serializeDifferentialState(
uint8_t *outputData,
size_t* outputDataPos,
const size_t outputDataMaxSize,
const uint8_t* referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib) const = 0;
virtual void deserializeDifferentialState(
const uint8_t *inputData,
size_t* inputDataPos,
const size_t inputDataMaxSize,
const uint8_t* referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib) = 0;
virtual size_t getDifferentialStateSize() const = 0;
virtual void doSoftReset() = 0; virtual void doSoftReset() = 0;
virtual void doHardReset() = 0; virtual void doHardReset() = 0;

View File

@ -6,6 +6,8 @@
#include <SDL_image.h> #include <SDL_image.h>
#include <hqn/hqn.h> #include <hqn/hqn.h>
#include <hqn/hqn_gui_controller.h> #include <hqn/hqn_gui_controller.h>
#include <jaffarCommon/include/serializers/contiguous.hpp>
#include <jaffarCommon/include/deserializers/contiguous.hpp>
#include <jaffarCommon/include/hash.hpp> #include <jaffarCommon/include/hash.hpp>
#include "nesInstance.hpp" #include "nesInstance.hpp"
@ -28,8 +30,10 @@ class PlaybackInstance
{ {
stepData_t step; stepData_t step;
step.input = input; step.input = input;
step.stateData = (uint8_t *)malloc(_emu->getStateSize()); step.stateData = (uint8_t *)malloc(_emu->getFullStateSize());
_emu->serializeState(step.stateData);
jaffarCommon::serializer::Contiguous serializer(step.stateData);
_emu->serializeState(serializer);
step.hash = jaffarCommon::calculateMetroHash(_emu->getLowMem(), _emu->getLowMemSize()); step.hash = jaffarCommon::calculateMetroHash(_emu->getLowMem(), _emu->getLowMemSize());
// Adding the step into the sequence // Adding the step into the sequence
@ -166,7 +170,8 @@ class PlaybackInstance
if (stepId > 0) if (stepId > 0)
{ {
const auto stateData = getStateData(stepId - 1); const auto stateData = getStateData(stepId - 1);
_emu->deserializeState(stateData); jaffarCommon::deserializer::Contiguous deserializer(stateData);
_emu->deserializeState(deserializer);
_emu->advanceState(getStateInput(stepId - 1)); _emu->advanceState(getStateInput(stepId - 1));
} }

View File

@ -1,5 +1,7 @@
#include <cstdlib> #include <cstdlib>
#include "jaffarCommon/extern/argparse/argparse.hpp" #include "jaffarCommon/extern/argparse/argparse.hpp"
#include "jaffarCommon/include/serializers/contiguous.hpp"
#include "jaffarCommon/include/deserializers/contiguous.hpp"
#include "jaffarCommon/include/file.hpp" #include "jaffarCommon/include/file.hpp"
#include "jaffarCommon/include/logger.hpp" #include "jaffarCommon/include/logger.hpp"
#include "jaffarCommon/include/string.hpp" #include "jaffarCommon/include/string.hpp"
@ -109,14 +111,15 @@ int main(int argc, char *argv[])
{ {
std::string stateFileData; std::string stateFileData;
if (jaffarCommon::loadStringFromFile(stateFileData, stateFilePath) == false) EXIT_WITH_ERROR("Could not initial state file: %s\n", stateFilePath.c_str()); if (jaffarCommon::loadStringFromFile(stateFileData, stateFilePath) == false) EXIT_WITH_ERROR("Could not initial state file: %s\n", stateFilePath.c_str());
e.deserializeState((uint8_t*)stateFileData.data()); jaffarCommon::deserializer::Contiguous deserializer(stateFileData.data());
e.deserializeState(deserializer);
} }
// Creating playback instance // Creating playback instance
auto p = PlaybackInstance(&e, sequence); auto p = PlaybackInstance(&e, sequence);
// Getting state size // Getting state size
auto stateSize = e.getStateSize(); auto stateSize = e.getFullStateSize();
// Flag to continue running playback // Flag to continue running playback
bool continueRunning = true; bool continueRunning = true;

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "jaffarCommon/include/serializers/base.hpp"
#include "jaffarCommon/include/deserializers/base.hpp"
#include "core/nes_emu/Nes_Emu.h" #include "core/nes_emu/Nes_Emu.h"
#include "core/nes_emu/Nes_State.h" #include "core/nes_emu/Nes_State.h"
#include "../nesInstanceBase.hpp" #include "../nesInstanceBase.hpp"
@ -26,21 +28,21 @@ class NESInstance final : public NESInstanceBase
uint8_t *getLowMem() const override { return _nes.low_mem(); }; uint8_t *getLowMem() const override { return _nes.low_mem(); };
size_t getLowMemSize() const override { return 0x800; }; size_t getLowMemSize() const override { return 0x800; };
void serializeState(uint8_t *state) const override void serializeState(jaffarCommon::serializer::Base& serializer) const override
{ {
Mem_Writer w(state, _stateSize, 0); Mem_Writer w(serializer.getOutputDataBuffer(), _stateSize, 0);
Auto_File_Writer a(w); Auto_File_Writer a(w);
_nes.save_state(a); _nes.save_state(a);
} }
void deserializeState(const uint8_t *state) override void deserializeState(jaffarCommon::deserializer::Base& deserializer) override
{ {
Mem_File_Reader r(state, _stateSize); Mem_File_Reader r(deserializer.getInputDataBuffer(), _stateSize);
Auto_File_Reader a(r); Auto_File_Reader a(r);
_nes.load_state(a); _nes.load_state(a);
} }
inline size_t getStateSize() const override inline size_t getFullStateSize() const override
{ {
uint8_t *data = (uint8_t *)malloc(_DUMMY_SIZE); uint8_t *data = (uint8_t *)malloc(_DUMMY_SIZE);
Mem_Writer w(data, _DUMMY_SIZE); Mem_Writer w(data, _DUMMY_SIZE);
@ -50,28 +52,7 @@ class NESInstance final : public NESInstanceBase
return w.size(); return w.size();
} }
void serializeDifferentialState( inline size_t getDifferentialStateSize() const override { return getFullStateSize(); }
uint8_t *outputData,
size_t* outputDataPos,
const size_t outputDataMaxSize,
const uint8_t* referenceData,
size_t* referenceDataPos,
const size_t maxSize,
const bool useZlib) const override
{ serializeState(outputData); }
void deserializeDifferentialState(
const uint8_t *inputData,
size_t* inputDataPos,
const size_t inputDataMaxSize,
const uint8_t* referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib) override
{ deserializeState(inputData); }
size_t getDifferentialStateSize() const override
{ return getStateSize(); }
std::string getCoreName() const override { return "QuickNES"; } std::string getCoreName() const override { return "QuickNES"; }
void doSoftReset() override { _nes.reset(false); } void doSoftReset() override { _nes.reset(false); }

View File

@ -22,7 +22,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "ppu/ppu.hpp" #include "ppu/ppu.hpp"
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <jaffarCommon/include/diff.hpp> #include <jaffarCommon/include/serializers/base.hpp>
#include <jaffarCommon/include/deserializers/base.hpp>
namespace quickerNES namespace quickerNES
{ {
@ -156,39 +157,24 @@ class Core : private Cpu
static inline void serializeBlockHead( static inline void serializeBlockHead(
const char* blockTag, const char* blockTag,
const uint32_t blockSize, const uint32_t blockSize,
uint8_t* __restrict__ outputData, jaffarCommon::serializer::Base& serializer)
size_t* outputDataPos,
const size_t outputDataMaxSize,
size_t* referenceDataPos,
const size_t referenceDataMaxSize)
{ {
jaffarCommon::serializeContiguousData(blockTag, 4, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(blockTag, 4);
jaffarCommon::serializeContiguousData(&blockSize, 4, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(&blockSize, 4);
} }
static inline void deserializeBlockHead( static inline void deserializeBlockHead(jaffarCommon::deserializer::Base& deserializer)
size_t* inputDataPos,
size_t* referenceDataPos = nullptr)
{ {
*inputDataPos += 8; uint32_t nullValue = 0;
if (referenceDataPos != nullptr) *referenceDataPos += 8; deserializer.popContiguous(&nullValue, 4);
deserializer.popContiguous(&nullValue, 4);
} }
inline void serializeState( inline void serializeState(jaffarCommon::serializer::Base& serializer) const
uint8_t* __restrict__ outputData,
size_t* outputDataPos,
const size_t outputDataMaxSize,
const uint8_t* __restrict__ referenceData = nullptr,
size_t* referenceDataPos = nullptr,
const size_t referenceDataMaxSize = 0,
const bool useZlib = false) const
{ {
size_t tmpIOutputDataPos = 0;
if (outputDataPos == nullptr) outputDataPos = &tmpIOutputDataPos;
// NESS Block // NESS Block
if (HEADBlockEnabled == true) serializeBlockHead("NESS", 0xFFFFFFFF, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("NESS", 0xFFFFFFFF, serializer);
// TIME Block // TIME Block
if (TIMEBlockEnabled == true) if (TIMEBlockEnabled == true)
@ -199,8 +185,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("TIME", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("TIME", inputDataSize, serializer);
jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(inputData, inputDataSize);
} }
// CPUR Block // CPUR Block
@ -218,8 +204,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("CPUR", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("CPUR", inputDataSize, serializer);
jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(inputData, inputDataSize);
} }
if (PPURBlockEnabled == true) if (PPURBlockEnabled == true)
@ -227,8 +213,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("PPUR", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("PPUR", inputDataSize, serializer);
jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(inputData, inputDataSize);
} }
// APUR Block // APUR Block
@ -240,8 +226,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("APUR", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("APUR", inputDataSize, serializer);
jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(inputData, inputDataSize);
} }
// CTRL Block // CTRL Block
@ -250,8 +236,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("CTRL", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("CTRL", inputDataSize, serializer);
jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(inputData, inputDataSize);
} }
// MAPR Block // MAPR Block
@ -260,8 +246,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("MAPR", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("MAPR", inputDataSize, serializer);
jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.pushContiguous(inputData, inputDataSize);
} }
// LRAM Block // LRAM Block
@ -270,9 +256,8 @@ 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("LRAM", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("LRAM", inputDataSize, serializer);
if (referenceDataPos == nullptr) jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.push(inputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize,useZlib);
} }
// SPRT Block // SPRT Block
@ -281,9 +266,8 @@ 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("SPRT", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("SPRT", inputDataSize, serializer);
if (referenceDataPos == nullptr) jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.push(inputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize,useZlib);
} }
// NTAB Block // NTAB Block
@ -295,9 +279,8 @@ 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("NTAB", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("NTAB", inputDataSize, serializer);
if (referenceDataPos == nullptr) jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.push(inputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize,useZlib);
} }
// CHRR Block // CHRR Block
@ -308,9 +291,8 @@ 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("CHRR", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("CHRR", inputDataSize, serializer);
if (referenceDataPos == nullptr) jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.push(inputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize,useZlib);
} }
} }
@ -322,34 +304,23 @@ 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("SRAM", inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("SRAM", inputDataSize, serializer);
if (referenceDataPos == nullptr) jaffarCommon::serializeContiguousData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); serializer.push(inputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::serializeDifferentialData(inputData, inputDataSize, outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize,useZlib);
} }
} }
// gend Block // gend Block
if (HEADBlockEnabled == true) serializeBlockHead("gend", 0, outputData, outputDataPos, outputDataMaxSize, referenceDataPos, referenceDataMaxSize); if (HEADBlockEnabled == true) serializeBlockHead("gend", 0, serializer);
} }
inline void deserializeState( inline void deserializeState(jaffarCommon::deserializer::Base& deserializer)
const uint8_t* __restrict__ inputData,
size_t* inputDataPos,
const size_t inputDataMaxSize,
const uint8_t* __restrict__ referenceData = nullptr,
size_t* referenceDataPos = nullptr,
const size_t referenceDataMaxSize = 0,
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 tmpInputDataPos = 0;
if (inputDataPos == nullptr) inputDataPos = &tmpInputDataPos;
// NESS Block // NESS Block
if (HEADBlockEnabled == true) deserializeBlockHead(inputDataPos, referenceDataPos); if (HEADBlockEnabled == true) deserializeBlockHead(deserializer);
// TIME Block // TIME Block
if (TIMEBlockEnabled == true) if (TIMEBlockEnabled == true)
@ -359,8 +330,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(deserializer);
jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.popContiguous(outputData, inputDataSize);
nes = nesState; nes = nesState;
nes.timestamp /= 5; nes.timestamp /= 5;
@ -374,8 +345,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(deserializer);
jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.popContiguous(outputData, inputDataSize);
r.pc = s.pc; r.pc = s.pc;
r.sp = s.s; r.sp = s.s;
@ -391,8 +362,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(deserializer);
jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.popContiguous(outputData, inputDataSize);
} }
// APUR Block // APUR Block
@ -403,8 +374,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(deserializer);
jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.popContiguous(outputData, inputDataSize);
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);
@ -416,8 +387,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(deserializer);
jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.popContiguous(outputData, inputDataSize);
} }
// MAPR Block // MAPR Block
@ -428,8 +399,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(deserializer);
jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.popContiguous(outputData, inputDataSize);
mapper->apply_mapping(); mapper->apply_mapping();
} }
@ -440,9 +411,8 @@ 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(deserializer);
if (referenceDataPos == nullptr) jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.pop(outputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib);
} }
// SPRT Block // SPRT Block
@ -451,9 +421,8 @@ 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(deserializer);
if (referenceDataPos == nullptr) jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.pop(outputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib);
} }
// NTAB Block // NTAB Block
@ -465,9 +434,8 @@ 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(deserializer);
if (referenceDataPos == nullptr) jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.pop(outputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib);
} }
// CHRR Block // CHRR Block
@ -478,9 +446,8 @@ 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(deserializer);
if (referenceDataPos == nullptr) jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.pop(outputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib);
ppu.all_tiles_modified(); ppu.all_tiles_modified();
} }
@ -494,16 +461,15 @@ 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(deserializer);
if (referenceDataPos == nullptr) jaffarCommon::deserializeContiguousData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceDataPos, referenceDataMaxSize); deserializer.pop(outputData, inputDataSize);
if (referenceDataPos != nullptr) jaffarCommon::deserializeDifferentialData(outputData, inputDataSize, inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, 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(deserializer);
} }
void enableStateBlock(const std::string& block) void enableStateBlock(const std::string& block)

View File

@ -4,7 +4,6 @@
// Emu 0.7.0 // Emu 0.7.0
#include <limits>
#include "cart.hpp" #include "cart.hpp"
#include "core.hpp" #include "core.hpp"
#include "apu/multiBuffer.hpp" #include "apu/multiBuffer.hpp"
@ -46,47 +45,8 @@ 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
void serializeState(uint8_t *buffer) const { emu.serializeState(buffer, nullptr, std::numeric_limits<uint32_t>::max()); } void serializeState(jaffarCommon::serializer::Base& serializer) const { emu.serializeState(serializer); }
void deserializeState(const uint8_t *buffer) { emu.deserializeState(buffer, nullptr, std::numeric_limits<uint32_t>::max()); } void deserializeState(jaffarCommon::deserializer::Base& deserializer) { emu.deserializeState(deserializer); }
size_t getStateSize() const { size_t outputDataPos = 0; emu.serializeState(nullptr, &outputDataPos, std::numeric_limits<uint32_t>::max()); return outputDataPos; }
void serializeDifferentialState(
uint8_t* __restrict__ outputData,
size_t* outputDataPos,
const size_t outputDataMaxSize,
const uint8_t* __restrict__ referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib) const
{
emu.serializeState(outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib);
}
void deserializeDifferentialState(
const uint8_t* __restrict__ inputData,
size_t* inputDataPos,
const size_t inputDataMaxSize,
const uint8_t* __restrict__ referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib)
{
emu.deserializeState(inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib);
}
size_t getDifferentialStateSize() const
{
uint8_t* outputDataPtr = nullptr;
size_t outputDataPos = 0;
uint8_t* referenceDataPtr = nullptr;
size_t referenceDataPos = 0;
uint32_t outputDataMaxSize = std::numeric_limits<uint32_t>::max();
uint32_t referenceDataMaxSize = std::numeric_limits<uint32_t>::max();
emu.serializeState(outputDataPtr, &outputDataPos, outputDataMaxSize, referenceDataPtr, &referenceDataPos, referenceDataMaxSize, 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

@ -24,33 +24,8 @@ class NESInstance final : public NESInstanceBase
uint8_t *getCHRMem() const { return _nes.chr_mem(); }; uint8_t *getCHRMem() const { return _nes.chr_mem(); };
size_t getCHRMemSize() const { return _nes.chr_size(); }; size_t getCHRMemSize() const { return _nes.chr_size(); };
void serializeState(uint8_t *state) const override { _nes.serializeState(state); } void serializeState(jaffarCommon::serializer::Base& serializer) const override { _nes.serializeState(serializer); }
void deserializeState(const uint8_t *state) override { _nes.deserializeState(state); } void deserializeState(jaffarCommon::deserializer::Base& deserializer) override { _nes.deserializeState(deserializer); }
size_t getStateSize() const override { return _nes.getStateSize(); }
void serializeDifferentialState(
uint8_t *outputData,
size_t* outputDataPos,
const size_t outputDataMaxSize,
const uint8_t* referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib) const override
{ _nes.serializeDifferentialState(outputData, outputDataPos, outputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib); }
void deserializeDifferentialState(
const uint8_t *inputData,
size_t* inputDataPos,
const size_t inputDataMaxSize,
const uint8_t* referenceData,
size_t* referenceDataPos,
const size_t referenceDataMaxSize,
const bool useZlib
) override
{ _nes.deserializeDifferentialState(inputData, inputDataPos, inputDataMaxSize, referenceData, referenceDataPos, referenceDataMaxSize, useZlib); }
size_t getDifferentialStateSize() const override
{ return _nes.getDifferentialStateSize(); }
std::string getCoreName() const override { return "QuickerNES"; } std::string getCoreName() const override { return "QuickerNES"; }
@ -59,6 +34,20 @@ class NESInstance final : public NESInstanceBase
void *getInternalEmulatorPointer() override { return &_nes; } void *getInternalEmulatorPointer() override { return &_nes; }
inline size_t getFullStateSize() const override
{
jaffarCommon::serializer::Contiguous serializer;
serializeState(serializer);
return serializer.getOutputSize();
}
inline size_t getDifferentialStateSize() const override
{
jaffarCommon::serializer::Differential serializer;
serializeState(serializer);
return serializer.getOutputSize();
}
protected: protected:
bool loadROMImpl(const uint8_t* romData, const size_t romSize) override bool loadROMImpl(const uint8_t* romData, const size_t romSize) override

View File

@ -1,5 +1,9 @@
#include <jaffarCommon/extern/argparse/argparse.hpp> #include <jaffarCommon/extern/argparse/argparse.hpp>
#include <jaffarCommon/include/json.hpp> #include <jaffarCommon/include/json.hpp>
#include <jaffarCommon/include/serializers/contiguous.hpp>
#include <jaffarCommon/include/serializers/differential.hpp>
#include <jaffarCommon/include/deserializers/contiguous.hpp>
#include <jaffarCommon/include/deserializers/differential.hpp>
#include <jaffarCommon/include/hash.hpp> #include <jaffarCommon/include/hash.hpp>
#include <jaffarCommon/include/string.hpp> #include <jaffarCommon/include/string.hpp>
#include <jaffarCommon/include/file.hpp> #include <jaffarCommon/include/file.hpp>
@ -131,7 +135,8 @@ int main(int argc, char *argv[])
{ {
std::string stateFileData; std::string stateFileData;
if (jaffarCommon::loadStringFromFile(stateFileData, initialStateFilePath) == false) EXIT_WITH_ERROR("Could not initial state file: %s\n", initialStateFilePath.c_str()); if (jaffarCommon::loadStringFromFile(stateFileData, initialStateFilePath) == false) EXIT_WITH_ERROR("Could not initial state file: %s\n", initialStateFilePath.c_str());
e.deserializeState((uint8_t*)stateFileData.data()); jaffarCommon::deserializer::Contiguous d(stateFileData.data());
e.deserializeState(d);
} }
// Disabling requested blocks from state serialization // Disabling requested blocks from state serialization
@ -140,8 +145,8 @@ int main(int argc, char *argv[])
// Disable rendering // Disable rendering
e.disableRendering(); e.disableRendering();
// Getting state size // Getting full state size
const auto stateSize = e.getStateSize(); const auto stateSize = e.getFullStateSize();
// Getting differential state size // Getting differential state size
const auto fixedDiferentialStateSize = e.getDifferentialStateSize(); const auto fixedDiferentialStateSize = e.getDifferentialStateSize();
@ -187,19 +192,23 @@ int main(int argc, char *argv[])
fflush(stdout); fflush(stdout);
// Serializing initial state // Serializing initial state
uint8_t *currentState = (uint8_t *)malloc(stateSize); auto currentState = (uint8_t *)malloc(stateSize);
e.serializeState(currentState); {
jaffarCommon::serializer::Contiguous cs(currentState);
e.serializeState(cs);
}
// Serializing differential state data (in case it's used) // Serializing differential state data (in case it's used)
uint8_t *differentialStateData = nullptr; uint8_t *differentialStateData = nullptr;
size_t differentialStateMaxSizeDetected = 0; size_t differentialStateMaxSizeDetected = 0;
// Allocating memory for differential data and performing the first serialization
if (differentialCompressionEnabled == true) if (differentialCompressionEnabled == true)
{ {
differentialStateData = (uint8_t *)malloc(fullDifferentialStateSize); differentialStateData = (uint8_t *)malloc(fullDifferentialStateSize);
size_t differentialDataPos = 0; auto s = jaffarCommon::serializer::Differential(differentialStateData, fullDifferentialStateSize, currentState, stateSize, differentialCompressionUseZlib);
size_t referenceDataPos = 0; e.serializeState(s);
e.serializeDifferentialState(differentialStateData, &differentialDataPos, fullDifferentialStateSize, currentState, &referenceDataPos, stateSize, differentialCompressionUseZlib); differentialStateMaxSizeDetected = s.getOutputSize();
differentialStateMaxSizeDetected = differentialDataPos;
} }
// Check whether to perform each action // Check whether to perform each action
@ -217,12 +226,15 @@ int main(int argc, char *argv[])
{ {
if (differentialCompressionEnabled == true) if (differentialCompressionEnabled == true)
{ {
size_t differentialDataPos = 0; jaffarCommon::deserializer::Differential d(differentialStateData, fullDifferentialStateSize, currentState, stateSize, differentialCompressionUseZlib);
size_t referenceDataPos = 0; e.deserializeState(d);
e.deserializeDifferentialState(differentialStateData, &differentialDataPos, fullDifferentialStateSize, currentState, &referenceDataPos, stateSize, differentialCompressionUseZlib);
} }
if (differentialCompressionEnabled == false) e.deserializeState(currentState); if (differentialCompressionEnabled == false)
{
jaffarCommon::deserializer::Contiguous d(currentState, stateSize);
e.deserializeState(d);
}
} }
e.advanceState(input); e.advanceState(input);
@ -231,13 +243,16 @@ int main(int argc, char *argv[])
{ {
if (differentialCompressionEnabled == true) if (differentialCompressionEnabled == true)
{ {
size_t differentialDataPos = 0; auto s = jaffarCommon::serializer::Differential(differentialStateData, fullDifferentialStateSize, currentState, stateSize, differentialCompressionUseZlib);
size_t referenceDataPos = 0; e.serializeState(s);
e.serializeDifferentialState(differentialStateData, &differentialDataPos, fullDifferentialStateSize, currentState, &referenceDataPos, stateSize, differentialCompressionUseZlib); differentialStateMaxSizeDetected = std::max(differentialStateMaxSizeDetected, s.getOutputSize());
differentialStateMaxSizeDetected = std::max(differentialStateMaxSizeDetected, differentialDataPos);
} }
if (differentialCompressionEnabled == false) e.serializeState(currentState); if (differentialCompressionEnabled == false)
{
auto s = jaffarCommon::serializer::Contiguous(currentState, stateSize);
e.serializeState(s);
}
} }
} }
auto tf = std::chrono::high_resolution_clock::now(); auto tf = std::chrono::high_resolution_clock::now();

View File

@ -8,7 +8,7 @@
"Controller 2 Type": "None", "Controller 2 Type": "None",
"Differential Compression": "Differential Compression":
{ {
"Enabled": true, "Enabled": true,
"Max Differences": 3100, "Max Differences": 3100,
"Use Zlib": true "Use Zlib": true
} }