From 04c418d02a4720ffd788552505fdfb7ce7bfcbc1 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 31 Jan 2023 10:13:03 +0100 Subject: [PATCH] serialize: move code out of serialize.cpp and into modules --- core/hw/aica/aica_if.h | 2 + core/hw/holly/sb.cpp | 28 ++ core/hw/holly/sb.h | 2 + core/hw/modem/modem.cpp | 6 +- core/hw/sh4/modules/modules.h | 2 + core/hw/sh4/modules/tmu.cpp | 34 ++- core/hw/sh4/sh4_interrupts.cpp | 23 ++ core/hw/sh4/sh4_interrupts.h | 2 + core/hw/sh4/sh4_mmr.cpp | 150 +++++++++- core/hw/sh4/sh4_mmr.h | 10 + core/hw/sh4/sh4_sched.cpp | 91 +++++- core/hw/sh4/sh4_sched.h | 11 +- core/serialize.cpp | 501 +-------------------------------- core/serialize.h | 24 +- tests/src/serialize_test.cpp | 2 +- 15 files changed, 379 insertions(+), 509 deletions(-) diff --git a/core/hw/aica/aica_if.h b/core/hw/aica/aica_if.h index 1662c7e9c..63fdbdce3 100644 --- a/core/hw/aica/aica_if.h +++ b/core/hw/aica/aica_if.h @@ -2,6 +2,8 @@ #include "types.h" #include "stdclass.h" +extern u32 SB_ADST; + namespace aica { diff --git a/core/hw/holly/sb.cpp b/core/hw/holly/sb.cpp index 86d82f26d..96c433d44 100644 --- a/core/hw/holly/sb.cpp +++ b/core/hw/holly/sb.cpp @@ -13,6 +13,7 @@ #include "hw/pvr/pvr_sb_regs.h" #include "emulator.h" #include "hw/bba/bba.h" +#include "serialize.h" std::array sb_regs; @@ -752,3 +753,30 @@ void sb_Term() naomi_reg_Term(); asic_reg_Term(); } + +void sb_serialize(Serializer& ser) +{ + register_serialize(sb_regs, ser); + ser << SB_ISTNRM; + ser << SB_ISTNRM1; + ser << SB_ADST; +} + +void sb_deserialize(Deserializer& deser) +{ + register_deserialize(sb_regs, deser); + deser >> SB_ISTNRM; + if (deser.version() >= Deserializer::V24) + deser >> SB_ISTNRM1; + else + SB_ISTNRM1 = 0; + if (deser.version() < Deserializer::V30) + { + deser.skip(); // SB_FFST_rc; + deser.skip(); // SB_FFST; + } + if (deser.version() >= Deserializer::V15) + deser >> SB_ADST; + else + SB_ADST = 0; +} diff --git a/core/hw/holly/sb.h b/core/hw/holly/sb.h index 137fd0a8e..8dfffa412 100644 --- a/core/hw/holly/sb.h +++ b/core/hw/holly/sb.h @@ -12,6 +12,8 @@ void sb_WriteMem(u32 addr, u32 data); void sb_Init(); void sb_Reset(bool hard); void sb_Term(); +void sb_serialize(Serializer& ser); +void sb_deserialize(Deserializer& deser); extern std::array sb_regs; diff --git a/core/hw/modem/modem.cpp b/core/hw/modem/modem.cpp index ac206f188..5ea4bfcae 100644 --- a/core/hw/modem/modem.cpp +++ b/core/hw/modem/modem.cpp @@ -27,6 +27,7 @@ #include "hw/sh4/sh4_sched.h" #include "network/picoppp.h" #include "serialize.h" +#include "cfg/option.h" #ifndef NDEBUG #include "oslib/oslib.h" @@ -53,7 +54,7 @@ static modemreg_t modem_regs; static u8 dspram[0x1000]; -int modem_sched; +static int modem_sched; enum ModemStates { @@ -753,6 +754,7 @@ void ModemWriteMem_A0_006(u32 addr, u32 data, u32 size) void ModemSerialize(Serializer& ser) { + sh4_sched_serialize(ser, modem_sched); ser << modem_regs; ser << dspram; ser << state; @@ -762,6 +764,8 @@ void ModemSerialize(Serializer& ser) } void ModemDeserialize(Deserializer& deser) { + if (!config::EmulateBBA || deser.version() > Deserializer::V31) + sh4_sched_deserialize(deser, modem_sched); if (deser.version() >= Deserializer::V20) { deser >> modem_regs; diff --git a/core/hw/sh4/modules/modules.h b/core/hw/sh4/modules/modules.h index 5214ead88..0b6e97d44 100644 --- a/core/hw/sh4/modules/modules.h +++ b/core/hw/sh4/modules/modules.h @@ -43,6 +43,8 @@ void ubc_term(); void tmu_init(); void tmu_reset(bool hard); void tmu_term(); +void tmu_serialize(Serializer& ser); +void tmu_deserialize(Deserializer& deser); void ccn_init(); void ccn_reset(bool hard); diff --git a/core/hw/sh4/modules/tmu.cpp b/core/hw/sh4/modules/tmu.cpp index cc53bacba..519d2e9b6 100644 --- a/core/hw/sh4/modules/tmu.cpp +++ b/core/hw/sh4/modules/tmu.cpp @@ -6,16 +6,16 @@ #include "hw/sh4/sh4_sched.h" #include "hw/sh4/sh4_interrupts.h" #include "hw/sh4/sh4_mmr.h" - +#include "serialize.h" #define tmu_underflow 0x0100 #define tmu_UNIE 0x0020 -u32 tmu_shift[3]; -u32 tmu_mask[3]; -u64 tmu_mask64[3]; +static u32 tmu_shift[3]; +static u32 tmu_mask[3]; +static u64 tmu_mask64[3]; -u32 old_mode[3] = { 0xFFFF, 0xFFFF, 0xFFFF}; +static u32 old_mode[3] = { 0xFFFF, 0xFFFF, 0xFFFF}; static const InterruptID tmu_intID[3] = { sh4_TMU0_TUNI0, sh4_TMU1_TUNI1, sh4_TMU2_TUNI2 }; int tmu_sched[3]; @@ -73,8 +73,8 @@ void UpdateTMU_i(u32 Cycles) } #endif -u32 tmu_ch_base[3]; -u64 tmu_ch_base64[3]; +static u32 tmu_ch_base[3]; +static u64 tmu_ch_base64[3]; static u32 read_TMU_TCNTch(u32 ch) { @@ -328,3 +328,23 @@ void tmu_term() sched_id = -1; } } + +void tmu_serialize(Serializer& ser) +{ + ser << tmu_shift; + ser << tmu_mask; + ser << tmu_mask64; + ser << old_mode; + ser << tmu_ch_base; + ser << tmu_ch_base64; +} + +void tmu_deserialize(Deserializer& deser) +{ + deser >> tmu_shift; + deser >> tmu_mask; + deser >> tmu_mask64; + deser >> old_mode; + deser >> tmu_ch_base; + deser >> tmu_ch_base64; +} diff --git a/core/hw/sh4/sh4_interrupts.cpp b/core/hw/sh4/sh4_interrupts.cpp index 0fdc62019..ee6c9066e 100644 --- a/core/hw/sh4/sh4_interrupts.cpp +++ b/core/hw/sh4/sh4_interrupts.cpp @@ -15,6 +15,7 @@ #include "sh4_mmr.h" #include "oslib/oslib.h" #include "debug/gdb_server.h" +#include "serialize.h" #include //these are fixed @@ -241,3 +242,25 @@ void interrupts_term() { } +void interrupts_serialize(Serializer& ser) +{ + ser << InterruptEnvId; + ser << InterruptBit; + ser << InterruptLevelBit; + ser << interrupt_vpend; + ser << interrupt_vmask; + ser << decoded_srimask; + +} + +void interrupts_deserialize(Deserializer& deser) +{ + if (deser.version() < Deserializer::V9_LIBRETRO) + deser.skip(2); + deser >> InterruptEnvId; + deser >> InterruptBit; + deser >> InterruptLevelBit; + deser >> interrupt_vpend; + deser >> interrupt_vmask; + deser >> decoded_srimask; +} diff --git a/core/hw/sh4/sh4_interrupts.h b/core/hw/sh4/sh4_interrupts.h index 0bbf879a0..f4718e46c 100644 --- a/core/hw/sh4/sh4_interrupts.h +++ b/core/hw/sh4/sh4_interrupts.h @@ -97,3 +97,5 @@ void SIIDRebuild(); void interrupts_init(); void interrupts_reset(); void interrupts_term(); +void interrupts_serialize(Serializer& ser); +void interrupts_deserialize(Deserializer& deser); diff --git a/core/hw/sh4/sh4_mmr.cpp b/core/hw/sh4/sh4_mmr.cpp index 6fb56bb58..02423e963 100644 --- a/core/hw/sh4/sh4_mmr.cpp +++ b/core/hw/sh4/sh4_mmr.cpp @@ -9,13 +9,17 @@ #include "modules/ccn.h" #include "modules/modules.h" #include "sh4_cache.h" +#include "serialize.h" +#include "sh4_interrupts.h" +#include "sh4_sched.h" +#include "sh4_interpreter.h" #include #include //64bytes of sq // now on context ~ -std::array OnChipRAM; +static std::array OnChipRAM; //All registers are 4 byte aligned @@ -903,3 +907,147 @@ void map_p4() addrspace::mapHandler(p4mmr_handler, 0xFF, 0xFF); } + +namespace sh4 +{ + +void serialize(Serializer& ser) +{ + ser << OnChipRAM; + + 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); + + if (!ser.rollback()) + mem_b.serialize(ser); + + interrupts_serialize(ser); + + ser << (*p_sh4rcb).sq_buffer; + + ser << (*p_sh4rcb).cntx; + + sh4_sched_serialize(ser); +} + +void deserialize(Deserializer& deser) +{ + deser >> OnChipRAM; + + 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 + // Note (lr): was added in V11 fa49de29 24/12/2020 but ver not updated until V12 (13/4/2021) + || (deser.version() >= Deserializer::V11_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO)) + icache.Deserialize(deser); + else + icache.Reset(true); + if (deser.version() >= Deserializer::V10 + // Note (lr): was added in V11 2eb66879 27/12/2020 but ver not updated until V12 (13/4/2021) + || (deser.version() >= Deserializer::V11_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO)) + ocache.Deserialize(deser); + else + ocache.Reset(true); + + if (!deser.rollback()) + mem_b.deserialize(deser); + + interrupts_deserialize(deser); + + if (deser.version() <= Deserializer::V31) + deser.skip(); // do_sqw index + CCN_QACR_write<0>(0, CCN_QACR0.reg_data); + CCN_QACR_write<1>(0, CCN_QACR1.reg_data); + + deser >> (*p_sh4rcb).sq_buffer; + + deser >> (*p_sh4rcb).cntx; + if (deser.version() < Deserializer::V9_LIBRETRO) + { + deser.skip(); // old_rm + deser.skip(); // old_dn + } + if (deser.version() >= Deserializer::V19 && deser.version() < Deserializer::V21) + deser.skip(); // sh4InterpCycles + if (deser.version() < Deserializer::V21) + p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE; + + sh4_sched_deserialize(deser); +} + +void serialize2(Serializer& ser) +{ + ser << SCIF_SCFSR2; + ser << SCIF_SCSCR2; + ser << BSC_PDTRA; + + tmu_serialize(ser); + + ser << CCN_QACR_TR; // FIXME this is set in CCN_QACR_write<>() above, so useless. And it's really a cached thing + + ser << UTLB; + ser << ITLB; + ser << sq_remap; +} + +void deserialize2(Deserializer& deser) +{ + deser >> SCIF_SCFSR2; + if (deser.version() < Deserializer::V9_LIBRETRO + || (deser.version() >= Deserializer::V5 && deser.version() < Deserializer::V8)) + { + deser.skip(); // SCIF_SCFRDR2 + deser.skip(); // SCIF_SCFDR2 + } + else if ((deser.version() >= Deserializer::V11_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO) + || deser.version() >= Deserializer::V11) + deser >> SCIF_SCSCR2; + deser >> BSC_PDTRA; + + tmu_deserialize(deser); + + deser >> CCN_QACR_TR; + + if (deser.version() < Deserializer::V6_LIBRETRO) + { + for (int i = 0; i < 64; i++) + { + deser >> UTLB[i].Address; + deser >> UTLB[i].Data; + } + for (int i = 0; i < 4; i++) + { + deser >> ITLB[i].Address; + deser >> ITLB[i].Data; + } + } + else + { + deser >> UTLB; + deser >> ITLB; + } + if (deser.version() >= Deserializer::V11 + || (deser.version() >= Deserializer::V11_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO)) + deser >> sq_remap; + deser.skip(64 * 4, Deserializer::V23); // ITLB_LRU_USE +} + +} //namespace sh4 diff --git a/core/hw/sh4/sh4_mmr.h b/core/hw/sh4/sh4_mmr.h index 0c3559065..f65f99d0a 100644 --- a/core/hw/sh4/sh4_mmr.h +++ b/core/hw/sh4/sh4_mmr.h @@ -28,6 +28,16 @@ void sh4_mmr_init(); void sh4_mmr_reset(bool hard); void sh4_mmr_term(); +namespace sh4 +{ + +void serialize(Serializer& ser); +void deserialize(Deserializer& deser); +void serialize2(Serializer& ser); +void deserialize2(Deserializer& deser); + +} + void sh4_rio_reg(RegisterStruct *arr, u32 addr, RegIO flags, RegReadAddrFP *rf = nullptr, RegWriteAddrFP *wf = nullptr); #define SH4IO_REGN(mod, addr) ((mod)[((addr) & 255) / 4].data32) diff --git a/core/hw/sh4/sh4_sched.cpp b/core/hw/sh4/sh4_sched.cpp index e89c27dd2..f91d0e502 100755 --- a/core/hw/sh4/sh4_sched.cpp +++ b/core/hw/sh4/sh4_sched.cpp @@ -1,6 +1,7 @@ #include "types.h" #include "sh4_if.h" #include "sh4_sched.h" +#include "serialize.h" #include #include @@ -20,10 +21,17 @@ sh4_sched_now() */ +struct sched_list +{ + sh4_sched_callback* cb; + int tag; + int start; + int end; +}; -u64 sh4_sched_ffb; -std::vector sch_list; -int sh4_sched_next_id = -1; +static u64 sh4_sched_ffb; +static std::vector sch_list; +static int sh4_sched_next_id = -1; static u32 sh4_sched_now(); @@ -184,3 +192,80 @@ void sh4_sched_reset(bool hard) Sh4cntx.sh4_sched_next = 0; } } + +void sh4_sched_serialize(Serializer& ser, int id) +{ + ser << sch_list[id].tag; + ser << sch_list[id].start; + ser << sch_list[id].end; +} + +void sh4_sched_deserialize(Deserializer& deser, int id) +{ + deser >> sch_list[id].tag; + deser >> sch_list[id].start; + deser >> sch_list[id].end; +} + +// FIXME modules should save their scheduling data so that it doesn't depend on their scheduler id +namespace aica +{ +// hw/aica/aica.cpp +extern int aica_schid; +extern int rtc_schid; +// hw/aica/aica_if.cpp +extern int dma_sched_id; +} +// hw/gdrom/gdromv3.cpp +extern int gdrom_schid; +// hw/maple/maple_if.cpp +extern int maple_schid; +// hw/pvr/spg.cpp +extern int render_end_schid; +extern int vblank_schid; +// hw/sh4/modules/tmu.cpp +extern int tmu_sched[3]; + +void sh4_sched_serialize(Serializer& ser) +{ + ser << sh4_sched_ffb; + + sh4_sched_serialize(ser, aica::aica_schid); + sh4_sched_serialize(ser, aica::rtc_schid); + sh4_sched_serialize(ser, gdrom_schid); + sh4_sched_serialize(ser, maple_schid); + sh4_sched_serialize(ser, aica::dma_sched_id); + for (int id : tmu_sched) + sh4_sched_serialize(ser, id); + sh4_sched_serialize(ser, render_end_schid); + sh4_sched_serialize(ser, vblank_schid); +} + +void sh4_sched_deserialize(Deserializer& deser) +{ + deser >> sh4_sched_ffb; + + if (deser.version() >= Deserializer::V19 && deser.version() <= Deserializer::V31) + deser.skip(); // sh4_sched_next_id + else if ((deser.version() >= Deserializer::V5 && deser.version() < Deserializer::V8) + || deser.version() < Deserializer::V9_LIBRETRO) + deser.skip(); // sh4_sched_intr + + sh4_sched_deserialize(deser, aica::aica_schid); + sh4_sched_deserialize(deser, aica::rtc_schid); + sh4_sched_deserialize(deser, gdrom_schid); + sh4_sched_deserialize(deser, maple_schid); + sh4_sched_deserialize(deser, aica::dma_sched_id); + for (int id : tmu_sched) + sh4_sched_deserialize(deser, id); + sh4_sched_deserialize(deser, render_end_schid); + sh4_sched_deserialize(deser, vblank_schid); + + if ((deser.version() >= Deserializer::V5 && deser.version() < Deserializer::V8) + || deser.version() < Deserializer::V9_LIBRETRO) + { + deser.skip(); // sch_list[time_sync].tag + deser.skip(); // sch_list[time_sync].start + deser.skip(); // sch_list[time_sync].end + } +} diff --git a/core/hw/sh4/sh4_sched.h b/core/hw/sh4/sh4_sched.h index 1625beb2f..b7d146352 100644 --- a/core/hw/sh4/sh4_sched.h +++ b/core/hw/sh4/sh4_sched.h @@ -44,12 +44,9 @@ void sh4_sched_tick(int cycles); void sh4_sched_ffts(); void sh4_sched_reset(bool hard); -struct sched_list -{ - sh4_sched_callback* cb; - int tag; - int start; - int end; -}; +void sh4_sched_serialize(Serializer& ser); +void sh4_sched_deserialize(Deserializer& deser); +void sh4_sched_serialize(Serializer& ser, int id); +void sh4_sched_deserialize(Deserializer& deser, int id); #endif //SH4_SCHED_H diff --git a/core/serialize.cpp b/core/serialize.cpp index eba91da89..b5ebbd77c 100644 --- a/core/serialize.cpp +++ b/core/serialize.cpp @@ -8,131 +8,23 @@ #include "hw/maple/maple_cfg.h" #include "hw/modem/modem.h" #include "hw/pvr/pvr.h" -#include "hw/pvr/pvr_mem.h" #include "hw/sh4/sh4_sched.h" #include "hw/sh4/sh4_mmr.h" -#include "hw/sh4/modules/mmu.h" #include "reios/gdrom_hle.h" #include "hw/naomi/naomi.h" #include "hw/naomi/naomi_cart.h" -#include "hw/sh4/sh4_cache.h" -#include "hw/sh4/sh4_interpreter.h" #include "hw/bba/bba.h" #include "cfg/option.h" -#include -#include - -namespace aica -{ - -//./core/hw/aica/aica.o -extern int aica_schid; -extern int rtc_schid; - -//./core/hw/aica/aica_if.o -extern int dma_sched_id; - -} -extern u32 SB_ADST; - -//./core/hw/gdrom/gdromv3.o -extern int gdrom_schid; - -//./core/hw/maple/maple_if.o -extern int maple_schid; - -//./core/hw/modem/modem.cpp -extern int modem_sched; - -//./core/hw/pvr/spg.o -extern int render_end_schid; -extern int vblank_schid; - -//./core/hw/sh4/sh4_mmr.o -extern std::array OnChipRAM; - -//./core/hw/sh4/sh4_mem.o -extern RamRegion mem_b; - -//./core/hw/sh4/sh4_interrupts.o -alignas(64) extern Sh4ExceptionCode InterruptEnvId[32]; -alignas(64) extern u32 InterruptBit[32]; -alignas(64) extern u32 InterruptLevelBit[16]; -extern u32 interrupt_vpend; // Vector of pending interrupts -extern u32 interrupt_vmask; // Vector of masked interrupts (-1 inhibits all interrupts) -extern u32 decoded_srimask; // Vector of interrupts allowed by SR.IMSK (-1 inhibits all interrupts) - -//./core/hw/sh4/sh4_core_regs.o -extern Sh4RCB* p_sh4rcb; - -//./core/hw/sh4/sh4_sched.o -extern u64 sh4_sched_ffb; -extern std::vector sch_list; -extern int sh4_sched_next_id; - -//./core/hw/sh4/modules/serial.o -extern SCIF_SCFSR2_type SCIF_SCFSR2; -extern SCIF_SCSCR2_type SCIF_SCSCR2; - -//./core/hw/sh4/modules/bsc.o -extern BSC_PDTRA_type BSC_PDTRA; - -//./core/hw/sh4/modules/tmu.o -extern u32 tmu_shift[3]; -extern u32 tmu_mask[3]; -extern u64 tmu_mask64[3]; -extern u32 old_mode[3]; -extern int tmu_sched[3]; -extern u32 tmu_ch_base[3]; -extern u64 tmu_ch_base64[3]; - -//./core/hw/sh4/modules/ccn.o -extern u32 CCN_QACR_TR[2]; - -//./core/hw/sh4/modules/mmu.o -extern TLB_Entry UTLB[64]; -extern TLB_Entry ITLB[4]; -extern u32 sq_remap[64]; - //./core/imgread/common.o extern u32 NullDriveDiscType; extern u8 q_subchannel[96]; -template -void register_serialize(const T& regs, Serializer& ser) -{ - for (const auto& reg : regs) - ser << reg.data32; -} -template -void register_deserialize(T& regs, Deserializer& deser) -{ - for (auto& reg : regs) - { - if (deser.version() < Deserializer::V5) - deser.skip(); // regs.data[i].flags - if (!(reg.flags & REG_RF)) - deser >> reg.data32; - else - deser.skip(); - } -} - -static const std::array getSchedulerIds() { - return { aica::aica_schid, aica::rtc_schid, gdrom_schid, maple_schid, aica::dma_sched_id, - tmu_sched[0], tmu_sched[1], tmu_sched[2], render_end_schid, vblank_schid, - modem_sched }; -} - void dc_serialize(Serializer& ser) { aica::serialize(ser); - register_serialize(sb_regs, ser); - ser << SB_ISTNRM; - ser << SB_ISTNRM1; - ser << SB_ADST; + sb_serialize(ser); nvmem::serialize(ser); @@ -142,93 +34,14 @@ void dc_serialize(Serializer& ser) pvr::serialize(ser); - ser << OnChipRAM; - - 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); - - if (!ser.rollback()) - mem_b.serialize(ser); - - ser << InterruptEnvId; - ser << InterruptBit; - ser << InterruptLevelBit; - ser << interrupt_vpend; - ser << interrupt_vmask; - ser << decoded_srimask; - - - //default to nommu_full - int i = 3; - if ( do_sqw_nommu == &do_sqw_nommu_area_3) - i = 0; - else if (do_sqw_nommu == &do_sqw_nommu_area_3_nonvmem) - i = 1; - else if (do_sqw_nommu == &TAWriteSQ) - i = 2; - else if (do_sqw_nommu==&do_sqw_nommu_full) - i = 3; - ser << i; - - ser << (*p_sh4rcb).sq_buffer; - - ser << (*p_sh4rcb).cntx; - - ser << sh4_sched_ffb; - std::array schedIds = getSchedulerIds(); - if (sh4_sched_next_id == -1) - ser << sh4_sched_next_id; - else - for (u32 i = 0; i < schedIds.size(); i++) - if (schedIds[i] == sh4_sched_next_id) - ser << i; - - for (u32 i = 0; i < schedIds.size() - 1; i++) - { - ser << sch_list[schedIds[i]].tag; - ser << sch_list[schedIds[i]].start; - ser << sch_list[schedIds[i]].end; - } + sh4::serialize(ser); ser << config::EmulateBBA.get(); if (config::EmulateBBA) - { bba_Serialize(ser); - } - else - { - ser << sch_list[modem_sched].tag; - ser << sch_list[modem_sched].start; - ser << sch_list[modem_sched].end; - } ModemSerialize(ser); - ser << SCIF_SCFSR2; - ser << SCIF_SCSCR2; - ser << BSC_PDTRA; - - ser << tmu_shift; - ser << tmu_mask; - ser << tmu_mask64; - ser << old_mode; - ser << tmu_ch_base; - ser << tmu_ch_base64; - - ser << CCN_QACR_TR; - - ser << UTLB; - ser << ITLB; - ser << sq_remap; + sh4::serialize2(ser); ser << NullDriveDiscType; ser << q_subchannel; @@ -251,11 +64,7 @@ static void dc_deserialize_libretro(Deserializer& deser) { aica::deserialize(deser); - register_deserialize(sb_regs, deser); - deser >> SB_ISTNRM; - deser.skip(); // SB_FFST_rc; - deser.skip(); // SB_FFST; - SB_ADST = 0; + sb_deserialize(deser); nvmem::deserialize(deser); @@ -265,162 +74,15 @@ static void dc_deserialize_libretro(Deserializer& deser) pvr::deserialize(deser); - deser >> OnChipRAM; - - 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 (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); - - mem_b.deserialize(deser); - if (deser.version() < Deserializer::V9_LIBRETRO) - deser.skip(); - deser >> InterruptEnvId; - deser >> InterruptBit; - deser >> InterruptLevelBit; - deser >> interrupt_vpend; - deser >> interrupt_vmask; - deser >> decoded_srimask; - - int i; - deser >> i; - switch (i) - { - case 0: - case 1: - if (addrspace::virtmemEnabled()) - do_sqw_nommu = &do_sqw_nommu_area_3; - else - do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem; - break; - case 2: - do_sqw_nommu = &TAWriteSQ; - break; - case 3: - do_sqw_nommu = &do_sqw_nommu_full; - break; - default: - throw Deserializer::Exception("Invalid SQ handler index"); - } - - deser >> (*p_sh4rcb).sq_buffer; - - deser >> (*p_sh4rcb).cntx; - p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE; - - if (deser.version() < Deserializer::V9_LIBRETRO) - { - deser.skip(); // old_rm - deser.skip(); // old_dn - } - - deser >> sh4_sched_ffb; - if (deser.version() < Deserializer::V9_LIBRETRO) - deser.skip(); // sh4_sched_intr - - deser >> sch_list[aica::aica_schid].tag; - deser >> sch_list[aica::aica_schid].start; - deser >> sch_list[aica::aica_schid].end; - - deser >> sch_list[aica::rtc_schid].tag; - deser >> sch_list[aica::rtc_schid].start; - deser >> sch_list[aica::rtc_schid].end; - - deser >> sch_list[gdrom_schid].tag; - deser >> sch_list[gdrom_schid].start; - deser >> sch_list[gdrom_schid].end; - - deser >> sch_list[maple_schid].tag; - deser >> sch_list[maple_schid].start; - deser >> sch_list[maple_schid].end; - - deser >> sch_list[aica::dma_sched_id].tag; - deser >> sch_list[aica::dma_sched_id].start; - deser >> sch_list[aica::dma_sched_id].end; - - for (int i = 0; i < 3; i++) - { - deser >> sch_list[tmu_sched[i]].tag; - deser >> sch_list[tmu_sched[i]].start; - deser >> sch_list[tmu_sched[i]].end; - } - - deser >> sch_list[render_end_schid].tag; - deser >> sch_list[render_end_schid].start; - deser >> sch_list[render_end_schid].end; - - deser >> sch_list[vblank_schid].tag; - deser >> sch_list[vblank_schid].start; - deser >> sch_list[vblank_schid].end; - - if (deser.version() < Deserializer::V9_LIBRETRO) - { - deser.skip(); // sch_list[time_sync].tag - deser.skip(); // sch_list[time_sync].start - deser.skip(); // sch_list[time_sync].end - } + sh4::deserialize(deser); if (deser.version() >= Deserializer::V13_LIBRETRO) deser.skip(); // settings.network.EmulateBBA + config::EmulateBBA.override(false); - deser >> sch_list[modem_sched].tag; - deser >> sch_list[modem_sched].start; - deser >> sch_list[modem_sched].end; + ModemDeserialize(deser); - deser >> SCIF_SCFSR2; - if (deser.version() < Deserializer::V9_LIBRETRO) - { - deser.skip(1); // SCIF_SCFRDR2 - deser.skip(4); // SCIF_SCFDR2 - } - else if (deser.version() >= Deserializer::V11_LIBRETRO) - deser >> SCIF_SCSCR2; - deser >> BSC_PDTRA; - - deser >> tmu_shift; - deser >> tmu_mask; - deser >> tmu_mask64; - deser >> old_mode; - deser >> tmu_ch_base; - deser >> tmu_ch_base64; - - deser >> CCN_QACR_TR; - - if (deser.version() < Deserializer::V6_LIBRETRO) - { - for (int i = 0; i < 64; i++) - { - deser >> UTLB[i].Address; - deser >> UTLB[i].Data; - } - for (int i = 0; i < 4; i++) - { - deser >> ITLB[i].Address; - deser >> ITLB[i].Data; - } - } - else - { - deser >> UTLB; - deser >> ITLB; - } - if (deser.version() >= Deserializer::V11_LIBRETRO) - deser >> sq_remap; - deser.skip(64 * 4); // ITLB_LRU_USE + sh4::deserialize2(deser); deser >> NullDriveDiscType; deser >> q_subchannel; @@ -468,7 +130,6 @@ static void dc_deserialize_libretro(Deserializer& deser) 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)", (u32)deser.size()); } @@ -478,27 +139,14 @@ void dc_deserialize(Deserializer& deser) if (deser.version() >= Deserializer::V5_LIBRETRO && deser.version() <= Deserializer::VLAST_LIBRETRO) { dc_deserialize_libretro(deser); + sh4_sched_ffts(); return; } DEBUG_LOG(SAVESTATE, "Loading state version %d", deser.version()); aica::deserialize(deser); - register_deserialize(sb_regs, deser); - deser >> SB_ISTNRM; - if (deser.version() >= Deserializer::V24) - deser >> SB_ISTNRM1; - else - SB_ISTNRM1 = 0; - if (deser.version() < Deserializer::V30) - { - deser.skip(); // SB_FFST_rc; - deser.skip(); // SB_FFST; - } - if (deser.version() >= Deserializer::V15) - deser >> SB_ADST; - else - SB_ADST = 0; + sb_deserialize(deser); nvmem::deserialize(deser); @@ -508,141 +156,17 @@ void dc_deserialize(Deserializer& deser) pvr::deserialize(deser); - deser >> OnChipRAM; - - 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 (deser.version() >= Deserializer::V10) - ocache.Deserialize(deser); - else - ocache.Reset(true); - - if (!deser.rollback()) - mem_b.deserialize(deser); - - if (deser.version() < Deserializer::V5) - deser.skip(2); - deser >> InterruptEnvId; - deser >> InterruptBit; - deser >> InterruptLevelBit; - deser >> interrupt_vpend; - deser >> interrupt_vmask; - deser >> decoded_srimask; - - int i; - deser >> i; - switch (i) - { - case 0: - case 1: - if (addrspace::virtmemEnabled()) - do_sqw_nommu = &do_sqw_nommu_area_3; - else - do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem; - break; - case 2: - do_sqw_nommu = &TAWriteSQ; - break; - case 3: - do_sqw_nommu = &do_sqw_nommu_full; - break; - default: - throw Deserializer::Exception("Invalid SQ handler index"); - } - - deser >> (*p_sh4rcb).sq_buffer; - - deser >> (*p_sh4rcb).cntx; - if (deser.version() < Deserializer::V5) - { - deser.skip(4); - deser.skip(4); - } - if (deser.version() >= Deserializer::V19 && deser.version() < Deserializer::V21) - deser.skip(); // sh4InterpCycles - if (deser.version() < Deserializer::V21) - p_sh4rcb->cntx.cycle_counter = SH4_TIMESLICE; - - deser >> sh4_sched_ffb; - std::array schedIds = getSchedulerIds(); - - if (deser.version() >= Deserializer::V19) - { - deser >> sh4_sched_next_id; - if (sh4_sched_next_id != -1) - sh4_sched_next_id = schedIds[sh4_sched_next_id]; - } - if (deser.version() < Deserializer::V8) - deser.skip(); // sh4_sched_intr - - for (u32 i = 0; i < schedIds.size() - 1; i++) - { - deser >> sch_list[schedIds[i]].tag; - deser >> sch_list[schedIds[i]].start; - deser >> sch_list[schedIds[i]].end; - } - - if (deser.version() < Deserializer::V8) - { - deser.skip(); // sch_list[time_sync].tag - deser.skip(); // sch_list[time_sync].start - deser.skip(); // sch_list[time_sync].end - } + sh4::deserialize(deser); if (deser.version() >= Deserializer::V13) deser >> config::EmulateBBA.get(); else config::EmulateBBA.override(false); if (config::EmulateBBA) - { bba_Deserialize(deser); - } - else - { - deser >> sch_list[modem_sched].tag; - deser >> sch_list[modem_sched].start; - deser >> sch_list[modem_sched].end; - } - if (deser.version() < Deserializer::V19) - sh4_sched_ffts(); ModemDeserialize(deser); - deser >> SCIF_SCFSR2; - if (deser.version() < Deserializer::V8) - { - deser.skip(); // SCIF_SCFRDR2 - deser.skip(); // SCIF_SCFDR2 - } - else if (deser.version() >= Deserializer::V11) - deser >> SCIF_SCSCR2; - deser >> BSC_PDTRA; - - deser >> tmu_shift; - deser >> tmu_mask; - deser >> tmu_mask64; - deser >> old_mode; - deser >> tmu_ch_base; - deser >> tmu_ch_base64; - - deser >> CCN_QACR_TR; - - deser >> UTLB; - deser >> ITLB; - if (deser.version() >= Deserializer::V11) - deser >> sq_remap; - deser.skip(64 * 4, Deserializer::V23); // ITLB_LRU_USE + sh4::deserialize2(deser); deser >> NullDriveDiscType; deser >> q_subchannel; @@ -683,6 +207,7 @@ void dc_deserialize(Deserializer& deser) CurrentCartridge->Deserialize(deser); if (deser.version() >= Deserializer::V6) gd_hle_state.Deserialize(deser); + sh4_sched_ffts(); DEBUG_LOG(SAVESTATE, "Loaded %d bytes", (u32)deser.size()); } diff --git a/core/serialize.h b/core/serialize.h index d85a85868..16d1cbbce 100644 --- a/core/serialize.h +++ b/core/serialize.h @@ -18,6 +18,7 @@ */ #pragma once #include "types.h" +#include "hw/hwreg.h" #include @@ -67,7 +68,8 @@ public: V29, V30, V31, - Current = V31, + V32, + Current = V32, Next = Current + 1, }; @@ -216,3 +218,23 @@ Deserializer& operator>>(Deserializer& ctx, T& obj) { void dc_serialize(Serializer& ctx); void dc_deserialize(Deserializer& ctx); + +template +void register_serialize(const T& regs, Serializer& ser) +{ + for (const auto& reg : regs) + ser << reg.data32; +} +template +void register_deserialize(T& regs, Deserializer& deser) +{ + for (auto& reg : regs) + { + if (deser.version() < Deserializer::V5) + deser.skip(); // regs.data[i].flags + if (!(reg.flags & REG_RF)) + deser >> reg.data32; + else + deser.skip(); + } +} diff --git a/tests/src/serialize_test.cpp b/tests/src/serialize_test.cpp index 95b2b22f9..3cdf9ec7c 100644 --- a/tests/src/serialize_test.cpp +++ b/tests/src/serialize_test.cpp @@ -32,7 +32,7 @@ TEST_F(SerializeTest, SizeTest) std::vector data(30000000); Serializer ser(data.data(), data.size()); dc_serialize(ser); - ASSERT_EQ(28191591u, ser.size()); + ASSERT_EQ(28191583u, ser.size()); }