Major GUI stability renovations: Pcsx2 now supports an "automagic" to-memory savestate system that allows it to recover on-the-fly from most dialog box changes (speedhacks, advanced roundmodes, and even MTGS). Use Run:Execute to resume your game right where you left off!

Fixed several memory leaks, including one that ate up about 40 megs of ram everytime you hit esc to go to the GUI.  Also added quite a bit more error checking to init/deinit procedures.

Run:Reset menu now *fully* resets all plugins, including the GS.

Added color to the Win32 console! :)

TODO: The "Configure" dialog box doesn't support the new recovery system yet, so you can't change plugin versions on the fly yet (coming soon).

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@488 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2008-12-25 02:29:43 +00:00 committed by Gregory Hainaut
parent 9a70d486f5
commit 2d95e58bba
69 changed files with 3130 additions and 2112 deletions

View File

@ -583,7 +583,6 @@ s32 cdvdGetTrayStatus()
}
// Note: Is tray status being kept as a var here somewhere?
// cdvdNewDiskCB() can update it's status as well...
extern int needReset;
// Modified by (efp) - 16/01/2006
s32 cdvdGetDiskType() {
@ -596,9 +595,11 @@ s32 cdvdGetDiskType() {
// or just throw it out. CDVDgetDiskType() sets type to "NODISC" anyway.
cdvd.Type = CDVDgetDiskType();
if (cdvd.Type == CDVD_TYPE_PS2CD && needReset == 1) {
if (cdvd.Type == CDVD_TYPE_PS2CD) // && needReset == 1)
{
char str[g_MaxPath];
if (GetPS2ElfName(str) == 1) {
if (GetPS2ElfName(str) == 1)
{
cdvd.Type = CDVD_TYPE_PSCD;
} // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then.
} // ENDIF- Is the type listed as a PS2 CD?
@ -717,16 +718,14 @@ void cdvdReset()
}
int cdvdFreeze(gzFile f, int Mode)
void SaveState::cdvdFreeze()
{
gzfreeze(&cdvd, sizeof(cdvd));
if (Mode == FREEZE_LOAD) {
if (cdvd.Reading) {
cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
}
}
Freeze(cdvd);
return 0;
// Make sure the Cdvd plugin has the expected track loaded into the buffer.
if( IsLoading() && cdvd.Reading)
cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
}
int cdvdInterrupt() {

View File

@ -88,7 +88,6 @@ struct cdvdStruct {
void cdvdReset();
void cdvdVsync();
int cdvdInterrupt();
int cdvdFreeze(gzFile f, int Mode);
extern void cdvdReadInterrupt();
void cdvdNewDiskCB();
u8 cdvdRead04(void);

View File

@ -75,8 +75,8 @@ void CDVDFS_init(){
// CDVDFS_open
// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:"
//////////////////////////////////////////////////////////////////////
int CDVDFS_open(char *name, int mode){
register int j;
int CDVDFS_open(const char *name, int mode){
int j;
static struct TocEntry tocEntry;
// check if the file exists

View File

@ -30,7 +30,7 @@ extern CdRMode cdReadMode;
/* Filing-system exported functions */
void CDVDFS_init();
int CDVDFS_open(char *name, int mode);
int CDVDFS_open(const char *name, int mode);
int CDVDFS_lseek(int fd, int offset, int whence);
int CDVDFS_read( int fd, char * buffer, int size );
int CDVDFS_write( int fd, char * buffer, int size );

View File

@ -226,7 +226,7 @@ void MapTLB(int i)
u32 saddr, eaddr;
#ifndef PCSX2_VIRTUAL_MEM
DevCon::FormatLn("MAP TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X",
DevCon::MsgLn("MAP TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X",
i,tlb[i].VPN2,tlb[i].PFN0,tlb[i].PFN1,tlb[i].S,tlb[i].G,tlb[i].ASID,tlb[i].Mask);
if (tlb[i].S)

View File

@ -951,15 +951,15 @@ void cdrReset() {
cdReadTime = (PSXCLK / 1757) * BIAS;
}
int cdrFreeze(gzFile f, int Mode) {
int tmp;
void SaveState::cdrFreeze() {
Freeze(cdr);
gzfreeze(&cdr, sizeof(cdr));
// Alrighty! This code ised 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.
if (Mode == 1) tmp = (int)(cdr.pTransfer - cdr.Transfer);
gzfreeze(&tmp, 4);
if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp;
return 0;
int tmp; // = (int)(cdr.pTransfer - cdr.Transfer);
Freeze(tmp);
//if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp;
}

View File

@ -89,6 +89,5 @@ void cdrWrite0(u8 rt);
void cdrWrite1(u8 rt);
void cdrWrite2(u8 rt);
void cdrWrite3(u8 rt);
int cdrFreeze(gzFile f, int Mode);
#endif /* __CDROM_H__ */

View File

@ -89,7 +89,7 @@ struct TESTRUNARGS
int numimages;
int curimage;
u32 autopad; // mask for auto buttons
int efile;
bool efile;
int snapdone;
const char* ptitle;

View File

@ -237,7 +237,7 @@ u32 UpdateVSyncRate()
if( m_iTicks != ticks )
{
m_iTicks = ticks;
SysPrintf( limiterMsg, vSyncInfo.Framerate/50, vSyncInfo.Framerate%50 );
SysPrintf( limiterMsg, vSyncInfo.Framerate/50, (vSyncInfo.Framerate*2)%100 );
}
}
@ -299,27 +299,27 @@ void vSyncDebugStuff() {
freezeData fP;
g_SaveGSStream = 2;
gsFreeze(g_fGSSave, 1);
g_fGSSave->gsFreeze();
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
gzclose(g_fGSSave);
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
}
else {
fP.data = (s8*)malloc(fP.size);
if (fP.data == NULL) {
gzclose(g_fGSSave);
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
}
else {
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
gzclose(g_fGSSave);
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
}
else {
gzwrite(g_fGSSave, &fP.size, sizeof(fP.size));
g_fGSSave->Freeze( fP.size );
if (fP.size) {
gzwrite(g_fGSSave, fP.data, fP.size);
g_fGSSave->FreezeMem( fP.data, fP.size );
free(fP.data);
}
}
@ -329,10 +329,9 @@ void vSyncDebugStuff() {
else if( g_SaveGSStream == 2 ) {
if( --g_nLeftGSFrames <= 0 ) {
gzclose(g_fGSSave);
g_fGSSave = NULL;
safe_delete( g_fGSSave );
g_SaveGSStream = 0;
SysPrintf("Done saving GS stream\n");
Console::WriteLn("Done saving GS stream");
}
}
#endif
@ -767,13 +766,13 @@ u32 rcntCycle(int index) {
return counters[index].count;
}
int rcntFreeze(gzFile f, int Mode) {
void SaveState::rcntFreeze()
{
Freeze(counters);
Freeze(nextCounter);
Freeze(nextsCounter);
gzfreezel(counters);
gzfreeze(&nextCounter, sizeof(nextCounter));
gzfreeze(&nextsCounter, sizeof(nextsCounter));
if( Mode == 0 )
if( !IsSaving() )
{
#ifdef PCSX2_VIRTUAL_MEM
// Sanity check for loading older savestates:
@ -788,10 +787,8 @@ int rcntFreeze(gzFile f, int Mode) {
// make sure the gate flags are set based on the counter modes...
for( int i=0; i<4; i++ )
_rcntSetGate( i );
}
iopBranchAction = 1; // probably not needed but won't hurt anything either.
return 0;
iopBranchAction = 1; // probably not needed but won't hurt anything either.
}
}

View File

@ -92,7 +92,6 @@ void rcntWtarget(int index, u32 value);
void rcntWhold(int index, u32 value);
u32 rcntRcount(int index);
u32 rcntCycle(int index);
int rcntFreeze(gzFile f, int Mode);
u32 UpdateVSyncRate();

View File

@ -161,11 +161,11 @@ unsigned int args_ptr; //a big value; in fact, it is an address
//+08+4*argc the program name(first param) <--
//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args'
// see above 'char args[256];'
unsigned int parseCommandLine( char *filename )
static uint parseCommandLine( const char *filename )
{
if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) )
{ // 4 + 4 + 256
char * p;
const char * p;
int argc,
i;
@ -245,7 +245,7 @@ unsigned int parseCommandLine( char *filename )
}
//---------------
int readFile( char *Exepath, char *ptr, u32 offset, int size ) {
static int readFile( const char *Exepath, char *ptr, u32 offset, int size ) {
FILE *f;
int fi;
@ -269,7 +269,7 @@ int readFile( char *Exepath, char *ptr, u32 offset, int size ) {
return size;
}
int loadHeaders( char *Exepath ) {
static int loadHeaders( const char *Exepath ) {
elfHeader = (ELF_HEADER*)elfdata;
if ( ( elfHeader->e_shentsize != sizeof(ELF_SHR) ) && ( elfHeader->e_shnum > 0 ) ) {
@ -340,7 +340,7 @@ int loadHeaders( char *Exepath ) {
}
BOOL loadProgramHeaders( char *Exepath )
static BOOL loadProgramHeaders( const char *Exepath )
{
int i;
@ -388,7 +388,7 @@ BOOL loadProgramHeaders( char *Exepath )
break;
}
ELF_LOG("\n");
ELF_LOG("\n");
ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset);
ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr);
ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr);
@ -404,7 +404,7 @@ BOOL loadProgramHeaders( char *Exepath )
}
BOOL loadSectionHeaders( char * Exepath )
static BOOL loadSectionHeaders( const char * Exepath )
{
int i;
int i_st = -1;
@ -504,12 +504,18 @@ BOOL loadSectionHeaders( char * Exepath )
return TRUE;
}
int loadElfFile(char *filename) {
int loadElfFile(const char *filename) {
char str[256],str2[256];
u32 crc;
u32 i;
SysPrintf("loadElfFile: %s\n", filename);
if( filename == NULL || filename[0] == 0 )
{
Console::Notice( "Running the PS2 BIOS...", filename );
return -1;
}
Console::MsgLn("loadElfFile: %s", filename);
if (strnicmp( filename, "cdrom0:", strlen( "cdrom0:" ) ) &&
strnicmp( filename, "cdrom1:", strlen( "cdrom1:" ) ) ) {
if ( stat( filename, &sbuf ) != 0 )
@ -522,7 +528,7 @@ int loadElfFile(char *filename) {
elfsize = toc.fileSize;
}
SysPrintf("loadElfFile: %d\n", elfsize);
Console::MsgLn( Color_Green, "loadElfFile: %d", elfsize);
elfdata = (u8*)malloc(elfsize);
if (elfdata == NULL) return -1;
readFile(filename, (char*)elfdata, 0, elfsize);
@ -556,21 +562,21 @@ int loadElfFile(char *filename) {
}
ElfCRC = crc;
SysPrintf("loadElfFile: %s; CRC = %8.8X\n", filename, crc);
Console::MsgLn( Color_Green, "loadElfFile: %s; CRC = %8.8X\n", filename, crc);
// Applying patches
if (Config.Patch) {
sprintf(str, "%8.8x", crc);
sprintf(str2,"No patch found.Game will run normally. [CRC=%8.8x]",crc);//if patches found it will overwritten :p
sprintf(str2,"No patch found. Game will run normally. [CRC=%8.8x]",crc);//if patches found it will overwritten :p
Console::SetTitle( str2 );
if(LoadPatch(str)!=0)
{
SysPrintf("XML Loader returned an error. Trying to load a pnach...\n");
Console::WriteLn("XML Loader returned an error. Trying to load a pnach...");
inifile_read(str);
}
else SysPrintf("XML Loading success. Will not load from pnach...\n");
else Console::WriteLn("XML Loading success. Will not load from pnach...");
applypatch( 0 );
}

View File

@ -24,7 +24,7 @@ extern char args[256]; //to be filled by GUI
extern unsigned int args_ptr;
//-------------------
int loadElfFile(char *filename);
int loadElfFile(const char *filename);
void LoadGameSpecificSettings();
extern u32 ElfCRC;

127
pcsx2/Exceptions.h Normal file
View File

@ -0,0 +1,127 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _PCSX2_EXCEPTIONS_H_
#define _PCSX2_EXCEPTIONS_H_
#include <string>
namespace Exception
{
// This exception exception thrown any time an operation is attempted when an object
// is in an uninitialized state.
class InvalidOperation : public std::logic_error
{
public:
virtual ~InvalidOperation() throw() {}
explicit InvalidOperation( const std::string& msg="Attempted method call is invalid for the current object or program state." ) :
logic_error( msg ) {}
};
// This exception is thrown by the PS2 emulation (R5900, etc) when bad things happen
// that force the emulation state to terminate. The GUI should handle them by returning
// the user to the GUI.
class CpuStateShutdown : public std::runtime_error
{
public:
virtual ~CpuStateShutdown() throw() {}
explicit CpuStateShutdown( const std::string& msg="The PS2 emulated state was shut down unexpectedly." ) :
runtime_error( msg ) {}
};
// Exception thrown by SaveState class when a critical plugin or gzread
class FreezePluginFailure : public std::runtime_error
{
public:
std::string plugin_name; // name of the plugin
std::string freeze_action;
virtual ~FreezePluginFailure() throw() {}
explicit FreezePluginFailure( const std::string& plugin, const std::string& action ) :
runtime_error( plugin + " plugin returned an error while " + action + " the state." )
, plugin_name( plugin )
, freeze_action( action ){}
};
class UnsupportedStateVersion : public std::runtime_error
{
public:
virtual ~UnsupportedStateVersion() throw() {}
explicit UnsupportedStateVersion( const std::string& msg="Unknown or unsupported savestate version." ) :
runtime_error( msg ) {}
};
class PluginFailure : public std::runtime_error
{
public:
std::string plugin_name; // name of the plugin
virtual ~PluginFailure() throw() {}
explicit PluginFailure( const std::string& plugin, const std::string& msg = "An error occured in the " ) :
runtime_error( plugin + msg + " Plugin" )
, plugin_name( plugin ) {}
};
/**** BEGIN STREAMING EXCEPTIONS ****/
// Generic stream error. Contains the name of the stream and a message.
// This exception is usually thrown via derrived classes, except in the (rare) case of a generic / unknown error.
class Stream : public std::runtime_error
{
public:
std::string stream_name; // name of the stream (if applicable)
virtual ~Stream() throw() {}
// copy construct!
Stream( const Stream& src ) :
std::runtime_error( src.what() )
, stream_name( src.stream_name ) {}
explicit Stream(
const std::string& objname=std::string(),
const std::string& msg="Invalid stream object" ) :
std::runtime_error( msg + ": " + objname )
, stream_name( objname ) {}
};
// Exception thrown when a corrupted or truncated savestate is encountered.
class BadSavedState : public Stream
{
public:
virtual ~BadSavedState() throw() {}
explicit BadSavedState(
const std::string& objname=std::string(),
const std::string& msg="Corrupted data or end of file encountered while loading savestate" ) :
Stream( objname, msg ) {}
};
// Exception thrown when an attempt to open a non-existant file is made.
// (this exception can also mean file permissions are invalid)
class FileNotFound : public Stream
{
public:
virtual ~FileNotFound() throw() {}
explicit FileNotFound(
const std::string& objname=std::string(),
const std::string& msg="File not found or permission denied" ) :
Stream( objname, msg ) {}
};
}
#endif

View File

@ -224,15 +224,15 @@ static s32 g_pGSvSyncCount = 0;
// GS Playback
int g_SaveGSStream = 0; // save GS stream; 1 - prepare, 2 - save
int g_nLeftGSFrames = 0; // when saving, number of frames left
gzFile g_fGSSave;
gzSavingState* g_fGSSave;
void GSGIFTRANSFER1(u32 *pMem, u32 addr) {
if( g_SaveGSStream == 2) {
u32 type = GSRUN_TRANS1;
u32 size = (0x4000-(addr))/16;
gzwrite(g_fGSSave, &type, sizeof(type));
gzwrite(g_fGSSave, &size, 4);
gzwrite(g_fGSSave, ((u8*)pMem)+(addr), size*16);
u32 size = (0x4000-(addr))/16;
g_fGSSave->Freeze( type );
g_fGSSave->Freeze( size );
g_fGSSave->FreezeMem( ((u8*)pMem)+(addr), size*16 );
}
GSgifTransfer1(pMem, addr);
}
@ -241,9 +241,9 @@ void GSGIFTRANSFER2(u32 *pMem, u32 size) {
if( g_SaveGSStream == 2) {
u32 type = GSRUN_TRANS2;
u32 _size = size;
gzwrite(g_fGSSave, &type, sizeof(type));
gzwrite(g_fGSSave, &_size, 4);
gzwrite(g_fGSSave, pMem, _size*16);
g_fGSSave->Freeze( type );
g_fGSSave->Freeze( size );
g_fGSSave->FreezeMem( pMem, _size*16 );
}
GSgifTransfer2(pMem, size);
}
@ -252,9 +252,9 @@ void GSGIFTRANSFER3(u32 *pMem, u32 size) {
if( g_SaveGSStream == 2 ) {
u32 type = GSRUN_TRANS3;
u32 _size = size;
gzwrite(g_fGSSave, &type, sizeof(type));
gzwrite(g_fGSSave, &_size, 4);
gzwrite(g_fGSSave, pMem, _size*16);
g_fGSSave->Freeze( type );
g_fGSSave->Freeze( size );
g_fGSSave->FreezeMem( pMem, _size*16 );
}
GSgifTransfer3(pMem, size);
}
@ -262,7 +262,7 @@ void GSGIFTRANSFER3(u32 *pMem, u32 size) {
__forceinline void GSVSYNC(void) {
if( g_SaveGSStream == 2 ) {
u32 type = GSRUN_VSYNC;
gzwrite(g_fGSSave, &type, sizeof(type));
g_fGSSave->Freeze( type );
}
}
#else
@ -450,9 +450,21 @@ void gsSetVideoRegionType( u32 isPal )
// Initializes MultiGS ringbuffer and registers.
// (does nothing for single threaded GS)
// Make sure framelimiter options are in sync with the plugin's capabilities.
void gsInit()
{
switch(CHECK_FRAMELIMIT)
{
case PCSX2_FRAMELIMIT_SKIP:
case PCSX2_FRAMELIMIT_VUSKIP:
if( GSsetFrameSkip == NULL )
{
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
Console::WriteLn("Notice: Disabling frameskip -- GS plugin does not support it.");
}
break;
}
if( CHECK_MULTIGS )
{
g_pGSRingPos = GS_RINGBUFFERBASE;
@ -607,7 +619,7 @@ void GSRINGBUF_DONECOPY(const u8* mem, u32 size)
}
}
void gsShutdown()
void gsClose()
{
if( CHECK_MULTIGS ) {
@ -616,7 +628,7 @@ void gsShutdown()
// (they might be 1 byte under some compilers).
gsHasToExit = true;
SysPrintf("MTGS > Closing GS thread...\n");
Console::WriteLn( "MTGS > Closing GS thread..." );
GS_SETEVENT();
if (g_hVuGsThread != NULL) thread_close( g_hVuGsThread );
@ -630,6 +642,8 @@ void gsShutdown()
}
else
GSclose();
m_gsOpened = false;
}
#ifdef PCSX2_GSRING_TX_STATS
@ -824,8 +838,6 @@ void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
while( future_writepos == *(volatile PU8*)&g_pGSRingPos )
gsSetEventWait();
#ifdef RINGBUF_DEBUG_STACK
mutex_lock( stackLock );
ringposStack.push_front( (uptr)writepos );
@ -841,7 +853,7 @@ void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
AtomicExchangePointer( g_pGSWritePos, future_writepos );
}
void GSRingBufSimplePacket64(int type, u32 data0, u64 data1 )
void GSRingBufPointerPacket(int type, u32 data0, void* data1 )
{
u8* writepos = g_pGSWritePos;
const u8* future_writepos = writepos+16;
@ -862,7 +874,7 @@ void GSRingBufSimplePacket64(int type, u32 data0, u64 data1 )
*(u32*)writepos = type;
*(u32*)(writepos+4) = data0;
*(u64*)(writepos+8) = data1;
*(uptr*)(writepos+8) = (uptr)data1;
assert( future_writepos != *(volatile PU8*)&g_pGSRingPos );
AtomicExchangePointer( g_pGSWritePos, future_writepos );
@ -1254,9 +1266,7 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
else if(path.tag.nloop == 0)
{
if(pathidx == 0 && g_FFXHack)
{
continue;
}
eop = true;
}
@ -1270,6 +1280,9 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
while(size > 0)
{
// Register 0xe is a NOP.
// Why were we treating it as a handler?
if( path.GetReg() == 0xe )
{
const int handler = pMem[8];
@ -1285,13 +1298,11 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
path.tag.nloop--;
if(path.tag.nloop == 0)
{
break;
}
}
}
break;
break;
case GIF_FLG_REGLIST:
@ -1319,32 +1330,27 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
}
if(size & 1) pMem += 8; //sizeof(GIFReg);
size /= 2;
break;
break;
case GIF_FLG_IMAGE2: // hmmm
assert(0);
path.tag.nloop = 0;
break;
break;
case GIF_FLG_IMAGE:
{
int len = (int)min(size, path.tag.nloop);
{
int len = (int)min(size, path.tag.nloop);
//ASSERT(!(len&3));
pMem += len * 16;
path.tag.nloop -= len;
size -= len;
}
break;
//ASSERT(!(len&3));
pMem += len * 16;
path.tag.nloop -= len;
size -= len;
}
break;
jNO_DEFAULT;
@ -1364,7 +1370,7 @@ u32 GSgifTransferDummy(int pathidx, const u8 *pMem, u32 size)
if(!path.tag.eop && path.tag.nloop > 0)
{
path.tag.nloop = 0;
SysPrintf( "path1 hack! " );
Console::Write( "path1 hack! " );
}
}
@ -2207,52 +2213,13 @@ GS_THREADPROC
break;
case GS_RINGTYPE_SAVE:
{
gzFile f = *(gzFile*)(g_pGSRingPos+4);
freezeData fP;
if (GSfreeze(FREEZE_SIZE, &fP) == -1) {
gzclose(f);
break;
}
fP.data = (s8*)malloc(fP.size);
if (fP.data == NULL) {
break;
}
if (GSfreeze(FREEZE_SAVE, &fP) == -1) {
gzclose(f);
break;
}
gzwrite(f, &fP.size, sizeof(fP.size));
if (fP.size) {
gzwrite(f, fP.data, fP.size);
free(fP.data);
}
break;
}
case GS_RINGTYPE_LOAD:
{
gzFile f = *(gzFile*)(g_pGSRingPos+4);
freezeData fP;
gzread(f, &fP.size, sizeof(fP.size));
if (fP.size) {
fP.data = (s8*)malloc(fP.size);
if (fP.data == NULL)
break;
gzread(f, fP.data, fP.size);
}
if (GSfreeze(FREEZE_LOAD, &fP) == -1) {
// failed
}
if (fP.size)
free(fP.data);
SaveState* f = (SaveState*)(*(uptr*)(g_pGSRingPos+8));
f->FreezePlugin( "GS", GSfreeze );
break;
}
case GS_RINGTYPE_RECORD:
{
int record = *(u32*)(g_pGSRingPos+4);
@ -2312,25 +2279,23 @@ GS_THREADPROC
return 0;
}
int gsFreeze(gzFile f, int Mode)
void SaveState::gsFreeze()
{
gzfreeze(PS2MEM_GS, 0x2000);
gzfreeze(&CSRw, sizeof(CSRw));
FreezeMem(PS2MEM_GS, 0x2000);
Freeze(CSRw);
for(int i=0; i<3; i++ )
{
gzfreeze( &g_path[i].tag, sizeof( g_path[i].tag ) );
Freeze( g_path[i].tag );
// Earlier versions had an extra u32 in the tag struct:
u32 dummy=g_path[i].nreg;
gzfreeze( &dummy, sizeof( dummy ) );
Freeze( dummy );
}
for(int i=0; i<3; i++ )
gzfreeze( &g_path[i].regs, sizeof( g_path[i].regs ) );
return 0;
Freeze( g_path[i].regs );
}
#ifdef PCSX2_DEVBUILD
@ -2342,16 +2307,17 @@ struct GSStatePacket
};
// runs the GS
void RunGSState(gzFile f)
void RunGSState( gzLoadingState& f )
{
u32 newfield;
list< GSStatePacket > packets;
while(!gzeof(f)) {
while( !f.Finished() )
{
int type, size;
gzread(f, &type, sizeof(type));
f.Freeze( type );
if( type != GSRUN_VSYNC ) gzread(f, &size, 4);
if( type != GSRUN_VSYNC ) f.Freeze( size );
packets.push_back(GSStatePacket());
GSStatePacket& p = packets.back();
@ -2360,7 +2326,7 @@ void RunGSState(gzFile f)
if( type != GSRUN_VSYNC ) {
p.mem.resize(size*16);
gzread(f, &p.mem[0], size*16);
f.FreezeMem( &p.mem[0], size*16 );
}
}
@ -2393,8 +2359,8 @@ void RunGSState(gzFile f)
if( g_SaveGSStream != 3 )
return;
break;
default:
assert(0);
jNO_DEFAULT
}
++it;

View File

@ -76,13 +76,13 @@ enum GS_RINGTYPE
// if returns NULL, don't copy (memory is preserved)
u8* GSRingBufCopy(u32 size, u32 type);
void GSRingBufSimplePacket(int type, int data0, int data1, int data2);
void GSRingBufSimplePacket64(int type, u32 data0, u64 data1 );
void GSRingBufPointerPacket(int type, u32 data0, void* data1 );
u32 GSgifTransferDummy(int path, const u8 *pMem, u32 size);
void gsInit();
s32 gsOpen();
void gsShutdown();
void gsClose();
void gsReset();
void gsSetVideoRegionType( u32 isPal );
void gsResetFrameSkip();
@ -125,7 +125,6 @@ extern void gsInterrupt();
void dmaGIF();
void GIFdma();
void mfifoGIFtransfer(int qwc);
int gsFreeze(gzFile f, int Mode);
int _GIFchain();
void gifMFIFOInterrupt();
@ -141,11 +140,11 @@ extern u32 g_vu1SkipCount;
extern int g_SaveGSStream;
extern int g_nLeftGSFrames;
extern gzFile g_fGSSave;
extern gzSavingState* g_fGSSave;
#endif
void RunGSState(gzFile f);
void RunGSState(gzLoadingState& f);
extern void GSGIFTRANSFER1(u32 *pMem, u32 addr);
extern void GSGIFTRANSFER2(u32 *pMem, u32 addr);

View File

@ -170,69 +170,67 @@ void ipuShutdown()
{
}
int ipuFreeze(gzFile f, int Mode) {
// fixme - ipuFreeze looks fairly broken. Should probably take a closer look at some point.
void SaveState::ipuFreeze() {
IPUProcessInterrupt();
gzfreeze(ipuRegs, sizeof(IPUregisters));
gzfreeze(&g_nDMATransfer, sizeof(g_nDMATransfer));
gzfreeze(&FIreadpos, sizeof(FIreadpos));
gzfreeze(&FIwritepos, sizeof(FIwritepos));
gzfreeze(fifo_input, sizeof(fifo_input));
gzfreeze(&FOreadpos, sizeof(FOreadpos));
gzfreeze(&FOwritepos, sizeof(FOwritepos));
gzfreeze(fifo_output, sizeof(fifo_output));
gzfreeze(&g_BP, sizeof(g_BP));
gzfreeze(niq, sizeof(niq));
gzfreeze(iq, sizeof(niq));
gzfreeze(vqclut, sizeof(vqclut));
gzfreeze(s_thresh, sizeof(s_thresh));
gzfreeze(&coded_block_pattern, sizeof(coded_block_pattern));
gzfreeze(&g_decoder, sizeof(g_decoder));
gzfreeze(mpeg2_scan_norm, sizeof(mpeg2_scan_norm));
gzfreeze(mpeg2_scan_alt, sizeof(mpeg2_scan_alt));
gzfreeze(g_nCmdPos, sizeof(g_nCmdPos));
gzfreeze(&g_nCmdIndex, sizeof(g_nCmdIndex));
gzfreeze(&ipuCurCmd, sizeof(ipuCurCmd));
FreezeMem(ipuRegs, sizeof(IPUregisters));
Freeze(g_nDMATransfer);
Freeze(FIreadpos);
Freeze(FIwritepos);
Freeze(fifo_input);
Freeze(FOreadpos);
Freeze(FOwritepos);
Freeze(fifo_output);
Freeze(g_BP);
Freeze(niq);
Freeze(iq);
Freeze(vqclut);
Freeze(s_thresh);
Freeze(coded_block_pattern);
Freeze(g_decoder);
Freeze(mpeg2_scan_norm);
Freeze(mpeg2_scan_alt);
Freeze(g_nCmdPos);
Freeze(g_nCmdIndex);
Freeze(ipuCurCmd);
gzfreeze(_readbits, sizeof(_readbits));
Freeze(_readbits);
if( Mode == 0 ) {
int temp = readbits-_readbits;
gzfreeze(&temp, sizeof(temp));
}
else {
int temp;
gzfreeze(&temp, sizeof(temp));
int temp = readbits-_readbits;
Freeze(temp);
if( IsLoading() )
{
readbits = _readbits;
//other stuff
g_decoder.intra_quantizer_matrix =(u8*)iq;
g_decoder.non_intra_quantizer_matrix =(u8*)niq;
g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P
g_decoder.mb8 =&mb8;
g_decoder.mb16=&mb16;
g_decoder.rgb32=&rgb32;
g_decoder.rgb16=&rgb16;
g_decoder.stride=16;
if (!mpeg2_inited){
mpeg2_idct_init();
convert=convert_rgb (CONVERT_RGB, 32);
convert(16, 16, 0, NULL, &convert_init);
memset(mb8.Y,0,sizeof(mb8.Y));
memset(mb8.Cb,0,sizeof(mb8.Cb));
memset(mb8.Cr,0,sizeof(mb8.Cr));
memset(mb16.Y,0,sizeof(mb16.Y));
memset(mb16.Cb,0,sizeof(mb16.Cb));
memset(mb16.Cr,0,sizeof(mb16.Cr));
mpeg2_inited=1;
}
}
//other stuff
g_decoder.intra_quantizer_matrix =(u8*)iq;
g_decoder.non_intra_quantizer_matrix =(u8*)niq;
g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P
g_decoder.mb8 =&mb8;
g_decoder.mb16=&mb16;
g_decoder.rgb32=&rgb32;
g_decoder.rgb16=&rgb16;
g_decoder.stride=16;
if (!mpeg2_inited){
mpeg2_idct_init();
convert=convert_rgb (CONVERT_RGB, 32);
convert(16, 16, 0, NULL, &convert_init);
memset(mb8.Y,0,sizeof(mb8.Y));
memset(mb8.Cb,0,sizeof(mb8.Cb));
memset(mb8.Cr,0,sizeof(mb8.Cr));
memset(mb16.Y,0,sizeof(mb16.Y));
memset(mb16.Cb,0,sizeof(mb16.Cb));
memset(mb16.Cr,0,sizeof(mb16.Cr));
mpeg2_inited=1;
}
return 0;
}
BOOL ipuCanFreeze()
bool ipuCanFreeze()
{
return ipuCurCmd == 0xffffffff;
}

View File

@ -195,7 +195,7 @@ int ipuInit();
void ipuReset();
void ipuShutdown();
int ipuFreeze(gzFile f, int Mode);
BOOL ipuCanFreeze();
bool ipuCanFreeze();
u32 ipuRead32(u32 mem);
int ipuConstRead32(u32 x86reg, u32 mem);

View File

@ -833,7 +833,7 @@ int __Deci2Call(int call, u32 *addr) {
return 1;
case 0x10://kputs
SysPrintf("%s", PSM(*addr));
Console::Msg( Color_Cyan, "%s", PSM(*addr));
return 1;
}
@ -850,7 +850,7 @@ void SYSCALL() {
else call = cpuRegs.GPR.n.v1.UC[0];
BIOS_LOG("Bios call: %s (%x)\n", bios[call], call);
if (call == 0x7c && cpuRegs.GPR.n.a0.UL[0] == 0x10) {
SysPrintf("%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0])));
Console::Msg( Color_Cyan, "%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0])));
} else
//if (call == 0x7c) SysPrintf("Deci2Call: %x\n", cpuRegs.GPR.n.a0.UL[0]);
if (call == 0x7c) __Deci2Call(cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0]));

View File

@ -124,6 +124,18 @@ void SignalExit(int sig) {
void RunExecute(int run)
{
// (air notes:)
// If you want to use the new to-memory savestate feature, take a look at the new
// RunExecute in WinMain.c, and secondly the CpuDlg.c or AdvancedDlg.cpp. The
// objects used are MemoryAlloc, memLoadingState, and memSavingState.
// It's important to make sure to reset the CPU and the plugins correctly, which is
// where the new RunExecute comes into play. It can be kind of tricky knowing
// when to call cpuExecuteBios and loadElfFile, and with what parameters.
// (or, as an alternative maybe we should switch to wxWidgets and have a unified
// cross platform gui?) - Air
if (needReset == TRUE)
if (!SysReset())
return;
@ -281,31 +293,102 @@ void UpdateMenuSlots(GtkMenuItem *menuitem, gpointer user_data) {
}
}
void States_Load(int num) {
char Text[g_MaxPath];
int ret;
void States_Load(const char* file, int num = -1 )
{
efile = 2;
RunExecute(0);
try
{
// when we init joe it'll throw an UnsupportedStateVersion.
// So reset the cpu afterward so that trying to load a bum save
// doesn't fry the current emulation state.
gzLoadingState joe( file );
sprintf (Text, SSTATES_DIR "/%8.8X.%3.3d", ElfCRC, num);
ret = LoadState(Text);
// Make sure the cpu and plugins are ready to be state-ified!
cpuReset();
OpenPlugins( NULL );
joe.FreezeAll();
}
catch( Exception::UnsupportedStateVersion& )
{
if( num != -1 )
SysMessage( _( "Savestate slot %d is an unsupported version." ), num);
else
SysMessage( _( "%s : This is an unsupported savestate version." ), file);
// At this point the cpu hasn't been reset, so we can return
// control to the user safely...
return;
}
catch( std::exception& ex )
{
if( num != -1 )
Console::Error( _("Error occured while trying to load savestate slot %d"), num);
else
Console::Error( _("Error occured while trying to load savestate file: %d"), file);
Console::Error( ex.what() );
// The emulation state is ruined. Might as well give them a popup and start the gui.
SysMessage( _(
"An error occured while trying to load the savestate data.\n"
"Pcsx2 emulation state has been reset."
) );
cpuShutdown();
return;
}
Cpu->Execute();
}
void States_Load(int num) {
char Text[g_MaxPath];
SaveState::GetFilename( Text, num );
struct stat buf;
if( stat(Text, &buf ) == -1 )
{
Console::Notice( "Saveslot %d is empty.", num );
return;
}
States_Load( Text, num );
}
void States_Save( const char* file, int num = -1 );
{
try
{
gzSavingState(file).FreezeAll();
if( num != -1 )
Console::Notice( _( "State saved to slot %d" ), num );
else
Console::Notice( _( "State saved to file: %s" ), file );
}
catch( std::exception& ex )
{
if( num != -1 )
SysMessage( _("An error occured while trying to save to slot %d"), num );
else
SysMessage( _("An error occured while trying to save to file: %s"), file );
Console::Error( _( "Save state request failed with the following error:" ) );
Console::Error( ex.what() );
}
// Do you really want the game ro resume after saving from the menu?
// I found it annoying and removed it from the Win32 side (air)
RunExecute(1);
}
void States_Save(int num) {
char Text[g_MaxPath];
int ret;
sprintf (Text, SSTATES_DIR "/%8.8X.%3.3d", ElfCRC, num);
ret = SaveState(Text);
if (ret == 0)
sprintf(Text, _("*PCSX2*: Saving State %d"), num+1);
else
sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1);
RunExecute(1);
SaveState::GetFilename( Text, num );
States_Save( Text, num );
}
void OnStates_Load1(GtkMenuItem *menuitem, gpointer user_data) { States_Load(0); }
@ -323,12 +406,7 @@ void OnLoadOther_Ok(GtkButton* button, gpointer user_data) {
strcpy(str, File);
gtk_widget_destroy(FileSel);
efile = 2;
RunExecute(0);
ret = LoadState(str);
Cpu->Execute();
States_Load( str );
}
void OnLoadOther_Cancel(GtkButton* button, gpointer user_data) {
@ -367,11 +445,8 @@ void OnSaveOther_Ok(GtkButton* button, gpointer user_data) {
File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel));
strcpy(str, File);
gtk_widget_destroy(FileSel);
RunExecute(0);
ret = SaveState(str);
Cpu->Execute();
States_Save( str );
}
void OnSaveOther_Cancel(GtkButton* button, gpointer user_data) {
@ -451,13 +526,6 @@ void OnCpu_Ok(GtkButton *button, gpointer user_data) {
Config.CustomConsecutiveFrames = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(CpuDlg, "FramesBeforeSkipping")));
Config.CustomConsecutiveSkip = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(CpuDlg, "FramesToSkip")));
if ((Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD)) {
Config.Options = newopts;
SaveConfig();
SysMessage("Restart Pcsx2");
exit(0);
}
if (newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC;
Config.Options = newopts;
@ -465,8 +533,14 @@ void OnCpu_Ok(GtkButton *button, gpointer user_data) {
UpdateVSyncRate();
SaveConfig();
cpuRestartCPU();
if ((Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD))
{
cpuShutdown();
ResetPlugins();
}
cpuReset(); // cpuReset will call cpuInit() automatically if needed.
gtk_widget_destroy(CpuDlg);
if (MainWindow) gtk_widget_set_sensitive(MainWindow, TRUE);
gtk_main_quit();

View File

@ -21,10 +21,26 @@
#include "System.h"
#include "Linux.h"
#define COLOR_RESET "\033[0m"
// Linux Note : The Linux Console is pretty simple. It just dumps to the stdio!
// (no console open/close/title stuff tho, so those functions are dummies)
namespace Console
{
static const char* tbl_color_codes[] =
{
"\033[30m" // black
, "\033[31m" // red
, "\033[32m" // green
, "\033[33m" // yellow
, "\033[34m" // blue
, "\033[35m" // magenta
, "\033[36m" // cyan
, "\033[37m" // white!
};
void SetTitle( const char* title )
{
}
@ -63,6 +79,16 @@ namespace Console
return false;
}
void __fastcall SetColor( Colors color )
{
Write( tbl_color_codes[color] );
}
void ClearColor()
{
Write( COLOR_RESET );
}
__forceinline bool __fastcall WriteLn( const char* fmt )
{
Write( fmt );
@ -70,7 +96,38 @@ namespace Console
return false;
}
bool Format( const char* fmt, ... )
static __forceinline void __fastcall _MsgLn( Colors color, const char* fmt, va_list args )
{
char msg[2048];
vsnprintf(msg,2045,fmt,list);
msg[2044] = '\0';
strcat( msg, "\n" );
SetColor( color );
Write( msg );
ClearColor();
if( emuLog != NULL )
fflush( emuLog ); // manual flush to accompany manual newline
}
bool Msg( Colors color, const char* fmt, ... )
{
va_list list;
char msg[2048];
va_start(list,fmt);
vsnprintf(msg,2047,fmt,list);
msg[2047] = '\0';
va_end(list);
SetColor( color );
Write( msg );
ClearColor();
return false;
}
bool Msg( const char* fmt, ... )
{
va_list list;
char msg[2048];
@ -84,7 +141,7 @@ namespace Console
return false;
}
bool FormatLn( const char* fmt, ... )
bool MsgLn( const char* fmt, ... )
{
va_list list;
char msg[2048];
@ -99,5 +156,27 @@ namespace Console
fflush( emuLog ); // manual flush to accomany manual newline
return false;
}
// Displays a message in the console with red emphasis.
// Newline is automatically appended.
bool Error( const char* fmt, ... )
{
va_list list;
va_start(list,fmt);
_MsgLn( Color_Red, fmt, list );
va_end(list);
return false;
}
// Displays a message in the console with yellow emphasis.
// Newline is automatically appended.
bool Notice( const char* fmt, ... )
{
va_list list;
va_start(list,fmt);
_MsgLn( Color_Yellow, fmt, list );
va_end(list);
return false;
}
}

View File

@ -26,7 +26,7 @@
namespace EE { namespace Interpreter{ namespace OpcodeImpl
{
void MMI_Unknown() { SysPrintf ("Unknown MMI opcode called\n"); }
void MMI_Unknown() { Console::Notice("Unknown MMI opcode called"); }
//*****************MMI OPCODES*********************************

View File

@ -104,19 +104,37 @@ u16 ba0R16(u32 mem) {
/////////////////////////////
#ifdef PCSX2_VIRTUAL_MEM
class vm_alloc_failed_exception : public std::runtime_error
{
public:
void* requested_addr;
int requested_size;
void* returned_addr;
explicit vm_alloc_failed_exception( void* reqadr, uint reqsize, void* retadr ) :
std::runtime_error( "virtual memory allocation failure." )
, requested_addr( reqadr )
, requested_size( reqsize )
, returned_addr( retadr )
{}
};
PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0};
#define PHYSICAL_ALLOC(ptr, size, block) { \
if(SysPhysicalAlloc(size, &block) == -1 ) \
goto eCleanupAndExit; \
if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \
goto eCleanupAndExit; \
} \
static void PHYSICAL_ALLOC( void* ptr, uint size, PSMEMORYBLOCK& block)
{
if(SysPhysicalAlloc(size, &block) == -1 )
throw vm_alloc_failed_exception( ptr, size, NULL );
if(SysVirtualPhyAlloc(ptr, size, &block) == -1)
throw vm_alloc_failed_exception( ptr, size, NULL );
}
static void PHYSICAL_FREE( void* ptr, uint size, PSMEMORYBLOCK& block)
{
SysVirtualFree(ptr, size);
SysPhysicalFree(&block);
}
#define PHYSICAL_FREE(ptr, size, block) { \
SysVirtualFree(ptr, size); \
SysPhysicalFree(&block); \
} \
#ifdef _WIN32 // windows implementation of vm
@ -136,19 +154,19 @@ static PSMEMORYMAP initMemoryMap(uptr* aPFNs, uptr* aVFNs)
// virtual memory blocks
PSMEMORYMAP *memLUT = NULL;
#define VIRTUAL_ALLOC(base, size, Protection) { \
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \
if( lpMemReserved == NULL || base != lpMemReserved ) \
{ \
SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \
goto eCleanupAndExit; \
} \
} \
static void VIRTUAL_ALLOC( void* base, uint size, uint Protection)
{
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection );
if( base != lpMemReserved )
throw vm_alloc_failed_exception( base, size, lpMemReserved );
}
#define VIRTUAL_FREE(ptr, size) { \
VirtualFree(ptr, size, MEM_DECOMMIT); \
VirtualFree(ptr, 0, MEM_RELEASE); \
} \
static void ReserveExtraMem( void* base, uint size )
{
void* pExtraMem = VirtualAlloc(base, size, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != base )
throw vm_alloc_failed_exception( base, size, pExtraMem);
}
int memInit() {
@ -158,72 +176,81 @@ int memInit() {
// release the previous reserved mem
VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE);
// allocate all virtual memory
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY);
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
try
{
// allocate all virtual memory
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY);
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE);
//VIRTUAL_ALLOC(PS2MEM_PSXHW2, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE);
//VIRTUAL_ALLOC(PS2MEM_PSXHW2, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE);
// reserve the left over 224Mb, don't map
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != PS2MEM_BASE+0x02000000 )
goto eCleanupAndExit;
// reserve the left over 224Mb, don't map
ReserveExtraMem( PS2MEM_BASE+0x02000000, 0x0e000000 );
// reserve left over psx mem
pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != PS2MEM_PSX+0x00200000 )
goto eCleanupAndExit;
// reserve left over psx mem
ReserveExtraMem( PS2MEM_PSX+0x00200000, 0x00600000 );
// reserve gs mem
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != PS2MEM_BASE+0x20000000 )
goto eCleanupAndExit;
// special addrs mmap
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE);
// reserve gs mem
ReserveExtraMem( PS2MEM_BASE+0x20000000, 0x10000000 );
// special addrs mmap
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE);
// alloc virtual mappings
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16);
memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000);
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]);
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]);
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]);
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]);
// alloc virtual mappings
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16);
if( memLUT == NULL )
throw std::bad_alloc();
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]);
memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000);
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]);
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]);
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]);
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]);
// map to other modes
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]);
if (psxInit() == -1)
goto eCleanupAndExit;
// map to other modes
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
return 0;
if(psxInit() == -1)
throw std::bad_alloc( "IOP memory allocations failed" );
eCleanupAndExit:
if( pExtraMem != NULL )
VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE);
memShutdown();
return 0;
}
catch( vm_alloc_failed_exception& ex )
{
Console::Error( "Virtual Memory Error > Cannot reserve %dk memory block at 0x%8.8x",
ex.requested_size / 1024, ex.requested_addr );
Console::Error( "\tError code: %d \tReturned address: 0x%8.8x",
GetLastError(), ex.returned_addr);
memShutdown();
}
catch( std::exception& )
{
memShutdown();
}
return -1;
}
@ -234,31 +261,34 @@ void memShutdown()
VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE);
PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_FREE(PS2MEM_ROM, 0x00400000);
VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000);
VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000);
VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000);
SysMunmap(PS2MEM_ROM, 0x00400000);
SysMunmap(PS2MEM_ROM1, 0x00080000);
SysMunmap(PS2MEM_ROM2, 0x00080000);
SysMunmap(PS2MEM_EROM, 0x001C0000);
PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_FREE(PS2MEM_PSX, 0x00200000, s_psxM);
PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
SysMunmap(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000);
//VIRTUAL_FREE(PS2MEM_PSXHW2, 0x00010000);
VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000);
VIRTUAL_FREE(PS2MEM_GS, 0x00010000);
VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000);
VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000);
VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000);
SysMunmap(PS2MEM_PSXHW, 0x00010000);
//SysMunmap(PS2MEM_PSXHW2, 0x00010000);
SysMunmap(PS2MEM_PSXHW4, 0x00010000);
SysMunmap(PS2MEM_GS, 0x00010000);
SysMunmap(PS2MEM_DEV9, 0x00010000);
SysMunmap(PS2MEM_SPU2, 0x00010000);
SysMunmap(PS2MEM_SPU2_, 0x00010000);
VIRTUAL_FREE(PS2MEM_B80, 0x00010000);
VIRTUAL_FREE(PS2MEM_BA0, 0x00010000);
SysMunmap(PS2MEM_B80, 0x00010000);
SysMunmap(PS2MEM_BA0, 0x00010000);
// Special Addrs.. ?
SysMunmap(PS2MEM_BASE+0x5fff0000, 0x10000);
VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE);
_aligned_free(memLUT); memLUT = NULL;
safe_aligned_free( memLUT );
// reserve mem
VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS);
@ -386,7 +416,7 @@ int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps)
if( SysMapUserPhysicalPages((void*)curvaddr, 1, pmap->aPFNs, 0) )
return EXCEPTION_CONTINUE_EXECUTION;
SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n",
Console::Error("Virtual Memory Error > page 0x%x cannot be found %d (p:%x,v:%x)\n",
addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], curvaddr);
}
}
@ -2438,6 +2468,7 @@ int __fastcall vuMicroRead8(u32 addr,mem8_t* data)
*data=vu->Micro[addr];
return 0;
}
template<int vunum>
int __fastcall vuMicroRead16(u32 addr,mem16_t* data)
{
@ -2447,6 +2478,7 @@ int __fastcall vuMicroRead16(u32 addr,mem16_t* data)
*data=*(u16*)&vu->Micro[addr];
return 0;
}
template<int vunum>
int __fastcall vuMicroRead32(u32 addr,mem32_t* data)
{
@ -2456,6 +2488,7 @@ int __fastcall vuMicroRead32(u32 addr,mem32_t* data)
*data=*(u32*)&vu->Micro[addr];
return 0;
}
template<int vunum>
int __fastcall vuMicroRead64(u32 addr,mem64_t* data)
{
@ -2465,6 +2498,7 @@ int __fastcall vuMicroRead64(u32 addr,mem64_t* data)
*data=*(u64*)&vu->Micro[addr];
return 0;
}
template<int vunum>
int __fastcall vuMicroRead128(u32 addr,mem128_t* data)
{
@ -2475,6 +2509,7 @@ int __fastcall vuMicroRead128(u32 addr,mem128_t* data)
data[1]=*(u64*)&vu->Micro[addr+8];
return 0;
}
template<int vunum>
void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
{
@ -2491,6 +2526,7 @@ void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
Cpu->ClearVU1(addr&(~7),1);
}
}
template<int vunum>
void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
{
@ -2507,6 +2543,7 @@ void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
Cpu->ClearVU1(addr&(~7),1);
}
}
template<int vunum>
void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
{
@ -2523,6 +2560,7 @@ void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
Cpu->ClearVU1(addr&(~7),1);
}
}
template<int vunum>
void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
{
@ -2539,6 +2577,7 @@ void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
Cpu->ClearVU1(addr,1);
}
}
template<int vunum>
void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
{
@ -2556,6 +2595,7 @@ void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
Cpu->ClearVU1(addr,2);
}
}
int memInit()
{
if (!vtlb_Init())
@ -2698,6 +2738,7 @@ int memReset() {
memset(PS2MEM_BASE, 0, 0x02000000);
memset(PS2MEM_SCRATCH, 0, 0x00004000);
#else
vtlb_Reset();
memset(psM, 0, 0x02000000);
memset(psS, 0, 0x00004000);
#endif
@ -2705,7 +2746,7 @@ int memReset() {
CombinePaths( Bios, Config.BiosDir, Config.Bios );
if (stat(Bios, &buf) == -1) {
SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios);
Console::Error(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios);
return 0;
}
@ -2731,7 +2772,7 @@ int memReset() {
fclose(fp);
BiosVersion = GetBiosVersion();
SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff);
Console::Notice("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff);
//injectIRX("host.irx"); //not fully tested; still buggy
@ -2784,6 +2825,7 @@ int mmap_GetRamPageInfo(void* ptr)
offset>>=12;
return (psMPWC[(offset/32)]&(1<<(offset&31)))?1:0;
}
void mmap_MarkCountedRamPage(void* ptr,u32 vaddr)
{
#ifdef _WIN32
@ -2805,7 +2847,7 @@ void mmap_MarkCountedRamPage(void* ptr,u32 vaddr)
}
void mmap_ResetBlockTracking()
{
SysPrintf("vtlb/mmap: Block Tracking reseted ..\n");
Console::WriteLn("vtlb/mmap: Block Tracking reseted ..");
memset(psMPWC,0,sizeof(psMPWC));
for(u32 i=0;i<(0x02000000>>12);i++)
{
@ -2822,16 +2864,16 @@ void mmap_ResetBlockTracking()
#ifdef _WIN32
int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps)
{
struct _EXCEPTION_RECORD* ExceptionRecord = eps->ExceptionRecord;
struct _CONTEXT* ContextRecord = eps->ContextRecord;
const _EXCEPTION_RECORD& ExceptionRecord = *eps->ExceptionRecord;
//const _CONTEXT& ContextRecord = *eps->ContextRecord;
if (eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
if (ExceptionRecord.ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
{
return EXCEPTION_CONTINUE_SEARCH;
}
// get bad virtual address
u32 offset = (u8*)eps->ExceptionRecord->ExceptionInformation[1]-psM;
u32 offset = (u8*)ExceptionRecord.ExceptionInformation[1]-psM;
if (offset>=0x02000000)
return EXCEPTION_CONTINUE_SEARCH;

View File

@ -45,11 +45,6 @@
#include "Paths.h"
u32 dwCurSaveStateVer = 0;
extern u32 s_iLastCOP0Cycle;
extern u32 s_iLastPERFCycle[2];
extern int g_psxWriteOk;
PcsxConfig Config;
u32 BiosVersion;
char CdromId[12];
@ -318,7 +313,7 @@ int GetPS2ElfName(char *name){
// check if the file exists
if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){
SysPrintf("SYSTEM.CNF not found\n");
Console::Error("Boot Error > SYSTEM.CNF not found");
return 0;//could not find; not a PS/PS2 cdvd
}
@ -327,16 +322,12 @@ int GetPS2ElfName(char *name){
CDVDFS_close(f);
buffer[tocEntry.fileSize]='\0';
// SysPrintf(
// "---------------------SYSTEM.CNF---------------------\n"
// "%s"
// "----------------------------------------------------\n", buffer);
pos=strstr(buffer, "BOOT2");
if (pos==NULL){
pos=strstr(buffer, "BOOT");
if (pos==NULL) {
SysPrintf("This is not a PS2 game!\n");
Console::Error("Boot Error > This is not a PS2 game!");
return 0;
}
return 1;
@ -359,7 +350,7 @@ int GetPS2ElfName(char *name){
if (fp) {
u32 addr;
SysPrintf("Loading System.map\n", fp);
Console::WriteLn("Loading System.map...");
while (!feof(fp)) {
fseek(fp, 8, SEEK_CUR);
buffer[0] = '0'; buffer[1] = 'x';
@ -381,370 +372,78 @@ int GetPS2ElfName(char *name){
return 2;
}
// STATES
#define STATE_VERSION "STv6"
const char Pcsx2Header[32] = STATE_VERSION " PCSX2 " PCSX2_VERSION;
#define _PS2Esave(type) \
if (type##freeze(FREEZE_SIZE, &fP) == -1) { \
gzclose(f); \
return -1; \
} \
fP.data = (s8*)malloc(fP.size); \
if (fP.data == NULL) return -1; \
\
if (type##freeze(FREEZE_SAVE, &fP) == -1) { \
gzclose(f); \
return -1; \
} \
\
gzwrite(f, &fP.size, sizeof(fP.size)); \
if (fP.size) { \
gzwrite(f, fP.data, fP.size); \
free(fP.data); \
}
#define _PS2Eload(type) \
gzread(f, &fP.size, sizeof(fP.size)); \
if (fP.size) { \
fP.data = (s8*)malloc(fP.size); \
if (fP.data == NULL) return -1; \
gzread(f, fP.data, fP.size); \
} \
if (type##freeze(FREEZE_LOAD, &fP) == -1) { \
/* skip */ \
/*if (fP.size) free(fP.data); \
gzclose(f); \
return -1;*/ \
} \
if (fP.size) free(fP.data);
int SaveState(const char *file) {
gzFile f;
freezeData fP;
gsWaitGS();
SysPrintf("SaveState: %s\n", file);
f = gzopen(file, "wb");
if (f == NULL) return -1;
gzwrite(f, &g_SaveVersion, 4);
gzwrite(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory
gzwrite(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory
gzwrite(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory
gzwrite(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad
gzwrite(f, PS2MEM_HW, 0x00010000); // hardware memory
gzwrite(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0
gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs]
gzwrite(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs
gzwrite(f, (void*)&tlb, sizeof(tlb)); // tlbs
gzwrite(f, &EEsCycle, sizeof(EEsCycle));
gzwrite(f, &EEoCycle, sizeof(EEoCycle));
gzwrite(f, &psxRegs.cycle, sizeof(u32)); // used to be IOPoCycle. This retains compatibility.
gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle));
gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle));
gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle));
gzwrite(f, s_iLastPERFCycle, sizeof(u32)*2);
gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk));
//hope didn't forgot any cpu....
rcntFreeze(f, 1);
gsFreeze(f, 1);
vu0Freeze(f, 1);
vu1Freeze(f, 1);
vif0Freeze(f, 1);
vif1Freeze(f, 1);
sifFreeze(f, 1);
ipuFreeze(f, 1);
// iop now
gzwrite(f, psxM, 0x00200000); // 2 MB main memory
//gzwrite(f, psxP, 0x00010000); // pralell memory
gzwrite(f, psxH, 0x00010000); // hardware memory
//gzwrite(f, psxS, 0x00010000); // sif memory
sioFreeze(f, 1);
cdrFreeze(f, 1);
cdvdFreeze(f, 1);
psxRcntFreeze(f, 1);
//mdecFreeze(f, 1);
sio2Freeze(f, 1);
SysPrintf("Saving GS\n");
if( CHECK_MULTIGS ) {
// have to call in thread, otherwise weird stuff will start happening
u64 uf = (uptr)f;
GSRingBufSimplePacket(GS_RINGTYPE_SAVE, (u32)(uf&0xffffffff), (u32)(uf>>32), 0);
gsWaitGS();
}
else {
_PS2Esave(GS);
}
SysPrintf("Saving SPU2\n");
_PS2Esave(SPU2);
SysPrintf("Saving DEV9\n");
_PS2Esave(DEV9);
SysPrintf("Saving USB\n");
_PS2Esave(USB);
SysPrintf("Saving ok\n");
gzclose(f);
return 0;
}
extern u32 dumplog;
u32 s_vucount=0;
int LoadState(const char *file) {
gzFile f;
freezeData fP;
int i;
u32 dud; // for loading unused vars.
#ifdef PCSX2_VIRTUAL_MEM
DWORD OldProtect;
#endif
#ifdef _DEBUG
s_vucount = 0;
#endif
SysPrintf("LoadState: %s\n", file);
f = gzopen(file, "rb");
if (f == NULL) return -1;
gzread(f, &dwCurSaveStateVer, 4);
if( dwCurSaveStateVer != g_SaveVersion ) {
#ifdef PCSX2_VIRTUAL_MEM
if( dwCurSaveStateVer >= 0x8b400000 )
{
gzclose(f);
SysPrintf(
"Savestate load aborted:\n"
" VM edition cannot safely load savestates created by the VTLB edition.\n" );
return 0;
}
// pcsx2 vm supports opening these formats
if( dwCurSaveStateVer < 0x7a30000d) {
gzclose(f);
SysPrintf("Unsupported savestate version: %x.\n", dwCurSaveStateVer );
return 0;
}
#else
gzclose(f);
SysPrintf(
"Savestate load aborted:\n"
" VTLB edition cannot safely load savestates created by the VM edition.\n" );
return 0;
#endif
}
// stop and reset the system first
gsWaitGS();
for (i=0; i<48; i++) UnmapTLB(i);
Cpu->Reset();
recResetVU0();
recResetVU1();
psxCpu->Reset();
SysPrintf("Loading memory\n");
#ifdef PCSX2_VIRTUAL_MEM
// make sure can write
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect);
#endif
gzread(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory
gzread(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory
gzread(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory
gzread(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad
#ifdef PCSX2_VIRTUAL_MEM
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect);
#endif
gzread(f, PS2MEM_HW, 0x00010000); // hardware memory
SysPrintf("Loading structs\n");
gzread(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0
gzread(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs
gzread(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs
gzread(f, (void*)&tlb, sizeof(tlb)); // tlbs
gzread(f, &EEsCycle, sizeof(EEsCycle));
gzread(f, &EEoCycle, sizeof(EEoCycle));
gzread(f, &dud, sizeof(u32)); // was IOPoCycle
gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle));
gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle));
gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle));
if( dwCurSaveStateVer >= 0x7a30000e ) {
gzread(f, s_iLastPERFCycle, sizeof(u32)*2);
}
gzread(f, &g_psxWriteOk, sizeof(g_psxWriteOk));
rcntFreeze(f, 0);
gsFreeze(f, 0);
vu0Freeze(f, 0);
vu1Freeze(f, 0);
vif0Freeze(f, 0);
vif1Freeze(f, 0);
sifFreeze(f, 0);
ipuFreeze(f, 0);
// iop now
SysPrintf("Loading iop mem\n");
gzread(f, psxM, 0x00200000); // 2 MB main memory
//gzread(f, psxP, 0x00010000); // pralell memory
gzread(f, psxH, 0x00010000); // hardware memory
//gzread(f, psxS, 0x00010000); // sif memory
SysPrintf("Loading iop stuff\n");
sioFreeze(f, 0);
cdrFreeze(f, 0);
cdvdFreeze(f, 0);
psxRcntFreeze(f, 0);
//mdecFreeze(f, 0);
sio2Freeze(f, 0);
SysPrintf("Loading GS\n");
if( CHECK_MULTIGS ) {
// have to call in thread, otherwise weird stuff will start happening
u64 uf = (uptr)f;
GSRingBufSimplePacket(GS_RINGTYPE_LOAD, (u32)(uf&0xffffffff), (u32)(uf>>32), 0);
gsWaitGS();
}
else {
_PS2Eload(GS);
}
SysPrintf("Loading SPU2\n");
_PS2Eload(SPU2);
SysPrintf("Loading DEV9\n");
_PS2Eload(DEV9);
SysPrintf("Loading USB\n");
_PS2Eload(USB);
SysPrintf("Loading ok\n");
gzclose(f);
memset(pCache,0,sizeof(_cacheS)*64);
//dumplog |= 4;
WriteCP0Status(cpuRegs.CP0.n.Status.val);
for (i=0; i<48; i++) MapTLB(i);
return 0;
}
#ifdef PCSX2_DEVBUILD
int SaveGSState(const char *file)
void SaveGSState(const char *file)
{
if( g_SaveGSStream ) return -1;
if( g_SaveGSStream ) return;
SysPrintf("SaveGSState: %s\n", file);
g_fGSSave = gzopen(file, "wb");
if (g_fGSSave == NULL) return -1;
Console::Write( "SaveGSState: " ); Console::WriteLn( file );
g_fGSSave = new gzSavingState( file );
g_SaveGSStream = 1;
g_nLeftGSFrames = 2;
gzwrite(g_fGSSave, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames));
return 0;
g_fGSSave->Freeze( g_nLeftGSFrames );
}
extern uptr pDsp;
int LoadGSState(const char *file)
void LoadGSState(const char *file)
{
int ret;
gzFile f;
freezeData fP;
gzLoadingState* f;
f = gzopen(file, "rb");
if( f == NULL )
Console::Write( "LoadGSState: " );
try
{
f = new gzLoadingState( file );
Console::WriteLn( file );
}
catch( Exception::FileNotFound& )
{
// file not found? try prefixing with sstates folder:
if( !isPathRooted( file ) )
{
// file not found? try prefixing with sstates folder:
char strfile[g_MaxPath];
CombinePaths( strfile, SSTATES_DIR, file );
f = gzopen(strfile, "rb");
file = strfile;
f = new gzLoadingState( file );
Console::WriteLn( strfile );
// If this load attempt fails, then let the exception bubble up to
// the caller to deal with...
}
}
if( f == NULL ) {
SysPrintf("Failed to find gs state\n");
return -1;
}
SysPrintf("LoadGSState: %s\n", file);
// Always set gsIrq callback -- GS States are always exclusionary of MTGS mode
GSirqCallback( gsIrq );
ret = GSopen(&pDsp, "PCSX2", 0);
if (ret != 0) {
SysMessage (_("Error Opening GS Plugin"));
return -1;
if (ret != 0)
{
delete f;
throw Exception::PluginFailure( "GS", "Error opening" );
}
ret = PAD1open((void *)&pDsp);
gzread(f, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames));
f->Freeze(g_nLeftGSFrames);
f->gsFreeze();
gsFreeze(f, 0);
_PS2Eload(GS);
f->FreezePlugin( "GS", GSfreeze );
RunGSState(f);
gzclose(f);
RunGSState( *f );
delete( f );
GSclose();
PAD1close();
return 0;
}
#endif
int CheckState(const char *file) {
gzFile f;
char header[32];
f = gzopen(file, "rb");
if (f == NULL) return -1;
gzread(f, header, 32);
gzclose(f);
if (strncmp(STATE_VERSION " PCSX2", header, 10)) return -1;
return 0;
}
struct LangDef {
char id[8];
char name[64];
@ -805,13 +504,6 @@ char* mystrlwr( char* string )
return string;
}
static void GetSaveStateFilename( char* dest )
{
char elfcrcText[72];
sprintf( elfcrcText, "%8.8X.%3.3d", ElfCRC, StatesC );
CombinePaths( dest, SSTATES_DIR, elfcrcText );
}
static void GetGSStateFilename( char* dest )
{
char gsText[72];
@ -821,31 +513,76 @@ static void GetGSStateFilename( char* dest )
void ProcessFKeys(int fkey, int shift)
{
int ret;
char Text[g_MaxPath];
assert(fkey >= 1 && fkey <= 12 );
switch(fkey) {
case 1:
GetSaveStateFilename(Text);
ret = SaveState(Text);
try
{
SaveState::GetFilename( Text, StatesC );
gzSavingState(Text).FreezeAll();
}
catch( std::exception& ex )
{
// 99% of the time this is a file permission error and the
// cpu state is intact so just display a passive msg to console.
Console::Error( _( "Error > Could not save state to slot %d" ), StatesC );
Console::Error( ex.what() );
}
break;
case 2:
if( shift )
StatesC = (StatesC+NUM_STATES-1)%NUM_STATES;
StatesC = (StatesC+NUM_STATES-1) % NUM_STATES;
else
StatesC = (StatesC+1)%NUM_STATES;
SysPrintf("*PCSX2*: Selected State %ld\n", StatesC);
StatesC = (StatesC+1) % NUM_STATES;
Console::Notice( _( " > Selected savestate slot %d" ), StatesC+1);
if( GSchangeSaveState != NULL ) {
GetSaveStateFilename(Text);
SaveState::GetFilename(Text, StatesC);
GSchangeSaveState(StatesC, Text);
}
break;
case 3:
GetSaveStateFilename(Text);
ret = LoadState(Text);
break;
try
{
SaveState::GetFilename( Text, StatesC );
gzLoadingState joe(Text); // throws exception on version mismatch
cpuReset();
joe.FreezeAll();
}
catch( Exception::UnsupportedStateVersion& )
{
// At this point the cpu hasn't been reset, so we can return
// control to the user safely...
}
catch( Exception::FileNotFound& )
{
Console::Notice( _("Saveslot %d cannot be loaded; slot does not exist (file not found)"), StatesC );
}
catch( std::runtime_error& ex )
{
// This is the bad one. Chances are the cpu has been reset, so emulation has
// to be aborted. Sorry user! We'll give you some info for your trouble:
Console::Error( _("An error occured while trying to load saveslot %d"), StatesC );
Console::Error( ex.what() );
SysMessage(
"Pcsx2 encountered an error while trying to load the savestate\n"
"and emulation had to be aborted." );
cpuShutdown();
ClosePlugins();
throw Exception::CpuStateShutdown(
"Saveslot load failed; PS2 emulated state had to be shut down." ); // let the GUI handle the error "gracefully"
}
break;
case 4:
{
@ -875,7 +612,7 @@ void ProcessFKeys(int fkey, int shift)
if( GSsetFrameSkip == NULL )
{
newOptions &= ~PCSX2_FRAMELIMIT_MASK;
SysPrintf("Notice: GS Plugin does not support frameskipping.\n");
Console::Notice("Notice: GS Plugin does not support frameskipping.");
limitMsg = "None/Normal";
}
else
@ -890,7 +627,7 @@ void ProcessFKeys(int fkey, int shift)
}
AtomicExchange( Config.Options, newOptions );
SysPrintf("Frame Limit Mode Changed: %s\n", limitMsg );
Console::Notice("Frame Limit Mode Changed: %s", limitMsg );
// [Air]: Do we really want to save runtime changes to frameskipping?
//SaveConfig();
@ -924,7 +661,7 @@ void ProcessFKeys(int fkey, int shift)
case 11:
if( CHECK_MULTIGS ) {
SysPrintf("Cannot make gsstates in MTGS mode\n");
Console::Notice( "Cannot make gsstates in MTGS mode" );
}
else {
if( strgametitle[0] != 0 ) {
@ -952,7 +689,7 @@ void ProcessFKeys(int fkey, int shift)
if( shift ) {
#ifdef PCSX2_DEVBUILD
iDumpRegisters(cpuRegs.pc, 0);
SysPrintf("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc);
Console::Notice("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc);
#endif
}
else {
@ -1035,6 +772,37 @@ void injectIRX(const char *filename){
rd[i].extInfoSize=0;
}
MemoryAlloc::MemoryAlloc() :
m_ptr( NULL )
, m_alloc( 0 )
, ChunkSize( DefaultChunkSize )
{
}
MemoryAlloc::MemoryAlloc( int initialSize ) :
m_ptr( (u8*)malloc( initialSize ) )
, m_alloc( initialSize )
, ChunkSize( DefaultChunkSize )
{
if( m_ptr == NULL )
throw std::bad_alloc();
}
MemoryAlloc::~MemoryAlloc()
{
safe_free( m_ptr );
}
void MemoryAlloc::MakeRoomFor( int blockSize )
{
if( blockSize > m_alloc )
{
m_alloc += blockSize + ChunkSize;
m_ptr = (u8*)realloc( m_ptr, m_alloc );
}
}
// [TODO] I'd like to move the following functions to their own module eventually.
// It might even be a good idea to just go ahead and move them into Win32/Linux
// specific files since they're all #ifdef'd that way anyways.

View File

@ -30,6 +30,7 @@
#endif
#include "PS2Etypes.h"
#include "System.h"
// compile-time assert
#ifndef C_ASSERT
@ -180,29 +181,10 @@ int GetPS2ElfName(char*);
extern const char *LabelAuthors;
extern const char *LabelGreets;
// --->> Savestate stuff [PathUtil.c]
#include "SaveState.h"
// Savestate Versioning!
// If you make changes to the savestate version, please increment the value below.
#ifdef PCSX2_VIRTUAL_MEM
static const u32 g_SaveVersion = 0x7a300010;
#else
static const u32 g_SaveVersion = 0x8b400000;
#endif
int SaveState(const char *file);
int LoadState(const char *file);
int CheckState(const char *file);
int SaveGSState(const char *file);
int LoadGSState(const char *file);
#define gzfreeze(ptr, size) \
if (Mode == 1) gzwrite(f, ptr, size); \
else if (Mode == 0) gzread(f, ptr, size);
#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr))
void SaveGSState(const char *file);
void LoadGSState(const char *file);
// <<--- End Savestate Stuff

View File

@ -51,7 +51,6 @@ u32 LastType = 0;
int g_ZeroGSOptions=0;
int patchnumber;
extern int RunExe;
char strgametitle[256]= {0};
@ -383,10 +382,7 @@ void patchFunc_patch( char * cmd, char * param )
pText = strtok( param, "," );
pText = param;
if(RunExe == 1)
patch[ patchnumber ].placetopatch = 1;
else
patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 );
patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 );
pText = strtok( NULL, "," );
inifile_trim( pText );
@ -551,10 +547,7 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data)
return -1;
}
if(RunExe == 1)
patch[patchnumber].placetopatch = 1;
else
patch[patchnumber].placetopatch = Mode;
patch[patchnumber].placetopatch = Mode;
patch[patchnumber].cpu = (patch_cpu_type)Place;
patch[patchnumber].addr=Address;

View File

@ -571,7 +571,23 @@ int LoadFWplugin(char *filename) {
return 0;
}
static int loadp=0;
struct PluginOpenStatusFlags
{
u8 GS : 1
, CDVD : 1
, DEV9 : 1
, USB : 1
, SPU2 : 1
, PAD1 : 1
, PAD2 : 1
, FW : 1;
};
static PluginOpenStatusFlags OpenStatus = {0};
static bool loadp=false;
int InitPlugins() {
int ret;
@ -606,7 +622,18 @@ int InitPlugins() {
return 0;
}
void ShutdownPlugins() {
void ShutdownPlugins()
{
// GS is a special case: It needs closed first usually.
// (the GS isn't closed during emulation pauses)
if( OpenStatus.GS )
{
gsClose();
OpenStatus.GS = false;
}
ClosePlugins();
GSshutdown();
PAD1shutdown();
PAD2shutdown();
@ -618,9 +645,10 @@ void ShutdownPlugins() {
}
int LoadPlugins() {
if( loadp ) return 0;
char Plugin[g_MaxPath];
CombinePaths( Plugin, Config.PluginsDir, Config.GS );
if (LoadGSplugin(Plugin) == -1) return -1;
@ -648,7 +676,7 @@ int LoadPlugins() {
if( g_Error_PathTooLong ) return -1;
if (InitPlugins() == -1) return -1;
loadp=1;
loadp=true;
return 0;
}
@ -658,26 +686,11 @@ extern void spu2DMA4Irq();
extern void spu2DMA7Irq();
extern void spu2Irq();
struct PluginOpenStatusFlags
{
u8 GS : 1
, CDVD : 1
, DEV9 : 1
, USB : 1
, SPU2 : 1
, PAD1 : 1
, PAD2 : 1
, FW : 1;
};
static PluginOpenStatusFlags OpenStatus;
int OpenPlugins(const char* pTitleFilename) {
GSdriverInfo info;
int ret;
if (loadp == 0) return -1;
if (!loadp) return -1;
#ifndef _WIN32
// change dir so that CDVD can find its config file
@ -776,13 +789,16 @@ OpenError:
#define CLOSE_PLUGIN( name ) \
if( OpenStatus.name ) { \
name##close(); \
OpenStatus.name = 0; \
OpenStatus.name = false; \
}
void ClosePlugins()
{
// GS plugin is special and is not closed during emulation pauses.
// (that's because the GS is the most complicated plugin and to close it would
// require we save the GS state -- plus, Gsdx doesn't really support being
// closed)
if( OpenStatus.GS )
gsWaitGS();
@ -796,15 +812,17 @@ void ClosePlugins()
CLOSE_PLUGIN( PAD2 );
}
void ResetPlugins() {
void ResetPlugins()
{
gsWaitGS();
ShutdownPlugins();
InitPlugins();
}
void ReleasePlugins() {
if (loadp == 0) return;
void ReleasePlugins()
{
if (!loadp) return;
if (GSplugin == NULL || PAD1plugin == NULL || PAD2plugin == NULL ||
SPU2plugin == NULL || CDVDplugin == NULL || DEV9plugin == NULL ||
@ -820,5 +838,5 @@ void ReleasePlugins() {
SysCloseLibrary(DEV9plugin); DEV9plugin = NULL;
SysCloseLibrary(USBplugin); USBplugin = NULL;
SysCloseLibrary(FWplugin); FWplugin = NULL;
loadp=0;
loadp = false;
}

View File

@ -23,10 +23,19 @@
#define PLUGINfuncs
#include "PS2Edefs.h"
// Loads plugins as specified in the Config global.
int LoadPlugins();
// Unloads all plugin DLLs. To change plugins, call ReleasePlugins followed by
// changes to Config.Plugins filenames, and then call LoadPlugins.
void ReleasePlugins();
int OpenPlugins(const char* pTitleFilename);
void ClosePlugins();
// Completely shuts down all plugins and re-initializes them. (clean slate)
// Plugins are not unloaded, so changes to Config.Plugins values will not
// take effect. Use a manual set oc alls to ReleasePlugins and LoadPlugins for that.
void ResetPlugins();
#endif /* __PLUGINS_H__ */

View File

@ -252,23 +252,18 @@ _start:
memcpy((char*)PSXM(sp), save, 4*4);
SysPrintf( "%s", tmp);
Console::Msg( Color_Cyan, "%s", tmp);
pc0 = ra;
}
void bios_putchar () { // 3d
char tmp[12];
sprintf (tmp,"%c",(char)a0);
SysPrintf(tmp);
Console::Msg( Color_Cyan, "%c", a0 );
pc0 = ra;
}
void bios_puts () { // 3e/3f
SysPrintf(Ra0);
Console::Msg( Color_Cyan, Ra0 );
pc0 = ra;
}

View File

@ -707,11 +707,10 @@ u64 psxRcntCycles(int index)
return (u64)(psxCounters[index].count + (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate));
}
extern u32 dwCurSaveStateVer;
int psxRcntFreeze(gzFile f, int Mode)
void SaveState::psxRcntFreeze()
{
#ifdef PCSX2_VIRTUAL_MEM
if( Mode == 0 && (dwCurSaveStateVer < 0x7a300010) )
if( IsLoading() && (m_version < 0x7a300010) )
{
// --- Reading Mode, Old Version ---
// struct used to be 32bit count and target
@ -719,18 +718,18 @@ int psxRcntFreeze(gzFile f, int Mode)
u32 val;
for(i = 0; i < ARRAYSIZE(psxCounters); ++i)
{
gzfreeze(&val,4); psxCounters[i].count = val;
gzfreeze(&val,4); psxCounters[i].mode = val;
gzfreeze(&val,4); psxCounters[i].target = val;
gzfreeze((u8*)&psxCounters[i].rate, sizeof(psxCounters[i])-20);
Freeze(val); psxCounters[i].count = val;
Freeze(val); psxCounters[i].mode = val;
Freeze(val); psxCounters[i].target = val;
FreezeMem((u8*)&psxCounters[i].rate, sizeof(psxCounters[i])-20);
}
}
else
{
gzfreezel(psxCounters);
Freeze(psxCounters);
}
if( Mode == 0 && (dwCurSaveStateVer <= 0x7a300010) )
if( IsLoading() && (m_version <= 0x7a300010) )
{
// This is needed to make old save states compatible.
psxCounters[6].rate = 768*12;
@ -754,10 +753,10 @@ int psxRcntFreeze(gzFile f, int Mode)
}
#else
gzfreezel(psxCounters);
gzfreeze(&psxNextCounter, sizeof(psxNextCounter));
gzfreeze(&psxNextsCounter, sizeof(psxNextsCounter));
#endif
// vTLB's new savestate version! :D
return 0;
Freeze(psxCounters);
Freeze(psxNextCounter);
Freeze(psxNextsCounter);
#endif
}

View File

@ -51,7 +51,6 @@ void psxRcntWtarget32(int index, u32 value);
u16 psxRcntRcount16(int index);
u32 psxRcntRcount32(int index);
u64 psxRcntCycles(int index);
int psxRcntFreeze(gzFile f, int Mode);
void psxVBlankStart();
void psxVBlankEnd();

View File

@ -271,15 +271,15 @@ void zeroEx()
}
if (!strncmp(lib, "loadcore", 8) && code == 6) {
DevCon::FormatLn("loadcore RegisterLibraryEntries (%x): %8.8s", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12));
DevCon::MsgLn("loadcore RegisterLibraryEntries (%x): %8.8s", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12));
}
if (!strncmp(lib, "intrman", 7) && code == 4) {
DevCon::FormatLn("intrman RegisterIntrHandler (%x): intr %s, handler %x", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2);
DevCon::MsgLn("intrman RegisterIntrHandler (%x): intr %s, handler %x", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2);
}
if (!strncmp(lib, "sifcmd", 6) && code == 17) {
DevCon::FormatLn("sifcmd sceSifRegisterRpc (%x): rpc_id %x", psxRegs.pc, psxRegs.GPR.n.a1);
DevCon::MsgLn("sifcmd sceSifRegisterRpc (%x): rpc_id %x", psxRegs.pc, psxRegs.GPR.n.a1);
}
if (!strncmp(lib, "sysclib", 8))

View File

@ -429,12 +429,13 @@ void psxMemReset() {
void psxMemShutdown()
{
SysMunmap((uptr)psxM, 0x00200000); psxM = NULL;
SysMunmap((uptr)psxP, 0x00010000); psxP = NULL;
SysMunmap((uptr)psxH, 0x00010000); psxH = NULL;
SysMunmap((uptr)psxS, 0x00010000); psxS = NULL;
_aligned_free(psxMemRLUT);
_aligned_free(psxMemWLUT);
SafeSysMunmap(psxM, 0x00200000);
SafeSysMunmap(psxP, 0x00010000);
SafeSysMunmap(psxH, 0x00010000);
SafeSysMunmap(psxS, 0x00010000);
safe_aligned_free(psxMemRLUT);
safe_aligned_free(psxMemWLUT);
}
u8 psxMemRead8(u32 mem) {

View File

@ -268,9 +268,7 @@ void psxDMA12Interrupt()
psxRegs.interrupt&= ~(1 << 12);
}
int sio2Freeze(gzFile f, int Mode) {
gzfreeze(&sio2, sizeof(sio2));
return 0;
void SaveState::sio2Freeze() {
Freeze(sio2);
}

View File

@ -94,7 +94,6 @@ void psxDma12(u32 madr, u32 bcr, u32 chcr);
void psxDMA11Interrupt();
void psxDMA12Interrupt();
int sio2Freeze(gzFile f, int Mode);
#endif /* __PSXSIO2_H__ */

View File

@ -273,14 +273,3 @@ void psxExecuteBios() {
*/
}
void psxRestartCPU()
{
psxCpu->Shutdown();
psxCpu = CHECK_EEREC ? &psxRec : &psxInt;
if (psxCpu->Init() == -1) {
SysClose();
exit(1);
}
psxCpu->Reset();
}

View File

@ -211,7 +211,6 @@ void psxShutdown();
void psxException(u32 code, u32 step);
void psxBranchTest();
void psxExecuteBios();
void psxRestartCPU();
extern s32 psxNextCounter;
extern u32 psxNextsCounter;

View File

@ -43,23 +43,36 @@ s32 EEsCycle; // used to sync the IOP to the EE
u32 EEoCycle;
u32 bExecBIOS = 0; // set if the BIOS has already been executed
int cpuInit()
static bool cpuIsInitialized = false;
#ifdef _DEBUG
extern u32 s_vucount;
#endif
bool cpuInit()
{
if( cpuIsInitialized ) return true;
cpuIsInitialized = true;
int ret;
SysPrintf("PCSX2 " PCSX2_VERSION " save ver: %x\n", g_SaveVersion);
SysPrintf("EE pc offset: 0x%x, PSX pc offset: 0x%x\n", (u32)&cpuRegs.pc - (u32)&cpuRegs, (u32)&psxRegs.pc - (u32)&psxRegs);
Console::Notice("PCSX2 " PCSX2_VERSION " save ver: %x", g_SaveVersion);
Console::Notice("EE pc offset: 0x%x, PSX pc offset: 0x%x", (u32)&cpuRegs.pc - (u32)&cpuRegs, (u32)&psxRegs.pc - (u32)&psxRegs);
cpuRegs.constzero = 0;
cpudetectInit();
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
Console::SetColor( Console::Color_White );
ret = Cpu->Init();
Console::ClearColor();
if (ret == -1 && CHECK_EEREC) {
SysMessage(_("Error initializing Recompiler, switching to Interpreter"));
Console::WriteLn(_("Error initializing Recompiler, switching to Interpreter"));
Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC);
Cpu = &intCpu;
ret = Cpu->Init();
if( ret == -1 ) return false;
}
#ifdef PCSX2_VIRTUAL_MEM
@ -77,7 +90,7 @@ int cpuInit()
memset(&si, 0, sizeof(si));
if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) {
_snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe);
_snprintf(strdir, ARRAYSIZE(strdir), "Failed to launch %s\n", strexe);
MessageBox(NULL, strdir, "Failure", MB_OK);
}
else {
@ -86,24 +99,33 @@ int cpuInit()
}
}
return -1;
return false;
}
#endif
if (hwInit() == -1) return -1;
if (vu0Init() == -1) return -1;
if (vu1Init() == -1) return -1;
if (hwInit() == -1) return false;
if (vu0Init() == -1) return false;
if (vu1Init() == -1) return false;
#ifndef PCSX2_VIRTUAL_MEM
if (memInit() == -1) return -1;
if (memInit() == -1) return false;
#endif
return ret;
return true;
}
int cpuReset()
bool cpuReset()
{
if( cpuIsInitialized )
{
for( int i=0; i<48; i++ )
UnmapTLB(i);
}
gsWaitGS(); // GS better be done before we reset the EE..
cpuInit();
Cpu->Reset();
if( !memReset() ) return 0;
if( !memReset() ) return false;
memset(&cpuRegs, 0, sizeof(cpuRegs));
memset(&fpuRegs, 0, sizeof(fpuRegs));
@ -128,12 +150,22 @@ int cpuReset()
rcntInit();
psxReset();
return 1;
#ifdef _DEBUG
s_vucount = 0;
#endif
return true;
}
void cpuShutdown()
{
gsShutdown(); // shut down the GS first because it's running a thread.
if( !cpuIsInitialized ) return;
gsWaitGS();
//gsShutdown(); // shut down the GS first because it's running a thread.
for( int i=0; i<48; i++ )
UnmapTLB(i);
hwShutdown();
// biosShutdown();
@ -144,6 +176,8 @@ void cpuShutdown()
disR5900FreeSyms();
Cpu->Shutdown();
cpuIsInitialized = false;
}
void cpuException(u32 code, u32 bd) {
@ -159,7 +193,7 @@ void cpuException(u32 code, u32 bd) {
if (cpuRegs.CP0.n.Status.b.EXL == 0) {
cpuRegs.CP0.n.Status.b.EXL = 1;
if (bd) {
SysPrintf("branch delay!!\n");
Console::Notice("branch delay!!");
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
cpuRegs.CP0.n.Cause |= 0x80000000;
} else {
@ -176,20 +210,20 @@ void cpuException(u32 code, u32 bd) {
cpuRegs.pc = 0xBFC00200 + offset;
}
} else { //Error Level 2
SysPrintf("FIX ME: Level 2 cpuException\n");
Console::Error("FIX ME: Level 2 cpuException");
if((code & 0x38000) <= 0x8000 ) { //Reset / NMI
cpuRegs.pc = 0xBFC00000;
SysPrintf("Reset request\n");
Console::Notice("Reset request");
UpdateCP0Status();
return;
} else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter
else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug
else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code);
else Console::Error("Unknown Level 2 Exception!! Cause %x", code);
if (cpuRegs.CP0.n.Status.b.EXL == 0) {
cpuRegs.CP0.n.Status.b.EXL = 1;
if (bd) {
SysPrintf("branch delay!!\n");
Console::Notice("branch delay!!");
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
cpuRegs.CP0.n.Cause |= 0x80000000;
} else {
@ -198,7 +232,7 @@ void cpuException(u32 code, u32 bd) {
}
} else {
offset = 0x180; //Overrride the cause
SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code);
Console::Notice("cpuException: Status.EXL = 1 cause %x", code);
}
if (cpuRegs.CP0.n.Status.b.DEV == 0) {
cpuRegs.pc = 0x80000000 + offset;
@ -614,22 +648,10 @@ void cpuExecuteBios()
if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC;
else Config.Options &= ~PCSX2_COP2REC;
// remove frame skipping if GS doesn't support it
switch(CHECK_FRAMELIMIT) {
case PCSX2_FRAMELIMIT_SKIP:
case PCSX2_FRAMELIMIT_VUSKIP:
if( GSsetFrameSkip == NULL )
{
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
SysPrintf("Notice: Disabling frameskip -- GS plugin does not support it.\n");
}
break;
}
// Set the video mode to user's default request:
gsSetVideoRegionType( Config.PsxType & 1 );
SysPrintf("* PCSX2 *: ExecuteBios\n");
Console::Notice( "* PCSX2 *: ExecuteBios" );
bExecBIOS = TRUE;
while (cpuRegs.pc != 0x00200008 &&
@ -655,26 +677,10 @@ void cpuExecuteBios()
// REC_CLEARM(cpuRegs.pc);
if( CHECK_EEREC ) Cpu->Reset();
SysPrintf("* PCSX2 *: ExecuteBios Complete\n");
Console::Notice("* PCSX2 *: ExecuteBios Complete");
GSprintf(5, "PCSX2 " PCSX2_VERSION "\nExecuteBios Complete\n");
}
void cpuRestartCPU()
{
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
// restart vus
if (Cpu->Init() == -1) {
SysClose();
exit(1);
}
vu0Init();
vu1Init();
Cpu->Reset();
psxRestartCPU();
}
// for interpreter only
void IntcpuBranchTest()
{

View File

@ -225,8 +225,8 @@ extern PCSX2_ALIGNED16_DECL(tlbs tlb[48]);
#endif
int cpuInit();
int cpuReset();
bool cpuInit();
bool cpuReset();
void cpuShutdown();
void cpuException(u32 code, u32 bd);
void cpuTlbMissR(u32 addr, u32 bd);
@ -238,7 +238,6 @@ extern void cpuTestINTCInts();
extern void cpuTestDMACInts();
extern void cpuTestTIMRInts();
void cpuExecuteBios();
void cpuRestartCPU();
u32 VirtualToPhysicalR(u32 addr);
u32 VirtualToPhysicalW(u32 addr);

356
pcsx2/SaveState.cpp Normal file
View File

@ -0,0 +1,356 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Common.h"
#include "PsxCommon.h"
#include "CDVDisodrv.h"
#include "VUmicro.h"
#include "VU.h"
#include "iCore.h"
#include "iVUzerorec.h"
#include "GS.h"
#include "COP0.h"
#include "Cache.h"
#include "Paths.h"
extern u32 s_iLastCOP0Cycle;
extern u32 s_iLastPERFCycle[2];
extern int g_psxWriteOk;
// STATES
static void PreLoadPrep()
{
#ifdef PCSX2_VIRTUAL_MEM
DWORD OldProtect;
// make sure can write
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect);
#endif
}
static void PostLoadPrep()
{
#ifdef PCSX2_VIRTUAL_MEM
DWORD OldProtect;
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect);
#endif
memset(pCache,0,sizeof(_cacheS)*64);
WriteCP0Status(cpuRegs.CP0.n.Status.val);
for(int i=0; i<48; i++) MapTLB(i);
}
void SaveState::GetFilename( char* dest, int slot )
{
char elfcrcText[72];
sprintf( elfcrcText, "%8.8X.%3.3d", ElfCRC, slot );
CombinePaths( dest, SSTATES_DIR, elfcrcText );
}
SaveState::SaveState( const char* msg, const char* destination ) :
m_version( g_SaveVersion )
{
Console::MsgLn( "%s %s", msg, destination );
}
void SaveState::FreezeAll()
{
if( IsLoading() )
PreLoadPrep();
FreezeMem(PS2MEM_BASE, 0x02000000); // 32 MB main memory
FreezeMem(PS2MEM_ROM, 0x00400000); // 4 mb rom memory
FreezeMem(PS2MEM_ROM1,0x00040000); // 256kb rom1 memory
FreezeMem(PS2MEM_SCRATCH, 0x00004000); // scratch pad
FreezeMem(PS2MEM_HW, 0x00010000); // hardware memory
Freeze(cpuRegs); // cpu regs + COP0
Freeze(psxRegs); // iop regs
Freeze(fpuRegs); // fpu regs
Freeze(tlb); // tlbs
Freeze(EEsCycle);
Freeze(EEoCycle);
Freeze(psxRegs.cycle); // used to be IOPoCycle. This retains compatibility.
Freeze(g_nextBranchCycle);
Freeze(g_psxNextBranchCycle);
Freeze(s_iLastCOP0Cycle);
if( m_version >= 0x7a30000e )
Freeze(s_iLastPERFCycle);
Freeze(g_psxWriteOk);
//hope didn't forgot any cpu....
rcntFreeze();
gsFreeze();
vu0Freeze();
vu1Freeze();
vif0Freeze();
vif1Freeze();
sifFreeze();
ipuFreeze();
// iop now
FreezeMem(psxM, 0x00200000); // 2 MB main memory
FreezeMem(psxH, 0x00010000); // hardware memory
//FreezeMem(psxS, 0x00010000); // sif memory
sioFreeze();
cdrFreeze();
cdvdFreeze();
psxRcntFreeze();
sio2Freeze();
if( CHECK_MULTIGS ) {
// have to call in thread, otherwise weird stuff will start happening
GSRingBufPointerPacket(
IsSaving() ? GS_RINGTYPE_SAVE : GS_RINGTYPE_LOAD, 0, this
);
gsWaitGS();
}
else {
FreezePlugin( "GS", GSfreeze );
}
FreezePlugin( "SPU2", SPU2freeze );
FreezePlugin( "DEV9", DEV9freeze );
FreezePlugin( "USB", USBfreeze );
if( IsLoading() )
PostLoadPrep();
}
gzBaseStateInfo::gzBaseStateInfo( const char* msg, const char* filename ) :
SaveState( msg, filename )
, m_filename( filename )
, m_file( NULL )
{
}
gzBaseStateInfo::~gzBaseStateInfo()
{
if( m_file != NULL )
{
gzclose( m_file );
m_file = NULL;
}
}
gzSavingState::gzSavingState( const char* filename ) :
gzBaseStateInfo( _("Saving state to: "), filename )
{
m_file = gzopen(filename, "wb");
if( m_file == NULL )
throw Exception::FileNotFound();
Freeze( m_version );
}
gzLoadingState::gzLoadingState( const char* filename ) :
gzBaseStateInfo( _("Loading state from: "), filename )
{
m_file = gzopen(filename, "rb");
if( m_file == NULL )
throw Exception::FileNotFound();
gzread( m_file, &m_version, 4 );
if( m_version != g_SaveVersion )
{
#ifdef PCSX2_VIRTUAL_MEM
if( m_version >= 0x8b400000 )
{
Console::Error(
"Savestate load aborted:\n"
"\tVM edition cannot safely load savestates created by the VTLB edition."
);
throw Exception::UnsupportedStateVersion();
}
// pcsx2 vm supports opening these formats
if( m_version < 0x7a30000d )
{
Console::MsgLn( "Unsupported or unrecognized savestate version: %x.", m_version );
throw Exception::UnsupportedStateVersion();
}
#else
Console::Error(
"Savestate load aborted:\n"
"\tVTLB edition cannot safely load savestates created by the VM edition." );
throw Exception::UnsupportedStateVersion();
#endif
}
}
gzLoadingState::~gzLoadingState() { }
void gzSavingState::FreezeMem( void* data, int size )
{
gzwrite( m_file, data, size );
}
void gzLoadingState::FreezeMem( void* data, int size )
{
gzread( m_file, data, size );
}
void gzSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
{
Console::MsgLn( "\tSaving %s", name );
freezeData fP = { 0, NULL };
if (freezer(FREEZE_SIZE, &fP) == -1)
throw Exception::FreezePluginFailure( name, "saving" );
gzwrite(m_file, &fP.size, sizeof(fP.size));
if( fP.size == 0 ) return;
fP.data = (s8*)malloc(fP.size);
if (fP.data == NULL)
throw std::bad_alloc();
if(freezer(FREEZE_SAVE, &fP) == -1)
throw Exception::FreezePluginFailure( name, "saving" );
if (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) )
{
freezeData fP = { 0, NULL };
Console::MsgLn( "\tLoading %s", name );
gzread(m_file, &fP.size, sizeof(fP.size));
if( fP.size == 0 ) return;
fP.data = (s8*)malloc(fP.size);
if (fP.data == NULL)
throw std::bad_alloc();
gzread(m_file, fP.data, fP.size);
if( gzeof( m_file ) )
throw Exception::BadSavedState( m_filename );
if(freezer(FREEZE_LOAD, &fP) == -1)
throw Exception::FreezePluginFailure( name, "loading" );
if (fP.size) free(fP.data);
}
//////////////////////////////////////////////////////////////////////////////////
memBaseStateInfo::memBaseStateInfo( MemoryAlloc& memblock, const char* msg ) :
SaveState( msg, "Memory" )
, m_memory( memblock )
, m_idx( 0 )
{
}
memSavingState::memSavingState( MemoryAlloc& save_to ) : memBaseStateInfo( save_to, _("Saving state to: ") )
{
save_to.ChunkSize = ReallocThreshold;
save_to.MakeRoomFor( MemoryBaseAllocSize );
}
// Saving of state data to a memory buffer
void memSavingState::FreezeMem( void* data, int size )
{
const int end = m_idx+size;
m_memory.MakeRoomFor( end );
u8* dest = (u8*)m_memory.GetPtr();
const u8* src = (u8*)data;
for( ; m_idx<end; ++m_idx, ++src )
dest[m_idx] = *src;
}
memLoadingState::memLoadingState(MemoryAlloc& load_from ) : memBaseStateInfo( load_from, _("Loading state from: ") )
{
}
memLoadingState::~memLoadingState() { }
// Loading of state data from a memory buffer...
void memLoadingState::FreezeMem( void* data, int size )
{
const int end = m_idx+size;
const u8* src = (u8*)m_memory.GetPtr();
u8* dest = (u8*)data;
for( ; m_idx<end; ++m_idx, ++dest )
*dest = src[m_idx];
}
void memSavingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
{
freezeData fP = { 0, NULL };
Console::MsgLn( "\tSaving %s", name );
if( freezer(FREEZE_SIZE, &fP) == -1 )
throw Exception::FreezePluginFailure( name, "saving" );
Freeze( fP.size );
if( fP.size == 0 ) return;
const int end = m_idx+fP.size;
m_memory.MakeRoomFor( end );
fP.data = ((s8*)m_memory.GetPtr()) + m_idx;
if(freezer(FREEZE_SAVE, &fP) == -1)
throw Exception::FreezePluginFailure( name, "saving" );
m_idx += fP.size;
}
void memLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) )
{
freezeData fP;
Console::MsgLn( "\tLoading %s", name );
Freeze( fP.size );
if( fP.size == 0 ) return;
if( ( fP.size + m_idx ) > m_memory.GetSize() )
throw Exception::BadSavedState( "memory" );
fP.data = ((s8*)m_memory.GetPtr()) + m_idx;
if(freezer(FREEZE_LOAD, &fP) == -1)
throw Exception::FreezePluginFailure( name, "loading" );
m_idx += fP.size;
if( ( fP.size + m_idx ) > m_memory.GetSize() )
throw Exception::BadSavedState( "memory" );
}

178
pcsx2/SaveState.h Normal file
View File

@ -0,0 +1,178 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _SAVESTATE_H_
#define _SAVESTATE_H_
#include <zlib.h>
// Savestate Versioning!
// If you make changes to the savestate version, please increment the value below.
#ifdef PCSX2_VIRTUAL_MEM
static const u32 g_SaveVersion = 0x7a300010;
#else
static const u32 g_SaveVersion = 0x8b400000;
#endif
// This class provides the base API for both loading and saving savestates.
// Normally you'll want to use one of the four "functional" derrived classes rather
// than this class directly: gzLoadingState, gzSavingState (gzipped disk-saved
// states), and memLoadingState, memSavingState (uncompressed memory states).
class SaveState
{
protected:
u32 m_version; // version of the savestate being loaded.
public:
SaveState( const char* msg, const char* destination );
virtual ~SaveState() { }
static void GetFilename( char* dest, int slot );
// Gets the version of savestate that this object is acting on.
u32 GetVersion() const { return m_version; }
// Loads or saves the entire emulation state.
// Note: The Cpu state must be reset, and plugins *open*, prior to Defrosting
// (loading) a state!
void FreezeAll();
// Loads or saves an arbitrary data type. Usable on atomic types, structs, and arrays.
// For dynamically allocated pointers use FreezeMem instead.
template<typename T>
void Freeze( T& data )
{
FreezeMem( &data, sizeof( T ) );
}
// 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;
// Loads or saves a memory block.
virtual void FreezeMem( void* data, int size )=0;
// Returns true if this object is a StateSaving type object.
virtual bool IsSaving() const=0;
// Returns true if this object is a StateLoading type object.
bool IsLoading() const { return !IsSaving(); }
// note: gsFreeze() needs to be public because of the GSState recorder.
public:
void gsFreeze();
protected:
// Load/Save functions for the various components of our glorious emulator!
void rcntFreeze();
void vu0Freeze();
void vu1Freeze();
void vif0Freeze();
void vif1Freeze();
void sifFreeze();
void ipuFreeze();
void sioFreeze();
void cdrFreeze();
void cdvdFreeze();
void psxRcntFreeze();
void sio2Freeze();
};
/////////////////////////////////////////////////////////////////////////////////
// Class Declarations for Savestates using zlib
class gzBaseStateInfo : public SaveState
{
protected:
const char* m_filename;
gzFile m_file; // used for reading/writing disk saves
public:
gzBaseStateInfo( const char* msg, const char* filename );
virtual ~gzBaseStateInfo();
};
class gzSavingState : public gzBaseStateInfo
{
public:
virtual ~gzSavingState() {}
gzSavingState( const char* filename ) ;
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
void FreezeMem( void* data, int size );
bool IsSaving() const { return true; }
};
class gzLoadingState : public gzBaseStateInfo
{
public:
virtual ~gzLoadingState();
gzLoadingState( const char* filename );
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
void FreezeMem( void* data, int size );
bool IsSaving() const { return false; }
bool Finished() const { return !!gzeof( m_file ); }
};
//////////////////////////////////////////////////////////////////////////////////
class memBaseStateInfo : public SaveState
{
protected:
MemoryAlloc& m_memory;
int m_idx; // current read/write index of the allocation
public:
virtual ~memBaseStateInfo() { }
memBaseStateInfo( MemoryAlloc& memblock, const char* msg );
};
class memSavingState : public memBaseStateInfo
{
protected:
static const int ReallocThreshold = 0x200000; // 256k reallocation block size.
static const int MemoryBaseAllocSize = 0x02a00000; // 42 meg base alloc
public:
virtual ~memSavingState() { }
memSavingState( MemoryAlloc& save_to );
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
// Saving of state data to a memory buffer
void FreezeMem( void* data, int size );
bool IsSaving() const { return true; }
};
class memLoadingState : public memBaseStateInfo
{
public:
virtual ~memLoadingState();
memLoadingState(MemoryAlloc& load_from );
void FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int mode, freezeData *data) );
// Loading of state data from a memory buffer...
void FreezeMem( void* data, int size );
bool IsSaving() const { return false; }
};
#endif

View File

@ -588,8 +588,7 @@ __forceinline void dmaSIF2() {
}
int sifFreeze(gzFile f, int Mode) {
gzfreeze(&sif0, sizeof(sif0));
gzfreeze(&sif1, sizeof(sif1));
return 0;
void SaveState::sifFreeze() {
Freeze(sif0);
Freeze(sif1);
}

View File

@ -515,22 +515,21 @@ void sioInterrupt() {
psxRegs.interrupt&= ~(1 << 16);
}
extern u32 dwCurSaveStateVer;
int sioFreeze(gzFile f, int Mode) {
void SaveState::sioFreeze() {
int savesize = sizeof(sio);
if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e )
savesize -= 4;
sio.count = 0;
gzfreeze(&sio, savesize);
// eh, not supported anymore.. :)
//if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e )
// savesize -= 4;
return 0;
if( IsLoading() )
sio.count = 0;
Freeze( sio );
}
/*******************************************************************
*******************************************************************
*************** MEMORY CARD SPECIFIC FUNTIONS ******************
*************** MEMORY CARD SPECIFIC FUNCTIONS *****************
*******************************************************************
*******************************************************************/
FILE *LoadMcd(int mcd) {

View File

@ -95,7 +95,6 @@ u8 sioRead8();
void sioWrite8(unsigned char value);
void sioWriteCtrl16(unsigned short value);
extern void sioInterrupt();
int sioFreeze(gzFile f, int Mode);
void InitializeSIO(u8 value);
FILE *LoadMcd(int mcd);

View File

@ -19,8 +19,10 @@
#ifndef __SYSTEM_H__
#define __SYSTEM_H__
#include "Exceptions.h"
int SysInit(); // Init mem and plugins
int SysReset(); // Resets mem
void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
void SysUpdate(); // Called on VBlank (to update i.e. pads)
void SysRunGui(); // Returns to the Gui
void SysClose(); // Close mem and plugins
@ -46,57 +48,173 @@ void SysMunmap(uptr base, u32 size);
void SysPrintf(const char *fmt, ...); // *DEPRECIATED*
static __forceinline void SysMunmap( void* base, u32 size )
{
SysMunmap( (uptr)base, size );
}
// Console Namespace -- Replacements for SysPrintf.
// SysPrintf is depreciated -- We should phase these in over time.
namespace Console
{
enum Colors
{
Color_Black = 0,
Color_Red,
Color_Green,
Color_Yellow,
Color_Blue,
Color_Magenta,
Color_Cyan,
Color_White
};
extern void Open();
extern void Close();
extern void SetTitle( const char* title );
// Changes the active console color.
// This color will be unset by calls to colored text methods
// such as ErrorMsg and Notice.
extern void __fastcall SetColor( Colors color );
// Restores the console color to default (usually low-intensity white on Win32)
extern void ClearColor();
// The following Write functions return bool so that we can use macros to exclude
// them from different buildypes. The return values are always zero.
// Writes a newline to the console.
extern bool __fastcall WriteLn();
// Writes an unformatted string of text to the console (fast!)
// No newline is appended.
extern bool __fastcall Write( const char* fmt );
// Writes an unformatted string of text to the console (fast!)
// A newline is automatically appended.
extern bool __fastcall WriteLn( const char* fmt );
extern bool Format( const char* fmt, ... );
extern bool FormatLn( const char* fmt, ... );
// Writes a line of colored text to the console, with automatic newline appendage.
// The console color is reset to default when the operation is complete.
extern bool MsgLn( Colors color, const char* fmt, ... );
// Writes a line of colored text to the console (no newline).
// The console color is reset to default when the operation is complete.
extern bool Msg( Colors color, const char* fmt, ... );
// Writes a formatted message to the console (no newline)
extern bool Msg( const char* fmt, ... );
// Writes a formatted message to the console, with appended newline.
extern bool MsgLn( const char* fmt, ... );
// Displays a message in the console with red emphasis.
// Newline is automatically appended.
extern bool Error( const char* fmt, ... );
// Displays a message in the console with yellow emphasis.
// Newline is automatically appended.
extern bool Notice( const char* fmt, ... );
}
using Console::Color_Red;
using Console::Color_Green;
using Console::Color_Blue;
using Console::Color_Magenta;
using Console::Color_Cyan;
using Console::Color_Yellow;
using Console::Color_White;
//////////////////////////////////////////////////////////////////
// Class for allocating a resizable memory block.
class MemoryAlloc
{
public:
static const int DefaultChunkSize = 0x1000;
protected:
u8* m_ptr;
int m_alloc; // size of the allocation of memory
public:
int ChunkSize;
public:
virtual ~MemoryAlloc();
MemoryAlloc( int initalSize );
MemoryAlloc();
int GetSize() const { return m_alloc; }
// Gets the pointer to the beginning of the memory allocation.
// Returns null if no memory has been allocated to this handle.
void *GetPtr() { return m_ptr; }
const void *GetPtr() const { return m_ptr; }
void MakeRoomFor( int blockSize );
};
//////////////////////////////////////////////////////////////
// Safe deallocation macros -- always check pointer validity (non-null)
// and set pointer to null on deallocation.
#define safe_delete( ptr ) \
if( ptr != NULL ) { \
delete ptr; \
ptr = NULL; \
}
#define safe_delete_array( ptr ) \
if( ptr != NULL ) { \
delete[] ptr; \
ptr = NULL; \
}
#define safe_free( ptr ) \
if( ptr != NULL ) { \
free( ptr ); \
ptr = NULL; \
}
#define safe_aligned_free( ptr ) \
if( ptr != NULL ) { \
_aligned_free( ptr ); \
ptr = NULL; \
}
#define SafeSysMunmap( ptr, size ) \
if( ptr != NULL ) { \
SysMunmap( (uptr)ptr, size ); \
ptr = NULL; \
}
//////////////////////////////////////////////////////////////
// Macros for ifdef'ing out specific lines of code.
#ifdef PCSX2_DEVBUILD
# define DEVCODE(x) (x)
# define DevCon Console
# define PUBCODE 0&&
static const bool IsDevBuild = true;
#else
# define DEVCODE(x) 0&&(x)
# define DevCon 0&&Console
# define PUBCODE(x) (x)
static const bool IsDevBuild = false;
#endif
#ifdef _DEBUG
static const bool IsDebugBuild = true;
# define DBGCODE(x) (x)
# define DbgCon 0&&Console
static const bool IsDebugBuild = true;
#else
# define DBGCODE(x) 0&&
# define DbgCon 0&&Console
static const bool IsDebugBuild = false;
#endif

View File

@ -25,7 +25,6 @@
int vu0Init();
void vu0Reset();
void vu0ResetRegs();
void vu0Freeze(gzFile f, int Mode);
void vu0Shutdown();
void recResetVU0( void );

View File

@ -81,7 +81,7 @@ int vu0Init()
VU0.Mem = (u8*)VirtualAlloc((void*)0x11000000, 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( VU0.Mem != (void*)0x11000000 ) {
SysPrintf("Failed to alloc vu0mem 0x11000000 %d\n", GetLastError());
Console::MsgLn("Failed to alloc vu0mem 0x11000000 %d", GetLastError());
return -1;
}
@ -131,11 +131,13 @@ void vu0Shutdown()
#ifdef PCSX2_VIRTUAL_MEM
if( !SysMapUserPhysicalPages(VU0.Mem, 16, NULL, 0) )
SysPrintf("err releasing vu0 mem %d\n", GetLastError());
// note: this function *always* fails! (in XP at least)
if( VirtualFree(VU0.Mem, 0, MEM_RELEASE) == 0 )
SysPrintf("err freeing vu0 %d\n", GetLastError());
#else
_aligned_free(VU0.Mem);
_aligned_free(VU0.Micro);
safe_aligned_free(VU0.Mem);
safe_aligned_free(VU0.Micro);
#endif
VU0.Mem = NULL;
@ -172,13 +174,13 @@ void recResetVU0( void )
if( CHECK_VU0REC ) SuperVUReset(0);
}
void vu0Freeze(gzFile f, int Mode) {
gzfreeze(&VU0.ACC, sizeof(VECTOR));
gzfreeze(&VU0.code, sizeof(u32));
gzfreeze(VU0.Mem, 4*1024);
gzfreeze(VU0.Micro, 4*1024);
gzfreeze(VU0.VF, 32*sizeof(VECTOR));
gzfreeze(VU0.VI, 32*sizeof(REG_VI));
void SaveState::vu0Freeze() {
Freeze(VU0.ACC);
Freeze(VU0.code);
FreezeMem(VU0.Mem, 4*1024);
FreezeMem(VU0.Micro, 4*1024);
FreezeMem(VU0.VF, 32*sizeof(VECTOR));
FreezeMem(VU0.VI, 32*sizeof(REG_VI));
}

View File

@ -124,13 +124,13 @@ void vu1Reset() {
recResetVU1();
}
void vu1Freeze(gzFile f, int Mode) {
gzfreeze(&VU1.ACC, sizeof(VECTOR));
gzfreeze(&VU1.code, sizeof(u32));
gzfreeze(VU1.Mem, 16*1024);
gzfreeze(VU1.Micro, 16*1024);
gzfreeze(VU1.VF, 32*sizeof(VECTOR));
gzfreeze(VU1.VI, 32*sizeof(REG_VI));
void SaveState::vu1Freeze() {
Freeze(VU1.ACC);
Freeze(VU1.code);
FreezeMem(VU1.Mem, 16*1024);
FreezeMem(VU1.Micro, 16*1024);
FreezeMem(VU1.VF, 32*sizeof(VECTOR));
FreezeMem(VU1.VI, 32*sizeof(REG_VI));
}
static int count;

View File

@ -62,7 +62,6 @@ extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn);
int vu0Init();
void vu0Reset();
void vu0ResetRegs();
void vu0Freeze(gzFile f, int Mode);
void vu0Shutdown();
void vu0ExecMicro(u32 addr);
void vu0Exec(VURegs* VU);
@ -74,7 +73,6 @@ int vu1Init();
void vu1Reset();
void vu1ResetRegs();
void recResetVU1( void );
void vu1Freeze(gzFile f, int Mode);
void vu1Shutdown();
void vu1ExecMicro(u32 addr);
void vu1Exec(VURegs* VU);

View File

@ -1438,12 +1438,10 @@ void vif0Reset() {
//FreezeMMXRegs(0);
}
int vif0Freeze(gzFile f, int Mode) {
gzfreeze(&vif0, sizeof(vif0));
if (Mode == 0)
void SaveState::vif0Freeze() {
Freeze(vif0);
if( IsLoading() )
SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask);
return 0;
}
//////////////////////////////////////////////////////////////////////////////
@ -2452,10 +2450,8 @@ void vif1Reset() {
FreezeMMXRegs(0);*/
}
int vif1Freeze(gzFile f, int Mode) {
gzfreeze(&vif1, sizeof(vif1));
if (Mode == 0)
void SaveState::vif1Freeze() {
Freeze(vif1);
if( IsLoading() )
SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask);
return 0;
}

View File

@ -93,7 +93,5 @@ void vif1Write32(u32 mem, u32 value);
void vif0Reset();
void vif1Reset();
int vif0Freeze(gzFile f, int Mode);
int vif1Freeze(gzFile f, int Mode);
#endif

View File

@ -455,6 +455,8 @@ bool vtlb_Init()
vtlbUnmappedPWrite64<0x80000000>,vtlbUnmappedPWrite128<0x80000000>);
DefaultPhyHandler=vtlb_RegisterHandler(0,0,0,0,0,0,0,0,0,0);
//done !
//Setup the initial mappings
vtlb_MapHandler(DefaultPhyHandler,0,VTLB_PMAP_SZ);
@ -462,9 +464,15 @@ bool vtlb_Init()
vtlb_VMapUnmap(0,(VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE);
//yeah i know, its stupid .. but this code has to be here for now ;p
vtlb_VMapUnmap((VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE,VTLB_PAGE_SIZE);
//done !
return true;
}
void vtlb_Reset()
{
for(int i=0; i<48; i++) UnmapTLB(i);
}
void vtlb_Term()
{
//nothing to do for now

View File

@ -29,6 +29,7 @@ typedef void __fastcall vltbMemW128FP(u32 addr,const mem128_t* data);
typedef u32 vtlbHandler;
bool vtlb_Init();
void vtlb_Reset();
void vtlb_Term();
//physical stuff

View File

@ -0,0 +1,182 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Win32.h"
#include <windowsx.h>
#include "Common.h"
#include "ix86/ix86.h"
// the EE and VU roundmodes are passed in so that we can "retain" the config values during
// default button action. The checkbox statuses are checked against the Config settings when
// the user hits OK, and the game only resets if they differ.
static void InitRoundClampModes( HWND hDlg, u32 new_eeopt, u32 new_vuopt )
{
CheckRadioButton(hDlg, IDC_EE_ROUNDMODE0, IDC_EE_ROUNDMODE3, IDC_EE_ROUNDMODE0 + ((Config.sseMXCSR & 0x6000) >> 13));
CheckRadioButton(hDlg, IDC_VU_ROUNDMODE0, IDC_VU_ROUNDMODE3, IDC_VU_ROUNDMODE0 + ((Config.sseVUMXCSR & 0x6000) >> 13));
CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE2, IDC_EE_CLAMPMODE0 + ((new_eeopt & 0x2) ? 2 : (new_eeopt & 0x1)));
if (new_vuopt & 0x4) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 3);
else if (new_vuopt & 0x2) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 2);
else if (new_vuopt & 0x1) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 1);
else CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 0);
if (Config.sseMXCSR & 0x8000) CheckDlgButton(hDlg, IDC_EE_CHECK1, TRUE);
if (Config.sseVUMXCSR & 0x8000) CheckDlgButton(hDlg, IDC_VU_CHECK1, TRUE);
}
BOOL APIENTRY AdvancedOptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
InitRoundClampModes( hDlg, Config.eeOptions, Config.vuOptions );
if( !cpucaps.hasStreamingSIMD2Extensions ) {
// SSE1 cpus do not support Denormals Are Zero flag.
Config.sseMXCSR &= ~0x0040;
Config.sseVUMXCSR &= ~0x0040;
EnableWindow( GetDlgItem( hDlg, IDC_EE_CHECK2 ), FALSE );
EnableWindow( GetDlgItem( hDlg, IDC_VU_CHECK2 ), FALSE );
CheckDlgButton( hDlg, IDC_EE_CHECK2, FALSE );
CheckDlgButton( hDlg, IDC_VU_CHECK2, FALSE );
}
else {
if (Config.sseMXCSR & 0x0040) CheckDlgButton(hDlg, IDC_EE_CHECK2, TRUE);
if (Config.sseVUMXCSR & 0x0040) CheckDlgButton(hDlg, IDC_VU_CHECK2, TRUE);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
{
u32 new_eeopt = 0;
u32 new_vuopt = 0;
Config.sseMXCSR &= 0x1fbf;
Config.sseVUMXCSR &= 0x1fbf;
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE0) ? 0x0000 : 0; // Round Nearest
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE1) ? 0x2000 : 0; // Round Negative
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE2) ? 0x4000 : 0; // Round Postive
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_ROUNDMODE3) ? 0x6000 : 0; // Round Zero / Chop
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE0) ? 0x0000 : 0; // Round Nearest
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE1) ? 0x2000 : 0; // Round Negative
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE2) ? 0x4000 : 0; // Round Postive
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_ROUNDMODE3) ? 0x6000 : 0; // Round Zero / Chop
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE0) ? 0x0 : 0;
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE1) ? 0x1 : 0;
new_eeopt |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE2) ? 0x3 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE0) ? 0x0 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE1) ? 0x1 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0;
new_vuopt |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE3) ? 0x7 : 0;
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_CHECK1) ? 0x8000 : 0; // FtZ
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_CHECK1) ? 0x8000 : 0; // FtZ
Config.sseMXCSR |= IsDlgButtonChecked(hDlg, IDC_EE_CHECK2) ? 0x0040 : 0; // DaZ
Config.sseVUMXCSR |= IsDlgButtonChecked(hDlg, IDC_VU_CHECK2) ? 0x0040 : 0; // DaZ
EndDialog(hDlg, TRUE);
// Roundmode options do not require CPU resets to take effect.
SetCPUState(Config.sseMXCSR, Config.sseVUMXCSR);
if( new_eeopt != Config.eeOptions || new_vuopt != Config.vuOptions )
{
// these do, however...
Config.eeOptions = new_eeopt;
Config.vuOptions = new_vuopt;
SysRestorableReset();
}
SaveConfig();
break;
}
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
case IDDEFAULT:
Config.sseMXCSR = DEFAULT_sseMXCSR;
Config.sseVUMXCSR = DEFAULT_sseVUMXCSR;
// SSE1 cpus do not support Denormals Are Zero flag.
if( !cpucaps.hasStreamingSIMD2Extensions ) {
Config.sseMXCSR &= ~0x0040;
Config.sseVUMXCSR &= ~0x0040;
}
InitRoundClampModes( hDlg, DEFAULT_eeOptions, DEFAULT_vuOptions );
CheckDlgButton(hDlg, IDC_EE_CHECK1, (Config.sseMXCSR & 0x8000) ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_VU_CHECK1, (Config.sseVUMXCSR & 0x8000) ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_EE_CHECK2, (Config.sseMXCSR & 0x0040) ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_VU_CHECK2, (Config.sseVUMXCSR & 0x0040) ? TRUE : FALSE);
break;
case IDC_EE_ROUNDMODE0:
case IDC_EE_ROUNDMODE1:
case IDC_EE_ROUNDMODE2:
case IDC_EE_ROUNDMODE3:
CheckRadioButton(hDlg, IDC_EE_ROUNDMODE0, IDC_EE_ROUNDMODE3, IDC_EE_ROUNDMODE0 + ( LOWORD(wParam) % IDC_EE_ROUNDMODE0 ) );
break;
case IDC_VU_ROUNDMODE0:
case IDC_VU_ROUNDMODE1:
case IDC_VU_ROUNDMODE2:
case IDC_VU_ROUNDMODE3:
CheckRadioButton(hDlg, IDC_VU_ROUNDMODE0, IDC_VU_ROUNDMODE3, IDC_VU_ROUNDMODE0 + ( LOWORD(wParam) % IDC_VU_ROUNDMODE0 ) );
break;
case IDC_EE_CLAMPMODE0:
case IDC_EE_CLAMPMODE1:
case IDC_EE_CLAMPMODE2:
CheckRadioButton(hDlg, IDC_EE_CLAMPMODE0, IDC_EE_CLAMPMODE2, IDC_EE_CLAMPMODE0 + ( LOWORD(wParam) % IDC_EE_CLAMPMODE0 ) );
break;
case IDC_VU_CLAMPMODE0:
case IDC_VU_CLAMPMODE1:
case IDC_VU_CLAMPMODE2:
case IDC_VU_CLAMPMODE3:
CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + ( LOWORD(wParam) % IDC_VU_CLAMPMODE0 ) );
break;
}
return TRUE;
}
return FALSE;
}

View File

@ -16,7 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windows.h>
#include "Win32.h"
#include <windowsx.h>
#include <shlobj.h>
#include <stdio.h>
@ -24,7 +25,6 @@
#include "common.h"
#include "plugins.h"
#include "resource.h"
#include "Win32.h"
#define ComboAddPlugin(hw, str) { \
sprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff); \
@ -251,7 +251,7 @@ void OnOK(HWND hW) {
ApplyPluginPath( FW );
SaveConfig();
needReset = 1;
SysRestorableReset();
}

View File

@ -26,6 +26,18 @@ namespace Console
{
static HANDLE hConsole = NULL;
static const int tbl_color_codes[] =
{
0 // black
, FOREGROUND_RED | FOREGROUND_INTENSITY
, FOREGROUND_GREEN | FOREGROUND_INTENSITY
, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
, FOREGROUND_BLUE | FOREGROUND_INTENSITY
, FOREGROUND_RED | FOREGROUND_BLUE
, FOREGROUND_GREEN | FOREGROUND_BLUE
, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
};
void SetTitle( const char* title )
{
if( !hConsole || title==NULL ) return;
@ -61,6 +73,19 @@ namespace Console
hConsole = NULL;
}
__forceinline void __fastcall SetColor( Colors color )
{
SetConsoleTextAttribute( hConsole, tbl_color_codes[color] );
}
__forceinline void ClearColor()
{
SetConsoleTextAttribute( hConsole,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
}
// Writes a newline to the console.
__forceinline bool __fastcall WriteLn()
{
if (hConsole != NULL)
@ -78,6 +103,8 @@ namespace Console
return false;
}
// Writes an unformatted string of text to the console (fast!)
// No newline is appended.
__forceinline bool __fastcall Write( const char* fmt )
{
if (hConsole != NULL)
@ -93,6 +120,8 @@ namespace Console
return false;
}
// Writes an unformatted string of text to the console (fast!)
// A newline is automatically appended.
__forceinline bool __fastcall WriteLn( const char* fmt )
{
Write( fmt );
@ -100,13 +129,39 @@ namespace Console
return false;
}
bool Format( const char* fmt, ... )
// Writes a formatted message to the console, with appended newline.
static __forceinline void __fastcall _MsgLn( Colors color, const char* fmt, va_list args )
{
char msg[2048];
vsprintf_s(msg,2045,fmt,args);
strcat( msg, "\r\n" );
SetColor( color );
Write( msg );
ClearColor();
if( emuLog != NULL )
fflush( emuLog ); // manual flush to accompany manual newline
}
// Writes a line of colored text to the console, with automatic newline appendage.
bool MsgLn( Colors color, const char* fmt, ... )
{
va_list list;
va_start(list,fmt);
_MsgLn( Color_White, fmt, list );
va_end(list);
return false;
}
// writes a formatted message to the console (no newline and no color)
bool Msg( const char* fmt, ... )
{
va_list list;
char msg[2048];
va_start(list,fmt);
_vsnprintf(msg,2047,fmt,list);
vsprintf_s(msg,fmt,list);
msg[2047] = '\0';
va_end(list);
@ -114,13 +169,32 @@ namespace Console
return false;
}
bool FormatLn( const char* fmt, ... )
// writes a formatted message to the console (no newline and no color)
bool Msg( Colors color, const char* fmt, ... )
{
va_list list;
char msg[2048];
va_start(list,fmt);
_vsnprintf(msg,2045,fmt,list);
vsprintf_s(msg,fmt,list);
msg[2047] = '\0';
va_end(list);
SetColor( color );
Write( msg );
ClearColor();
return false;
}
// Writes a formatted message to the console, with appended newline.
// (no coloring)
bool MsgLn( const char* fmt, ... )
{
va_list list;
char msg[2048];
va_start(list,fmt);
vsprintf_s(msg,2045,fmt,list);
va_end(list);
strcat( msg, "\r\n" );
@ -129,4 +203,26 @@ namespace Console
fflush( emuLog ); // manual flush to accomany manual newline
return false;
}
// Displays a message in the console with red emphasis.
// Newline is automatically appended.
bool Error( const char* fmt, ... )
{
va_list list;
va_start(list,fmt);
_MsgLn( Color_Red, fmt, list );
va_end(list);
return false;
}
// Displays a message in the console with yellow emphasis.
// Newline is automatically appended.
bool Notice( const char* fmt, ... )
{
va_list list;
va_start(list,fmt);
_MsgLn( Color_Yellow, fmt, list );
va_end(list);
return false;
}
}

View File

@ -16,17 +16,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windows.h>
#include "Win32.h"
#include <windowsx.h>
#include <commctrl.h>
#include <stdio.h>
#include "Common.h"
#include "VUmicro.h"
#include "PsxCommon.h"
#include "plugins.h"
#include "resource.h"
#include "Win32.h"
#include "ix86/ix86.h"
@ -69,8 +66,6 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
Static_SetText(GetDlgItem(hW, IDC_FRAMESKIP_LABEL5), _("Consecutive Frames to skip:\n(See Note 3)"));
Static_SetText(GetDlgItem(hW, IDC_FRAMESKIP_LABEL6), _("*Note 3: Will skip this number of frames before\n rendering the next sequence of frames. (0=default)\n (e.g. If set to 2, will skip 2 consecutive frames whenever its time\n to skip.)"));
Button_SetText(GetDlgItem(hW, IDOK), _("OK"));
Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel"));
@ -88,17 +83,8 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
SetDlgItemText(hW, IDC_FEATURESINPUT, features);
CheckDlgButton(hW, IDC_CPU_EEREC, !!CHECK_EEREC);
//#ifdef PCSX2_DEVBUILD
CheckDlgButton(hW, IDC_CPU_VU0REC, !!CHECK_VU0REC);
CheckDlgButton(hW, IDC_CPU_VU1REC, !!CHECK_VU1REC);
//#else
// // don't show
// ShowWindow(GetDlgItem(hW, IDC_CPU_VUGROUP), SW_HIDE);
// ShowWindow(GetDlgItem(hW, IDC_CPU_VU0REC), SW_HIDE);
// ShowWindow(GetDlgItem(hW, IDC_CPU_VU1REC), SW_HIDE);
//#endif
CheckDlgButton(hW, IDC_CPU_GSMULTI, !!CHECK_MULTIGS);
@ -116,19 +102,18 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
sprintf(cConsecutiveSkip,"%d",Config.CustomConsecutiveSkip);
SetDlgItemText(hW, IDC_CUSTOM_CONSECUTIVE_SKIP, cConsecutiveSkip);
//EnableWindow( GetDlgItem( hW, IDC_CPU_GSMULTI ), !g_GameInProgress );
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam)) {
switch(LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hW, FALSE);
return TRUE;
return FALSE;
case IDOK:
Cpu->Shutdown();
vu0Shutdown();
vu1Shutdown();
newopts = 0;
if( SendDlgItemMessage(hW,IDC_CPU_EEREC,BM_GETCHECK,0,0) ) newopts |= PCSX2_EEREC;
@ -143,17 +128,8 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIP,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_SKIP;
else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIPVU,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_VUSKIP;
if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) {
Config.Options = newopts;
SaveConfig();
MessageBox(NULL, "Restart Pcsx2", "Query", MB_OK);
exit(0);
}
if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC;
Config.Options = newopts;
GetDlgItemText(hW, IDC_CUSTOMFPS, cfps, 20);
Config.CustomFps = atoi(cfps);
@ -166,15 +142,27 @@ BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
GetDlgItemText(hW, IDC_CUSTOM_CONSECUTIVE_SKIP, cConsecutiveSkip, 20);
Config.CustomConsecutiveSkip = atoi(cConsecutiveSkip);
// [TODO]: This needs to inform the GS too, but it doesn't matter for now
// since the CPU is reset regardless.
UpdateVSyncRate();
EndDialog(hW, TRUE);
if( Config.Options != newopts )
{
SysRestorableReset();
if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) )
{
// gotta shut down *all* the plugins.
ResetPlugins();
}
Config.Options = newopts;
}
else
UpdateVSyncRate();
SaveConfig();
cpuRestartCPU();
EndDialog(hW, TRUE);
return TRUE;
return FALSE;
}
return TRUE;
}
return FALSE;
}

View File

@ -16,8 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <windows.h>
#include <commctrl.h>
#include "win32.h"
#include <windowsx.h>
#include <stdio.h>
#include <string>
@ -26,7 +25,6 @@
#include "InterTables.h"
#include "Debugger.h"
#include "Common.h"
#include "win32.h"
#include "PsxMem.h"
#include "R3000A.h"

View File

@ -23,10 +23,9 @@
* no interaction with emulation code
***************************/
#include <windows.h>
#include "win32.h"
#include <windowsx.h>
#include "Common.h"
#include "win32.h"
#include "resource.h"
/*

View File

@ -17,8 +17,7 @@
*/
#include <winsock2.h>
#include <windows.h>
#include "win32.h"
#include <commctrl.h>
#include <windowsx.h>
#include "resource.h"
@ -26,7 +25,6 @@
#include "RDebugger.h"
#include "Common.h"
#include "PsxCommon.h"
#include "win32.h"
#include "../rdebug/deci2.h"
u32 port=8510;

View File

@ -52,6 +52,7 @@
/>
<Tool
Name="VCCLCompilerTool"
SmallerTypeCheck="false"
CompileAs="2"
/>
<Tool
@ -123,6 +124,9 @@
/>
<Tool
Name="VCCLCompilerTool"
MinimalRebuild="true"
SmallerTypeCheck="false"
EnableFunctionLevelLinking="true"
CompileAs="2"
/>
<Tool
@ -195,6 +199,10 @@
/>
<Tool
Name="VCCLCompilerTool"
MinimalRebuild="true"
ExceptionHandling="1"
SmallerTypeCheck="false"
EnableFunctionLevelLinking="true"
CompileAs="2"
/>
<Tool
@ -279,6 +287,7 @@
PreprocessorDefinitions="NDEBUG,WIN32,_WINDOWS,__MSCW32__,__WIN32__,__i386__,ENABLE_NLS,PACKAGE=\&quot;pcsx2\&quot;;PCSX2_DEVBUILD;_CRT_SECURE_NO_DEPRECATE;TIXML_USE_STL"
StringPooling="true"
ExceptionHandling="1"
SmallerTypeCheck="false"
RuntimeLibrary="0"
StructMemberAlignment="5"
BufferSecurityCheck="false"
@ -363,6 +372,7 @@
Name="VCCLCompilerTool"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="NDEBUG"
SmallerTypeCheck="false"
EnableEnhancedInstructionSet="0"
CompileAs="2"
/>
@ -441,6 +451,7 @@
Name="VCCLCompilerTool"
EnableFiberSafeOptimizations="true"
PreprocessorDefinitions="NDEBUG"
SmallerTypeCheck="false"
EnableEnhancedInstructionSet="0"
CompileAs="2"
/>
@ -496,6 +507,10 @@
RelativePath="..\AboutDlg.h"
>
</File>
<File
RelativePath="..\AdvancedDlg.cpp"
>
</File>
<File
RelativePath="..\Cdrom02.ico"
>
@ -552,6 +567,10 @@
RelativePath="..\WinMain.c"
>
</File>
<File
RelativePath="..\WinVM.cpp"
>
</File>
<Filter
Name="Debugger"
>
@ -608,6 +627,10 @@
<Filter
Name="Misc"
>
<File
RelativePath="..\..\Exceptions.h"
>
</File>
<File
RelativePath="..\..\x86\fast_routines.cpp"
>
@ -640,6 +663,14 @@
RelativePath="..\..\SamplProf.h"
>
</File>
<File
RelativePath="..\..\SaveState.cpp"
>
</File>
<File
RelativePath="..\..\SaveState.h"
>
</File>
<File
RelativePath="..\..\SourceLog.cpp"
>

View File

@ -16,11 +16,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WIN32_H__
#define __WIN32_H__
#ifndef _PCSX2_WIN32_H__
#define _PCSX2_WIN32_H__
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tchar.h>
#include "Misc.h"
#include "resource.h"
// --->> Ini Configuration [ini.c]
@ -39,30 +45,28 @@ struct AppData
HMENU hMenu; // Main window menu
};
extern AppData gApp;
extern int needReset;
extern AppData gApp;
extern HWND hStatusWnd;
extern PcsxConfig winConfig; // local storage of the configuration options.
extern bool g_GameInProgress;
LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
void CreateMainWindow(int nCmdShow);
void RunGui();
BOOL Open_File_Proc(char *filename);
BOOL Pcsx2Configure(HWND hWnd);
void RunExecute(int run);
void InitLanguages();
char *GetLanguageNext();
void CloseLanguages();
void ChangeLanguage(char *lang);
#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text);
#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)(text));
void SysRestorableReset();
//patch browser window
BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
//cpu dialog window
BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK AdvancedOptionsProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif

File diff suppressed because it is too large Load Diff

470
pcsx2/windows/WinVM.cpp Normal file
View File

@ -0,0 +1,470 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "win32.h"
#include <windowsx.h>
#ifdef PCSX2_VIRTUAL_MEM
// virtual memory/privileges
#include "ntsecapi.h"
static wchar_t s_szUserName[255];
LRESULT WINAPI UserNameProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_INITDIALOG:
SetWindowPos(hDlg, HWND_TOPMOST, 200, 100, 0, 0, SWP_NOSIZE);
return TRUE;
case WM_COMMAND:
switch(wParam) {
case IDOK:
{
wchar_t str[255];
GetWindowTextW(GetDlgItem(hDlg, IDC_USER_NAME), str, 255);
swprintf(s_szUserName, 255, L"%S", str);
EndDialog(hDlg, TRUE );
return TRUE;
}
case IDCANCEL:
EndDialog(hDlg, FALSE );
return TRUE;
}
break;
}
return FALSE;
}
BOOL InitLsaString(
PLSA_UNICODE_STRING pLsaString,
LPCWSTR pwszString
)
{
DWORD dwLen = 0;
if (NULL == pLsaString)
return FALSE;
if (NULL != pwszString)
{
dwLen = wcslen(pwszString);
if (dwLen > 0x7ffe) // String is too large
return FALSE;
}
// Store the string.
pLsaString->Buffer = (WCHAR *)pwszString;
pLsaString->Length = (USHORT)dwLen * sizeof(WCHAR);
pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR);
return TRUE;
}
PLSA_TRANSLATED_SID2 GetSIDInformation (LPWSTR AccountName,LSA_HANDLE PolicyHandle)
{
LSA_UNICODE_STRING lucName;
PLSA_TRANSLATED_SID2 ltsTranslatedSID;
PLSA_REFERENCED_DOMAIN_LIST lrdlDomainList;
//LSA_TRUST_INFORMATION myDomain;
NTSTATUS ntsResult;
PWCHAR DomainString = NULL;
// Initialize an LSA_UNICODE_STRING with the name.
if (!InitLsaString(&lucName, AccountName))
{
wprintf(L"Failed InitLsaString\n");
return NULL;
}
ntsResult = LsaLookupNames2(
PolicyHandle, // handle to a Policy object
0,
1, // number of names to look up
&lucName, // pointer to an array of names
&lrdlDomainList, // receives domain information
&ltsTranslatedSID // receives relative SIDs
);
if (0 != ntsResult)
{
wprintf(L"Failed LsaLookupNames - %lu \n",
LsaNtStatusToWinError(ntsResult));
return NULL;
}
// Get the domain the account resides in.
// myDomain = lrdlDomainList->Domains[ltsTranslatedSID->DomainIndex];
// DomainString = (PWCHAR) LocalAlloc(LPTR, myDomain.Name.Length + 1);
// wcsncpy(DomainString, myDomain.Name.Buffer, myDomain.Name.Length);
// Display the relative Id.
// wprintf(L"Relative Id is %lu in domain %ws.\n",
// ltsTranslatedSID->RelativeId,
// DomainString);
LsaFreeMemory(lrdlDomainList);
return ltsTranslatedSID;
}
BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle, BOOL bAdd)
{
LSA_UNICODE_STRING lucPrivilege;
NTSTATUS ntsResult;
// Create an LSA_UNICODE_STRING for the privilege name(s).
if (!InitLsaString(&lucPrivilege, L"SeLockMemoryPrivilege"))
{
wprintf(L"Failed InitLsaString\n");
return FALSE;
}
if( bAdd ) {
ntsResult = LsaAddAccountRights(
PolicyHandle, // An open policy handle.
AccountSID, // The target SID.
&lucPrivilege, // The privilege(s).
1 // Number of privileges.
);
}
else {
ntsResult = LsaRemoveAccountRights(
PolicyHandle, // An open policy handle.
AccountSID, // The target SID
FALSE,
&lucPrivilege, // The privilege(s).
1 // Number of privileges.
);
}
if (ntsResult == 0)
{
wprintf(L"Privilege added.\n");
}
else
{
int err = LsaNtStatusToWinError(ntsResult);
char str[255];
_snprintf(str, 255, "Privilege was not added - %lu \n", LsaNtStatusToWinError(ntsResult));
MessageBox(NULL, str, "Privilege error", MB_OK);
return FALSE;
}
return TRUE;
}
#define TARGET_SYSTEM_NAME L"mysystem"
LSA_HANDLE GetPolicyHandle()
{
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR SystemName[] = TARGET_SYSTEM_NAME;
USHORT SystemNameLength;
LSA_UNICODE_STRING lusSystemName;
NTSTATUS ntsResult;
LSA_HANDLE lsahPolicyHandle;
// Object attributes are reserved, so initialize to zeroes.
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
//Initialize an LSA_UNICODE_STRING to the server name.
SystemNameLength = wcslen(SystemName);
lusSystemName.Buffer = SystemName;
lusSystemName.Length = SystemNameLength * sizeof(WCHAR);
lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR);
// Get a handle to the Policy object.
ntsResult = LsaOpenPolicy(
NULL, //Name of the target system.
&ObjectAttributes, //Object attributes.
POLICY_ALL_ACCESS, //Desired access permissions.
&lsahPolicyHandle //Receives the policy handle.
);
if (ntsResult != 0)
{
// An error occurred. Display it as a win32 error code.
wprintf(L"OpenPolicy returned %lu\n",
LsaNtStatusToWinError(ntsResult));
return NULL;
}
return lsahPolicyHandle;
}
/*****************************************************************
LoggedSetLockPagesPrivilege: a function to obtain, if possible, or
release the privilege of locking physical pages.
Inputs:
HANDLE hProcess: Handle for the process for which the
privilege is needed
BOOL bEnable: Enable (TRUE) or disable?
Return value: TRUE indicates success, FALSE failure.
*****************************************************************/
BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable)
{
struct {
u32 Count;
LUID_AND_ATTRIBUTES Privilege [1];
} Info;
HANDLE Token;
BOOL Result;
// Open the token.
Result = OpenProcessToken ( hProcess,
TOKEN_ADJUST_PRIVILEGES,
& Token);
if( Result != TRUE ) {
Console::Error( "VirtualMemory Error > Cannot open process token." );
return FALSE;
}
// Enable or disable?
Info.Count = 1;
if( bEnable )
{
Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else
{
Info.Privilege[0].Attributes = SE_PRIVILEGE_REMOVED;
}
// Get the LUID.
Result = LookupPrivilegeValue ( NULL,
SE_LOCK_MEMORY_NAME,
&(Info.Privilege[0].Luid));
if( Result != TRUE )
{
Console::Error( "VirtualMemory Error > Cannot get privilege value for %s.", SE_LOCK_MEMORY_NAME );
return FALSE;
}
// Adjust the privilege.
Result = AdjustTokenPrivileges ( Token, FALSE,
(PTOKEN_PRIVILEGES) &Info,
0, NULL, NULL);
// Check the result.
if( Result != TRUE )
{
Console::Error( "VirtualMemory Error > Cannot adjust token privileges, error %u.", GetLastError() );
return FALSE;
}
else
{
if( GetLastError() != ERROR_SUCCESS )
{
BOOL bSuc = FALSE;
LSA_HANDLE policy;
PLSA_TRANSLATED_SID2 ltsTranslatedSID;
// if( !DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_USERNAME), gApp.hWnd, (DLGPROC)UserNameProc) )
// return FALSE;
DWORD len = sizeof(s_szUserName);
GetUserNameW(s_szUserName, &len);
policy = GetPolicyHandle();
if( policy != NULL ) {
ltsTranslatedSID = GetSIDInformation(s_szUserName, policy);
if( ltsTranslatedSID != NULL ) {
bSuc = AddPrivileges(ltsTranslatedSID->Sid, policy, bEnable);
LsaFreeMemory(ltsTranslatedSID);
}
LsaClose(policy);
}
if( bSuc ) {
// Get the LUID.
LookupPrivilegeValue ( NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid));
bSuc = AdjustTokenPrivileges ( Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL);
}
if( bSuc ) {
if( MessageBox(NULL, "PCSX2 just changed your SE_LOCK_MEMORY privilege in order to gain access to physical memory.\n"
"Log off/on and run pcsx2 again. Do you want to log off?\n",
"Privilege changed query", MB_YESNO) == IDYES ) {
ExitWindows(EWX_LOGOFF, 0);
}
}
else {
MessageBox(NULL, "Failed adding SE_LOCK_MEMORY privilege, please check the local policy.\n"
"Go to security settings->Local Policies->User Rights. There should be a \"Lock pages in memory\".\n"
"Add your user to that and log off/on. This enables pcsx2 to run at real-time by allocating physical memory.\n"
"Also can try Control Panel->Local Security Policy->... (this does not work on Windows XP Home)\n"
"(zerofrog)\n", "Virtual Memory Access Denied", MB_OK);
return FALSE;
}
}
}
CloseHandle( Token );
return TRUE;
}
static u32 s_dwPageSize = 0;
int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock)
{
//#ifdef WIN32_FILE_MAPPING
// assert(0);
//#endif
ULONG_PTR NumberOfPagesInitial; // initial number of pages requested
int PFNArraySize; // memory to request for PFN array
BOOL bResult;
assert( pblock != NULL );
memset(pblock, 0, sizeof(PSMEMORYBLOCK));
if( s_dwPageSize == 0 ) {
SYSTEM_INFO sSysInfo; // useful system information
GetSystemInfo(&sSysInfo); // fill the system information structure
s_dwPageSize = sSysInfo.dwPageSize;
if( s_dwPageSize != 0x1000 ) {
SysMessage("Error! OS page size must be 4Kb!\n"
"If for some reason the OS cannot have 4Kb pages, then run the TLB build.");
return -1;
}
}
// Calculate the number of pages of memory to request.
pblock->NumberPages = (size+s_dwPageSize-1)/s_dwPageSize;
PFNArraySize = pblock->NumberPages * sizeof (ULONG_PTR);
pblock->aPFNs = (uptr*)HeapAlloc (GetProcessHeap (), 0, PFNArraySize);
if (pblock->aPFNs == NULL) {
SysPrintf("Failed to allocate on heap.\n");
goto eCleanupAndExit;
}
// Allocate the physical memory.
NumberOfPagesInitial = pblock->NumberPages;
bResult = AllocateUserPhysicalPages( GetCurrentProcess(), (PULONG_PTR)&pblock->NumberPages, (PULONG_PTR)pblock->aPFNs );
if( bResult != TRUE )
{
SysPrintf("Cannot allocate physical pages, error %u.\n", GetLastError() );
goto eCleanupAndExit;
}
if( NumberOfPagesInitial != pblock->NumberPages )
{
SysPrintf("Allocated only %p of %p pages.\n", pblock->NumberPages, NumberOfPagesInitial );
goto eCleanupAndExit;
}
pblock->aVFNs = (uptr*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);
return 0;
eCleanupAndExit:
SysPhysicalFree(pblock);
return -1;
}
void SysPhysicalFree(PSMEMORYBLOCK* pblock)
{
assert( pblock != NULL );
// Free the physical pages.
FreeUserPhysicalPages( GetCurrentProcess(), (PULONG_PTR)&pblock->NumberPages, (PULONG_PTR)pblock->aPFNs );
if( pblock->aPFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aPFNs);
if( pblock->aVFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aVFNs);
memset(pblock, 0, sizeof(PSMEMORYBLOCK));
}
int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock)
{
BOOL bResult;
int i;
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE );
if( lpMemReserved == NULL || base != lpMemReserved )
{
Console::MsgLn("VirtualMemory Error %d > Cannot reserve memory at 0x%8.8x(%x).", base, lpMemReserved, GetLastError());
goto eCleanupAndExit;
}
// Map the physical memory into the window.
bResult = MapUserPhysicalPages( base, (ULONG_PTR)pblock->NumberPages, (PULONG_PTR)pblock->aPFNs );
for(i = 0; i < pblock->NumberPages; ++i)
pblock->aVFNs[i] = (uptr)base + 0x1000*i;
if( bResult != TRUE )
{
Console::MsgLn("VirtualMemory Error %u > MapUserPhysicalPages failed to map.", GetLastError() );
goto eCleanupAndExit;
}
return 0;
eCleanupAndExit:
SysVirtualFree(base, size);
return -1;
}
void SysVirtualFree(void* lpMemReserved, u32 size)
{
// unmap
if( MapUserPhysicalPages( lpMemReserved, (size+s_dwPageSize-1)/s_dwPageSize, NULL ) != TRUE )
{
Console::MsgLn("VirtualMemory Error %u > MapUserPhysicalPages failed to unmap", GetLastError() );
return;
}
// Free virtual memory.
VirtualFree( lpMemReserved, 0, MEM_RELEASE );
}
int SysMapUserPhysicalPages(void* Addr, uptr NumPages, uptr* pfn, int pageoffset)
{
BOOL bResult = MapUserPhysicalPages(Addr, NumPages, (PULONG_PTR)(pfn+pageoffset));
#ifdef _DEBUG
//if( !bResult )
//__Log("Failed to map user pages: 0x%x:0x%x, error = %d\n", Addr, NumPages, GetLastError());
#endif
return bResult;
}
#else
#endif

View File

@ -19,12 +19,11 @@
15-09-2004 : file rewriten for work with inis (shadow)
*/
#include <windows.h>
#include "win32.h"
#include <windowsx.h>
#include <stdio.h>
#include "Common.h"
#include "win32.h"
#include "Paths.h"
#include <sys/stat.h>

View File

@ -73,12 +73,12 @@ uptr *psxRecLUT;
// R3000A statics
int psxreclog = 0;
static u8 *recMem; // the recompiled blocks will be here
static BASEBLOCK *recRAM; // and the ptr to the blocks here
static BASEBLOCK *recROM; // and here
static BASEBLOCK *recROM1; // also here
static u8 *recMem = NULL; // the recompiled blocks will be here
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
static BASEBLOCK *recROM = NULL; // and here
static BASEBLOCK *recROM1 = NULL; // also here
static BASEBLOCKEX *recBlocks = NULL;
static u8 *recPtr;
static u8 *recPtr = NULL;
u32 psxpc; // recompiler psxpc
int psxbranch; // set for branch
u32 g_iopCyclePenalty;
@ -529,37 +529,53 @@ static int recInit() {
uptr startaddr;
// can't have upper 4 bits nonzero!
// ... we can't? (air)
startaddr = 0x0f000000;
while(!(startaddr & 0xf0000000)) {
if( recMem == NULL )
//while(!(startaddr & 0xf0000000)) {
recMem = (u8*)SysMmap(startaddr, RECMEM_SIZE);
if( (uptr)recMem & 0xf0000000 ) {
SysMunmap((uptr)recMem, RECMEM_SIZE); recMem = NULL;
/*if( (uptr)recMem & 0xf0000000 ) {
SysMunmap(recMem, RECMEM_SIZE); recMem = NULL;
startaddr += 0x00100000;
continue;
}
else break;
}
else break;*/
//}
if( recMem == NULL ) {
SysPrintf("R3000A bad rec memory allocation\n");
Console::Error( "Error > R3000A failed to allocate recompiler memory." );
return 1;
}
ProfilerRegisterSource("IOPRec",recMem, RECMEM_SIZE);
if( psxRecLUT == NULL )
psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
memset(psxRecLUT, 0, 0x010000 * sizeof(uptr));
if( recRAM == NULL )
recRAM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x200000, 16);
if( recROM == NULL )
recROM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x400000, 16);
if( recROM1 == NULL )
recROM1= (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x040000, 16);
if( recBlocks == NULL )
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*PSX_NUMBLOCKS, 16);
recRAM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x200000, 16);
recROM = (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x400000, 16);
recROM1= (BASEBLOCK*) _aligned_malloc(sizeof(BASEBLOCK)/4*0x040000, 16);
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*PSX_NUMBLOCKS, 16);
if (recRAM == NULL || recROM == NULL || recROM1 == NULL ||
recMem == NULL || psxRecLUT == NULL) {
SysMessage("Error allocating memory"); return -1;
if( s_pInstCache == NULL )
{
s_nInstCacheSize = 128;
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
}
s_nInstCacheSize = 128;
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
if( recRAM == NULL || recROM == NULL || recROM1 == NULL ||
psxRecLUT == NULL || recBlocks == NULL || s_pInstCache == NULL )
{
SysMessage( _("Error allocating memory") ); return -1;
}
// No errors! Proceed with initialization...
memset(psxRecLUT, 0, 0x010000 * sizeof(uptr));
ProfilerRegisterSource("IOPRec",recMem, RECMEM_SIZE);
for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (uptr)&recRAM[(i & 0x1f) << 14];
for (i=0; i<0x80; i++) psxRecLUT[i + 0x8000] = (uptr)&recRAM[(i & 0x1f) << 14];
@ -578,11 +594,9 @@ static int recInit() {
return 0;
}
static void recReset() {
#ifdef PCSX2_DEVBUILD
SysPrintf("IOP Recompiler data reset\n");
#endif
static void recReset()
{
DevCon::WriteLn("IOP Recompiler data reset");
memset(recRAM, 0, sizeof(BASEBLOCK)/4*0x200000);
memset(recROM, 0, sizeof(BASEBLOCK)/4*0x400000);
@ -597,15 +611,17 @@ static void recReset() {
psxbranch = 0;
}
static void recShutdown() {
if (recMem == NULL) return;
free(psxRecLUT);
SysMunmap((uptr)recMem, RECMEM_SIZE);
_aligned_free(recRAM);
_aligned_free(recROM);
_aligned_free(recROM1);
_aligned_free( recBlocks ); recBlocks = NULL;
free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0;
static void recShutdown()
{
SafeSysMunmap(recMem, RECMEM_SIZE);
safe_free(psxRecLUT);
safe_aligned_free(recRAM);
safe_aligned_free(recROM);
safe_aligned_free(recROM1);
safe_aligned_free( recBlocks );
safe_free( s_pInstCache );
s_nInstCacheSize = 0;
x86Shutdown();
}

View File

@ -337,10 +337,21 @@ static void SuperVURecompile();
void SuperVUInit(int vuindex)
{
if( vuindex < 0 ) {
// upper 4 bits cannot be nonzero!
s_recVUMem = (u8*)SysMmap(0x0c000000, VU_EXESIZE);
if( (uptr)s_recVUMem > 0x80000000 )
SysPrintf("bad SuperVU alloc %x\n", s_recVUMem);
// upper 4 bits cannot be nonzero!
uptr baseaddr = 0x0c000000;
while( baseaddr < 0x7a000000 && ( s_recVUMem == NULL || ((uptr)s_recVUMem > 0x80000000) ) )
{
s_recVUMem = (u8*)SysMmap( baseaddr, VU_EXESIZE);
baseaddr += 0x100000;
}
if( s_recVUMem == NULL || ((uptr)s_recVUMem > 0x80000000) )
{
Console::Error( "Error > SuperVU failed to allocate recompiler memory (addr: 0x%x)", (u32)s_recVUMem );
throw std::bad_alloc();
}
ProfilerRegisterSource("VURec",s_recVUMem, VU_EXESIZE);
memset(s_recVUMem, 0xcd, VU_EXESIZE);
s_recVUPtr = s_recVUMem;
@ -361,20 +372,19 @@ void SuperVUDestroy(int vuindex)
if( vuindex < 0 ) {
SuperVUDestroy(0);
SuperVUDestroy(1);
SysMunmap((uptr)s_recVUMem, VU_EXESIZE);
s_recVUPtr = NULL;
delete[] recVUStack; recVUStack = NULL;
SafeSysMunmap(s_recVUMem, VU_EXESIZE);
safe_delete_array( recVUStack );
}
else {
delete[] recVUHeaders[vuindex]; recVUHeaders[vuindex] = NULL;
delete[] recVUBlocks[vuindex]; recVUBlocks[vuindex] = NULL;
safe_delete_array( recVUHeaders[vuindex] );
safe_delete_array( recVUBlocks[vuindex] );
if( s_plistCachedHeaders[vuindex] != NULL ) {
for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) {
FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it;
s_plistCachedHeaders[vuindex][j].clear();
}
delete[] s_plistCachedHeaders[vuindex]; s_plistCachedHeaders[vuindex] = NULL;
safe_delete_array( s_plistCachedHeaders[vuindex] );
}
FORIT(it, s_listVUHeaders[vuindex]) delete *it;
@ -2587,7 +2597,7 @@ static void SuperVURecompile()
// debug
#ifdef _DEBUG
extern u32 s_vucount;
u32 s_vucount=0;
static u32 g_vu1lastrec = 0, skipparent = -1;
static u32 s_svulast = 0, s_vufnheader;
@ -2647,7 +2657,7 @@ void svudispfntemp()
{
//static int curesp;
//__asm mov curesp, esp
Console::FormatLn("tVU: %x %x %x", s_svulast, s_vucount, s_vufnheader);
Console::MsgLn("tVU: %x %x %x", s_svulast, s_vucount, s_vufnheader);
if( g_curdebugvu ) iDumpVU1Registers();
else iDumpVU0Registers();
s_vucount++;

View File

@ -60,7 +60,7 @@
#endif
u32 maxrecmem = 0;
uptr *recLUT;
uptr *recLUT = NULL;
#define X86
#define RECSTACK_SIZE 0x00010000
@ -1491,27 +1491,51 @@ int recInit( void )
int i;
const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 );
memset( recLUT, 0, 0x010000 * sizeof(uptr) );
if( recLUT == NULL )
recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 );
// can't have upper 4 bits nonzero!
recMem = (u8*)SysMmap(0x0d000000, REC_CACHEMEM+0x1000); // +0x1000 ? vtlb check.
ProfilerRegisterSource("EERec",recMem, REC_CACHEMEM+0x1000);
// ... then why don't we care to check if they are or not? (air)
if( recMem == NULL )
recMem = (u8*)SysMmap(0x0d000000, REC_CACHEMEM+0x1000);
if( recMem == NULL ) {
Console::Error("Error > R5900-32 failed to allocate recompiler memory.");
return 1;
}
// 32 alignment necessary
recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK));
recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK));
recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK));
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16);
recStack = (u8*)malloc( RECSTACK_SIZE );
if( recRAM == NULL )
recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK));
if( recROM == NULL )
recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK));
if( recROM1 == NULL )
recROM1 = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK));
if( recBlocks == NULL )
recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16);
if( recStack == NULL )
recStack = (u8*)malloc( RECSTACK_SIZE );
s_nInstCacheSize = 128;
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
if( s_pInstCache == NULL )
{
s_nInstCacheSize = 128;
s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize );
}
if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) {
if( recBlocks == NULL || recRAM == NULL || recROM == NULL ||
recROM1 == NULL || recMem == NULL || recLUT == NULL ||
recStack == NULL || s_pInstCache == NULL )
{
SysMessage( _( "Error allocating memory" ) );
return -1;
}
// No errors.. Proceed with initialization:
ProfilerRegisterSource("EERec",recMem, REC_CACHEMEM+0x1000);
memset( recLUT, 0, 0x010000 * sizeof(uptr) );
for ( i = 0x0000; i < 0x0200; i++ )
{
recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ];
@ -1607,9 +1631,8 @@ int recInit( void )
////////////////////////////////////////////////////
static void recReset( void ) {
#ifdef PCSX2_DEVBUILD
SysPrintf("EE Recompiler data reset\n");
#endif
DevCon::WriteLn( "EE Recompiler data reset" );
s_nNextBlock = 0;
maxrecmem = 0;
@ -1644,21 +1667,20 @@ static void recReset( void ) {
void recShutdown( void )
{
if ( recMem == NULL ) {
return;
}
SafeSysMunmap(recMem, REC_CACHEMEM);
_aligned_free( recLUT );
SysMunmap((uptr)recMem, REC_CACHEMEM); recMem = NULL;
_aligned_free( recRAM ); recRAM = NULL;
_aligned_free( recROM ); recROM = NULL;
_aligned_free( recROM1 ); recROM1 = NULL;
_aligned_free( recBlocks ); recBlocks = NULL;
free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0;
safe_aligned_free( recLUT );
safe_aligned_free( recRAM );
safe_aligned_free( recROM );
safe_aligned_free( recROM1 );
safe_aligned_free( recBlocks );
safe_free( s_pInstCache );
s_nInstCacheSize = 0;
SuperVUDestroy(-1);
x86Shutdown( );
x86Shutdown();
}
void recEnableVU0micro(int enable) {
@ -3287,7 +3309,7 @@ StartRecomp:
stg-=4;
lpc+=4;
}
DbgCon::FormatLn("Manual block @ %08X : %08X %d %d %d %d",
DbgCon::MsgLn("Manual block @ %08X : %08X %d %d %d %d",
startpc,inpage_ptr,pgsz,0x1000-inpage_offs,inpage_sz,sz*4);
}
}

View File

@ -1749,7 +1749,6 @@ extern void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from );
extern void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from );
extern void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from );
extern void PF2IDMtoR( x86IntRegType to, uptr from );
extern void PF2IDRtoR( x86IntRegType to, x86IntRegType from );
extern void PI2FDMtoR( x86IntRegType to, uptr from );
extern void PI2FDRtoR( x86IntRegType to, x86IntRegType from );
extern void PFMAXMtoR( x86IntRegType to, uptr from );

View File

@ -214,7 +214,7 @@ void cpudetectInit( void )
u32 x86_64_8BITBRANDID;
u32 x86_64_12BITBRANDID;
int num;
char str[50];
char str[50];
memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) );
cpuinfo.x86Family = 0;