add save states
This commit is contained in:
parent
a8711e2cf2
commit
daae7c8e68
|
@ -35,6 +35,11 @@ reicast-ios.xccheckout
|
|||
shell/linux/.map
|
||||
shell/linux/nosym-reicast.elf
|
||||
shell/linux/reicast.elf
|
||||
.map
|
||||
nosym-reicast.elf
|
||||
reicast.elf
|
||||
Makefile
|
||||
|
||||
|
||||
# Visual Studio
|
||||
generated
|
||||
|
|
|
@ -82,6 +82,7 @@ bool cfgOpen()
|
|||
string config_path_read = get_readonly_config_path(filename);
|
||||
cfgPath = get_writable_config_path(filename);
|
||||
|
||||
printf("opening cfg file %s\n", config_path_read.c_str()) ;
|
||||
FILE* cfgfile = fopen(config_path_read.c_str(),"r");
|
||||
if(cfgfile != NULL) {
|
||||
cfgdb.parse(cfgfile);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -312,3 +312,75 @@ void WriteAicaReg8(u32 reg,u32 data);
|
|||
|
||||
template<u32 sz>
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -93,18 +93,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)
|
||||
|
@ -324,13 +312,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<<AEG_STEP_BITS; }
|
||||
|
||||
_EG_state state;
|
||||
_EG_state state=EG_Attack;
|
||||
|
||||
u32 AttackRate;
|
||||
u32 Decay1Rate;
|
||||
|
@ -342,7 +334,7 @@ struct ChannelEx
|
|||
struct
|
||||
{
|
||||
s32 value;
|
||||
_EG_state state;
|
||||
_EG_state state=EG_Attack;
|
||||
} FEG;//i have to figure out how this works w/ AEG and channel state, and the iir values
|
||||
|
||||
struct
|
||||
|
@ -354,6 +346,8 @@ struct ChannelEx
|
|||
u8 alfo_shft;
|
||||
u8 plfo;
|
||||
u8 plfo_shft;
|
||||
u8 alfo_calc_lut=0 ;
|
||||
u8 plfo_calc_lut=0 ;
|
||||
void (* alfo_calc)(ChannelEx* ch);
|
||||
void (* plfo_calc)(ChannelEx* ch);
|
||||
__forceinline void Step(ChannelEx* ch) { counter--;if (counter==0) { state++; counter=start_value; alfo_calc(ch);plfo_calc(ch); } }
|
||||
|
@ -363,6 +357,7 @@ struct ChannelEx
|
|||
|
||||
bool enabled; //set to false to 'freeze' the channel
|
||||
int ChanelNumber;
|
||||
|
||||
void Init(int cn,u8* ccd_raw)
|
||||
{
|
||||
ccd=(ChannelCommonData*)&ccd_raw[cn*0x80];
|
||||
|
@ -516,6 +511,9 @@ struct ChannelEx
|
|||
|
||||
StepStream=STREAM_STEP_LUT[fmt][ccd->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()
|
||||
|
@ -590,6 +588,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)
|
||||
{
|
||||
|
@ -935,7 +935,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<u32 state>
|
||||
|
@ -1169,7 +1169,7 @@ s16 cdda_sector[CDDA_SIZE]={0};
|
|||
u32 cdda_index=CDDA_SIZE<<1;
|
||||
|
||||
|
||||
static SampleType mxlr[64];
|
||||
SampleType mxlr[64];
|
||||
|
||||
u32 samples_gen;
|
||||
|
||||
|
@ -1381,3 +1381,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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -286,6 +286,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));
|
||||
|
@ -701,6 +715,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));
|
||||
|
@ -883,6 +907,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)
|
||||
|
@ -972,12 +1010,6 @@ struct maple_sega_purupuru : maple_base
|
|||
char EEPROM[0x100];
|
||||
bool EEPROM_loaded = false;
|
||||
|
||||
struct _NaomiState
|
||||
{
|
||||
u8 Cmd;
|
||||
u8 Mode;
|
||||
u8 Node;
|
||||
};
|
||||
_NaomiState State;
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -83,10 +83,10 @@ PolyParam* CurrentPP=&nullPP;
|
|||
List<PolyParam>* 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;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include "blockmanager.h"
|
||||
#include "ngen.h"
|
||||
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
@ -1042,10 +988,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;
|
||||
|
@ -1222,4 +1188,5 @@ _end:
|
|||
blk=0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -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;
|
||||
|
||||
} ;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -269,6 +277,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;
|
||||
|
|
|
@ -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,<REG_N>
|
||||
|
@ -2155,7 +2155,7 @@ sh4op(i0100_nnnn_0000_0011)
|
|||
//iNimp("stc.l SR,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], sr.GetFull());
|
||||
WriteMemU32(r[n], sh4_sr_GetFull());
|
||||
}
|
||||
|
||||
//lds.l @<REG_N>+,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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<typename T>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<sched_list> list;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
libevdev_func2_t libevdev_event_code_get_name;
|
||||
|
||||
void dc_stop(void);
|
||||
bool dc_loadstate(void);
|
||||
bool dc_savestate(void);
|
||||
|
||||
void load_libevdev()
|
||||
{
|
||||
|
@ -179,6 +181,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"),
|
||||
|
@ -222,6 +226,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)
|
||||
|
@ -245,6 +251,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)
|
||||
|
@ -351,6 +359,7 @@
|
|||
size_t size_needed = snprintf(NULL, 0, EVDEV_MAPPING_PATH, mapping_fname) + 1;
|
||||
char* mapping_path = (char*)malloc(size_needed);
|
||||
sprintf(mapping_path, EVDEV_MAPPING_PATH, mapping_fname);
|
||||
printf("evdev: mapping file : %s\n", get_readonly_data_path(mapping_path).c_str()) ;
|
||||
mapping_fd = fopen(get_readonly_data_path(mapping_path).c_str(), "r");
|
||||
free(mapping_path);
|
||||
}
|
||||
|
@ -359,6 +368,7 @@
|
|||
{
|
||||
printf("evdev: reading mapping file: '%s'\n", mapping_fname);
|
||||
loaded_mappings.insert(std::make_pair(string(mapping_fname), load_mapping(mapping_fd)));
|
||||
printf("evdev: read mapping file\n") ;
|
||||
fclose(mapping_fd);
|
||||
|
||||
}
|
||||
|
@ -416,6 +426,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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -42,6 +42,8 @@ Atom wmDeleteMessage;
|
|||
void* x11_vis;
|
||||
|
||||
void dc_stop(void);
|
||||
bool dc_loadstate(void);
|
||||
bool dc_savestate(void);
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -113,6 +115,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];
|
||||
|
|
256
core/nullDC.cpp
256
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 <windows.h>
|
||||
#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");
|
||||
|
@ -252,9 +293,26 @@ int dc_init()
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool dc_is_running()
|
||||
{
|
||||
return sh4_cpu.IsCpuRunning();
|
||||
}
|
||||
|
||||
void dc_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 ;
|
||||
}
|
||||
}
|
||||
|
||||
void dc_term()
|
||||
|
@ -283,6 +341,11 @@ void dc_stop()
|
|||
sh4_cpu.Stop();
|
||||
}
|
||||
|
||||
void dc_start()
|
||||
{
|
||||
sh4_cpu.Start();
|
||||
}
|
||||
|
||||
void LoadSettings()
|
||||
{
|
||||
#ifndef _ANDROID
|
||||
|
@ -380,3 +443,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", filename) ;
|
||||
|
||||
}
|
||||
|
||||
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\n", filename) ;
|
||||
}
|
||||
|
||||
|
||||
void dc_savestate()
|
||||
{
|
||||
cThread thd(dc_savestate_thread,0);
|
||||
thd.Start() ;
|
||||
}
|
||||
|
||||
void dc_loadstate()
|
||||
{
|
||||
cThread thd(dc_loadstate_thread,0);
|
||||
thd.Start() ;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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()
|
||||
|
|
96
core/types.h
96
core/types.h
|
@ -517,6 +517,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
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
[emulator]
|
||||
mapping_name = Generic Controller
|
||||
btn_escape = 0x13a
|
||||
btn_savestate = 0x3c
|
||||
btn_loadstate = 0x3e
|
||||
|
||||
[dreamcast]
|
||||
btn_a = 0x130
|
||||
|
|
Loading…
Reference in New Issue