mirror of
https://github.com/libretro/parallel-dc.git
synced 2026-11-11 03:11:24 -10:00
retro_unserialize() receives the frontend buffer length but dc_unserialize()
only ever used it to disambiguate two legacy save-state versions, never to
bound the reads. ra_unserialize() did an unconditional memcpy from the input
cursor, so a truncated or malformed state (netplay peer, runahead, corrupt
file) walked straight off the end of the input buffer, and several length
fields taken verbatim from the state were used as memcpy destinations:
- UnserializeTAContext: 'size' copied into the fixed TA_DATA_SIZE buffer and
'render_pass_count' used to index the fixed render_passes[10] array.
- sys_nvmem_sram/flash: stored .size overwrote the live size and drove the
copy length into the fixed data[] allocation.
Track the input base/limit in dc_unserialize() and reject any read that would
run past the end, latching a failure that propagates to the retro_unserialize()
return value. Clamp the attacker-controlled TA size, render_pass_count, and
nvmem copy lengths to their real destination capacities. Legitimate states
round-trip byte-for-byte unchanged.
1207 lines
30 KiB
C++
1207 lines
30 KiB
C++
// serialize.cpp : save states
|
|
|
|
#include "types.h"
|
|
#include "hw/aica/dsp.h"
|
|
#include "hw/aica/aica.h"
|
|
#include "hw/aica/sgc_if.h"
|
|
#include "hw/arm7/arm7.h"
|
|
#include "hw/holly/sb_mem.h"
|
|
#include "hw/flashrom/flashrom.h"
|
|
#include "hw/mem/_vmem.h"
|
|
#include "hw/gdrom/gdromv3.h"
|
|
#include "hw/maple/maple_devs.h"
|
|
#include "hw/maple/maple_cfg.h"
|
|
#include "hw/pvr/Renderer_if.h"
|
|
#include "hw/pvr/ta_structs.h"
|
|
#include "hw/sh4/sh4_interrupts.h"
|
|
#include "hw/sh4/sh4_sched.h"
|
|
#include "hw/sh4/sh4_mmr.h"
|
|
#include "hw/sh4/modules/mmu.h"
|
|
#include "imgread/common.h"
|
|
#include "reios/reios.h"
|
|
#include "reios/gdrom_hle.h"
|
|
#include <map>
|
|
#include <set>
|
|
#include "rend/gles/gles.h"
|
|
#include "hw/sh4/dyna/blockmanager.h"
|
|
#include "hw/sh4/dyna/ngen.h"
|
|
#include "hw/naomi/naomi.h"
|
|
#include "hw/naomi/naomi_cart.h"
|
|
#include "hw/sh4/sh4_cache.h"
|
|
#include "hw/bba/bba.h"
|
|
|
|
#define LIBRETRO_SKIP(size) do { if (*data) *(u8**)data += (size); *total_size += (size); } while (false)
|
|
|
|
/*
|
|
* search for "maybe" to find items that were left out that may be needed
|
|
*/
|
|
|
|
//./core/hw/arm7/arm_mem.cpp
|
|
extern bool aica_interr;
|
|
extern u32 aica_reg_L;
|
|
extern bool e68k_out;
|
|
extern u32 e68k_reg_L;
|
|
extern u32 e68k_reg_M;
|
|
|
|
//./core/hw/arm7/arm7.cpp
|
|
extern DECL_ALIGN(8) reg_pair arm_Reg[RN_ARM_REG_COUNT];
|
|
extern bool armIrqEnable;
|
|
extern bool armFiqEnable;
|
|
extern int armMode;
|
|
extern bool Arm7Enabled;
|
|
|
|
//./core/hw/aica/dsp.o
|
|
extern DECL_ALIGN(4096) dsp_t dsp;
|
|
|
|
//./core/hw/aica/aica.o
|
|
extern AicaTimer timers[3];
|
|
|
|
//./core/hw/aica/aica_if.o
|
|
extern VArray2 aica_ram;
|
|
extern u32 VREG;//video reg =P
|
|
extern u32 ARMRST;//arm reset reg
|
|
extern u32 rtc_EN;
|
|
extern int dma_sched_id;
|
|
|
|
//./core/hw/aica/aica_mem.o
|
|
extern u8 aica_reg[0x8000];
|
|
|
|
//./core/hw/aica/sgc_if.o
|
|
struct ChannelEx;
|
|
#define AicaChannel ChannelEx
|
|
//special handling
|
|
//extern AicaChannel AicaChannel::Chans[64];
|
|
#define Chans AicaChannel::Chans
|
|
#define CDDA_SIZE (2352/2)
|
|
extern s16 cdda_sector[CDDA_SIZE];
|
|
extern u32 cdda_index;
|
|
|
|
//./core/hw/holly/sb.o
|
|
extern Array<RegisterStruct> sb_regs;
|
|
extern u32 SB_ISTNRM;
|
|
extern u32 SB_FFST_rc;
|
|
extern u32 SB_FFST;
|
|
|
|
//./core/hw/holly/sb_mem.o
|
|
extern SRamChip sys_nvmem_sram;
|
|
extern DCFlashChip sys_nvmem_flash;
|
|
|
|
//./core/hw/gdrom/gdromv3.o
|
|
extern int gdrom_sched;
|
|
extern signed int sns_asc;
|
|
extern signed int sns_ascq;
|
|
extern signed int sns_key;
|
|
extern packet_cmd_t packet_cmd;
|
|
extern u32 set_mode_offset;
|
|
extern read_params_t read_params ;
|
|
extern packet_cmd_t packet_cmd;
|
|
//Buffer for sector reads [dma]
|
|
extern read_buff_t read_buff ;
|
|
//pio buffer
|
|
extern pio_buff_t pio_buff ;
|
|
extern u32 set_mode_offset;
|
|
extern ata_cmd_t ata_cmd ;
|
|
extern cdda_t cdda ;
|
|
extern gd_states gd_state;
|
|
extern DiscType gd_disk_type;
|
|
extern u32 data_write_mode;
|
|
//Registers
|
|
extern u32 DriveSel;
|
|
extern GD_ErrRegT Error;
|
|
extern GD_InterruptReasonT IntReason;
|
|
extern GD_FeaturesT Features;
|
|
extern GD_SecCountT SecCount;
|
|
extern GD_SecNumbT SecNumber;
|
|
extern GD_StatusT GDStatus;
|
|
extern ByteCount_t ByteCount ;
|
|
extern int GDROM_TICK;
|
|
|
|
//./core/hw/maple/maple_devs.o
|
|
extern char EEPROM[0x100];
|
|
extern bool EEPROM_loaded;
|
|
|
|
//./core/hw/maple/maple_if.o
|
|
//needs special handler
|
|
extern maple_device* MapleDevices[4][6];
|
|
extern int maple_sched;
|
|
extern bool maple_ddt_pending_reset;
|
|
|
|
#ifdef ENABLE_MODEM
|
|
//./core/hw/modem/modem.cpp
|
|
extern int modem_sched;
|
|
#endif
|
|
|
|
|
|
//./core/hw/pvr/Renderer_if.o
|
|
extern bool pend_rend;
|
|
extern u32 fb_w_cur;
|
|
|
|
//./core/hw/pvr/pvr_mem.o
|
|
extern u32 YUV_tempdata[512/4];//512 bytes
|
|
extern u32 YUV_dest;
|
|
extern u32 YUV_blockcount;
|
|
extern u32 YUV_x_curr;
|
|
extern u32 YUV_y_curr;
|
|
extern u32 YUV_x_size;
|
|
extern u32 YUV_y_size;
|
|
|
|
//./core/hw/pvr/pvr_regs.o
|
|
extern bool fog_needs_update;
|
|
extern u8 pvr_regs[pvr_RegSize];
|
|
|
|
//./core/hw/pvr/spg.o
|
|
extern u32 in_vblank;
|
|
extern u32 clc_pvr_scanline;
|
|
extern int render_end_schid;
|
|
extern int vblank_schid;
|
|
|
|
//./core/hw/pvr/ta.o
|
|
extern u8 ta_fsm[2049]; //[2048] stores the current state
|
|
extern u32 ta_fsm_cl;
|
|
|
|
//./core/hw/pvr/ta_vtx.o
|
|
extern bool pal_needs_update;
|
|
|
|
//./core/rend/TexCache.o
|
|
extern VArray2 vram;
|
|
|
|
//./core/hw/sh4/sh4_mmr.o
|
|
extern Array<u8> OnChipRAM;
|
|
extern Array<RegisterStruct> CCN; //CCN : 14 registers
|
|
extern Array<RegisterStruct> UBC; //UBC : 9 registers
|
|
extern Array<RegisterStruct> BSC; //BSC : 18 registers
|
|
extern Array<RegisterStruct> DMAC; //DMAC : 17 registers
|
|
extern Array<RegisterStruct> CPG; //CPG : 5 registers
|
|
extern Array<RegisterStruct> RTC; //RTC : 16 registers
|
|
extern Array<RegisterStruct> INTC; //INTC : 4 registers
|
|
extern Array<RegisterStruct> TMU; //TMU : 12 registers
|
|
extern Array<RegisterStruct> SCI; //SCI : 8 registers
|
|
extern Array<RegisterStruct> SCIF; //SCIF : 10 registers
|
|
|
|
//./core/hw/sh4/sh4_mem.o
|
|
extern VArray2 mem_b;
|
|
|
|
//./core/hw/sh4/sh4_interrupts.o
|
|
extern DECL_ALIGN(64) u16 InterruptEnvId[32];
|
|
extern DECL_ALIGN(64) u32 InterruptBit[32];
|
|
extern DECL_ALIGN(64) 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<sched_list> sch_list;
|
|
|
|
//./core/hw/sh4/interpr/sh4_interpreter.o
|
|
extern int aica_schid;
|
|
extern int rtc_schid;
|
|
|
|
//./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 u32 ITLB_LRU_USE[64];
|
|
|
|
//./core/imgread/common.o
|
|
extern u32 NullDriveDiscType;
|
|
extern u8 q_subchannel[96];
|
|
|
|
//./core/nullDC.o
|
|
extern unsigned FLASH_SIZE;
|
|
extern unsigned BBSRAM_SIZE;
|
|
extern unsigned BIOS_SIZE;
|
|
extern unsigned RAM_SIZE;
|
|
extern unsigned ARAM_SIZE;
|
|
extern unsigned VRAM_SIZE;
|
|
extern unsigned RAM_MASK;
|
|
extern unsigned ARAM_MASK;
|
|
extern unsigned VRAM_MASK;
|
|
|
|
//./core/hw/naomi/naomi.o
|
|
extern u32 GSerialBuffer;
|
|
extern u32 BSerialBuffer;
|
|
extern int GBufPos;
|
|
extern int BBufPos;
|
|
extern int GState;
|
|
extern int BState;
|
|
extern int GOldClk;
|
|
extern int BOldClk;
|
|
extern int BControl;
|
|
extern int BCmd;
|
|
extern int BLastCmd;
|
|
extern int GControl;
|
|
extern int GCmd;
|
|
extern int GLastCmd;
|
|
extern int SerStep;
|
|
extern int SerStep2;
|
|
extern unsigned char BSerial[];
|
|
extern unsigned char GSerial[];
|
|
|
|
/*
|
|
* Deserialization input-buffer bounds tracking.
|
|
*
|
|
* The libretro frontend hands retro_unserialize() a buffer and its length.
|
|
* Historically that length was only used to disambiguate two legacy save-state
|
|
* versions and never to bound the reads, so a truncated or malformed state
|
|
* (netplay peer, runahead, on-disk corruption) walked memcpy() straight off the
|
|
* end of the input buffer. dc_unserialize() now publishes the input base and
|
|
* length here; ra_unserialize() refuses to read past the end and latches a
|
|
* failure that propagates to the retro_unserialize() return value.
|
|
*/
|
|
static const u8 *unserialize_base = NULL;
|
|
static size_t unserialize_limit = 0;
|
|
static bool unserialize_failed = false;
|
|
|
|
void ra_unserialize_init(const void *base, size_t limit)
|
|
{
|
|
unserialize_base = (const u8 *)base;
|
|
unserialize_limit = limit;
|
|
unserialize_failed = false;
|
|
}
|
|
|
|
bool ra_unserialize_failed(void)
|
|
{
|
|
return unserialize_failed;
|
|
}
|
|
|
|
bool ra_serialize(const void *src, unsigned int src_size, void **dest, unsigned int *total_size)
|
|
{
|
|
if ( *dest != NULL )
|
|
{
|
|
memcpy(*dest, src, src_size) ;
|
|
*dest = ((unsigned char*)*dest) + src_size ;
|
|
}
|
|
|
|
*total_size += src_size ;
|
|
return true ;
|
|
}
|
|
|
|
bool ra_unserialize(void *src, unsigned int src_size, void **dest, unsigned int *total_size)
|
|
{
|
|
if ( *dest != NULL )
|
|
{
|
|
/* Reject any read that would run past the end of the frontend-supplied
|
|
* input buffer. base==NULL means the limit is unknown (legacy callers);
|
|
* fall back to the original unchecked behavior in that case only. */
|
|
if (unserialize_base != NULL)
|
|
{
|
|
size_t offset = (size_t)((const u8 *)*dest - unserialize_base);
|
|
if (offset > unserialize_limit || src_size > unserialize_limit - offset)
|
|
{
|
|
unserialize_failed = true;
|
|
/* Leave the destination zero-initialized rather than reading
|
|
* out of bounds, and stop consuming input. */
|
|
memset(src, 0, src_size);
|
|
*total_size += src_size ;
|
|
return false ;
|
|
}
|
|
}
|
|
memcpy(src, *dest, src_size) ;
|
|
*dest = ((unsigned char*)*dest) + src_size ;
|
|
}
|
|
|
|
*total_size += src_size ;
|
|
return true ;
|
|
}
|
|
|
|
bool register_serialize(Array<RegisterStruct>& regs,void **data, unsigned int *total_size )
|
|
{
|
|
int i = 0 ;
|
|
|
|
for ( i = 0 ; i < regs.Size ; i++ )
|
|
{
|
|
LIBRETRO_S(regs.data[i].flags) ;
|
|
LIBRETRO_S(regs.data[i].data32) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
bool register_unserialize(Array<RegisterStruct>& regs,void **data, unsigned int *total_size, u32 force_size = 0)
|
|
{
|
|
int i = 0 ;
|
|
u32 dummy = 0 ;
|
|
|
|
if (force_size == 0)
|
|
force_size = regs.Size;
|
|
for ( i = 0 ; i < force_size ; i++ )
|
|
{
|
|
LIBRETRO_US(regs.data[i].flags) ;
|
|
if ( ! (regs.data[i].flags & REG_RF) )
|
|
LIBRETRO_US(regs.data[i].data32) ;
|
|
else
|
|
LIBRETRO_US(dummy) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
bool dc_serialize(void **data, unsigned int *total_size)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
serialize_version_enum version = VCUR_LIBRETRO;
|
|
|
|
*total_size = 0 ;
|
|
|
|
//dc not initialized yet
|
|
if ( p_sh4rcb == NULL )
|
|
return false ;
|
|
|
|
LIBRETRO_S(version) ;
|
|
LIBRETRO_S(aica_interr) ;
|
|
LIBRETRO_S(aica_reg_L) ;
|
|
LIBRETRO_S(e68k_out) ;
|
|
LIBRETRO_S(e68k_reg_L) ;
|
|
LIBRETRO_S(e68k_reg_M) ;
|
|
|
|
LIBRETRO_SA(arm_Reg,RN_ARM_REG_COUNT);
|
|
LIBRETRO_S(armIrqEnable);
|
|
LIBRETRO_S(armFiqEnable);
|
|
LIBRETRO_S(armMode);
|
|
LIBRETRO_S(Arm7Enabled);
|
|
|
|
LIBRETRO_S(dsp);
|
|
|
|
for ( i = 0 ; i < 3 ; i++)
|
|
{
|
|
LIBRETRO_S(timers[i].c_step);
|
|
LIBRETRO_S(timers[i].m_step);
|
|
}
|
|
|
|
LIBRETRO_SA(aica_ram.data,aica_ram.size) ;
|
|
LIBRETRO_S(VREG);
|
|
LIBRETRO_S(ARMRST);
|
|
LIBRETRO_S(rtc_EN);
|
|
|
|
LIBRETRO_SA(aica_reg,0x8000);
|
|
|
|
channel_serialize(data, total_size) ;
|
|
|
|
LIBRETRO_SA(cdda_sector,CDDA_SIZE);
|
|
LIBRETRO_S(cdda_index);
|
|
|
|
register_serialize(sb_regs, data, total_size) ;
|
|
LIBRETRO_S(SB_ISTNRM);
|
|
LIBRETRO_S(SB_FFST_rc);
|
|
LIBRETRO_S(SB_FFST);
|
|
|
|
LIBRETRO_S(sys_nvmem_sram.size);
|
|
LIBRETRO_S(sys_nvmem_sram.mask);
|
|
LIBRETRO_SA(sys_nvmem_sram.data,sys_nvmem_sram.size);
|
|
|
|
LIBRETRO_S(sys_nvmem_flash.size);
|
|
LIBRETRO_S(sys_nvmem_flash.mask);
|
|
LIBRETRO_S(sys_nvmem_flash.state);
|
|
LIBRETRO_SA(sys_nvmem_flash.data,sys_nvmem_flash.size);
|
|
|
|
LIBRETRO_S(GD_HardwareInfo) ;
|
|
|
|
|
|
LIBRETRO_S(sns_asc);
|
|
LIBRETRO_S(sns_ascq);
|
|
LIBRETRO_S(sns_key);
|
|
|
|
LIBRETRO_S(packet_cmd);
|
|
LIBRETRO_S(set_mode_offset);
|
|
LIBRETRO_S(read_params);
|
|
LIBRETRO_S(packet_cmd);
|
|
LIBRETRO_S(pio_buff);
|
|
LIBRETRO_S(set_mode_offset);
|
|
LIBRETRO_S(ata_cmd);
|
|
LIBRETRO_S(cdda);
|
|
LIBRETRO_S(gd_state);
|
|
LIBRETRO_S(gd_disk_type);
|
|
LIBRETRO_S(data_write_mode);
|
|
LIBRETRO_S(DriveSel);
|
|
LIBRETRO_S(Error);
|
|
|
|
LIBRETRO_S(IntReason);
|
|
LIBRETRO_S(Features);
|
|
LIBRETRO_S(SecCount);
|
|
LIBRETRO_S(SecNumber);
|
|
LIBRETRO_S(GDStatus);
|
|
LIBRETRO_S(ByteCount);
|
|
LIBRETRO_S(GDROM_TICK);
|
|
|
|
|
|
LIBRETRO_SA(EEPROM,0x100);
|
|
LIBRETRO_S(EEPROM_loaded);
|
|
|
|
|
|
LIBRETRO_S(maple_ddt_pending_reset);
|
|
|
|
mcfg_SerializeDevices(data, total_size);
|
|
|
|
LIBRETRO_SA(YUV_tempdata,512/4);
|
|
LIBRETRO_S(YUV_dest);
|
|
LIBRETRO_S(YUV_blockcount);
|
|
LIBRETRO_S(YUV_x_curr);
|
|
LIBRETRO_S(YUV_y_curr);
|
|
LIBRETRO_S(YUV_x_size);
|
|
LIBRETRO_S(YUV_y_size);
|
|
|
|
LIBRETRO_SA(pvr_regs,pvr_RegSize);
|
|
|
|
LIBRETRO_S(in_vblank);
|
|
LIBRETRO_S(clc_pvr_scanline);
|
|
LIBRETRO_S(fb_w_cur);
|
|
|
|
LIBRETRO_S(ta_fsm[2048]);
|
|
LIBRETRO_S(ta_fsm_cl);
|
|
|
|
SerializeTAContext(data, total_size);
|
|
|
|
LIBRETRO_SA(vram.data, vram.size);
|
|
|
|
LIBRETRO_SA(OnChipRAM.data,OnChipRAM_SIZE);
|
|
|
|
register_serialize(CCN, data, total_size) ;
|
|
register_serialize(UBC, data, total_size) ;
|
|
register_serialize(BSC, data, total_size) ;
|
|
register_serialize(DMAC, data, total_size) ;
|
|
register_serialize(CPG, data, total_size) ;
|
|
register_serialize(RTC, data, total_size) ;
|
|
register_serialize(INTC, data, total_size) ;
|
|
register_serialize(TMU, data, total_size) ;
|
|
register_serialize(SCI, data, total_size) ;
|
|
register_serialize(SCIF, data, total_size) ;
|
|
icache.Serialize(data, total_size);
|
|
ocache.Serialize(data, total_size);
|
|
|
|
LIBRETRO_SA(mem_b.data, mem_b.size);
|
|
|
|
LIBRETRO_SA(InterruptEnvId,32);
|
|
LIBRETRO_SA(InterruptBit,32);
|
|
LIBRETRO_SA(InterruptLevelBit,16);
|
|
LIBRETRO_S(interrupt_vpend);
|
|
LIBRETRO_S(interrupt_vmask);
|
|
LIBRETRO_S(decoded_srimask);
|
|
|
|
|
|
//default to nommu_full
|
|
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==(sqw_fp*)&TAWriteSQ)
|
|
i = 2 ;
|
|
else if (do_sqw_nommu==&do_sqw_nommu_full)
|
|
i = 3 ;
|
|
|
|
LIBRETRO_S(i) ;
|
|
|
|
LIBRETRO_SA((*p_sh4rcb).sq_buffer,64/8);
|
|
|
|
//store these before unserializing and then restore after
|
|
//void *getptr = &((*p_sh4rcb).cntx.sr.GetFull) ;
|
|
//void *setptr = &((*p_sh4rcb).cntx.sr.SetFull) ;
|
|
LIBRETRO_S((*p_sh4rcb).cntx);
|
|
|
|
|
|
LIBRETRO_S(sh4_sched_ffb);
|
|
|
|
LIBRETRO_S(sch_list[aica_schid].tag) ;
|
|
LIBRETRO_S(sch_list[aica_schid].start) ;
|
|
LIBRETRO_S(sch_list[aica_schid].end) ;
|
|
|
|
LIBRETRO_S(sch_list[rtc_schid].tag) ;
|
|
LIBRETRO_S(sch_list[rtc_schid].start) ;
|
|
LIBRETRO_S(sch_list[rtc_schid].end) ;
|
|
|
|
LIBRETRO_S(sch_list[gdrom_sched].tag) ;
|
|
LIBRETRO_S(sch_list[gdrom_sched].start) ;
|
|
LIBRETRO_S(sch_list[gdrom_sched].end) ;
|
|
|
|
LIBRETRO_S(sch_list[maple_sched].tag) ;
|
|
LIBRETRO_S(sch_list[maple_sched].start) ;
|
|
LIBRETRO_S(sch_list[maple_sched].end) ;
|
|
|
|
LIBRETRO_S(sch_list[dma_sched_id].tag) ;
|
|
LIBRETRO_S(sch_list[dma_sched_id].start) ;
|
|
LIBRETRO_S(sch_list[dma_sched_id].end) ;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
LIBRETRO_S(sch_list[tmu_sched[i]].tag) ;
|
|
LIBRETRO_S(sch_list[tmu_sched[i]].start) ;
|
|
LIBRETRO_S(sch_list[tmu_sched[i]].end) ;
|
|
}
|
|
|
|
LIBRETRO_S(sch_list[render_end_schid].tag) ;
|
|
LIBRETRO_S(sch_list[render_end_schid].start) ;
|
|
LIBRETRO_S(sch_list[render_end_schid].end) ;
|
|
|
|
LIBRETRO_S(sch_list[vblank_schid].tag) ;
|
|
LIBRETRO_S(sch_list[vblank_schid].start) ;
|
|
LIBRETRO_S(sch_list[vblank_schid].end) ;
|
|
|
|
LIBRETRO_S(settings.network.EmulateBBA);
|
|
#ifdef ENABLE_MODEM
|
|
if (settings.network.EmulateBBA)
|
|
{
|
|
bba_Serialize(data, total_size);
|
|
}
|
|
else
|
|
{
|
|
LIBRETRO_S(sch_list[modem_sched].tag) ;
|
|
LIBRETRO_S(sch_list[modem_sched].start) ;
|
|
LIBRETRO_S(sch_list[modem_sched].end) ;
|
|
}
|
|
#else
|
|
LIBRETRO_S(i);
|
|
LIBRETRO_S(i);
|
|
LIBRETRO_S(i);
|
|
#endif
|
|
|
|
LIBRETRO_S(SCIF_SCFSR2);
|
|
LIBRETRO_S(SCIF_SCSCR2);
|
|
LIBRETRO_S(BSC_PDTRA);
|
|
|
|
LIBRETRO_SA(tmu_shift,3);
|
|
LIBRETRO_SA(tmu_mask,3);
|
|
LIBRETRO_SA(tmu_mask64,3);
|
|
LIBRETRO_SA(old_mode,3);
|
|
LIBRETRO_SA(tmu_ch_base,3);
|
|
LIBRETRO_SA(tmu_ch_base64,3);
|
|
|
|
LIBRETRO_SA(CCN_QACR_TR,2);
|
|
|
|
LIBRETRO_S(UTLB);
|
|
LIBRETRO_S(ITLB);
|
|
LIBRETRO_S(sq_remap);
|
|
LIBRETRO_S(ITLB_LRU_USE);
|
|
|
|
LIBRETRO_S(NullDriveDiscType);
|
|
LIBRETRO_SA(q_subchannel,96);
|
|
|
|
|
|
LIBRETRO_S(FLASH_SIZE);
|
|
LIBRETRO_S(BBSRAM_SIZE);
|
|
LIBRETRO_S(BIOS_SIZE);
|
|
LIBRETRO_S(RAM_SIZE);
|
|
LIBRETRO_S(ARAM_SIZE);
|
|
LIBRETRO_S(VRAM_SIZE);
|
|
LIBRETRO_S(RAM_MASK);
|
|
LIBRETRO_S(ARAM_MASK);
|
|
LIBRETRO_S(VRAM_MASK);
|
|
|
|
LIBRETRO_S(GSerialBuffer);
|
|
LIBRETRO_S(BSerialBuffer);
|
|
LIBRETRO_S(GBufPos);
|
|
LIBRETRO_S(BBufPos);
|
|
LIBRETRO_S(GState);
|
|
LIBRETRO_S(BState);
|
|
LIBRETRO_S(GOldClk);
|
|
LIBRETRO_S(BOldClk);
|
|
LIBRETRO_S(BControl);
|
|
LIBRETRO_S(BCmd);
|
|
LIBRETRO_S(BLastCmd);
|
|
LIBRETRO_S(GControl);
|
|
LIBRETRO_S(GCmd);
|
|
LIBRETRO_S(GLastCmd);
|
|
LIBRETRO_S(SerStep);
|
|
LIBRETRO_S(SerStep2);
|
|
LIBRETRO_SA(BSerial,69);
|
|
LIBRETRO_SA(GSerial,69);
|
|
LIBRETRO_S(reg_dimm_command);
|
|
LIBRETRO_S(reg_dimm_offsetl);
|
|
LIBRETRO_S(reg_dimm_parameterl);
|
|
LIBRETRO_S(reg_dimm_parameterh);
|
|
LIBRETRO_S(reg_dimm_status);
|
|
LIBRETRO_SKIP(1); // NaomiDataRead
|
|
|
|
LIBRETRO_S(settings.dreamcast.broadcast);
|
|
LIBRETRO_S(settings.dreamcast.cable);
|
|
LIBRETRO_S(settings.dreamcast.region);
|
|
|
|
if (CurrentCartridge != NULL)
|
|
CurrentCartridge->Serialize(data, total_size);
|
|
gd_hle_state.Serialize(data, total_size);
|
|
settings.network.EmulateBBA = false;
|
|
|
|
return true ;
|
|
}
|
|
|
|
bool dc_unserialize(void **data, unsigned int *total_size, size_t actual_data_size)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
u8 dummy ;
|
|
int dummy_int ;
|
|
serialize_version_enum version = V1 ;
|
|
|
|
*total_size = 0 ;
|
|
|
|
/* Publish the input buffer bounds so ra_unserialize() can reject reads
|
|
* past the end of a truncated or malformed state. *data points at the
|
|
* start of the frontend-supplied buffer on entry. */
|
|
ra_unserialize_init(*data, actual_data_size);
|
|
|
|
LIBRETRO_US(version) ;
|
|
|
|
//This normally isn't necessary - but we need some way to differentiate between save states
|
|
//that were created after the format change and before the new format had a new version saved in it
|
|
if (version == V1 && actual_data_size != 48324799 && actual_data_size != 48855967)
|
|
version = V2 ;
|
|
|
|
LIBRETRO_US(aica_interr) ;
|
|
LIBRETRO_US(aica_reg_L) ;
|
|
LIBRETRO_US(e68k_out) ;
|
|
LIBRETRO_US(e68k_reg_L) ;
|
|
LIBRETRO_US(e68k_reg_M) ;
|
|
|
|
LIBRETRO_USA(arm_Reg,RN_ARM_REG_COUNT);
|
|
LIBRETRO_US(armIrqEnable);
|
|
LIBRETRO_US(armFiqEnable);
|
|
LIBRETRO_US(armMode);
|
|
LIBRETRO_US(Arm7Enabled);
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_SKIP(256); // cpuBitsSet
|
|
LIBRETRO_SKIP(1); // intState
|
|
LIBRETRO_SKIP(1); // stopState
|
|
LIBRETRO_SKIP(1); // holdState
|
|
}
|
|
|
|
LIBRETRO_US(dsp);
|
|
|
|
for ( i = 0 ; i < 3 ; i++)
|
|
{
|
|
LIBRETRO_US(timers[i].c_step);
|
|
LIBRETRO_US(timers[i].m_step);
|
|
}
|
|
|
|
|
|
LIBRETRO_USA(aica_ram.data,aica_ram.size) ;
|
|
LIBRETRO_US(VREG);
|
|
LIBRETRO_US(ARMRST);
|
|
LIBRETRO_US(rtc_EN);
|
|
if (version < V3)
|
|
LIBRETRO_US(dummy_int); //dma_sched_id
|
|
|
|
LIBRETRO_USA(aica_reg,0x8000);
|
|
|
|
|
|
if (version < V7)
|
|
{
|
|
LIBRETRO_SKIP(4 * 16); // volume_lut
|
|
LIBRETRO_SKIP(4 * 256 + 768); // tl_lut. Due to a previous bug this is not 4 * (256 + 768)
|
|
LIBRETRO_SKIP(4 * 64); // AEG_ATT_SPS
|
|
LIBRETRO_SKIP(4 * 64); // AEG_DSR_SPS
|
|
LIBRETRO_SKIP(2); // pl
|
|
LIBRETRO_SKIP(2); // pr
|
|
}
|
|
channel_unserialize(data, total_size, version);
|
|
|
|
LIBRETRO_USA(cdda_sector,CDDA_SIZE);
|
|
LIBRETRO_US(cdda_index);
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_SKIP(4 * 64); // mxlr
|
|
LIBRETRO_SKIP(4); // samples_gen
|
|
}
|
|
|
|
register_unserialize(sb_regs, data, total_size) ;
|
|
LIBRETRO_US(SB_ISTNRM);
|
|
LIBRETRO_US(SB_FFST_rc);
|
|
LIBRETRO_US(SB_FFST);
|
|
|
|
|
|
/* size/mask describe the live, already-allocated nvmem buffers. Read the
|
|
* stored values into temporaries and only copy up to the real allocation,
|
|
* so a corrupt state whose size exceeds the buffer can't overflow data[]
|
|
* (and can't clobber the live size/mask either). */
|
|
{
|
|
u32 stored_size, stored_mask;
|
|
LIBRETRO_US(stored_size);
|
|
LIBRETRO_US(stored_mask);
|
|
u32 copy = stored_size < sys_nvmem_sram.size ? stored_size : sys_nvmem_sram.size;
|
|
LIBRETRO_USA(sys_nvmem_sram.data, copy);
|
|
if (stored_size > copy)
|
|
LIBRETRO_SKIP(stored_size - copy);
|
|
}
|
|
|
|
{
|
|
u32 stored_size, stored_mask;
|
|
LIBRETRO_US(stored_size);
|
|
LIBRETRO_US(stored_mask);
|
|
LIBRETRO_US(sys_nvmem_flash.state);
|
|
u32 copy = stored_size < sys_nvmem_flash.size ? stored_size : sys_nvmem_flash.size;
|
|
LIBRETRO_USA(sys_nvmem_flash.data, copy);
|
|
if (stored_size > copy)
|
|
LIBRETRO_SKIP(stored_size - copy);
|
|
}
|
|
|
|
|
|
LIBRETRO_US(GD_HardwareInfo) ;
|
|
|
|
if (version < V3)
|
|
LIBRETRO_US(dummy_int); //gdrom_sched
|
|
LIBRETRO_US(sns_asc);
|
|
LIBRETRO_US(sns_ascq);
|
|
LIBRETRO_US(sns_key);
|
|
|
|
LIBRETRO_US(packet_cmd);
|
|
LIBRETRO_US(set_mode_offset);
|
|
LIBRETRO_US(read_params);
|
|
LIBRETRO_US(packet_cmd);
|
|
// read_buff
|
|
read_buff.cache_size = 0;
|
|
if (version < V9)
|
|
LIBRETRO_SKIP(4 + 4 + 2352 * 8192);
|
|
LIBRETRO_US(pio_buff);
|
|
LIBRETRO_US(set_mode_offset);
|
|
LIBRETRO_US(ata_cmd);
|
|
LIBRETRO_US(cdda);
|
|
cdda.status = (bool)cdda.status ? cdda_t::Playing : cdda_t::NoInfo;
|
|
LIBRETRO_US(gd_state);
|
|
LIBRETRO_US(gd_disk_type);
|
|
LIBRETRO_US(data_write_mode);
|
|
LIBRETRO_US(DriveSel);
|
|
LIBRETRO_US(Error);
|
|
LIBRETRO_US(IntReason);
|
|
LIBRETRO_US(Features);
|
|
LIBRETRO_US(SecCount);
|
|
LIBRETRO_US(SecNumber);
|
|
LIBRETRO_US(GDStatus);
|
|
LIBRETRO_US(ByteCount);
|
|
LIBRETRO_US(GDROM_TICK);
|
|
|
|
|
|
LIBRETRO_USA(EEPROM,0x100);
|
|
LIBRETRO_US(EEPROM_loaded);
|
|
|
|
if ( version == V1 )
|
|
{
|
|
//V1 saved NaomiState which was a struct of 3 u8 variables
|
|
LIBRETRO_US(dummy);
|
|
LIBRETRO_US(dummy);
|
|
LIBRETRO_US(dummy);
|
|
}
|
|
|
|
LIBRETRO_US(maple_ddt_pending_reset);
|
|
|
|
if ( version == V1 )
|
|
{
|
|
for (i = 0 ; i < 4 ; i++)
|
|
for (j = 0 ; j < 6 ; j++)
|
|
if ( MapleDevices[i][j] != 0 )
|
|
{
|
|
MapleDeviceType devtype = MapleDevices[i][j]->get_device_type() ;
|
|
mcfg_DestroyDevice(i,j) ;
|
|
mcfg_Create(devtype, i, j);
|
|
MapleDevices[i][j]->maple_unserialize(data, total_size) ;
|
|
}
|
|
}
|
|
else
|
|
mcfg_UnserializeDevices(data, total_size);
|
|
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_SKIP(4); // FrameCOunt
|
|
LIBRETRO_SKIP(1); // pend_rend
|
|
}
|
|
pend_rend = false;
|
|
|
|
LIBRETRO_USA(YUV_tempdata,512/4);
|
|
LIBRETRO_US(YUV_dest);
|
|
LIBRETRO_US(YUV_blockcount);
|
|
LIBRETRO_US(YUV_x_curr);
|
|
LIBRETRO_US(YUV_y_curr);
|
|
LIBRETRO_US(YUV_x_size);
|
|
LIBRETRO_US(YUV_y_size);
|
|
|
|
|
|
|
|
if (version < V9)
|
|
LIBRETRO_SKIP(1); // fog_needs_update
|
|
LIBRETRO_USA(pvr_regs,pvr_RegSize);
|
|
fog_needs_update = true ;
|
|
|
|
|
|
LIBRETRO_US(in_vblank);
|
|
LIBRETRO_US(clc_pvr_scanline);
|
|
fb_w_cur = 1;
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_US(i); // pvr_numscanlines
|
|
LIBRETRO_US(i); // prv_cur_scanline
|
|
LIBRETRO_US(i); // vblk_cnt
|
|
LIBRETRO_US(i); // Line_Cycles
|
|
LIBRETRO_US(i); // Frame_Cycles
|
|
if (version < V3)
|
|
{
|
|
LIBRETRO_US(dummy_int); //render_end_schid
|
|
LIBRETRO_US(dummy_int); //vblank_schid
|
|
LIBRETRO_US(dummy_int); //time_sync
|
|
}
|
|
LIBRETRO_SKIP(8); // speed_load_mspdf
|
|
LIBRETRO_US(dummy_int); // mips_counter
|
|
LIBRETRO_SKIP(8); // full_rps
|
|
|
|
LIBRETRO_SKIP(4 * 256); // ta_type_lut
|
|
LIBRETRO_SKIP(2048); // ta_fsm
|
|
}
|
|
if (version >= V12)
|
|
LIBRETRO_US(fb_w_cur);
|
|
else
|
|
fb_w_cur = 1;
|
|
LIBRETRO_US(ta_fsm[2048]);
|
|
LIBRETRO_US(ta_fsm_cl);
|
|
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_SKIP(1); // pal_needs_update
|
|
LIBRETRO_SKIP(4 * 4); // _pal_rev_256
|
|
LIBRETRO_SKIP(4 * 64); // _pal_rev_16
|
|
LIBRETRO_SKIP(4 * 4); // pal_rev_256
|
|
LIBRETRO_SKIP(4 * 64); // pal_rev_16
|
|
LIBRETRO_SKIP(4 * 65536 * 3); // decoded_colors
|
|
LIBRETRO_US(i); // tileclip_val
|
|
LIBRETRO_SKIP(65536); // f32_su8_tbl
|
|
LIBRETRO_US(i); // FaceBaseColor
|
|
LIBRETRO_US(i); // FaceOffsColor
|
|
LIBRETRO_US(i); // SFaceBaseColor
|
|
LIBRETRO_US(i); // SFaceOffsColor
|
|
|
|
|
|
LIBRETRO_US(i); // palette_index
|
|
LIBRETRO_US(dummy); // KillTex
|
|
LIBRETRO_SKIP(4 * 1024); // palette16_ram
|
|
LIBRETRO_SKIP(4 * 1024); // palette32_ram
|
|
LIBRETRO_SKIP(4 * 1024 * 8 * 2); // detwiddle
|
|
}
|
|
KillTex = true;
|
|
pal_needs_update = true;
|
|
if (version >= V10)
|
|
UnserializeTAContext(data, total_size, VCUR_LIBRETRO);
|
|
|
|
LIBRETRO_USA(vram.data, vram.size);
|
|
|
|
LIBRETRO_USA(OnChipRAM.data,OnChipRAM_SIZE);
|
|
|
|
register_unserialize(CCN, data, total_size, version < V4 ? 16 : 0) ;
|
|
register_unserialize(UBC, data, total_size) ;
|
|
register_unserialize(BSC, data, total_size) ;
|
|
register_unserialize(DMAC, data, total_size) ;
|
|
register_unserialize(CPG, data, total_size) ;
|
|
register_unserialize(RTC, data, total_size) ;
|
|
register_unserialize(INTC, data, total_size, version < V4 ? 4 : 0) ;
|
|
register_unserialize(TMU, data, total_size) ;
|
|
register_unserialize(SCI, data, total_size) ;
|
|
register_unserialize(SCIF, data, total_size) ;
|
|
if (version >= V9)
|
|
icache.Unserialize(data, total_size);
|
|
else
|
|
icache.Reset(true);
|
|
if (version >= V10)
|
|
ocache.Unserialize(data, total_size);
|
|
else
|
|
ocache.Reset(true);
|
|
|
|
LIBRETRO_USA(mem_b.data, mem_b.size);
|
|
|
|
if (version < V9)
|
|
{
|
|
u16 dum16;
|
|
LIBRETRO_US(dum16); // IRLPriority
|
|
}
|
|
LIBRETRO_USA(InterruptEnvId,32);
|
|
LIBRETRO_USA(InterruptBit,32);
|
|
LIBRETRO_USA(InterruptLevelBit,16);
|
|
LIBRETRO_US(interrupt_vpend);
|
|
LIBRETRO_US(interrupt_vmask);
|
|
LIBRETRO_US(decoded_srimask);
|
|
|
|
LIBRETRO_US(i) ;
|
|
if ( i == 0 )
|
|
do_sqw_nommu = &do_sqw_nommu_area_3 ;
|
|
else if ( i == 1 )
|
|
do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem ;
|
|
else if ( i == 2 )
|
|
do_sqw_nommu = (sqw_fp*)&TAWriteSQ ;
|
|
else if ( i == 3 )
|
|
do_sqw_nommu = &do_sqw_nommu_full ;
|
|
|
|
LIBRETRO_USA((*p_sh4rcb).sq_buffer,64/8);
|
|
|
|
LIBRETRO_US((*p_sh4rcb).cntx);
|
|
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_US(dummy_int); // old_rm
|
|
LIBRETRO_US(dummy_int); // old_dn
|
|
}
|
|
|
|
LIBRETRO_US(sh4_sched_ffb);
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_SKIP(4); // sh4_sched_intr
|
|
if (version < V3)
|
|
LIBRETRO_US(dummy_int); // sh4_sched_next_id
|
|
}
|
|
|
|
LIBRETRO_US(sch_list[aica_schid].tag) ;
|
|
LIBRETRO_US(sch_list[aica_schid].start) ;
|
|
LIBRETRO_US(sch_list[aica_schid].end) ;
|
|
|
|
LIBRETRO_US(sch_list[rtc_schid].tag) ;
|
|
LIBRETRO_US(sch_list[rtc_schid].start) ;
|
|
LIBRETRO_US(sch_list[rtc_schid].end) ;
|
|
|
|
LIBRETRO_US(sch_list[gdrom_sched].tag) ;
|
|
LIBRETRO_US(sch_list[gdrom_sched].start) ;
|
|
LIBRETRO_US(sch_list[gdrom_sched].end) ;
|
|
|
|
LIBRETRO_US(sch_list[maple_sched].tag) ;
|
|
LIBRETRO_US(sch_list[maple_sched].start) ;
|
|
LIBRETRO_US(sch_list[maple_sched].end) ;
|
|
|
|
LIBRETRO_US(sch_list[dma_sched_id].tag) ;
|
|
LIBRETRO_US(sch_list[dma_sched_id].start) ;
|
|
LIBRETRO_US(sch_list[dma_sched_id].end) ;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
LIBRETRO_US(sch_list[tmu_sched[i]].tag) ;
|
|
LIBRETRO_US(sch_list[tmu_sched[i]].start) ;
|
|
LIBRETRO_US(sch_list[tmu_sched[i]].end) ;
|
|
}
|
|
|
|
LIBRETRO_US(sch_list[render_end_schid].tag) ;
|
|
LIBRETRO_US(sch_list[render_end_schid].start) ;
|
|
LIBRETRO_US(sch_list[render_end_schid].end) ;
|
|
|
|
LIBRETRO_US(sch_list[vblank_schid].tag) ;
|
|
LIBRETRO_US(sch_list[vblank_schid].start) ;
|
|
LIBRETRO_US(sch_list[vblank_schid].end) ;
|
|
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_US(dummy_int); // sch_list[time_sync].tag
|
|
LIBRETRO_US(dummy_int); // sch_list[time_sync].start
|
|
LIBRETRO_US(dummy_int); // sch_list[time_sync].end
|
|
}
|
|
|
|
if (version >= V13)
|
|
LIBRETRO_US(settings.network.EmulateBBA);
|
|
else
|
|
settings.network.EmulateBBA = false;
|
|
|
|
if ( version >= V2 )
|
|
{
|
|
#ifdef ENABLE_MODEM
|
|
if (settings.network.EmulateBBA)
|
|
{
|
|
bba_Unserialize(data, total_size);
|
|
}
|
|
else
|
|
{
|
|
LIBRETRO_US(sch_list[modem_sched].tag) ;
|
|
LIBRETRO_US(sch_list[modem_sched].start) ;
|
|
LIBRETRO_US(sch_list[modem_sched].end) ;
|
|
}
|
|
#else
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
#endif
|
|
}
|
|
|
|
if (version < V3)
|
|
{
|
|
LIBRETRO_US(dummy_int); //aica_sched
|
|
LIBRETRO_US(dummy_int); //rtc_sched
|
|
}
|
|
|
|
LIBRETRO_US(SCIF_SCFSR2);
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_SKIP(1); // SCIF_SCFRDR2
|
|
LIBRETRO_US(dummy_int); // SCIF_SCFDR2
|
|
}
|
|
else if (version >= V11)
|
|
LIBRETRO_US(SCIF_SCSCR2);
|
|
LIBRETRO_US(BSC_PDTRA);
|
|
|
|
LIBRETRO_USA(tmu_shift,3);
|
|
LIBRETRO_USA(tmu_mask,3);
|
|
LIBRETRO_USA(tmu_mask64,3);
|
|
LIBRETRO_USA(old_mode,3);
|
|
if (version < V3)
|
|
{
|
|
//tmu_sched*3
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
}
|
|
LIBRETRO_USA(tmu_ch_base,3);
|
|
LIBRETRO_USA(tmu_ch_base64,3);
|
|
|
|
LIBRETRO_USA(CCN_QACR_TR,2);
|
|
|
|
if (version < V6)
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
{
|
|
LIBRETRO_US(UTLB[i].Address);
|
|
LIBRETRO_US(UTLB[i].Data);
|
|
}
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
LIBRETRO_US(ITLB[i].Address);
|
|
LIBRETRO_US(ITLB[i].Data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LIBRETRO_US(UTLB);
|
|
LIBRETRO_US(ITLB);
|
|
}
|
|
if (version >= V11)
|
|
LIBRETRO_US(sq_remap);
|
|
LIBRETRO_US(ITLB_LRU_USE);
|
|
|
|
LIBRETRO_US(NullDriveDiscType);
|
|
LIBRETRO_USA(q_subchannel,96);
|
|
|
|
LIBRETRO_US(FLASH_SIZE);
|
|
LIBRETRO_US(BBSRAM_SIZE);
|
|
LIBRETRO_US(BIOS_SIZE);
|
|
LIBRETRO_US(RAM_SIZE);
|
|
LIBRETRO_US(ARAM_SIZE);
|
|
LIBRETRO_US(VRAM_SIZE);
|
|
LIBRETRO_US(RAM_MASK);
|
|
LIBRETRO_US(ARAM_MASK);
|
|
LIBRETRO_US(VRAM_MASK);
|
|
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_US(dummy_int); // naomi_updates
|
|
if (version < V4)
|
|
{
|
|
LIBRETRO_US(dummy_int); // RomPioOffset
|
|
LIBRETRO_US(dummy_int); // DmaOffset
|
|
LIBRETRO_US(dummy_int); // DmaCount
|
|
}
|
|
LIBRETRO_US(dummy_int); // BoardID
|
|
}
|
|
LIBRETRO_US(GSerialBuffer);
|
|
LIBRETRO_US(BSerialBuffer);
|
|
LIBRETRO_US(GBufPos);
|
|
LIBRETRO_US(BBufPos);
|
|
LIBRETRO_US(GState);
|
|
LIBRETRO_US(BState);
|
|
LIBRETRO_US(GOldClk);
|
|
LIBRETRO_US(BOldClk);
|
|
LIBRETRO_US(BControl);
|
|
LIBRETRO_US(BCmd);
|
|
LIBRETRO_US(BLastCmd);
|
|
LIBRETRO_US(GControl);
|
|
LIBRETRO_US(GCmd);
|
|
LIBRETRO_US(GLastCmd);
|
|
LIBRETRO_US(SerStep);
|
|
LIBRETRO_US(SerStep2);
|
|
LIBRETRO_USA(BSerial,69);
|
|
LIBRETRO_USA(GSerial,69);
|
|
LIBRETRO_US(reg_dimm_command);
|
|
LIBRETRO_US(reg_dimm_offsetl);
|
|
LIBRETRO_US(reg_dimm_parameterl);
|
|
LIBRETRO_US(reg_dimm_parameterh);
|
|
LIBRETRO_US(reg_dimm_status);
|
|
LIBRETRO_SKIP(1); // NaomiDataRead
|
|
if (version < V4)
|
|
{
|
|
LIBRETRO_US(dummy_int); // NAOMI_ROM_OFFSETH
|
|
LIBRETRO_US(dummy_int); // NAOMI_ROM_OFFSETL
|
|
LIBRETRO_US(dummy_int); // NAOMI_ROM_DATA
|
|
LIBRETRO_US(dummy_int); // NAOMI_DMA_OFFSETH
|
|
LIBRETRO_US(dummy_int); // NAOMI_DMA_OFFSETL
|
|
LIBRETRO_US(dummy_int); // NAOMI_DMA_COUNT
|
|
LIBRETRO_US(dummy_int); // NAOMI_BOARDID_WRITE
|
|
LIBRETRO_US(dummy_int); // NAOMI_BOARDID_READ
|
|
LIBRETRO_US(dummy_int); // NAOMI_COMM_OFFSET
|
|
LIBRETRO_US(dummy_int); // NAOMI_COMM_DATA
|
|
}
|
|
|
|
if (version < V9)
|
|
{
|
|
LIBRETRO_US(dummy_int); // cycle_counter
|
|
LIBRETRO_US(dummy_int); // idxnxx
|
|
|
|
#if FEAT_SHREC != DYNAREC_NONE
|
|
LIBRETRO_SKIP(sizeof(state_t)); // state
|
|
LIBRETRO_US(dummy_int); // div_som_reg1
|
|
LIBRETRO_US(dummy_int); // div_som_reg2
|
|
LIBRETRO_US(dummy_int); // div_som_reg3
|
|
|
|
LIBRETRO_US(dummy_int); // LastAddr
|
|
LIBRETRO_US(dummy_int); // LastAddr_min
|
|
LIBRETRO_SKIP(1024); // block_hash
|
|
#endif
|
|
|
|
// RegisterRead, RegisterWrite
|
|
for (int i = 0; i < sh4_reg_count; i++)
|
|
{
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
}
|
|
LIBRETRO_US(dummy_int); // fallback_blocks
|
|
LIBRETRO_US(dummy_int); // total_blocks
|
|
LIBRETRO_US(dummy_int); // REMOVED_OPS
|
|
|
|
if (version < V5)
|
|
{
|
|
LIBRETRO_US(dummy_int); // u16 kcode[4]
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int); // u8 rt[4]
|
|
LIBRETRO_US(dummy_int); // u8 lt[4]
|
|
LIBRETRO_US(dummy_int); // u32 vks[4]
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int);
|
|
LIBRETRO_US(dummy_int); // s8 joyx[4]
|
|
LIBRETRO_US(dummy_int); // s8 joyy[4]
|
|
}
|
|
}
|
|
if (version >= V3)
|
|
{
|
|
LIBRETRO_US(settings.dreamcast.broadcast);
|
|
LIBRETRO_US(settings.dreamcast.cable);
|
|
LIBRETRO_US(settings.dreamcast.region);
|
|
}
|
|
|
|
if (version >= V4 && CurrentCartridge != NULL)
|
|
{
|
|
CurrentCartridge->Unserialize(data, total_size);
|
|
}
|
|
if (version >= V7)
|
|
gd_hle_state.Unserialize(data, total_size);
|
|
|
|
/* Fail the whole load if any read was rejected for running past the end
|
|
* of the input buffer. Callers (retro_unserialize) then bail cleanly
|
|
* instead of continuing on partially-garbage state. */
|
|
return !ra_unserialize_failed() ;
|
|
}
|