diff --git a/pcsx2/Exceptions.h b/pcsx2/Exceptions.h index 0d92db9ce0..4c92d5780f 100644 --- a/pcsx2/Exceptions.h +++ b/pcsx2/Exceptions.h @@ -83,7 +83,7 @@ namespace Exception { public: virtual ~RuntimeError() throw() {} - explicit RuntimeError( const std::string& msg="An unhandled runtime error has occured, somewhere in the depths of Pcsx2's cluttered brain-matter." ) : + explicit RuntimeError( const std::string& msg="An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter." ) : BaseException( msg ) {} }; @@ -96,7 +96,7 @@ namespace Exception BaseException( msg ) {} }; - + class OutOfMemory : public RuntimeError { public: @@ -114,6 +114,16 @@ namespace Exception LogicError( msg ) {} }; + // This exception thrown any time an operation is attempted when an object + // is in an uninitialized state. + class InvalidArgument : public LogicError + { + public: + virtual ~InvalidArgument() throw() {} + explicit InvalidArgument( const std::string& msg="Invalid argument passed to a function." ) : + LogicError( msg ) {} + }; + // Keep those array indexers in bounds when using the SafeArray type, or you'll be // seeing these. class IndexBoundsFault : public LogicError @@ -142,6 +152,132 @@ namespace Exception RuntimeError( msg ) {} }; + class PluginFailure : public RuntimeError + { + public: + std::string plugin_name; // name of the plugin + + virtual ~PluginFailure() throw() {} + explicit PluginFailure( const std::string& plugin, const std::string& msg = "A plugin encountered a critical error." ) : + RuntimeError( msg ) + , plugin_name( plugin ) {} + }; + + class ThreadCreationError : public RuntimeError + { + public: + virtual ~ThreadCreationError() throw() {} + explicit ThreadCreationError( const std::string& msg="Thread could not be created." ) : + RuntimeError( msg ) {} + }; + + // This is a "special" exception that's primarily included for safe functioning in the + // Win32's ASCII API (ie, the non-Unicode one). Many of the old Win32 APIs don't support + // paths over 256 characters. + class PathTooLong : public RuntimeError + { + public: + virtual ~PathTooLong() throw() {} + explicit PathTooLong( const std::string& msg= + "A Pcsx2 pathname was too long for the system. Please move or reinstall Pcsx2 to\n" + "a location on your hard drive that has a shorter path." ) : + RuntimeError( msg ) {} + }; + + /////////////////////////////////////////////////////////////////////// + // 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 RuntimeError + { + public: + std::string stream_name; // name of the stream (if applicable) + + virtual ~Stream() throw() {} + + // copy construct! + Stream( const Stream& src ) : + RuntimeError( src.Message() ) + , stream_name( src.stream_name ) {} + + explicit Stream( + const std::string& objname=std::string(), + const std::string& msg="Invalid stream object" ) : + RuntimeError( msg + "\n\tFilename: " + objname ) + , stream_name( objname ) {} + }; + + // A generic base error class for bad streams -- corrupted data, sudden closures, loss of + // connection, or anything else that would indicate a failure to read the data after the + // stream was successfully opened. + class BadStream : public Stream + { + public: + virtual ~BadStream() throw() {} + explicit BadStream( + const std::string& objname=std::string(), + const std::string& msg="Stream data is corrupted or incomplete, or the stream connection closed unexpectedly" ) : + Stream( objname, msg ) {} + }; + + // A generic exception for odd-ball stream creation errors. + class CreateStream : public Stream + { + public: + virtual ~CreateStream() throw() {} + explicit CreateStream( + const std::string& objname=std::string(), + const std::string& msg="Stream could not be created or opened" ) : + Stream( objname, msg ) {} + }; + + // Exception thrown when an attempt to open a non-existent file is made. + // (this exception can also mean file permissions are invalid) + class FileNotFound : public CreateStream + { + public: + virtual ~FileNotFound() throw() {} + explicit FileNotFound( + const std::string& objname=std::string(), + const std::string& msg="File not found" ) : + CreateStream( objname, msg ) {} + }; + + class AccessDenied : public CreateStream + { + public: + virtual ~AccessDenied() throw() {} + explicit AccessDenied( + const std::string& objname=std::string(), + const std::string& msg="Permission denied to file or stream" ) : + CreateStream( objname, msg ) {} + }; + + // Generic End of Stream exception (sometimes an error, and sometimes just used as a + // shortcut for manual feof checks). + class EndOfStream : public Stream + { + public: + virtual ~EndOfStream() throw() {} + explicit EndOfStream( const std::string& objname=std::string(), const std::string& msg="End of stream was encountered" ) : + Stream( objname, msg ) {} + }; + + ////////////////////////////////////////////////////////////////////////// + // SAVESTATE EXCEPTIONS + + // Exception thrown when a corrupted or truncated savestate is encountered. + class BadSavedState : public BadStream + { + public: + virtual ~BadSavedState() throw() {} + explicit BadSavedState( + const std::string& objname=std::string(), + const std::string& msg="Savestate data is corrupted or incomplete" ) : + BadStream( objname, msg ) {} + }; + // Exception thrown by SaveState class when a critical plugin or gzread class FreezePluginFailure : public RuntimeError { @@ -208,96 +344,6 @@ namespace Exception , Crc_Cdvd( crc_cdvd ) {} }; - - class PluginFailure : public RuntimeError - { - public: - std::string plugin_name; // name of the plugin - - virtual ~PluginFailure() throw() {} - explicit PluginFailure( const std::string& plugin, const std::string& msg = "A plugin encountered a critical error." ) : - RuntimeError( msg ) - , plugin_name( plugin ) {} - }; - - class ThreadCreationError : public RuntimeError - { - public: - virtual ~ThreadCreationError() throw() {} - explicit ThreadCreationError( const std::string& msg="Thread could not be created." ) : - RuntimeError( msg ) {} - }; - - // This is a "special" exception that's primarily included for safe functioning in the - // Win32's ASCII API (ie, the non-Unicode one). Many of the old Win32 APIs don't support - // paths over 256 characters. - class PathTooLong : public RuntimeError - { - public: - virtual ~PathTooLong() throw() {} - explicit PathTooLong( const std::string& msg= - "A Pcsx2 pathname was too long for the system. Please move or reinstall Pcsx2 to\n" - "a location on your hard drive that has a shorter path." ) : - RuntimeError( msg ) {} - }; - - /////////////////////////////////////////////////////////////////////// - // 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 RuntimeError - { - public: - std::string stream_name; // name of the stream (if applicable) - - virtual ~Stream() throw() {} - - // copy construct! - Stream( const Stream& src ) : - RuntimeError( src.Message() ) - , stream_name( src.stream_name ) {} - - explicit Stream( - const std::string& objname=std::string(), - const std::string& msg="Invalid stream object" ) : - RuntimeError( 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 ) {} - }; - - // Generic End of Stream exception (sometimes an error, and sometimes just used as a - // shortcut for manual feof checks). - class EndOfStream : public Stream - { - public: - virtual ~EndOfStream() throw() {} - explicit EndOfStream( const std::string& objname=std::string(), const std::string& msg="End of stream was encountered" ) : - Stream( objname, msg ) {} - }; - } #endif diff --git a/pcsx2/IopCounters.cpp b/pcsx2/IopCounters.cpp index bc73bc13ea..3f30937e2b 100644 --- a/pcsx2/IopCounters.cpp +++ b/pcsx2/IopCounters.cpp @@ -30,7 +30,6 @@ s32 psxNextCounter; u32 psxNextsCounter; u8 psxhblankgate = 0; u8 psxvblankgate = 0; -u8 psxcntmask = 0; // flags when the gate is off or counter disabled. (do not count) #define IOPCNT_STOPPED (0x10000000ul) @@ -718,9 +717,30 @@ u64 psxRcntCycles(int index) return (u64)(psxCounters[index].count + (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); } +void psxRcntSetGates() +{ + if(psxCounters[0].mode & IOPCNT_ENABLE_GATE) + psxhblankgate |= 1; + else + psxhblankgate &= ~1; + + if(psxCounters[1].mode & IOPCNT_ENABLE_GATE) + psxvblankgate |= 1<<1; + else + psxvblankgate &= ~(1<<1); + + if(psxCounters[3].mode & IOPCNT_ENABLE_GATE) + psxvblankgate |= 1<<3; + else + psxvblankgate &= ~(1<<3); +} + void SaveState::psxRcntFreeze() { Freeze(psxCounters); Freeze(psxNextCounter); Freeze(psxNextsCounter); + + if( IsLoading() ) + psxRcntSetGates(); } diff --git a/pcsx2/IopSio2.cpp b/pcsx2/IopSio2.cpp index acad16bcee..d46502728b 100644 --- a/pcsx2/IopSio2.cpp +++ b/pcsx2/IopSio2.cpp @@ -98,16 +98,13 @@ void sio2_setSend3(u32 index, u32 value) { // int i; sio2.packet.sendArray3[index]=value; -#ifdef PAD_LOG // if (index==15){ // for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray1[i]);}PAD_LOG("\n"); // for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray2[i]);}PAD_LOG("\n"); // for (i=0; i<8; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); // for ( ; i<16; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); - PAD_LOG("[%d] : 0x%08X ", index,sio2.packet.sendArray3[index]); - PAD_LOG("\n"); + PAD_LOG("[%d] : 0x%08X\n", index,sio2.packet.sendArray3[index]); // } -#endif } //0->15 u32 sio2_getSend3(u32 index) {return sio2.packet.sendArray3[index];} //0->15 @@ -227,14 +224,12 @@ void psxDma11(u32 madr, u32 bcr, u32 chcr) { { sio2_fifoIn(PSXMu8(madr)); madr++; - if(sio2.packet.sendSize == BUFSIZE) { - HW_DMA11_MADR = madr; - PSX_INT(IopEvt_Dma11,(size>>2)); // Interrupts should always occur at the end - return; - } + if(sio2.packet.sendSize == BUFSIZE) + goto finished; } } +finished: HW_DMA11_MADR = madr; PSX_INT(IopEvt_Dma11,(size>>2)); // Interrupts should always occur at the end } diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index 2087540bd1..5dffc2da4b 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -23,12 +23,12 @@ _sio sio; -static FILE * MemoryCard1, * MemoryCard2; +static FILE * MemoryCard1=NULL, * MemoryCard2=NULL; static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; // Memory Card Specs : Sector size etc. -static const struct mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A}; +static const mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A}; // SIO Inline'd IRQs : Calls the SIO interrupt handlers directly instead of // feeding them through the IOP's branch test. (see SIO.H for details) @@ -68,8 +68,11 @@ void sioInit() { memzero_obj(sio); - MemoryCard1 = LoadMcd(1); - MemoryCard2 = LoadMcd(2); + if( MemoryCard1 == NULL ) + MemoryCard1 = LoadMcd(1); + + if( MemoryCard2 == NULL ) + MemoryCard2 = LoadMcd(2); // Transfer(?) Ready and the Buffer is Empty sio.StatReg = TX_RDY | TX_EMPTY; @@ -81,6 +84,9 @@ void psxSIOShutdown() { if(MemoryCard1) fclose(MemoryCard1); if(MemoryCard2) fclose(MemoryCard2); + + MemoryCard1 = NULL; + MemoryCard2 = NULL; } u8 sioRead8() { @@ -538,23 +544,32 @@ void SaveState::sioFreeze() *************** MEMORY CARD SPECIFIC FUNCTIONS ***************** ******************************************************************* *******************************************************************/ -FILE *LoadMcd(int mcd) { - char str[g_MaxPath]; + +#ifdef WIN32 +extern void NTFS_CompressFile( const char* file ); +#endif + +FILE *LoadMcd(int mcd) +{ + string str; FILE *f; - if (mcd == 1) { - strcpy(str, Config.Mcd1); - } else { - strcpy(str, Config.Mcd2); - } - if (*str == 0) sprintf(str, MEMCARDS_DIR "/Mcd00%d.ps2", mcd); - f = fopen(str, "r+b"); + str = (mcd == 1) ? Config.Mcd1 : Config.Mcd2; + + if( str.empty() ) + Path::Combine( str, MEMCARDS_DIR, fmt_string( "Mcd00%d.ps2", mcd ) ); + + if( !Path::Exists(str) ) + CreateMcd(str.c_str()); + +#ifdef WIN32 + NTFS_CompressFile( str.c_str() ); +#endif + + f = fopen(str.c_str(), "r+b"); + if (f == NULL) { - CreateMcd(str); - f = fopen(str, "r+b"); - } - if (f == NULL) { - Msgbox::Alert("Failed loading MemCard %s", params str); + Msgbox::Alert("Failed loading MemCard from file: %hs", params &str); return NULL; } @@ -573,76 +588,51 @@ void SeekMcd(FILE *f, u32 adr) { fseek(f, adr, SEEK_SET); } -void ReadMcd(int mcd, u8 *data, u32 adr, int size) { - if(mcd == 1) - { - if (MemoryCard1 == NULL) { - memset(data, 0, size); - return; - } - SeekMcd(MemoryCard1, adr); - fread(data, 1, size, MemoryCard1); - } - else - { - if (MemoryCard2 == NULL) { - memset(data, 0, size); - return; - } - SeekMcd(MemoryCard2, adr); - fread(data, 1, size, MemoryCard2); +void ReadMcd(int mcd, u8 *data, u32 adr, int size) +{ + FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2; + + if (mcfp == NULL) { + memset(data, 0, size); + return; } + SeekMcd(mcfp, adr); + fread(data, 1, size, mcfp); } -void SaveMcd(int mcd, const u8 *data, u32 adr, int size) { - if(mcd == 1) +void SaveMcd(int mcd, const u8 *data, u32 adr, int size) +{ + FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2; + + SeekMcd(mcfp, adr); + u8 *currentdata = (u8 *)malloc(size); + fread(currentdata, 1, size, mcfp); + for (int i=0; i(data); // clears to -1's - if(mcd == 1) - { - SeekMcd(MemoryCard1, adr); - fwrite(data, 1, 528*16, MemoryCard1); - } - else - { - SeekMcd(MemoryCard2, adr); - fwrite(data, 1, 528*16, MemoryCard2); - } + + FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2; + SeekMcd(mcfp, adr); + fwrite(data, 1, 528*16, mcfp); } -void CreateMcd(char *mcd) { +void CreateMcd(const char *mcd) +{ FILE *fp; int i=0, j=0; //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; diff --git a/pcsx2/Sio.h b/pcsx2/Sio.h index c895415c4e..c23acad523 100644 --- a/pcsx2/Sio.h +++ b/pcsx2/Sio.h @@ -101,7 +101,7 @@ FILE *LoadMcd(int mcd); void ReadMcd(int mcd, u8 *data, u32 adr, int size); void SaveMcd(int mcd, const u8 *data, u32 adr, int size); void EraseMcd(int mcd, u32 adr); -void CreateMcd(char *mcd); +void CreateMcd(const char *mcd); struct McdBlock { char Title[48]; diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 8e240c4a0f..29d65f83ea 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2594,6 +2594,10 @@ RelativePath="..\..\ThreadTools.cpp" > + + diff --git a/pcsx2/windows/Win32.h b/pcsx2/windows/Win32.h index 5b2d6e1b72..7bff43adff 100644 --- a/pcsx2/windows/Win32.h +++ b/pcsx2/windows/Win32.h @@ -99,8 +99,22 @@ extern int g_SaveGSStream; // sets the contents of the Pcsx2 status bar... -void StatusBar_Notice( const std::string& text ); -void StatusBar_SetMsg( const std::string& text ); +extern void StatusBar_Notice( const std::string& text ); +extern void StatusBar_SetMsg( const std::string& text ); + +// Throws an exception based on the value returned from GetLastError. +// Performs an option return value success/fail check on hresult. +extern void StreamException_ThrowLastError( const string& streamname, HANDLE result=INVALID_HANDLE_VALUE ); + +// Throws an exception based on the given error code (usually taken from ANSI C's errno) +extern void StreamException_ThrowFromErrno( const string& streamname, errno_t errcode ); + +extern bool StreamException_LogFromErrno( const string& streamname, const char* action, errno_t result ); +extern bool StreamException_LogLastError( const string& streamname, const char* action, HANDLE result=INVALID_HANDLE_VALUE ); + +// Sets the NTFS compression flag for a directory or file. +// This function does not operate recursively. If the given directory +extern void NTFS_CompressFile( const char* file ); #endif diff --git a/pcsx2/windows/WinSysExec.cpp b/pcsx2/windows/WinSysExec.cpp index 2219ee55e0..c9bb289a34 100644 --- a/pcsx2/windows/WinSysExec.cpp +++ b/pcsx2/windows/WinSysExec.cpp @@ -757,6 +757,11 @@ bool SysInit() CreateDirectory(MEMCARDS_DIR, NULL); CreateDirectory(SSTATES_DIR, NULL); + // Set the compression attribute on the Memcards folder. + // Memcards generally compress very well via NTFS compression. + + NTFS_CompressFile( MEMCARDS_DIR ); + if( IsDevBuild && emuLog == NULL && g_TestRun.plogname != NULL ) emuLog = fopen(g_TestRun.plogname, "w");