From 2d95e58bbae09a41e4feea69b45cedc765f9273e Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Thu, 25 Dec 2008 02:29:43 +0000 Subject: [PATCH] Major GUI stability renovations: Pcsx2 now supports an "automagic" to-memory savestate system that allows it to recover on-the-fly from most dialog box changes (speedhacks, advanced roundmodes, and even MTGS). Use Run:Execute to resume your game right where you left off! Fixed several memory leaks, including one that ate up about 40 megs of ram everytime you hit esc to go to the GUI. Also added quite a bit more error checking to init/deinit procedures. Run:Reset menu now *fully* resets all plugins, including the GS. Added color to the Win32 console! :) TODO: The "Configure" dialog box doesn't support the new recovery system yet, so you can't change plugin versions on the fly yet (coming soon). git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@488 a6443dda-0b58-4228-96e9-037be469359c --- pcsx2/CDVD.c | 21 +- pcsx2/CDVD.h | 1 - pcsx2/CDVDisodrv.c | 4 +- pcsx2/CDVDisodrv.h | 2 +- pcsx2/COP0.c | 2 +- pcsx2/CdRom.c | 16 +- pcsx2/CdRom.h | 1 - pcsx2/Common.h | 2 +- pcsx2/Counters.c | 37 +- pcsx2/Counters.h | 1 - pcsx2/Elfheader.c | 34 +- pcsx2/Elfheader.h | 2 +- pcsx2/Exceptions.h | 127 ++ pcsx2/GS.cpp | 160 +- pcsx2/GS.h | 9 +- pcsx2/IPU/IPU.c | 108 +- pcsx2/IPU/IPU.h | 2 +- pcsx2/Interpreter.c | 4 +- pcsx2/Linux/GtkGui.cpp | 144 +- pcsx2/Linux/LnxConsole.cpp | 83 +- pcsx2/MMI.c | 2 +- pcsx2/Memory.c | 242 +-- pcsx2/Misc.c | 480 ++---- pcsx2/Misc.h | 26 +- pcsx2/Patch.c | 11 +- pcsx2/Plugins.c | 68 +- pcsx2/Plugins.h | 9 + pcsx2/PsxBios.c | 11 +- pcsx2/PsxCounters.c | 27 +- pcsx2/PsxCounters.h | 1 - pcsx2/PsxInterpreter.c | 6 +- pcsx2/PsxMem.c | 13 +- pcsx2/PsxSio2.c | 6 +- pcsx2/PsxSio2.h | 1 - pcsx2/R3000A.c | 11 - pcsx2/R3000A.h | 1 - pcsx2/R5900.c | 108 +- pcsx2/R5900.h | 5 +- pcsx2/SaveState.cpp | 356 +++++ pcsx2/SaveState.h | 178 +++ pcsx2/Sif.c | 7 +- pcsx2/Sio.c | 17 +- pcsx2/Sio.h | 1 - pcsx2/System.h | 146 +- pcsx2/VU0.h | 1 - pcsx2/VU0micro.c | 22 +- pcsx2/VU1micro.c | 14 +- pcsx2/VUmicro.h | 2 - pcsx2/VifDma.c | 16 +- pcsx2/VifDma.h | 2 - pcsx2/vtlb.cpp | 10 +- pcsx2/vtlb.h | 1 + pcsx2/windows/AdvancedDlg.cpp | 182 +++ pcsx2/windows/ConfigDlg.c | 6 +- pcsx2/windows/Console.cpp | 104 +- pcsx2/windows/CpuDlg.c | 60 +- pcsx2/windows/Debugger.c | 4 +- pcsx2/windows/PatchBrowser.c | 3 +- pcsx2/windows/RDebugger.c | 4 +- pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 31 + pcsx2/windows/Win32.h | 26 +- pcsx2/windows/WinMain.c | 1583 +++++++------------- pcsx2/windows/WinVM.cpp | 470 ++++++ pcsx2/windows/ini.c | 3 +- pcsx2/x86/iR3000A.cpp | 90 +- pcsx2/x86/iVUzerorec.cpp | 34 +- pcsx2/x86/ix86-32/iR5900-32.c | 78 +- pcsx2/x86/ix86/ix86.h | 1 - pcsx2/x86/ix86/ix86_cpudetect.c | 2 +- 69 files changed, 3130 insertions(+), 2112 deletions(-) create mode 100644 pcsx2/Exceptions.h create mode 100644 pcsx2/SaveState.cpp create mode 100644 pcsx2/SaveState.h create mode 100644 pcsx2/windows/AdvancedDlg.cpp create mode 100644 pcsx2/windows/WinVM.cpp 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;