diff --git a/pcsx2/CDVD.c b/pcsx2/CDVD.c index e03f0d23d9..342b99467e 100644 --- a/pcsx2/CDVD.c +++ b/pcsx2/CDVD.c @@ -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() { diff --git a/pcsx2/CDVD.h b/pcsx2/CDVD.h index 70eb886e12..e5c369b5ff 100644 --- a/pcsx2/CDVD.h +++ b/pcsx2/CDVD.h @@ -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); diff --git a/pcsx2/CDVDisodrv.c b/pcsx2/CDVDisodrv.c index 68f3c85de0..7d7b275b0c 100644 --- a/pcsx2/CDVDisodrv.c +++ b/pcsx2/CDVDisodrv.c @@ -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 diff --git a/pcsx2/CDVDisodrv.h b/pcsx2/CDVDisodrv.h index cefd4ce316..c94d4a021d 100644 --- a/pcsx2/CDVDisodrv.h +++ b/pcsx2/CDVDisodrv.h @@ -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 ); diff --git a/pcsx2/COP0.c b/pcsx2/COP0.c index f896e20972..4734a0b3cd 100644 --- a/pcsx2/COP0.c +++ b/pcsx2/COP0.c @@ -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) diff --git a/pcsx2/CdRom.c b/pcsx2/CdRom.c index 72abd3b188..98d41074f6 100644 --- a/pcsx2/CdRom.c +++ b/pcsx2/CdRom.c @@ -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; } diff --git a/pcsx2/CdRom.h b/pcsx2/CdRom.h index 17d36ee405..ebb4290c44 100644 --- a/pcsx2/CdRom.h +++ b/pcsx2/CdRom.h @@ -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__ */ diff --git a/pcsx2/Common.h b/pcsx2/Common.h index 0679a7a57b..5e5ad79d4c 100644 --- a/pcsx2/Common.h +++ b/pcsx2/Common.h @@ -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; diff --git a/pcsx2/Counters.c b/pcsx2/Counters.c index 56324d5821..dd6511a42e 100644 --- a/pcsx2/Counters.c +++ b/pcsx2/Counters.c @@ -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. + } } diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h index 705abe10b1..93b596cb02 100644 --- a/pcsx2/Counters.h +++ b/pcsx2/Counters.h @@ -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(); diff --git a/pcsx2/Elfheader.c b/pcsx2/Elfheader.c index 91d555df3e..9bc8af64c1 100644 --- a/pcsx2/Elfheader.c +++ b/pcsx2/Elfheader.c @@ -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 ); } diff --git a/pcsx2/Elfheader.h b/pcsx2/Elfheader.h index cf7dbbf017..47095061fb 100644 --- a/pcsx2/Elfheader.h +++ b/pcsx2/Elfheader.h @@ -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; diff --git a/pcsx2/Exceptions.h b/pcsx2/Exceptions.h new file mode 100644 index 0000000000..685cc3ab1f --- /dev/null +++ b/pcsx2/Exceptions.h @@ -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 + +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 diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 74f6e8c7b6..c1c07434ff 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -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; diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 9df45b33c8..8e38d09e83 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -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); diff --git a/pcsx2/IPU/IPU.c b/pcsx2/IPU/IPU.c index 3a4115c05d..8f1ddf98ad 100644 --- a/pcsx2/IPU/IPU.c +++ b/pcsx2/IPU/IPU.c @@ -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; } diff --git a/pcsx2/IPU/IPU.h b/pcsx2/IPU/IPU.h index 50a4e9d640..74f5923777 100644 --- a/pcsx2/IPU/IPU.h +++ b/pcsx2/IPU/IPU.h @@ -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); diff --git a/pcsx2/Interpreter.c b/pcsx2/Interpreter.c index f98fd17b8a..f3e40dd487 100644 --- a/pcsx2/Interpreter.c +++ b/pcsx2/Interpreter.c @@ -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])); diff --git a/pcsx2/Linux/GtkGui.cpp b/pcsx2/Linux/GtkGui.cpp index 517bca74bc..0c64790e66 100644 --- a/pcsx2/Linux/GtkGui.cpp +++ b/pcsx2/Linux/GtkGui.cpp @@ -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(); diff --git a/pcsx2/Linux/LnxConsole.cpp b/pcsx2/Linux/LnxConsole.cpp index 68f29864ba..3cf463844a 100644 --- a/pcsx2/Linux/LnxConsole.cpp +++ b/pcsx2/Linux/LnxConsole.cpp @@ -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; + } } diff --git a/pcsx2/MMI.c b/pcsx2/MMI.c index 37b910087c..8169a3ce50 100644 --- a/pcsx2/MMI.c +++ b/pcsx2/MMI.c @@ -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********************************* diff --git a/pcsx2/Memory.c b/pcsx2/Memory.c index 20211fb6d2..b43875a18d 100644 --- a/pcsx2/Memory.c +++ b/pcsx2/Memory.c @@ -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 __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 __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 __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 __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 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 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 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 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 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; diff --git a/pcsx2/Misc.c b/pcsx2/Misc.c index d1a10a43bd..bac6188ac8 100644 --- a/pcsx2/Misc.c +++ b/pcsx2/Misc.c @@ -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. diff --git a/pcsx2/Misc.h b/pcsx2/Misc.h index c292a19ac6..bf028cd062 100644 --- a/pcsx2/Misc.h +++ b/pcsx2/Misc.h @@ -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 diff --git a/pcsx2/Patch.c b/pcsx2/Patch.c index ac0ef34ced..397ea8cbdb 100644 --- a/pcsx2/Patch.c +++ b/pcsx2/Patch.c @@ -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; diff --git a/pcsx2/Plugins.c b/pcsx2/Plugins.c index d57e1d3c5f..e2b9faff41 100644 --- a/pcsx2/Plugins.c +++ b/pcsx2/Plugins.c @@ -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; } diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index 4051c765c6..c6764f5f2c 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -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__ */ diff --git a/pcsx2/PsxBios.c b/pcsx2/PsxBios.c index 965da0c214..ac251a8e3d 100644 --- a/pcsx2/PsxBios.c +++ b/pcsx2/PsxBios.c @@ -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; } diff --git a/pcsx2/PsxCounters.c b/pcsx2/PsxCounters.c index fcca7b1a53..8c8cad57ee 100644 --- a/pcsx2/PsxCounters.c +++ b/pcsx2/PsxCounters.c @@ -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 } diff --git a/pcsx2/PsxCounters.h b/pcsx2/PsxCounters.h index 831905ab82..4dc4540958 100644 --- a/pcsx2/PsxCounters.h +++ b/pcsx2/PsxCounters.h @@ -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(); diff --git a/pcsx2/PsxInterpreter.c b/pcsx2/PsxInterpreter.c index 509a6d67d1..80ff6ba0bf 100644 --- a/pcsx2/PsxInterpreter.c +++ b/pcsx2/PsxInterpreter.c @@ -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)) diff --git a/pcsx2/PsxMem.c b/pcsx2/PsxMem.c index 06997fcb46..649b912959 100644 --- a/pcsx2/PsxMem.c +++ b/pcsx2/PsxMem.c @@ -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) { diff --git a/pcsx2/PsxSio2.c b/pcsx2/PsxSio2.c index 23bc88fde2..8e574b01ac 100644 --- a/pcsx2/PsxSio2.c +++ b/pcsx2/PsxSio2.c @@ -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); } diff --git a/pcsx2/PsxSio2.h b/pcsx2/PsxSio2.h index 9bc7c1dfc2..34f9e8f388 100644 --- a/pcsx2/PsxSio2.h +++ b/pcsx2/PsxSio2.h @@ -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__ */ diff --git a/pcsx2/R3000A.c b/pcsx2/R3000A.c index beb330653a..aa493ba2ea 100644 --- a/pcsx2/R3000A.c +++ b/pcsx2/R3000A.c @@ -273,14 +273,3 @@ void psxExecuteBios() { */ } -void psxRestartCPU() -{ - psxCpu->Shutdown(); - psxCpu = CHECK_EEREC ? &psxRec : &psxInt; - - if (psxCpu->Init() == -1) { - SysClose(); - exit(1); - } - psxCpu->Reset(); -} diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h index 6fe8b27b3a..eb397c0f0a 100644 --- a/pcsx2/R3000A.h +++ b/pcsx2/R3000A.h @@ -211,7 +211,6 @@ void psxShutdown(); void psxException(u32 code, u32 step); void psxBranchTest(); void psxExecuteBios(); -void psxRestartCPU(); extern s32 psxNextCounter; extern u32 psxNextsCounter; diff --git a/pcsx2/R5900.c b/pcsx2/R5900.c index 843604b2e9..75a4e4c61d 100644 --- a/pcsx2/R5900.c +++ b/pcsx2/R5900.c @@ -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() { diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 9545f18835..57708ce66c 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -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); diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp new file mode 100644 index 0000000000..78cd0f9de6 --- /dev/null +++ b/pcsx2/SaveState.cpp @@ -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 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" ); +} diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h new file mode 100644 index 0000000000..61f14c40b0 --- /dev/null +++ b/pcsx2/SaveState.h @@ -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 + +// 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 + 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 \ No newline at end of file diff --git a/pcsx2/Sif.c b/pcsx2/Sif.c index 2e13f32f6d..e4102a8fd0 100644 --- a/pcsx2/Sif.c +++ b/pcsx2/Sif.c @@ -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); } diff --git a/pcsx2/Sio.c b/pcsx2/Sio.c index 8d95f8b2bf..1a5be217d1 100644 --- a/pcsx2/Sio.c +++ b/pcsx2/Sio.c @@ -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) { diff --git a/pcsx2/Sio.h b/pcsx2/Sio.h index 093029fb54..3f95643b7b 100644 --- a/pcsx2/Sio.h +++ b/pcsx2/Sio.h @@ -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); diff --git a/pcsx2/System.h b/pcsx2/System.h index 7ab7c8f242..437f01d3cb 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -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 diff --git a/pcsx2/VU0.h b/pcsx2/VU0.h index 2845f1bb77..8b0614d804 100644 --- a/pcsx2/VU0.h +++ b/pcsx2/VU0.h @@ -25,7 +25,6 @@ int vu0Init(); void vu0Reset(); void vu0ResetRegs(); -void vu0Freeze(gzFile f, int Mode); void vu0Shutdown(); void recResetVU0( void ); diff --git a/pcsx2/VU0micro.c b/pcsx2/VU0micro.c index 98e72a9e69..9d8d2628c5 100644 --- a/pcsx2/VU0micro.c +++ b/pcsx2/VU0micro.c @@ -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)); } diff --git a/pcsx2/VU1micro.c b/pcsx2/VU1micro.c index e906a062ac..21f073926a 100644 --- a/pcsx2/VU1micro.c +++ b/pcsx2/VU1micro.c @@ -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; diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h index 81cf5731c0..7cd64dc1ae 100644 --- a/pcsx2/VUmicro.h +++ b/pcsx2/VUmicro.h @@ -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); diff --git a/pcsx2/VifDma.c b/pcsx2/VifDma.c index 022908c295..6058fe40f8 100644 --- a/pcsx2/VifDma.c +++ b/pcsx2/VifDma.c @@ -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; } diff --git a/pcsx2/VifDma.h b/pcsx2/VifDma.h index 9d27244701..db80fc9343 100644 --- a/pcsx2/VifDma.h +++ b/pcsx2/VifDma.h @@ -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 diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index b409f2577b..e95af0a9ee 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -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 diff --git a/pcsx2/vtlb.h b/pcsx2/vtlb.h index 7ed7e6b462..2792702ef3 100644 --- a/pcsx2/vtlb.h +++ b/pcsx2/vtlb.h @@ -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 diff --git a/pcsx2/windows/AdvancedDlg.cpp b/pcsx2/windows/AdvancedDlg.cpp new file mode 100644 index 0000000000..e931c74938 --- /dev/null +++ b/pcsx2/windows/AdvancedDlg.cpp @@ -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 + +#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; +} diff --git a/pcsx2/windows/ConfigDlg.c b/pcsx2/windows/ConfigDlg.c index 1d20a9895f..a4ad5149fb 100644 --- a/pcsx2/windows/ConfigDlg.c +++ b/pcsx2/windows/ConfigDlg.c @@ -16,7 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include "Win32.h" + #include #include #include @@ -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(); } diff --git a/pcsx2/windows/Console.cpp b/pcsx2/windows/Console.cpp index 70ce9d307a..7d0096a143 100644 --- a/pcsx2/windows/Console.cpp +++ b/pcsx2/windows/Console.cpp @@ -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; + } } diff --git a/pcsx2/windows/CpuDlg.c b/pcsx2/windows/CpuDlg.c index d939add6e4..7b901b63eb 100644 --- a/pcsx2/windows/CpuDlg.c +++ b/pcsx2/windows/CpuDlg.c @@ -16,17 +16,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#include "Win32.h" #include -#include #include #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; } diff --git a/pcsx2/windows/Debugger.c b/pcsx2/windows/Debugger.c index 94dad7b912..022fdadc95 100644 --- a/pcsx2/windows/Debugger.c +++ b/pcsx2/windows/Debugger.c @@ -16,8 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include +#include "win32.h" #include #include #include @@ -26,7 +25,6 @@ #include "InterTables.h" #include "Debugger.h" #include "Common.h" -#include "win32.h" #include "PsxMem.h" #include "R3000A.h" diff --git a/pcsx2/windows/PatchBrowser.c b/pcsx2/windows/PatchBrowser.c index adbba29791..84b606ef45 100644 --- a/pcsx2/windows/PatchBrowser.c +++ b/pcsx2/windows/PatchBrowser.c @@ -23,10 +23,9 @@ * no interaction with emulation code ***************************/ -#include +#include "win32.h" #include #include "Common.h" -#include "win32.h" #include "resource.h" /* diff --git a/pcsx2/windows/RDebugger.c b/pcsx2/windows/RDebugger.c index a12532b666..7170853771 100644 --- a/pcsx2/windows/RDebugger.c +++ b/pcsx2/windows/RDebugger.c @@ -17,8 +17,7 @@ */ -#include -#include +#include "win32.h" #include #include #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; diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index a5e9b8ce09..c7c987a4f0 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -52,6 +52,7 @@ /> @@ -441,6 +451,7 @@ Name="VCCLCompilerTool" EnableFiberSafeOptimizations="true" PreprocessorDefinitions="NDEBUG" + SmallerTypeCheck="false" EnableEnhancedInstructionSet="0" CompileAs="2" /> @@ -496,6 +507,10 @@ RelativePath="..\AboutDlg.h" > + + @@ -552,6 +567,10 @@ RelativePath="..\WinMain.c" > + + @@ -608,6 +627,10 @@ + + @@ -640,6 +663,14 @@ RelativePath="..\..\SamplProf.h" > + + + + diff --git a/pcsx2/windows/Win32.h b/pcsx2/windows/Win32.h index 81c3fb6c74..a7efd4280c 100644 --- a/pcsx2/windows/Win32.h +++ b/pcsx2/windows/Win32.h @@ -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 #include + #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 diff --git a/pcsx2/windows/WinMain.c b/pcsx2/windows/WinMain.c index 30e8ed908c..86078b69ba 100644 --- a/pcsx2/windows/WinMain.c +++ b/pcsx2/windows/WinMain.c @@ -16,13 +16,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#define WINVER 0x0500 +#include "win32.h" -#if _WIN32_WINNT < 0x0501 -#define _WIN32_WINNT 0x0501 -#endif - -#include +#include #include #include #include @@ -37,8 +33,6 @@ #include "Common.h" #include "PsxCommon.h" -#include "win32.h" -#include "resource.h" #include "debugger.h" #include "rdebugger.h" #include "AboutDlg.h" @@ -56,10 +50,11 @@ #define COMPILEDATE __DATE__ -static int efile; -static char filename[g_MaxPath]; -static int AccBreak = 0; +static bool AccBreak = false; static unsigned int langsMax; +static bool m_ReturnToGame = false; // set to exit the RunGui message pump + +bool g_GameInProgress = false; // Set TRUE if a game is actively running. // This instance is not modified by command line overrides so // that command line plugins and stuff won't be saved into the @@ -71,9 +66,6 @@ AppData gApp; extern int g_SaveGSStream; -int needReset = 1; -int RunExe = 0; - struct _langs { TCHAR lang[256]; }; @@ -88,54 +80,94 @@ void strcatz(char *dst, char *src) { strcpy(dst + len, src); } +static MemoryAlloc* g_RecoveryState = NULL; + //2002-09-20 (Florin) BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);//forward def //------------------- -void RunExecute(int run) { +void ExecuteCpu() +{ + // This tells the WM_DELETE handler of our GUI that we don't want the + // system and plugins shut down, thanks... + if( UseGui ) + AccBreak = true; + + // ... and destroy the window. Ugly thing. + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + + g_GameInProgress = true; + Cpu->Execute(); + g_GameInProgress = false; +} + +// Runs and ELF image directly (ISO or ELF program or BIN) +// Used by Run::FromCD and such +void RunExecute( const char* elf_file ) +{ SetThreadPriority(GetCurrentThread(), Config.ThPriority); SetPriorityClass(GetCurrentProcess(), Config.ThPriority == THREAD_PRIORITY_HIGHEST ? ABOVE_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); nDisableSC = 1; - if (needReset == 1) { - if( !SysReset() ) return; - } + g_GameInProgress = false; - if( UseGui ) - AccBreak = 1; + if( !cpuReset() ) + throw std::runtime_error( "Cpu failed to initialize." ); - DestroyWindow(gApp.hWnd); - gApp.hWnd = NULL; - - if (OpenPlugins(g_TestRun.ptitle) == -1) { - CreateMainWindow(SW_SHOWNORMAL); + if (OpenPlugins(g_TestRun.ptitle) == -1) return; + + if( elf_file == NULL || elf_file[0] == 0) + { + if(g_RecoveryState != NULL) + { + try + { + memLoadingState( *g_RecoveryState ).FreezeAll(); + } + catch( std::runtime_error& ex ) + { + SysMessage( + "Gamestate recovery failed. Your game progress will be lost (sorry!)\n" + "\nError: %s\n", ex.what() ); + + // Take the user back to the GUI... + safe_delete( g_RecoveryState ); + ClosePlugins(); + return; + } + safe_delete( g_RecoveryState ); + } + else + { + // Not recovering a state, so need to execute the bios and load the ELF information. + + // Note: if the elf_file is null we use the CDVD elf file. + // But if the elf_file is an empty string then we boot the bios instead. + + cpuExecuteBios(); + char ename[g_MaxPath]; + GetPS2ElfName(ename); + loadElfFile( (elf_file == NULL) ? ename : ""); + } + } + else + { + // Custom ELF specified (not using CDVD). + // Run the BIOS and load the ELF. + + cpuExecuteBios(); + loadElfFile( elf_file ); } - if (needReset == 1) { - if(RunExe == 0) cpuExecuteBios(); - if(!efile) efile=GetPS2ElfName(filename); - loadElfFile(filename); - - RunExe = 0; - efile=0; - needReset = 0; - } + // this needs to be called for every new game! + // (note: sometimes launching games through bios will give a crc of 0) - // this needs to be called for every new game! (note: sometimes launching games through bios will give a crc of 0) if( GSsetGameCRC != NULL ) GSsetGameCRC(ElfCRC, g_ZeroGSOptions); - if (run) - { - // This makes sure the Windows Kernel is using high resolution - // timeslices for Sleep calls. - // (may not make much difference on most desktops but - // can improve performance a lot on laptops). - timeBeginPeriod( 1 ); - Cpu->Execute(); - timeEndPeriod( 1 ); - } + ExecuteCpu(); } int Slots[5] = { -1, -1, -1, -1, -1 }; @@ -151,7 +183,9 @@ void ResetMenuSlots() { } } -void UpdateMenuSlots() { +// fixme - this looks like the beginnings of a dynamic "list of valid saveslots" +// feature. Too bad it's never called and CheckState was old/dead code. +/*void UpdateMenuSlots() { char str[g_MaxPath]; int i; @@ -159,43 +193,112 @@ void UpdateMenuSlots() { sprintf_s (str, g_MaxPath, "sstates\\%8.8X.%3.3d", ElfCRC, i); Slots[i] = CheckState(str); } +}*/ + +static void States_Load( const char* file, int num=-1 ) +{ + struct stat buf; + if( stat(file, &buf ) == -1 ) + { + Console::Notice( "Saveslot %d is empty.", num ); + return; + } + + try + { + char Text[128]; + gzLoadingState joe( file ); // this'll throw an UnsupportedStateVersion. + + // Make sure the cpu and plugins are ready to be state-ified! + cpuReset(); + OpenPlugins( NULL ); + + joe.FreezeAll(); + + if( num != -1 ) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num); + else + sprintf (Text, _("*PCSX2*: Loaded State %s"), file); + + StatusSet( Text ); + } + 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; + } + + // Start emulating! + ExecuteCpu(); } -void States_Load(int num) { +static void States_Save( const char* file, int num=-1 ) +{ + try + { + char Text[128]; + gzSavingState(file).FreezeAll(); + if( num != -1 ) + sprintf( Text, _( "State saved to slot %d" ), num ); + else + sprintf( Text, _( "State saved to file: %s" ), file ); + + StatusSet( Text ); + } + 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() ); + } +} + +static void States_Load(int num) +{ char Text[g_MaxPath]; - int ret; - - efile = 0; - RunExecute(0); - - sprintf_s(Text, g_MaxPath, "sstates\\%8.8X.%3.3d", ElfCRC, num); - ret = LoadState(Text); - if (ret == 0) - sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); - else - sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); - StatusSet(Text); - - Cpu->Execute(); + SaveState::GetFilename( Text, num ); + States_Load( Text, num ); } -void States_Save(int num) { - char Text[256]; - int ret; - - - sprintf (Text, "sstates\\%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); - StatusSet(Text); - - RunExecute(1); +static void States_Save(int num) +{ + char Text[g_MaxPath]; + SaveState::GetFilename( Text, num ); + States_Save( Text, num ); } -void OnStates_LoadOther() { +void OnStates_LoadOther() +{ OPENFILENAME ofn; char szFileName[g_MaxPath]; char szFileTitle[g_MaxPath]; @@ -222,30 +325,10 @@ void OnStates_LoadOther() { ofn.lpstrDefExt = "EXE"; ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { - char Text[g_MaxPath]; - int ret; - - efile = 2; - RunExecute(0); - - ret = LoadState(szFileName); - - if (ret == 0) - sprintf_s(Text, g_MaxPath, _("*PCSX2*: Saving State %s"), szFileName); - else sprintf_s(Text, g_MaxPath, _("*PCSX2*: Error Saving State %s"), szFileName); - StatusSet(Text); - - Cpu->Execute(); - } + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) + States_Load( szFileName ); } -void OnStates_Save1() { States_Save(0); } -void OnStates_Save2() { States_Save(1); } -void OnStates_Save3() { States_Save(2); } -void OnStates_Save4() { States_Save(3); } -void OnStates_Save5() { States_Save(4); } - const char* g_pRunGSState = NULL; void OnStates_SaveOther() { @@ -275,18 +358,8 @@ void OnStates_SaveOther() { ofn.lpstrDefExt = "EXE"; ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { - char Text[g_MaxPath]; - int ret; - - ret = SaveState(szFileName); - if (ret == 0) - sprintf_s(Text, g_MaxPath, _("*PCSX2*: Loaded State %s"), szFileName); - else sprintf_s(Text, g_MaxPath, _("*PCSX2*: Error Loading State %s"), szFileName); - StatusSet(Text); - - RunExecute(1); - } + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) + States_Save( szFileName ); } @@ -452,7 +525,7 @@ static int ParseCommandLine( int tokenCount, TCHAR *const *const tokens ) } else if( CmdSwitchIs( "efile" ) ) { - g_TestRun.efile = atoi( param ); + g_TestRun.efile = !!atoi( param ); } else if( CmdSwitchIs( "loadgs" ) ) { g_pRunGSState = param; @@ -493,6 +566,23 @@ static int ParseCommandLine( int tokenCount, TCHAR *const *const tokens ) return 0; } +static void WinClose() +{ + // Don't check Config.Profiler here -- the Profiler will know if it's running or not. + ProfilerTerm(); + timeEndPeriod( 1 ); + + SysClose(); + ReleasePlugins(); + Console::Close(); + +#ifdef PCSX2_VIRTUAL_MEM + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); +#endif + + exit(0); +} + BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { @@ -603,8 +693,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine { Console::Open(); - if( lpCmdLine == NULL || *lpCmdLine == 0 ) - Console::WriteLn("-help to see arguments"); + //if( lpCmdLine == NULL || *lpCmdLine == 0 ) + // Console::WriteLn("-help to see arguments"); } // Load the command line overrides for plugins: @@ -614,17 +704,17 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if( g_TestRun.pgsdll ) { _tcscpy_s( Config.GS, g_MaxPath, g_TestRun.pgsdll ); - Console::FormatLn( "* GS plugin override: \n\t%s\n", Config.GS ); + Console::Notice( "* GS plugin override: \n\t%s\n", Config.GS ); } if( g_TestRun.pcdvddll ) { _tcscpy_s( Config.CDVD, g_MaxPath, g_TestRun.pcdvddll ); - Console::FormatLn( "* CDVD plugin override: \n\t%s\n", Config.CDVD ); + Console::Notice( "* CDVD plugin override: \n\t%s\n", Config.CDVD ); } if( g_TestRun.pspudll ) { _tcscpy_s( Config.SPU2, g_MaxPath, g_TestRun.pspudll ); - Console::FormatLn( "* SPU2 plugin override: \n\t%s\n", Config.SPU2 ); + Console::Notice( "* SPU2 plugin override: \n\t%s\n", Config.SPU2 ); } // [TODO] : Add the other plugin overrides here... @@ -634,6 +724,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine ProfilerInit(); #endif + // This makes sure the Windows Kernel is using high resolution + // timeslices for Sleep calls. + // (may not make much difference on most desktops but can improve performance + // a lot on laptops). + timeBeginPeriod( 1 ); + InitCPUTicks(); if (SysInit() == -1) return 1; @@ -641,17 +737,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if( g_TestRun.enabled || g_TestRun.ptitle != NULL ) { // run without ui UseGui = 0; - _snprintf(filename, sizeof(filename), "%s", g_TestRun.ptitle); - needReset = 1; - efile = g_TestRun.efile; - RunExecute(1); - SysClose(); + SysReset(); + RunExecute( g_TestRun.efile ? g_TestRun.ptitle : NULL ); + WinClose(); return 0; // success! } if( g_pRunGSState ) { LoadGSState(g_pRunGSState); - SysClose(); + WinClose(); return 0; } #endif @@ -661,21 +755,25 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if( Config.PsxOut ) { // output the help commands - Console::WriteLn("\tF1 - save state"); - Console::WriteLn("\t(Shift +) F2 - cycle states"); - Console::WriteLn("\tF3 - load state"); + Console::SetColor( Console::Color_White ); - DevCon::WriteLn("\tF10 - dump performance counters"); - DevCon::WriteLn("\tF11 - save GS state"); - DevCon::WriteLn("\tF12 - dump hardware registers"); + Console::WriteLn( "Hotkeys:" ); + + Console::WriteLn( + "\tF1 - save state\n" + "\t(Shift +) F2 - cycle states\n" + "\tF3 - load state" + ); + + DevCon::WriteLn( + "\tF10 - dump performance counters\n" + "\tF11 - save GS state\n" + "\tF12 - dump hardware registers" + ); + Console::ClearColor(); } LoadPatch("default"); - -// needReset = 1; -// efile = 0; -// RunExecute(1); - RunGui(); } @@ -683,19 +781,18 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine { } - #ifdef PCSX2_VIRTUAL_MEM + // Note : Because of how the GUI and recompiler function, this area of + // the code is effectively unreachable. Program termination is handled + // by a call to WinClose instead. (above) - VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); -#endif - - // Don't check Config.Profiler here -- the Profiler will know if it's running or not. - ProfilerTerm(); return 0; } + void RunGui() { MSG msg; + SetFocus( gApp.hWnd ); for (;;) { if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); @@ -706,13 +803,10 @@ void RunGui() { } } -static int m_ReturnToGame = 0; // set to 1 to exit the RunGui message pump -static int m_GameInProgress = 0; // if set to 1, Run->Execute will return instead of starting a new cpu->Execute session. - void RunGuiAndReturn() { MSG msg; - m_ReturnToGame = 0; + m_ReturnToGame = false; while( !m_ReturnToGame ) { if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); @@ -721,13 +815,91 @@ void RunGuiAndReturn() { Sleep(10); } + + // re-init plugins before returning execution: + + OpenPlugins( NULL ); + AccBreak = true; + DestroyWindow(gApp.hWnd); } +BOOL Open_File_Proc( std::string& outstr ) +{ + OPENFILENAME ofn; + char szFileName[ g_MaxPath ]; + char szFileTitle[ g_MaxPath ]; + char * filter = "ELF Files (*.ELF)\0*.ELF\0ALL Files (*.*)\0*.*\0"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = g_MaxPath; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = g_MaxPath; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "ELF"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName(&ofn)) { + struct stat buf; + + if (stat(szFileName, &buf) != 0) { + return FALSE; + } + + outstr.assign( szFileName ); + return TRUE; + } + + return FALSE; +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + SetWindowText(hDlg, _("Program arguments")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Button_SetText(GetDlgItem(hDlg, IDCANCEL), _("Cancel")); + Static_SetText(GetDlgItem(hDlg, IDC_TEXT), _("Fill in the command line arguments for opened program:")); + Static_SetText(GetDlgItem(hDlg, IDC_TIP), _("Tip: If you don't know what to write\nleave it blank")); + + SetDlgItemText(hDlg, IDC_CMDLINE, args); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + char tmp[256]; + + GetDlgItemText(hDlg, IDC_CMDLINE, tmp, 256); + + strcpy_s(args, 256, tmp); + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} static int shiftkey = 0; void CALLBACK KeyEvent(keyEvent* ev) { - if (ev == NULL) return; if (ev->evt == KEYRELEASE) { switch (ev->key) { @@ -745,18 +917,24 @@ void CALLBACK KeyEvent(keyEvent* ev) switch (ev->key) { case VK_SHIFT: shiftkey = 1; break; - case VK_F1: ProcessFKeys(1, shiftkey); break; - case VK_F2: ProcessFKeys(2, shiftkey); break; - case VK_F3: ProcessFKeys(3, shiftkey); break; - case VK_F4: ProcessFKeys(4, shiftkey); break; - case VK_F5: ProcessFKeys(5, shiftkey); break; - case VK_F6: ProcessFKeys(6, shiftkey); break; - case VK_F7: ProcessFKeys(7, shiftkey); break; - case VK_F8: ProcessFKeys(8, shiftkey); break; - case VK_F9: ProcessFKeys(9, shiftkey); break; - case VK_F10: ProcessFKeys(10, shiftkey); break; - case VK_F11: ProcessFKeys(11, shiftkey); break; - case VK_F12: ProcessFKeys(12, shiftkey); break; + + case VK_F1: case VK_F2: case VK_F3: case VK_F4: + case VK_F5: case VK_F6: case VK_F7: case VK_F8: + case VK_F9: case VK_F10: case VK_F11: case VK_F12: + try + { + ProcessFKeys(ev->key-VK_F1 + 1, shiftkey); + } + catch( Exception::CpuStateShutdown& ) + { + // Woops! Something was unrecoverable. Bummer. + // Let's give the user a RunGui! + + g_GameInProgress = false; + RunGui(); // ah the beauty of perpetual stack recursion! (air) + } + break; + /*case VK_NUMPAD0: Config.Hacks ^= 2; if (Config.Hacks & 2) {SysPrintf( "Overflow Check OFF\n" );} else {SysPrintf( "Overflow Check ON\n" );} @@ -773,23 +951,19 @@ void CALLBACK KeyEvent(keyEvent* ev) if (CHECK_ESCAPE_HACK) { PostMessage(GetForegroundWindow(), WM_CLOSE, 0, 0); - ClosePlugins(); - //SysClose(); - exit(0); + WinClose(); } else { ClosePlugins(); if( !UseGui ) { // not using GUI and user just quit, so exit - exit(0); + WinClose(); } CreateMainWindow(SW_SHOWNORMAL); - m_GameInProgress = 1; nDisableSC = 0; RunGuiAndReturn(); - m_GameInProgress = 0; } break; @@ -823,6 +997,7 @@ BOOL APIENTRY LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { SaveConfig(); EndDialog(hDlg, TRUE); + return FALSE; } return TRUE; } @@ -832,30 +1007,6 @@ BOOL APIENTRY LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { #endif -BOOL APIENTRY AdvancedProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - - switch (message) { - case WM_INITDIALOG: - return TRUE; - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK) { - SaveConfig(); - EndDialog(hDlg, TRUE); - } - else if (LOWORD(wParam) == IDCANCEL) { - EndDialog(hDlg, FALSE); - } - else if (LOWORD(wParam) == IDC_ADVRESET) { - CheckDlgButton(hDlg, IDC_REGCACHING, FALSE); - CheckDlgButton(hDlg, IDC_SPU2HACK, FALSE); - } - else return TRUE; - } - - return FALSE; -} - BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { @@ -863,21 +1014,31 @@ BOOL APIENTRY GameFixes(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) if(Config.GameFixes & 0x2) CheckDlgButton(hDlg, IDC_GAMEFIX2, TRUE); if(Config.GameFixes & 0x4) CheckDlgButton(hDlg, IDC_GAMEFIX3, TRUE); if(Config.GameFixes & 0x8) CheckDlgButton(hDlg, IDC_GAMEFIX4, TRUE); - return TRUE; + return TRUE; case WM_COMMAND: - if (LOWORD(wParam) == IDOK) { - Config.GameFixes = 0; - Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x2 : 0; - Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0; - Config.GameFixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x8 : 0; - SaveConfig(); + if (LOWORD(wParam) == IDOK) + { + uint newfixes = 0; + newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX2) ? 0x2 : 0; + newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX3) ? 0x4 : 0; + newfixes |= IsDlgButtonChecked(hDlg, IDC_GAMEFIX4) ? 0x8 : 0; + EndDialog(hDlg, TRUE); + + if( newfixes != Config.GameFixes ) + { + Config.GameFixes = newfixes; + SysRestorableReset(); + SaveConfig(); + } + return FALSE; } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, TRUE); + return FALSE; } - return TRUE; + return TRUE; } return FALSE; @@ -894,169 +1055,32 @@ BOOL APIENTRY HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; case WM_COMMAND: - switch (LOWORD(wParam)) { + switch (LOWORD(wParam)) + { case IDOK: - Config.Hacks = 0; - Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK) ? 0x1 : 0; - Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK2) ? 0x10 : 0; - Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK3) ? 0x20 : 0; - Config.Hacks |= IsDlgButtonChecked(hDlg, IDC_ESCHACK) ? 0x400 : 0; - SaveConfig(); + { + uint newhacks = 0; + newhacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK) ? 0x1 : 0; + newhacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK2) ? 0x10 : 0; + newhacks |= IsDlgButtonChecked(hDlg, IDC_SYNCHACK3) ? 0x20 : 0; + newhacks |= IsDlgButtonChecked(hDlg, IDC_ESCHACK) ? 0x400 : 0; + EndDialog(hDlg, TRUE); - break; + + if( newhacks != Config.Hacks ) + { + SysRestorableReset(); + Config.Hacks = newhacks; + SaveConfig(); + } + } + return FALSE; case IDCANCEL: EndDialog(hDlg, FALSE); - break; - - default: return TRUE; + return FALSE; } - } - - return FALSE; -} - -BOOL APIENTRY AdvancedOptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_INITDIALOG: - 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 + ((Config.eeOptions & 0x2) ? 2 : (Config.eeOptions & 0x1))); - - if (Config.vuOptions & 0x4) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 3); - else if (Config.vuOptions & 0x2) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 2); - else if (Config.vuOptions & 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); - - 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: - - Config.sseMXCSR &= 0x1fbf; - Config.sseVUMXCSR &= 0x1fbf; - Config.eeOptions = 0x0000; - Config.vuOptions = 0x0000; - - 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 - - Config.eeOptions |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE0) ? 0x0 : 0; - Config.eeOptions |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE1) ? 0x1 : 0; - Config.eeOptions |= IsDlgButtonChecked(hDlg, IDC_EE_CLAMPMODE2) ? 0x3 : 0; - - Config.vuOptions |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE0) ? 0x0 : 0; - Config.vuOptions |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE1) ? 0x1 : 0; - Config.vuOptions |= IsDlgButtonChecked(hDlg, IDC_VU_CLAMPMODE2) ? 0x3 : 0; - Config.vuOptions |= 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 - - SetCPUState(Config.sseMXCSR, Config.sseVUMXCSR); - SaveConfig(); - - EndDialog(hDlg, TRUE); - break; - - case IDCANCEL: - - EndDialog(hDlg, TRUE); - break; - - case IDDEFAULT: - - Config.sseMXCSR = DEFAULT_sseMXCSR; - Config.sseVUMXCSR = DEFAULT_sseVUMXCSR; - Config.eeOptions = DEFAULT_eeOptions; - Config.vuOptions = DEFAULT_vuOptions; - - // SSE1 cpus do not support Denormals Are Zero flag. - if( !cpucaps.hasStreamingSIMD2Extensions ) { - Config.sseMXCSR &= ~0x0040; - Config.sseVUMXCSR &= ~0x0040; - } - - 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 + ((Config.eeOptions & 0x2) ? 2 : (Config.eeOptions & 0x1))); - - if (Config.vuOptions & 0x4) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 3); - else if (Config.vuOptions & 0x2) CheckRadioButton(hDlg, IDC_VU_CLAMPMODE0, IDC_VU_CLAMPMODE3, IDC_VU_CLAMPMODE0 + 2); - else if (Config.vuOptions & 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); - - 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 TRUE; } return FALSE; @@ -1064,34 +1088,34 @@ BOOL APIENTRY AdvancedOptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM HBITMAP hbitmap_background;//the background image -LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - int remoteDebugBios=0; - - switch (msg) { +LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { case WM_CREATE: return TRUE; case WM_PAINT: - { + { BITMAP bm; PAINTSTRUCT ps; - HDC hdc = BeginPaint(gApp.hWnd, &ps); + HDC hdc = BeginPaint(gApp.hWnd, &ps); - HDC hdcMem = CreateCompatibleDC(hdc); - HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbitmap_background); + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbitmap_background); - GetObject(hbitmap_background, sizeof(bm), &bm); -// BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); + GetObject(hbitmap_background, sizeof(bm), &bm); + // BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left+1, ps.rcPaint.bottom-ps.rcPaint.top+1, hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); - SelectObject(hdcMem, hbmOld); - DeleteDC(hdcMem); - EndPaint(gApp.hWnd, &ps); - } + SelectObject(hdcMem, hbmOld); + DeleteDC(hdcMem); + EndPaint(gApp.hWnd, &ps); + } return TRUE; case WM_COMMAND: @@ -1099,83 +1123,71 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { { case ID_GAMEFIXES: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_GAMEFIXES), hWnd, (DLGPROC)GameFixes); - return TRUE; + return FALSE; case ID_HACKS: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_HACKS), hWnd, (DLGPROC)HacksProc); - return TRUE; + return FALSE; case ID_ADVANCED_OPTIONS: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_ADVANCED_OPTIONS), hWnd, (DLGPROC)AdvancedOptionsProc); - return TRUE; + return FALSE; case ID_CHEAT_FINDER_SHOW: ShowFinder(pInstance,hWnd); - return TRUE; + return FALSE; case ID_CHEAT_BROWSER_SHOW: ShowCheats(pInstance,hWnd); - return TRUE; + return FALSE; case ID_FILE_EXIT: - SysClose(); - PostQuitMessage(0); - exit(0); - return TRUE; + DestroyWindow( hWnd ); + // WM_DESTROY will do the shutdown work for us. + return FALSE; case ID_FILEOPEN: - if (Open_File_Proc(filename) == FALSE) return TRUE; - - needReset = 1; - efile = 1; - RunExecute(1); - return TRUE; + { + std::string outstr; + if( Open_File_Proc( outstr ) ) + RunExecute( outstr.c_str() ); + } + return FALSE; case ID_RUN_EXECUTE: - if(needReset == 1) - { - RunExe = 1; - m_ReturnToGame = 0; - m_GameInProgress = 0; - } - else if( m_GameInProgress ) + if( g_GameInProgress ) m_ReturnToGame = 1; - - efile = 0; - RunExecute( !m_ReturnToGame ); - - return TRUE; + else + RunExecute( "" ); // boots bios if no savestate is to be recovered + return FALSE; case ID_FILE_RUNCD: - needReset = 1; - efile = 0; - RunExecute(1); - - return TRUE; + safe_free( g_RecoveryState ); + RunExecute( NULL ); + return FALSE; case ID_RUN_RESET: - ResetPlugins(); - needReset = 1; - efile = 0; - return TRUE; + safe_free( g_RecoveryState ); + SysReset(); + return FALSE; //2002-09-20 (Florin) case ID_RUN_CMDLINE: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_CMDLINE), hWnd, (DLGPROC)CmdlineProc); - return TRUE; + return FALSE; //------------------- case ID_PATCHBROWSER: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_PATCHBROWSER), hWnd, (DLGPROC)PatchBDlgProc); - return TRUE; + return FALSE; case ID_CONFIG_CONFIGURE: Pcsx2Configure(hWnd); ReleasePlugins(); LoadPlugins(); - return TRUE; + return FALSE; case ID_CONFIG_GRAPHICS: if (GSconfigure) GSconfigure(); - return TRUE; + return FALSE; case ID_CONFIG_CONTROLLERS: @@ -1183,119 +1195,124 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (PAD2configure) { if (strcmp(Config.PAD1, Config.PAD2))PAD2configure(); } - return TRUE; + return FALSE; case ID_CONFIG_SOUND: if (SPU2configure) SPU2configure(); - return TRUE; + return FALSE; case ID_CONFIG_CDVDROM: if (CDVDconfigure) CDVDconfigure(); - return TRUE; + return FALSE; case ID_CONFIG_DEV9: if (DEV9configure) DEV9configure(); - return TRUE; + return FALSE; case ID_CONFIG_USB: if (USBconfigure) USBconfigure(); - return TRUE; + return FALSE; case ID_CONFIG_FW: if (FWconfigure) FWconfigure(); - return TRUE; + return FALSE; - case ID_FILE_STATES_LOAD_SLOT1: States_Load(0); return TRUE; - case ID_FILE_STATES_LOAD_SLOT2: States_Load(1); return TRUE; - case ID_FILE_STATES_LOAD_SLOT3: States_Load(2); return TRUE; - case ID_FILE_STATES_LOAD_SLOT4: States_Load(3); return TRUE; - case ID_FILE_STATES_LOAD_SLOT5: States_Load(4); return TRUE; - case ID_FILE_STATES_LOAD_OTHER: OnStates_LoadOther(); return TRUE; + case ID_FILE_STATES_LOAD_SLOT1: + case ID_FILE_STATES_LOAD_SLOT2: + case ID_FILE_STATES_LOAD_SLOT3: + case ID_FILE_STATES_LOAD_SLOT4: + case ID_FILE_STATES_LOAD_SLOT5: + States_Load(LOWORD(wParam) - ID_FILE_STATES_LOAD_SLOT1); + return FALSE; - case ID_FILE_STATES_SAVE_SLOT1: States_Save(0); return TRUE; - case ID_FILE_STATES_SAVE_SLOT2: States_Save(1); return TRUE; - case ID_FILE_STATES_SAVE_SLOT3: States_Save(2); return TRUE; - case ID_FILE_STATES_SAVE_SLOT4: States_Save(3); return TRUE; - case ID_FILE_STATES_SAVE_SLOT5: States_Save(4); return TRUE; - case ID_FILE_STATES_SAVE_OTHER: OnStates_SaveOther(); return TRUE; + case ID_FILE_STATES_LOAD_OTHER: + OnStates_LoadOther(); + return FALSE; + + case ID_FILE_STATES_SAVE_SLOT1: + case ID_FILE_STATES_SAVE_SLOT2: + case ID_FILE_STATES_SAVE_SLOT3: + case ID_FILE_STATES_SAVE_SLOT4: + case ID_FILE_STATES_SAVE_SLOT5: + States_Load(LOWORD(wParam) - ID_FILE_STATES_SAVE_SLOT1); + return FALSE; + + case ID_FILE_STATES_SAVE_OTHER: + OnStates_SaveOther(); + return FALSE; case ID_CONFIG_CPU: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_CPUDLG), hWnd, (DLGPROC)CpuDlgProc); - return TRUE; - - case ID_CONFIG_ADVANCED: - DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_ADVANCED), hWnd, (DLGPROC)AdvancedProc); - return TRUE; + return FALSE; #ifdef PCSX2_DEVBUILD case ID_DEBUG_ENTERDEBUGGER: - RunExecute(0); DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DEBUG), NULL, (DLGPROC)DebuggerProc); - - CreateMainWindow(SW_SHOWNORMAL); - RunGui(); - return TRUE; + return FALSE; case ID_DEBUG_REMOTEDEBUGGING: //read debugging params if (Config.Options & PCSX2_EEREC){ MessageBox(hWnd, _("Nah, you have to be in\nInterpreter Mode to debug"), 0, 0); - return FALSE; - } else { + } else + { + int remoteDebugBios=0; remoteDebugBios=DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_RDEBUGPARAMS), NULL, (DLGPROC)RemoteDebuggerParamsProc); - if (remoteDebugBios){ - RunExecute(0); + if (remoteDebugBios) + { + cpuReset(); + cpuExecuteBios(); DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_RDEBUG), NULL, (DLGPROC)RemoteDebuggerProc); CreateMainWindow(SW_SHOWNORMAL); RunGui(); } } - return TRUE; + return FALSE; case ID_DEBUG_MEMORY_DUMP: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MEMORY), hWnd, (DLGPROC)MemoryProc); - return TRUE; + return FALSE; case ID_DEBUG_LOGGING: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_LOGGING), hWnd, (DLGPROC)LogProc); - return TRUE; + return FALSE; #endif case ID_HELP_ABOUT: DialogBox(gApp.hInstance, MAKEINTRESOURCE(ABOUT_DIALOG), hWnd, (DLGPROC)AboutDlgProc); - return TRUE; + return FALSE; case ID_HELP_HELP: //system("help\\index.html"); system("compat_list\\compat_list.html"); - return TRUE; + return FALSE; case ID_CONFIG_MEMCARDS: DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MCDCONF), hWnd, (DLGPROC)ConfigureMcdsDlgProc); SaveConfig(); - return TRUE; + return FALSE; case ID_PROCESSLOW: Config.ThPriority = THREAD_PRIORITY_LOWEST; SaveConfig(); CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_UNCHECKED); CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_UNCHECKED); - return TRUE; + return FALSE; case ID_PROCESSNORMAL: Config.ThPriority = THREAD_PRIORITY_NORMAL; SaveConfig(); CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_UNCHECKED); CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_UNCHECKED); - return TRUE; + return FALSE; case ID_PROCESSHIGH: Config.ThPriority = THREAD_PRIORITY_HIGHEST; SaveConfig(); CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_UNCHECKED); CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_UNCHECKED); - return TRUE; + return FALSE; case ID_CONSOLE: Config.PsxOut = !Config.PsxOut; @@ -1310,14 +1327,14 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { Console::Open(); } SaveConfig(); - return TRUE; + return FALSE; case ID_PATCHES: Config.Patch = !Config.Patch; CheckMenuItem(gApp.hMenu,ID_PATCHES,Config.Patch ? MF_CHECKED : MF_UNCHECKED); SaveConfig(); - return TRUE; + return FALSE; #ifndef _DEBUG case ID_PROFILER: @@ -1333,46 +1350,44 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { ProfilerTerm(); } SaveConfig(); - return TRUE; + return FALSE; #endif default: if (LOWORD(wParam) >= ID_LANGS && LOWORD(wParam) <= (ID_LANGS + langsMax)) { - AccBreak = 1; + AccBreak = true; DestroyWindow(gApp.hWnd); ChangeLanguage(langs[LOWORD(wParam) - ID_LANGS].lang); CreateMainWindow(SW_NORMAL); return TRUE; } } - break; + return TRUE; + case WM_DESTROY: - if (!AccBreak) { - SysClose(); - DeleteObject(hbitmap_background); - PostQuitMessage(0); - exit(0); - } else AccBreak = 0; - return TRUE; + if (!AccBreak) + { + // [TODO] : Check if a game is active in the emulator and ask the user + // before closing! + DeleteObject(hbitmap_background); + WinClose(); + + } else AccBreak = false; + return FALSE; case WM_SYSCOMMAND: if( nDisableSC && (wParam== SC_SCREENSAVE || wParam == SC_MONITORPOWER) ) { return FALSE; } - else - return DefWindowProc(hWnd, msg, wParam, lParam); - break; + break; case WM_QUIT: - if (Config.PsxOut) Console::Close(); - exit(0); - break; - - default: - return DefWindowProc(hWnd, msg, wParam, lParam); + if (Config.PsxOut) + Console::Close(); + return TRUE; } - return FALSE; + return DefWindowProc(hWnd, msg, wParam, lParam); } #define _ADDSUBMENU(menu, menun, string) \ @@ -1431,17 +1446,17 @@ void CreateMainMenu() { ADDSUBMENUS(1, 3, _("&Save")); ADDSUBMENUS(1, 2, _("&Load")); ADDMENUITEM(2, _("&Other..."), ID_FILE_STATES_LOAD_OTHER); - ADDMENUITEM(2, _("Slot &5"), ID_FILE_STATES_LOAD_SLOT5); - ADDMENUITEM(2, _("Slot &4"), ID_FILE_STATES_LOAD_SLOT4); - ADDMENUITEM(2, _("Slot &3"), ID_FILE_STATES_LOAD_SLOT3); - ADDMENUITEM(2, _("Slot &2"), ID_FILE_STATES_LOAD_SLOT2); - ADDMENUITEM(2, _("Slot &1"), ID_FILE_STATES_LOAD_SLOT1); + ADDMENUITEM(2, _("Slot &4"), ID_FILE_STATES_LOAD_SLOT5); + ADDMENUITEM(2, _("Slot &3"), ID_FILE_STATES_LOAD_SLOT4); + ADDMENUITEM(2, _("Slot &2"), ID_FILE_STATES_LOAD_SLOT3); + ADDMENUITEM(2, _("Slot &1"), ID_FILE_STATES_LOAD_SLOT2); + ADDMENUITEM(2, _("Slot &0"), ID_FILE_STATES_LOAD_SLOT1); ADDMENUITEM(3, _("&Other..."), ID_FILE_STATES_SAVE_OTHER); - ADDMENUITEM(3, _("Slot &5"), ID_FILE_STATES_SAVE_SLOT5); - ADDMENUITEM(3, _("Slot &4"), ID_FILE_STATES_SAVE_SLOT4); - ADDMENUITEM(3, _("Slot &3"), ID_FILE_STATES_SAVE_SLOT3); - ADDMENUITEM(3, _("Slot &2"), ID_FILE_STATES_SAVE_SLOT2); - ADDMENUITEM(3, _("Slot &1"), ID_FILE_STATES_SAVE_SLOT1); + ADDMENUITEM(3, _("Slot &4"), ID_FILE_STATES_SAVE_SLOT5); + ADDMENUITEM(3, _("Slot &3"), ID_FILE_STATES_SAVE_SLOT4); + ADDMENUITEM(3, _("Slot &2"), ID_FILE_STATES_SAVE_SLOT3); + ADDMENUITEM(3, _("Slot &1"), ID_FILE_STATES_SAVE_SLOT2); + ADDMENUITEM(3, _("Slot &0"), ID_FILE_STATES_SAVE_SLOT1); ADDSUBMENU(0, _("&Run")); @@ -1555,10 +1570,12 @@ void CreateMainWindow(int nCmdShow) { #endif } - hWnd = CreateWindow("PCSX2 Main", - buf, WS_OVERLAPPED | WS_SYSMENU, - 20, 20, 320, 240, NULL, NULL, - gApp.hInstance, NULL); + hWnd = CreateWindow( + "PCSX2 Main", + buf, WS_OVERLAPPED | WS_SYSMENU, + 20, 20, 320, 240, NULL, NULL, + gApp.hInstance, NULL + ); gApp.hWnd = hWnd; ResetMenuSlots(); @@ -1590,77 +1607,6 @@ void CreateMainWindow(int nCmdShow) { SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); } -BOOL Open_File_Proc(char * filename) { - OPENFILENAME ofn; - char szFileName[ g_MaxPath ]; - char szFileTitle[ g_MaxPath ]; - char * filter = "ELF Files (*.ELF)\0*.ELF\0ALL Files (*.*)\0*.*\0"; - - memset( &szFileName, 0, sizeof( szFileName ) ); - memset( &szFileTitle, 0, sizeof( szFileTitle ) ); - - ofn.lStructSize = sizeof( OPENFILENAME ); - ofn.hwndOwner = gApp.hWnd; - ofn.lpstrFilter = filter; - ofn.lpstrCustomFilter = NULL; - ofn.nMaxCustFilter = 0; - ofn.nFilterIndex = 1; - ofn.lpstrFile = szFileName; - ofn.nMaxFile = g_MaxPath; - ofn.lpstrInitialDir = NULL; - ofn.lpstrFileTitle = szFileTitle; - ofn.nMaxFileTitle = g_MaxPath; - ofn.lpstrTitle = NULL; - ofn.lpstrDefExt = "ELF"; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - - if (GetOpenFileName(&ofn)) { - struct stat buf; - - if (stat(szFileName, &buf) != 0) { - return FALSE; - } - - strcpy(filename, szFileName); - return TRUE; - } - - return FALSE; -} -//2002-09-20 (Florin) -BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_INITDIALOG: - SetWindowText(hDlg, _("Program arguments")); - - Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); - Button_SetText(GetDlgItem(hDlg, IDCANCEL), _("Cancel")); - Static_SetText(GetDlgItem(hDlg, IDC_TEXT), _("Fill in the command line arguments for opened program:")); - Static_SetText(GetDlgItem(hDlg, IDC_TIP), _("Tip: If you don't know what to write\nleave it blank")); - - SetDlgItemText(hDlg, IDC_CMDLINE, args); - return TRUE; - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK) - { - char tmp[256]; - - GetDlgItemText(hDlg, IDC_CMDLINE, tmp, 256); - - strcpy_s(args, 256, tmp); - - EndDialog(hDlg, TRUE); - } else if (LOWORD(wParam) == IDCANCEL) { - EndDialog(hDlg, TRUE); - } - return TRUE; - } - - return FALSE; -} WIN32_FIND_DATA lFindData; HANDLE lFind; @@ -1699,75 +1645,95 @@ void CloseLanguages() { } void ChangeLanguage(char *lang) { - strcpy(Config.Lang, lang); + strcpy_s(Config.Lang, lang); SaveConfig(); LoadConfig(); } //------------------- -static int sinit=0; +static bool sinit=false; + +int SysInit() +{ + if( sinit ) + SysClose(); -int SysInit() { CreateDirectory(MEMCARDS_DIR, NULL); CreateDirectory(SSTATES_DIR, NULL); - CreateDirectory(LOGS_DIR, NULL); - - if( IsDevBuild && g_TestRun.plogname != NULL ) + if( IsDevBuild && emuLog == NULL && g_TestRun.plogname != NULL ) emuLog = fopen(g_TestRun.plogname, "w"); if( emuLog == NULL ) emuLog = fopen(LOGS_DIR "\\emuLog.txt","w"); - if (cpuInit() == -1) return -1; + if( !cpuInit() ) return -1; while (LoadPlugins() == -1) { if (Pcsx2Configure(NULL) == FALSE) { - exit(1); + exit(1); // user cancelled. } } - sinit=1; + sinit = true; return 0; } -int SysReset() { - if (sinit == 0) return 1; +void SysRestorableReset() +{ + // already reset? and saved? + if( !g_GameInProgress ) return; + if( g_RecoveryState != NULL ) return; + + try + { + g_RecoveryState = new MemoryAlloc(); + memSavingState( *g_RecoveryState ).FreezeAll(); + cpuShutdown(); + g_GameInProgress = false; + } + catch( std::runtime_error& ex ) + { + SysMessage( + "Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n" + "Error: %s", ex.what() ); + safe_delete( g_RecoveryState ); + } +} + +void SysReset() +{ + if (!sinit) return; + StatusSet(_("Resetting...")); - if( !cpuReset() ) return 0; + + g_GameInProgress = false; + safe_free( g_RecoveryState ); + + ResetPlugins(); + StatusSet(_("Ready")); - return 1; } - +// completely shuts down the emulator's cpu state, and unloads all plugins from memory. void SysClose() { - if (sinit == 0) return; + if (!sinit) return; cpuShutdown(); + ClosePlugins(); ReleasePlugins(); - sinit=0; + sinit=false; } -int concolors[] = { - 0, - FOREGROUND_RED, - FOREGROUND_GREEN, - FOREGROUND_GREEN | FOREGROUND_RED, - FOREGROUND_BLUE, - FOREGROUND_RED | FOREGROUND_BLUE, - FOREGROUND_RED | FOREGROUND_GREEN, - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE -}; - void SysPrintf(const char *fmt, ...) { va_list list; char msg[512]; va_start(list,fmt); - vsnprintf(msg,511,fmt,list); + vsprintf_s(msg,fmt,list); msg[511] = '\0'; va_end(list); @@ -1780,7 +1746,7 @@ void SysMessage(const char *fmt, ...) char tmp[512]; va_start(list,fmt); - _vsnprintf(tmp,511,fmt,list); + vsprintf_s(tmp,fmt,list); tmp[511] = '\0'; va_end(list); MessageBox(0, tmp, _("Pcsx2 Msg"), 0); @@ -1830,8 +1796,8 @@ void SysCloseLibrary(void *lib) { void *SysMmap(uptr base, u32 size) { void *mem; - mem = VirtualAlloc((void*)base, size, MEM_RESERVE, PAGE_EXECUTE_READWRITE); - mem = VirtualAlloc((void*)mem, size, MEM_COMMIT , PAGE_EXECUTE_READWRITE); + mem = VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + //mem = VirtualAlloc((void*)mem, size, MEM_COMMIT , PAGE_EXECUTE_READWRITE); return mem; } @@ -1839,452 +1805,3 @@ void SysMunmap(uptr base, u32 size) { VirtualFree((void*)base, size, MEM_DECOMMIT); VirtualFree((void*)base, 0, MEM_RELEASE); } - -#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 - <sTranslatedSID // 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::WriteLn( "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::FormatLn( "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::FormatLn( "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::FormatLn("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::FormatLn("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::FormatLn("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 diff --git a/pcsx2/windows/WinVM.cpp b/pcsx2/windows/WinVM.cpp new file mode 100644 index 0000000000..e757711369 --- /dev/null +++ b/pcsx2/windows/WinVM.cpp @@ -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 + + +#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 + <sTranslatedSID // 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 diff --git a/pcsx2/windows/ini.c b/pcsx2/windows/ini.c index ac47d115c2..7e248590ad 100644 --- a/pcsx2/windows/ini.c +++ b/pcsx2/windows/ini.c @@ -19,12 +19,11 @@ 15-09-2004 : file rewriten for work with inis (shadow) */ -#include +#include "win32.h" #include #include #include "Common.h" -#include "win32.h" #include "Paths.h" #include diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index ec0c50a5b1..8162f8c682 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -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(); } diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index 31082cf88b..902d2010e7 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -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++; diff --git a/pcsx2/x86/ix86-32/iR5900-32.c b/pcsx2/x86/ix86-32/iR5900-32.c index 577a3cd1eb..b82924bf9c 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.c +++ b/pcsx2/x86/ix86-32/iR5900-32.c @@ -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); } } diff --git a/pcsx2/x86/ix86/ix86.h b/pcsx2/x86/ix86/ix86.h index c26552f864..32acf4841b 100644 --- a/pcsx2/x86/ix86/ix86.h +++ b/pcsx2/x86/ix86/ix86.h @@ -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 ); diff --git a/pcsx2/x86/ix86/ix86_cpudetect.c b/pcsx2/x86/ix86/ix86_cpudetect.c index fceeabb03d..6a1346e918 100644 --- a/pcsx2/x86/ix86/ix86_cpudetect.c +++ b/pcsx2/x86/ix86/ix86_cpudetect.c @@ -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;