m64p: Made two new functions for saving and loading states, directly based on the m64p methods but without files

N64: Copied savestating code from other cores. States take a while to save, and the audio is weird when loading.
This commit is contained in:
pjgat09 2013-05-04 04:07:04 +00:00
parent 04ae097832
commit 55c7fc55ab
3 changed files with 499 additions and 5 deletions

View File

@ -76,7 +76,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64
public int Frame { get; set; }
public int LagCount { get; set; }
public bool IsLagFrame { get { return true; } }
public bool IsLagFrame { get; set; }
public void ResetFrameCounter() { }
public void FrameAdvance(bool render, bool rendersound)
{
@ -138,10 +138,60 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64
ser.EndSection();
}
public void SaveStateText(TextWriter writer) { SyncState(Serializer.CreateTextWriter(writer)); }
public void LoadStateText(TextReader reader) { SyncState(Serializer.CreateTextReader(reader)); }
public void SaveStateBinary(BinaryWriter bw) { SyncState(Serializer.CreateBinaryWriter(bw)); }
public void LoadStateBinary(BinaryReader br) { SyncState(Serializer.CreateBinaryReader(br)); }
// these next 5 functions are all exact copy paste from gambatte.
// if something's wrong here, it's probably wrong there too
public void SaveStateText(TextWriter writer)
{
var temp = SaveStateBinary();
temp.SaveAsHex(writer);
// write extra copy of stuff we don't use
writer.WriteLine("Frame {0}", Frame);
}
public void LoadStateText(TextReader reader)
{
string hex = reader.ReadLine();
if (hex.StartsWith("emuVersion")) // movie save
{
do // theoretically, our portion should start right after StartsFromSavestate, maybe...
{
hex = reader.ReadLine();
} while (!hex.StartsWith("StartsFromSavestate"));
hex = reader.ReadLine();
}
byte[] state = new byte[hex.Length / 2];
state.ReadFromHex(hex);
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
}
public void SaveStateBinary(BinaryWriter writer)
{
byte[] data = new byte[16788288 + 1024];
int bytes_used = m64pCoreSaveState(data);
writer.Write(data.Length);
writer.Write(data);
// other variables
writer.Write(IsLagFrame);
writer.Write(LagCount);
writer.Write(Frame);
}
public void LoadStateBinary(BinaryReader reader)
{
int length = reader.ReadInt32();
byte[] data = reader.ReadBytes(length);
m64pCoreLoadState(data);
// other variables
IsLagFrame = reader.ReadBoolean();
LagCount = reader.ReadInt32();
Frame = reader.ReadInt32();
}
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream();
@ -293,6 +343,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate m64p_error ConfigSetParameter(IntPtr ConfigSectionHandle, string ParamName, m64p_type ParamType, ref int ParamValue);
ConfigSetParameter m64pConfigSetParameter;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int CoreSaveState(byte[] buffer);
CoreSaveState m64pCoreSaveState;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int CoreLoadState(byte[] buffer);
CoreLoadState m64pCoreLoadState;
// The last parameter is a void pointer, so make a few delegates for the versions we want to use
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@ -465,6 +521,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64
m64pCoreDetachPlugin = (CoreDetachPlugin)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "CoreDetachPlugin"), typeof(CoreDetachPlugin));
m64pConfigOpenSection = (ConfigOpenSection)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "ConfigOpenSection"), typeof(ConfigOpenSection));
m64pConfigSetParameter = (ConfigSetParameter)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "ConfigSetParameter"), typeof(ConfigSetParameter));
m64pCoreSaveState = (CoreSaveState)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_save_bkm"), typeof(CoreSaveState));
m64pCoreLoadState = (CoreLoadState)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "savestates_load_bkm"), typeof(CoreLoadState));
GfxPluginStartup = (PluginStartup)Marshal.GetDelegateForFunctionPointer(GetProcAddress(GfxDll, "PluginStartup"), typeof(PluginStartup));
GfxPluginShutdown = (PluginShutdown)Marshal.GetDelegateForFunctionPointer(GetProcAddress(GfxDll, "PluginShutdown"), typeof(PluginShutdown));

View File

@ -474,6 +474,201 @@ static int savestates_load_m64p(char *filepath)
return 1;
}
EXPORT int CALL savestates_load_bkm(char * curr)
{
unsigned char header[44];
int version;
int i;
size_t savestateSize;
unsigned char *savestateData;
char *queue = curr + 16788288;
curr += 44;
// Parse savestate
rdram_register.rdram_config = GETDATA(curr, unsigned int);
rdram_register.rdram_device_id = GETDATA(curr, unsigned int);
rdram_register.rdram_delay = GETDATA(curr, unsigned int);
rdram_register.rdram_mode = GETDATA(curr, unsigned int);
rdram_register.rdram_ref_interval = GETDATA(curr, unsigned int);
rdram_register.rdram_ref_row = GETDATA(curr, unsigned int);
rdram_register.rdram_ras_interval = GETDATA(curr, unsigned int);
rdram_register.rdram_min_interval = GETDATA(curr, unsigned int);
rdram_register.rdram_addr_select = GETDATA(curr, unsigned int);
rdram_register.rdram_device_manuf = GETDATA(curr, unsigned int);
MI_register.w_mi_init_mode_reg = GETDATA(curr, unsigned int);
MI_register.mi_init_mode_reg = GETDATA(curr, unsigned int);
curr += 4; // Duplicate MI init mode flags from old implementation
MI_register.mi_version_reg = GETDATA(curr, unsigned int);
MI_register.mi_intr_reg = GETDATA(curr, unsigned int);
MI_register.mi_intr_mask_reg = GETDATA(curr, unsigned int);
MI_register.w_mi_intr_mask_reg = GETDATA(curr, unsigned int);
curr += 8; // Duplicated MI intr flags and padding from old implementation
pi_register.pi_dram_addr_reg = GETDATA(curr, unsigned int);
pi_register.pi_cart_addr_reg = GETDATA(curr, unsigned int);
pi_register.pi_rd_len_reg = GETDATA(curr, unsigned int);
pi_register.pi_wr_len_reg = GETDATA(curr, unsigned int);
pi_register.read_pi_status_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom1_lat_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom1_pwd_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom1_pgs_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom1_rls_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom2_lat_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom2_pwd_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom2_pgs_reg = GETDATA(curr, unsigned int);
pi_register.pi_bsd_dom2_rls_reg = GETDATA(curr, unsigned int);
sp_register.sp_mem_addr_reg = GETDATA(curr, unsigned int);
sp_register.sp_dram_addr_reg = GETDATA(curr, unsigned int);
sp_register.sp_rd_len_reg = GETDATA(curr, unsigned int);
sp_register.sp_wr_len_reg = GETDATA(curr, unsigned int);
sp_register.w_sp_status_reg = GETDATA(curr, unsigned int);
sp_register.sp_status_reg = GETDATA(curr, unsigned int);
curr += 16; // Duplicated SP flags and padding from old implementation
sp_register.sp_dma_full_reg = GETDATA(curr, unsigned int);
sp_register.sp_dma_busy_reg = GETDATA(curr, unsigned int);
sp_register.sp_semaphore_reg = GETDATA(curr, unsigned int);
rsp_register.rsp_pc = GETDATA(curr, unsigned int);
rsp_register.rsp_ibist = GETDATA(curr, unsigned int);
si_register.si_dram_addr = GETDATA(curr, unsigned int);
si_register.si_pif_addr_rd64b = GETDATA(curr, unsigned int);
si_register.si_pif_addr_wr64b = GETDATA(curr, unsigned int);
si_register.si_stat = GETDATA(curr, unsigned int);
vi_register.vi_status = GETDATA(curr, unsigned int);
vi_register.vi_origin = GETDATA(curr, unsigned int);
vi_register.vi_width = GETDATA(curr, unsigned int);
vi_register.vi_v_intr = GETDATA(curr, unsigned int);
vi_register.vi_current = GETDATA(curr, unsigned int);
vi_register.vi_burst = GETDATA(curr, unsigned int);
vi_register.vi_v_sync = GETDATA(curr, unsigned int);
vi_register.vi_h_sync = GETDATA(curr, unsigned int);
vi_register.vi_leap = GETDATA(curr, unsigned int);
vi_register.vi_h_start = GETDATA(curr, unsigned int);
vi_register.vi_v_start = GETDATA(curr, unsigned int);
vi_register.vi_v_burst = GETDATA(curr, unsigned int);
vi_register.vi_x_scale = GETDATA(curr, unsigned int);
vi_register.vi_y_scale = GETDATA(curr, unsigned int);
vi_register.vi_delay = GETDATA(curr, unsigned int);
update_vi_status(vi_register.vi_status);
update_vi_width(vi_register.vi_width);
ri_register.ri_mode = GETDATA(curr, unsigned int);
ri_register.ri_config = GETDATA(curr, unsigned int);
ri_register.ri_current_load = GETDATA(curr, unsigned int);
ri_register.ri_select = GETDATA(curr, unsigned int);
ri_register.ri_refresh = GETDATA(curr, unsigned int);
ri_register.ri_latency = GETDATA(curr, unsigned int);
ri_register.ri_error = GETDATA(curr, unsigned int);
ri_register.ri_werror = GETDATA(curr, unsigned int);
ai_register.ai_dram_addr = GETDATA(curr, unsigned int);
ai_register.ai_len = GETDATA(curr, unsigned int);
ai_register.ai_control = GETDATA(curr, unsigned int);
ai_register.ai_status = GETDATA(curr, unsigned int);
ai_register.ai_dacrate = GETDATA(curr, unsigned int);
ai_register.ai_bitrate = GETDATA(curr, unsigned int);
ai_register.next_delay = GETDATA(curr, unsigned int);
ai_register.next_len = GETDATA(curr, unsigned int);
ai_register.current_delay = GETDATA(curr, unsigned int);
ai_register.current_len = GETDATA(curr, unsigned int);
update_ai_dacrate(ai_register.ai_dacrate);
dpc_register.dpc_start = GETDATA(curr, unsigned int);
dpc_register.dpc_end = GETDATA(curr, unsigned int);
dpc_register.dpc_current = GETDATA(curr, unsigned int);
dpc_register.w_dpc_status = GETDATA(curr, unsigned int);
dpc_register.dpc_status = GETDATA(curr, unsigned int);
curr += 12; // Duplicated DPC flags and padding from old implementation
dpc_register.dpc_clock = GETDATA(curr, unsigned int);
dpc_register.dpc_bufbusy = GETDATA(curr, unsigned int);
dpc_register.dpc_pipebusy = GETDATA(curr, unsigned int);
dpc_register.dpc_tmem = GETDATA(curr, unsigned int);
dps_register.dps_tbist = GETDATA(curr, unsigned int);
dps_register.dps_test_mode = GETDATA(curr, unsigned int);
dps_register.dps_buftest_addr = GETDATA(curr, unsigned int);
dps_register.dps_buftest_data = GETDATA(curr, unsigned int);
COPYARRAY(rdram, curr, unsigned int, 0x800000/4);
COPYARRAY(SP_DMEM, curr, unsigned int, 0x1000/4);
COPYARRAY(SP_IMEM, curr, unsigned int, 0x1000/4);
COPYARRAY(PIF_RAM, curr, unsigned char, 0x40);
flashram_info.use_flashram = GETDATA(curr, int);
flashram_info.mode = GETDATA(curr, int);
flashram_info.status = GETDATA(curr, unsigned long long);
flashram_info.erase_offset = GETDATA(curr, unsigned int);
flashram_info.write_pointer = GETDATA(curr, unsigned int);
COPYARRAY(tlb_LUT_r, curr, unsigned int, 0x100000);
COPYARRAY(tlb_LUT_w, curr, unsigned int, 0x100000);
llbit = GETDATA(curr, unsigned int);
COPYARRAY(reg, curr, long long int, 32);
COPYARRAY(reg_cop0, curr, unsigned int, 32);
set_fpr_pointers(Status); // Status is reg_cop0[12]
lo = GETDATA(curr, long long int);
hi = GETDATA(curr, long long int);
COPYARRAY(reg_cop1_fgr_64, curr, long long int, 32);
if ((Status & 0x04000000) == 0) // 32-bit FPR mode requires data shuffling because 64-bit layout is always stored in savestate file
shuffle_fpr_data(0x04000000, 0);
FCR0 = GETDATA(curr, int);
FCR31 = GETDATA(curr, int);
for (i = 0; i < 32; i++)
{
tlb_e[i].mask = GETDATA(curr, short);
curr += 2;
tlb_e[i].vpn2 = GETDATA(curr, int);
tlb_e[i].g = GETDATA(curr, char);
tlb_e[i].asid = GETDATA(curr, unsigned char);
curr += 2;
tlb_e[i].pfn_even = GETDATA(curr, int);
tlb_e[i].c_even = GETDATA(curr, char);
tlb_e[i].d_even = GETDATA(curr, char);
tlb_e[i].v_even = GETDATA(curr, char);
curr++;
tlb_e[i].pfn_odd = GETDATA(curr, int);
tlb_e[i].c_odd = GETDATA(curr, char);
tlb_e[i].d_odd = GETDATA(curr, char);
tlb_e[i].v_odd = GETDATA(curr, char);
tlb_e[i].r = GETDATA(curr, char);
tlb_e[i].start_even = GETDATA(curr, unsigned int);
tlb_e[i].end_even = GETDATA(curr, unsigned int);
tlb_e[i].phys_even = GETDATA(curr, unsigned int);
tlb_e[i].start_odd = GETDATA(curr, unsigned int);
tlb_e[i].end_odd = GETDATA(curr, unsigned int);
tlb_e[i].phys_odd = GETDATA(curr, unsigned int);
}
if(r4300emu != CORE_PURE_INTERPRETER)
{
for (i = 0; i < 0x100000; i++)
invalid_code[i] = 1;
}
generic_jump_to(GETDATA(curr, unsigned int)); // PC
next_interupt = GETDATA(curr, unsigned int);
next_vi = GETDATA(curr, unsigned int);
vi_field = GETDATA(curr, unsigned int);
// assert(savestateData+savestateSize == curr)
to_little_endian_buffer(queue, 4, 256);
//load_eventqueue_infos(queue);
last_addr = PC->addr;
return 1;
}
static int savestates_load_pj64(char *filepath, void *handle,
int (*read_func)(void *, void *, size_t))
{
@ -1242,6 +1437,247 @@ static int savestates_save_m64p(char *filepath)
return 1;
}
EXPORT int CALL savestates_save_bkm(char *curr)
{
unsigned char outbuf[4];
int i;
char queue[1024];
int queuelength;
int savestate_size;
queuelength = save_eventqueue_infos(queue);
// Allocate memory for the save state data
savestate_size = 16788288 + queuelength;
// Write the save state data to memory
PUTARRAY(savestate_magic, curr, unsigned char, 8);
outbuf[0] = (savestate_latest_version >> 24) & 0xff;
outbuf[1] = (savestate_latest_version >> 16) & 0xff;
outbuf[2] = (savestate_latest_version >> 8) & 0xff;
outbuf[3] = (savestate_latest_version >> 0) & 0xff;
PUTARRAY(outbuf, curr, unsigned char, 4);
PUTARRAY(ROM_SETTINGS.MD5, curr, char, 32);
PUTDATA(curr, unsigned int, rdram_register.rdram_config);
PUTDATA(curr, unsigned int, rdram_register.rdram_device_id);
PUTDATA(curr, unsigned int, rdram_register.rdram_delay);
PUTDATA(curr, unsigned int, rdram_register.rdram_mode);
PUTDATA(curr, unsigned int, rdram_register.rdram_ref_interval);
PUTDATA(curr, unsigned int, rdram_register.rdram_ref_row);
PUTDATA(curr, unsigned int, rdram_register.rdram_ras_interval);
PUTDATA(curr, unsigned int, rdram_register.rdram_min_interval);
PUTDATA(curr, unsigned int, rdram_register.rdram_addr_select);
PUTDATA(curr, unsigned int, rdram_register.rdram_device_manuf);
PUTDATA(curr, unsigned int, MI_register.w_mi_init_mode_reg);
PUTDATA(curr, unsigned int, MI_register.mi_init_mode_reg);
PUTDATA(curr, unsigned char, MI_register.mi_init_mode_reg & 0x7F);
PUTDATA(curr, unsigned char, (MI_register.mi_init_mode_reg & 0x80) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_init_mode_reg & 0x100) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_init_mode_reg & 0x200) != 0);
PUTDATA(curr, unsigned int, MI_register.mi_version_reg);
PUTDATA(curr, unsigned int, MI_register.mi_intr_reg);
PUTDATA(curr, unsigned int, MI_register.mi_intr_mask_reg);
PUTDATA(curr, unsigned int, MI_register.w_mi_intr_mask_reg);
PUTDATA(curr, unsigned char, (MI_register.mi_intr_mask_reg & 0x1) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_intr_mask_reg & 0x2) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_intr_mask_reg & 0x4) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_intr_mask_reg & 0x8) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_intr_mask_reg & 0x10) != 0);
PUTDATA(curr, unsigned char, (MI_register.mi_intr_mask_reg & 0x20) != 0);
PUTDATA(curr, unsigned short, 0); // Padding from old implementation
PUTDATA(curr, unsigned int, pi_register.pi_dram_addr_reg);
PUTDATA(curr, unsigned int, pi_register.pi_cart_addr_reg);
PUTDATA(curr, unsigned int, pi_register.pi_rd_len_reg);
PUTDATA(curr, unsigned int, pi_register.pi_wr_len_reg);
PUTDATA(curr, unsigned int, pi_register.read_pi_status_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom1_lat_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom1_pwd_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom1_pgs_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom1_rls_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom2_lat_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom2_pwd_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom2_pgs_reg);
PUTDATA(curr, unsigned int, pi_register.pi_bsd_dom2_rls_reg);
PUTDATA(curr, unsigned int, sp_register.sp_mem_addr_reg);
PUTDATA(curr, unsigned int, sp_register.sp_dram_addr_reg);
PUTDATA(curr, unsigned int, sp_register.sp_rd_len_reg);
PUTDATA(curr, unsigned int, sp_register.sp_wr_len_reg);
PUTDATA(curr, unsigned int, sp_register.w_sp_status_reg);
PUTDATA(curr, unsigned int, sp_register.sp_status_reg);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x1) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x2) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x4) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x8) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x10) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x20) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x40) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x80) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x100) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x200) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x400) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x800) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x1000) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x2000) != 0);
PUTDATA(curr, unsigned char, (sp_register.sp_status_reg & 0x4000) != 0);
PUTDATA(curr, unsigned char, 0);
PUTDATA(curr, unsigned int, sp_register.sp_dma_full_reg);
PUTDATA(curr, unsigned int, sp_register.sp_dma_busy_reg);
PUTDATA(curr, unsigned int, sp_register.sp_semaphore_reg);
PUTDATA(curr, unsigned int, rsp_register.rsp_pc);
PUTDATA(curr, unsigned int, rsp_register.rsp_ibist);
PUTDATA(curr, unsigned int, si_register.si_dram_addr);
PUTDATA(curr, unsigned int, si_register.si_pif_addr_rd64b);
PUTDATA(curr, unsigned int, si_register.si_pif_addr_wr64b);
PUTDATA(curr, unsigned int, si_register.si_stat);
PUTDATA(curr, unsigned int, vi_register.vi_status);
PUTDATA(curr, unsigned int, vi_register.vi_origin);
PUTDATA(curr, unsigned int, vi_register.vi_width);
PUTDATA(curr, unsigned int, vi_register.vi_v_intr);
PUTDATA(curr, unsigned int, vi_register.vi_current);
PUTDATA(curr, unsigned int, vi_register.vi_burst);
PUTDATA(curr, unsigned int, vi_register.vi_v_sync);
PUTDATA(curr, unsigned int, vi_register.vi_h_sync);
PUTDATA(curr, unsigned int, vi_register.vi_leap);
PUTDATA(curr, unsigned int, vi_register.vi_h_start);
PUTDATA(curr, unsigned int, vi_register.vi_v_start);
PUTDATA(curr, unsigned int, vi_register.vi_v_burst);
PUTDATA(curr, unsigned int, vi_register.vi_x_scale);
PUTDATA(curr, unsigned int, vi_register.vi_y_scale);
PUTDATA(curr, unsigned int, vi_register.vi_delay);
PUTDATA(curr, unsigned int, ri_register.ri_mode);
PUTDATA(curr, unsigned int, ri_register.ri_config);
PUTDATA(curr, unsigned int, ri_register.ri_current_load);
PUTDATA(curr, unsigned int, ri_register.ri_select);
PUTDATA(curr, unsigned int, ri_register.ri_refresh);
PUTDATA(curr, unsigned int, ri_register.ri_latency);
PUTDATA(curr, unsigned int, ri_register.ri_error);
PUTDATA(curr, unsigned int, ri_register.ri_werror);
PUTDATA(curr, unsigned int, ai_register.ai_dram_addr);
PUTDATA(curr, unsigned int, ai_register.ai_len);
PUTDATA(curr, unsigned int, ai_register.ai_control);
PUTDATA(curr, unsigned int, ai_register.ai_status);
PUTDATA(curr, unsigned int, ai_register.ai_dacrate);
PUTDATA(curr, unsigned int, ai_register.ai_bitrate);
PUTDATA(curr, unsigned int, ai_register.next_delay);
PUTDATA(curr, unsigned int, ai_register.next_len);
PUTDATA(curr, unsigned int, ai_register.current_delay);
PUTDATA(curr, unsigned int, ai_register.current_len);
PUTDATA(curr, unsigned int, dpc_register.dpc_start);
PUTDATA(curr, unsigned int, dpc_register.dpc_end);
PUTDATA(curr, unsigned int, dpc_register.dpc_current);
PUTDATA(curr, unsigned int, dpc_register.w_dpc_status);
PUTDATA(curr, unsigned int, dpc_register.dpc_status);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x1) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x2) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x4) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x8) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x10) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x20) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x40) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x80) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x100) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x200) != 0);
PUTDATA(curr, unsigned char, (dpc_register.dpc_status & 0x400) != 0);
PUTDATA(curr, unsigned char, 0);
PUTDATA(curr, unsigned int, dpc_register.dpc_clock);
PUTDATA(curr, unsigned int, dpc_register.dpc_bufbusy);
PUTDATA(curr, unsigned int, dpc_register.dpc_pipebusy);
PUTDATA(curr, unsigned int, dpc_register.dpc_tmem);
PUTDATA(curr, unsigned int, dps_register.dps_tbist);
PUTDATA(curr, unsigned int, dps_register.dps_test_mode);
PUTDATA(curr, unsigned int, dps_register.dps_buftest_addr);
PUTDATA(curr, unsigned int, dps_register.dps_buftest_data);
PUTARRAY(rdram, curr, unsigned int, 0x800000/4);
PUTARRAY(SP_DMEM, curr, unsigned int, 0x1000/4);
PUTARRAY(SP_IMEM, curr, unsigned int, 0x1000/4);
PUTARRAY(PIF_RAM, curr, unsigned char, 0x40);
PUTDATA(curr, int, flashram_info.use_flashram);
PUTDATA(curr, int, flashram_info.mode);
PUTDATA(curr, unsigned long long, flashram_info.status);
PUTDATA(curr, unsigned int, flashram_info.erase_offset);
PUTDATA(curr, unsigned int, flashram_info.write_pointer);
PUTARRAY(tlb_LUT_r, curr, unsigned int, 0x100000);
PUTARRAY(tlb_LUT_w, curr, unsigned int, 0x100000);
PUTDATA(curr, unsigned int, llbit);
PUTARRAY(reg, curr, long long int, 32);
PUTARRAY(reg_cop0, curr, unsigned int, 32);
PUTDATA(curr, long long int, lo);
PUTDATA(curr, long long int, hi);
if ((Status & 0x04000000) == 0) // FR bit == 0 means 32-bit (MIPS I) FGR mode
shuffle_fpr_data(0, 0x04000000); // shuffle data into 64-bit register format for storage
PUTARRAY(reg_cop1_fgr_64, curr, long long int, 32);
if ((Status & 0x04000000) == 0)
shuffle_fpr_data(0x04000000, 0); // put it back in 32-bit mode
PUTDATA(curr, int, FCR0);
PUTDATA(curr, int, FCR31);
for (i = 0; i < 32; i++)
{
PUTDATA(curr, short, tlb_e[i].mask);
PUTDATA(curr, short, 0);
PUTDATA(curr, int, tlb_e[i].vpn2);
PUTDATA(curr, char, tlb_e[i].g);
PUTDATA(curr, unsigned char, tlb_e[i].asid);
PUTDATA(curr, short, 0);
PUTDATA(curr, int, tlb_e[i].pfn_even);
PUTDATA(curr, char, tlb_e[i].c_even);
PUTDATA(curr, char, tlb_e[i].d_even);
PUTDATA(curr, char, tlb_e[i].v_even);
PUTDATA(curr, char, 0);
PUTDATA(curr, int, tlb_e[i].pfn_odd);
PUTDATA(curr, char, tlb_e[i].c_odd);
PUTDATA(curr, char, tlb_e[i].d_odd);
PUTDATA(curr, char, tlb_e[i].v_odd);
PUTDATA(curr, char, tlb_e[i].r);
PUTDATA(curr, unsigned int, tlb_e[i].start_even);
PUTDATA(curr, unsigned int, tlb_e[i].end_even);
PUTDATA(curr, unsigned int, tlb_e[i].phys_even);
PUTDATA(curr, unsigned int, tlb_e[i].start_odd);
PUTDATA(curr, unsigned int, tlb_e[i].end_odd);
PUTDATA(curr, unsigned int, tlb_e[i].phys_odd);
}
if (PC != NULL)
{
PUTDATA(curr, unsigned int, PC->addr);
}
else
{
PUTDATA(curr, unsigned int, 0);
}
PUTDATA(curr, unsigned int, next_interupt);
PUTDATA(curr, unsigned int, next_vi);
PUTDATA(curr, unsigned int, vi_field);
to_little_endian_buffer(queue, 4, queuelength/4);
PUTARRAY(queue, curr, char, queuelength);
// assert(curr == save->data + save->size)
return savestate_size;
}
static int savestates_save_pj64(char *filepath, void *handle,
int (*write_func)(void *, const void *, size_t))
{