From 8f80bcb159762d38eb9e5bf14005cb57a34c160c Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Sat, 13 Nov 2021 15:56:42 +0100 Subject: [PATCH] New serialize framework. Delay maple dma xfer New serialize framework. Refactor serialization into modules. Maple dma xfer must not be executed immediately. Delay until interrupt is raised. Fixes Geist Force freeze at start. --- CMakeLists.txt | 4 +- core/emulator.cpp | 20 +- core/emulator.h | 5 +- core/hw/aica/dsp.h | 44 +- core/hw/aica/sgc_if.cpp | 320 ++++---- core/hw/aica/sgc_if.h | 7 +- core/hw/bba/bba.cpp | 30 +- core/hw/bba/bba.h | 4 +- core/hw/bba/rtl8139c.cpp | 193 ++--- core/hw/bba/rtl8139c.h | 4 +- core/hw/flashrom/flashrom.h | 30 +- core/hw/gdrom/gdrom_if.h | 5 + core/hw/gdrom/gdromv3.cpp | 80 ++ core/hw/holly/holly_intc.cpp | 96 +-- core/hw/maple/maple_cfg.cpp | 48 +- core/hw/maple/maple_cfg.h | 4 +- core/hw/maple/maple_devs.cpp | 83 +- core/hw/maple/maple_devs.h | 27 +- core/hw/maple/maple_if.cpp | 43 +- core/hw/maple/maple_jvs.cpp | 139 ++-- core/hw/modem/modem.cpp | 32 +- core/hw/modem/modem.h | 4 +- core/hw/naomi/awcartridge.cpp | 41 +- core/hw/naomi/awcartridge.h | 4 +- core/hw/naomi/m1cartridge.cpp | 51 +- core/hw/naomi/m1cartridge.h | 4 +- core/hw/naomi/m4cartridge.cpp | 42 +- core/hw/naomi/m4cartridge.h | 4 +- core/hw/naomi/naomi.cpp | 123 +-- core/hw/naomi/naomi.h | 6 +- core/hw/naomi/naomi_cart.cpp | 37 +- core/hw/naomi/naomi_cart.h | 12 +- core/hw/naomi/naomi_flashrom.cpp | 1 - core/hw/pvr/Renderer_if.cpp | 33 +- core/hw/pvr/Renderer_if.h | 4 +- core/hw/pvr/drkPvr.cpp | 44 -- core/hw/pvr/pvr.cpp | 141 ++++ core/hw/pvr/pvr.h | 32 + core/hw/pvr/pvr_mem.cpp | 40 +- core/hw/pvr/pvr_mem.h | 4 +- core/hw/pvr/spg.cpp | 75 +- core/hw/pvr/spg.h | 4 +- core/hw/pvr/ta_ctx.cpp | 59 +- core/hw/pvr/ta_ctx.h | 4 +- core/hw/sh4/modules/mmu.cpp | 2 +- core/hw/sh4/sh4_cache.h | 31 +- core/network/ggpo.cpp | 25 +- core/nullDC.cpp | 43 +- core/reios/gdrom_hle.h | 72 +- core/serialize.cpp | 1259 +++++++++++------------------- core/serialize.h | 212 +++++ core/types.h | 55 +- shell/libretro/libretro.cpp | 29 +- tests/src/serialize_test.cpp | 8 +- 54 files changed, 1863 insertions(+), 1860 deletions(-) delete mode 100644 core/hw/pvr/drkPvr.cpp create mode 100644 core/hw/pvr/pvr.cpp create mode 100644 core/hw/pvr/pvr.h create mode 100644 core/serialize.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d70bf372..4f0003489 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,8 +652,9 @@ target_sources(${PROJECT_NAME} PRIVATE core/hw/naomi/naomi_roms.cpp core/hw/naomi/naomi_roms.h core/hw/naomi/naomi_roms_input.h - core/hw/pvr/drkPvr.cpp core/hw/pvr/helper_classes.h + core/hw/pvr/pvr.cpp + core/hw/pvr/pvr.h core/hw/pvr/pvr_mem.cpp core/hw/pvr/pvr_mem.h core/hw/pvr/pvr_regs.cpp @@ -890,6 +891,7 @@ target_sources(${PROJECT_NAME} PRIVATE core/emulator.h core/nullDC.cpp core/serialize.cpp + core/serialize.h core/stdclass.cpp core/stdclass.h core/types.h diff --git a/core/emulator.cpp b/core/emulator.cpp index a83772410..81359351a 100644 --- a/core/emulator.cpp +++ b/core/emulator.cpp @@ -40,6 +40,8 @@ #include "rend/gui.h" #include "lua/lua.h" #include "network/naomi_network.h" +#include "serialize.h" +#include "hw/pvr/pvr.h" #include settings_t settings; @@ -327,7 +329,7 @@ void dc_reset(bool hard) if (hard) _vmem_unprotect_vram(0, VRAM_SIZE); sh4_sched_reset(hard); - libPvr_Reset(hard); + pvr::reset(hard); libAICA_Reset(hard); libARM_Reset(hard); sh4_cpu.Reset(true); @@ -382,7 +384,7 @@ void Emulator::init() // Default platform setPlatform(DC_PLATFORM_DREAMCAST); - libPvr_Init(); + pvr::init(); libAICA_Init(); libARM_Init(); mem_Init(); @@ -567,7 +569,7 @@ void Emulator::term() reios_term(); libARM_Term(); libAICA_Term(); - libPvr_Term(); + pvr::term(); mem_Term(); _vmem_release(); @@ -646,7 +648,7 @@ void Emulator::step() stop(); } -bool dc_loadstate(const void **data, u32 size) +void dc_loadstate(Deserializer& deser) { custom_texture.Terminate(); #if FEAT_AREC == DYNAREC_JIT @@ -657,17 +659,10 @@ bool dc_loadstate(const void **data, u32 size) bm_Reset(); #endif - u32 usedSize = 0; - if (!dc_unserialize((void **)data, &usedSize)) - return false; - - if (size != usedSize) - WARN_LOG(SAVESTATE, "Savestate: loaded %d bytes but used %d", size, usedSize); + dc_deserialize(deser); mmu_set_state(); sh4_cpu.ResetCache(); - - return true; } void Emulator::setNetworkState(bool online) @@ -821,4 +816,5 @@ void Emulator::vblank() else if (!config::ThreadedRendering) sh4_cpu.Stop(); } + Emulator emu; diff --git a/core/emulator.h b/core/emulator.h index 49c2f77ad..4946c32cc 100644 --- a/core/emulator.h +++ b/core/emulator.h @@ -26,17 +26,18 @@ #include #include #include +#include void loadGameSpecificSettings(); void SaveSettings(); int flycast_init(int argc, char* argv[]); -void dc_reset(bool hard); +void dc_reset(bool hard); // for tests only void flycast_term(); void dc_exit(); void dc_savestate(int index = 0); void dc_loadstate(int index = 0); -bool dc_loadstate(const void **data, unsigned size); +void dc_loadstate(Deserializer& deser); enum class Event { Start, diff --git a/core/hw/aica/dsp.h b/core/hw/aica/dsp.h index 2b70829af..ff3b9453a 100644 --- a/core/hw/aica/dsp.h +++ b/core/hw/aica/dsp.h @@ -1,5 +1,6 @@ #pragma once #include "types.h" +#include "serialize.h" namespace dsp { @@ -28,35 +29,28 @@ struct DSPState bool stopped; // DSP program is a no-op bool dirty; // DSP program has changed - bool serialize(void **data, unsigned int *total_size) + void serialize(Serializer& ser) { - REICAST_S(TEMP); - REICAST_S(MEMS); - REICAST_S(MIXS); - REICAST_S(RBP); - REICAST_S(RBL); - REICAST_S(MDEC_CT); - - return true; + ser << TEMP; + ser << MEMS; + ser << MIXS; + ser << RBP; + ser << RBL; + ser << MDEC_CT; } - bool deserialize(void **data, unsigned int *total_size, serialize_version_enum version) + void deserialize(Deserializer& deser) { - if (version < V18) - REICAST_SKIP(4096 * 8); // DynCode - REICAST_US(TEMP); - REICAST_US(MEMS); - REICAST_US(MIXS); - REICAST_US(RBP); - REICAST_US(RBL); - if (version < V18) - REICAST_SKIP(44); - REICAST_US(MDEC_CT); - if (version < V18) - REICAST_SKIP(33596 - 4096 * 8 - sizeof(TEMP) - sizeof(MEMS) - sizeof(MIXS) - 4 * 3 - 44); // other dsp stuff - dirty = true; - - return true; + deser.skip(4096 * 8, Deserializer::V18); // DynCode + deser >> TEMP; + deser >> MEMS; + deser >> MIXS; + deser >> RBP; + deser >> RBL; + deser.skip(44, Deserializer::V18); + deser >> MDEC_CT; + deser.skip(33596 - 4096 * 8 - sizeof(TEMP) - sizeof(MEMS) - sizeof(MIXS) - 4 * 3 - 44, + Deserializer::V18); // other dsp stuff } }; diff --git a/core/hw/aica/sgc_if.cpp b/core/hw/aica/sgc_if.cpp index a3721a2ad..6e44c5ffb 100755 --- a/core/hw/aica/sgc_if.cpp +++ b/core/hw/aica/sgc_if.cpp @@ -26,6 +26,7 @@ #include "oslib/audiostream.h" #include "hw/gdrom/gdrom_if.h" #include "cfg/option.h" +#include "serialize.h" #include #include @@ -153,7 +154,17 @@ static void VolumePan(SampleType value, u32 vol, u32 pan, SampleType& outl, Samp } } -DSP_OUT_VOL_REG* dsp_out_vol; +template +static void clip(T& v, T min, T max) { + v = std::min(max, std::max(min, v)); +} + +template +static void clip16(T& v) { + clip(v, -32768, 32767); +} + +const DSP_OUT_VOL_REG *dsp_out_vol = (DSP_OUT_VOL_REG *)&aica_reg[0x2000]; static int beepOn; static int beepPeriod; static int beepCounter; @@ -549,8 +560,8 @@ struct ChannelEx __forceinline static void StepAll(SampleType& mixl, SampleType& mixr) { - for (int i = 0; i < 64; i++) - Chans[i].Step(mixl, mixr); + for (ChannelEx& channel : Chans) + channel.Step(mixl, mixr); } void SetAegState(_EG_state newstate) @@ -780,12 +791,12 @@ struct ChannelEx if ((offset == 0x01 || size == 2) && ccd->KYONEX) { ccd->KYONEX=0; - for (int i = 0; i < 64; i++) + for (ChannelEx& channel : Chans) { - if (Chans[i].ccd->KYONB) - Chans[i].KEY_ON(); + if (channel.ccd->KYONB) + channel.KEY_ON(); else - Chans[i].KEY_OFF(); + channel.KEY_OFF(); } } break; @@ -1289,7 +1300,6 @@ void sgc_Init() } for (int i=0;i<64;i++) Chans[i].Init(i,aica_reg); - dsp_out_vol=(DSP_OUT_VOL_REG*)&aica_reg[0x2000]; for (int s = 0; s < 8; s++) { @@ -1400,8 +1410,8 @@ static SampleType vmuBeepSample() } constexpr int CDDA_SIZE = 2352 / 2; -s16 cdda_sector[CDDA_SIZE]; -u32 cdda_index = CDDA_SIZE; +static s16 cdda_sector[CDDA_SIZE]; +static u32 cdda_index = CDDA_SIZE; //no DSP for now in this version void AICA_Sample32() @@ -1587,157 +1597,160 @@ void AICA_Sample() WriteSample(mixr,mixl); } -bool channel_serialize(void **data, unsigned int *total_size) +void channel_serialize(Serializer& ser) { - int i = 0 ; - int addr = 0 ; - - for ( i = 0 ; i < 64 ; i++) + for (const ChannelEx& channel : Chans) { - addr = Chans[i].SA - (&(aica_ram[0])) ; - REICAST_S(addr); + u32 addr = channel.SA - &aica_ram[0]; + ser << addr; - REICAST_S(Chans[i].CA) ; - REICAST_S(Chans[i].step) ; - REICAST_S(Chans[i].s0) ; - REICAST_S(Chans[i].s1) ; - REICAST_S(Chans[i].loop.looped) ; - REICAST_S(Chans[i].adpcm.last_quant) ; - REICAST_S(Chans[i].adpcm.loopstart_quant); - REICAST_S(Chans[i].adpcm.loopstart_prev_sample); - REICAST_S(Chans[i].adpcm.in_loop); - REICAST_S(Chans[i].noise_state) ; + ser << channel.CA; + ser << channel.step; + ser << channel.s0; + ser << channel.s1; + ser << channel.loop.looped; + ser << channel.adpcm.last_quant; + ser << channel.adpcm.loopstart_quant; + ser << channel.adpcm.loopstart_prev_sample; + ser << channel.adpcm.in_loop; + ser << channel.noise_state; - REICAST_S(Chans[i].AEG.val) ; - REICAST_S(Chans[i].AEG.state) ; - REICAST_S(Chans[i].FEG.value); - REICAST_S(Chans[i].FEG.state); - REICAST_S(Chans[i].FEG.prev1); - REICAST_S(Chans[i].FEG.prev2); + ser << channel.AEG.val; + ser << channel.AEG.state; + ser << channel.FEG.value; + ser << channel.FEG.state; + ser << channel.FEG.prev1; + ser << channel.FEG.prev2; - REICAST_S(Chans[i].lfo.counter) ; - REICAST_S(Chans[i].lfo.state) ; - REICAST_S(Chans[i].enabled) ; + ser << channel.lfo.counter; + ser << channel.lfo.state; + ser << channel.enabled; } - REICAST_S(beepOn); - REICAST_S(beepPeriod); - REICAST_S(beepCounter); - - return true; + ser << beepOn; + ser << beepPeriod; + ser << beepCounter; + ser << cdda_sector; + ser << cdda_index; } -bool channel_unserialize(void **data, unsigned int *total_size, serialize_version_enum ver) +void channel_deserialize(Deserializer& deser) { - int i = 0 ; - int addr = 0 ; - u32 dum; - bool old_format = (ver >= V5 && ver < V7) || ver < V8_LIBRETRO; - - for ( i = 0 ; i < 64 ; i++) + if (deser.version() < Deserializer::V7_LIBRETRO) { - Chans[i].quiet = true; - REICAST_US(addr); - Chans[i].SA = addr + (&(aica_ram[0])) ; - - REICAST_US(Chans[i].CA) ; - REICAST_US(Chans[i].step) ; - if (old_format) - REICAST_US(dum); // Chans[i].update_rate - Chans[i].UpdatePitch(); - REICAST_US(Chans[i].s0) ; - REICAST_US(Chans[i].s1) ; - REICAST_US(Chans[i].loop.looped); - if (old_format) - { - REICAST_US(dum); // Chans[i].loop.LSA - REICAST_US(dum); // Chans[i].loop.LEA - } - Chans[i].UpdateLoop(); - REICAST_US(Chans[i].adpcm.last_quant) ; - if (!old_format) - { - REICAST_US(Chans[i].adpcm.loopstart_quant); - REICAST_US(Chans[i].adpcm.loopstart_prev_sample); - REICAST_US(Chans[i].adpcm.in_loop); - } - else - { - Chans[i].adpcm.in_loop = true; - Chans[i].adpcm.loopstart_quant = 0; - Chans[i].adpcm.loopstart_prev_sample = 0; - } - REICAST_US(Chans[i].noise_state) ; - if (old_format) - { - REICAST_US(dum); // Chans[i].VolMix.DLAtt - REICAST_US(dum); // Chans[i].VolMix.DRAtt - REICAST_US(dum); // Chans[i].VolMix.DSPAtt - } - Chans[i].UpdateAtts(); - if (old_format) - REICAST_US(dum); // Chans[i].VolMix.DSPOut - Chans[i].UpdateDSPMIX(); - - REICAST_US(Chans[i].AEG.val) ; - REICAST_US(Chans[i].AEG.state) ; - Chans[i].SetAegState(Chans[i].AEG.state); - if (old_format) - { - REICAST_US(dum); // Chans[i].AEG.AttackRate - REICAST_US(dum); // Chans[i].AEG.Decay1Rate - REICAST_US(dum); // Chans[i].AEG.Decay2Rate - REICAST_US(dum); // Chans[i].AEG.Decay2Value - REICAST_US(dum); // Chans[i].AEG.ReleaseRate - } - Chans[i].UpdateAEG(); - REICAST_US(Chans[i].FEG.value); - REICAST_US(Chans[i].FEG.state); - if (!old_format) - { - REICAST_US(Chans[i].FEG.prev1); - REICAST_US(Chans[i].FEG.prev2); - } - else - { - Chans[i].FEG.prev1 = 0; - Chans[i].FEG.prev2 = 0; - } - Chans[i].SetFegState(Chans[i].FEG.state); - Chans[i].UpdateFEG(); - if (old_format) - { - u8 dumu8; - REICAST_US(dumu8); // Chans[i].step_stream_lut1 - REICAST_US(dumu8); // Chans[i].step_stream_lut2 - REICAST_US(dumu8); // Chans[i].step_stream_lut3 - } - Chans[i].UpdateStreamStep(); - - REICAST_US(Chans[i].lfo.counter) ; - if (old_format) - REICAST_US(dum); // Chans[i].lfo.start_value - REICAST_US(Chans[i].lfo.state) ; - if (old_format) - { - u8 dumu8; - REICAST_US(dumu8); // Chans[i].lfo.alfo - REICAST_US(dumu8); // Chans[i].lfo.alfo_shft - REICAST_US(dumu8); // Chans[i].lfo.plfo - REICAST_US(dumu8); // Chans[i].lfo.plfo_shft - REICAST_US(dumu8); // Chans[i].lfo.alfo_calc_lut - REICAST_US(dumu8); // Chans[i].lfo.plfo_calc_lut - } - Chans[i].UpdateLFO(true); - REICAST_US(Chans[i].enabled) ; - if (old_format) - REICAST_US(dum); // Chans[i].ChannelNumber - Chans[i].quiet = false; + deser.skip(4 * 16); // volume_lut + deser.skip(4 * 256 + 768); // tl_lut. Due to a previous bug this is not 4 * (256 + 768) + deser.skip(4 * 64); // AEG_ATT_SPS + deser.skip(4 * 64); // AEG_DSR_SPS + deser.skip(2); // pl + deser.skip(2); // pr } - if (ver >= V22) + + bool old_format = (deser.version() >= Deserializer::V5 && deser.version() < Deserializer::V7) || deser.version() < Deserializer::V8_LIBRETRO; + + for (ChannelEx& channel : Chans) { - REICAST_US(beepOn); - REICAST_US(beepPeriod); - REICAST_US(beepCounter); + channel.quiet = true; + u32 addr; + deser >> addr; + channel.SA = addr + &aica_ram[0]; + + deser >> channel.CA; + deser >> channel.step; + if (old_format) + deser.skip(); // channel.update_rate + channel.UpdatePitch(); + deser >> channel.s0; + deser >> channel.s1; + deser >> channel.loop.looped; + if (old_format) + { + deser.skip(); // channel.loop.LSA + deser.skip(); // channel.loop.LEA + } + channel.UpdateLoop(); + deser >> channel.adpcm.last_quant; + if (!old_format) + { + deser >> channel.adpcm.loopstart_quant; + deser >> channel.adpcm.loopstart_prev_sample; + deser >> channel.adpcm.in_loop; + } + else + { + channel.adpcm.in_loop = true; + channel.adpcm.loopstart_quant = 0; + channel.adpcm.loopstart_prev_sample = 0; + } + deser >> channel.noise_state; + if (old_format) + { + deser.skip(); // channel.VolMix.DLAtt + deser.skip(); // channel.VolMix.DRAtt + deser.skip(); // channel.VolMix.DSPAtt + } + channel.UpdateAtts(); + if (old_format) + deser.skip(); // channel.VolMix.DSPOut + channel.UpdateDSPMIX(); + + deser >> channel.AEG.val; + deser >> channel.AEG.state; + channel.SetAegState(channel.AEG.state); + if (old_format) + { + deser.skip(); // channel.AEG.AttackRate + deser.skip(); // channel.AEG.Decay1Rate + deser.skip(); // channel.AEG.Decay2Rate + deser.skip(); // channel.AEG.Decay2Value + deser.skip(); // channel.AEG.ReleaseRate + } + channel.UpdateAEG(); + deser >> channel.FEG.value; + deser >> channel.FEG.state; + if (!old_format) + { + deser >> channel.FEG.prev1; + deser >> channel.FEG.prev2; + } + else + { + channel.FEG.prev1 = 0; + channel.FEG.prev2 = 0; + } + channel.SetFegState(channel.FEG.state); + channel.UpdateFEG(); + if (old_format) + { + deser.skip(); // channel.step_stream_lut1 + deser.skip(); // channel.step_stream_lut2 + deser.skip(); // channel.step_stream_lut3 + } + channel.UpdateStreamStep(); + + deser >> channel.lfo.counter; + if (old_format) + deser.skip(); // channel.lfo.start_value + deser >> channel.lfo.state; + if (old_format) + { + deser.skip(); // channel.lfo.alfo + deser.skip(); // channel.lfo.alfo_shft + deser.skip(); // channel.lfo.plfo + deser.skip(); // channel.lfo.plfo_shft + deser.skip(); // channel.lfo.alfo_calc_lut + deser.skip(); // channel.lfo.plfo_calc_lut + } + channel.UpdateLFO(true); + deser >> channel.enabled; + if (old_format) + deser.skip(); // channel.ChannelNumber + channel.quiet = false; + } + if (deser.version() >= Deserializer::V22) + { + deser >> beepOn; + deser >> beepPeriod; + deser >> beepCounter; } else { @@ -1745,6 +1758,11 @@ bool channel_unserialize(void **data, unsigned int *total_size, serialize_versio beepPeriod = 0; beepCounter = 0; } - - return true; + deser >> cdda_sector; + deser >> cdda_index; + if (deser.version() < Deserializer::V9_LIBRETRO) + { + deser.skip(4 * 64); // mxlr + deser.skip(4); // samples_gen + } } diff --git a/core/hw/aica/sgc_if.h b/core/hw/aica/sgc_if.h index 52da16ce8..f6c44a733 100644 --- a/core/hw/aica/sgc_if.h +++ b/core/hw/aica/sgc_if.h @@ -50,13 +50,10 @@ struct DSP_OUT_VOL_REG u32 pad:16; }; -//#define SAMPLE_TYPE_SHIFT (8) typedef s32 SampleType; void ReadCommonReg(u32 reg,bool byte); void WriteCommonReg8(u32 reg,u32 data); -#define clip(x,min,max) do { if ((x)<(min)) (x)=(min); else if ((x)>(max)) (x)=(max); } while (false) -#define clip16(x) clip(x,-32768,32767) -bool channel_serialize(void **data, unsigned int *total_size); -bool channel_unserialize(void **data, unsigned int *total_size, serialize_version_enum version); +void channel_serialize(Serializer& ctx); +void channel_deserialize(Deserializer& ctx); void vmuBeep(int on, int period); diff --git a/core/hw/bba/bba.cpp b/core/hw/bba/bba.cpp index 546993f95..be071d252 100644 --- a/core/hw/bba/bba.cpp +++ b/core/hw/bba/bba.cpp @@ -20,6 +20,7 @@ #include "rtl8139c.h" #include "hw/holly/holly_intc.h" #include "network/picoppp.h" +#include "serialize.h" static RTL8139State *rtl8139device; @@ -231,27 +232,26 @@ void pci_dma_write(PCIDevice *dev, dma_addr_t addr, const void *buf, dma_addr_t memcpy(&GAPS_ram[addr & GAPSPCI_RAM_MASK], buf, len); } -void bba_Serialize(void **data, unsigned int *total_size) +void bba_Serialize(Serializer& ser) { - REICAST_S(GAPS_regs); - REICAST_S(GAPS_ram); - REICAST_S(dmaOffset); - REICAST_S(interruptPending); - rtl8139_serialize(rtl8139device, data, total_size); + ser << GAPS_regs; + ser << GAPS_ram; + ser << dmaOffset; + ser << interruptPending; + rtl8139_serialize(rtl8139device, ser); } -void bba_Unserialize(void **data, unsigned int *total_size) +void bba_Deserialize(Deserializer& deser) { - REICAST_US(GAPS_regs); - REICAST_US(GAPS_ram); - REICAST_US(dmaOffset); - REICAST_US(interruptPending); - // returns true if the receiver is enabled and the network stack must be started - if (rtl8139_unserialize(rtl8139device, data, total_size)) - start_pico(); + deser >> GAPS_regs; + deser >> GAPS_ram; + deser >> dmaOffset; + deser >> interruptPending; + // returns true if the receiver is enabled and the network stack must be started + if (rtl8139_deserialize(rtl8139device, deser)) + start_pico(); } - #define POLYNOMIAL_BE 0x04c11db6 uint32_t net_crc32(const uint8_t *p, int len) diff --git a/core/hw/bba/bba.h b/core/hw/bba/bba.h index be6497889..e20f8ad21 100644 --- a/core/hw/bba/bba.h +++ b/core/hw/bba/bba.h @@ -24,5 +24,5 @@ void bba_Term(); void bba_Reset(bool hard); u32 bba_ReadMem(u32 addr, u32 sz); void bba_WriteMem(u32 addr, u32 data, u32 sz); -void bba_Serialize(void **data, unsigned int *total_size); -void bba_Unserialize(void **data, unsigned int *total_size); +void bba_Serialize(Serializer& ser); +void bba_Deserialize(Deserializer& deser); diff --git a/core/hw/bba/rtl8139c.cpp b/core/hw/bba/rtl8139c.cpp index 3172318e9..e39f09f63 100644 --- a/core/hw/bba/rtl8139c.cpp +++ b/core/hw/bba/rtl8139c.cpp @@ -50,6 +50,7 @@ /* For crc32 */ #include #include "rtl8139c.h" +#include "serialize.h" /* debug RTL8139 card */ //#define DEBUG_RTL8139 1 @@ -2327,132 +2328,132 @@ void rtl8139_destroy(RTL8139State *state) free(state); } -void rtl8139_serialize(RTL8139State *s, void **data, unsigned int *total_size) +void rtl8139_serialize(RTL8139State *s, Serializer& ser) { - REICAST_SA(s->parent_obj.config, 256); - REICAST_SA(s->parent_obj.cmask, 256); - REICAST_SA(s->parent_obj.wmask, 256); - REICAST_S(s->parent_obj.io_regions); + ser.serialize(s->parent_obj.config, 256); + ser.serialize(s->parent_obj.cmask, 256); + ser.serialize(s->parent_obj.wmask, 256); + ser << s->parent_obj.io_regions; - REICAST_S(s->phys); - REICAST_S(s->mult); - REICAST_S(s->TxStatus); - REICAST_S(s->TxAddr); + ser << s->phys; + ser << s->mult; + ser << s->TxStatus; + ser << s->TxAddr; - REICAST_S(s->RxBuf); - REICAST_S(s->RxBufferSize); - REICAST_S(s->RxBufPtr); - REICAST_S(s->RxBufAddr); + ser << s->RxBuf; + ser << s->RxBufferSize; + ser << s->RxBufPtr; + ser << s->RxBufAddr; - REICAST_S(s->IntrStatus); - REICAST_S(s->IntrMask); + ser << s->IntrStatus; + ser << s->IntrMask; - REICAST_S(s->TxConfig); - REICAST_S(s->RxConfig); - REICAST_S(s->RxMissed); - REICAST_S(s->CSCR); + ser << s->TxConfig; + ser << s->RxConfig; + ser << s->RxMissed; + ser << s->CSCR; - REICAST_S(s->Cfg9346); - REICAST_S(s->Config0); - REICAST_S(s->Config1); - REICAST_S(s->Config3); - REICAST_S(s->Config4); - REICAST_S(s->Config5); + ser << s->Cfg9346; + ser << s->Config0; + ser << s->Config1; + ser << s->Config3; + ser << s->Config4; + ser << s->Config5; - REICAST_S(s->clock_enabled); - REICAST_S(s->bChipCmdState); + ser << s->clock_enabled; + ser << s->bChipCmdState; - REICAST_S(s->MultiIntr); + ser << s->MultiIntr; - REICAST_S(s->BasicModeCtrl); - REICAST_S(s->BasicModeStatus); - REICAST_S(s->NWayAdvert); - REICAST_S(s->NWayLPAR); - REICAST_S(s->NWayExpansion); + ser << s->BasicModeCtrl; + ser << s->BasicModeStatus; + ser << s->NWayAdvert; + ser << s->NWayLPAR; + ser << s->NWayExpansion; - REICAST_S(s->conf.macaddr); + ser << s->conf.macaddr; - REICAST_S(s->currTxDesc); + ser << s->currTxDesc; - REICAST_S(s->eeprom.contents); - REICAST_S(s->eeprom.mode); - REICAST_S(s->eeprom.tick); - REICAST_S(s->eeprom.address); - REICAST_S(s->eeprom.input); - REICAST_S(s->eeprom.output); + ser << s->eeprom.contents; + ser << s->eeprom.mode; + ser << s->eeprom.tick; + ser << s->eeprom.address; + ser << s->eeprom.input; + ser << s->eeprom.output; - REICAST_S(s->eeprom.eecs); - REICAST_S(s->eeprom.eesk); - REICAST_S(s->eeprom.eedi); - REICAST_S(s->eeprom.eedo); + ser << s->eeprom.eecs; + ser << s->eeprom.eesk; + ser << s->eeprom.eedi; + ser << s->eeprom.eedo; - REICAST_S(s->TCTR); - REICAST_S(s->TimerInt); - REICAST_S(s->TCTR_base); + ser << s->TCTR; + ser << s->TimerInt; + ser << s->TCTR_base; } -bool rtl8139_unserialize(RTL8139State *s, void **data, unsigned int *total_size) +bool rtl8139_deserialize(RTL8139State *s, Deserializer& deser) { - REICAST_USA(s->parent_obj.config, 256); - REICAST_USA(s->parent_obj.cmask, 256); - REICAST_USA(s->parent_obj.wmask, 256); - REICAST_US(s->parent_obj.io_regions); + deser.deserialize(s->parent_obj.config, 256); + deser.deserialize(s->parent_obj.cmask, 256); + deser.deserialize(s->parent_obj.wmask, 256); + deser >> s->parent_obj.io_regions; - REICAST_US(s->phys); - REICAST_US(s->mult); - REICAST_US(s->TxStatus); - REICAST_US(s->TxAddr); + deser >> s->phys; + deser >> s->mult; + deser >> s->TxStatus; + deser >> s->TxAddr; - REICAST_US(s->RxBuf); - REICAST_US(s->RxBufferSize); - REICAST_US(s->RxBufPtr); - REICAST_US(s->RxBufAddr); + deser >> s->RxBuf; + deser >> s->RxBufferSize; + deser >> s->RxBufPtr; + deser >> s->RxBufAddr; - REICAST_US(s->IntrStatus); - REICAST_US(s->IntrMask); + deser >> s->IntrStatus; + deser >> s->IntrMask; - REICAST_US(s->TxConfig); - REICAST_US(s->RxConfig); - REICAST_US(s->RxMissed); - REICAST_US(s->CSCR); + deser >> s->TxConfig; + deser >> s->RxConfig; + deser >> s->RxMissed; + deser >> s->CSCR; - REICAST_US(s->Cfg9346); - REICAST_US(s->Config0); - REICAST_US(s->Config1); - REICAST_US(s->Config3); - REICAST_US(s->Config4); - REICAST_US(s->Config5); + deser >> s->Cfg9346; + deser >> s->Config0; + deser >> s->Config1; + deser >> s->Config3; + deser >> s->Config4; + deser >> s->Config5; - REICAST_US(s->clock_enabled); - REICAST_US(s->bChipCmdState); + deser >> s->clock_enabled; + deser >> s->bChipCmdState; - REICAST_US(s->MultiIntr); + deser >> s->MultiIntr; - REICAST_US(s->BasicModeCtrl); - REICAST_US(s->BasicModeStatus); - REICAST_US(s->NWayAdvert); - REICAST_US(s->NWayLPAR); - REICAST_US(s->NWayExpansion); + deser >> s->BasicModeCtrl; + deser >> s->BasicModeStatus; + deser >> s->NWayAdvert; + deser >> s->NWayLPAR; + deser >> s->NWayExpansion; - REICAST_US(s->conf.macaddr); + deser >> s->conf.macaddr; - REICAST_US(s->currTxDesc); + deser >> s->currTxDesc; - REICAST_US(s->eeprom.contents); - REICAST_US(s->eeprom.mode); - REICAST_US(s->eeprom.tick); - REICAST_US(s->eeprom.address); - REICAST_US(s->eeprom.input); - REICAST_US(s->eeprom.output); + deser >> s->eeprom.contents; + deser >> s->eeprom.mode; + deser >> s->eeprom.tick; + deser >> s->eeprom.address; + deser >> s->eeprom.input; + deser >> s->eeprom.output; - REICAST_US(s->eeprom.eecs); - REICAST_US(s->eeprom.eesk); - REICAST_US(s->eeprom.eedi); - REICAST_US(s->eeprom.eedo); + deser >> s->eeprom.eecs; + deser >> s->eeprom.eesk; + deser >> s->eeprom.eedi; + deser >> s->eeprom.eedo; - REICAST_US(s->TCTR); - REICAST_US(s->TimerInt); - REICAST_US(s->TCTR_base); + deser >> s->TCTR; + deser >> s->TimerInt; + deser >> s->TCTR_base; return s->bChipCmdState & CmdRxEnb; } diff --git a/core/hw/bba/rtl8139c.h b/core/hw/bba/rtl8139c.h index ce8c0430a..973d90047 100644 --- a/core/hw/bba/rtl8139c.h +++ b/core/hw/bba/rtl8139c.h @@ -214,5 +214,5 @@ ssize_t rtl8139_receive(RTL8139State *s, const uint8_t *buf, size_t size); RTL8139State *rtl8139_init(NICConf *conf); void rtl8139_destroy(RTL8139State *state); -void rtl8139_serialize(RTL8139State *state, void **data, unsigned int *total_size); -bool rtl8139_unserialize(RTL8139State *state, void **data, unsigned int *total_size); +void rtl8139_serialize(RTL8139State *state, Serializer& ser); +bool rtl8139_deserialize(RTL8139State *state, Deserializer& deser); diff --git a/core/hw/flashrom/flashrom.h b/core/hw/flashrom/flashrom.h index eece44b91..6d7f0ac86 100644 --- a/core/hw/flashrom/flashrom.h +++ b/core/hw/flashrom/flashrom.h @@ -5,6 +5,7 @@ #pragma once #include #include "types.h" +#include "serialize.h" struct MemChip { @@ -54,8 +55,8 @@ public: void digest(u8 md5Digest[16]); virtual void Reset() {} - virtual bool Serialize(void **data, unsigned int *total_size) { return true; } - virtual bool Unserialize(void **data, unsigned int *total_size) { return true; } + virtual void Serialize(Serializer& ser) const { } + virtual void Deserialize(Deserializer& deser) { } }; struct WritableChip : MemChip @@ -106,16 +107,13 @@ struct SRamChip : WritableChip } } - bool Serialize(void **data, unsigned int *total_size) override + void Serialize(Serializer& ser) const override { - REICAST_SA(&this->data[write_protect_size], size - write_protect_size); - return true; + ser.serialize(&this->data[write_protect_size], size - write_protect_size); } - - bool Unserialize(void **data, unsigned int *total_size) override + void Deserialize(Deserializer& deser) override { - REICAST_USA(&this->data[write_protect_size], size - write_protect_size); - return true; + deser.deserialize(&this->data[write_protect_size], size - write_protect_size); } }; @@ -712,18 +710,16 @@ private: return result; } - bool Serialize(void **data, unsigned int *total_size) override + void Serialize(Serializer& ser) const override { - REICAST_S(state); - REICAST_SA(&this->data[write_protect_size], size - write_protect_size); - return true; + ser << state; + ser.serialize(&this->data[write_protect_size], size - write_protect_size); } - bool Unserialize(void **data, unsigned int *total_size) override + void Deserialize(Deserializer& deser) override { - REICAST_US(state); - REICAST_USA(&this->data[write_protect_size], size - write_protect_size); - return true; + deser >> state; + deser.deserialize(&this->data[write_protect_size], size - write_protect_size); } void erase_partition(u32 part_id) diff --git a/core/hw/gdrom/gdrom_if.h b/core/hw/gdrom/gdrom_if.h index feaf0c7a1..b71180429 100644 --- a/core/hw/gdrom/gdrom_if.h +++ b/core/hw/gdrom/gdrom_if.h @@ -25,3 +25,8 @@ enum DiscType Open=0x2, //tray is open :) }; +namespace gdrom +{ +void serialize(Serializer& ser); +void deserialize(Deserializer& deser); +} diff --git a/core/hw/gdrom/gdromv3.cpp b/core/hw/gdrom/gdromv3.cpp index c096496fe..6a76b3ab5 100644 --- a/core/hw/gdrom/gdromv3.cpp +++ b/core/hw/gdrom/gdromv3.cpp @@ -12,6 +12,7 @@ #include "hw/sh4/sh4_mem.h" #include "hw/sh4/sh4_sched.h" #include "imgread/common.h" +#include "serialize.h" int gdrom_schid; @@ -1251,3 +1252,82 @@ void gdrom_reg_Reset(bool hard) libCore_gdrom_disc_change(); } + +namespace gdrom +{ + +void serialize(Serializer& ser) +{ + ser << GD_HardwareInfo; + + ser << sns_asc; + ser << sns_ascq; + ser << sns_key; + + ser << packet_cmd; + ser << set_mode_offset; + ser << read_params; + ser << read_buff; + ser << pio_buff; + ser << set_mode_offset; + ser << ata_cmd; + ser << cdda; + ser << gd_state; + ser << gd_disk_type; + ser << data_write_mode; + ser << DriveSel; + ser << Error; + + ser << IntReason; + ser << Features; + ser << SecCount; + ser << SecNumber; + ser << GDStatus; + ser << ByteCount; +} + +void deserialize(Deserializer& deser) +{ + deser >> GD_HardwareInfo; + + deser >> sns_asc; + deser >> sns_ascq; + deser >> sns_key; + + deser >> packet_cmd; + deser >> set_mode_offset; + deser >> read_params; + if (deser.version() >= Deserializer::V17) + deser >> read_buff; + else + { + deser >> packet_cmd; + read_buff.cache_size = 0; + // read_buff (old) + if (deser.version() < Deserializer::V9_LIBRETRO + || (deser.version() >= Deserializer::V5 && deser.version() < Deserializer::V8)) + deser.skip(4 + 4 + 2352 * 8192); + } + deser >> pio_buff; + deser >> set_mode_offset; + deser >> ata_cmd; + deser >> cdda; + if (deser.version() < Deserializer::V10) + cdda.status = (bool)cdda.status ? cdda_t::Playing : cdda_t::NoInfo; + deser >> gd_state; + deser >> gd_disk_type; + deser >> data_write_mode; + deser >> DriveSel; + deser >> Error; + + deser >> IntReason; + deser >> Features; + deser >> SecCount; + deser >> SecNumber; + deser >> GDStatus; + deser >> ByteCount; + if (deser.version() >= Deserializer::V5_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO) + deser.skip(); // GDROM_TICK +} + +} diff --git a/core/hw/holly/holly_intc.cpp b/core/hw/holly/holly_intc.cpp index 4bbdab67e..742d641b8 100644 --- a/core/hw/holly/holly_intc.cpp +++ b/core/hw/holly/holly_intc.cpp @@ -1,6 +1,5 @@ #include "holly_intc.h" #include "sb.h" -#include "hw/maple/maple_if.h" #include "hw/sh4/sh4_interrupts.h" /* @@ -9,7 +8,7 @@ */ //asic_RLXXPending: Update the intc flags for pending interrupts -void asic_RL6Pending() +static void asic_RL6Pending() { bool t1=(SB_ISTNRM & SB_IML6NRM)!=0; bool t2=(SB_ISTERR & SB_IML6ERR)!=0; @@ -18,7 +17,7 @@ void asic_RL6Pending() InterruptPend(sh4_IRL_9,t1|t2|t3); } -void asic_RL4Pending() +static void asic_RL4Pending() { bool t1=(SB_ISTNRM & SB_IML4NRM)!=0; bool t2=(SB_ISTERR & SB_IML4ERR)!=0; @@ -27,7 +26,7 @@ void asic_RL4Pending() InterruptPend(sh4_IRL_11,t1|t2|t3); } -void asic_RL2Pending() +static void asic_RL2Pending() { bool t1=(SB_ISTNRM & SB_IML2NRM)!=0; bool t2=(SB_ISTERR & SB_IML2ERR)!=0; @@ -36,58 +35,28 @@ void asic_RL2Pending() InterruptPend(sh4_IRL_13,t1|t2|t3); } -//Raise interrupt interface -void RaiseAsicNormal(HollyInterruptID inter) -{ - if (inter==holly_SCANINT2) - maple_vblank(); - - u32 Interrupt = 1<<(u8)inter; - SB_ISTNRM |= Interrupt; - - asic_RL2Pending(); - asic_RL4Pending(); - asic_RL6Pending(); -} - -void RaiseAsicExt(HollyInterruptID inter) -{ - u32 Interrupt = 1<<(u8)inter; - SB_ISTEXT |= Interrupt; - - asic_RL2Pending(); - asic_RL4Pending(); - asic_RL6Pending(); -} - -void RaiseAsicErr(HollyInterruptID inter) -{ - u32 Interrupt = 1<<(u8)inter; - SB_ISTERR |= Interrupt; - - asic_RL2Pending(); - asic_RL4Pending(); - asic_RL6Pending(); -} - void asic_RaiseInterrupt(HollyInterruptID inter) { - u8 m=inter>>8; - switch(m) + u8 type = inter >> 8; + u32 mask = 1 << (u8)inter; + switch(type) { case 0: - RaiseAsicNormal(inter); + SB_ISTNRM |= mask; break; case 1: - RaiseAsicExt(inter); + SB_ISTEXT |= mask; break; case 2: - RaiseAsicErr(inter); + SB_ISTERR |= mask; break; } + asic_RL2Pending(); + asic_RL4Pending(); + asic_RL6Pending(); } -u32 Read_SB_ISTNRM(u32 addr) +static u32 Read_SB_ISTNRM(u32 addr) { /* Note that the two highest bits indicate * the OR'ed result of all the bits in @@ -104,7 +73,7 @@ u32 Read_SB_ISTNRM(u32 addr) return tmp; } -void Write_SB_ISTNRM(u32 addr, u32 data) +static void Write_SB_ISTNRM(u32 addr, u32 data) { /* writing a 1 clears the interrupt */ SB_ISTNRM &= ~data; @@ -116,18 +85,31 @@ void Write_SB_ISTNRM(u32 addr, u32 data) void asic_CancelInterrupt(HollyInterruptID inter) { - SB_ISTEXT&=~(1<<(u8)inter); + u8 type = inter >> 8; + u32 mask = ~(1 << (u8)inter); + switch (type) + { + case 0: + SB_ISTNRM &= mask; + break; + case 1: + SB_ISTEXT &= mask; + break; + case 2: + SB_ISTERR &= mask; + break; + } asic_RL2Pending(); asic_RL4Pending(); asic_RL6Pending(); } -void Write_SB_ISTEXT(u32 addr, u32 data) +static void Write_SB_ISTEXT(u32 addr, u32 data) { //nothing happens -- asic_CancelInterrupt is used instead } -void Write_SB_ISTERR(u32 addr, u32 data) +static void Write_SB_ISTERR(u32 addr, u32 data) { SB_ISTERR &= ~data; @@ -136,58 +118,58 @@ void Write_SB_ISTERR(u32 addr, u32 data) asic_RL6Pending(); } -void Write_SB_IML6NRM(u32 addr, u32 data) +static void Write_SB_IML6NRM(u32 addr, u32 data) { SB_IML6NRM=data; asic_RL6Pending(); } -void Write_SB_IML4NRM(u32 addr, u32 data) +static void Write_SB_IML4NRM(u32 addr, u32 data) { SB_IML4NRM=data; asic_RL4Pending(); } -void Write_SB_IML2NRM(u32 addr, u32 data) +static void Write_SB_IML2NRM(u32 addr, u32 data) { SB_IML2NRM=data; asic_RL2Pending(); } -void Write_SB_IML6EXT(u32 addr, u32 data) +static void Write_SB_IML6EXT(u32 addr, u32 data) { SB_IML6EXT=data; asic_RL6Pending(); } -void Write_SB_IML4EXT(u32 addr, u32 data) +static void Write_SB_IML4EXT(u32 addr, u32 data) { SB_IML4EXT=data; asic_RL4Pending(); } -void Write_SB_IML2EXT(u32 addr, u32 data) +static void Write_SB_IML2EXT(u32 addr, u32 data) { SB_IML2EXT=data; asic_RL2Pending(); } -void Write_SB_IML6ERR(u32 addr, u32 data) +static void Write_SB_IML6ERR(u32 addr, u32 data) { SB_IML6ERR=data; asic_RL6Pending(); } -void Write_SB_IML4ERR(u32 addr, u32 data) +static void Write_SB_IML4ERR(u32 addr, u32 data) { SB_IML4ERR=data; asic_RL4Pending(); } -void Write_SB_IML2ERR(u32 addr, u32 data) +static void Write_SB_IML2ERR(u32 addr, u32 data) { SB_IML2ERR=data; diff --git a/core/hw/maple/maple_cfg.cpp b/core/hw/maple/maple_cfg.cpp index da2540d3d..868c6337e 100644 --- a/core/hw/maple/maple_cfg.cpp +++ b/core/hw/maple/maple_cfg.cpp @@ -4,8 +4,11 @@ #include "hw/naomi/naomi_cart.h" #include "cfg/option.h" #include "stdclass.h" +#include "serialize.h" MapleInputState mapleInputState[4]; +extern bool maple_ddt_pending_reset; +extern std::vector>> mapleDmaOut; void (*MapleConfigMap::UpdateVibration)(u32 port, float power, float inclination, u32 duration_ms); @@ -366,8 +369,16 @@ void mcfg_DestroyDevices() } } -void mcfg_SerializeDevices(void **data, unsigned int *total_size) +void mcfg_SerializeDevices(Serializer& ser) { + ser << maple_ddt_pending_reset; + ser << (u32)mapleDmaOut.size(); + for (const auto& pair : mapleDmaOut) + { + ser << pair.first; // u32 address + ser << (u32)pair.second.size(); + ser.serialize(pair.second.data(), pair.second.size()); + } for (int i = 0; i < MAPLE_PORTS; i++) for (int j = 0; j < 6; j++) { @@ -375,25 +386,50 @@ void mcfg_SerializeDevices(void **data, unsigned int *total_size) maple_device* device = MapleDevices[i][j]; if (device != nullptr) deviceType = device->get_device_type(); - REICAST_S(deviceType); + ser << deviceType; if (device != nullptr) - device->serialize(data, total_size); + device->serialize(ser); } } -void mcfg_UnserializeDevices(void **data, unsigned int *total_size, serialize_version_enum version) +void mcfg_DeserializeDevices(Deserializer& deser) { mcfg_DestroyDevices(); + u8 eeprom[sizeof(maple_naomi_jamma::eeprom)]; + if (deser.version() < Deserializer::V23) + { + deser >> eeprom; + deser.skip(128); // Unused eeprom space + deser.skip(); // EEPROM_loaded + } + deser >> maple_ddt_pending_reset; + mapleDmaOut.clear(); + if (deser.version() >= Deserializer::V23) + { + u32 size; + deser >> size; + for (u32 i = 0; i < size; i++) + { + u32 address; + deser >> address; + u32 dataSize; + deser >> dataSize; + mapleDmaOut.emplace_back(address, std::vector(dataSize)); + deser.deserialize(mapleDmaOut.back().second.data(), dataSize); + } + } for (int i = 0; i < MAPLE_PORTS; i++) for (int j = 0; j < 6; j++) { u8 deviceType; - REICAST_US(deviceType); + deser >> deviceType; if (deviceType != MDT_None) { mcfg_Create((MapleDeviceType)deviceType, i, j); - MapleDevices[i][j]->unserialize(data, total_size, version); + MapleDevices[i][j]->deserialize(deser); } } + if (deser.version() < Deserializer::V23 && EEPROM != nullptr) + memcpy(EEPROM, eeprom, sizeof(eeprom)); } diff --git a/core/hw/maple/maple_cfg.h b/core/hw/maple/maple_cfg.h index 7b798aaa4..6ccf1d6d2 100644 --- a/core/hw/maple/maple_cfg.h +++ b/core/hw/maple/maple_cfg.h @@ -102,8 +102,8 @@ extern MapleInputState mapleInputState[4]; void mcfg_CreateDevices(); void mcfg_DestroyDevices(); -void mcfg_SerializeDevices(void **data, unsigned int *total_size); -void mcfg_UnserializeDevices(void **data, unsigned int *total_size, serialize_version_enum version); +void mcfg_SerializeDevices(Serializer& ser); +void mcfg_DeserializeDevices(Deserializer& deser); bool maple_atomiswave_coin_chute(int slot); void push_vmu_screen(int bus_id, int bus_port, u8* buffer); diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index 7b38a0b3d..5a02cb7af 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -323,27 +323,25 @@ struct maple_sega_vmu: maple_base return MDT_SegaVMU; } - bool serialize(void **data, unsigned int *total_size) override + void serialize(Serializer& ser) const override { - maple_base::serialize(data, total_size); - REICAST_S(flash_data); - REICAST_S(lcd_data); - REICAST_S(lcd_data_decoded); - return true ; + maple_base::serialize(ser); + ser << flash_data; + ser << lcd_data; + ser << lcd_data_decoded; } - bool unserialize(void **data, unsigned int *total_size, serialize_version_enum version) override + void deserialize(Deserializer& deser) override { - maple_base::unserialize(data, total_size, version); - REICAST_US(flash_data); - REICAST_US(lcd_data); - REICAST_US(lcd_data_decoded); + maple_base::deserialize(deser); + deser >> flash_data; + deser >> lcd_data; + deser >> lcd_data_decoded; for (u8 b : lcd_data) if (b != 0) { config->SetImage(lcd_data_decoded); break; } - return true ; } void initializeVmu() @@ -735,28 +733,26 @@ struct maple_microphone: maple_base return MDT_Microphone; } - bool serialize(void **data, unsigned int *total_size) override + void serialize(Serializer& ser) const override { - maple_base::serialize(data, total_size); - REICAST_S(gain); - REICAST_S(sampling); - REICAST_S(eight_khz); - REICAST_SKIP(480 - sizeof(u32) - sizeof(bool) * 2); - return true; + maple_base::serialize(ser); + ser << gain; + ser << sampling; + ser << eight_khz; } - bool unserialize(void **data, unsigned int *total_size, serialize_version_enum version) override + void deserialize(Deserializer& deser) override { if (sampling) StopAudioRecording(); - maple_base::unserialize(data, total_size, version); - REICAST_US(gain); - REICAST_US(sampling); - REICAST_US(eight_khz); - REICAST_SKIP(480 - sizeof(u32) - sizeof(bool) * 2); + maple_base::deserialize(deser); + deser >> gain; + deser >> sampling; + deser >> eight_khz; + deser.skip(480 - sizeof(u32) - sizeof(bool) * 2, Deserializer::V23); if (sampling) StartAudioRecording(eight_khz); - return true; } + void OnSetup() override { gain = 0xf; @@ -909,22 +905,21 @@ struct maple_sega_purupuru : maple_base return MDT_PurupuruPack; } - bool serialize(void **data, unsigned int *total_size) override - { - maple_base::serialize(data, total_size); - REICAST_S(AST); - REICAST_S(AST_ms); - REICAST_S(VIBSET); - return true ; - } - bool unserialize(void **data, unsigned int *total_size, serialize_version_enum version) override - { - maple_base::unserialize(data, total_size, version); - REICAST_US(AST); - REICAST_US(AST_ms); - REICAST_US(VIBSET); - return true ; - } + void serialize(Serializer& ser) const override + { + maple_base::serialize(ser); + ser << AST; + ser << AST_ms; + ser << VIBSET; + } + void deserialize(Deserializer& deser) override + { + maple_base::deserialize(deser); + deser >> AST; + deser >> AST_ms; + deser >> VIBSET; + } + u32 dma(u32 cmd) override { switch (cmd) @@ -1166,10 +1161,10 @@ struct maple_mouse : maple_base wstr(maple_sega_brand, 60); // Low-consumption standby current (2) - w16(0x0069); // 10.5 mA + w16(0x0190); // 40 mA // Maximum current consumption (2) - w16(0x0120); // 28.8 mA + w16(0x01f4); // 50 mA return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll; diff --git a/core/hw/maple/maple_devs.h b/core/hw/maple/maple_devs.h index 7c00b9eef..277ccc496 100755 --- a/core/hw/maple/maple_devs.h +++ b/core/hw/maple/maple_devs.h @@ -5,6 +5,7 @@ #include "maple_helper.h" #include #include "input/gamepad.h" +#include "serialize.h" enum MapleFunctionID { @@ -133,15 +134,15 @@ struct maple_device virtual ~maple_device(); virtual u32 RawDma(u32* buffer_in, u32 buffer_in_len, u32* buffer_out) = 0; - virtual bool serialize(void **data, unsigned int *total_size) { - REICAST_S(player_num); - return true; + + virtual void serialize(Serializer& ser) const { + ser << player_num; } - virtual bool unserialize(void **data, unsigned int *total_size, serialize_version_enum version) { - if (version >= V14) - REICAST_US(player_num); - return true; + virtual void deserialize(Deserializer& deser) { + if (deser.version() >= Deserializer::V14) + deser >> player_num; } + virtual MapleDeviceType get_device_type() = 0; virtual bool get_lightgun_pos() { return false; } virtual const void *getData(size_t& size) const { size = 0; return nullptr; } @@ -163,8 +164,7 @@ void limit_joystick_magnitude(s8& joyx, s8& joyy) } } -extern u8 EEPROM[0x100]; -void load_naomi_eeprom(); +extern u8 *EEPROM; #define SWAP32(a) ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff)) @@ -257,7 +257,7 @@ class jvs_io_board; struct maple_naomi_jamma : maple_base { - const u8 ALL_NODES = 0xff; + static constexpr u8 ALL_NODES = 0xff; std::vector> io_boards; bool crazy_mode = false; @@ -265,9 +265,10 @@ struct maple_naomi_jamma : maple_base u8 jvs_repeat_request[32][256]; u8 jvs_receive_buffer[32][258]; u32 jvs_receive_length[32] = { 0 }; + u8 eeprom[128]; maple_naomi_jamma(); - ~maple_naomi_jamma() override; + ~maple_naomi_jamma(); MapleDeviceType get_device_type() override { @@ -289,6 +290,6 @@ struct maple_naomi_jamma : maple_base u32 RawDma(u32* buffer_in, u32 buffer_in_len, u32* buffer_out) override; u32 dma(u32 cmd) override { return 0; } - bool serialize(void **data, unsigned int *total_size) override; - bool unserialize(void **data, unsigned int *total_size, serialize_version_enum version) override; + void serialize(Serializer& ser) const override; + void deserialize(Deserializer& deser) override; }; diff --git a/core/hw/maple/maple_if.cpp b/core/hw/maple/maple_if.cpp index c3d9e5732..dd449a843 100644 --- a/core/hw/maple/maple_if.cpp +++ b/core/hw/maple/maple_if.cpp @@ -38,6 +38,8 @@ static void maple_handle_reconnect(); //ddt/etc are just hacked for wince to work //now with proper maple delayed DMA maybe its time to look into it ? bool maple_ddt_pending_reset; +// pending DMA xfers +std::vector>> mapleDmaOut; void maple_vblank() { @@ -175,6 +177,7 @@ static void maple_DoDma() { asic_RaiseInterrupt(holly_MAPLE_OVERRUN); SB_MDST = 0; + mapleDmaOut.clear(); return; } #else @@ -185,13 +188,12 @@ static void maple_DoDma() header_2|=(3<<26); } #endif - u32* p_out=(u32*)GetMemPtr(header_2,4); - - u32* p_data =(u32*) GetMemPtr(addr + 8,(plen)*sizeof(u32)); - if (p_data == NULL) + u32* p_data = (u32 *)GetMemPtr(addr + 8, plen * sizeof(u32)); + if (p_data == nullptr) { INFO_LOG(MAPLE, "MAPLE ERROR : INVALID SB_MDSTAR value 0x%X", addr); - SB_MDST=0; + SB_MDST = 0; + mapleDmaOut.clear(); return; } const u32 frame_header = swap_msb ? SWAP32(p_data[0]) : p_data[0]; @@ -213,37 +215,33 @@ static void maple_DoDma() if (swap_msb) { static u32 maple_in_buf[1024 / 4]; - static u32 maple_out_buf[1024 / 4]; maple_in_buf[0] = frame_header; for (u32 i = 1; i < inlen; i++) maple_in_buf[i] = SWAP32(p_data[i]); p_data = maple_in_buf; - p_out = maple_out_buf; } - u32 outlen = MapleDevices[bus][port]->RawDma(&p_data[0], inlen * 4 + 4, &p_out[0]); + u32 outbuf[1024 / 4]; + u32 outlen = MapleDevices[bus][port]->RawDma(&p_data[0], inlen * 4 + 4, outbuf); xfer_count += outlen; #ifdef STRICT_MODE if (!check_mdapro(header_2 + outlen - 1)) { - // TODO: This isn't correct (with SB_MMSEL=1) since the interrupt - // should be raised before the memory is written to asic_RaiseInterrupt(holly_MAPLE_OVERRUN); SB_MDST = 0; + mapleDmaOut.clear(); return; } #endif if (swap_msb) - { - u32 *final_out = (u32 *)GetMemPtr(header_2, outlen); for (u32 i = 0; i < outlen / 4; i++) - final_out[i] = SWAP32(p_out[i]); - } + outbuf[i] = SWAP32(outbuf[i]); + mapleDmaOut.emplace_back(header_2, std::vector(outbuf, outbuf + outlen / 4)); } else { if (port != 5 && command != 1) INFO_LOG(MAPLE, "MAPLE: Unknown device bus %d port %d cmd %d reci %d", bus, port, command, reci); - p_out[0]=0xFFFFFFFF; + mapleDmaOut.emplace_back(header_2, std::vector(1, 0xFFFFFFFF)); } //goto next command @@ -278,23 +276,30 @@ static void maple_DoDma() } } - //printf("Maple XFER size %d bytes - %.2f ms\n",xfer_count,xfer_count*100.0f/(2*1024*1024/8)); + //printf("Maple XFER size %d bytes - %.2f ms\n", xfer_count, xfer_count * 1000.0f / (2 * 1024 * 1024 / 8)); if (!occupy) sh4_sched_request(maple_schid, std::min((u64)xfer_count * (SH4_MAIN_CLOCK / (2 * 1024 * 1024 / 8)), (u64)SH4_MAIN_CLOCK)); } static int maple_schd(int tag, int c, int j) { - if (SB_MDEN&1) + if (SB_MDEN & 1) { - SB_MDST=0; + for (const auto& pair : mapleDmaOut) + { + size_t size = pair.second.size() * sizeof(u32); + u32 *p = (u32 *)GetMemPtr(pair.first, size); + memcpy(p, pair.second.data(), size); + } + SB_MDST = 0; asic_RaiseInterrupt(holly_MAPLE_DMA); } else { INFO_LOG(MAPLE, "WARNING: MAPLE DMA ABORT"); - SB_MDST=0; //I really wonder what this means, can the DMA be continued ? + SB_MDST = 0; //I really wonder what this means, can the DMA be continued ? } + mapleDmaOut.clear(); return 0; } diff --git a/core/hw/maple/maple_jvs.cpp b/core/hw/maple/maple_jvs.cpp index 837043385..623c1b9c7 100644 --- a/core/hw/maple/maple_jvs.cpp +++ b/core/hw/maple/maple_jvs.cpp @@ -27,36 +27,7 @@ #define LOGJVS(...) DEBUG_LOG(JVS, __VA_ARGS__) -u8 EEPROM[0x100]; -bool EEPROM_loaded = false; - -void load_naomi_eeprom() -{ - if (!EEPROM_loaded) - { - EEPROM_loaded = true; - std::string eeprom_file = hostfs::getArcadeFlashPath() + ".eeprom"; - FILE* f = nowide::fopen(eeprom_file.c_str(), "rb"); - if (f) - { - if (std::fread(EEPROM, 1, 0x80, f) != 0x80) - WARN_LOG(MAPLE, "Failed or truncated read of EEPROM '%s'", eeprom_file.c_str()); - std::fclose(f); - DEBUG_LOG(MAPLE, "Loaded EEPROM from %s", eeprom_file.c_str()); - } - else if (naomi_default_eeprom != NULL) - { - DEBUG_LOG(MAPLE, "Using default EEPROM file"); - memcpy(EEPROM, naomi_default_eeprom, 0x80); - } - else - DEBUG_LOG(MAPLE, "EEPROM file not found at %s and no default found", eeprom_file.c_str()); - if (config::GGPOEnable) - MD5Sum().add(EEPROM, sizeof(EEPROM)) - .getDigest(settings.network.md5.eeprom); - - } -} +u8 *EEPROM; const u32 naomi_button_mapping[32] = { NAOMI_BTN2_KEY, // DC_BTN_C @@ -175,8 +146,8 @@ public: virtual ~jvs_io_board() = default; u32 handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_out); - bool serialize(void **data, unsigned int *total_size); - bool unserialize(void **data, unsigned int *total_size, serialize_version_enum version); + void serialize(Serializer& ser) const; + void deserialize(Deserializer& deser); bool lightgun_as_analog = false; @@ -706,11 +677,32 @@ maple_naomi_jamma::maple_naomi_jamma() io_boards.push_back(std::unique_ptr(new jvs_837_13844_wrungp(1, this))); break; } + + std::string eeprom_file = hostfs::getArcadeFlashPath() + ".eeprom"; + FILE* f = nowide::fopen(eeprom_file.c_str(), "rb"); + if (f) + { + if (std::fread(eeprom, 1, 0x80, f) != 0x80) + WARN_LOG(MAPLE, "Failed or truncated read of EEPROM '%s'", eeprom_file.c_str()); + std::fclose(f); + DEBUG_LOG(MAPLE, "Loaded EEPROM from %s", eeprom_file.c_str()); + } + else if (naomi_default_eeprom != NULL) + { + DEBUG_LOG(MAPLE, "Using default EEPROM file"); + memcpy(eeprom, naomi_default_eeprom, 0x80); + } + else + DEBUG_LOG(MAPLE, "EEPROM file not found at %s and no default found", eeprom_file.c_str()); + if (config::GGPOEnable) + MD5Sum().add(eeprom, sizeof(eeprom)) + .getDigest(settings.network.md5.eeprom); + EEPROM = eeprom; } maple_naomi_jamma::~maple_naomi_jamma() { - EEPROM_loaded = false; + EEPROM = nullptr; } void maple_naomi_jamma::send_jvs_message(u32 node_id, u32 channel, u32 length, u8 *data) @@ -976,18 +968,19 @@ void maple_naomi_jamma::handle_86_subcommand() case 0x0B: //EEPROM write { - load_naomi_eeprom(); int address = dma_buffer_in[1]; int size = dma_buffer_in[2]; DEBUG_LOG(MAPLE, "EEprom write %08X %08X\n", address, size); //printState(Command,buffer_in,buffer_in_len); - memcpy(EEPROM + address, dma_buffer_in + 4, size); + address = address % sizeof(eeprom); + size = std::min((int)sizeof(eeprom) - address, size); + memcpy(eeprom + address, dma_buffer_in + 4, size); std::string eeprom_file = hostfs::getArcadeFlashPath() + ".eeprom"; FILE* f = nowide::fopen(eeprom_file.c_str(), "wb"); if (f) { - std::fwrite(EEPROM, 1, 0x80, f); + std::fwrite(eeprom, 1, sizeof(eeprom), f); std::fclose(f); INFO_LOG(MAPLE, "Saved EEPROM to %s", eeprom_file.c_str()); } @@ -998,7 +991,7 @@ void maple_naomi_jamma::handle_86_subcommand() w8(0x00); w8(0x20); w8(0x01); - memcpy(dma_buffer_out, EEPROM, 4); + memcpy(dma_buffer_out, eeprom, 4); dma_buffer_out += 4; *dma_count_out += 4; } @@ -1006,17 +999,17 @@ void maple_naomi_jamma::handle_86_subcommand() case 0x3: //EEPROM read { - load_naomi_eeprom(); //printf("EEprom READ\n"); - int address = dma_buffer_in[1]; + int address = dma_buffer_in[1] % sizeof(eeprom); //printState(Command,buffer_in,buffer_in_len); w8(MDRS_JVSReply); w8(0x00); w8(0x20); w8(0x20); - memcpy(dma_buffer_out, EEPROM + address, 0x80); - dma_buffer_out += 0x80; - *dma_count_out += 0x80; + int size = sizeof(eeprom) - address; + memcpy(dma_buffer_out, eeprom + address, size); + dma_buffer_out += size; + *dma_count_out += size; } break; @@ -1237,34 +1230,33 @@ u32 maple_naomi_jamma::RawDma(u32* buffer_in, u32 buffer_in_len, u32* buffer_out return out_len; } -bool maple_naomi_jamma::serialize(void **data, unsigned int *total_size) +void maple_naomi_jamma::serialize(Serializer& ser) const { - maple_base::serialize(data, total_size); - REICAST_S(crazy_mode); - REICAST_S(jvs_repeat_request); - REICAST_S(jvs_receive_length); - REICAST_S(jvs_receive_buffer); - size_t board_count = io_boards.size(); - REICAST_S(board_count); + maple_base::serialize(ser); + ser << crazy_mode; + ser << jvs_repeat_request; + ser << jvs_receive_length; + ser << jvs_receive_buffer; + ser << eeprom; + u32 board_count = io_boards.size(); + ser << board_count; for (u32 i = 0; i < io_boards.size(); i++) - io_boards[i]->serialize(data, total_size); - - return true ; + io_boards[i]->serialize(ser); } - -bool maple_naomi_jamma::unserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void maple_naomi_jamma::deserialize(Deserializer& deser) { - maple_base::unserialize(data, total_size, version); - REICAST_US(crazy_mode); - REICAST_US(jvs_repeat_request); - REICAST_US(jvs_receive_length); - REICAST_US(jvs_receive_buffer); - size_t board_count; - REICAST_US(board_count); + maple_base::deserialize(deser); + deser >> crazy_mode; + deser >> jvs_repeat_request; + deser >> jvs_receive_length; + deser >> jvs_receive_buffer; + if (deser.version() >= Deserializer::V23) + deser >> eeprom; + u32 board_count; + deser >> board_count; + deser.skip(sizeof(size_t) - sizeof(u32), Deserializer::V23); for (u32 i = 0; i < board_count; i++) - io_boards[i]->unserialize(data, total_size, version); - - return true ; + io_boards[i]->deserialize(deser); } u16 jvs_io_board::read_analog_axis(int player_num, int player_axis, bool inverted) @@ -1675,18 +1667,13 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou return length; } -bool jvs_io_board::serialize(void **data, unsigned int *total_size) +void jvs_io_board::serialize(Serializer& ser) const { - REICAST_S(node_id); - REICAST_S(lightgun_as_analog); - - return true ; + ser << node_id; + ser << lightgun_as_analog; } - -bool jvs_io_board::unserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void jvs_io_board::deserialize(Deserializer& deser) { - REICAST_US(node_id); - REICAST_US(lightgun_as_analog); - - return true ; + deser >> node_id; + deser >> lightgun_as_analog; } diff --git a/core/hw/modem/modem.cpp b/core/hw/modem/modem.cpp index 680d2fdfe..57d4e5704 100644 --- a/core/hw/modem/modem.cpp +++ b/core/hw/modem/modem.cpp @@ -27,6 +27,7 @@ #include "hw/sh4/sh4_sched.h" #include "oslib/oslib.h" #include "network/picoppp.h" +#include "serialize.h" #define MODEM_COUNTRY_RES 0 #define MODEM_COUNTRY_JAP 1 @@ -748,25 +749,24 @@ void ModemWriteMem_A0_006(u32 addr, u32 data, u32 size) LOG("modem reg %03X write %X -- wtf is it?",reg,data); } -void ModemSerialize(void **data, unsigned int *total_size) +void ModemSerialize(Serializer& ser) { - REICAST_S(modem_regs); - REICAST_S(dspram); - REICAST_S(state); - REICAST_S(connect_state); - REICAST_S(last_dial_time); - REICAST_S(data_sent); + ser << modem_regs; + ser << dspram; + ser << state; + ser << connect_state; + ser << last_dial_time; + ser << data_sent; } - -void ModemDeserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void ModemDeserialize(Deserializer& deser) { - if (version >= V20) + if (deser.version() >= Deserializer::V20) { - REICAST_US(modem_regs); - REICAST_US(dspram); - REICAST_US(state); - REICAST_US(connect_state); - REICAST_US(last_dial_time); - REICAST_US(data_sent); + deser >> modem_regs; + deser >> dspram; + deser >> state; + deser >> connect_state; + deser >> last_dial_time; + deser >> data_sent; } } diff --git a/core/hw/modem/modem.h b/core/hw/modem/modem.h index 41a87d394..0c45ba8aa 100644 --- a/core/hw/modem/modem.h +++ b/core/hw/modem/modem.h @@ -29,5 +29,5 @@ void ModemReset(); void ModemTerm(); u32 ModemReadMem_A0_006(u32 addr,u32 size); void ModemWriteMem_A0_006(u32 addr,u32 data,u32 size); -void ModemSerialize(void **data, unsigned int *total_size); -void ModemDeserialize(void **data, unsigned int *total_size, serialize_version_enum version); +void ModemSerialize(Serializer& ser); +void ModemDeserialize(Deserializer& deser); diff --git a/core/hw/naomi/awcartridge.cpp b/core/hw/naomi/awcartridge.cpp index 3715d2452..be170e995 100644 --- a/core/hw/naomi/awcartridge.cpp +++ b/core/hw/naomi/awcartridge.cpp @@ -162,6 +162,7 @@ ROM board internal layouts: */ #include "awcartridge.h" #include "awave_regs.h" +#include "serialize.h" u32 AWCartridge::ReadMem(u32 address, u32 size) { verify(size != 1); @@ -423,28 +424,28 @@ std::string AWCartridge::GetGameId() return game_id; } -void AWCartridge::Serialize(void **data, unsigned int *total_size) +void AWCartridge::Serialize(Serializer& ser) const { - REICAST_S(mpr_offset); - REICAST_S(mpr_bank); - REICAST_S(epr_offset); - REICAST_S(mpr_file_offset); - REICAST_S(mpr_record_index); - REICAST_S(mpr_first_file_index); - REICAST_S(dma_offset); - REICAST_S(dma_limit); - Cartridge::Serialize(data, total_size); + ser << mpr_offset; + ser << mpr_bank; + ser << epr_offset; + ser << mpr_file_offset; + ser << mpr_record_index; + ser << mpr_first_file_index; + ser << dma_offset; + ser << dma_limit; + Cartridge::Serialize(ser); } -void AWCartridge::Unserialize(void **data, unsigned int *total_size) +void AWCartridge::Deserialize(Deserializer& deser) { - REICAST_US(mpr_offset); - REICAST_US(mpr_bank); - REICAST_US(epr_offset); - REICAST_US(mpr_file_offset); - REICAST_US(mpr_record_index); - REICAST_US(mpr_first_file_index); - REICAST_US(dma_offset); - REICAST_US(dma_limit); - Cartridge::Unserialize(data, total_size); + deser >> mpr_offset; + deser >> mpr_bank; + deser >> epr_offset; + deser >> mpr_file_offset; + deser >> mpr_record_index; + deser >> mpr_first_file_index; + deser >> dma_offset; + deser >> dma_limit; + Cartridge::Deserialize(deser); } diff --git a/core/hw/naomi/awcartridge.h b/core/hw/naomi/awcartridge.h index 9d5b29ffc..6ddfae4ad 100644 --- a/core/hw/naomi/awcartridge.h +++ b/core/hw/naomi/awcartridge.h @@ -28,8 +28,8 @@ public: std::string GetGameId() override; void SetKey(u32 key) override; - void Serialize(void **data, unsigned int *total_size) override; - void Unserialize(void **data, unsigned int *total_size) override; + void Serialize(Serializer& ser) const override; + void Deserialize(Deserializer& deser) override; private: void device_reset(); diff --git a/core/hw/naomi/m1cartridge.cpp b/core/hw/naomi/m1cartridge.cpp index 9313196bf..bd82664ce 100644 --- a/core/hw/naomi/m1cartridge.cpp +++ b/core/hw/naomi/m1cartridge.cpp @@ -8,6 +8,7 @@ * // copyright-holders:Olivier Galibert */ #include "m1cartridge.h" +#include "serialize.h" M1Cartridge::M1Cartridge(u32 size) : NaomiCartridge(size) { @@ -127,32 +128,34 @@ u32 M1Cartridge::get_decrypted_32b() return res; } -void M1Cartridge::Serialize(void** data, unsigned int* total_size) { - REICAST_S(buffer); - REICAST_S(dict); - REICAST_S(hist); - REICAST_S(avail_val); - REICAST_S(rom_cur_address); - REICAST_S(buffer_actual_size); - REICAST_S(avail_bits); - REICAST_S(stream_ended); - REICAST_S(has_history); - REICAST_S(encryption); +void M1Cartridge::Serialize(Serializer& ser) const +{ + ser << buffer; + ser << dict; + ser << hist; + ser << avail_val; + ser << rom_cur_address; + ser << buffer_actual_size; + ser << avail_bits; + ser << stream_ended; + ser << has_history; + ser << encryption; - NaomiCartridge::Serialize(data, total_size); + NaomiCartridge::Serialize(ser); } -void M1Cartridge::Unserialize(void** data, unsigned int* total_size) { - REICAST_US(buffer); - REICAST_US(dict); - REICAST_US(hist); - REICAST_US(avail_val); - REICAST_US(rom_cur_address); - REICAST_US(buffer_actual_size); - REICAST_US(avail_bits); - REICAST_US(stream_ended); - REICAST_US(has_history); - REICAST_US(encryption); +void M1Cartridge::Deserialize(Deserializer& deser) +{ + deser >> buffer; + deser >> dict; + deser >> hist; + deser >> avail_val; + deser >> rom_cur_address; + deser >> buffer_actual_size; + deser >> avail_bits; + deser >> stream_ended; + deser >> has_history; + deser >> encryption; - NaomiCartridge::Unserialize(data, total_size); + NaomiCartridge::Deserialize(deser); } diff --git a/core/hw/naomi/m1cartridge.h b/core/hw/naomi/m1cartridge.h index 9ca54a84f..f35497806 100644 --- a/core/hw/naomi/m1cartridge.h +++ b/core/hw/naomi/m1cartridge.h @@ -34,8 +34,8 @@ public: } void AdvancePtr(u32 size) override; - void Serialize(void** data, unsigned int* total_size) override; - void Unserialize(void** data, unsigned int* total_size) override; + void Serialize(Serializer& ser) const override; + void Deserialize(Deserializer& deser) override; void setActelId(u32 actel_id) { this->actel_id = actel_id; } diff --git a/core/hw/naomi/m4cartridge.cpp b/core/hw/naomi/m4cartridge.cpp index bd46fc73c..d548795d1 100644 --- a/core/hw/naomi/m4cartridge.cpp +++ b/core/hw/naomi/m4cartridge.cpp @@ -9,6 +9,7 @@ */ #include "m4cartridge.h" +#include "serialize.h" // Decoder for M4-type NAOMI cart encryption @@ -294,31 +295,30 @@ std::string M4Cartridge::GetGameId() return game_id; } -void M4Cartridge::Serialize(void** data, unsigned int* total_size) +void M4Cartridge::Serialize(Serializer& ser) const { - REICAST_S(buffer); - REICAST_S(rom_cur_address); - REICAST_S(buffer_actual_size); - REICAST_S(iv); - REICAST_S(counter); - REICAST_S(encryption); - REICAST_S(cfi_mode); - REICAST_S(xfer_ready); + ser << buffer; + ser << rom_cur_address; + ser << buffer_actual_size; + ser << iv; + ser << counter; + ser << encryption; + ser << cfi_mode; + ser << xfer_ready; - NaomiCartridge::Serialize(data, total_size); + NaomiCartridge::Serialize(ser); } -void M4Cartridge::Unserialize(void** data, unsigned int* total_size) +void M4Cartridge::Deserialize(Deserializer& deser) { - REICAST_US(buffer); - REICAST_US(rom_cur_address); - REICAST_US(buffer_actual_size); - REICAST_US(iv); - REICAST_US(counter); - REICAST_US(encryption); - REICAST_US(cfi_mode); - REICAST_US(xfer_ready); + deser >> buffer; + deser >> rom_cur_address; + deser >> buffer_actual_size; + deser >> iv; + deser >> counter; + deser >> encryption; + deser >> cfi_mode; + deser >> xfer_ready; - NaomiCartridge::Unserialize(data, total_size); + NaomiCartridge::Deserialize(deser); } - diff --git a/core/hw/naomi/m4cartridge.h b/core/hw/naomi/m4cartridge.h index 14b2d2bd6..b10ef69fd 100644 --- a/core/hw/naomi/m4cartridge.h +++ b/core/hw/naomi/m4cartridge.h @@ -45,8 +45,8 @@ public: void* GetDmaPtr(u32 &size) override; void AdvancePtr(u32 size) override; std::string GetGameId() override; - void Serialize(void** data, unsigned int* total_size) override; - void Unserialize(void** data, unsigned int* total_size) override; + void Serialize(Serializer& ser) const override; + void Deserialize(Deserializer& deser) override; void SetKey(u32 key) override { this->m4id = key; } void SetKeyData(u8 *key_data) override { this->m_key_data = key_data; } diff --git a/core/hw/naomi/naomi.cpp b/core/hw/naomi/naomi.cpp index 74bed2d4c..b53a892a1 100644 --- a/core/hw/naomi/naomi.cpp +++ b/core/hw/naomi/naomi.cpp @@ -15,6 +15,7 @@ #include "naomi_regs.h" #include "naomi_m3comm.h" #include "network/naomi_network.h" +#include "serialize.h" //#define NAOMI_COMM @@ -652,69 +653,73 @@ void libExtDevice_WriteMem_A0_006(u32 addr,u32 data,u32 size) { INFO_LOG(NAOMI, "Unhandled write @ %x (%d): %x", addr, size, data); } -void naomi_Serialize(void **data, unsigned int *total_size) +void naomi_Serialize(Serializer& ser) { - REICAST_S(GSerialBuffer); - REICAST_S(BSerialBuffer); - REICAST_S(GBufPos); - REICAST_S(BBufPos); - REICAST_S(GState); - REICAST_S(BState); - REICAST_S(GOldClk); - REICAST_S(BOldClk); - REICAST_S(BControl); - REICAST_S(BCmd); - REICAST_S(BLastCmd); - REICAST_S(GControl); - REICAST_S(GCmd); - REICAST_S(GLastCmd); - REICAST_S(SerStep); - REICAST_S(SerStep2); - REICAST_SA(BSerial,69); - REICAST_SA(GSerial,69); - REICAST_S(reg_dimm_command); - REICAST_S(reg_dimm_offsetl); - REICAST_S(reg_dimm_parameterl); - REICAST_S(reg_dimm_parameterh); - REICAST_S(reg_dimm_status); - REICAST_S(aw_maple_devs); - REICAST_S(coin_chute_time); - REICAST_S(aw_ram_test_skipped); + ser << GSerialBuffer; + ser << BSerialBuffer; + ser << GBufPos; + ser << BBufPos; + ser << GState; + ser << BState; + ser << GOldClk; + ser << BOldClk; + ser << BControl; + ser << BCmd; + ser << BLastCmd; + ser << GControl; + ser << GCmd; + ser << GLastCmd; + ser << SerStep; + ser << SerStep2; + ser.serialize(BSerial, 69); + ser.serialize(GSerial, 69); + ser << reg_dimm_command; + ser << reg_dimm_offsetl; + ser << reg_dimm_parameterl; + ser << reg_dimm_parameterh; + ser << reg_dimm_status; + ser << aw_maple_devs; + ser << coin_chute_time; + ser << aw_ram_test_skipped; // TODO serialize m3comm? } - -void naomi_Unserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void naomi_Deserialize(Deserializer& deser) { - REICAST_US(GSerialBuffer); - REICAST_US(BSerialBuffer); - REICAST_US(GBufPos); - REICAST_US(BBufPos); - REICAST_US(GState); - REICAST_US(BState); - REICAST_US(GOldClk); - REICAST_US(BOldClk); - REICAST_US(BControl); - REICAST_US(BCmd); - REICAST_US(BLastCmd); - REICAST_US(GControl); - REICAST_US(GCmd); - REICAST_US(GLastCmd); - REICAST_US(SerStep); - REICAST_US(SerStep2); - REICAST_USA(BSerial,69); - REICAST_USA(GSerial,69); - REICAST_US(reg_dimm_command); - REICAST_US(reg_dimm_offsetl); - REICAST_US(reg_dimm_parameterl); - REICAST_US(reg_dimm_parameterh); - REICAST_US(reg_dimm_status); - if (version < V11) - REICAST_SKIP(1); // NaomiDataRead - else if (version >= V14) - REICAST_US(aw_maple_devs); - if (version >= V20) + if (deser.version() < Deserializer::V9_LIBRETRO) { - REICAST_US(coin_chute_time); - REICAST_US(aw_ram_test_skipped); + deser.skip(); // naomi_updates + deser.skip(); // BoardID + } + deser >> GSerialBuffer; + deser >> BSerialBuffer; + deser >> GBufPos; + deser >> BBufPos; + deser >> GState; + deser >> BState; + deser >> GOldClk; + deser >> BOldClk; + deser >> BControl; + deser >> BCmd; + deser >> BLastCmd; + deser >> GControl; + deser >> GCmd; + deser >> GLastCmd; + deser >> SerStep; + deser >> SerStep2; + deser.deserialize(BSerial, 69); + deser.deserialize(GSerial, 69); + deser >> reg_dimm_command; + deser >> reg_dimm_offsetl; + deser >> reg_dimm_parameterl; + deser >> reg_dimm_parameterh; + deser >> reg_dimm_status; + if (deser.version() < Deserializer::V11) + deser.skip(); + else if (deser.version() >= Deserializer::V14) + deser >> aw_maple_devs; + if (deser.version() >= Deserializer::V20) + { + deser >> coin_chute_time; + deser >> aw_ram_test_skipped; } } diff --git a/core/hw/naomi/naomi.h b/core/hw/naomi/naomi.h index 9afebd785..cc7d2c076 100644 --- a/core/hw/naomi/naomi.h +++ b/core/hw/naomi/naomi.h @@ -1,14 +1,14 @@ /* ** naomi.h */ - #pragma once +#include "types.h" void naomi_reg_Init(); void naomi_reg_Term(); void naomi_reg_Reset(bool hard); -void naomi_Serialize(void **data, unsigned int *total_size); -void naomi_Unserialize(void **data, unsigned int *total_size, serialize_version_enum version); +void naomi_Serialize(Serializer& ser); +void naomi_Deserialize(Deserializer& deser); u32 ReadMem_naomi(u32 Addr, u32 size); void WriteMem_naomi(u32 Addr, u32 data, u32 size); diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp index 0e74de513..bc799ec2a 100644 --- a/core/hw/naomi/naomi_cart.cpp +++ b/core/hw/naomi/naomi_cart.cpp @@ -36,6 +36,7 @@ #include "emulator.h" #include "cfg/option.h" #include "oslib/oslib.h" +#include "serialize.h" Cartridge *CurrentCartridge; bool bios_loaded = false; @@ -857,22 +858,22 @@ void NaomiCartridge::WriteMem(u32 address, u32 data, u32 size) DEBUG_LOG(NAOMI, "naomi?WTF? WriteMem: %X <= %X, %d", address, data, size); } -void NaomiCartridge::Serialize(void** data, unsigned int* total_size) +void NaomiCartridge::Serialize(Serializer& ser) const { - REICAST_S(RomPioOffset); - REICAST_S(RomPioAutoIncrement); - REICAST_S(DmaOffset); - REICAST_S(DmaCount); - Cartridge::Serialize(data, total_size); + ser << RomPioOffset; + ser << RomPioAutoIncrement; + ser << DmaOffset; + ser << DmaCount; + Cartridge::Serialize(ser); } -void NaomiCartridge::Unserialize(void** data, unsigned int* total_size) +void NaomiCartridge::Deserialize(Deserializer& deser) { - REICAST_US(RomPioOffset); - REICAST_US(RomPioAutoIncrement); - REICAST_US(DmaOffset); - REICAST_US(DmaCount); - Cartridge::Unserialize(data, total_size); + deser >> RomPioOffset; + deser >> RomPioAutoIncrement; + deser >> DmaOffset; + deser >> DmaCount; + Cartridge::Deserialize(deser); } bool M2Cartridge::Read(u32 offset, u32 size, void* dst) @@ -962,12 +963,12 @@ std::string M2Cartridge::GetGameId() return game_id; } -void M2Cartridge::Serialize(void** data, unsigned int* total_size) { - REICAST_S(naomi_cart_ram); - NaomiCartridge::Serialize(data, total_size); +void M2Cartridge::Serialize(Serializer& ser) const { + ser << naomi_cart_ram; + NaomiCartridge::Serialize(ser); } -void M2Cartridge::Unserialize(void** data, unsigned int* total_size) { - REICAST_US(naomi_cart_ram); - NaomiCartridge::Unserialize(data, total_size); +void M2Cartridge::Deserialize(Deserializer& deser) { + deser >> naomi_cart_ram; + NaomiCartridge::Deserialize(deser); } diff --git a/core/hw/naomi/naomi_cart.h b/core/hw/naomi/naomi_cart.h index d07f803b8..ae5359cdf 100644 --- a/core/hw/naomi/naomi_cart.h +++ b/core/hw/naomi/naomi_cart.h @@ -24,8 +24,8 @@ public: virtual void* GetDmaPtr(u32 &size) = 0; virtual void AdvancePtr(u32 size) = 0; virtual std::string GetGameId(); - virtual void Serialize(void **data, unsigned int *total_size) {} - virtual void Unserialize(void **data, unsigned int *total_size) {} + virtual void Serialize(Serializer& ser) const {} + virtual void Deserialize(Deserializer& deser) {} virtual void SetKey(u32 key) { } virtual void SetKeyData(u8 *key_data) { } @@ -43,8 +43,8 @@ public: void WriteMem(u32 address, u32 data, u32 size) override; void* GetDmaPtr(u32 &size) override; void AdvancePtr(u32 size) override {} - void Serialize(void** data, unsigned int* total_size) override; - void Unserialize(void** data, unsigned int* total_size) override; + void Serialize(Serializer& ser) const override; + void Deserialize(Deserializer& deser) override; void SetKey(u32 key) override { this->key = key; } @@ -72,8 +72,8 @@ public: bool Read(u32 offset, u32 size, void* dst) override; bool Write(u32 offset, u32 size, u32 data) override; u16 ReadCipheredData(u32 offset); - void Serialize(void** data, unsigned int* total_size) override; - void Unserialize(void** data, unsigned int* total_size) override; + void Serialize(Serializer& ser) const override; + void Deserialize(Deserializer& deser) override; void* GetDmaPtr(u32& size) override; std::string GetGameId() override; diff --git a/core/hw/naomi/naomi_flashrom.cpp b/core/hw/naomi/naomi_flashrom.cpp index c159b6dbf..4431a7c40 100644 --- a/core/hw/naomi/naomi_flashrom.cpp +++ b/core/hw/naomi/naomi_flashrom.cpp @@ -101,7 +101,6 @@ void write_naomi_flash(u32 addr, u8 value) // void write_naomi_eeprom(u32 offset, u8 value) { - load_naomi_eeprom(); if (offset >= 3 && offset < 20) { EEPROM[offset] = value; diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index ad1ef9df9..7d3c127ff 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -7,6 +7,7 @@ #include "cfg/option.h" #include "network/ggpo.h" #include "emulator.h" +#include "serialize.h" #include #include @@ -37,7 +38,7 @@ u32 fb_watch_addr_start; u32 fb_watch_addr_end; bool fb_dirty; -bool pend_rend = false; +static bool pend_rend; TA_context* _pvrrc; @@ -470,28 +471,28 @@ void rend_start_rollback() vramRollback.Wait(); } -void rend_serialize(void **data, unsigned int *total_size) +void rend_serialize(Serializer& ser) { - REICAST_S(fb_w_cur); - REICAST_S(render_called); - REICAST_S(fb_dirty); - REICAST_S(fb_watch_addr_start); - REICAST_S(fb_watch_addr_end); + ser << fb_w_cur; + ser << render_called; + ser << fb_dirty; + ser << fb_watch_addr_start; + ser << fb_watch_addr_end; } - -void rend_deserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void rend_deserialize(Deserializer& deser) { - if ((version >= V12_LIBRETRO && version < V5) || version >= V12) - REICAST_US(fb_w_cur); + if ((deser.version() >= Deserializer::V12_LIBRETRO && deser.version() < Deserializer::V5) || deser.version() >= Deserializer::V12) + deser >> fb_w_cur; else fb_w_cur = 1; - if (version >= V20) + if (deser.version() >= Deserializer::V20) { - REICAST_US(render_called); - REICAST_US(fb_dirty); - REICAST_US(fb_watch_addr_start); - REICAST_US(fb_watch_addr_end); + deser >> render_called; + deser >> fb_dirty; + deser >> fb_watch_addr_start; + deser >> fb_watch_addr_end; } + pend_rend = false; } void rend_resize_renderer() diff --git a/core/hw/pvr/Renderer_if.h b/core/hw/pvr/Renderer_if.h index a8ffcd964..11f898bf1 100644 --- a/core/hw/pvr/Renderer_if.h +++ b/core/hw/pvr/Renderer_if.h @@ -18,8 +18,8 @@ void rend_reset(); void rend_disable_rollback(); void rend_start_rollback(); void rend_allow_rollback(); -void rend_serialize(void **data, unsigned int *total_size); -void rend_deserialize(void **data, unsigned int *total_size, serialize_version_enum version); +void rend_serialize(Serializer& ser); +void rend_deserialize(Deserializer& deser); void rend_resize_renderer(); /////// diff --git a/core/hw/pvr/drkPvr.cpp b/core/hw/pvr/drkPvr.cpp deleted file mode 100644 index 0bcf05184..000000000 --- a/core/hw/pvr/drkPvr.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// drkPvr.cpp : Defines the entry point for the DLL application. -// - -/* - Plugin structure - Interface - SPG - TA - Renderer -*/ - -#include "spg.h" -#include "pvr_regs.h" -#include "Renderer_if.h" -#include "ta_ctx.h" -#include "rend/TexCache.h" - -void libPvr_Reset(bool hard) -{ - KillTex = true; - Regs_Reset(hard); - spg_Reset(hard); - if (hard) - rend_reset(); - tactx_Term(); -} - -s32 libPvr_Init() -{ - if (!spg_Init()) - { - //failed - return -1; - } - - return 0; -} - -//called when exiting from sh4 thread , from the new thread context (for any thread specific de init) :P -void libPvr_Term() -{ - tactx_Term(); - spg_Term(); -} diff --git a/core/hw/pvr/pvr.cpp b/core/hw/pvr/pvr.cpp new file mode 100644 index 000000000..ed2d545c6 --- /dev/null +++ b/core/hw/pvr/pvr.cpp @@ -0,0 +1,141 @@ +/* + Copyright 2021 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . + */ +#include "pvr.h" +#include "spg.h" +#include "pvr_regs.h" +#include "Renderer_if.h" +#include "ta_ctx.h" +#include "rend/TexCache.h" +#include "serialize.h" +#include "pvr_mem.h" + +// ta.cpp +extern u8 ta_fsm[2049]; //[2048] stores the current state +extern u32 ta_fsm_cl; +// pvr_regs.cpp +extern bool fog_needs_update; +extern bool pal_needs_update; + +namespace pvr +{ + +void reset(bool hard) +{ + KillTex = true; + Regs_Reset(hard); + spg_Reset(hard); + if (hard) + rend_reset(); + tactx_Term(); +} + +void init() +{ + spg_Init(); +} + +void term() +{ + tactx_Term(); + spg_Term(); +} + +void serialize(Serializer& ser) +{ + YUV_serialize(ser); + + ser << pvr_regs; + + spg_Serialize(ser); + rend_serialize(ser); + + ser << ta_fsm[2048]; + ser << ta_fsm_cl; + + SerializeTAContext(ser); + + if (!ser.rollback()) + ser.serialize(vram.data, vram.size); +} + +void deserialize(Deserializer& deser) +{ + if (deser.version() < Deserializer::V9_LIBRETRO) + { + deser.skip(); // FrameCount + deser.skip(); // pend_rend + } + + YUV_deserialize(deser); + + if (deser.version() >= Deserializer::V5_LIBRETRO && deser.version() < Deserializer::V9_LIBRETRO) + deser.skip(); // fog_needs_update + deser >> pvr_regs; + fog_needs_update = true; + + spg_Deserialize(deser); + + if (deser.version() < Deserializer::V9_LIBRETRO) + { + deser.skip(4 * 256); // ta_type_lut + deser.skip(2048); // ta_fsm + } + rend_deserialize(deser); + + deser >> ta_fsm[2048]; + deser >> ta_fsm_cl; + if (deser.version() >= Deserializer::V5_LIBRETRO && deser.version() < Deserializer::V9_LIBRETRO) + { + deser.skip(); // pal_needs_update + deser.skip(4 * 4); // _pal_rev_256 + deser.skip(4 * 64); // _pal_rev_16 + deser.skip(4 * 4); // pal_rev_256 + deser.skip(4 * 64); // pal_rev_16 + deser.skip(4 * 65536 * 3); // decoded_colors + deser.skip(4); // tileclip_val + deser.skip(65536); // f32_su8_tbl + deser.skip(4); // FaceBaseColor + deser.skip(4); // FaceOffsColor + deser.skip(4); // SFaceBaseColor + deser.skip(4); // SFaceOffsColor + + deser.skip(4); // palette_index + deser.skip(); // KillTex + deser.skip(4 * 1024); // palette16_ram + deser.skip(4 * 1024); // palette32_ram + deser.skip(4 * 1024 * 8 * 2); // detwiddle + } + else if (deser.version() <= Deserializer::V4) + { + deser.skip(4); + deser.skip(65536); + deser.skip(4); + deser.skip(4); + deser.skip(4); + deser.skip(4); + } + if (deser.version() >= Deserializer::V11 || (deser.version() >= Deserializer::V10_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO)) + DeserializeTAContext(deser); + + if (!deser.rollback()) + deser.deserialize(vram.data, vram.size); + pal_needs_update = true; +} + +} diff --git a/core/hw/pvr/pvr.h b/core/hw/pvr/pvr.h new file mode 100644 index 000000000..777d7d752 --- /dev/null +++ b/core/hw/pvr/pvr.h @@ -0,0 +1,32 @@ +/* + Copyright 2021 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . + */ +#pragma once +#include "types.h" + +namespace pvr +{ + +void init(); +void term(); +void reset(bool hard); + +void serialize(Serializer& ser); +void deserialize(Deserializer& deser); + +} diff --git a/core/hw/pvr/pvr_mem.cpp b/core/hw/pvr/pvr_mem.cpp index fbdc882ab..26ee43cb2 100644 --- a/core/hw/pvr/pvr_mem.cpp +++ b/core/hw/pvr/pvr_mem.cpp @@ -9,6 +9,7 @@ #include "ta.h" #include "hw/holly/sb.h" #include "hw/holly/holly_intc.h" +#include "serialize.h" static u32 pvr_map32(u32 offset32); @@ -172,29 +173,28 @@ static void YUV_data(const SQBuffer *data, u32 count) verify(count==0); } -void YUV_serialize(void **data, unsigned int *total_size) +void YUV_serialize(Serializer& ser) { - REICAST_S(YUV_tempdata); - REICAST_S(YUV_dest); - REICAST_S(YUV_blockcount); - REICAST_S(YUV_x_curr); - REICAST_S(YUV_y_curr); - REICAST_S(YUV_x_size); - REICAST_S(YUV_y_size); - REICAST_S(YUV_index); + ser << YUV_tempdata; + ser << YUV_dest; + ser << YUV_blockcount; + ser << YUV_x_curr; + ser << YUV_y_curr; + ser << YUV_x_size; + ser << YUV_y_size; + ser << YUV_index; } - -void YUV_unserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void YUV_deserialize(Deserializer& deser) { - REICAST_US(YUV_tempdata); - REICAST_US(YUV_dest); - REICAST_US(YUV_blockcount); - REICAST_US(YUV_x_curr); - REICAST_US(YUV_y_curr); - REICAST_US(YUV_x_size); - REICAST_US(YUV_y_size); - if (version >= V16) - REICAST_US(YUV_index); + deser >> YUV_tempdata; + deser >> YUV_dest; + deser >> YUV_blockcount; + deser >> YUV_x_curr; + deser >> YUV_y_curr; + deser >> YUV_x_size; + deser >> YUV_y_size; + if (deser.version() >= Deserializer::V16) + deser >> YUV_index; else YUV_index = 0; } diff --git a/core/hw/pvr/pvr_mem.h b/core/hw/pvr/pvr_mem.h index b3a7b29e1..914f45f6b 100644 --- a/core/hw/pvr/pvr_mem.h +++ b/core/hw/pvr/pvr_mem.h @@ -14,8 +14,8 @@ void DYNACALL TAWrite(u32 address, const SQBuffer *data, u32 count); void DYNACALL TAWriteSQ(u32 address, const SQBuffer *sqb); void YUV_init(); -void YUV_serialize(void **data, unsigned int *total_size); -void YUV_unserialize(void **data, unsigned int *total_size, serialize_version_enum version); +void YUV_serialize(Serializer& ser); +void YUV_deserialize(Deserializer& deser); // 32-bit vram path handlers template T DYNACALL pvr_read32p(u32 addr); diff --git a/core/hw/pvr/spg.cpp b/core/hw/pvr/spg.cpp index c812da047..b185706b8 100755 --- a/core/hw/pvr/spg.cpp +++ b/core/hw/pvr/spg.cpp @@ -6,6 +6,8 @@ #include "input/gamepad_device.h" #include "oslib/oslib.h" #include "rend/TexCache.h" +#include "hw/maple/maple_if.h" +#include "serialize.h" //SPG emulation; Scanline/Raster beam registers & interrupts @@ -104,7 +106,10 @@ int spg_line_sched(int tag, int cycl, int jit) } if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline) + { + maple_vblank(); asic_RaiseInterrupt(holly_SCANINT2); + } if (SPG_VBLANK.vstart == prv_cur_scanline) in_vblank=1; @@ -318,51 +323,49 @@ void SetREP(TA_context* cntx) sh4_sched_request(render_end_schid, 4096); } -void spg_Serialize(void **data, unsigned int *total_size) +void spg_Serialize(Serializer& ser) { - REICAST_S(in_vblank); - REICAST_S(clc_pvr_scanline); - REICAST_S(maple_int_pending); - REICAST_S(pvr_numscanlines); - REICAST_S(prv_cur_scanline); - REICAST_S(Line_Cycles); - REICAST_S(Frame_Cycles); - REICAST_S(lightgun_line); - REICAST_S(lightgun_hpos); + ser << in_vblank; + ser << clc_pvr_scanline; + ser << maple_int_pending; + ser << pvr_numscanlines; + ser << prv_cur_scanline; + ser << Line_Cycles; + ser << Frame_Cycles; + ser << lightgun_line; + ser << lightgun_hpos; } - -void spg_Unserialize(void **data, unsigned int *total_size, serialize_version_enum version) +void spg_Deserialize(Deserializer& deser) { - REICAST_US(in_vblank); - REICAST_US(clc_pvr_scanline); - if (version < V9_LIBRETRO) + deser >> in_vblank; + deser >> clc_pvr_scanline; + if (deser.version() < Deserializer::V9_LIBRETRO) { - u32 i; - REICAST_US(pvr_numscanlines); - REICAST_US(prv_cur_scanline); - REICAST_US(vblk_cnt); - REICAST_US(Line_Cycles); - REICAST_US(Frame_Cycles); - REICAST_SKIP(8); // speed_load_mspdf - REICAST_US(i); // mips_counter - REICAST_SKIP(8); // full_rps - if (version <= V4) - REICAST_US(i); // fskip + deser >> pvr_numscanlines; + deser >> prv_cur_scanline; + deser >> vblk_cnt; + deser >> Line_Cycles; + deser >> Frame_Cycles; + deser.skip(); // speed_load_mspdf + deser.skip(); // mips_counter + deser.skip(); // full_rps + if (deser.version() <= Deserializer::V4) + deser.skip(); // fskip } - else if (version >= V12) + else if (deser.version() >= Deserializer::V12) { - REICAST_US(maple_int_pending); - if (version >= V14) + deser >> maple_int_pending; + if (deser.version() >= Deserializer::V14) { - REICAST_US(pvr_numscanlines); - REICAST_US(prv_cur_scanline); - REICAST_US(Line_Cycles); - REICAST_US(Frame_Cycles); - REICAST_US(lightgun_line); - REICAST_US(lightgun_hpos); + deser >> pvr_numscanlines; + deser >> prv_cur_scanline; + deser >> Line_Cycles; + deser >> Frame_Cycles; + deser >> lightgun_line; + deser >> lightgun_hpos; } } - if (version < V14) + if (deser.version() < Deserializer::V14) CalculateSync(); else setFramebufferScaling(); diff --git a/core/hw/pvr/spg.h b/core/hw/pvr/spg.h index f2e11d8b2..66f9cba7c 100644 --- a/core/hw/pvr/spg.h +++ b/core/hw/pvr/spg.h @@ -6,8 +6,8 @@ extern bool SH4FastEnough; bool spg_Init(); void spg_Term(); void spg_Reset(bool Manual); -void spg_Serialize(void **data, unsigned int *total_size); -void spg_Unserialize(void **data, unsigned int *total_size, serialize_version_enum version); +void spg_Serialize(Serializer& ser); +void spg_Deserialize(Deserializer& deser); void CalculateSync(); void read_lightgun_position(int x, int y); diff --git a/core/hw/pvr/ta_ctx.cpp b/core/hw/pvr/ta_ctx.cpp index 90256e88d..b1c681568 100644 --- a/core/hw/pvr/ta_ctx.cpp +++ b/core/hw/pvr/ta_ctx.cpp @@ -2,6 +2,7 @@ #include "spg.h" #include "cfg/option.h" #include "Renderer_if.h" +#include "serialize.h" extern u32 fskip; extern u32 FrameCount; @@ -207,36 +208,36 @@ void tactx_Term() const u32 NULL_CONTEXT = ~0u; -static void serializeContext(void **data, unsigned int *total_size, const TA_context *ctx) +static void serializeContext(Serializer& ser, const TA_context *ctx) { + if (ser.dryrun()) + { + // Maximum size: address, size, data, render pass count, render passes + ser.skip(4 + 4 + TA_DATA_SIZE + 4 + ARRAY_SIZE(tad_context::render_passes) * 4); + return; + } if (ctx == nullptr) { - REICAST_S(NULL_CONTEXT); + ser << NULL_CONTEXT; return; } - REICAST_S(ctx->Address); + ser << ctx->Address; const tad_context& tad = ctx == ::ta_ctx ? ta_tad : ctx->tad; const u32 taSize = tad.thd_data - tad.thd_root; - REICAST_S(taSize); - if (*data == nullptr) - { - // Maximum size - REICAST_SKIP(TA_DATA_SIZE + 4 + ARRAY_SIZE(tad.render_passes) * 4); - return; - } - REICAST_SA(tad.thd_root, taSize); - REICAST_S(tad.render_pass_count); + ser << taSize; + ser.serialize(tad.thd_root, taSize); + ser << tad.render_pass_count; for (u32 i = 0; i < tad.render_pass_count; i++) { u32 offset = (u32)(tad.render_passes[i] - tad.thd_root); - REICAST_S(offset); + ser << offset; } } -static void deserializeContext(void **data, unsigned int *total_size, serialize_version_enum version, TA_context **pctx) +static void deserializeContext(Deserializer& deser, TA_context **pctx) { u32 address; - REICAST_US(address); + deser >> address; if (address == NULL_CONTEXT) { *pctx = nullptr; @@ -244,17 +245,17 @@ static void deserializeContext(void **data, unsigned int *total_size, serialize_ } *pctx = tactx_Find(address, true); u32 size; - REICAST_US(size); + deser >> size; tad_context& tad = (*pctx)->tad; - REICAST_USA(tad.thd_root, size); + deser.deserialize(tad.thd_root, size); tad.thd_data = tad.thd_root + size; - if (version >= V12 || (version >= V12_LIBRETRO && version < V5)) + if (deser.version() >= Deserializer::V12 || (deser.version() >= Deserializer::V12_LIBRETRO && deser.version() < Deserializer::V5)) { - REICAST_US(tad.render_pass_count); + deser >> tad.render_pass_count; for (u32 i = 0; i < tad.render_pass_count; i++) { u32 offset; - REICAST_US(offset); + deser >> offset; tad.render_passes[i] = tad.thd_root + offset; } } @@ -264,23 +265,23 @@ static void deserializeContext(void **data, unsigned int *total_size, serialize_ } } -void SerializeTAContext(void **data, unsigned int *total_size) +void SerializeTAContext(Serializer& ser) { - serializeContext(data, total_size, ta_ctx); + serializeContext(ser, ta_ctx); if (TA_CURRENT_CTX != CORE_CURRENT_CTX) - serializeContext(data, total_size, tactx_Find(TA_CURRENT_CTX, false)); + serializeContext(ser, tactx_Find(TA_CURRENT_CTX, false)); else - serializeContext(data, total_size, nullptr); -} + serializeContext(ser, nullptr); -void UnserializeTAContext(void **data, unsigned int *total_size, serialize_version_enum version) +} +void DeserializeTAContext(Deserializer& deser) { if (::ta_ctx != nullptr) SetCurrentTARC(TACTX_NONE); TA_context *ta_cur_ctx; - deserializeContext(data, total_size, version, &ta_cur_ctx); + deserializeContext(deser, &ta_cur_ctx); if (ta_cur_ctx != nullptr) SetCurrentTARC(ta_cur_ctx->Address); - if (version >= V20) - deserializeContext(data, total_size, version, &ta_cur_ctx); + if (deser.version() >= Deserializer::V20) + deserializeContext(deser, &ta_cur_ctx); } diff --git a/core/hw/pvr/ta_ctx.h b/core/hw/pvr/ta_ctx.h index 7de03380f..a3ea8d0aa 100644 --- a/core/hw/pvr/ta_ctx.h +++ b/core/hw/pvr/ta_ctx.h @@ -276,5 +276,5 @@ void FinishRender(TA_context* ctx); void FillBGP(TA_context* ctx); bool UsingAutoSort(int pass_number); bool rend_framePending(); -void SerializeTAContext(void **data, unsigned int *total_size); -void UnserializeTAContext(void **data, unsigned int *total_size, serialize_version_enum version); +void SerializeTAContext(Serializer& ser); +void DeserializeTAContext(Deserializer& deser); diff --git a/core/hw/sh4/modules/mmu.cpp b/core/hw/sh4/modules/mmu.cpp index 038bd75f7..b592dfcb1 100644 --- a/core/hw/sh4/modules/mmu.cpp +++ b/core/hw/sh4/modules/mmu.cpp @@ -6,7 +6,7 @@ TLB_Entry UTLB[64]; TLB_Entry ITLB[4]; -u32 ITLB_LRU_USE[64]; +static u32 ITLB_LRU_USE[64]; //SQ fast remap , mainly hackish , assumes 1MB pages //max 64MB can be remapped on SQ diff --git a/core/hw/sh4/sh4_cache.h b/core/hw/sh4/sh4_cache.h index 6dcb67a49..ca3ea93e5 100644 --- a/core/hw/sh4/sh4_cache.h +++ b/core/hw/sh4/sh4_cache.h @@ -22,6 +22,7 @@ #include "sh4_mem.h" #include "modules/mmu.h" #include "hw/sh4/sh4_core.h" +#include "serialize.h" static bool cachedArea(u32 area) { @@ -101,18 +102,11 @@ public: memset(&lines[0], 0, sizeof(lines)); } - bool Serialize(void **data, unsigned int *total_size) - { - REICAST_S(lines); - - return true; + void Serialize(Serializer& ser) { + ser << lines; } - - bool Unserialize(void **data, unsigned int *total_size) - { - REICAST_US(lines); - - return true; + void Deserialize(Deserializer& deser) { + deser >> lines; } u32 ReadAddressArray(u32 addr) @@ -373,18 +367,11 @@ public: memset(&lines[0], 0, sizeof(lines)); } - bool Serialize(void **data, unsigned int *total_size) - { - REICAST_S(lines); - - return true; + void Serialize(Serializer& ser) { + ser << lines; } - - bool Unserialize(void **data, unsigned int *total_size) - { - REICAST_US(lines); - - return true; + void Deserialize(Deserializer& deser) { + deser >> lines; } u32 ReadAddressArray(u32 addr) diff --git a/core/network/ggpo.cpp b/core/network/ggpo.cpp index 9c6700217..3dc20c71f 100644 --- a/core/network/ggpo.cpp +++ b/core/network/ggpo.cpp @@ -272,15 +272,14 @@ static bool load_game_state(unsigned char *buffer, int len) INFO_LOG(NETWORK, "load_game_state"); rend_start_rollback(); - // FIXME will invalidate too much stuff: palette/fog textures, maple stuff // FIXME dynarecs - int frame = *(u32 *)buffer; - unsigned usedLen = sizeof(u32); - buffer += usedLen; - dc_unserialize((void **)&buffer, &usedLen, true); - if (len != (int)usedLen) + Deserializer deser(buffer, len, true); + int frame; + deser >> frame; + dc_deserialize(deser); + if (deser.size() != (u32)len) { - ERROR_LOG(NETWORK, "load_game_state len %d used %d", len, usedLen); + ERROR_LOG(NETWORK, "load_game_state len %d used %d", len, (int)deser.size()); die("fatal"); } for (int f = lastSavedFrame - 1; f >= frame; f--) @@ -319,13 +318,11 @@ static bool save_game_state(unsigned char **buffer, int *len, int *checksum, int *len = 0; return false; } - u8 *data = *buffer; - *(u32 *)data = frame; - unsigned usedSize = sizeof(frame); - data += usedSize; - dc_serialize((void **)&data, &usedSize, true); - verify(usedSize < allocSize); - *len = usedSize; + Serializer ser(*buffer, allocSize, true); + ser << frame; + dc_serialize(ser); + verify(ser.size() < allocSize); + *len = ser.size(); #ifdef SYNC_TEST *checksum = XXH32(*buffer, usedSize, 7); #endif diff --git a/core/nullDC.cpp b/core/nullDC.cpp index c428ff4cf..fc173c92f 100644 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -13,6 +13,7 @@ #include "input/gamepad_device.h" #include "lua/lua.h" #include "stdclass.h" +#include "serialize.h" int flycast_init(int argc, char* argv[]) { @@ -79,33 +80,19 @@ void flycast_term() void dc_savestate(int index) { - unsigned int total_size = 0; - void *data = nullptr; + Serializer ser; + dc_serialize(ser); - if (!dc_serialize(&data, &total_size)) - { - WARN_LOG(SAVESTATE, "Failed to save state - could not initialize total size") ; - gui_display_notification("Save state failed", 2000); - return; - } - - data = malloc(total_size); + void *data = malloc(ser.size()); if (data == nullptr) { - WARN_LOG(SAVESTATE, "Failed to save state - could not malloc %d bytes", total_size); + WARN_LOG(SAVESTATE, "Failed to save state - could not malloc %d bytes", (int)ser.size()); gui_display_notification("Save state failed - memory full", 2000); return; } - void *data_ptr = data; - total_size = 0; - if (!dc_serialize(&data_ptr, &total_size)) - { - WARN_LOG(SAVESTATE, "Failed to save state - could not serialize data") ; - gui_display_notification("Save state failed", 2000); - free(data); - return; - } + ser = Serializer(data, ser.size()); + dc_serialize(ser); std::string filename = hostfs::getSavestatePath(index, true); #if 0 @@ -119,7 +106,7 @@ void dc_savestate(int index) return; } - std::fwrite(data, 1, total_size, f) ; + std::fwrite(data, 1, ser.size(), f) ; std::fclose(f); #else RZipFile zipFile; @@ -130,7 +117,7 @@ void dc_savestate(int index) free(data); return; } - if (zipFile.Write(data, total_size) != total_size) + if (zipFile.Write(data, ser.size()) != ser.size()) { WARN_LOG(SAVESTATE, "Failed to save state - error writing %s", filename.c_str()); gui_display_notification("Error saving state", 2000); @@ -142,7 +129,7 @@ void dc_savestate(int index) #endif free(data); - INFO_LOG(SAVESTATE, "Saved state to %s size %d", filename.c_str(), total_size) ; + INFO_LOG(SAVESTATE, "Saved state to %s size %d", filename.c_str(), (int)ser.size()) ; gui_display_notification("State saved", 1000); } @@ -216,8 +203,14 @@ void dc_loadstate(int index) return; } - const void *data_ptr = data; - dc_loadstate(&data_ptr, total_size); + try { + Deserializer deser(data, total_size); + dc_loadstate(deser); + if (deser.size() != total_size) + WARN_LOG(SAVESTATE, "Savestate size %d but only %d bytes used", total_size, (int)deser.size()); + } catch (const Deserializer::Exception& e) { + ERROR_LOG(SAVESTATE, "%s", e.what()); + } free(data); EventManager::event(Event::LoadState); diff --git a/core/reios/gdrom_hle.h b/core/reios/gdrom_hle.h index 94f61876d..01cf0a03e 100644 --- a/core/reios/gdrom_hle.h +++ b/core/reios/gdrom_hle.h @@ -1,4 +1,5 @@ #pragma once +#include "serialize.h" #define SYSCALL_GDROM 0x00 @@ -44,6 +45,8 @@ #define MISC_INIT 0x00 #define MISC_SETVECTOR 0x01 +void gdrom_hle_init(); +void gdrom_hle_term(); void gdrom_hle_op(); typedef enum { BIOS_ERROR = -1, BIOS_INACTIVE, BIOS_ACTIVE, BIOS_COMPLETED, BIOS_DATA_AVAIL } gd_bios_status; @@ -67,45 +70,42 @@ struct gdrom_hle_state_t bool dma_trans_ended = false; u64 xfer_end_time = 0; - bool Serialize(void **data, unsigned int *total_size) + void Serialize(Serializer& ser) { - REICAST_S(last_request_id); - REICAST_S(next_request_id); - REICAST_S(status); - REICAST_S(command); - REICAST_S(params); - REICAST_S(result); - REICAST_S(cur_sector); - REICAST_S(multi_read_sector); - REICAST_S(multi_read_offset); - REICAST_S(multi_read_count); - REICAST_S(multi_read_total); - REICAST_S(multi_callback); - REICAST_S(multi_callback_arg); - REICAST_S(dma_trans_ended); - REICAST_S(xfer_end_time); - - return true; + ser << last_request_id; + ser << next_request_id; + ser << status; + ser << command; + ser << params; + ser << result; + ser << cur_sector; + ser << multi_read_sector; + ser << multi_read_offset; + ser << multi_read_count; + ser << multi_read_total; + ser << multi_callback; + ser << multi_callback_arg; + ser << dma_trans_ended; + ser << xfer_end_time; + } - bool Unserialize(void **data, unsigned int *total_size) + void Deserialize(Deserializer& deser) { - REICAST_US(last_request_id); - REICAST_US(next_request_id); - REICAST_US(status); - REICAST_US(command); - REICAST_US(params); - REICAST_US(result); - REICAST_US(cur_sector); - REICAST_US(multi_read_sector); - REICAST_US(multi_read_offset); - REICAST_US(multi_read_count); - REICAST_US(multi_read_total); - REICAST_US(multi_callback); - REICAST_US(multi_callback_arg); - REICAST_US(dma_trans_ended); - REICAST_US(xfer_end_time); - - return true; + deser >> last_request_id; + deser >> next_request_id; + deser >> status; + deser >> command; + deser >> params; + deser >> result; + deser >> cur_sector; + deser >> multi_read_sector; + deser >> multi_read_offset; + deser >> multi_read_count; + deser >> multi_read_total; + deser >> multi_callback; + deser >> multi_callback_arg; + deser >> dma_trans_ended; + deser >> xfer_end_time; } }; extern gdrom_hle_state_t gd_hle_state; diff --git a/core/serialize.cpp b/core/serialize.cpp index d71340363..4bfa92bdf 100644 --- a/core/serialize.cpp +++ b/core/serialize.cpp @@ -1,4 +1,5 @@ // serialize.cpp : save states +#include "serialize.h" #include "types.h" #include "hw/aica/dsp.h" #include "hw/aica/aica.h" @@ -6,13 +7,11 @@ #include "hw/arm7/arm7.h" #include "hw/holly/sb.h" #include "hw/flashrom/flashrom.h" -#include "hw/gdrom/gdromv3.h" #include "hw/gdrom/gdrom_if.h" #include "hw/maple/maple_cfg.h" #include "hw/modem/modem.h" -#include "hw/pvr/Renderer_if.h" +#include "hw/pvr/pvr.h" #include "hw/pvr/pvr_mem.h" -#include "hw/pvr/spg.h" #include "hw/sh4/sh4_sched.h" #include "hw/sh4/sh4_mmr.h" #include "hw/sh4/modules/mmu.h" @@ -53,16 +52,6 @@ extern u32 SB_ADST; //./core/hw/aica/aica_mem.o extern u8 aica_reg[0x8000]; -//./core/hw/aica/sgc_if.o -struct ChannelEx; -#define AicaChannel ChannelEx - -//special handling -#define Chans AicaChannel::Chans -#define CDDA_SIZE (2352/2) -extern s16 cdda_sector[CDDA_SIZE]; -extern u32 cdda_index; - //./core/hw/holly/sb.o extern u32 SB_FFST_rc; extern u32 SB_FFST; @@ -73,63 +62,17 @@ extern WritableChip *sys_nvmem; //./core/hw/gdrom/gdromv3.o extern int gdrom_schid; -extern packet_cmd_t packet_cmd; -extern u32 set_mode_offset; -extern read_params_t read_params ; -extern packet_cmd_t packet_cmd; -//Buffer for sector reads [dma] -extern read_buff_t read_buff ; -//pio buffer -extern pio_buff_t pio_buff ; -extern u32 set_mode_offset; -extern ata_cmd_t ata_cmd ; -extern cdda_t cdda ; -extern gd_states gd_state; -extern DiscType gd_disk_type; -extern u32 data_write_mode; -//Registers -extern u32 DriveSel; -extern GD_ErrRegT Error; -extern GD_InterruptReasonT IntReason; -extern GD_FeaturesT Features; -extern GD_SecCountT SecCount; -extern GD_SecNumbT SecNumber; -extern GD_StatusT GDStatus; -extern ByteCount_t ByteCount ; - -//./core/hw/maple/maple_devs.o -extern u8 EEPROM[0x100]; -extern bool EEPROM_loaded; //./core/hw/maple/maple_if.o extern int maple_schid; -extern bool maple_ddt_pending_reset; //./core/hw/modem/modem.cpp extern int modem_sched; -//./core/hw/pvr/Renderer_if.o -extern bool pend_rend; -extern u32 fb_w_cur; - -//./core/hw/pvr/pvr_regs.o -extern bool fog_needs_update; -extern u8 pvr_regs[pvr_RegSize]; - //./core/hw/pvr/spg.o extern int render_end_schid; extern int vblank_schid; -//./core/hw/pvr/ta.o -extern u8 ta_fsm[2049]; //[2048] stores the current state -extern u32 ta_fsm_cl; - -//./core/hw/pvr/ta_vtx.o -extern bool pal_needs_update; - -//./core/rend/TexCache.o -extern VArray2 vram; - //./core/hw/sh4/sh4_mmr.o extern std::array OnChipRAM; @@ -179,60 +122,29 @@ extern u32 CCN_QACR_TR[2]; extern TLB_Entry UTLB[64]; extern TLB_Entry ITLB[4]; extern u32 sq_remap[64]; -static u32 ITLB_LRU_USE[64]; //./core/imgread/common.o extern u32 NullDriveDiscType; extern u8 q_subchannel[96]; -bool rc_serialize(const void *src, unsigned int src_size, void **dest, unsigned int *total_size) -{ - if ( *dest != NULL ) - { - memcpy(*dest, src, src_size) ; - *dest = ((unsigned char*)*dest) + src_size ; - } - - *total_size += src_size ; - return true ; -} - -bool rc_unserialize(void *src, unsigned int src_size, void **dest, unsigned int *total_size) -{ - if ( *dest != NULL ) - { - memcpy(src, *dest, src_size) ; - *dest = ((unsigned char*)*dest) + src_size ; - } - - *total_size += src_size ; - return true ; -} - template -bool register_serialize(const T& regs,void **data, unsigned int *total_size ) +void register_serialize(const T& regs, Serializer& ser) { for (const auto& reg : regs) - REICAST_S(reg.data32); - - return true; + ser << reg.data32; } - template -bool register_unserialize(T& regs,void **data, unsigned int *total_size, serialize_version_enum version) +void register_deserialize(T& regs, Deserializer& deser) { - u32 dummy = 0; - for (auto& reg : regs) { - if (version < V5) - REICAST_US(dummy); // regs.data[i].flags + if (deser.version() < Deserializer::V5) + deser.skip(); // regs.data[i].flags if (!(reg.flags & REG_RF)) - REICAST_US(reg.data32); + deser >> reg.data32; else - REICAST_US(dummy); + deser.skip(); } - return true; } static const std::array getSchedulerIds() { @@ -241,952 +153,665 @@ static const std::array getSchedulerIds() { modem_sched }; } -bool dc_serialize(void **data, unsigned int *total_size, bool rollback) +void dc_serialize(Serializer& ser) { - int i = 0; + ser << aica_interr; + ser << aica_reg_L; + ser << e68k_out; + ser << e68k_reg_L; + ser << e68k_reg_M; - serialize_version_enum version = VCUR_FLYCAST; + ser.serialize(arm_Reg, RN_ARM_REG_COUNT - 1); // Too lazy to create a new version and the scratch register is not used between blocks anyway + ser << armIrqEnable; + ser << armFiqEnable; + ser << armMode; + ser << Arm7Enabled; + ser << arm7ClockTicks; - //dc not initialized yet - if ( p_sh4rcb == NULL ) - return false ; + dsp::state.serialize(ser); - REICAST_S(version) ; - REICAST_S(aica_interr) ; - REICAST_S(aica_reg_L) ; - REICAST_S(e68k_out) ; - REICAST_S(e68k_reg_L) ; - REICAST_S(e68k_reg_M) ; - - REICAST_SA(arm_Reg,RN_ARM_REG_COUNT - 1); // Too lazy to create a new version and the scratch register is not used between blocks anyway - REICAST_S(armIrqEnable); - REICAST_S(armFiqEnable); - REICAST_S(armMode); - REICAST_S(Arm7Enabled); - REICAST_S(arm7ClockTicks); - - dsp::state.serialize(data, total_size); - - for ( i = 0 ; i < 3 ; i++) + for (int i = 0 ; i < 3 ; i++) { - REICAST_S(timers[i].c_step); - REICAST_S(timers[i].m_step); + ser << timers[i].c_step; + ser << timers[i].m_step; } - if (!rollback) - REICAST_SA(aica_ram.data,aica_ram.size) ; - REICAST_S(VREG); - REICAST_S(ARMRST); - REICAST_S(rtc_EN); - REICAST_S(RealTimeClock); + if (!ser.rollback()) + ser.serialize(aica_ram.data, aica_ram.size); + ser << VREG; + ser << ARMRST; + ser << rtc_EN; + ser << RealTimeClock; - REICAST_SA(aica_reg,0x8000); + ser << aica_reg; - channel_serialize(data, total_size) ; + channel_serialize(ser); - REICAST_SA(cdda_sector,CDDA_SIZE); - REICAST_S(cdda_index); + register_serialize(sb_regs, ser); + ser << SB_ISTNRM; + ser << SB_FFST_rc; + ser << SB_FFST; + ser << SB_ADST; - register_serialize(sb_regs, data, total_size) ; - REICAST_S(SB_ISTNRM); - REICAST_S(SB_FFST_rc); - REICAST_S(SB_FFST); - REICAST_S(SB_ADST); + sys_rom->Serialize(ser); + sys_nvmem->Serialize(ser); - sys_rom->Serialize(data, total_size); - sys_nvmem->Serialize(data, total_size); + gdrom::serialize(ser); - REICAST_S(GD_HardwareInfo); + mcfg_SerializeDevices(ser); + pvr::serialize(ser); - REICAST_S(sns_asc); - REICAST_S(sns_ascq); - REICAST_S(sns_key); + ser << OnChipRAM; - REICAST_S(packet_cmd); - REICAST_S(set_mode_offset); - REICAST_S(read_params); - REICAST_S(read_buff); - REICAST_S(pio_buff); - REICAST_S(set_mode_offset); - REICAST_S(ata_cmd); - REICAST_S(cdda); - REICAST_S(gd_state); - REICAST_S(gd_disk_type); - REICAST_S(data_write_mode); - REICAST_S(DriveSel); - REICAST_S(Error); + register_serialize(CCN, ser); + register_serialize(UBC, ser); + register_serialize(BSC, ser); + register_serialize(DMAC, ser); + register_serialize(CPG, ser); + register_serialize(RTC, ser); + register_serialize(INTC, ser); + register_serialize(TMU, ser); + register_serialize(SCI, ser); + register_serialize(SCIF, ser); + icache.Serialize(ser); + ocache.Serialize(ser); - REICAST_S(IntReason); - REICAST_S(Features); - REICAST_S(SecCount); - REICAST_S(SecNumber); - REICAST_S(GDStatus); - REICAST_S(ByteCount); + if (!ser.rollback()) + ser.serialize(mem_b.data, mem_b.size); - - REICAST_SA(EEPROM,0x100); - REICAST_S(EEPROM_loaded); - - - REICAST_S(maple_ddt_pending_reset); - - mcfg_SerializeDevices(data, total_size); - - YUV_serialize(data, total_size); - - REICAST_SA(pvr_regs,pvr_RegSize); - - spg_Serialize(data, total_size); - rend_serialize(data, total_size); - - REICAST_S(ta_fsm[2048]); - REICAST_S(ta_fsm_cl); - - SerializeTAContext(data, total_size); - - if (!rollback) - REICAST_SA(vram.data, vram.size); - - REICAST_SA(OnChipRAM.data(), OnChipRAM_SIZE); - - register_serialize(CCN, data, total_size) ; - register_serialize(UBC, data, total_size) ; - register_serialize(BSC, data, total_size) ; - register_serialize(DMAC, data, total_size) ; - register_serialize(CPG, data, total_size) ; - register_serialize(RTC, data, total_size) ; - register_serialize(INTC, data, total_size) ; - register_serialize(TMU, data, total_size) ; - register_serialize(SCI, data, total_size) ; - register_serialize(SCIF, data, total_size) ; - icache.Serialize(data, total_size); - ocache.Serialize(data, total_size); - - if (!rollback) - REICAST_SA(mem_b.data, mem_b.size); - - REICAST_SA(InterruptEnvId,32); - REICAST_SA(InterruptBit,32); - REICAST_SA(InterruptLevelBit,16); - REICAST_S(interrupt_vpend); - REICAST_S(interrupt_vmask); - REICAST_S(decoded_srimask); + ser << InterruptEnvId; + ser << InterruptBit; + ser << InterruptLevelBit; + ser << interrupt_vpend; + ser << interrupt_vmask; + ser << decoded_srimask; //default to nommu_full - i = 3 ; + int i = 3; if ( do_sqw_nommu == &do_sqw_nommu_area_3) - i = 0 ; + i = 0; else if (do_sqw_nommu == &do_sqw_nommu_area_3_nonvmem) - i = 1 ; + i = 1; else if (do_sqw_nommu == &TAWriteSQ) - i = 2 ; + i = 2; else if (do_sqw_nommu==&do_sqw_nommu_full) - i = 3 ; + i = 3; + ser << i; - REICAST_S(i) ; + ser << (*p_sh4rcb).sq_buffer; - REICAST_S((*p_sh4rcb).sq_buffer); + ser << (*p_sh4rcb).cntx; - REICAST_S((*p_sh4rcb).cntx); - - REICAST_S(sh4_sched_ffb); + ser << sh4_sched_ffb; std::array schedIds = getSchedulerIds(); if (sh4_sched_next_id == -1) - REICAST_S(sh4_sched_next_id); + ser << sh4_sched_next_id; else for (u32 i = 0; i < schedIds.size(); i++) if (schedIds[i] == sh4_sched_next_id) - REICAST_S(i); + ser << i; for (u32 i = 0; i < schedIds.size() - 1; i++) { - REICAST_S(sch_list[schedIds[i]].tag); - REICAST_S(sch_list[schedIds[i]].start); - REICAST_S(sch_list[schedIds[i]].end); + ser << sch_list[schedIds[i]].tag; + ser << sch_list[schedIds[i]].start; + ser << sch_list[schedIds[i]].end; } - REICAST_S(config::EmulateBBA.get()); + ser << config::EmulateBBA.get(); if (config::EmulateBBA) { - bba_Serialize(data, total_size); + bba_Serialize(ser); } else { - REICAST_S(sch_list[modem_sched].tag); - REICAST_S(sch_list[modem_sched].start); - REICAST_S(sch_list[modem_sched].end); + ser << sch_list[modem_sched].tag; + ser << sch_list[modem_sched].start; + ser << sch_list[modem_sched].end; } - ModemSerialize(data, total_size); + ModemSerialize(ser); - REICAST_S(SCIF_SCFSR2); - REICAST_S(SCIF_SCSCR2); - REICAST_S(BSC_PDTRA); + ser << SCIF_SCFSR2; + ser << SCIF_SCSCR2; + ser << BSC_PDTRA; - REICAST_SA(tmu_shift,3); - REICAST_SA(tmu_mask,3); - REICAST_SA(tmu_mask64,3); - REICAST_SA(old_mode,3); - REICAST_SA(tmu_ch_base,3); - REICAST_SA(tmu_ch_base64,3); + ser << tmu_shift; + ser << tmu_mask; + ser << tmu_mask64; + ser << old_mode; + ser << tmu_ch_base; + ser << tmu_ch_base64; - REICAST_SA(CCN_QACR_TR,2); + ser << CCN_QACR_TR; - REICAST_S(UTLB); - REICAST_S(ITLB); - REICAST_S(sq_remap); - REICAST_S(ITLB_LRU_USE); + ser << UTLB; + ser << ITLB; + ser << sq_remap; - REICAST_S(NullDriveDiscType); - REICAST_SA(q_subchannel,96); + ser << NullDriveDiscType; + ser << q_subchannel; - naomi_Serialize(data, total_size); + naomi_Serialize(ser); - REICAST_S(config::Broadcast.get()); - REICAST_S(config::Cable.get()); - REICAST_S(config::Region.get()); + ser << config::Broadcast.get(); + ser << config::Cable.get(); + ser << config::Region.get(); if (CurrentCartridge != NULL) - CurrentCartridge->Serialize(data, total_size); - - gd_hle_state.Serialize(data, total_size); + CurrentCartridge->Serialize(ser); - DEBUG_LOG(SAVESTATE, "Saved %d bytes", *total_size); + gd_hle_state.Serialize(ser); - return true ; + DEBUG_LOG(SAVESTATE, "Saved %d bytes", (u32)ser.size()); } -static bool dc_unserialize_libretro(void **data, unsigned int *total_size, serialize_version_enum version) +static void dc_deserialize_libretro(Deserializer& deser) { - int i = 0; + deser >> aica_interr; + deser >> aica_reg_L; + deser >> e68k_out; + deser >> e68k_reg_L; + deser >> e68k_reg_M; - REICAST_US(aica_interr) ; - REICAST_US(aica_reg_L) ; - REICAST_US(e68k_out) ; - REICAST_US(e68k_reg_L) ; - REICAST_US(e68k_reg_M) ; - - REICAST_USA(arm_Reg,RN_ARM_REG_COUNT - 1); - REICAST_US(armIrqEnable); - REICAST_US(armFiqEnable); - REICAST_US(armMode); - REICAST_US(Arm7Enabled); - if (version < V9_LIBRETRO) + deser.deserialize(arm_Reg, RN_ARM_REG_COUNT - 1); + deser >> armIrqEnable; + deser >> armFiqEnable; + deser >> armMode; + deser >> Arm7Enabled; + if (deser.version() < Deserializer::V9_LIBRETRO) { - REICAST_SKIP(256); // cpuBitsSet - REICAST_SKIP(1); // intState - REICAST_SKIP(1); // stopState - REICAST_SKIP(1); // holdState + deser.skip(256); // cpuBitsSet + deser.skip(1); // intState + deser.skip(1); // stopState + deser.skip(1); // holdState } arm7ClockTicks = 0; - dsp::state.deserialize(data, total_size, version); + dsp::state.deserialize(deser); - for ( i = 0 ; i < 3 ; i++) + for (int i = 0 ; i < 3 ; i++) { - REICAST_US(timers[i].c_step); - REICAST_US(timers[i].m_step); + deser >> timers[i].c_step; + deser >> timers[i].m_step; } - REICAST_USA(aica_ram.data,aica_ram.size) ; - REICAST_US(VREG); - REICAST_US(ARMRST); - REICAST_US(rtc_EN); + deser.deserialize(aica_ram.data, aica_ram.size); + deser >> VREG; + deser >> ARMRST; + deser >> rtc_EN; - REICAST_USA(aica_reg,0x8000); + deser >> aica_reg; - if (version < V7_LIBRETRO) - { - REICAST_SKIP(4 * 16); // volume_lut - REICAST_SKIP(4 * 256 + 768); // tl_lut. Due to a previous bug this is not 4 * (256 + 768) - REICAST_SKIP(4 * 64); // AEG_ATT_SPS - REICAST_SKIP(4 * 64); // AEG_DSR_SPS - REICAST_SKIP(2); // pl - REICAST_SKIP(2); // pr - } - channel_unserialize(data, total_size, version); + channel_deserialize(deser); - REICAST_USA(cdda_sector,CDDA_SIZE); - REICAST_US(cdda_index); - if (version < V9_LIBRETRO) - { - REICAST_SKIP(4 * 64); // mxlr - REICAST_SKIP(4); // samples_gen - } - - register_unserialize(sb_regs, data, total_size, version); - REICAST_US(SB_ISTNRM); - REICAST_US(SB_FFST_rc); - REICAST_US(SB_FFST); + register_deserialize(sb_regs, deser); + deser >> SB_ISTNRM; + deser >> SB_FFST_rc; + deser >> SB_FFST; SB_ADST = 0; - REICAST_SKIP(4); // sys_nvmem->size - REICAST_SKIP(4); // sys_nvmem->mask + deser.skip(); // sys_nvmem->size + deser.skip(); // sys_nvmem->mask if (settings.platform.system == DC_PLATFORM_NAOMI || settings.platform.system == DC_PLATFORM_ATOMISWAVE) - sys_nvmem->Unserialize(data, total_size); + sys_nvmem->Deserialize(deser); - REICAST_SKIP(4); // sys_nvmem/sys_rom->size - REICAST_SKIP(4); // sys_nvmem/sys_rom->mask + deser.skip(); // sys_nvmem/sys_rom->size + deser.skip(); // sys_nvmem/sys_rom->mask if (settings.platform.system == DC_PLATFORM_DREAMCAST) { - sys_nvmem->Unserialize(data, total_size); + sys_nvmem->Deserialize(deser); } else if (settings.platform.system == DC_PLATFORM_ATOMISWAVE) { - REICAST_US(static_cast(sys_rom)->state); - REICAST_USA(sys_rom->data, sys_rom->size); + deser >> static_cast(sys_rom)->state; + deser.deserialize(sys_rom->data, sys_rom->size); } else { - REICAST_US(i); + deser.skip(); } - REICAST_US(GD_HardwareInfo); + gdrom::deserialize(deser); - REICAST_US(sns_asc); - REICAST_US(sns_ascq); - REICAST_US(sns_key); + mcfg_DeserializeDevices(deser); - REICAST_US(packet_cmd); - REICAST_US(set_mode_offset); - REICAST_US(read_params); - REICAST_US(packet_cmd); - // read_buff - read_buff.cache_size = 0; - if (version < V9_LIBRETRO) - REICAST_SKIP(4 + 4 + 2352 * 8192); - REICAST_US(pio_buff); - REICAST_US(set_mode_offset); - REICAST_US(ata_cmd); - REICAST_US(cdda); - cdda.status = (bool)cdda.status ? cdda_t::Playing : cdda_t::NoInfo; - REICAST_US(gd_state); - REICAST_US(gd_disk_type); - REICAST_US(data_write_mode); - REICAST_US(DriveSel); - REICAST_US(Error); - REICAST_US(IntReason); - REICAST_US(Features); - REICAST_US(SecCount); - REICAST_US(SecNumber); - REICAST_US(GDStatus); - REICAST_US(ByteCount); - REICAST_US(i); // GDROM_TICK - REICAST_USA(EEPROM,0x100); - REICAST_US(EEPROM_loaded); + pvr::deserialize(deser); - REICAST_US(maple_ddt_pending_reset); - mcfg_UnserializeDevices(data, total_size, version); + deser >> OnChipRAM; - if (version < V9_LIBRETRO) - { - REICAST_SKIP(4); // FrameCOunt - REICAST_SKIP(1); // pend_rend - } - pend_rend = false; - - YUV_unserialize(data, total_size, version); - - if (version < V9_LIBRETRO) - REICAST_SKIP(1); // fog_needs_update - REICAST_USA(pvr_regs, pvr_RegSize); - fog_needs_update = true ; - - spg_Unserialize(data, total_size, version); - - if (version < V9_LIBRETRO) - { - REICAST_SKIP(4 * 256); // ta_type_lut - REICAST_SKIP(2048); // ta_fsm - } - rend_deserialize(data, total_size, version); - - REICAST_US(ta_fsm[2048]); - REICAST_US(ta_fsm_cl); - if (version < V9_LIBRETRO) - { - REICAST_SKIP(1); // pal_needs_update - REICAST_SKIP(4 * 4); // _pal_rev_256 - REICAST_SKIP(4 * 64); // _pal_rev_16 - REICAST_SKIP(4 * 4); // pal_rev_256 - REICAST_SKIP(4 * 64); // pal_rev_16 - REICAST_SKIP(4 * 65536 * 3); // decoded_colors - REICAST_US(i); // tileclip_val - REICAST_SKIP(65536); // f32_su8_tbl - REICAST_US(i); // FaceBaseColor - REICAST_US(i); // FaceOffsColor - REICAST_US(i); // SFaceBaseColor - REICAST_US(i); // SFaceOffsColor - - REICAST_US(i); // palette_index - REICAST_SKIP(1); // KillTex - REICAST_SKIP(4 * 1024); // palette16_ram - REICAST_SKIP(4 * 1024); // palette32_ram - REICAST_SKIP(4 * 1024 * 8 * 2); // detwiddle - } - - pal_needs_update = true; - if (version >= V10_LIBRETRO) - UnserializeTAContext(data, total_size, version); - - REICAST_USA(vram.data, vram.size); - - REICAST_USA(OnChipRAM.data(), OnChipRAM_SIZE); - - register_unserialize(CCN, data, total_size, version); - register_unserialize(UBC, data, total_size, version); - register_unserialize(BSC, data, total_size, version); - register_unserialize(DMAC, data, total_size, version); - register_unserialize(CPG, data, total_size, version); - register_unserialize(RTC, data, total_size, version); - register_unserialize(INTC, data, total_size, version); - register_unserialize(TMU, data, total_size, version); - register_unserialize(SCI, data, total_size, version); - register_unserialize(SCIF, data, total_size, version); - if (version >= V11_LIBRETRO) // FIXME was added in V11 fa49de29 24/12/2020 but ver not updated until V12 (13/4/2021) - icache.Unserialize(data, total_size); + register_deserialize(CCN, deser); + register_deserialize(UBC, deser); + register_deserialize(BSC, deser); + register_deserialize(DMAC, deser); + register_deserialize(CPG, deser); + register_deserialize(RTC, deser); + register_deserialize(INTC, deser); + register_deserialize(TMU, deser); + register_deserialize(SCI, deser); + register_deserialize(SCIF, deser); + if (deser.version() >= Deserializer::V11_LIBRETRO) // FIXME was added in V11 fa49de29 24/12/2020 but ver not updated until V12 (13/4/2021) + icache.Deserialize(deser); else icache.Reset(true); - if (version >= V11_LIBRETRO) // FIXME was added in V11 2eb66879 27/12/2020 but ver not updated until V12 (13/4/2021) - ocache.Unserialize(data, total_size); + if (deser.version() >= Deserializer::V11_LIBRETRO) // FIXME was added in V11 2eb66879 27/12/2020 but ver not updated until V12 (13/4/2021) + ocache.Deserialize(deser); else ocache.Reset(true); - REICAST_USA(mem_b.data, mem_b.size); - if (version < V9_LIBRETRO) - { - u16 dum16; - REICAST_US(dum16); // IRLPriority - } - REICAST_USA(InterruptEnvId,32); - REICAST_USA(InterruptBit,32); - REICAST_USA(InterruptLevelBit,16); - REICAST_US(interrupt_vpend); - REICAST_US(interrupt_vmask); - REICAST_US(decoded_srimask); + deser.deserialize(mem_b.data, mem_b.size); + if (deser.version() < Deserializer::V9_LIBRETRO) + deser.skip(); + deser >> InterruptEnvId; + deser >> InterruptBit; + deser >> InterruptLevelBit; + deser >> interrupt_vpend; + deser >> interrupt_vmask; + deser >> decoded_srimask; - REICAST_US(i) ; - if ( i == 0 ) - do_sqw_nommu = &do_sqw_nommu_area_3 ; - else if ( i == 1 ) - do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem ; - else if ( i == 2 ) + int i; + deser >> i; + if (i == 0) + do_sqw_nommu = &do_sqw_nommu_area_3; + else if (i == 1) + do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem; + else if (i == 2) do_sqw_nommu = &TAWriteSQ ; - else if ( i == 3 ) - do_sqw_nommu = &do_sqw_nommu_full ; + else if (i == 3) + do_sqw_nommu = &do_sqw_nommu_full; - REICAST_US((*p_sh4rcb).sq_buffer); + deser >> (*p_sh4rcb).sq_buffer; - REICAST_US((*p_sh4rcb).cntx); + deser >> (*p_sh4rcb).cntx; p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE; - if (version < V9_LIBRETRO) + if (deser.version() < Deserializer::V9_LIBRETRO) { - REICAST_SKIP(4); // old_rm - REICAST_SKIP(4); // old_dn + deser.skip(); // old_rm + deser.skip(); // old_dn } - REICAST_US(sh4_sched_ffb); - if (version < V9_LIBRETRO) - REICAST_SKIP(4); // sh4_sched_intr + deser >> sh4_sched_ffb; + if (deser.version() < Deserializer::V9_LIBRETRO) + deser.skip(); // sh4_sched_intr - REICAST_US(sch_list[aica_schid].tag); - REICAST_US(sch_list[aica_schid].start); - REICAST_US(sch_list[aica_schid].end); + deser >> sch_list[aica_schid].tag; + deser >> sch_list[aica_schid].start; + deser >> sch_list[aica_schid].end; - REICAST_US(sch_list[rtc_schid].tag); - REICAST_US(sch_list[rtc_schid].start); - REICAST_US(sch_list[rtc_schid].end); + deser >> sch_list[rtc_schid].tag; + deser >> sch_list[rtc_schid].start; + deser >> sch_list[rtc_schid].end; - REICAST_US(sch_list[gdrom_schid].tag); - REICAST_US(sch_list[gdrom_schid].start); - REICAST_US(sch_list[gdrom_schid].end); + deser >> sch_list[gdrom_schid].tag; + deser >> sch_list[gdrom_schid].start; + deser >> sch_list[gdrom_schid].end; - REICAST_US(sch_list[maple_schid].tag); - REICAST_US(sch_list[maple_schid].start); - REICAST_US(sch_list[maple_schid].end); + deser >> sch_list[maple_schid].tag; + deser >> sch_list[maple_schid].start; + deser >> sch_list[maple_schid].end; - REICAST_US(sch_list[dma_sched_id].tag); - REICAST_US(sch_list[dma_sched_id].start); - REICAST_US(sch_list[dma_sched_id].end); + deser >> sch_list[dma_sched_id].tag; + deser >> sch_list[dma_sched_id].start; + deser >> sch_list[dma_sched_id].end; for (int i = 0; i < 3; i++) { - REICAST_US(sch_list[tmu_sched[i]].tag); - REICAST_US(sch_list[tmu_sched[i]].start); - REICAST_US(sch_list[tmu_sched[i]].end); + deser >> sch_list[tmu_sched[i]].tag; + deser >> sch_list[tmu_sched[i]].start; + deser >> sch_list[tmu_sched[i]].end; } - REICAST_US(sch_list[render_end_schid].tag) ; - REICAST_US(sch_list[render_end_schid].start) ; - REICAST_US(sch_list[render_end_schid].end) ; + deser >> sch_list[render_end_schid].tag; + deser >> sch_list[render_end_schid].start; + deser >> sch_list[render_end_schid].end; - REICAST_US(sch_list[vblank_schid].tag) ; - REICAST_US(sch_list[vblank_schid].start) ; - REICAST_US(sch_list[vblank_schid].end) ; + deser >> sch_list[vblank_schid].tag; + deser >> sch_list[vblank_schid].start; + deser >> sch_list[vblank_schid].end; - if (version < V9_LIBRETRO) + if (deser.version() < Deserializer::V9_LIBRETRO) { - REICAST_SKIP(4); // sch_list[time_sync].tag - REICAST_SKIP(4); // sch_list[time_sync].start - REICAST_SKIP(4); // sch_list[time_sync].end + deser.skip(); // sch_list[time_sync].tag + deser.skip(); // sch_list[time_sync].start + deser.skip(); // sch_list[time_sync].end } - if (version >= V13_LIBRETRO) - REICAST_SKIP(1); // settings.network.EmulateBBA + if (deser.version() >= Deserializer::V13_LIBRETRO) + deser.skip(); // settings.network.EmulateBBA - REICAST_US(sch_list[modem_sched].tag) ; - REICAST_US(sch_list[modem_sched].start) ; - REICAST_US(sch_list[modem_sched].end) ; + deser >> sch_list[modem_sched].tag; + deser >> sch_list[modem_sched].start; + deser >> sch_list[modem_sched].end; - REICAST_US(SCIF_SCFSR2); - if (version < V9_LIBRETRO) + deser >> SCIF_SCFSR2; + if (deser.version() < Deserializer::V9_LIBRETRO) { - REICAST_SKIP(1); // SCIF_SCFRDR2 - REICAST_SKIP(4); // SCIF_SCFDR2 + deser.skip(1); // SCIF_SCFRDR2 + deser.skip(4); // SCIF_SCFDR2 } - else if (version >= V11_LIBRETRO) - REICAST_US(SCIF_SCSCR2); - REICAST_US(BSC_PDTRA); + else if (deser.version() >= Deserializer::V11_LIBRETRO) + deser >> SCIF_SCSCR2; + deser >> BSC_PDTRA; - REICAST_USA(tmu_shift,3); - REICAST_USA(tmu_mask,3); - REICAST_USA(tmu_mask64,3); - REICAST_USA(old_mode,3); - REICAST_USA(tmu_ch_base,3); - REICAST_USA(tmu_ch_base64,3); + deser >> tmu_shift; + deser >> tmu_mask; + deser >> tmu_mask64; + deser >> old_mode; + deser >> tmu_ch_base; + deser >> tmu_ch_base64; - REICAST_USA(CCN_QACR_TR,2); + deser >> CCN_QACR_TR; - if (version < V6_LIBRETRO) + if (deser.version() < Deserializer::V6_LIBRETRO) { for (int i = 0; i < 64; i++) { - REICAST_US(UTLB[i].Address); - REICAST_US(UTLB[i].Data); + deser >> UTLB[i].Address; + deser >> UTLB[i].Data; } for (int i = 0; i < 4; i++) { - REICAST_US(ITLB[i].Address); - REICAST_US(ITLB[i].Data); + deser >> ITLB[i].Address; + deser >> ITLB[i].Data; } } else { - REICAST_US(UTLB); - REICAST_US(ITLB); + deser >> UTLB; + deser >> ITLB; } - if (version >= V11_LIBRETRO) - REICAST_US(sq_remap); - REICAST_US(ITLB_LRU_USE); + if (deser.version() >= Deserializer::V11_LIBRETRO) + deser >> sq_remap; + deser.skip(64 * 4); // ITLB_LRU_USE - REICAST_US(NullDriveDiscType); - REICAST_USA(q_subchannel,96); + deser >> NullDriveDiscType; + deser >> q_subchannel; - REICAST_US(i); // FLASH_SIZE - REICAST_US(i); // BBSRAM_SIZE - REICAST_US(i); // BIOS_SIZE - REICAST_US(i); // RAM_SIZE - REICAST_US(i); // ARAM_SIZE - REICAST_US(i); // VRAM_SIZE - REICAST_US(i); // RAM_MASK - REICAST_US(i); // ARAM_MASK - REICAST_US(i); // VRAM_MASK + deser.skip(); // FLASH_SIZE + deser.skip(); // BBSRAM_SIZE + deser.skip(); // BIOS_SIZE + deser.skip(); // RAM_SIZE + deser.skip(); // ARAM_SIZE + deser.skip(); // VRAM_SIZE + deser.skip(); // RAM_MASK + deser.skip(); // ARAM_MASK + deser.skip(); // VRAM_MASK - if (version < V9_LIBRETRO) + naomi_Deserialize(deser); + + if (deser.version() < Deserializer::V9_LIBRETRO) { - REICAST_SKIP(4); // naomi_updates - REICAST_SKIP(4); // BoardID - } - naomi_Unserialize(data, total_size, version); + deser.skip(); // cycle_counter + deser.skip(); // idxnxx + deser.skip(44); // sizeof(state_t) + deser.skip(); // div_som_reg1 + deser.skip(); // div_som_reg2 + deser.skip(); // div_som_reg3 - if (version < V9_LIBRETRO) - { - REICAST_SKIP(4); // cycle_counter - REICAST_SKIP(4); // idxnxx - REICAST_SKIP(44); // sizeof(state_t) - REICAST_SKIP(4); // div_som_reg1 - REICAST_SKIP(4); // div_som_reg2 - REICAST_SKIP(4); // div_som_reg3 - - REICAST_SKIP(4); // LastAddr - REICAST_SKIP(4); // LastAddr_min - REICAST_SKIP(1024); // block_hash + deser.skip(); // LastAddr + deser.skip(); // LastAddr_min + deser.skip(1024); // block_hash // RegisterRead, RegisterWrite for (int i = 0; i < 74; i++) // sh4_reg_count (changed to 75 on 9/6/2020 (V9), V10 on 22/6/2020) { - REICAST_SKIP(4); - REICAST_SKIP(4); + deser.skip(4); + deser.skip(4); } - REICAST_SKIP(4); // fallback_blocks - REICAST_SKIP(4); // total_blocks - REICAST_SKIP(4); // REMOVED_OPS + deser.skip(); // fallback_blocks + deser.skip(); // total_blocks + deser.skip(); // REMOVED_OPS } - REICAST_US(config::Broadcast.get()); - REICAST_US(config::Cable.get()); - REICAST_US(config::Region.get()); + deser >> config::Broadcast.get(); + deser >> config::Cable.get(); + deser >> config::Region.get(); - if (CurrentCartridge != nullptr && (settings.platform.system != DC_PLATFORM_ATOMISWAVE || version >= V10_LIBRETRO)) - CurrentCartridge->Unserialize(data, total_size); - if (version >= V7_LIBRETRO) - gd_hle_state.Unserialize(data, total_size); + if (CurrentCartridge != nullptr && (settings.platform.system != DC_PLATFORM_ATOMISWAVE || deser.version() >= Deserializer::V10_LIBRETRO)) + CurrentCartridge->Deserialize(deser); + if (deser.version() >= Deserializer::V7_LIBRETRO) + gd_hle_state.Deserialize(deser); config::EmulateBBA.override(false); - DEBUG_LOG(SAVESTATE, "Loaded %d bytes (libretro compat)", *total_size); - - return true; + DEBUG_LOG(SAVESTATE, "Loaded %d bytes (libretro compat)", (u32)deser.size()); } -bool dc_unserialize(void **data, unsigned int *total_size, bool rollback) +void dc_deserialize(Deserializer& deser) { - int i = 0; - - serialize_version_enum version = V1 ; - - REICAST_US(version) ; - if (version >= V5_LIBRETRO && version <= V13_LIBRETRO) - return dc_unserialize_libretro(data, total_size, version); - if (version != V4 && version < V5) + if (deser.version() >= Deserializer::V5_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO) { - WARN_LOG(SAVESTATE, "Save State version not supported: %d", version); - return false; + dc_deserialize_libretro(deser); + return; } - if (version > VCUR_FLYCAST) - { - WARN_LOG(SAVESTATE, "Save State version too recent: %d", version); - return false; - } - DEBUG_LOG(SAVESTATE, "Loading state version %d", version); + DEBUG_LOG(SAVESTATE, "Loading state version %d", deser.version()); - REICAST_US(aica_interr) ; - REICAST_US(aica_reg_L) ; - REICAST_US(e68k_out) ; - REICAST_US(e68k_reg_L) ; - REICAST_US(e68k_reg_M) ; + deser >> aica_interr; + deser >> aica_reg_L; + deser >> e68k_out; + deser >> e68k_reg_L; + deser >> e68k_reg_M; - REICAST_USA(arm_Reg,RN_ARM_REG_COUNT - 1); - REICAST_US(armIrqEnable); - REICAST_US(armFiqEnable); - REICAST_US(armMode); - REICAST_US(Arm7Enabled); - if (version < V5) - REICAST_SKIP(256 + 3); - if (version >= V19) - REICAST_US(arm7ClockTicks); + deser.deserialize(arm_Reg, RN_ARM_REG_COUNT - 1); + deser >> armIrqEnable; + deser >> armFiqEnable; + deser >> armMode; + deser >> Arm7Enabled; + if (deser.version() < Deserializer::V5) + deser.skip(256 + 3); + if (deser.version() >= Deserializer::V19) + deser >> arm7ClockTicks; else arm7ClockTicks = 0; - dsp::state.deserialize(data, total_size, version); + dsp::state.deserialize(deser); - for ( i = 0 ; i < 3 ; i++) + for (int i = 0 ; i < 3 ; i++) { - REICAST_US(timers[i].c_step); - REICAST_US(timers[i].m_step); + deser >> timers[i].c_step; + deser >> timers[i].m_step; } - if (!rollback) - REICAST_USA(aica_ram.data,aica_ram.size) ; - REICAST_US(VREG); - REICAST_US(ARMRST); - REICAST_US(rtc_EN); - if (version >= V9) - REICAST_US(RealTimeClock); + if (!deser.rollback()) + deser.deserialize(aica_ram.data, aica_ram.size); + deser >> VREG; + deser >> ARMRST; + deser >> rtc_EN; + if (deser.version() >= Deserializer::V9) + deser >> RealTimeClock; - REICAST_USA(aica_reg,0x8000); + deser >> aica_reg; - if (version < V5) - { - REICAST_SKIP(4 * 16); - REICAST_SKIP(4 * 256 + 768); - REICAST_SKIP(4 * 64); - REICAST_SKIP(4 * 64); - REICAST_SKIP(2); - REICAST_SKIP(2); - } - channel_unserialize(data, total_size, version); + channel_deserialize(deser); - REICAST_USA(cdda_sector,CDDA_SIZE); - REICAST_US(cdda_index); - if (version < V5) - { - REICAST_SKIP(4 * 64); - REICAST_SKIP(4); - } - - register_unserialize(sb_regs, data, total_size, version) ; - REICAST_US(SB_ISTNRM); - REICAST_US(SB_FFST_rc); - REICAST_US(SB_FFST); - if (version >= V15) - REICAST_US(SB_ADST); + register_deserialize(sb_regs, deser); + deser >> SB_ISTNRM; + deser >> SB_FFST_rc; + deser >> SB_FFST; + if (deser.version() >= Deserializer::V15) + deser >> SB_ADST; else SB_ADST = 0; - if (version < V5) + if (deser.version() < Deserializer::V5) { - REICAST_SKIP(4); // size - REICAST_SKIP(4); // mask + deser.skip(); // size + deser.skip(); // mask } - sys_rom->Unserialize(data, total_size); - sys_nvmem->Unserialize(data, total_size); + sys_rom->Deserialize(deser); + sys_nvmem->Deserialize(deser); - REICAST_US(GD_HardwareInfo); + gdrom::deserialize(deser); - REICAST_US(sns_asc); - REICAST_US(sns_ascq); - REICAST_US(sns_key); + mcfg_DeserializeDevices(deser); - REICAST_US(packet_cmd); - REICAST_US(set_mode_offset); - REICAST_US(read_params); - if (version >= V17) - REICAST_US(read_buff); - else - { - REICAST_US(packet_cmd); - read_buff.cache_size = 0; - } - if (version < V8) - REICAST_SKIP(4 + 4 + 2352 * 8192); - REICAST_US(pio_buff); - REICAST_US(set_mode_offset); - REICAST_US(ata_cmd); - REICAST_US(cdda); - if (version < V10) - cdda.status = (bool)cdda.status ? cdda_t::Playing : cdda_t::NoInfo; - REICAST_US(gd_state); - REICAST_US(gd_disk_type); - REICAST_US(data_write_mode); - REICAST_US(DriveSel); - REICAST_US(Error); - REICAST_US(IntReason); - REICAST_US(Features); - REICAST_US(SecCount); - REICAST_US(SecNumber); - REICAST_US(GDStatus); - REICAST_US(ByteCount); + pvr::deserialize(deser); - REICAST_USA(EEPROM,0x100); - REICAST_US(EEPROM_loaded); + deser >> OnChipRAM; - REICAST_US(maple_ddt_pending_reset); - - mcfg_UnserializeDevices(data, total_size, version); - - if (version < V5) - { - REICAST_SKIP(4); - REICAST_SKIP(1); // pend_rend - } - pend_rend = false; - - YUV_unserialize(data, total_size, version); - - REICAST_USA(pvr_regs,pvr_RegSize); - fog_needs_update = true ; - - spg_Unserialize(data, total_size, version); - - if (version < V5) - { - REICAST_SKIP(4 * 256); - REICAST_SKIP(2048); // ta_fsm - } - rend_deserialize(data, total_size, version); - - REICAST_US(ta_fsm[2048]); - REICAST_US(ta_fsm_cl); - - if (version < V5) - { - REICAST_SKIP(4); - REICAST_SKIP(65536); - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4); - } - if (version >= V11) - UnserializeTAContext(data, total_size, version); - - if (!rollback) - REICAST_USA(vram.data, vram.size); - pal_needs_update = true; - - REICAST_USA(OnChipRAM.data(), OnChipRAM_SIZE); - - register_unserialize(CCN, data, total_size, version) ; - register_unserialize(UBC, data, total_size, version) ; - register_unserialize(BSC, data, total_size, version) ; - register_unserialize(DMAC, data, total_size, version) ; - register_unserialize(CPG, data, total_size, version) ; - register_unserialize(RTC, data, total_size, version) ; - register_unserialize(INTC, data, total_size, version) ; - register_unserialize(TMU, data, total_size, version) ; - register_unserialize(SCI, data, total_size, version) ; - register_unserialize(SCIF, data, total_size, version) ; - if (version >= V9) - icache.Unserialize(data, total_size); + register_deserialize(CCN, deser); + register_deserialize(UBC, deser); + register_deserialize(BSC, deser); + register_deserialize(DMAC, deser); + register_deserialize(CPG, deser); + register_deserialize(RTC, deser); + register_deserialize(INTC, deser); + register_deserialize(TMU, deser); + register_deserialize(SCI, deser); + register_deserialize(SCIF, deser); + if (deser.version() >= Deserializer::V9) + icache.Deserialize(deser); else icache.Reset(true); - if (version >= V10) - ocache.Unserialize(data, total_size); + if (deser.version() >= Deserializer::V10) + ocache.Deserialize(deser); else ocache.Reset(true); - if (!rollback) - REICAST_USA(mem_b.data, mem_b.size); + if (!deser.rollback()) + deser.deserialize(mem_b.data, mem_b.size); - if (version < V5) - REICAST_SKIP(2); - REICAST_USA(InterruptEnvId,32); - REICAST_USA(InterruptBit,32); - REICAST_USA(InterruptLevelBit,16); - REICAST_US(interrupt_vpend); - REICAST_US(interrupt_vmask); - REICAST_US(decoded_srimask); + if (deser.version() < Deserializer::V5) + deser.skip(2); + deser >> InterruptEnvId; + deser >> InterruptBit; + deser >> InterruptLevelBit; + deser >> interrupt_vpend; + deser >> interrupt_vmask; + deser >> decoded_srimask; - REICAST_US(i) ; - if ( i == 0 ) - do_sqw_nommu = &do_sqw_nommu_area_3 ; - else if ( i == 1 ) - do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem ; - else if ( i == 2 ) - do_sqw_nommu = &TAWriteSQ ; - else if ( i == 3 ) - do_sqw_nommu = &do_sqw_nommu_full ; + int i; + deser >> i; + if (i == 0) + do_sqw_nommu = &do_sqw_nommu_area_3; + else if (i == 1) + do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem; + else if (i == 2) + do_sqw_nommu = &TAWriteSQ; + else if (i == 3) + do_sqw_nommu = &do_sqw_nommu_full; - REICAST_US((*p_sh4rcb).sq_buffer); + deser >> (*p_sh4rcb).sq_buffer; - REICAST_US((*p_sh4rcb).cntx); - if (version < V5) + deser >> (*p_sh4rcb).cntx; + if (deser.version() < Deserializer::V5) { - REICAST_SKIP(4); - REICAST_SKIP(4); + deser.skip(4); + deser.skip(4); } - if (version >= V19 && version < V21) - REICAST_SKIP(4); // sh4InterpCycles - if (version < V21) + if (deser.version() >= Deserializer::V19 && deser.version() < Deserializer::V21) + deser.skip(); // sh4InterpCycles + if (deser.version() < Deserializer::V21) p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE; - REICAST_US(sh4_sched_ffb); + deser >> sh4_sched_ffb; std::array schedIds = getSchedulerIds(); - if (version >= V19) + if (deser.version() >= Deserializer::V19) { - REICAST_US(sh4_sched_next_id); + deser >> sh4_sched_next_id; if (sh4_sched_next_id != -1) sh4_sched_next_id = schedIds[sh4_sched_next_id]; } - if (version < V8) - REICAST_US(i); // sh4_sched_intr + if (deser.version() < Deserializer::V8) + deser.skip(); // sh4_sched_intr for (u32 i = 0; i < schedIds.size() - 1; i++) { - REICAST_US(sch_list[schedIds[i]].tag); - REICAST_US(sch_list[schedIds[i]].start); - REICAST_US(sch_list[schedIds[i]].end); + deser >> sch_list[schedIds[i]].tag; + deser >> sch_list[schedIds[i]].start; + deser >> sch_list[schedIds[i]].end; } - if (version < V8) + if (deser.version() < Deserializer::V8) { - REICAST_US(i); // sch_list[time_sync].tag - REICAST_US(i); // sch_list[time_sync].start - REICAST_US(i); // sch_list[time_sync].end + deser.skip(); // sch_list[time_sync].tag + deser.skip(); // sch_list[time_sync].start + deser.skip(); // sch_list[time_sync].end } - if (version >= V13) - REICAST_US(config::EmulateBBA.get()); + if (deser.version() >= Deserializer::V13) + deser >> config::EmulateBBA.get(); else config::EmulateBBA.override(false); if (config::EmulateBBA) { - bba_Unserialize(data, total_size); + bba_Deserialize(deser); } else { - REICAST_US(sch_list[modem_sched].tag); - REICAST_US(sch_list[modem_sched].start); - REICAST_US(sch_list[modem_sched].end); + deser >> sch_list[modem_sched].tag; + deser >> sch_list[modem_sched].start; + deser >> sch_list[modem_sched].end; } - if (version < V19) + if (deser.version() < Deserializer::V19) sh4_sched_ffts(); - ModemDeserialize(data, total_size, version); + ModemDeserialize(deser); - REICAST_US(SCIF_SCFSR2); - if (version < V8) + deser >> SCIF_SCFSR2; + if (deser.version() < Deserializer::V8) { - bool dum_bool; - REICAST_US(dum_bool); // SCIF_SCFRDR2 - REICAST_US(i); // SCIF_SCFDR2 + deser.skip(); // SCIF_SCFRDR2 + deser.skip(); // SCIF_SCFDR2 } - else if (version >= V11) - REICAST_US(SCIF_SCSCR2); - REICAST_US(BSC_PDTRA); + else if (deser.version() >= Deserializer::V11) + deser >> SCIF_SCSCR2; + deser >> BSC_PDTRA; - REICAST_USA(tmu_shift,3); - REICAST_USA(tmu_mask,3); - REICAST_USA(tmu_mask64,3); - REICAST_USA(old_mode,3); - REICAST_USA(tmu_ch_base,3); - REICAST_USA(tmu_ch_base64,3); + deser >> tmu_shift; + deser >> tmu_mask; + deser >> tmu_mask64; + deser >> old_mode; + deser >> tmu_ch_base; + deser >> tmu_ch_base64; - REICAST_USA(CCN_QACR_TR,2); + deser >> CCN_QACR_TR; - REICAST_USA(UTLB,64); - REICAST_USA(ITLB,4); - if (version >= V11) - REICAST_US(sq_remap); - REICAST_USA(ITLB_LRU_USE,64); + deser >> UTLB; + deser >> ITLB; + if (deser.version() >= Deserializer::V11) + deser >> sq_remap; + deser.skip(64 * 4, Deserializer::V23); // ITLB_LRU_USE - REICAST_US(NullDriveDiscType); - REICAST_USA(q_subchannel,96); + deser >> NullDriveDiscType; + deser >> q_subchannel; - if (version < V5) + naomi_Deserialize(deser); + + if (deser.version() < Deserializer::V5) { - REICAST_SKIP(4); - REICAST_SKIP(4); + deser.skip(); // idxnxx + deser.skip(44); // sizeof(state_t) + deser.skip(4); + deser.skip(4); + deser.skip(4); + deser.skip(4); + deser.skip(4); + deser.skip(1024); + + deser.skip(8 * 74); // sh4_reg_count + deser.skip(4); + deser.skip(4); + deser.skip(4); + + deser.skip(2 * 4); + deser.skip(4); + deser.skip(4); + deser.skip(4 * 4); + deser.skip(4); + deser.skip(4); } - naomi_Unserialize(data, total_size, version); - - if (version < V5) - { - REICAST_US(i); // idxnxx - REICAST_SKIP(44); // sizeof(state_t) - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(1024); - - REICAST_SKIP(8 * 74); // sh4_reg_count - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4); - - REICAST_SKIP(2 * 4); - REICAST_SKIP(4); - REICAST_SKIP(4); - REICAST_SKIP(4 * 4); - REICAST_SKIP(4); - REICAST_SKIP(4); - } - REICAST_US(config::Broadcast.get()); + deser >> config::Broadcast.get(); verify(config::Broadcast <= 4); - REICAST_US(config::Cable.get()); + deser >> config::Cable.get(); verify(config::Cable <= 3); - REICAST_US(config::Region.get()); + deser >> config::Region.get(); verify(config::Region <= 3); if (CurrentCartridge != NULL) - CurrentCartridge->Unserialize(data, total_size); - if (version >= V6) - gd_hle_state.Unserialize(data, total_size); + CurrentCartridge->Deserialize(deser); + if (deser.version() >= Deserializer::V6) + gd_hle_state.Deserialize(deser); - DEBUG_LOG(SAVESTATE, "Loaded %d bytes", *total_size); - - return true ; + DEBUG_LOG(SAVESTATE, "Loaded %d bytes", (u32)deser.size()); } diff --git a/core/serialize.h b/core/serialize.h new file mode 100644 index 000000000..8ad141b05 --- /dev/null +++ b/core/serialize.h @@ -0,0 +1,212 @@ +/* + Copyright 2021 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . +*/ +#pragma once +#include "types.h" + +#include + +class SerializeBase +{ +public: + enum Version : int32_t { + V1, + V2, + V3, + V4, + V5_LIBRETRO, + V6_LIBRETRO, + V7_LIBRETRO, + V8_LIBRETRO, + V9_LIBRETRO, + V10_LIBRETRO, + V11_LIBRETRO, + V12_LIBRETRO, + V13_LIBRETRO, + VLAST_LIBRETRO = V13_LIBRETRO, + + V5 = 800, + V6 = 801, + V7 = 802, + V8 = 803, + V9 = 804, + V10 = 805, + V11 = 806, + V12 = 807, + V13 = 808, + V14 = 809, + V15 = 810, + V16 = 811, + V17 = 812, + V18 = 813, + V19 = 814, + V20 = 815, + V21 = 816, + V22 = 817, + V23 = 818, + Current = V23, + + Next = Current + 1, + }; + + size_t size() const { return _size; } + bool rollback() const { return _rollback; } + +protected: + SerializeBase(size_t limit, bool rollback) + : _size(0), limit(limit), _rollback(rollback) {} + + size_t _size; + size_t limit; + bool _rollback; +}; + +class Deserializer : public SerializeBase +{ +public: + class Exception : public std::runtime_error + { + public: + Exception(const char *msg) : std::runtime_error(msg) {} + }; + + Deserializer(const void *data, size_t limit, bool rollback = false) + : SerializeBase(limit, rollback), data((const u8 *)data) + { + deserialize(_version); + if (_version > V13_LIBRETRO && _version < V5) + throw Exception("Unsupported version"); + if (_version > Current) + throw Exception("Version too recent"); + } + + template + void deserialize(T& obj) + { + doDeserialize(&obj, sizeof(T)); + } + template + void deserialize(T *obj, size_t count) + { + doDeserialize(obj, sizeof(T) * count); + } + + template + void skip(Version minVersion = Next) + { + skip(sizeof(T), minVersion); + } + void skip(size_t size, Version minVersion = Next) + { + if (_version >= minVersion) + return; + if (this->_size + size > limit) + { + WARN_LOG(SAVESTATE, "Savestate overflow: current %d limit %d sz %d", (int)this->_size, (int)limit, (int)size); + throw Exception("Invalid savestate"); + } + data += size; + this->_size += size; + } + + Version version() const { return _version; } + +private: + void doDeserialize(void *dest, size_t size) + { + if (this->_size + size > limit) // FIXME one more test vs. current + { + WARN_LOG(SAVESTATE, "Savestate overflow: current %d limit %d sz %d", (int)this->_size, (int)limit, (int)size); + throw Exception("Invalid savestate"); + } + memcpy(dest, data, size); + data += size; + this->_size += size; + } + + Version _version; + const u8 *data; +}; + +class Serializer : public SerializeBase +{ +public: + Serializer() + : SerializeBase(std::numeric_limits::max(), false), data(nullptr) { } + + Serializer(void *data, size_t limit, bool rollback = false) + : SerializeBase(limit, rollback), data((u8 *)data) + { + Version v = Current; + serialize(v); + } + + template + void serialize(const T& obj) + { + doSerialize(&obj, sizeof(T)); + } + template + void serialize(const T *obj, size_t count) + { + doSerialize(obj, sizeof(T) * count); + } + + template + void skip() + { + skip(sizeof(T)); + } + void skip(size_t size) + { + verify(this->_size + size <= limit); + if (data != nullptr) + data += size; + this->_size += size; + } + bool dryrun() const { return data == nullptr; } + +private: + void doSerialize(const void *src, size_t size) + { + verify(this->_size + size <= limit); + if (data != nullptr) + { + memcpy(data, src, size); + data += size; + } + this->_size += size; + } + + u8 *data; +}; + +template +Serializer& operator<<(Serializer& ctx, const T& obj) { + ctx.serialize(obj); + return ctx; +} + +template +Deserializer& operator>>(Deserializer& ctx, T& obj) { + ctx.deserialize(obj); + return ctx; +} + +void dc_serialize(Serializer& ctx); +void dc_deserialize(Deserializer& ctx); diff --git a/core/types.h b/core/types.h index 6b690f16f..07b44104c 100644 --- a/core/types.h +++ b/core/types.h @@ -186,19 +186,6 @@ inline static void JITWriteProtect(bool enabled) { void os_DebugBreak(); #define dbgbreak os_DebugBreak() -bool rc_serialize(const void *src, unsigned int src_size, void **dest, unsigned int *total_size) ; -bool rc_unserialize(void *src, unsigned int src_size, void **dest, unsigned int *total_size); -bool dc_serialize(void **data, unsigned int *total_size, bool rollback = false); -bool dc_unserialize(void **data, unsigned int *total_size, bool rollback = false); - -#define REICAST_S(v) rc_serialize(&(v), sizeof(v), data, total_size) -#define REICAST_US(v) rc_unserialize(&(v), sizeof(v), data, total_size) - -#define REICAST_SA(v_arr,num) rc_serialize((v_arr), sizeof((v_arr)[0])*(num), data, total_size) -#define REICAST_USA(v_arr,num) rc_unserialize((v_arr), sizeof((v_arr)[0])*(num), data, total_size) - -#define REICAST_SKIP(size) do { if (*data) *(u8**)data += (size); *total_size += (size); } while (false) - #ifndef _MSC_VER #define stricmp strcasecmp #endif @@ -400,11 +387,6 @@ inline bool is_u8(u32 v) { return (u8)v==(s32)v; } inline bool is_s16(u32 v) { return (s16)v==(s32)v; } inline bool is_u16(u32 v) { return (u16)v==(u32)v; } -//PVR -s32 libPvr_Init(); -void libPvr_Reset(bool hard); -void libPvr_Term(); - // 0x00600000 - 0x006007FF [NAOMI] (modem area for dreamcast) u32 libExtDevice_ReadMem_A0_006(u32 addr,u32 size); void libExtDevice_WriteMem_A0_006(u32 addr,u32 data,u32 size); @@ -481,38 +463,5 @@ public: LoadCancelledException() : FlycastException("") {} }; -enum serialize_version_enum { - V1, - V2, - V3, - V4, - V5_LIBRETRO, - V6_LIBRETRO, - V7_LIBRETRO, - V8_LIBRETRO, - V9_LIBRETRO, - V10_LIBRETRO, - V11_LIBRETRO, - V12_LIBRETRO, - V13_LIBRETRO, - - V5 = 800, - V6 = 801, - V7 = 802, - V8 = 803, - V9 = 804, - V10 = 805, - V11 = 806, - V12 = 807, - V13 = 808, - V14 = 809, - V15 = 810, - V16 = 811, - V17 = 812, - V18 = 813, - V19 = 814, - V20 = 815, - V21 = 816, - V22 = 817, - VCUR_FLYCAST = V22, -}; +class Serializer; +class Deserializer; diff --git a/shell/libretro/libretro.cpp b/shell/libretro/libretro.cpp index bec1332a4..a9651ca5f 100644 --- a/shell/libretro/libretro.cpp +++ b/shell/libretro/libretro.cpp @@ -1739,14 +1739,11 @@ size_t retro_serialize_size() emu.stop(); - unsigned int total_size = 0; - void *data = nullptr; - - dc_serialize(&data, &total_size); - + Serializer ser; + dc_serialize(ser); emu.start(); - return total_size; + return ser.size(); } bool retro_serialize(void *data, size_t size) @@ -1756,12 +1753,11 @@ bool retro_serialize(void *data, size_t size) emu.stop(); - unsigned int total_size = 0; - bool result = dc_serialize(&data, &total_size); - + Serializer ser(data, size); + dc_serialize(ser); emu.start(); - return result; + return true; } bool retro_unserialize(const void * data, size_t size) @@ -1771,11 +1767,16 @@ bool retro_unserialize(const void * data, size_t size) emu.stop(); - bool result = dc_loadstate(&data, size); + try { + Deserializer deser(data, size); + dc_loadstate(deser); + emu.start(); - emu.start(); - - return result; + return true; + } catch (const Deserializer::Exception& e) { + ERROR_LOG(SAVESTATE, "Loading state failed: %s", e.what()); + return false; + } } // Cheats diff --git a/tests/src/serialize_test.cpp b/tests/src/serialize_test.cpp index c0e8cb058..b086374a7 100644 --- a/tests/src/serialize_test.cpp +++ b/tests/src/serialize_test.cpp @@ -28,10 +28,10 @@ TEST_F(SerializeTest, SizeTest) MapleExpansionDevices[1][1] = MDT_SegaVMU; mcfg_CreateDevices(); - unsigned int total_size = 0; - void *data = nullptr; - ASSERT_TRUE(dc_serialize(&data, &total_size)); - ASSERT_EQ(28192092u, total_size); + std::vector data(30000000); + Serializer ser(data.data(), data.size()); + dc_serialize(ser); + ASSERT_EQ(28191583u, ser.size()); }