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()); }