mirror of https://github.com/PCSX2/pcsx2.git
Major overhaul of the savestate system!
Since backwards compat of savestates got totally broken a few revisions ago anyway, I decided to take this opportunity to revamp the savestate system with some significant cleanups (yes it loses all backward compat once again). Improvements include: * Reduced state size by removing some unneeded data (faster saves now too!) * Added string tags to varios "sections" of the states to assist in troubleshooting and retaining savestate compat in future versions. * Better error handling and fewer memory leaks. * Removed some unused/obsolete data from psxRegs, Counters, and psxCounters structures. * Removed all old savestate versioning code, since none of the old versions are supported anymore anyways. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@815 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
a51b407cdb
commit
1f36e97927
|
@ -786,6 +786,7 @@ struct Freeze_v10Compat
|
||||||
|
|
||||||
void SaveState::cdvdFreeze()
|
void SaveState::cdvdFreeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "cdvd" );
|
||||||
Freeze( cdvd );
|
Freeze( cdvd );
|
||||||
|
|
||||||
if( IsLoading() )
|
if( IsLoading() )
|
||||||
|
|
|
@ -944,15 +944,9 @@ void cdrReset() {
|
||||||
cdReadTime = (PSXCLK / 1757) * BIAS;
|
cdReadTime = (PSXCLK / 1757) * BIAS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveState::cdrFreeze() {
|
void SaveState::cdrFreeze()
|
||||||
|
{
|
||||||
|
FreezeTag( "cdrom" );
|
||||||
Freeze(cdr);
|
Freeze(cdr);
|
||||||
|
|
||||||
// Alrighty! This code used to, for some reason, recalculate the pTransfer value
|
|
||||||
// even though it's being saved as part of the cdr struct. Probably a backwards
|
|
||||||
// compat fix with an earlier save version.
|
|
||||||
|
|
||||||
int tmp; // = (int)(cdr.pTransfer - cdr.Transfer);
|
|
||||||
Freeze(tmp);
|
|
||||||
//if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,9 @@ int gates = 0;
|
||||||
|
|
||||||
// Counter 4 takes care of scanlines - hSync/hBlanks
|
// Counter 4 takes care of scanlines - hSync/hBlanks
|
||||||
// Counter 5 takes care of vSync/vBlanks
|
// Counter 5 takes care of vSync/vBlanks
|
||||||
Counter counters[6];
|
Counter counters[4];
|
||||||
|
SyncCounter hsyncCounter;
|
||||||
|
SyncCounter vsyncCounter;
|
||||||
|
|
||||||
u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate()
|
u32 nextsCounter; // records the cpuRegs.cycle value of the last call to rcntUpdate()
|
||||||
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
|
s32 nextCounter; // delta from nextsCounter, in cycles, until the next rcntUpdate()
|
||||||
|
@ -101,7 +103,7 @@ static __forceinline void cpuRcntSet()
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
nextsCounter = cpuRegs.cycle;
|
nextsCounter = cpuRegs.cycle;
|
||||||
nextCounter = (counters[5].sCycle + counters[5].CycleT) - cpuRegs.cycle;
|
nextCounter = (vsyncCounter.sCycle + vsyncCounter.CycleT) - cpuRegs.cycle;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
_rcntSet( i );
|
_rcntSet( i );
|
||||||
|
@ -124,10 +126,10 @@ void rcntInit() {
|
||||||
counters[2].interrupt = 11;
|
counters[2].interrupt = 11;
|
||||||
counters[3].interrupt = 12;
|
counters[3].interrupt = 12;
|
||||||
|
|
||||||
counters[4].modeval = MODE_HRENDER;
|
hsyncCounter.Mode = MODE_HRENDER;
|
||||||
counters[4].sCycle = cpuRegs.cycle;
|
hsyncCounter.sCycle = cpuRegs.cycle;
|
||||||
counters[5].modeval = MODE_VRENDER;
|
vsyncCounter.Mode = MODE_VRENDER;
|
||||||
counters[5].sCycle = cpuRegs.cycle;
|
vsyncCounter.sCycle = cpuRegs.cycle;
|
||||||
|
|
||||||
UpdateVSyncRate();
|
UpdateVSyncRate();
|
||||||
|
|
||||||
|
@ -136,7 +138,7 @@ void rcntInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug code, used for stats
|
// debug code, used for stats
|
||||||
int g_nCounters[4];
|
int g_nhsyncCounter;
|
||||||
static uint iFrame = 0;
|
static uint iFrame = 0;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -235,8 +237,8 @@ u32 UpdateVSyncRate()
|
||||||
vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC );
|
vSyncInfoCalc( &vSyncInfo, FRAMERATE_NTSC, SCANLINES_TOTAL_NTSC );
|
||||||
}
|
}
|
||||||
|
|
||||||
counters[4].CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated
|
hsyncCounter.CycleT = vSyncInfo.hRender; // Amount of cycles before the counter will be updated
|
||||||
counters[5].CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated
|
vsyncCounter.CycleT = vSyncInfo.Render; // Amount of cycles before the counter will be updated
|
||||||
|
|
||||||
if (Config.CustomFps > 0)
|
if (Config.CustomFps > 0)
|
||||||
{
|
{
|
||||||
|
@ -393,28 +395,28 @@ static int vblankinc = 0;
|
||||||
|
|
||||||
__forceinline void rcntUpdate_hScanline()
|
__forceinline void rcntUpdate_hScanline()
|
||||||
{
|
{
|
||||||
if( !cpuTestCycle( counters[4].sCycle, counters[4].CycleT ) ) return;
|
if( !cpuTestCycle( hsyncCounter.sCycle, hsyncCounter.CycleT ) ) return;
|
||||||
|
|
||||||
//iopBranchAction = 1;
|
//iopBranchAction = 1;
|
||||||
if (counters[4].modeval & MODE_HBLANK) { //HBLANK Start
|
if (hsyncCounter.Mode & MODE_HBLANK) { //HBLANK Start
|
||||||
rcntStartGate(false, counters[4].sCycle);
|
rcntStartGate(false, hsyncCounter.sCycle);
|
||||||
psxCheckStartGate16(0);
|
psxCheckStartGate16(0);
|
||||||
|
|
||||||
// Setup the hRender's start and end cycle information:
|
// Setup the hRender's start and end cycle information:
|
||||||
counters[4].sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
|
hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value)
|
||||||
counters[4].CycleT = vSyncInfo.hRender; // endpoint (delta from start value)
|
hsyncCounter.CycleT = vSyncInfo.hRender; // endpoint (delta from start value)
|
||||||
counters[4].modeval = MODE_HRENDER;
|
hsyncCounter.Mode = MODE_HRENDER;
|
||||||
}
|
}
|
||||||
else { //HBLANK END / HRENDER Begin
|
else { //HBLANK END / HRENDER Begin
|
||||||
if (CSRw & 0x4) GSCSRr |= 4; // signal
|
if (CSRw & 0x4) GSCSRr |= 4; // signal
|
||||||
if (!(GSIMR&0x400)) gsIrq();
|
if (!(GSIMR&0x400)) gsIrq();
|
||||||
if (gates) rcntEndGate(false, counters[4].sCycle);
|
if (gates) rcntEndGate(false, hsyncCounter.sCycle);
|
||||||
if (psxhblankgate) psxCheckEndGate16(0);
|
if (psxhblankgate) psxCheckEndGate16(0);
|
||||||
|
|
||||||
// set up the hblank's start and end cycle information:
|
// set up the hblank's start and end cycle information:
|
||||||
counters[4].sCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
||||||
counters[4].CycleT = vSyncInfo.hBlank; // endpoint (delta from start value)
|
hsyncCounter.CycleT = vSyncInfo.hBlank; // endpoint (delta from start value)
|
||||||
counters[4].modeval = MODE_HBLANK;
|
hsyncCounter.Mode = MODE_HBLANK;
|
||||||
|
|
||||||
# ifdef VSYNC_DEBUG
|
# ifdef VSYNC_DEBUG
|
||||||
hsc++;
|
hsc++;
|
||||||
|
@ -424,30 +426,30 @@ __forceinline void rcntUpdate_hScanline()
|
||||||
|
|
||||||
__forceinline bool rcntUpdate_vSync()
|
__forceinline bool rcntUpdate_vSync()
|
||||||
{
|
{
|
||||||
s32 diff = (cpuRegs.cycle - counters[5].sCycle);
|
s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
|
||||||
if( diff < counters[5].CycleT ) return false;
|
if( diff < vsyncCounter.CycleT ) return false;
|
||||||
|
|
||||||
//iopBranchAction = 1;
|
//iopBranchAction = 1;
|
||||||
if (counters[5].modeval == MODE_VSYNC)
|
if (vsyncCounter.Mode == MODE_VSYNC)
|
||||||
{
|
{
|
||||||
VSyncEnd(counters[5].sCycle);
|
VSyncEnd(vsyncCounter.sCycle);
|
||||||
|
|
||||||
counters[5].sCycle += vSyncInfo.Blank;
|
vsyncCounter.sCycle += vSyncInfo.Blank;
|
||||||
counters[5].CycleT = vSyncInfo.Render;
|
vsyncCounter.CycleT = vSyncInfo.Render;
|
||||||
counters[5].modeval = MODE_VRENDER;
|
vsyncCounter.Mode = MODE_VRENDER;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else // VSYNC end / VRENDER begin
|
else // VSYNC end / VRENDER begin
|
||||||
{
|
{
|
||||||
VSyncStart(counters[5].sCycle);
|
VSyncStart(vsyncCounter.sCycle);
|
||||||
|
|
||||||
counters[5].sCycle += vSyncInfo.Render;
|
vsyncCounter.sCycle += vSyncInfo.Render;
|
||||||
counters[5].CycleT = vSyncInfo.Blank;
|
vsyncCounter.CycleT = vSyncInfo.Blank;
|
||||||
counters[5].modeval = MODE_VSYNC;
|
vsyncCounter.Mode = MODE_VSYNC;
|
||||||
|
|
||||||
// Accumulate hsync rounding errors:
|
// Accumulate hsync rounding errors:
|
||||||
counters[4].sCycle += vSyncInfo.hSyncError;
|
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
||||||
|
|
||||||
# ifdef VSYNC_DEBUG
|
# ifdef VSYNC_DEBUG
|
||||||
vblankinc++;
|
vblankinc++;
|
||||||
|
@ -766,15 +768,12 @@ u32 __fastcall rcntCycle(int index)
|
||||||
|
|
||||||
void SaveState::rcntFreeze()
|
void SaveState::rcntFreeze()
|
||||||
{
|
{
|
||||||
Freeze(counters);
|
Freeze( counters );
|
||||||
Freeze(nextCounter);
|
Freeze( hsyncCounter );
|
||||||
Freeze(nextsCounter);
|
Freeze( vsyncCounter );
|
||||||
|
Freeze( nextCounter );
|
||||||
// New in version 1 -- save the PAL/NTSC info!
|
Freeze( nextsCounter );
|
||||||
if( GetVersion() >= 0x1 )
|
Freeze( Config.PsxType );
|
||||||
{
|
|
||||||
Freeze( Config.PsxType );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( IsLoading() )
|
if( IsLoading() )
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,7 +66,8 @@ struct EECNT_MODE
|
||||||
|
|
||||||
// fixme: Cycle and sCycleT members are unused.
|
// fixme: Cycle and sCycleT members are unused.
|
||||||
// But they can't be removed without making a new savestate version.
|
// But they can't be removed without making a new savestate version.
|
||||||
struct Counter {
|
struct Counter
|
||||||
|
{
|
||||||
u32 count;
|
u32 count;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -75,10 +76,14 @@ struct Counter {
|
||||||
};
|
};
|
||||||
u32 target, hold;
|
u32 target, hold;
|
||||||
u32 rate, interrupt;
|
u32 rate, interrupt;
|
||||||
u32 Cycle;
|
u32 sCycleT; // delta values should be signed.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SyncCounter
|
||||||
|
{
|
||||||
|
u32 Mode;
|
||||||
u32 sCycle; // start cycle of timer
|
u32 sCycle; // start cycle of timer
|
||||||
s32 CycleT;
|
s32 CycleT;
|
||||||
u32 sCycleT; // delta values should be signed.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -124,7 +129,10 @@ struct Counter {
|
||||||
#define MODE_HBLANK 0x1 //Set for the remaining ~1/6 of 1 Scanline
|
#define MODE_HBLANK 0x1 //Set for the remaining ~1/6 of 1 Scanline
|
||||||
|
|
||||||
|
|
||||||
extern Counter counters[6];
|
extern Counter counters[4];
|
||||||
|
extern SyncCounter hsyncCounter;
|
||||||
|
extern SyncCounter vsyncCounter;
|
||||||
|
|
||||||
extern s32 nextCounter; // delta until the next counter event (must be signed)
|
extern s32 nextCounter; // delta until the next counter event (must be signed)
|
||||||
extern u32 nextsCounter;
|
extern u32 nextsCounter;
|
||||||
|
|
||||||
|
|
|
@ -615,13 +615,12 @@ void gifMFIFOInterrupt()
|
||||||
|
|
||||||
void SaveState::gifFreeze()
|
void SaveState::gifFreeze()
|
||||||
{
|
{
|
||||||
if( GetVersion() >= 0x04 )
|
FreezeTag( "GIFdma" );
|
||||||
{
|
|
||||||
Freeze( gifstate );
|
|
||||||
Freeze( gifqwc );
|
|
||||||
Freeze( gspath3done );
|
|
||||||
Freeze( gscycles );
|
|
||||||
|
|
||||||
// Note: mfifocycles is not a persistent var, so no need to save it here.
|
Freeze( gifstate );
|
||||||
}
|
Freeze( gifqwc );
|
||||||
|
Freeze( gspath3done );
|
||||||
|
Freeze( gscycles );
|
||||||
|
|
||||||
|
// Note: mfifocycles is not a persistent var, so no need to save it here.
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,14 +163,14 @@ void ipuShutdown()
|
||||||
|
|
||||||
// fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point.
|
// fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point.
|
||||||
|
|
||||||
void SaveState::ipuFreeze() {
|
void SaveState::ipuFreeze()
|
||||||
|
{
|
||||||
IPUProcessInterrupt();
|
IPUProcessInterrupt();
|
||||||
|
|
||||||
if( GetVersion() < 0x04 )
|
FreezeTag( "IPU" );
|
||||||
{
|
|
||||||
// old versions saved the IPU regs, but they're already saved as part of HW!
|
// old versions saved the IPU regs, but they're already saved as part of HW!
|
||||||
FreezeMem(ipuRegs, sizeof(IPUregisters));
|
//FreezeMem(ipuRegs, sizeof(IPUregisters));
|
||||||
}
|
|
||||||
|
|
||||||
Freeze(g_nDMATransfer);
|
Freeze(g_nDMATransfer);
|
||||||
Freeze(FIreadpos);
|
Freeze(FIreadpos);
|
||||||
|
|
|
@ -751,6 +751,8 @@ void psxRcntSetGates()
|
||||||
|
|
||||||
void SaveState::psxRcntFreeze()
|
void SaveState::psxRcntFreeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "iopCounters" );
|
||||||
|
|
||||||
Freeze(psxCounters);
|
Freeze(psxCounters);
|
||||||
Freeze(psxNextCounter);
|
Freeze(psxNextCounter);
|
||||||
Freeze(psxNextsCounter);
|
Freeze(psxNextsCounter);
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
struct psxCounter {
|
struct psxCounter {
|
||||||
u64 count, target;
|
u64 count, target;
|
||||||
u32 mode;
|
u32 mode;
|
||||||
u32 rate, interrupt, otarget;
|
u32 rate, interrupt;
|
||||||
u32 sCycle, Cycle;
|
|
||||||
u32 sCycleT;
|
u32 sCycleT;
|
||||||
s32 CycleT;
|
s32 CycleT;
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,6 +203,7 @@ u8 sio2_fifoOut(){
|
||||||
|
|
||||||
void SaveState::sio2Freeze()
|
void SaveState::sio2Freeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "sio2" );
|
||||||
Freeze(sio2);
|
Freeze(sio2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,8 @@ static void _mtgsFreezeGIF( SaveState& state, GIFPath (&paths)[3] )
|
||||||
|
|
||||||
void SaveState::mtgsFreeze()
|
void SaveState::mtgsFreeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "mtgs" );
|
||||||
|
|
||||||
if( mtgsThread != NULL )
|
if( mtgsThread != NULL )
|
||||||
{
|
{
|
||||||
mtgsThread->Freeze( *this );
|
mtgsThread->Freeze( *this );
|
||||||
|
|
|
@ -176,9 +176,9 @@ u32 GetBiosVersion() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//2002-09-22 (Florin)
|
//2002-09-22 (Florin)
|
||||||
int IsBIOS(char *filename, char *description)
|
int IsBIOS(const char *filename, char *description)
|
||||||
{
|
{
|
||||||
char ROMVER[14+1], zone[12+1];
|
char ROMVER[14+1];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
unsigned int fileOffset=0, found=FALSE;
|
unsigned int fileOffset=0, found=FALSE;
|
||||||
struct romdir rd;
|
struct romdir rd;
|
||||||
|
@ -200,31 +200,38 @@ int IsBIOS(char *filename, char *description)
|
||||||
return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img
|
return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img
|
||||||
}
|
}
|
||||||
|
|
||||||
while(strlen(rd.fileName) > 0){
|
while(strlen(rd.fileName) > 0)
|
||||||
if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver
|
{
|
||||||
unsigned int filepos=ftell(fp);
|
if (strcmp(rd.fileName, "ROMVER") == 0) // found romver
|
||||||
|
{
|
||||||
|
uint filepos = ftell(fp);
|
||||||
fseek(fp, fileOffset, SEEK_SET);
|
fseek(fp, fileOffset, SEEK_SET);
|
||||||
if (fread(&ROMVER, 14, 1, fp) == 0) break;
|
if (fread(&ROMVER, 14, 1, fp) == 0) break;
|
||||||
fseek(fp, filepos, SEEK_SET);//go back
|
fseek(fp, filepos, SEEK_SET);//go back
|
||||||
|
|
||||||
switch(ROMVER[4]){
|
const char zonefail[2] = { ROMVER[4], '\0' }; // the default "zone" (unknown code)
|
||||||
case 'T':sprintf(zone, "T10K "); break;
|
const char* zone = zonefail;
|
||||||
case 'X':sprintf(zone, "Test ");break;
|
|
||||||
case 'J':sprintf(zone, "Japan "); break;
|
switch(ROMVER[4])
|
||||||
case 'A':sprintf(zone, "USA "); break;
|
{
|
||||||
case 'E':sprintf(zone, "Europe"); break;
|
case 'T': zone = "T10K "; break;
|
||||||
case 'H':sprintf(zone, "HK "); break;
|
case 'X': zone = "Test "; break;
|
||||||
case 'P':sprintf(zone, "Free "); break;
|
case 'J': zone = "Japan "; break;
|
||||||
case 'C':sprintf(zone, "China "); break;
|
case 'A': zone = "USA "; break;
|
||||||
default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show
|
case 'E': zone = "Europe"; break;
|
||||||
|
case 'H': zone = "HK "; break;
|
||||||
|
case 'P': zone = "Free "; break;
|
||||||
|
case 'C': zone = "China "; break;
|
||||||
}
|
}
|
||||||
sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone,
|
|
||||||
ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":"");
|
sprintf(description, "%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s", zone,
|
||||||
strncpy(description+ 8, ROMVER+ 0, 2);//ver major
|
ROMVER[0], ROMVER[1], // ver major
|
||||||
strncpy(description+11, ROMVER+ 2, 2);//ver minor
|
ROMVER[2], ROMVER[3], // ver minor
|
||||||
strncpy(description+14, ROMVER+12, 2);//day
|
ROMVER[12], ROMVER[13], // day
|
||||||
strncpy(description+17, ROMVER+10, 2);//month
|
ROMVER[10], ROMVER[11], // month
|
||||||
strncpy(description+20, ROMVER+ 6, 4);//year
|
ROMVER[6], ROMVER[7], ROMVER[8], ROMVER[9], // year!
|
||||||
|
(ROMVER[5]=='C') ? "Console" : (ROMVER[5]=='D') ? "Devel" : ""
|
||||||
|
);
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,9 @@ extern u64 GetCPUTicks();
|
||||||
extern u64 GetTickFrequency();
|
extern u64 GetTickFrequency();
|
||||||
|
|
||||||
// Used in Misc,and Windows/Linux files.
|
// Used in Misc,and Windows/Linux files.
|
||||||
void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12
|
extern void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12
|
||||||
int IsBIOS(char *filename, char *description);
|
extern int IsBIOS(const char *filename, char *description);
|
||||||
|
|
||||||
char *ParseLang(char *id);
|
char *ParseLang(char *id);
|
||||||
extern const char *LabelAuthors;
|
extern const char *LabelAuthors;
|
||||||
extern const char *LabelGreets;
|
extern const char *LabelGreets;
|
||||||
|
|
|
@ -112,10 +112,10 @@ struct psxRegisters {
|
||||||
u32 code; /* The instruction */
|
u32 code; /* The instruction */
|
||||||
u32 cycle;
|
u32 cycle;
|
||||||
u32 interrupt;
|
u32 interrupt;
|
||||||
u32 sCycle[64]; // start cycle for signaled ints
|
u32 sCycle[32]; // start cycle for signaled ints
|
||||||
s32 eCycle[64]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle)
|
s32 eCycle[32]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle)
|
||||||
u32 _msflag[32];
|
//u32 _msflag[32];
|
||||||
u32 _smflag[32];
|
//u32 _smflag[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
PCSX2_ALIGNED16_EXTERN(psxRegisters psxRegs);
|
PCSX2_ALIGNED16_EXTERN(psxRegisters psxRegs);
|
||||||
|
|
|
@ -522,7 +522,7 @@ __forceinline bool _cpuBranchTest_Shared()
|
||||||
cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );
|
cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );
|
||||||
|
|
||||||
// Apply the hsync counter's nextCycle
|
// Apply the hsync counter's nextCycle
|
||||||
cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT );
|
cpuSetNextBranch( hsyncCounter.sCycle, hsyncCounter.CycleT );
|
||||||
|
|
||||||
// Apply vsync and other counter nextCycles
|
// Apply vsync and other counter nextCycles
|
||||||
cpuSetNextBranch( nextsCounter, nextCounter );
|
cpuSetNextBranch( nextsCounter, nextCounter );
|
||||||
|
|
|
@ -454,11 +454,9 @@ void SPRTOinterrupt()
|
||||||
|
|
||||||
void SaveState::sprFreeze()
|
void SaveState::sprFreeze()
|
||||||
{
|
{
|
||||||
// Gotta save the weird ref-style DMA timing vars!
|
FreezeTag( "SPRdma" );
|
||||||
if( GetVersion() >= 0x05 )
|
|
||||||
{
|
Freeze(spr0finished);
|
||||||
Freeze(spr0finished);
|
Freeze(spr1finished);
|
||||||
Freeze(spr1finished);
|
Freeze(mfifotransferred);
|
||||||
Freeze(mfifotransferred);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -53,7 +53,9 @@ string SaveState::GetFilename( int slot )
|
||||||
return Path::Combine( SSTATES_DIR, fmt_string( "%8.8X.%3.3d", ElfCRC, slot ) );
|
return Path::Combine( SSTATES_DIR, fmt_string( "%8.8X.%3.3d", ElfCRC, slot ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveState::SaveState( const char* msg, const string& destination ) : m_version( g_SaveVersion )
|
SaveState::SaveState( const char* msg, const string& destination ) :
|
||||||
|
m_version( g_SaveVersion )
|
||||||
|
, m_tagspace( 128 )
|
||||||
{
|
{
|
||||||
Console::WriteLn( "%s %hs", params msg, &destination );
|
Console::WriteLn( "%s %hs", params msg, &destination );
|
||||||
}
|
}
|
||||||
|
@ -77,44 +79,76 @@ s32 CALLBACK gsSafeFreeze( int mode, freezeData *data )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SaveState::FreezeTag( const char* src )
|
||||||
|
{
|
||||||
|
const int length = strlen( src );
|
||||||
|
m_tagspace.MakeRoomFor( length+1 );
|
||||||
|
|
||||||
|
strcpy( m_tagspace.GetPtr(), src );
|
||||||
|
FreezeMem( m_tagspace.GetPtr(), length );
|
||||||
|
|
||||||
|
if( strcmp( m_tagspace.GetPtr(), src ) != 0 )
|
||||||
|
{
|
||||||
|
assert( 0 );
|
||||||
|
throw Exception::BadSavedState( string( "Tag: " )+src );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SaveState::FreezeAll()
|
void SaveState::FreezeAll()
|
||||||
{
|
{
|
||||||
if( IsLoading() )
|
if( IsLoading() )
|
||||||
PreLoadPrep();
|
PreLoadPrep();
|
||||||
|
|
||||||
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory
|
// Check the BIOS, and issue a warning if the bios for this state
|
||||||
FreezeMem(PS2MEM_ROM, Ps2MemSize::Rom); // 4 mb rom memory
|
// doesn't match the bios currently being used (chances are it'll still
|
||||||
FreezeMem(PS2MEM_ROM1, Ps2MemSize::Rom1); // 256kb rom1 memory
|
// work fine, but some games are very picky).
|
||||||
FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad
|
|
||||||
FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory
|
|
||||||
|
|
||||||
|
char descout[128], descin[128];
|
||||||
|
memzero_obj( descout );
|
||||||
|
IsBIOS( Config.Bios, descout );
|
||||||
|
memcpy_fast( descin, descout, 128 );
|
||||||
|
Freeze( descin );
|
||||||
|
|
||||||
|
if( memcmp( descin, descout, 128 ) != 0 )
|
||||||
|
{
|
||||||
|
Console::Error(
|
||||||
|
"\n\tWarning: BIOS Version Mismatch, savestate may be unstable!\n"
|
||||||
|
"\t\tCurrent BIOS: %s\n"
|
||||||
|
"\t\tSavestate BIOS: %s\n",
|
||||||
|
params descout, descin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First Block - Memory Dumps
|
||||||
|
// ---------------------------
|
||||||
|
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory
|
||||||
|
FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad
|
||||||
|
FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory
|
||||||
|
|
||||||
|
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory
|
||||||
|
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory
|
||||||
|
FreezeMem(psxS, 0x000100); // iop's sif memory
|
||||||
|
|
||||||
|
// Second Block - Various CPU Registers and States
|
||||||
|
// -----------------------------------------------
|
||||||
|
FreezeTag( "cpuRegs" );
|
||||||
Freeze(cpuRegs); // cpu regs + COP0
|
Freeze(cpuRegs); // cpu regs + COP0
|
||||||
Freeze(psxRegs); // iop regs
|
Freeze(psxRegs); // iop regs
|
||||||
if (GetVersion() >= 0x6)
|
Freeze(fpuRegs);
|
||||||
Freeze(fpuRegs);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Old versiosn didn't save the ACCflags...
|
|
||||||
FreezeLegacy(fpuRegs, sizeof(u32)); // fpu regs
|
|
||||||
fpuRegs.ACCflag = 0;
|
|
||||||
}
|
|
||||||
Freeze(tlb); // tlbs
|
Freeze(tlb); // tlbs
|
||||||
|
|
||||||
|
// Third Block - Cycle Timers and Events
|
||||||
|
// -------------------------------------
|
||||||
|
FreezeTag( "Cycles" );
|
||||||
Freeze(EEsCycle);
|
Freeze(EEsCycle);
|
||||||
Freeze(EEoCycle);
|
Freeze(EEoCycle);
|
||||||
Freeze(psxRegs.cycle); // used to be IOPoCycle. This retains compatibility.
|
|
||||||
Freeze(g_nextBranchCycle);
|
Freeze(g_nextBranchCycle);
|
||||||
Freeze(g_psxNextBranchCycle);
|
Freeze(g_psxNextBranchCycle);
|
||||||
|
|
||||||
Freeze(s_iLastCOP0Cycle);
|
Freeze(s_iLastCOP0Cycle);
|
||||||
Freeze(s_iLastPERFCycle);
|
Freeze(s_iLastPERFCycle);
|
||||||
|
|
||||||
u32 dummy = 1;
|
// Fourth Block - EE-related systems
|
||||||
Freeze( dummy ); // was g_psxWriteOk
|
// ---------------------------------
|
||||||
|
|
||||||
|
|
||||||
//hope didn't forgot any cpu....
|
|
||||||
|
|
||||||
rcntFreeze();
|
rcntFreeze();
|
||||||
gsFreeze();
|
gsFreeze();
|
||||||
vuMicroFreeze();
|
vuMicroFreeze();
|
||||||
|
@ -125,17 +159,16 @@ void SaveState::FreezeAll()
|
||||||
gifFreeze();
|
gifFreeze();
|
||||||
sprFreeze();
|
sprFreeze();
|
||||||
|
|
||||||
// iop now
|
// Fifth Block - iop-related systems
|
||||||
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory
|
// ---------------------------------
|
||||||
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory
|
psxRcntFreeze();
|
||||||
//FreezeMem(psxS, 0x00010000); // sif memory
|
|
||||||
|
|
||||||
sioFreeze();
|
sioFreeze();
|
||||||
|
sio2Freeze();
|
||||||
cdrFreeze();
|
cdrFreeze();
|
||||||
cdvdFreeze();
|
cdvdFreeze();
|
||||||
psxRcntFreeze();
|
|
||||||
sio2Freeze();
|
|
||||||
|
|
||||||
|
// Sixth Block - Plugins Galore!
|
||||||
|
// -----------------------------
|
||||||
FreezePlugin( "GS", gsSafeFreeze );
|
FreezePlugin( "GS", gsSafeFreeze );
|
||||||
FreezePlugin( "SPU2", SPU2freeze );
|
FreezePlugin( "SPU2", SPU2freeze );
|
||||||
FreezePlugin( "DEV9", DEV9freeze );
|
FreezePlugin( "DEV9", DEV9freeze );
|
||||||
|
@ -147,18 +180,6 @@ void SaveState::FreezeAll()
|
||||||
PostLoadPrep();
|
PostLoadPrep();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function is yet incomplete. Version numbers hare still < 0x12 so it won't be run.
|
|
||||||
// (which is good because it won't work :P)
|
|
||||||
void SaveState::_testCdvdCrc()
|
|
||||||
{
|
|
||||||
/*if( GetVersion() < 0x0012 ) return;
|
|
||||||
|
|
||||||
u32 thiscrc = ElfCRC;
|
|
||||||
Freeze( thiscrc );
|
|
||||||
if( thiscrc != ElfCRC )
|
|
||||||
throw Exception::StateCrcMismatch( thiscrc, ElfCRC );*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// gzipped to/from disk state saves implementation
|
// gzipped to/from disk state saves implementation
|
||||||
|
|
||||||
|
@ -215,8 +236,6 @@ gzLoadingState::gzLoadingState( const string& filename ) :
|
||||||
"\tThe savestate was created with a newer version of Pcsx2. I don't know how to load it!" );
|
"\tThe savestate was created with a newer version of Pcsx2. I don't know how to load it!" );
|
||||||
throw Exception::UnsupportedStateVersion( m_version );
|
throw Exception::UnsupportedStateVersion( m_version );
|
||||||
}
|
}
|
||||||
|
|
||||||
_testCdvdCrc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gzLoadingState::~gzLoadingState() { }
|
gzLoadingState::~gzLoadingState() { }
|
||||||
|
@ -229,34 +248,30 @@ void gzSavingState::FreezeMem( void* data, int size )
|
||||||
|
|
||||||
void gzLoadingState::FreezeMem( void* data, int size )
|
void gzLoadingState::FreezeMem( void* data, int size )
|
||||||
{
|
{
|
||||||
gzread( m_file, data, size );
|
if( gzread( m_file, data, size ) != size )
|
||||||
if( gzeof( m_file ) )
|
|
||||||
throw Exception::BadSavedState( m_filename );
|
throw Exception::BadSavedState( m_filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||||
{
|
{
|
||||||
Console::WriteLn( "\tSaving %s", params name );
|
|
||||||
freezeData fP = { 0, NULL };
|
freezeData fP = { 0, NULL };
|
||||||
|
Console::WriteLn( "\tSaving %s", params name );
|
||||||
|
|
||||||
|
FreezeTag( name );
|
||||||
|
|
||||||
if (freezer(FREEZE_SIZE, &fP) == -1)
|
if (freezer(FREEZE_SIZE, &fP) == -1)
|
||||||
throw Exception::FreezePluginFailure( name, "saving" );
|
throw Exception::FreezePluginFailure( name, "saving" );
|
||||||
|
|
||||||
gzwrite(m_file, &fP.size, sizeof(fP.size));
|
Freeze( fP.size );
|
||||||
if( fP.size == 0 ) return;
|
if( fP.size == 0 ) return;
|
||||||
|
|
||||||
fP.data = (s8*)malloc(fP.size);
|
SafeArray<s8> buffer( fP.size );
|
||||||
if (fP.data == NULL)
|
fP.data = buffer.GetPtr();
|
||||||
throw Exception::OutOfMemory();
|
|
||||||
|
|
||||||
if(freezer(FREEZE_SAVE, &fP) == -1)
|
if(freezer(FREEZE_SAVE, &fP) == -1)
|
||||||
throw Exception::FreezePluginFailure( name, "saving" );
|
throw Exception::FreezePluginFailure( name, "saving" );
|
||||||
|
|
||||||
if (fP.size)
|
FreezeMem( fP.data, fP.size );
|
||||||
{
|
|
||||||
gzwrite(m_file, fP.data, fP.size);
|
|
||||||
free(fP.data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
|
||||||
|
@ -264,21 +279,17 @@ void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int
|
||||||
freezeData fP = { 0, NULL };
|
freezeData fP = { 0, NULL };
|
||||||
Console::WriteLn( "\tLoading %s", params name );
|
Console::WriteLn( "\tLoading %s", params name );
|
||||||
|
|
||||||
gzread(m_file, &fP.size, sizeof(fP.size));
|
FreezeTag( name );
|
||||||
|
Freeze( fP.size );
|
||||||
if( fP.size == 0 ) return;
|
if( fP.size == 0 ) return;
|
||||||
|
|
||||||
fP.data = (s8*)malloc(fP.size);
|
SafeArray<s8> buffer( fP.size );
|
||||||
if (fP.data == NULL)
|
fP.data = buffer.GetPtr();
|
||||||
throw Exception::OutOfMemory();
|
|
||||||
int read = gzread(m_file, fP.data, fP.size);
|
|
||||||
|
|
||||||
if( read != fP.size )
|
FreezeMem( fP.data, fP.size );
|
||||||
throw Exception::BadSavedState( m_filename );
|
|
||||||
|
|
||||||
if(freezer(FREEZE_LOAD, &fP) == -1)
|
if(freezer(FREEZE_LOAD, &fP) == -1)
|
||||||
throw Exception::FreezePluginFailure( name, "loading" );
|
throw Exception::FreezePluginFailure( name, "loading" );
|
||||||
|
|
||||||
if (fP.size) free(fP.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -24,10 +24,14 @@
|
||||||
#include "PS2Edefs.h"
|
#include "PS2Edefs.h"
|
||||||
#endif
|
#endif
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
|
|
||||||
// Savestate Versioning!
|
// Savestate Versioning!
|
||||||
// If you make changes to the savestate version, please increment the value below.
|
// If you make changes to the savestate version, please increment the value below.
|
||||||
|
// If the change is minor and compatibility with old states is retained, increment
|
||||||
|
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
||||||
|
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
|
||||||
|
|
||||||
static const u32 g_SaveVersion = 0x8b400006;
|
static const u32 g_SaveVersion = 0x8b410000;
|
||||||
|
|
||||||
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
||||||
// between the GS saving function and the MTGS's needs. :)
|
// between the GS saving function and the MTGS's needs. :)
|
||||||
|
@ -41,6 +45,7 @@ class SaveState
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
u32 m_version; // version of the savestate being loaded.
|
u32 m_version; // version of the savestate being loaded.
|
||||||
|
SafeArray<char> m_tagspace;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SaveState( const char* msg, const string& destination );
|
SaveState( const char* msg, const string& destination );
|
||||||
|
@ -76,6 +81,12 @@ public:
|
||||||
FreezeMem( &data, sizeof( T ) - sizeOfNewStuff );
|
FreezeMem( &data, sizeof( T ) - sizeOfNewStuff );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Freezes an identifier value into the savestate for troubleshooting purposes.
|
||||||
|
// Identifiers can be used to determine where in a savestate that data has become
|
||||||
|
// skewed (if the value does not match then the error occurs somewhere prior to that
|
||||||
|
// position).
|
||||||
|
void FreezeTag( const char* src );
|
||||||
|
|
||||||
// Loads or saves a plugin. Plugin name is for console logging purposes.
|
// Loads or saves a plugin. Plugin name is for console logging purposes.
|
||||||
virtual void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )=0;
|
virtual void FreezePlugin( const char* name, s32 (CALLBACK* freezer)(int mode, freezeData *data) )=0;
|
||||||
|
|
||||||
|
@ -95,11 +106,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Used internally by constructors to check the cdvd's crc against the CRC of the savestate.
|
|
||||||
// This allows for proper exception handling of changed CDs on-the-fly.
|
|
||||||
void _testCdvdCrc();
|
|
||||||
|
|
||||||
|
|
||||||
// Load/Save functions for the various components of our glorious emulator!
|
// Load/Save functions for the various components of our glorious emulator!
|
||||||
|
|
||||||
void rcntFreeze();
|
void rcntFreeze();
|
||||||
|
|
|
@ -586,22 +586,13 @@ __forceinline void dmaSIF2() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SaveState::sifFreeze() {
|
void SaveState::sifFreeze()
|
||||||
|
{
|
||||||
|
FreezeTag( "SIFdma" );
|
||||||
|
|
||||||
Freeze(sif0);
|
Freeze(sif0);
|
||||||
Freeze(sif1);
|
Freeze(sif1);
|
||||||
|
|
||||||
if( GetVersion() >= 0x0002 )
|
Freeze(eesifbusy);
|
||||||
{
|
Freeze(iopsifbusy);
|
||||||
Freeze(eesifbusy);
|
|
||||||
Freeze(iopsifbusy);
|
|
||||||
}
|
|
||||||
else if( IsLoading() )
|
|
||||||
{
|
|
||||||
// Old savestate, inferior data so...
|
|
||||||
// Take an educated guess on what they should be. Or well, set to 1 because
|
|
||||||
// it more or less forces them to "kick"
|
|
||||||
|
|
||||||
iopsifbusy[0] = eesifbusy[0] = 1;
|
|
||||||
iopsifbusy[1] = eesifbusy[1] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -566,22 +566,15 @@ void SaveState::sioFreeze()
|
||||||
// CRCs for memory cards.
|
// CRCs for memory cards.
|
||||||
u64 m_mcdCRCs[2];
|
u64 m_mcdCRCs[2];
|
||||||
|
|
||||||
|
FreezeTag( "sio" );
|
||||||
Freeze( sio );
|
Freeze( sio );
|
||||||
|
|
||||||
// versions prior to 3 didn't have CRCs.
|
if( IsSaving() )
|
||||||
if( GetVersion() >= 0x03 )
|
|
||||||
{
|
{
|
||||||
if( IsSaving() )
|
for( int i=0; i<2; ++i )
|
||||||
{
|
m_mcdCRCs[i] = MemoryCard::GetCRC( i );
|
||||||
for( int i=0; i<2; ++i )
|
|
||||||
m_mcdCRCs[i] = MemoryCard::GetCRC( i );
|
|
||||||
}
|
|
||||||
Freeze( m_mcdCRCs );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_mcdCRCs[0] = m_mcdCRCs[1] = 0;
|
|
||||||
}
|
}
|
||||||
|
Freeze( m_mcdCRCs );
|
||||||
|
|
||||||
if( IsLoading() && Config.McdEnableEject )
|
if( IsLoading() && Config.McdEnableEject )
|
||||||
{
|
{
|
||||||
|
|
|
@ -160,6 +160,8 @@ void vuMicroMemReset()
|
||||||
|
|
||||||
void SaveState::vuMicroFreeze()
|
void SaveState::vuMicroFreeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "vuMicro" );
|
||||||
|
|
||||||
jASSUME( VU0.Mem != NULL );
|
jASSUME( VU0.Mem != NULL );
|
||||||
jASSUME( VU1.Mem != NULL );
|
jASSUME( VU1.Mem != NULL );
|
||||||
|
|
||||||
|
@ -169,15 +171,7 @@ void SaveState::vuMicroFreeze()
|
||||||
FreezeMem(VU0.Micro, 4*1024);
|
FreezeMem(VU0.Micro, 4*1024);
|
||||||
|
|
||||||
Freeze(VU0.VF);
|
Freeze(VU0.VF);
|
||||||
if( GetVersion() >= 0x02 )
|
Freeze(VU0.VI);
|
||||||
Freeze(VU0.VI);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Old versions stored the VIregs as 32 bit values...
|
|
||||||
memzero_obj( VU0.VI );
|
|
||||||
for(int i=0; i<32; i++ )
|
|
||||||
Freeze( VU0.VI[i].UL );
|
|
||||||
}
|
|
||||||
|
|
||||||
Freeze(VU1.ACC);
|
Freeze(VU1.ACC);
|
||||||
Freeze(VU1.code);
|
Freeze(VU1.code);
|
||||||
|
@ -185,14 +179,5 @@ void SaveState::vuMicroFreeze()
|
||||||
FreezeMem(VU1.Micro, 16*1024);
|
FreezeMem(VU1.Micro, 16*1024);
|
||||||
|
|
||||||
Freeze(VU1.VF);
|
Freeze(VU1.VF);
|
||||||
if( GetVersion() >= 0x02 )
|
Freeze(VU1.VI);
|
||||||
Freeze(VU1.VI);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Old versions stored the VIregs as 32 bit values...
|
|
||||||
memzero_obj( VU1.VI );
|
|
||||||
for(int i=0; i<32; i++ )
|
|
||||||
Freeze( VU1.VI[i].UL );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1344,23 +1344,17 @@ void vif0Reset() {
|
||||||
|
|
||||||
void SaveState::vif0Freeze()
|
void SaveState::vif0Freeze()
|
||||||
{
|
{
|
||||||
|
FreezeTag( "VIFdma" );
|
||||||
|
|
||||||
// Dunno if this one is needed, but whatever, it's small. :)
|
// Dunno if this one is needed, but whatever, it's small. :)
|
||||||
if( GetVersion() >= 0x04 )
|
Freeze( g_vifCycles );
|
||||||
Freeze( g_vifCycles );
|
|
||||||
|
|
||||||
Freeze( vif0 );
|
Freeze( vif0 );
|
||||||
if( GetVersion() >= 0x04 )
|
|
||||||
{
|
Freeze( g_vif0HasMask3 );
|
||||||
Freeze( g_vif0HasMask3 );
|
Freeze( g_vif0Masks );
|
||||||
Freeze( g_vif0Masks );
|
Freeze( g_vifRow0 );
|
||||||
Freeze( g_vifRow0 );
|
Freeze( g_vifCol0 );
|
||||||
Freeze( g_vifCol0 );
|
|
||||||
}
|
|
||||||
else if( IsLoading() )
|
|
||||||
{
|
|
||||||
// Hack to "help" old savestates recover...
|
|
||||||
SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2357,16 +2351,8 @@ void SaveState::vif1Freeze()
|
||||||
{
|
{
|
||||||
Freeze(vif1);
|
Freeze(vif1);
|
||||||
|
|
||||||
if( GetVersion() >= 0x04 )
|
Freeze( g_vif1HasMask3 );
|
||||||
{
|
Freeze( g_vif1Masks );
|
||||||
Freeze( g_vif1HasMask3 );
|
Freeze( g_vifRow1 );
|
||||||
Freeze( g_vif1Masks );
|
Freeze( g_vifCol1 );
|
||||||
Freeze( g_vifRow1 );
|
|
||||||
Freeze( g_vifCol1 );
|
|
||||||
}
|
|
||||||
else if( IsLoading() )
|
|
||||||
{
|
|
||||||
SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask);
|
|
||||||
//if(vif1ch->chcr & 0x100) vif1.done = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue