Merged patch from olejl77 in issue #52, comment #12, with a few small changes

This commit is contained in:
Richard Goedeken 2009-01-25 13:12:03 +00:00
parent dcedd81bd3
commit 65e9212a2b
4 changed files with 345 additions and 3 deletions

View file

@ -36,8 +36,11 @@
#include "../r4300/interupt.h"
#include "../opengl/osd.h"
#include "zip/unzip.h"
const char* savestate_magic = "M64+SAVE";
const int savestate_version = 0x00010000; /* 1.0 */
const int pj64_magic = 0x23D8A6C8;
extern unsigned int interp_addr;
@ -104,6 +107,15 @@ char* savestates_get_filename()
return filename;
}
char* savestates_get_pj64_filename()
{
size_t length;
length = strlen((char*)ROM_HEADER->nom)+7+1;
char* filename = (char*)malloc(length);
snprintf(filename, length, "%s.pj.zip", (char*)ROM_HEADER->nom);
return filename;
}
void savestates_save()
{
char *filename, *file, buffer[1024];
@ -232,9 +244,10 @@ void savestates_load()
gzread(f, buffer, 8);
if(strncmp(buffer, savestate_magic, 8)!=0)
{
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error: Unrecognized savestate format."));
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error: Not a Mupen64plus savestate format. Checking PJ64..."));
free(filename);
gzclose(f);
savestates_load_pj64(file);
return;
}
@ -328,3 +341,294 @@ void savestates_load()
free(filename);
}
void savestates_load_pj64()
{
char *file, *filename, buffer[1024], RomHeader[64], szFileName[256], szExtraField[256], szComment[256];
unsigned int magic, value, vi_timer, SaveRDRAMSize;
int queuelength, i;
size_t length;
unzFile zipromfile;
unz_file_info fileinfo;
if(fname[0]!=0) // A specific filename was given.
{
file = malloc(strlen(fname)+1);
strcpy(file, fname);
fname[0] = 0;
}
else
{
filename = savestates_get_pj64_filename();
length = strlen(get_savespath()) + strlen(filename) + 1;
file = malloc(length);
snprintf(file, length, "%s%s", get_savespath(), filename);
free(filename);
}
zipromfile = unzOpen(file); // Open the .zip file.
if (zipromfile == NULL)
{
unzClose(zipromfile);
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate: '%s' doesn't exist"), file);
free(file);
return;
}
if (unzGoToFirstFile(zipromfile)!=UNZ_OK)
{
unzClose(zipromfile);
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate. ZIP error #1 in: '%s'"), file);
free(file);
return;
}
if(unzGetCurrentFileInfo(zipromfile, &fileinfo, szFileName, 255,
szExtraField, 255, szComment, 255)!=UNZ_OK)
{
unzClose(zipromfile);
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate. ZIP error #2 in: '%s'"), file);
free(file);
return;
}
if(unzOpenCurrentFile(zipromfile)!=UNZ_OK)
{
unzClose(zipromfile);
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate. ZIP error #3 in: '%s'"), file);
free(file);
return;
}
if(fileinfo.uncompressed_size<4)
{
unzClose(zipromfile);
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate. ZIP error #4 in: '%s'"), file);
free(file);
return;
}
// Check for PJ64 magic number
unzReadCurrentFile(zipromfile,&magic,4);
if (magic != pj64_magic)
{
unzClose(zipromfile);
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate: '%s'. Unrecognized file format."), file);
free(file);
return;
}
// SaveRDRAMSize
unzReadCurrentFile(zipromfile,&SaveRDRAMSize,4);
// RomHeader
unzReadCurrentFile(zipromfile, RomHeader,0x40);
if (memcmp(RomHeader,rom, 0x40) != 0) {
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("Error loading savestate: Savestate header doesn't match current ROM header."));
unzClose(zipromfile);
free(file);
return;
}
// vi_timer
unzReadCurrentFile(zipromfile, &vi_timer,4);
// Program Counter
if(!dynacore&&interpcore)
unzReadCurrentFile(zipromfile, &interp_addr,4);
else
{
unzReadCurrentFile(zipromfile, &queuelength,4);
for (i = 0; i < 0x100000; i++)
invalid_code[i] = 1;
jump_to(queuelength);
}
// GPR
unzReadCurrentFile(zipromfile, reg,8*32);
// FPR
unzReadCurrentFile(zipromfile, reg_cop1_fgr_64,8*32);
// CP0
unzReadCurrentFile(zipromfile, reg_cop0, 4*32);
// Initialze the interupts
vi_timer += reg_cop0[9]; // Add current Count
next_interupt = vi_timer;
next_vi = vi_timer;
vi_field = 0;
*((unsigned int*)&buffer[0]) = VI_INT;
*((unsigned int*)&buffer[4]) = vi_timer;
*((unsigned int*)&buffer[8]) = 0xFFFFFFFF;
load_eventqueue_infos(buffer);
// FPCR
unzReadCurrentFile(zipromfile, &FCR0,4);
unzReadCurrentFile(zipromfile, &buffer,120); // Dummy read.
unzReadCurrentFile(zipromfile, &FCR31,4);
// hi / lo
unzReadCurrentFile(zipromfile,&hi,8);
unzReadCurrentFile(zipromfile,&lo,8);
// rdram register
unzReadCurrentFile(zipromfile, &rdram_register, sizeof(RDRAM_register));
// sp_register
unzReadCurrentFile(zipromfile, &sp_register.sp_mem_addr_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.sp_dram_addr_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.sp_rd_len_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.sp_wr_len_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.w_sp_status_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.sp_dma_full_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.sp_dma_busy_reg, 4);
unzReadCurrentFile(zipromfile, &sp_register.sp_semaphore_reg, 4);
unzReadCurrentFile(zipromfile, &value, 4); // SP_PC_REG -> Not part of mupen savestate. Dummy read.
unzReadCurrentFile(zipromfile, &value, 4); // SP_IBIST_REG -> Not part of mupen savestate. Dummy read.
update_SP();
// dpc_register
unzReadCurrentFile(zipromfile, &dpc_register.dpc_start, 4);
unzReadCurrentFile(zipromfile, &dpc_register.dpc_end, 4);
unzReadCurrentFile(zipromfile, &dpc_register.dpc_current, 4);
unzReadCurrentFile(zipromfile, &dpc_register.w_dpc_status, 4);
unzReadCurrentFile(zipromfile, &dpc_register.dpc_clock, 4);
unzReadCurrentFile(zipromfile, &dpc_register.dpc_bufbusy, 4);
unzReadCurrentFile(zipromfile, &dpc_register.dpc_pipebusy, 4);
unzReadCurrentFile(zipromfile, &dpc_register.dpc_tmem, 4);
unzReadCurrentFile(zipromfile, &value, 4); // Dummy read ... Keeping up with PJ64
unzReadCurrentFile(zipromfile, &value, 4); // Dummy read ... Keeping up with PJ64
update_DPC();
// mi_register
unzReadCurrentFile(zipromfile, &MI_register.w_mi_init_mode_reg, 4);
unzReadCurrentFile(zipromfile, &MI_register.mi_version_reg, 4);
unzReadCurrentFile(zipromfile, &MI_register.mi_intr_reg, 4);
unzReadCurrentFile(zipromfile, &MI_register.w_mi_intr_mask_reg, 4);
update_MI_intr_mask_reg();
update_MI_init_mode_reg();
// vi_register
unzReadCurrentFile(zipromfile, &vi_register, 4*14);
// ai_register
unzReadCurrentFile(zipromfile, &ai_register, 4*6);
// TODO: Not avialable in PJ64 savestate
// ai_register.next_delay = 0; ai_register.next_len = 0;
// ai_register.current_delay = 0;//804629; ai_register.current_len = 0;
// pi_register
unzReadCurrentFile(zipromfile, &pi_register, sizeof(PI_register));
// ri_register
unzReadCurrentFile(zipromfile, &ri_register, sizeof(RI_register));
// si_register
unzReadCurrentFile(zipromfile, &si_register, sizeof(SI_register));
// tlb
memset(tlb_LUT_r, 0, 0x400000);
memset(tlb_LUT_w, 0, 0x400000);
TLB_pj64 tlb_pj64;
for (i=0;i<32;i++)
{
unsigned int j;
unzReadCurrentFile(zipromfile, &tlb_pj64, sizeof(TLB_pj64));
tlb_e[i].mask = (short) tlb_pj64.BreakDownPageMask.Mask;
tlb_e[i].vpn2 = tlb_pj64.BreakDownEntryHi.VPN2;
tlb_e[i].g = (char) tlb_pj64.BreakDownEntryLo0.GLOBAL & tlb_pj64.BreakDownEntryLo1.GLOBAL;
tlb_e[i].asid = (unsigned char) tlb_pj64.BreakDownEntryHi.ASID;
tlb_e[i].pfn_even = tlb_pj64.BreakDownEntryLo0.PFN;
tlb_e[i].c_even = (char) tlb_pj64.BreakDownEntryLo0.C;
tlb_e[i].d_even = (char) tlb_pj64.BreakDownEntryLo0.D;
tlb_e[i].v_even = (char) tlb_pj64.BreakDownEntryLo0.V;
tlb_e[i].pfn_odd = tlb_pj64.BreakDownEntryLo1.PFN;
tlb_e[i].c_odd = (char) tlb_pj64.BreakDownEntryLo1.C;
tlb_e[i].d_odd = (char) tlb_pj64.BreakDownEntryLo1.D;
tlb_e[i].v_odd = (char) tlb_pj64.BreakDownEntryLo1.V;
// This is copied from TLBWI instruction
// tlb_e[i].r = 0;
tlb_e[i].start_even = (unsigned int) tlb_e[i].vpn2 << 13;
tlb_e[i].end_even = (unsigned int) tlb_e[i].start_even + (tlb_e[i].mask << 12) + 0xFFF;
tlb_e[i].phys_even = (unsigned int) tlb_e[i].pfn_even << 12;;
tlb_e[i].start_odd = (unsigned int) tlb_e[i].end_even + 1;
tlb_e[i].end_odd = (unsigned int) tlb_e[i].start_odd + (tlb_e[i].mask << 12) + 0xFFF;;
tlb_e[i].phys_odd = (unsigned int) tlb_e[i].pfn_odd << 12;
if (tlb_e[i].v_even)
{
if (tlb_e[i].start_even < tlb_e[i].end_even &&
!(tlb_e[i].start_even >= 0x80000000 && tlb_e[i].end_even < 0xC0000000) &&
tlb_e[i].phys_even < 0x20000000)
{
for (j=tlb_e[i].start_even;j<tlb_e[i].end_even;j++)
tlb_LUT_r[j>>12] = 0x80000000 | (tlb_e[i].phys_even +
(j - tlb_e[i].start_even));
if (tlb_e[i].d_even)
for (j=tlb_e[i].start_even;j<tlb_e[i].end_even;j++)
tlb_LUT_w[j>>12] = 0x80000000 | (tlb_e[i].phys_even + (j - tlb_e[i].start_even));
}
for (j=tlb_e[i].start_even>>12; j<=tlb_e[i].end_even>>12; j++)
{
if(blocks[j] && blocks[j]->adler32)
{
if(blocks[j]->adler32 ==
adler32(0,(const Bytef*)&rdram[(tlb_LUT_r[j]&0x7FF000)/4],0x1000))
invalid_code[j] = 0;
}
}
}
if (tlb_e[i].v_odd)
{
if (tlb_e[i].start_odd < tlb_e[i].end_odd &&
!(tlb_e[i].start_odd >= 0x80000000 &&
tlb_e[i].end_odd < 0xC0000000) &&
tlb_e[i].phys_odd < 0x20000000)
{
for (j=tlb_e[i].start_odd;j<tlb_e[i].end_odd;j++)
tlb_LUT_r[j>>12] = 0x80000000 | (tlb_e[i].phys_odd + (j - tlb_e[i].start_odd));
if (tlb_e[i].d_odd)
for (j=tlb_e[i].start_odd;j<tlb_e[i].end_odd;j++)
tlb_LUT_w[j>>12] = 0x80000000 | (tlb_e[i].phys_odd + (j - tlb_e[i].start_odd));
}
for (j=tlb_e[i].start_odd>>12; j<=tlb_e[i].end_odd>>12; j++)
{
if(blocks[j] && blocks[j]->adler32)
{
if(blocks[j]->adler32 == adler32(0,(const Bytef*)&rdram[(tlb_LUT_r[j]&0x7FF000)/4],0x1000))
invalid_code[j] = 0;
}
}
}
}
// pif ram
unzReadCurrentFile(zipromfile, PIF_RAM, 0x40);
// RDRAM
memset(rdram, 0, 0x800000);
unzReadCurrentFile(zipromfile, rdram, SaveRDRAMSize);
// DMEM
unzReadCurrentFile(zipromfile, SP_DMEM, 0x1000);
// IMEM
unzReadCurrentFile(zipromfile, SP_IMEM, 0x1000);
// TODO: The following is not available in PJ64 savestate. Keep the values as is.
// rsp_register.rsp_pc = 0; rsp_register.rsp_ibist = 0; dps_register.dps_tbist = 0; dps_register.dps_test_mode = 0;
// dps_register.dps_buftest_addr = 0; dps_register.dps_buftest_data = 0; llbit = 0;
// No flashram info in pj64 savestate.
init_flashram();
unzClose(zipromfile);
if(!dynacore&&interpcore)
last_addr = interp_addr;
else
last_addr = PC->addr;
main_message(0, 1, 1, OSD_BOTTOM_LEFT, tr("State loaded from: %s"), file);
free(file);
}

View file

@ -30,6 +30,7 @@ extern int savestates_job;
void savestates_save();
void savestates_load();
void savestates_load_pj64();
void savestates_select_slot(unsigned int s);
unsigned int savestates_get_slot(void);
@ -39,5 +40,40 @@ void savestates_inc_slot(void);
void savestates_select_filename(const char* fn);
char* savestates_get_filename();
typedef struct _TLB_pj64 {
unsigned int _EntryDefined;
struct _BreakDownPageMask {
unsigned int zero : 13;
unsigned int Mask : 12;
unsigned int zero2 : 7;
} BreakDownPageMask;
struct _BreakDownEntryHi {
unsigned int ASID : 8;
unsigned int Zero : 4;
unsigned int G : 1;
unsigned int VPN2 : 19;
} BreakDownEntryHi;
struct _BreakDownEntryLo0 {
unsigned int GLOBAL: 1;
unsigned int V : 1;
unsigned int D : 1;
unsigned int C : 3;
unsigned int PFN : 20;
unsigned int ZERO: 6;
} BreakDownEntryLo0;
struct _BreakDownEntryLo1 {
unsigned int GLOBAL: 1;
unsigned int V : 1;
unsigned int D : 1;
unsigned int C : 3;
unsigned int PFN : 20;
unsigned int ZERO: 6;
} BreakDownEntryLo1;
} TLB_pj64;
#endif /* __SAVESTAVES_H__ */

View file

@ -1008,7 +1008,7 @@ void free_memory()
{
}
static void update_MI_init_mode_reg()
void update_MI_init_mode_reg()
{
MI_register.init_length = MI_register.w_mi_init_mode_reg & 0x7F;
if (MI_register.w_mi_init_mode_reg & 0x80)
@ -1035,7 +1035,7 @@ static void update_MI_init_mode_reg()
);
}
static void update_MI_intr_mask_reg()
void update_MI_intr_mask_reg()
{
if (MI_register.w_mi_intr_mask_reg & 0x1) MI_register.SP_intr_mask = 0;
if (MI_register.w_mi_intr_mask_reg & 0x2) MI_register.SP_intr_mask = 1;

View file

@ -422,6 +422,8 @@ void write_pifd();
void update_SP();
void update_DPC();
void update_MI_intr_mode_reg();
void update_MI_init_mask_reg();
#endif