diff --git a/core/hw/aica/aica.cpp b/core/hw/aica/aica.cpp index 4ad045854..a69b7c558 100644 --- a/core/hw/aica/aica.cpp +++ b/core/hw/aica/aica.cpp @@ -83,77 +83,6 @@ void UpdateSh4Ints() } -//// -//Timers :) -struct AicaTimerData -{ - union - { - struct - { - u32 count:8; - u32 md:3; - u32 nil:5; - u32 pad:16; - }; - u32 data; - }; -}; -class AicaTimer -{ -public: - AicaTimerData* data; - s32 c_step; - u32 m_step; - u32 id; - void Init(u8* regbase,u32 timer) - { - data=(AicaTimerData*)®base[0x2890 + timer*4]; - id=timer; - m_step=1<<(data->md); - c_step=m_step; - } - void StepTimer(u32 samples) - { - do - { - c_step--; - if (c_step==0) - { - c_step=m_step; - data->count++; - if (data->count==0) - { - if (id==0) - { - SCIPD->TimerA=1; - MCIPD->TimerA=1; - } - else if (id==1) - { - SCIPD->TimerB=1; - MCIPD->TimerB=1; - } - else - { - SCIPD->TimerC=1; - MCIPD->TimerC=1; - } - } - } - } while(--samples); - } - - void RegisterWrite() - { - u32 n_step=1<<(data->md); - if (n_step!=m_step) - { - m_step=n_step; - c_step=m_step; - } - } -}; AicaTimer timers[3]; //Mainloop diff --git a/core/hw/aica/aica.h b/core/hw/aica/aica.h index a19c6d409..12edca626 100644 --- a/core/hw/aica/aica.h +++ b/core/hw/aica/aica.h @@ -311,4 +311,76 @@ void AICA_Term(); void WriteAicaReg8(u32 reg,u32 data); template -void WriteAicaReg(u32 reg,u32 data); \ No newline at end of file +void WriteAicaReg(u32 reg,u32 data); + +//// +//Timers :) +struct AicaTimerData +{ + union + { + struct + { + u32 count:8; + u32 md:3; + u32 nil:5; + u32 pad:16; + }; + u32 data; + }; +}; +class AicaTimer +{ +public: + AicaTimerData* data; + s32 c_step; + u32 m_step; + u32 id; + void Init(u8* regbase,u32 timer) + { + data=(AicaTimerData*)®base[0x2890 + timer*4]; + id=timer; + m_step=1<<(data->md); + c_step=m_step; + } + void StepTimer(u32 samples) + { + do + { + c_step--; + if (c_step==0) + { + c_step=m_step; + data->count++; + if (data->count==0) + { + if (id==0) + { + SCIPD->TimerA=1; + MCIPD->TimerA=1; + } + else if (id==1) + { + SCIPD->TimerB=1; + MCIPD->TimerB=1; + } + else + { + SCIPD->TimerC=1; + MCIPD->TimerC=1; + } + } + } + } while(--samples); + } + + void RegisterWrite() + { + u32 n_step=1<<(data->md); + if (n_step!=m_step) + { + m_step=n_step; + c_step=m_step; + } + } +}; diff --git a/core/hw/aica/sgc_if.cpp b/core/hw/aica/sgc_if.cpp index 35c89cbb6..76099a6b7 100755 --- a/core/hw/aica/sgc_if.cpp +++ b/core/hw/aica/sgc_if.cpp @@ -95,18 +95,6 @@ void AICA_Sample(); } s16 pl=0,pr=0; -struct DSP_OUT_VOL_REG -{ - //-- EFSDL[3:0] -- EFPAN[4:0] - - u32 EFPAN:5; - u32 res_1:3; - - u32 EFSDL:4; - u32 res_2:4; - - u32 pad:16; -}; DSP_OUT_VOL_REG* dsp_out_vol; #pragma pack (1) @@ -326,13 +314,17 @@ struct ChannelEx void (* StepStream)(ChannelEx* ch); void (* StepStreamInitial)(ChannelEx* ch); + u8 step_stream_lut1=0 ; + u8 step_stream_lut2=0 ; + u8 step_stream_lut3=0 ; + struct { s32 val; __forceinline s32 GetValue() { return val>>AEG_STEP_BITS;} void SetValue(u32 aegb) { val=aegb<LPCTL][ccd->LPSLNK]; StepStreamInitial=STREAM_INITAL_STEP_LUT[fmt]; + step_stream_lut1 = fmt ; + step_stream_lut2 = ccd->LPCTL ; + step_stream_lut3 = ccd->LPSLNK ; } //SA,PCMS void UpdateSA() @@ -598,6 +596,8 @@ struct ChannelEx lfo.alfo_calc=ALFOWS_CALC[ccd->ALFOWS]; lfo.plfo_calc=PLFOWS_CALC[ccd->PLFOWS]; + lfo.alfo_calc_lut=ccd->ALFOWS; + lfo.plfo_calc_lut=ccd->PLFOWS; if (ccd->LFORE) { @@ -943,7 +943,7 @@ void CalcPlfo(ChannelEx* ch) rv=(ch->lfo.state>>3)^(ch->lfo.state<<3)^(ch->lfo.state&0xE3); break; } - ch->lfo.alfo=rv>>ch->lfo.plfo_shft; + ch->lfo.plfo=rv>>ch->lfo.plfo_shft; } template @@ -1177,7 +1177,7 @@ s16 cdda_sector[CDDA_SIZE]={0}; u32 cdda_index=CDDA_SIZE<<1; -static SampleType mxlr[64]; +SampleType mxlr[64]; u32 samples_gen; @@ -1397,3 +1397,117 @@ void AICA_Sample() WriteSample(mixr,mixl); } +bool channel_serialize(void **data, unsigned int *total_size) +{ + int i = 0 ; + int addr = 0 ; + + for ( i = 0 ; i < 64 ; i++) + { + addr = Chans[i].SA - (&(aica_ram.data[0])) ; + REICAST_S(addr); + + REICAST_S(Chans[i].CA) ; + REICAST_S(Chans[i].step) ; + REICAST_S(Chans[i].update_rate) ; + REICAST_S(Chans[i].s0) ; + REICAST_S(Chans[i].s1) ; + REICAST_S(Chans[i].loop) ; + REICAST_S(Chans[i].adpcm.last_quant) ; + REICAST_S(Chans[i].noise_state) ; + REICAST_S(Chans[i].VolMix.DLAtt) ; + REICAST_S(Chans[i].VolMix.DRAtt) ; + REICAST_S(Chans[i].VolMix.DSPAtt) ; + + addr = Chans[i].VolMix.DSPOut - (&(dsp.MIXS[0])) ; + REICAST_S(addr); + + REICAST_S(Chans[i].AEG.val) ; + REICAST_S(Chans[i].AEG.state) ; + REICAST_S(Chans[i].AEG.AttackRate) ; + REICAST_S(Chans[i].AEG.Decay1Rate) ; + REICAST_S(Chans[i].AEG.Decay2Rate) ; + REICAST_S(Chans[i].AEG.Decay2Value) ; + REICAST_S(Chans[i].AEG.ReleaseRate) ; + REICAST_S(Chans[i].FEG) ; + REICAST_S(Chans[i].step_stream_lut1) ; + REICAST_S(Chans[i].step_stream_lut2) ; + REICAST_S(Chans[i].step_stream_lut3) ; + + REICAST_S(Chans[i].lfo.counter) ; + REICAST_S(Chans[i].lfo.start_value) ; + REICAST_S(Chans[i].lfo.state) ; + REICAST_S(Chans[i].lfo.alfo) ; + REICAST_S(Chans[i].lfo.alfo_shft) ; + REICAST_S(Chans[i].lfo.plfo) ; + REICAST_S(Chans[i].lfo.plfo_shft) ; + REICAST_S(Chans[i].lfo.alfo_calc_lut) ; + REICAST_S(Chans[i].lfo.plfo_calc_lut) ; + REICAST_S(Chans[i].enabled) ; + REICAST_S(Chans[i].ChanelNumber) ; + } + + /* TODO/FIXME - no possibility for this to return false? */ + return true; +} + +bool channel_unserialize(void **data, unsigned int *total_size) +{ + int i = 0 ; + int addr = 0 ; + + for ( i = 0 ; i < 64 ; i++) + { + REICAST_US(addr); + Chans[i].SA = addr + (&(aica_ram.data[0])) ; + + REICAST_US(Chans[i].CA) ; + REICAST_US(Chans[i].step) ; + REICAST_US(Chans[i].update_rate) ; + REICAST_US(Chans[i].s0) ; + REICAST_US(Chans[i].s1) ; + REICAST_US(Chans[i].loop) ; + REICAST_US(Chans[i].adpcm.last_quant) ; + REICAST_US(Chans[i].noise_state) ; + REICAST_US(Chans[i].VolMix.DLAtt) ; + REICAST_US(Chans[i].VolMix.DRAtt) ; + REICAST_US(Chans[i].VolMix.DSPAtt) ; + + REICAST_US(addr); + Chans[i].VolMix.DSPOut = addr + (&(dsp.MIXS[0])) ; + + REICAST_US(Chans[i].AEG.val) ; + REICAST_US(Chans[i].AEG.state) ; + Chans[i].StepAEG=AEG_STEP_LUT[Chans[i].AEG.state]; + REICAST_US(Chans[i].AEG.AttackRate) ; + REICAST_US(Chans[i].AEG.Decay1Rate) ; + REICAST_US(Chans[i].AEG.Decay2Rate) ; + REICAST_US(Chans[i].AEG.Decay2Value) ; + REICAST_US(Chans[i].AEG.ReleaseRate) ; + REICAST_US(Chans[i].FEG) ; + Chans[i].StepFEG=FEG_STEP_LUT[Chans[i].FEG.state]; + REICAST_US(Chans[i].step_stream_lut1) ; + REICAST_US(Chans[i].step_stream_lut2) ; + REICAST_US(Chans[i].step_stream_lut3) ; + Chans[i].StepStream=STREAM_STEP_LUT[Chans[i].step_stream_lut1][Chans[i].step_stream_lut2][Chans[i].step_stream_lut3] ; + Chans[i].StepStreamInitial=STREAM_INITAL_STEP_LUT[Chans[i].step_stream_lut1]; + + REICAST_US(Chans[i].lfo.counter) ; + REICAST_US(Chans[i].lfo.start_value) ; + REICAST_US(Chans[i].lfo.state) ; + REICAST_US(Chans[i].lfo.alfo) ; + REICAST_US(Chans[i].lfo.alfo_shft) ; + REICAST_US(Chans[i].lfo.plfo) ; + REICAST_US(Chans[i].lfo.plfo_shft) ; + REICAST_US(Chans[i].lfo.alfo_calc_lut) ; + REICAST_US(Chans[i].lfo.plfo_calc_lut) ; + Chans[i].lfo.alfo_calc = ALFOWS_CALC[Chans[i].lfo.alfo_calc_lut]; + Chans[i].lfo.plfo_calc = PLFOWS_CALC[Chans[i].lfo.plfo_calc_lut]; + REICAST_US(Chans[i].enabled) ; + REICAST_US(Chans[i].ChanelNumber) ; + + } + + /* TODO/FIXME - no possibility for this to return false? */ + return true; +} diff --git a/core/hw/aica/sgc_if.h b/core/hw/aica/sgc_if.h index d1d40f759..151987d6c 100644 --- a/core/hw/aica/sgc_if.h +++ b/core/hw/aica/sgc_if.h @@ -38,6 +38,19 @@ union fp_20_12 u32 full; }; +struct DSP_OUT_VOL_REG +{ + //-- EFSDL[3:0] -- EFPAN[4:0] + + u32 EFPAN:5; + u32 res_1:3; + + u32 EFSDL:4; + u32 res_2:4; + + u32 pad:16; +}; + //#define SAMPLE_TYPE_SHIFT (8) typedef s32 SampleType; @@ -45,3 +58,5 @@ void ReadCommonReg(u32 reg,bool byte); void WriteCommonReg8(u32 reg,u32 data); #define clip(x,min,max) if ((x)<(min)) (x)=(min); if ((x)>(max)) (x)=(max); #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); diff --git a/core/hw/arm7/arm7.cpp b/core/hw/arm7/arm7.cpp index 968574783..cca573afe 100644 --- a/core/hw/arm7/arm7.cpp +++ b/core/hw/arm7/arm7.cpp @@ -1,4 +1,4 @@ -#include "arm7.h" +#include "arm7.h" #include "arm_mem.h" @@ -36,87 +36,6 @@ #define CPUUpdateTicksAccess16(a) 1 -enum -{ - RN_CPSR = 16, - RN_SPSR = 17, - - R13_IRQ = 18, - R14_IRQ = 19, - SPSR_IRQ = 20, - R13_USR = 26, - R14_USR = 27, - R13_SVC = 28, - R14_SVC = 29, - SPSR_SVC = 30, - R13_ABT = 31, - R14_ABT = 32, - SPSR_ABT = 33, - R13_UND = 34, - R14_UND = 35, - SPSR_UND = 36, - R8_FIQ = 37, - R9_FIQ = 38, - R10_FIQ = 39, - R11_FIQ = 40, - R12_FIQ = 41, - R13_FIQ = 42, - R14_FIQ = 43, - SPSR_FIQ = 44, - RN_PSR_FLAGS = 45, - R15_ARM_NEXT = 46, - INTR_PEND = 47, - CYCL_CNT = 48, - - RN_ARM_REG_COUNT, -}; - -typedef union -{ - struct - { - u8 B0; - u8 B1; - u8 B2; - u8 B3; - } B; - - struct - { - u16 W0; - u16 W1; - } W; - - union - { - struct - { - u32 _pad0 : 28; - u32 V : 1; //Bit 28 - u32 C : 1; //Bit 29 - u32 Z : 1; //Bit 30 - u32 N : 1; //Bit 31 - }; - - struct - { - u32 _pad1 : 28; - u32 NZCV : 4; //Bits [31:28] - }; - } FLG; - - struct - { - u32 M : 5; //mode, PSR[4:0] - u32 _pad0 : 1; //not used / zero - u32 F : 1; //FIQ disable, PSR[6] - u32 I : 1; //IRQ disable, PSR[7] - u32 _pad1 : 20; //not used / zero - u32 NZCV : 4; //Bits [31:28] - } PSR; - - u32 I; -} reg_pair; //bool arm_FiqPending; -- not used , i use the input directly :) //bool arm_IrqPending; diff --git a/core/hw/gdrom/gdromv3.cpp b/core/hw/gdrom/gdromv3.cpp index 5b520d2fe..797743f3c 100644 --- a/core/hw/gdrom/gdromv3.cpp +++ b/core/hw/gdrom/gdromv3.cpp @@ -1,4 +1,4 @@ -/* +/* gdrom, v3 Overly complex implementation of a very ugly device */ @@ -24,103 +24,14 @@ signed int sns_asc=0; signed int sns_ascq=0; signed int sns_key=0; -enum gd_states -{ - //Generic - gds_waitcmd, - gds_procata, - gds_waitpacket, - gds_procpacket, - gds_pio_send_data, - gds_pio_get_data, - gds_pio_end, - gds_procpacketdone, - - //Command spec. - gds_readsector_pio, - gds_readsector_dma, - gds_process_set_mode, -}; - -static struct -{ - u32 start_sector; - u32 remaining_sectors; - u32 sector_type; -} read_params; - -static struct -{ - u32 index; - union - { - u16 data_16[6]; - u8 data_8[12]; - //Spi command structs - union - { - struct - { - u8 cc; - - u8 prmtype : 1 ; - u8 expdtype : 3 ; - // u8 datasel : 4 ; - u8 other : 1 ; //"other" data. I guess that means SYNC/ECC/EDC ? - u8 data : 1 ; //user data. 2048 for mode1, 2048 for m2f1, 2324 for m2f2 - u8 subh : 1 ; //8 bytes, mode2 subheader - u8 head : 1 ; //4 bytes, main CDROM header - - u8 block[10]; - }; - - struct - { - u8 b[12]; - }; - }GDReadBlock; - }; -} packet_cmd; - -//Buffer for sector reads [dma] -static struct -{ - u32 cache_index; - u32 cache_size; - u8 cache[2352 * 8192]; //up to 8192 sectors -} read_buff; - -//pio buffer -static struct -{ - gd_states next_state; - u32 index; - u32 size; - u16 data[0x10000>>1]; //64 kb -} pio_buff; u32 set_mode_offset; -static struct -{ - u8 command; -} ata_cmd; - -static struct -{ - bool playing; - u32 repeats; - union - { - u32 FAD; - struct - { - u8 B0; // MSB - u8 B1; // Middle byte - u8 B2; // LSB - }; - }CurrAddr,EndAddr,StartAddr; -} cdda; - +read_params_t read_params ; +packet_cmd_t packet_cmd ; +read_buff_t read_buff ; +pio_buff_t pio_buff ; +ata_cmd_t ata_cmd ; +cdda_t cdda ; gd_states gd_state; DiscType gd_disk_type; @@ -144,16 +55,7 @@ u32 data_write_mode=0; GD_StatusT GDStatus; - static union - { - struct - { - u8 low; - u8 hi; - }; - - u16 full; - } ByteCount; + ByteCount_t ByteCount; //end @@ -217,6 +119,7 @@ void FillReadBuffer() read_params.remaining_sectors-=count; } + void gd_set_state(gd_states state) { gd_states prev=gd_state; diff --git a/core/hw/gdrom/gdromv3.h b/core/hw/gdrom/gdromv3.h index 5b4229a26..057fe4554 100644 --- a/core/hw/gdrom/gdromv3.h +++ b/core/hw/gdrom/gdromv3.h @@ -11,6 +11,24 @@ void gdrom_reg_Reset(bool Manual); u32 ReadMem_gdrom(u32 Addr, u32 sz); void WriteMem_gdrom(u32 Addr, u32 data, u32 sz); +enum gd_states +{ + //Generic + gds_waitcmd, + gds_procata, + gds_waitpacket, + gds_procpacket, + gds_pio_send_data, + gds_pio_get_data, + gds_pio_end, + gds_procpacketdone, + + //Command spec. + gds_readsector_pio, + gds_readsector_dma, + gds_process_set_mode, +}; + //Structs & unions struct SpiCommandInfo { @@ -115,6 +133,95 @@ struct GD_SecNumbT }; }; +struct read_params_t +{ + u32 start_sector; + u32 remaining_sectors; + u32 sector_type; +} ; + +struct packet_cmd_t +{ + u32 index; + union + { + u16 data_16[6]; + u8 data_8[12]; + //Spi command structs + union + { + struct + { + u8 cc; + + u8 prmtype : 1 ; + u8 expdtype : 3 ; + // u8 datasel : 4 ; + u8 other : 1 ; //"other" data. I guess that means SYNC/ECC/EDC ? + u8 data : 1 ; //user data. 2048 for mode1, 2048 for m2f1, 2324 for m2f2 + u8 subh : 1 ; //8 bytes, mode2 subheader + u8 head : 1 ; //4 bytes, main CDROM header + + u8 block[10]; + }; + + struct + { + u8 b[12]; + }; + }GDReadBlock; + }; +} ; + +//Buffer for sector reads [dma] +struct read_buff_t +{ + u32 cache_index; + u32 cache_size; + u8 cache[2352 * 8192]; //up to 8192 sectors +} ; + +//pio buffer +struct pio_buff_t +{ + gd_states next_state; + u32 index; + u32 size; + u16 data[0x10000>>1]; //64 kb +} ; + +struct ata_cmd_t +{ + u8 command; +} ; + +struct cdda_t +{ + bool playing; + u32 repeats; + union + { + u32 FAD; + struct + { + u8 B0; // MSB + u8 B1; // Middle byte + u8 B2; // LSB + }; + }CurrAddr,EndAddr,StartAddr; +} ; + +union ByteCount_t +{ + struct + { + u8 low; + u8 hi; + }; + + u16 full; +} ; + #define GD_BUSY 0x00 // State transition #define GD_PAUSE 0x01 // Pause #define GD_STANDBY 0x02 // Standby (drive stop) diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index 033e350ed..e0b75a5e4 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -288,6 +288,20 @@ struct maple_sega_vmu: maple_base return (rv == Z_OK && dec_sz == sizeof(flash_data)); } + virtual bool maple_serialize(void **data, unsigned int *total_size) + { + REICAST_SA(flash_data,128*1024); + REICAST_SA(lcd_data,192); + REICAST_SA(lcd_data_decoded,48*32); + return true ; + } + virtual bool maple_unserialize(void **data, unsigned int *total_size) + { + REICAST_USA(flash_data,128*1024); + REICAST_USA(lcd_data,192); + REICAST_USA(lcd_data_decoded,48*32); + return true ; + } virtual void OnSetup() { memset(flash_data, 0, sizeof(flash_data)); @@ -703,6 +717,16 @@ struct maple_microphone: maple_base { u8 micdata[SIZE_OF_MIC_DATA]; + virtual bool maple_serialize(void **data, unsigned int *total_size) + { + REICAST_SA(micdata,SIZE_OF_MIC_DATA); + return true ; + } + virtual bool maple_unserialize(void **data, unsigned int *total_size) + { + REICAST_USA(micdata,SIZE_OF_MIC_DATA); + return true ; + } virtual void OnSetup() { memset(micdata,0,sizeof(micdata)); @@ -885,6 +909,20 @@ struct maple_sega_purupuru : maple_base u16 AST, AST_ms; u32 VIBSET; + virtual bool maple_serialize(void **data, unsigned int *total_size) + { + REICAST_S(AST); + REICAST_S(AST_ms); + REICAST_S(VIBSET); + return true ; + } + virtual bool maple_unserialize(void **data, unsigned int *total_size) + { + REICAST_US(AST); + REICAST_US(AST_ms); + REICAST_US(VIBSET); + return true ; + } virtual u32 dma(u32 cmd) { switch (cmd) @@ -1134,12 +1172,6 @@ extern u8 rt[4], lt[4]; char EEPROM[0x100]; bool EEPROM_loaded = false; -struct _NaomiState -{ - u8 Cmd; - u8 Mode; - u8 Node; -}; _NaomiState State; diff --git a/core/hw/maple/maple_devs.h b/core/hw/maple/maple_devs.h index d1a2d9cff..edecbbfcc 100755 --- a/core/hw/maple/maple_devs.h +++ b/core/hw/maple/maple_devs.h @@ -33,6 +33,15 @@ struct maple_device virtual void OnSetup(){}; virtual ~maple_device(); virtual u32 Dma(u32 Command,u32* buffer_in,u32 buffer_in_len,u32* buffer_out,u32& buffer_out_len)=0; + virtual bool maple_serialize(void **data, unsigned int *total_size){return true;}; + virtual bool maple_unserialize(void **data, unsigned int *total_size){return true;}; +}; + +struct _NaomiState +{ + u8 Cmd; + u8 Mode; + u8 Node; }; maple_device* maple_Create(MapleDeviceType type); diff --git a/core/hw/naomi/naomi.cpp b/core/hw/naomi/naomi.cpp index 6e6cf3b24..5df6e75ad 100644 --- a/core/hw/naomi/naomi.cpp +++ b/core/hw/naomi/naomi.cpp @@ -42,8 +42,8 @@ A-H (0x41-0x48) J-N (0x4A-0x4E) P-Z (0x50-0x5A) */ -static unsigned char BSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649"; -static unsigned char GSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649"; +unsigned char BSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649"; +unsigned char GSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649"; unsigned int ShiftCRC(unsigned int CRC,unsigned int rounds) { diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp index 5c2a960cb..3b15230c2 100644 --- a/core/hw/pvr/ta_vtx.cpp +++ b/core/hw/pvr/ta_vtx.cpp @@ -83,10 +83,10 @@ PolyParam* CurrentPP=&nullPP; List* CurrentPPlist; //TA state vars -DECL_ALIGN(4) static u8 FaceBaseColor[4]; -DECL_ALIGN(4) static u8 FaceOffsColor[4]; -DECL_ALIGN(4) static u32 SFaceBaseColor; -DECL_ALIGN(4) static u32 SFaceOffsColor; +DECL_ALIGN(4) u8 FaceBaseColor[4]; +DECL_ALIGN(4) u8 FaceOffsColor[4]; +DECL_ALIGN(4) u32 SFaceBaseColor; +DECL_ALIGN(4) u32 SFaceOffsColor; diff --git a/core/hw/sh4/dyna/decoder.cpp b/core/hw/sh4/dyna/decoder.cpp index bba75f1f0..3b6705ef7 100644 --- a/core/hw/sh4/dyna/decoder.cpp +++ b/core/hw/sh4/dyna/decoder.cpp @@ -68,62 +68,8 @@ shil_param mk_regi(int reg) { return mk_reg((Sh4RegType)reg); } -enum NextDecoderOperation -{ - NDO_NextOp, //pc+=2 - NDO_End, //End the block, Type = BlockEndType - NDO_Delayslot, //pc+=2, NextOp=DelayOp - NDO_Jump, //pc=JumpAddr,NextOp=JumpOp -}; - -struct -{ - NextDecoderOperation NextOp; - NextDecoderOperation DelayOp; - NextDecoderOperation JumpOp; - u32 JumpAddr; - u32 NextAddr; - BlockEndType BlockType; - - struct - { - bool FPR64; //64 bit FPU opcodes - bool FSZ64; //64 bit FPU moves - bool RoundToZero; //false -> Round to nearest. - u32 rpc; - bool is_delayslot; - } cpu; - - ngen_features ngen; - - struct - { - bool has_readm; - bool has_writem; - bool has_fpu; - } info; - - void Setup(u32 rpc,fpscr_t fpu_cfg) - { - cpu.rpc=rpc; - cpu.is_delayslot=false; - cpu.FPR64=fpu_cfg.PR; - cpu.FSZ64=fpu_cfg.SZ; - cpu.RoundToZero=fpu_cfg.RM==1; - verify(fpu_cfg.RM<2); - //what about fp/fs ? - - NextOp=NDO_NextOp; - BlockType=BET_SCL_Intr; - JumpAddr=0xFFFFFFFF; - NextAddr=0xFFFFFFFF; - - info.has_readm=false; - info.has_writem=false; - info.has_fpu=false; - } -} state; +state_t state ; void Emit(shilop op,shil_param rd=shil_param(),shil_param rs1=shil_param(),shil_param rs2=shil_param(),u32 flags=0,shil_param rs3=shil_param(),shil_param rd2=shil_param()) { @@ -1045,10 +991,30 @@ bool dec_generic(u32 op) return true; } +void state_Setup(u32 rpc,fpscr_t fpu_cfg) +{ + state.cpu.rpc=rpc; + state.cpu.is_delayslot=false; + state.cpu.FPR64=fpu_cfg.PR; + state.cpu.FSZ64=fpu_cfg.SZ; + state.cpu.RoundToZero=fpu_cfg.RM==1; + verify(fpu_cfg.RM<2); + //what about fp/fs ? + + state.NextOp=NDO_NextOp; + state.BlockType=BET_SCL_Intr; + state.JumpAddr=0xFFFFFFFF; + state.NextAddr=0xFFFFFFFF; + + state.info.has_readm=false; + state.info.has_writem=false; + state.info.has_fpu=false; +} + void dec_DecodeBlock(RuntimeBlockInfo* rbi,u32 max_cycles) { blk=rbi; - state.Setup(blk->addr,blk->fpu_cfg); + state_Setup(blk->addr,blk->fpu_cfg); ngen_GetFeatures(&state.ngen); blk->guest_opcodes=0; diff --git a/core/hw/sh4/dyna/decoder.h b/core/hw/sh4/dyna/decoder.h index 710c95a11..efe0e470e 100644 --- a/core/hw/sh4/dyna/decoder.h +++ b/core/hw/sh4/dyna/decoder.h @@ -30,6 +30,48 @@ enum BlockEndType BET_Cond_1=mkbet(BET_CLS_COND,BET_SCL_Jump,1), //sr.T==1 -> BranchBlock else NextBlock }; +enum NextDecoderOperation +{ + NDO_NextOp, //pc+=2 + NDO_End, //End the block, Type = BlockEndType + NDO_Delayslot, //pc+=2, NextOp=DelayOp + NDO_Jump, //pc=JumpAddr,NextOp=JumpOp +}; +//ngen features +struct ngen_features +{ + bool OnlyDynamicEnds; //if set the block endings aren't handled natively and only Dynamic block end type is used + bool InterpreterFallback; //if set all the non-branch opcodes are handled with the ifb opcode +}; + struct RuntimeBlockInfo; void dec_DecodeBlock(RuntimeBlockInfo* rbi,u32 max_cycles); +struct state_t +{ + NextDecoderOperation NextOp; + NextDecoderOperation DelayOp; + NextDecoderOperation JumpOp; + u32 JumpAddr; + u32 NextAddr; + BlockEndType BlockType; + + struct + { + bool FPR64; //64 bit FPU opcodes + bool FSZ64; //64 bit FPU moves + bool RoundToZero; //false -> Round to nearest. + u32 rpc; + bool is_delayslot; + } cpu; + + ngen_features ngen; + + struct + { + bool has_readm; + bool has_writem; + bool has_fpu; + } info; + +} ; diff --git a/core/hw/sh4/dyna/driver.cpp b/core/hw/sh4/dyna/driver.cpp index 6f1c9e9dc..3f7983f24 100644 --- a/core/hw/sh4/dyna/driver.cpp +++ b/core/hw/sh4/dyna/driver.cpp @@ -382,6 +382,11 @@ void recSh4_Stop() Sh4_int_Stop(); } +void recSh4_Start() +{ + Sh4_int_Start(); +} + void recSh4_Step() { Sh4_int_Step(); @@ -485,6 +490,7 @@ void Get_Sh4Recompiler(sh4_if* rv) { rv->Run = recSh4_Run; rv->Stop = recSh4_Stop; + rv->Start = recSh4_Start; rv->Step = recSh4_Step; rv->Skip = recSh4_Skip; rv->Reset = recSh4_Reset; diff --git a/core/hw/sh4/dyna/ngen.h b/core/hw/sh4/dyna/ngen.h index 28c8ba507..c5814c4dc 100644 --- a/core/hw/sh4/dyna/ngen.h +++ b/core/hw/sh4/dyna/ngen.h @@ -94,12 +94,6 @@ void ngen_ResetBlocks(); extern void (*ngen_FailedToFindBlock)(); //the dynarec mainloop void ngen_mainloop(void* cntx); -//ngen features -struct ngen_features -{ - bool OnlyDynamicEnds; //if set the block endings aren't handled natively and only Dynamic block end type is used - bool InterpreterFallback; //if set all the non-branch opcodes are handled with the ifb opcode -}; void ngen_GetFeatures(ngen_features* dst); diff --git a/core/hw/sh4/interpr/sh4_interpreter.cpp b/core/hw/sh4/interpr/sh4_interpreter.cpp index 2ce06ba0c..5cc1454a2 100644 --- a/core/hw/sh4/interpr/sh4_interpreter.cpp +++ b/core/hw/sh4/interpr/sh4_interpreter.cpp @@ -82,6 +82,14 @@ void Sh4_int_Stop() } } +void Sh4_int_Start() +{ + if (!sh4_int_bCpuRun) + { + sh4_int_bCpuRun=true; + } +} + void Sh4_int_Step() { if (sh4_int_bCpuRun) @@ -124,7 +132,7 @@ void Sh4_int_Reset(bool Manual) gbr=ssr=spc=sgr=dbr=vbr=0; mac.full=pr=fpul=0; - sr.SetFull(0x700000F0); + sh4_sr_SetFull(0x700000F0); old_sr.status=sr.status; UpdateSR(); @@ -165,12 +173,12 @@ void ExecuteDelayslot() void ExecuteDelayslot_RTE() { - u32 oldsr = sr.GetFull(); + u32 oldsr = sh4_sr_GetFull(); #if !defined(NO_MMU) try { #endif - sr.SetFull(ssr); + sh4_sr_SetFull(ssr); ExecuteDelayslot(); #if !defined(NO_MMU) @@ -265,6 +273,7 @@ void Get_Sh4Interpreter(sh4_if* rv) { rv->Run=Sh4_int_Run; rv->Stop=Sh4_int_Stop; + rv->Start=Sh4_int_Start; rv->Step=Sh4_int_Step; rv->Skip=Sh4_int_Skip; rv->Reset=Sh4_int_Reset; diff --git a/core/hw/sh4/interpr/sh4_opcodes.cpp b/core/hw/sh4/interpr/sh4_opcodes.cpp index e470152e9..b71be433e 100644 --- a/core/hw/sh4/interpr/sh4_opcodes.cpp +++ b/core/hw/sh4/interpr/sh4_opcodes.cpp @@ -2129,7 +2129,7 @@ sh4op(i0100_nnnn_0001_1011) sh4op(i0000_nnnn_0000_0010)//0002 { u32 n = GetN(op); - r[n] = sr.GetFull(); + r[n] = sh4_sr_GetFull(); } //sts FPSCR, @@ -2155,7 +2155,7 @@ sh4op(i0100_nnnn_0000_0011) //iNimp("stc.l SR,@-"); u32 n = GetN(op); r[n] -= 4; - WriteMemU32(r[n], sr.GetFull()); + WriteMemU32(r[n], sh4_sr_GetFull()); } //lds.l @+,FPSCR @@ -2178,7 +2178,7 @@ sh4op(i0100_nnnn_0000_0111) u32 sr_t; ReadMemU32(sr_t,r[n]); - sr.SetFull(sr_t); + sh4_sr_SetFull(sr_t); r[n] += 4; if (UpdateSR()) { @@ -2198,7 +2198,7 @@ sh4op(i0100_nnnn_0110_1010) sh4op(i0100_nnnn_0000_1110) { u32 n = GetN(op); - sr.SetFull(r[n]); + sh4_sr_SetFull(r[n]); if (UpdateSR()) { UpdateINTC(); diff --git a/core/hw/sh4/sh4_core_regs.cpp b/core/hw/sh4/sh4_core_regs.cpp index ee791e580..7bcd1d2d5 100644 --- a/core/hw/sh4/sh4_core_regs.cpp +++ b/core/hw/sh4/sh4_core_regs.cpp @@ -234,7 +234,7 @@ u32* Sh4_int_GetRegisterPtr(Sh4RegType reg) } } -u32 Sh4Context::offset(u32 sh4_reg) +u32 sh4context_offset_u32(u32 sh4_reg) { void* addr=Sh4_int_GetRegisterPtr((Sh4RegType)sh4_reg); u32 offs=(u8*)addr-(u8*)&Sh4cntx; @@ -242,3 +242,7 @@ u32 Sh4Context::offset(u32 sh4_reg) return offs; } +u32 sh4context_offset_regtype(Sh4RegType sh4_reg) +{ + return sh4context_offset_u32(sh4_reg); +} diff --git a/core/hw/sh4/sh4_if.h b/core/hw/sh4/sh4_if.h index aa7aaf47c..332fb85be 100644 --- a/core/hw/sh4/sh4_if.h +++ b/core/hw/sh4/sh4_if.h @@ -169,16 +169,6 @@ struct sr_t u32 status; }; u32 T; - INLINE u32 GetFull() - { - return (status & 0x700083F2) | T; - } - - INLINE void SetFull(u32 value) - { - status=value & 0x700083F2; - T=value&1; - } }; @@ -225,6 +215,7 @@ struct fpscr_t typedef void RunFP(); typedef void StopFP(); +typedef void StartFP(); typedef void StepFP(); typedef void SkipFP(); typedef void ResetFP(bool Manual); @@ -251,6 +242,7 @@ struct sh4_if TermFP* ResetCache; IsCpuRunningFP* IsCpuRunning; + StartFP* Start; }; @@ -294,10 +286,11 @@ struct Sh4Context u64 raw[64-8]; }; - u32 offset(u32 sh4_reg); - u32 offset(Sh4RegType sh4_reg) { return offset(sh4_reg); } }; +u32 sh4context_offset_u32(u32 sh4_reg); +u32 sh4context_offset_regtype(Sh4RegType sh4_reg); + void DYNACALL do_sqw_mmu(u32 dst); extern "C" void DYNACALL do_sqw_nommu_area_3(u32 dst, u8* sqb); extern "C" void DYNACALL do_sqw_nommu_area_3_nonvmem(u32 dst, u8* sqb); @@ -324,6 +317,17 @@ struct Sh4RCB extern Sh4RCB* p_sh4rcb; extern u8* sh4_dyna_rcb; +INLINE u32 sh4_sr_GetFull() +{ + return (p_sh4rcb->cntx.sr.status & 0x700083F2) | p_sh4rcb->cntx.sr.T; +} + +INLINE void sh4_sr_SetFull(u32 value) +{ + p_sh4rcb->cntx.sr.status=value & 0x700083F2; + p_sh4rcb->cntx.sr.T=value&1; +} + #define do_sqw_nommu sh4rcb.do_sqw_nommu template diff --git a/core/hw/sh4/sh4_interpreter.h b/core/hw/sh4/sh4_interpreter.h index e66026457..43423e206 100644 --- a/core/hw/sh4/sh4_interpreter.h +++ b/core/hw/sh4/sh4_interpreter.h @@ -38,6 +38,7 @@ enum OpcodeType //interface void Sh4_int_Run(); void Sh4_int_Stop(); +void Sh4_int_Start(); void Sh4_int_Step(); void Sh4_int_Skip(); void Sh4_int_Reset(bool Manual); @@ -61,4 +62,4 @@ int UpdateSystem_INTC(); #if HOST_OS==OS_LINUX || HOST_OS==OS_DARWIN } -#endif \ No newline at end of file +#endif diff --git a/core/hw/sh4/sh4_interrupts.cpp b/core/hw/sh4/sh4_interrupts.cpp index e799fde2b..bec73565b 100644 --- a/core/hw/sh4/sh4_interrupts.cpp +++ b/core/hw/sh4/sh4_interrupts.cpp @@ -146,7 +146,7 @@ bool Do_Interrupt(u32 intEvn) { CCN_INTEVT = intEvn; - ssr = sr.GetFull(); + ssr = sh4_sr_GetFull(); spc = next_pc; sgr = r[15]; sr.BL = 1; @@ -163,7 +163,7 @@ bool Do_Exception(u32 epc, u32 expEvn, u32 CallVect) verify(sr.BL == 0); CCN_EXPEVT = expEvn; - ssr = sr.GetFull(); + ssr = sh4_sr_GetFull(); spc = epc; sgr = r[15]; sr.BL = 1; diff --git a/core/hw/sh4/sh4_sched.cpp b/core/hw/sh4/sh4_sched.cpp index dbb9770fa..d44b55453 100755 --- a/core/hw/sh4/sh4_sched.cpp +++ b/core/hw/sh4/sh4_sched.cpp @@ -24,13 +24,6 @@ u64 sh4_sched_ffb; u32 sh4_sched_intr; -struct sched_list -{ - sh4_sched_callback* cb; - int tag; - int start; - int end; -}; vector list; @@ -173,4 +166,4 @@ void sh4_sched_tick(int cycles) } sh4_sched_ffts(); } -} \ No newline at end of file +} diff --git a/core/hw/sh4/sh4_sched.h b/core/hw/sh4/sh4_sched.h index a2cdce581..27a648f04 100644 --- a/core/hw/sh4/sh4_sched.h +++ b/core/hw/sh4/sh4_sched.h @@ -49,4 +49,12 @@ void sh4_sched_tick(int cycles); extern u32 sh4_sched_intr; +struct sched_list +{ + sh4_sched_callback* cb; + int tag; + int start; + int end; +}; + #endif //SH4_SCHED_H diff --git a/core/linux-dist/evdev.cpp b/core/linux-dist/evdev.cpp index 7c277fcfe..5a1574228 100644 --- a/core/linux-dist/evdev.cpp +++ b/core/linux-dist/evdev.cpp @@ -28,6 +28,8 @@ }; void dc_stop(void); + bool dc_loadstate(void); + bool dc_savestate(void); void load_libevdev() { @@ -230,6 +232,8 @@ load_keycode(&mf, "dreamcast", "btn_z"), load_keycode(&mf, "dreamcast", "btn_start"), load_keycode(&mf, "emulator", "btn_escape"), + load_keycode(&mf, "emulator", "btn_loadstate"), + load_keycode(&mf, "emulator", "btn_savestate"), load_keycode(&mf, "dreamcast", "btn_dpad1_left"), load_keycode(&mf, "dreamcast", "btn_dpad1_right"), load_keycode(&mf, "dreamcast", "btn_dpad1_up"), @@ -273,6 +277,8 @@ || (mapping->Btn_Z == button) || (mapping->Btn_Start == button) || (mapping->Btn_Escape == button) + || (mapping->Btn_LoadState == button) + || (mapping->Btn_SaveState == button) || (mapping->Btn_DPad_Left == button) || (mapping->Btn_DPad_Right == button) || (mapping->Btn_DPad_Up == button) @@ -296,6 +302,8 @@ || input_evdev_button_assigned(mapping1, mapping2->Btn_Z) || input_evdev_button_assigned(mapping1, mapping2->Btn_Start) || input_evdev_button_assigned(mapping1, mapping2->Btn_Escape) + || input_evdev_button_assigned(mapping1, mapping2->Btn_LoadState) + || input_evdev_button_assigned(mapping1, mapping2->Btn_SaveState) || input_evdev_button_assigned(mapping1, mapping2->Btn_DPad_Left) || input_evdev_button_assigned(mapping1, mapping2->Btn_DPad_Right) || input_evdev_button_assigned(mapping1, mapping2->Btn_DPad_Up) @@ -537,6 +545,10 @@ SET_FLAG(kcode[port], DC_BTN_START, ie.value); } else if (ie.code == controller->mapping->Btn_Escape) { dc_stop(); + } else if (ie.code == controller->mapping->Btn_LoadState) { + dc_loadstate(); + } else if (ie.code == controller->mapping->Btn_SaveState) { + dc_savestate(); } else if (ie.code == controller->mapping->Btn_DPad_Left) { SET_FLAG(kcode[port], DC_DPAD_LEFT, ie.value); } else if (ie.code == controller->mapping->Btn_DPad_Right) { diff --git a/core/linux-dist/evdev.h b/core/linux-dist/evdev.h index 10d298819..888d2b70e 100644 --- a/core/linux-dist/evdev.h +++ b/core/linux-dist/evdev.h @@ -14,6 +14,8 @@ struct EvdevControllerMapping const int Btn_Z; const int Btn_Start; const int Btn_Escape; + const int Btn_LoadState; + const int Btn_SaveState; const int Btn_DPad_Left; const int Btn_DPad_Right; const int Btn_DPad_Up; diff --git a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp index 73b7c3fde..9f92ac147 100644 --- a/core/linux-dist/x11.cpp +++ b/core/linux-dist/x11.cpp @@ -44,6 +44,8 @@ void* x11_vis; extern bool dump_frame_switch; void dc_stop(void); +bool dc_loadstate(void); +bool dc_savestate(void); enum { @@ -396,6 +398,14 @@ void input_x11_handle() x11_fullscreen = !x11_fullscreen; x11_window_set_fullscreen(x11_fullscreen); } + else if (e.type == KeyRelease && e.xkey.keycode == KEY_F2) + { + dc_savestate() ; + } + else if (e.type == KeyRelease && e.xkey.keycode == KEY_F4) + { + dc_loadstate() ; + } else { int dc_key = x11_keymap[e.xkey.keycode]; diff --git a/core/nullDC.cpp b/core/nullDC.cpp index e702aa7c7..43d40abf7 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -16,8 +16,12 @@ #include "webui/server.h" #include "hw/naomi/naomi_cart.h" #include "reios/reios.h" +#include "hw/sh4/dyna/blockmanager.h" settings_t settings; +static bool performed_serialization = false; +static cMutex mtx_serialization ; +static cMutex mtx_mainloop ; /* libndc @@ -40,6 +44,43 @@ settings_t settings; #include #endif +/** + * cpu_features_get_time_usec: + * + * Gets time in microseconds. + * + * Returns: time in microseconds. + **/ +int64_t get_time_usec(void) +{ +#if HOST_OS==OS_WINDOWS + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + /* Frequency is guaranteed to not change. */ + if (!freq.QuadPart && !QueryPerformanceFrequency(&freq)) + return 0; + + if (!QueryPerformanceCounter(&count)) + return 0; + return count.QuadPart * 1000000 / freq.QuadPart; +#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) || HOST_OS==OS_LINUX + struct timespec tv = {0}; + if (clock_gettime(CLOCK_MONOTONIC, &tv) < 0) + return 0; + return tv.tv_sec * INT64_C(1000000) + (tv.tv_nsec + 500) / 1000; +#elif defined(EMSCRIPTEN) + return emscripten_get_now() * 1000; +#elif defined(__mips__) || defined(DJGPP) + struct timeval tv; + gettimeofday(&tv,NULL); + return (1000000 * tv.tv_sec + tv.tv_usec); +#else +#error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue." +#endif +} + + int GetFile(char *szFileName, char *szParse=0, u32 flags=0) { cfgLoadStr("config","image",szFileName,"null"); @@ -285,9 +326,26 @@ int dc_init() } #ifndef TARGET_DISPFRAME +bool dc_is_running() +{ + return sh4_cpu.IsCpuRunning(); +} + void dc_run() { - sh4_cpu.Run(); + while ( true ) + { + performed_serialization = false ; + mtx_mainloop.Lock() ; + sh4_cpu.Run(); + mtx_mainloop.Unlock() ; + + mtx_serialization.Lock() ; + mtx_serialization.Unlock() ; + + if (!performed_serialization) + break ; + } } #endif @@ -324,6 +382,11 @@ void dc_stop() sh4_cpu.Stop(); } +void dc_start() +{ + sh4_cpu.Start(); +} + void LoadSettings() { #ifndef _ANDROID @@ -442,3 +505,196 @@ void SaveSettings() cfgSaveInt("config","Dreamcast.Region", settings.dreamcast.region); cfgSaveInt("config","Dreamcast.Broadcast", settings.dreamcast.broadcast); } + +bool wait_until_dc_running() +{ + int64_t start_time = get_time_usec() ; + const int64_t FIVE_SECONDS = 5*1000000 ; + while(!dc_is_running()) + { + if ( start_time+FIVE_SECONDS < get_time_usec() ) + { + //timeout elapsed - dc not getting a chance to run - just bail + return false ; + } + } + return true ; +} + +bool acquire_mainloop_lock() +{ + bool result = false ; + int64_t start_time = get_time_usec() ; + const int64_t FIVE_SECONDS = 5*1000000 ; + + while ( ( start_time+FIVE_SECONDS > get_time_usec() ) && !(result = mtx_mainloop.TryLock()) ) + { + //rend_cancel_emu_wait() ; + //retro_run(); + } + + return result ; +} + +void cleanup_serialize(void *data) +{ + if ( data != NULL ) + free(data) ; + + performed_serialization = true ; + dc_start() ; + mtx_serialization.Unlock() ; + mtx_mainloop.Unlock() ; + +} + +void* dc_savestate_thread(void* p) +{ + char filename[2048] ; + unsigned int total_size = 0 ; + void *data = NULL ; + void *data_ptr = NULL ; + FILE *f ; + + mtx_serialization.Lock() ; + if ( !wait_until_dc_running()) { + printf("Failed to save state - dc loop kept running\n") ; + mtx_serialization.Unlock() ; + return NULL; + } + + dc_stop() ; + + if ( !acquire_mainloop_lock() ) + { + printf("Failed to save state - could not acquire main loop lock\n") ; + performed_serialization = true ; + dc_start() ; + mtx_serialization.Unlock() ; + return NULL; + } + + if ( ! dc_serialize(&data, &total_size) ) + { + printf("Failed to save state - could not initialize total size\n") ; + cleanup_serialize(data) ; + return NULL; + } + + data = malloc(total_size) ; + if ( data == NULL ) + { + printf("Failed to save state - could not malloc %d bytes", total_size) ; + cleanup_serialize(data) ; + return NULL; + } + + data_ptr = data ; + + if ( ! dc_serialize(&data_ptr, &total_size) ) + { + printf("Failed to save state - could not serialize data\n") ; + cleanup_serialize(data) ; + return NULL; + } + + snprintf(filename, 2048, "%s%s", get_writable_data_path("/data/").c_str(), "state") ; + f = fopen(filename, "wb") ; + + if ( f == NULL ) + { + printf("Failed to save state - could not open %s for writing\n", filename) ; + cleanup_serialize(data) ; + return NULL; + } + + fwrite(data, 1, total_size, f) ; + fclose(f); + + cleanup_serialize(data) ; + printf("Saved state to %s\n size %d", filename, total_size) ; + +} + +void* dc_loadstate_thread(void* p) +{ + char filename[2048] ; + unsigned int total_size = 0 ; + void *data = NULL ; + void *data_ptr = NULL ; + FILE *f ; + + mtx_serialization.Lock() ; + if ( !wait_until_dc_running()) { + printf("Failed to load state - dc loop kept running\n") ; + mtx_serialization.Unlock() ; + return NULL; + } + + dc_stop() ; + + if ( !acquire_mainloop_lock() ) + { + printf("Failed to load state - could not acquire main loop lock\n") ; + performed_serialization = true ; + dc_start() ; + mtx_serialization.Unlock() ; + return NULL; + } + + if ( ! dc_serialize(&data, &total_size) ) + { + printf("Failed to load state - could not initialize total size\n") ; + cleanup_serialize(data) ; + return NULL; + } + + data = malloc(total_size) ; + if ( data == NULL ) + { + printf("Failed to load state - could not malloc %d bytes", total_size) ; + cleanup_serialize(data) ; + return NULL; + } + + snprintf(filename, 2048, "%s%s", get_writable_data_path("/data/").c_str(), "state") ; + f = fopen(filename, "rb") ; + + if ( f == NULL ) + { + printf("Failed to load state - could not open %s for reading\n", filename) ; + cleanup_serialize(data) ; + return NULL; + } + + fread(data, 1, total_size, f) ; + fclose(f); + + + data_ptr = data ; + + bm_Reset() ; + + if ( ! dc_unserialize(&data_ptr, &total_size) ) + { + printf("Failed to load state - could not unserialize data\n") ; + cleanup_serialize(data) ; + return NULL; + } + + cleanup_serialize(data) ; + printf("Loaded state from %s size %d\n", filename, total_size) ; +} + + +void dc_savestate() +{ + cThread thd(dc_savestate_thread,0); + thd.Start() ; +} + +void dc_loadstate() +{ + cThread thd(dc_loadstate_thread,0); + thd.Start() ; +} diff --git a/core/serialize.cpp b/core/serialize.cpp new file mode 100644 index 000000000..eee51562f --- /dev/null +++ b/core/serialize.cpp @@ -0,0 +1,1663 @@ +// serialize.cpp : save states +#if 1 +#include "types.h" +#include "hw/aica/dsp.h" +#include "hw/aica/aica.h" +#include "hw/aica/sgc_if.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/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 +#include +#include "rend/gles/gles.h" +#include "hw/sh4/dyna/blockmanager.h" +#include "hw/sh4/dyna/ngen.h" + +/* + * search for "maybe" to find items that were left out that may be needed + */ + +extern "C" void DYNACALL TAWriteSQ(u32 address,u8* sqb); + +enum serialize_version_enum { + V1 +} ; + +//./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; +extern u8 cpuBitsSet[256]; +extern bool intState ; +extern bool stopState ; +extern bool holdState ; +/* + if AREC dynarec enabled: + vector ops; + u8* icPtr; + u8* ICache; + u8 ARM7_TCB[ICacheSize+4096]; + void* EntryPoints[8*1024*1024/4]; + map renamed_regs; + u32 rename_reg_base; + u32 nfb,ffb,bfb,mfb; + static x86_block* x86e; + x86_Label* end_lbl; + u8* ARM::emit_opt=0; + eReg ARM::reg_addr; + eReg ARM::reg_dst; + s32 ARM::imma; +*/ + + + + +//./core/hw/aica/dsp.o +extern DECL_ALIGN(4096) dsp_t dsp; +//recheck dsp.cpp if FEAT_DSPREC == DYNAREC_JIT + + + + +//./core/hw/aica/aica.o +//these are all just pointers into aica_reg +//extern CommonData_struct* CommonData; +//extern DSPData_struct* DSPData; +//extern InterruptInfo* MCIEB; +//extern InterruptInfo* MCIPD; +//extern InterruptInfo* MCIRE; +//extern InterruptInfo* SCIEB; +//extern InterruptInfo* SCIPD; +//extern InterruptInfo* SCIRE; + +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 s32 aica_pending_dma ; +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 +extern s32 volume_lut[16]; +extern s32 tl_lut[256 + 768]; //xx.15 format. >=255 is muted +extern u32 AEG_ATT_SPS[64]; +extern u32 AEG_DSR_SPS[64]; +extern s16 pl; +extern s16 pr; +//this is just a pointer to aica_reg +//extern DSP_OUT_VOL_REG* dsp_out_vol; +//not needed - one-time init +//void(* STREAM_STEP_LUT [5][2][2])(ChannelEx *ch) +//void(* STREAM_INITAL_STEP_LUT [5])(ChannelEx *ch) +//void(* AEG_STEP_LUT [4])(ChannelEx *ch) +//void(* FEG_STEP_LUT [4])(ChannelEx *ch) +//void(* ALFOWS_CALC [4])(ChannelEx *ch) +//void(* PLFOWS_CALC [4])(ChannelEx *ch) + +//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; +extern SampleType mxlr[64]; +extern u32 samples_gen; + + + + + +//./core/hw/holly/sb.o +extern Array sb_regs; +extern u32 SB_ISTNRM; +extern u32 SB_FFST_rc; +extern u32 SB_FFST; + + + +//./core/hw/holly/sb_mem.o +//unused +//static HollyInterruptID dmatmp1; +//static HollyInterruptID dmatmp2; +//static HollyInterruptID OldDmaId; + +//this is one-time init, no updates - don't need to serialize +//extern RomChip sys_rom; +#ifdef FLASH_SIZE +extern DCFlashChip sys_nvmem; +#endif + +#ifdef BBSRAM_SIZE +extern SRamChip sys_nvmem; +#endif +//this is one-time init, no updates - don't need to serialize +//extern _vmem_handler area0_handler; + + + + +//./core/hw/gdrom/gdrom_response.o +extern u16 reply_11[] ; + + + + +//./core/hw/gdrom/gdromv3.o +extern int gdrom_schid; +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 ; + + + + + +//./core/hw/maple/maple_devs.o +extern char EEPROM[0x100]; +extern bool EEPROM_loaded; +extern _NaomiState State; +/* + * each maple_device has unique sub-elements - need special handler +struct maple_base: maple_device +{ + u8* dma_buffer_out; + u32* dma_count_out; + + u8* dma_buffer_in; + u32 dma_count_in; + +struct maple_sega_vmu: maple_base +{ + FILE* file; + u8 flash_data[128*1024]; + u8 lcd_data[192]; + u8 lcd_data_decoded[48*32]; + +struct maple_device +{ + u8 maple_port; //raw maple port + u8 bus_port; //0 .. 5 + u8 bus_id; //0 .. 3 + wchar logical_port[3]; //A0, etc + IMapleConfigMap* config; +struct maple_microphone: maple_base + + u8 micdata[SIZE_OF_MIC_DATA]; +struct maple_sega_purupuru : maple_base + + u16 AST, AST_ms; + u32 VIBSET; +*/ + + + + +//./core/hw/maple/maple_if.o +//needs special handler +extern maple_device* MapleDevices[4][6]; +//one time set +//extern int maple_sched; +//incremented but never read +//extern u32 dmacount; +extern bool maple_ddt_pending_reset; + + + + + + +//./core/hw/pvr/Renderer_if.o +//only written - not read +//extern u32 VertexCount; +extern u32 FrameCount; +//one-time init +//extern Renderer* renderer; +//these are just mutexes used during rendering +//extern cResetEvent rs; +//extern cResetEvent re; +//these max_?? through ovrn are written and not read +//extern int max_idx; +//extern int max_mvo; +//extern int max_op; +//extern int max_pt; +//extern int max_tr; +//extern int max_vtx; +//extern int max_modt; +//extern int ovrn; +//seems safe to omit this - gets refreshed every frame from a pool +//extern TA_context* _pvrrc; +//just a flag indiating the rendering thread is running +//extern int rend_en ; +//the renderer thread - one time set +//extern cThread rthd; +extern bool pend_rend; + +//these will all get cleared out after a few frames - no need to serialize +//static bool render_called = false; +//u32 fb1_watch_addr_start; +//u32 fb1_watch_addr_end; +//u32 fb2_watch_addr_start; +//u32 fb2_watch_addr_end; +//bool fb_dirty; + + +//maybe +//extern u32 memops_t,memops_l; + + +//./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 u32 pvr_numscanlines; +extern u32 prv_cur_scanline; +extern u32 vblk_cnt; +extern u32 Line_Cycles; +extern u32 Frame_Cycles; +extern int render_end_schid; +extern int vblank_schid; +extern int time_sync; +extern double speed_load_mspdf; +extern int mips_counter; +extern double full_rps; +extern u32 fskip; + + + + +//./core/hw/pvr/ta.o +extern u32 ta_type_lut[256]; +extern u8 ta_fsm[2049]; //[2048] stores the current state +extern u32 ta_fsm_cl; + + + + +//./core/hw/pvr/ta_ctx.o +//these frameskipping don't need to be saved +//extern int frameskip; +//extern bool FrameSkipping; // global switch to enable/disable frameskip +//maybe need these - but hopefully not +//extern TA_context* ta_ctx; +//extern tad_context ta_tad; +//extern TA_context* vd_ctx; +//extern rend_context vd_rc; +//extern cMutex mtx_rqueue; +//extern TA_context* rqueue; +//extern cResetEvent frame_finished; +//extern cMutex mtx_pool; +//extern vector ctx_pool; +//extern vector ctx_list; +//end maybe + + + +//./core/hw/pvr/ta_vtx.o +extern bool pal_needs_update; +extern u32 _pal_rev_256[4]; +extern u32 _pal_rev_16[64]; +extern u32 pal_rev_256[4]; +extern u32 pal_rev_16[64]; +extern u32 palette16_ram[1024]; +extern u32 palette32_ram[1024]; +//extern u32 palette_ram[1024]; +extern u32 decoded_colors[3][65536]; +extern u32 tileclip_val; +extern u8 f32_su8_tbl[65536]; +//written but never read +//extern ModTriangle* lmr; +//never changed +//extern PolyParam nullPP; +//maybe +//extern PolyParam* CurrentPP; +//maybe +//extern List* CurrentPPlist; +//TA state vars +extern DECL_ALIGN(4) u8 FaceBaseColor[4]; +extern DECL_ALIGN(4) u8 FaceOffsColor[4]; +#ifdef HAVE_OIT +extern DECL_ALIGN(4) u8 FaceBaseColor1[4]; +extern DECL_ALIGN(4) u8 FaceOffsColor1[4]; +#endif +extern DECL_ALIGN(4) u32 SFaceBaseColor; +extern DECL_ALIGN(4) u32 SFaceOffsColor; +//maybe +//extern TaListFP* TaCmd; +//maybe +//extern u32 CurrentList; +//maybe +//extern TaListFP* VertexDataFP; +//written but never read +//extern bool ListIsFinished[5]; +//maybe ; need special handler +//FifoSplitter<0> TAFifo0; +//counter for frameskipping - doesn't need to be saved +//extern int ta_parse_cnt; + + + + +//./core/rend/TexCache.o +//maybe +//extern u8* vq_codebook; +extern u32 palette_index; +extern bool KillTex; +//extern u32 palette16_ram[1024]; +//extern u32 palette32_ram[1024]; +extern u32 detwiddle[2][8][1024]; +//maybe +//extern vector VramLocks[/*VRAM_SIZE*/(16*1024*1024)/PAGE_SIZE]; +//maybe - probably not - just a locking mechanism +//extern cMutex vramlist_lock; +extern VArray2 vram; + + + + +//./core/hw/sh4/sh4_mmr.o +extern Array OnChipRAM; +extern Array CCN; //CCN : 14 registers +extern Array UBC; //UBC : 9 registers +extern Array BSC; //BSC : 18 registers +extern Array DMAC; //DMAC : 17 registers +extern Array CPG; //CPG : 5 registers +extern Array RTC; //RTC : 16 registers +extern Array INTC; //INTC : 4 registers +extern Array TMU; //TMU : 12 registers +extern Array SCI; //SCI : 8 registers +extern Array SCIF; //SCIF : 10 registers + + + + +//./core/hw/sh4/sh4_mem.o +extern VArray2 mem_b; +//one-time init +//extern _vmem_handler area1_32b; +//one-time init +//extern _vmem_handler area5_handler; + + + + +//./core/hw/sh4/sh4_interrupts.o +extern u16 IRLPriority; +//one-time init +//extern InterptSourceList_Entry InterruptSourceList[28]; +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; +//just method pointers +//extern sh4_if sh4_cpu; +//one-time set +//extern u8* sh4_dyna_rcb; +extern u32 old_rm; +extern u32 old_dn; + + + + +//./core/hw/sh4/sh4_sched.o +extern u64 sh4_sched_ffb; +extern u32 sh4_sched_intr; +extern vector list; +extern int sh4_sched_next_id; + + + + +//./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 u8 SCIF_SCFRDR2; +extern SCIF_SCFDR2_type SCIF_SCFDR2; + + + + +//./core/hw/sh4/modules/bsc.o +extern BSC_PDTRA_type BSC_PDTRA; + + + + +//./core/hw/sh4/modules/tmu.o +extern u32 tmu_shift[3]; +extern u32 tmu_mask[3]; +extern u64 tmu_mask64[3]; +extern u32 old_mode[3]; +extern int tmu_sched[3]; +extern u32 tmu_ch_base[3]; +extern u64 tmu_ch_base64[3]; + + + + +//./core/hw/sh4/modules/ccn.o +extern u32 CCN_QACR_TR[2]; + + + + +//./core/hw/sh4/modules/mmu.o +extern TLB_Entry UTLB[64]; +extern TLB_Entry ITLB[4]; +#if defined(NO_MMU) +extern u32 sq_remap[64]; +#else +extern u32 ITLB_LRU_USE[64]; +extern u32 mmu_error_TT; +#endif + + + +//./core/imgread/common.o +extern u32 NullDriveDiscType; +//maybe - seems to all be one-time inits ; needs special handler +//extern Disc* disc; +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; +//settings can be dynamic +//extern settings_t settings; + + + + +//./core/reios/reios.o +//never used +//extern u8* biosrom; +//one time init +//extern u8* flashrom; +//one time init +//extern u32 base_fad ; +//one time init +//extern bool descrambl; +//one time init +//extern bool bootfile_inited; +//all these reios_?? are one-time inits +//extern char reios_bootfile[32]; +//extern char reios_hardware_id[17]; +//extern char reios_maker_id[17]; +//extern char reios_device_info[17]; +//extern char reios_area_symbols[9]; +//extern char reios_peripherals[9]; +//extern char reios_product_number[11]; +//extern char reios_product_version[7]; +//extern char reios_releasedate[17]; +//extern char reios_boot_filename[17]; +//extern char reios_software_company[17]; +//extern char reios_software_name[129]; +//one time init +//extern map hooks; +//one time init +//extern map hooks_rev; + + + + +//./core/reios/gdrom_hle.o +//never used in any meaningful way +//extern u32 SecMode[4]; + + + + +//./core/reios/descrambl.o +//random seeds can be...random +//extern unsigned int seed; + + + +//./core/rend/gles/gles.o +//maybe +//extern GLCache glcache; +//maybe +//extern gl_ctx gl; +//maybe +//extern struct ShaderUniforms_t ShaderUniforms; +//maybe +//extern u32 gcflip; +//maybe +//extern float fb_scale_x; +//extern float fb_scale_y; +//extern float scale_x; +//extern float scale_y; +//extern int screen_width; +//extern int screen_height; +//extern GLuint fogTextureId; +//end maybe + + + +//./core/rend/gles/gldraw.o +//maybe +//extern PipelineShader* CurrentShader; +//written, but never used +//extern Vertex* vtx_sort_base; +//maybe +//extern vector pidx_sort; + + + + +//./core/rend/gles/gltex.o +//maybe ; special handler +//extern map TexCache; +//maybe +//extern FBT fb_rtt; +//not used +//static int TexCacheLookups; +//static int TexCacheHits; +//static float LastTexCacheStats; +//maybe should get reset naturally if needed +//GLuint fbTextureId; + + + + +//./core/hw/naomi/naomi.o +extern u32 naomi_updates; +extern u32 RomPioOffset; +extern u32 DmaOffset; +extern u32 DmaCount; +extern u32 BoardID; +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[]; +extern u32 reg_dimm_3c; //IO window ! writen, 0x1E03 some flag ? +extern u32 reg_dimm_40; //parameters +extern u32 reg_dimm_44; //parameters +extern u32 reg_dimm_48; //parameters +extern u32 reg_dimm_4c; //status/control reg ? +extern bool NaomiDataRead; +extern u32 NAOMI_ROM_OFFSETH; +extern u32 NAOMI_ROM_OFFSETL; +extern u32 NAOMI_ROM_DATA; +extern u32 NAOMI_DMA_OFFSETH; +extern u32 NAOMI_DMA_OFFSETL; +extern u32 NAOMI_DMA_COUNT; +extern u32 NAOMI_BOARDID_WRITE; +extern u32 NAOMI_BOARDID_READ; +extern u32 NAOMI_COMM_OFFSET; +extern u32 NAOMI_COMM_DATA; + + + + +//./core/hw/naomi/naomi_cart.o +//all one-time loads +//u8* RomPtr; +//u32 RomSize; +//fd_t* RomCacheMap; +//u32 RomCacheMapCount; + + + + +//./core/rec-x64/rec_x64.o +//maybe need special handler +//extern BlockCompilerx64 *compilerx64_data; + + + + +//./core/rec.o +extern int cycle_counter; +#if FEAT_SHREC == DYNAREC_CPP +extern int idxnxx; +#endif + + + +//./core/hw/sh4/dyna/decoder.o +//temp storage only +//extern RuntimeBlockInfo* blk; +extern state_t state; +extern Sh4RegType div_som_reg1; +extern Sh4RegType div_som_reg2; +extern Sh4RegType div_som_reg3; + + + + +//./core/hw/sh4/dyna/driver.o +//extern u8 SH4_TCB[CODE_SIZE+4096]; +//one time ptr set +//extern u8* CodeCache; +extern u32 LastAddr; +extern u32 LastAddr_min; +//temp storage only +//extern u32* emit_ptr; +extern char block_hash[1024]; + + + + +//./core/hw/sh4/dyna/blockmanager.o +//cleared but never read +//extern bm_List blocks_page[/*BLOCKS_IN_PAGE_LIST_COUNT*/(32*1024*1024)/4096]; +//maybe - the next three seem to be list of precompiled blocks of code - but if not found will populate +//extern bm_List all_blocks; +//extern bm_List del_blocks; +//extern blkmap_t blkmap; +//these two are never referenced +//extern u32 bm_gc_luc; +//extern u32 bm_gcf_luc; +//data is never written to this +//extern u32 PAGE_STATE[(32*1024*1024)/*RAM_SIZE*//32]; +//never read +//extern u32 total_saved; +//counter with no real controlling logic behind it +//extern u32 rebuild_counter; +//just printf output +//extern bool print_stats; + + + + +//./core/hw/sh4/dyna/shil.o +extern u32 RegisterWrite[sh4_reg_count]; +extern u32 RegisterRead[sh4_reg_count]; +extern u32 fallback_blocks; +extern u32 total_blocks; +extern u32 REMOVED_OPS; + + + + +//./core/linux-dist/main.cpp, ./core/windows/winmain.cpp , ... +extern u16 kcode[4]; +extern u8 rt[4]; +extern u8 lt[4]; +extern u32 vks[4]; +extern s8 joyx[4]; +extern s8 joyy[4]; + + +bool rc_serialize(void *src, unsigned int src_size, void **dest, unsigned int *total_size) +{ + if ( *dest != NULL ) + { + memcpy(*dest, src, src_size) ; + *dest = ((unsigned char*)*dest) + src_size ; + } + + *total_size += src_size ; + return true ; +} + +bool rc_unserialize(void *src, unsigned int src_size, void **dest, unsigned int *total_size) +{ + if ( *dest != NULL ) + { + memcpy(src, *dest, src_size) ; + *dest = ((unsigned char*)*dest) + src_size ; + } + + *total_size += src_size ; + return true ; +} + +bool register_serialize(Array& regs,void **data, unsigned int *total_size ) +{ + int i = 0 ; + + for ( i = 0 ; i < regs.Size ; i++ ) + { + REICAST_S(regs.data[i].flags) ; + REICAST_S(regs.data[i].data32) ; + } + + return true ; +} + +bool register_unserialize(Array& regs,void **data, unsigned int *total_size ) +{ + int i = 0 ; + u32 dummy = 0 ; + + for ( i = 0 ; i < regs.Size ; i++ ) + { + REICAST_US(regs.data[i].flags) ; + if ( ! (regs.data[i].flags & REG_RF) ) + REICAST_US(regs.data[i].data32) ; + else + REICAST_US(dummy) ; + } + return true ; +} + +bool dc_serialize(void **data, unsigned int *total_size) +{ + int i = 0; + int j = 0; + serialize_version_enum version = V1 ; + + *total_size = 0 ; + + //dc not initialized yet + if ( p_sh4rcb == NULL ) + return false ; + + REICAST_S(version) ; + REICAST_S(aica_interr) ; + REICAST_S(aica_reg_L) ; + REICAST_S(e68k_out) ; + REICAST_S(e68k_reg_L) ; + REICAST_S(e68k_reg_M) ; + + REICAST_SA(arm_Reg,RN_ARM_REG_COUNT); + REICAST_S(armIrqEnable); + REICAST_S(armFiqEnable); + REICAST_S(armMode); + REICAST_S(Arm7Enabled); + REICAST_SA(cpuBitsSet,256); + REICAST_S(intState); + REICAST_S(stopState); + REICAST_S(holdState); + + REICAST_S(dsp); + + for ( i = 0 ; i < 3 ; i++) + { + REICAST_S(timers[i].c_step); + REICAST_S(timers[i].m_step); + } + + + REICAST_SA(aica_ram.data,aica_ram.size) ; + REICAST_S(VREG); + REICAST_S(ARMRST); + REICAST_S(rtc_EN); + REICAST_S(dma_sched_id); + + REICAST_SA(aica_reg,0x8000); + + + + REICAST_SA(volume_lut,16); + REICAST_SA(tl_lut,256 + 768); + REICAST_SA(AEG_ATT_SPS,64); + REICAST_SA(AEG_DSR_SPS,64); + REICAST_S(pl); + REICAST_S(pr); + + channel_serialize(data, total_size) ; + + REICAST_SA(cdda_sector,CDDA_SIZE); + REICAST_S(cdda_index); + REICAST_SA(mxlr,64); + REICAST_S(samples_gen); + + + register_serialize(sb_regs, data, total_size) ; + REICAST_S(SB_ISTNRM); + REICAST_S(SB_FFST_rc); + REICAST_S(SB_FFST); + + + + //this is one-time init, no updates - don't need to serialize + //extern RomChip sys_rom; + REICAST_S(sys_nvmem.size); + REICAST_S(sys_nvmem.mask); +#ifdef FLASH_SIZE + REICAST_S(sys_nvmem.state); +#endif + REICAST_SA(sys_nvmem.data,sys_nvmem.size); + + //this is one-time init, no updates - don't need to serialize + //extern _vmem_handler area0_handler; + + + + + REICAST_SA(reply_11,16) ; + + + + REICAST_S(gdrom_schid); + REICAST_S(sns_asc); + REICAST_S(sns_ascq); + REICAST_S(sns_key); + + REICAST_S(packet_cmd); + REICAST_S(set_mode_offset); + REICAST_S(read_params); + REICAST_S(packet_cmd); + REICAST_S(read_buff); + REICAST_S(pio_buff); + REICAST_S(set_mode_offset); + REICAST_S(ata_cmd); + REICAST_S(cdda); + REICAST_S(gd_state); + REICAST_S(gd_disk_type); + REICAST_S(data_write_mode); + REICAST_S(DriveSel); + REICAST_S(Error); + REICAST_S(IntReason); + REICAST_S(Features); + REICAST_S(SecCount); + REICAST_S(SecNumber); + REICAST_S(GDStatus); + REICAST_S(ByteCount); + REICAST_S(i); // GDROM_TICKS + + + REICAST_SA(EEPROM,0x100); + REICAST_S(EEPROM_loaded); + REICAST_S(State); + + + REICAST_S(maple_ddt_pending_reset); + + for (i = 0 ; i < 4 ; i++) + for (j = 0 ; j < 6 ; j++) + if ( MapleDevices[i][j] != 0 ) + MapleDevices[i][j]->maple_serialize(data, total_size) ; + + + + REICAST_S(FrameCount); + REICAST_S(pend_rend); + + + REICAST_SA(YUV_tempdata,512/4); + 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(fog_needs_update); + REICAST_SA(pvr_regs,pvr_RegSize); + + + + + REICAST_S(in_vblank); + REICAST_S(clc_pvr_scanline); + REICAST_S(pvr_numscanlines); + REICAST_S(prv_cur_scanline); + REICAST_S(vblk_cnt); + REICAST_S(Line_Cycles); + REICAST_S(Frame_Cycles); + REICAST_S(render_end_schid); + REICAST_S(vblank_schid); + REICAST_S(time_sync); + REICAST_S(speed_load_mspdf); + REICAST_S(mips_counter); + REICAST_S(full_rps); + REICAST_S(fskip); + + + + REICAST_SA(ta_type_lut,256); + REICAST_SA(ta_fsm,2049); + REICAST_S(ta_fsm_cl); + + + REICAST_S(pal_needs_update); + for (int i = 0; i < 64 + 64 + 4 + 4; i++) + REICAST_S(i); + //REICAST_SA(_pal_rev_256,4); + //REICAST_SA(_pal_rev_16,64); + //REICAST_SA(pal_rev_256,4); + //REICAST_SA(pal_rev_16,64); + + for ( i = 0 ; i < 3 ; i++ ) + { + u32 *ptr = decoded_colors[i] ; + REICAST_SA(ptr,65536); + } + REICAST_S(tileclip_val); + REICAST_SA(f32_su8_tbl,65536); + REICAST_SA(FaceBaseColor,4); + REICAST_SA(FaceOffsColor,4); + REICAST_S(SFaceBaseColor); + REICAST_S(SFaceOffsColor); + + + REICAST_S(palette_index); + REICAST_S(KillTex); + REICAST_SA(palette16_ram,1024); + REICAST_SA(palette32_ram,1024); + for (i = 0 ; i < 2 ; i++) + for (j = 0 ; j < 8 ; j++) + { + u32 *ptr = detwiddle[i][j] ; + REICAST_SA(ptr,1024); + } + REICAST_SA(vram.data, vram.size); + + + + + REICAST_SA(OnChipRAM.data,OnChipRAM_SIZE); + + register_serialize(CCN, data, total_size) ; + register_serialize(UBC, data, total_size) ; + register_serialize(BSC, data, total_size) ; + register_serialize(DMAC, data, total_size) ; + register_serialize(CPG, data, total_size) ; + register_serialize(RTC, data, total_size) ; + register_serialize(INTC, data, total_size) ; + register_serialize(TMU, data, total_size) ; + register_serialize(SCI, data, total_size) ; + register_serialize(SCIF, data, total_size) ; + + REICAST_SA(mem_b.data, mem_b.size); + + + + REICAST_S(IRLPriority); + REICAST_SA(InterruptEnvId,32); + REICAST_SA(InterruptBit,32); + REICAST_SA(InterruptLevelBit,16); + REICAST_S(interrupt_vpend); + REICAST_S(interrupt_vmask); + REICAST_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 ; + + REICAST_S(i) ; + + REICAST_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) ; + REICAST_S((*p_sh4rcb).cntx); + + REICAST_S(old_rm); + REICAST_S(old_dn); + + + + + REICAST_S(sh4_sched_ffb); + REICAST_S(sh4_sched_intr); + REICAST_S(sh4_sched_next_id); + //this list is populated during initialization so the size will always be the same + //extern vector list; + for ( i = 0 ; i < list.size() ; i++ ) + { + REICAST_S(list[i].tag) ; + REICAST_S(list[i].start) ; + REICAST_S(list[i].end) ; + } + + + + REICAST_S(aica_schid); + REICAST_S(rtc_schid); + + + REICAST_S(SCIF_SCFSR2); + REICAST_S(SCIF_SCFRDR2); + REICAST_S(SCIF_SCFDR2); + + + REICAST_S(BSC_PDTRA); + + + + + REICAST_SA(tmu_shift,3); + REICAST_SA(tmu_mask,3); + REICAST_SA(tmu_mask64,3); + REICAST_SA(old_mode,3); + REICAST_SA(tmu_sched,3); + REICAST_SA(tmu_ch_base,3); + REICAST_SA(tmu_ch_base64,3); + + + + + REICAST_SA(CCN_QACR_TR,2); + + + + + REICAST_SA(UTLB,64); + REICAST_SA(ITLB,4); +#if defined(NO_MMU) + REICAST_SA(sq_remap,64); +#else + REICAST_SA(ITLB_LRU_USE,64); + REICAST_S(mmu_error_TT); +#endif + + + + REICAST_S(NullDriveDiscType); + REICAST_SA(q_subchannel,96); + + REICAST_S(naomi_updates); + REICAST_S(RomPioOffset); + REICAST_S(DmaOffset); + REICAST_S(DmaCount); + REICAST_S(BoardID); + 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_3c); + REICAST_S(reg_dimm_40); + REICAST_S(reg_dimm_44); + REICAST_S(reg_dimm_48); + REICAST_S(reg_dimm_4c); + REICAST_S(NaomiDataRead); + REICAST_S(NAOMI_ROM_OFFSETH); + REICAST_S(NAOMI_ROM_OFFSETL); + REICAST_S(NAOMI_ROM_DATA); + REICAST_S(NAOMI_DMA_OFFSETH); + REICAST_S(NAOMI_DMA_OFFSETL); + REICAST_S(NAOMI_DMA_COUNT); + REICAST_S(NAOMI_BOARDID_WRITE); + REICAST_S(NAOMI_BOARDID_READ); + REICAST_S(NAOMI_COMM_OFFSET); + REICAST_S(NAOMI_COMM_DATA); + + REICAST_S(cycle_counter); +#if FEAT_SHREC == DYNAREC_CPP + REICAST_S(idxnxx); +#else + REICAST_S(i); +#endif + + REICAST_S(state); + REICAST_S(div_som_reg1); + REICAST_S(div_som_reg2); + REICAST_S(div_som_reg3); + + + + REICAST_S(LastAddr); + REICAST_S(LastAddr_min); + REICAST_SA(block_hash,1024); + + + REICAST_SA(RegisterWrite,sh4_reg_count); + REICAST_SA(RegisterRead,sh4_reg_count); + REICAST_S(fallback_blocks); + REICAST_S(total_blocks); + REICAST_S(REMOVED_OPS); + + + + + REICAST_SA(kcode,4); + REICAST_SA(rt,4); + REICAST_SA(lt,4); + REICAST_SA(vks,4); + REICAST_SA(joyx,4); + REICAST_SA(joyy,4); + + + + return true ; +} + +bool dc_unserialize(void **data, unsigned int *total_size) +{ + int i = 0; + int j = 0; + serialize_version_enum version = V1 ; + + *total_size = 0 ; + + REICAST_US(version) ; + REICAST_US(aica_interr) ; + REICAST_US(aica_reg_L) ; + REICAST_US(e68k_out) ; + REICAST_US(e68k_reg_L) ; + REICAST_US(e68k_reg_M) ; + + REICAST_USA(arm_Reg,RN_ARM_REG_COUNT); + REICAST_US(armIrqEnable); + REICAST_US(armFiqEnable); + REICAST_US(armMode); + REICAST_US(Arm7Enabled); + REICAST_USA(cpuBitsSet,256); + REICAST_US(intState); + REICAST_US(stopState); + REICAST_US(holdState); + + REICAST_US(dsp); + + for ( i = 0 ; i < 3 ; i++) + { + REICAST_US(timers[i].c_step); + REICAST_US(timers[i].m_step); + } + + + REICAST_USA(aica_ram.data,aica_ram.size) ; + REICAST_US(VREG); + REICAST_US(ARMRST); + REICAST_US(rtc_EN); + REICAST_US(dma_sched_id); + + REICAST_USA(aica_reg,0x8000); + + + + REICAST_USA(volume_lut,16); + REICAST_USA(tl_lut,256 + 768); + REICAST_USA(AEG_ATT_SPS,64); + REICAST_USA(AEG_DSR_SPS,64); + REICAST_US(pl); + REICAST_US(pr); + + channel_unserialize(data, total_size) ; + + REICAST_USA(cdda_sector,CDDA_SIZE); + REICAST_US(cdda_index); + REICAST_USA(mxlr,64); + REICAST_US(samples_gen); + + + register_unserialize(sb_regs, data, total_size) ; + REICAST_US(SB_ISTNRM); + REICAST_US(SB_FFST_rc); + REICAST_US(SB_FFST); + + + + //this is one-time init, no updates - don't need to serialize + //extern RomChip sys_rom; + REICAST_US(sys_nvmem.size); + REICAST_US(sys_nvmem.mask); +#ifdef FLASH_SIZE + REICAST_US(sys_nvmem.state); +#endif + REICAST_USA(sys_nvmem.data,sys_nvmem.size); + + + //this is one-time init, no updates - don't need to serialize + //extern _vmem_handler area0_handler; + + + + + REICAST_USA(reply_11,16) ; + + + + REICAST_US(gdrom_schid); + REICAST_US(sns_asc); + REICAST_US(sns_ascq); + REICAST_US(sns_key); + + REICAST_US(packet_cmd); + REICAST_US(set_mode_offset); + REICAST_US(read_params); + REICAST_US(packet_cmd); + REICAST_US(read_buff); + REICAST_US(pio_buff); + REICAST_US(set_mode_offset); + REICAST_US(ata_cmd); + REICAST_US(cdda); + REICAST_US(gd_state); + REICAST_US(gd_disk_type); + REICAST_US(data_write_mode); + REICAST_US(DriveSel); + REICAST_US(Error); + REICAST_US(IntReason); + REICAST_US(Features); + REICAST_US(SecCount); + REICAST_US(SecNumber); + REICAST_US(GDStatus); + REICAST_US(ByteCount); + REICAST_US(i); // GDROM_TICKS + + + REICAST_USA(EEPROM,0x100); + REICAST_US(EEPROM_loaded); + REICAST_US(State); + + + REICAST_US(maple_ddt_pending_reset); + + for (i = 0 ; i < 4 ; i++) + for (j = 0 ; j < 6 ; j++) + if ( MapleDevices[i][j] != 0 ) + MapleDevices[i][j]->maple_unserialize(data, total_size) ; + + + + REICAST_US(FrameCount); + REICAST_US(pend_rend); + + + REICAST_USA(YUV_tempdata,512/4); + 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); + + + + + REICAST_US(fog_needs_update); + REICAST_USA(pvr_regs,pvr_RegSize); + fog_needs_update = true ; + + + REICAST_US(in_vblank); + REICAST_US(clc_pvr_scanline); + REICAST_US(pvr_numscanlines); + REICAST_US(prv_cur_scanline); + REICAST_US(vblk_cnt); + REICAST_US(Line_Cycles); + REICAST_US(Frame_Cycles); + REICAST_US(render_end_schid); + REICAST_US(vblank_schid); + REICAST_US(time_sync); + REICAST_US(speed_load_mspdf); + REICAST_US(mips_counter); + REICAST_US(full_rps); + REICAST_US(fskip); + + + + REICAST_USA(ta_type_lut,256); + REICAST_USA(ta_fsm,2049); + REICAST_US(ta_fsm_cl); + + + REICAST_US(pal_needs_update); + for (int i = 0; i < 64 + 64 + 4 + 4; i++) + REICAST_US(j); + //REICAST_USA(_pal_rev_256,4); + //REICAST_USA(_pal_rev_16,64); + //REICAST_USA(pal_rev_256,4); + //REICAST_USA(pal_rev_16,64); + for ( i = 0 ; i < 3 ; i++ ) + { + u32 *ptr = decoded_colors[i] ; + REICAST_USA(ptr,65536); + } + REICAST_US(tileclip_val); + REICAST_USA(f32_su8_tbl,65536); + REICAST_USA(FaceBaseColor,4); + REICAST_USA(FaceOffsColor,4); + REICAST_US(SFaceBaseColor); + REICAST_US(SFaceOffsColor); + + + REICAST_US(palette_index); + REICAST_US(KillTex); + REICAST_USA(palette16_ram,1024); + REICAST_USA(palette32_ram,1024); + pal_needs_update = true; + for (i = 0 ; i < 2 ; i++) + for (j = 0 ; j < 8 ; j++) + { + u32 *ptr = detwiddle[i][j] ; + REICAST_USA(ptr,1024); + } + REICAST_USA(vram.data, vram.size); + + + + + REICAST_USA(OnChipRAM.data,OnChipRAM_SIZE); + + register_unserialize(CCN, data, total_size) ; + 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) ; + register_unserialize(TMU, data, total_size) ; + register_unserialize(SCI, data, total_size) ; + register_unserialize(SCIF, data, total_size) ; + + REICAST_USA(mem_b.data, mem_b.size); + + + + REICAST_US(IRLPriority); + REICAST_USA(InterruptEnvId,32); + REICAST_USA(InterruptBit,32); + REICAST_USA(InterruptLevelBit,16); + REICAST_US(interrupt_vpend); + REICAST_US(interrupt_vmask); + REICAST_US(decoded_srimask); + + + + + REICAST_US(i) ; + if ( i == 0 ) + do_sqw_nommu = &do_sqw_nommu_area_3 ; + else if ( i == 1 ) + do_sqw_nommu = &do_sqw_nommu_area_3_nonvmem ; + else if ( i == 2 ) + do_sqw_nommu = (sqw_fp*)&TAWriteSQ ; + else if ( i == 3 ) + do_sqw_nommu = &do_sqw_nommu_full ; + + + + REICAST_USA((*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) ; + REICAST_US((*p_sh4rcb).cntx); + //(*p_sh4rcb).cntx.sr.GetFull = getptr ; + //(*p_sh4rcb).cntx.sr.SetFull = setptr ; + + REICAST_US(old_rm); + REICAST_US(old_dn); + + + + + REICAST_US(sh4_sched_ffb); + REICAST_US(sh4_sched_intr); + REICAST_US(sh4_sched_next_id); + //this list is populated during initialization so the size will always be the same + //extern vector list; + for ( i = 0 ; i < list.size() ; i++ ) + { + REICAST_US(list[i].tag) ; + REICAST_US(list[i].start) ; + REICAST_US(list[i].end) ; + } + + + + REICAST_US(aica_schid); + REICAST_US(rtc_schid); + + + REICAST_US(SCIF_SCFSR2); + REICAST_US(SCIF_SCFRDR2); + REICAST_US(SCIF_SCFDR2); + + + REICAST_US(BSC_PDTRA); + + + + + REICAST_USA(tmu_shift,3); + REICAST_USA(tmu_mask,3); + REICAST_USA(tmu_mask64,3); + REICAST_USA(old_mode,3); + REICAST_USA(tmu_sched,3); + REICAST_USA(tmu_ch_base,3); + REICAST_USA(tmu_ch_base64,3); + + + + + REICAST_USA(CCN_QACR_TR,2); + + + + + REICAST_USA(UTLB,64); + REICAST_USA(ITLB,4); +#if defined(NO_MMU) + REICAST_USA(sq_remap,64); +#else + REICAST_USA(ITLB_LRU_USE,64); + REICAST_US(mmu_error_TT); +#endif + + + + + REICAST_US(NullDriveDiscType); + REICAST_USA(q_subchannel,96); + +// FIXME +// REICAST_US(i); // FLASH_SIZE +// REICAST_US(i); // BBSRAM_SIZE +// REICAST_US(i); // BIOS_SIZE +// REICAST_US(i); // RAM_SIZE +// REICAST_US(i); // ARAM_SIZE +// REICAST_US(i); // VRAM_SIZE +// REICAST_US(i); // RAM_MASK +// REICAST_US(i); // ARAM_MASK +// REICAST_US(i); // VRAM_MASK + + + + REICAST_US(naomi_updates); + REICAST_US(RomPioOffset); + REICAST_US(DmaOffset); + REICAST_US(DmaCount); + REICAST_US(BoardID); + 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_3c); + REICAST_US(reg_dimm_40); + REICAST_US(reg_dimm_44); + REICAST_US(reg_dimm_48); + REICAST_US(reg_dimm_4c); + REICAST_US(NaomiDataRead); + REICAST_US(NAOMI_ROM_OFFSETH); + REICAST_US(NAOMI_ROM_OFFSETL); + REICAST_US(NAOMI_ROM_DATA); + REICAST_US(NAOMI_DMA_OFFSETH); + REICAST_US(NAOMI_DMA_OFFSETL); + REICAST_US(NAOMI_DMA_COUNT); + REICAST_US(NAOMI_BOARDID_WRITE); + REICAST_US(NAOMI_BOARDID_READ); + REICAST_US(NAOMI_COMM_OFFSET); + REICAST_US(NAOMI_COMM_DATA); + + REICAST_US(cycle_counter); +#if FEAT_SHREC == DYNAREC_CPP + REICAST_US(idxnxx); +#else + REICAST_US(i); +#endif + + REICAST_US(state); + REICAST_US(div_som_reg1); + REICAST_US(div_som_reg2); + REICAST_US(div_som_reg3); + + + + + //REICAST_USA(CodeCache,CODE_SIZE) ; + //REICAST_USA(SH4_TCB,CODE_SIZE+4096); + REICAST_US(LastAddr); + REICAST_US(LastAddr_min); + REICAST_USA(block_hash,1024); + + + REICAST_USA(RegisterWrite,sh4_reg_count); + REICAST_USA(RegisterRead,sh4_reg_count); + REICAST_US(fallback_blocks); + REICAST_US(total_blocks); + REICAST_US(REMOVED_OPS); + + + + + REICAST_USA(kcode,4); + REICAST_USA(rt,4); + REICAST_USA(lt,4); + REICAST_USA(vks,4); + REICAST_USA(joyx,4); + REICAST_USA(joyy,4); + + return true ; +} +#endif diff --git a/core/stdclass.h b/core/stdclass.h index 133e08c53..6b76b4d35 100644 --- a/core/stdclass.h +++ b/core/stdclass.h @@ -238,6 +238,14 @@ public : EnterCriticalSection(&cs); #else pthread_mutex_lock(&mutx); +#endif + } + bool TryLock() + { +#if HOST_OS==OS_WINDOWS + return TryEnterCriticalSection(&cs); +#else + return pthread_mutex_trylock(&mutx)==0; #endif } void Unlock() diff --git a/core/types.h b/core/types.h index 3be2a2cfa..81c7a2f08 100644 --- a/core/types.h +++ b/core/types.h @@ -521,6 +521,102 @@ using namespace std; void os_DebugBreak(); #define dbgbreak os_DebugBreak() +bool rc_serialize(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 dc_unserialize(void **data, unsigned int *total_size); + +#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) + +enum +{ + RN_CPSR = 16, + RN_SPSR = 17, + + R13_IRQ = 18, + R14_IRQ = 19, + SPSR_IRQ = 20, + R13_USR = 26, + R14_USR = 27, + R13_SVC = 28, + R14_SVC = 29, + SPSR_SVC = 30, + R13_ABT = 31, + R14_ABT = 32, + SPSR_ABT = 33, + R13_UND = 34, + R14_UND = 35, + SPSR_UND = 36, + R8_FIQ = 37, + R9_FIQ = 38, + R10_FIQ = 39, + R11_FIQ = 40, + R12_FIQ = 41, + R13_FIQ = 42, + R14_FIQ = 43, + SPSR_FIQ = 44, + RN_PSR_FLAGS = 45, + R15_ARM_NEXT = 46, + INTR_PEND = 47, + CYCL_CNT = 48, + + RN_ARM_REG_COUNT, +}; + +typedef union +{ + struct + { + u8 B0; + u8 B1; + u8 B2; + u8 B3; + } B; + + struct + { + u16 W0; + u16 W1; + } W; + + union + { + struct + { + u32 _pad0 : 28; + u32 V : 1; //Bit 28 + u32 C : 1; //Bit 29 + u32 Z : 1; //Bit 30 + u32 N : 1; //Bit 31 + }; + + struct + { + u32 _pad1 : 28; + u32 NZCV : 4; //Bits [31:28] + }; + } FLG; + + struct + { + u32 M : 5; //mode, PSR[4:0] + u32 _pad0 : 1; //not used / zero + u32 F : 1; //FIQ disable, PSR[6] + u32 I : 1; //IRQ disable, PSR[7] + u32 _pad1 : 20; //not used / zero + u32 NZCV : 4; //Bits [31:28] + } PSR; + + u32 I; +} reg_pair; + + + + #if COMPILER_VC==BUILD_COMPILER #pragma warning( disable : 4127 4996 /*4244*/) #else diff --git a/shell/linux/mappings/controller_generic.cfg b/shell/linux/mappings/controller_generic.cfg index b6470dfb3..085d45c21 100644 --- a/shell/linux/mappings/controller_generic.cfg +++ b/shell/linux/mappings/controller_generic.cfg @@ -1,6 +1,8 @@ [emulator] mapping_name = Generic Controller btn_escape = 0x13a +btn_savestate = 0x3c +btn_loadstate = 0x3e [dreamcast] btn_a = 0x130