New serialize framework. Delay maple dma xfer

New serialize framework. Refactor serialization into modules.
Maple dma xfer must not be executed immediately. Delay until interrupt
is raised.
Fixes Geist Force freeze at start.
This commit is contained in:
Flyinghead 2021-11-13 15:56:42 +01:00
parent e56ecfec40
commit 8f80bcb159
54 changed files with 1863 additions and 1860 deletions

View File

@ -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

View File

@ -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 <chrono>
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;

View File

@ -26,17 +26,18 @@
#include <future>
#include <string>
#include <memory>
#include <utility>
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,

View File

@ -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
}
};

View File

@ -26,6 +26,7 @@
#include "oslib/audiostream.h"
#include "hw/gdrom/gdrom_if.h"
#include "cfg/option.h"
#include "serialize.h"
#include <algorithm>
#include <cmath>
@ -153,7 +154,17 @@ static void VolumePan(SampleType value, u32 vol, u32 pan, SampleType& outl, Samp
}
}
DSP_OUT_VOL_REG* dsp_out_vol;
template<typename T>
static void clip(T& v, T min, T max) {
v = std::min(max, std::max(min, v));
}
template<typename T>
static void clip16(T& v) {
clip<T>(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<u32>(); // channel.update_rate
channel.UpdatePitch();
deser >> channel.s0;
deser >> channel.s1;
deser >> channel.loop.looped;
if (old_format)
{
deser.skip<u32>(); // channel.loop.LSA
deser.skip<u32>(); // 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<u32>(); // channel.VolMix.DLAtt
deser.skip<u32>(); // channel.VolMix.DRAtt
deser.skip<u32>(); // channel.VolMix.DSPAtt
}
channel.UpdateAtts();
if (old_format)
deser.skip<u32>(); // channel.VolMix.DSPOut
channel.UpdateDSPMIX();
deser >> channel.AEG.val;
deser >> channel.AEG.state;
channel.SetAegState(channel.AEG.state);
if (old_format)
{
deser.skip<u32>(); // channel.AEG.AttackRate
deser.skip<u32>(); // channel.AEG.Decay1Rate
deser.skip<u32>(); // channel.AEG.Decay2Rate
deser.skip<u32>(); // channel.AEG.Decay2Value
deser.skip<u32>(); // 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<u8>(); // channel.step_stream_lut1
deser.skip<u8>(); // channel.step_stream_lut2
deser.skip<u8>(); // channel.step_stream_lut3
}
channel.UpdateStreamStep();
deser >> channel.lfo.counter;
if (old_format)
deser.skip<u32>(); // channel.lfo.start_value
deser >> channel.lfo.state;
if (old_format)
{
deser.skip<u8>(); // channel.lfo.alfo
deser.skip<u8>(); // channel.lfo.alfo_shft
deser.skip<u8>(); // channel.lfo.plfo
deser.skip<u8>(); // channel.lfo.plfo_shft
deser.skip<u8>(); // channel.lfo.alfo_calc_lut
deser.skip<u8>(); // channel.lfo.plfo_calc_lut
}
channel.UpdateLFO(true);
deser >> channel.enabled;
if (old_format)
deser.skip<u32>(); // 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
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -50,6 +50,7 @@
/* For crc32 */
#include <zlib.h>
#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;
}

View File

@ -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);

View File

@ -5,6 +5,7 @@
#pragma once
#include <cmath>
#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)

View File

@ -25,3 +25,8 @@ enum DiscType
Open=0x2, //tray is open :)
};
namespace gdrom
{
void serialize(Serializer& ser);
void deserialize(Deserializer& deser);
}

View File

@ -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<u32>(); // GDROM_TICK
}
}

View File

@ -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;

View File

@ -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<std::pair<u32, std::vector<u32>>> 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<bool>(); // 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<u32>(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));
}

View File

@ -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);

View File

@ -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;

View File

@ -5,6 +5,7 @@
#include "maple_helper.h"
#include <cmath>
#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<std::unique_ptr<jvs_io_board>> 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;
};

View File

@ -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<std::pair<u32, std::vector<u32>>> 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<u32>(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<u32>(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;
}

View File

@ -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<jvs_837_13844_wrungp>(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;
}

View File

@ -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;
}
}

View File

@ -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);

View File

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

View File

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

View File

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

View File

@ -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; }

View File

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

View File

@ -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; }

View File

@ -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<u32>(); // naomi_updates
deser.skip<u32>(); // 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<u8>();
else if (deser.version() >= Deserializer::V14)
deser >> aw_maple_devs;
if (deser.version() >= Deserializer::V20)
{
deser >> coin_chute_time;
deser >> aw_ram_test_skipped;
}
}

View File

@ -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);

View File

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

View File

@ -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;

View File

@ -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;

View File

@ -7,6 +7,7 @@
#include "cfg/option.h"
#include "network/ggpo.h"
#include "emulator.h"
#include "serialize.h"
#include <mutex>
#include <zlib.h>
@ -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()

View File

@ -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();
///////

View File

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

141
core/hw/pvr/pvr.cpp Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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<u32>(); // FrameCount
deser.skip<bool>(); // pend_rend
}
YUV_deserialize(deser);
if (deser.version() >= Deserializer::V5_LIBRETRO && deser.version() < Deserializer::V9_LIBRETRO)
deser.skip<bool>(); // 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<bool>(); // 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<bool>(); // 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;
}
}

32
core/hw/pvr/pvr.h Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
namespace pvr
{
void init();
void term();
void reset(bool hard);
void serialize(Serializer& ser);
void deserialize(Deserializer& deser);
}

View File

@ -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;
}

View File

@ -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<typename T> T DYNACALL pvr_read32p(u32 addr);

View File

@ -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<double>(); // speed_load_mspdf
deser.skip<u32>(); // mips_counter
deser.skip<double>(); // full_rps
if (deser.version() <= Deserializer::V4)
deser.skip<u32>(); // 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();

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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;

File diff suppressed because it is too large Load Diff

212
core/serialize.h Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
#include <limits>
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<typename T>
void deserialize(T& obj)
{
doDeserialize(&obj, sizeof(T));
}
template<typename T>
void deserialize(T *obj, size_t count)
{
doDeserialize(obj, sizeof(T) * count);
}
template<typename T>
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<size_t>::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<typename T>
void serialize(const T& obj)
{
doSerialize(&obj, sizeof(T));
}
template<typename T>
void serialize(const T *obj, size_t count)
{
doSerialize(obj, sizeof(T) * count);
}
template<typename T>
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<typename T>
Serializer& operator<<(Serializer& ctx, const T& obj) {
ctx.serialize(obj);
return ctx;
}
template<typename T>
Deserializer& operator>>(Deserializer& ctx, T& obj) {
ctx.deserialize(obj);
return ctx;
}
void dc_serialize(Serializer& ctx);
void dc_deserialize(Deserializer& ctx);

View File

@ -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;

View File

@ -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

View File

@ -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<char> data(30000000);
Serializer ser(data.data(), data.size());
dc_serialize(ser);
ASSERT_EQ(28191583u, ser.size());
}