Added NTFS compression to the memcards folder and any memory cards used from pcsx2. Most memory cards compress exceptionally well (from 16M to 3M typically).

Also in this commit: Some minor code cleanups to sio.cpp, and added some missing setup code to the Iop Counters savestate loader; psxhblankgate and psxvblankgate weren't being re-initialized.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@456 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-02-09 06:02:46 +00:00
parent b1600e57f7
commit fcad9f8ebc
8 changed files with 254 additions and 180 deletions

View File

@ -83,7 +83,7 @@ namespace Exception
{ {
public: public:
virtual ~RuntimeError() throw() {} 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 ) BaseException( msg )
{} {}
}; };
@ -114,6 +114,16 @@ namespace Exception
LogicError( msg ) {} 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 // Keep those array indexers in bounds when using the SafeArray type, or you'll be
// seeing these. // seeing these.
class IndexBoundsFault : public LogicError class IndexBoundsFault : public LogicError
@ -142,6 +152,132 @@ namespace Exception
RuntimeError( msg ) {} 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 // Exception thrown by SaveState class when a critical plugin or gzread
class FreezePluginFailure : public RuntimeError class FreezePluginFailure : public RuntimeError
{ {
@ -208,96 +344,6 @@ namespace Exception
, Crc_Cdvd( crc_cdvd ) , 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 #endif

View File

@ -30,7 +30,6 @@ s32 psxNextCounter;
u32 psxNextsCounter; u32 psxNextsCounter;
u8 psxhblankgate = 0; u8 psxhblankgate = 0;
u8 psxvblankgate = 0; u8 psxvblankgate = 0;
u8 psxcntmask = 0;
// flags when the gate is off or counter disabled. (do not count) // flags when the gate is off or counter disabled. (do not count)
#define IOPCNT_STOPPED (0x10000000ul) #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)); 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() void SaveState::psxRcntFreeze()
{ {
Freeze(psxCounters); Freeze(psxCounters);
Freeze(psxNextCounter); Freeze(psxNextCounter);
Freeze(psxNextsCounter); Freeze(psxNextsCounter);
if( IsLoading() )
psxRcntSetGates();
} }

View File

@ -98,16 +98,13 @@ void sio2_setSend3(u32 index, u32 value)
{ {
// int i; // int i;
sio2.packet.sendArray3[index]=value; sio2.packet.sendArray3[index]=value;
#ifdef PAD_LOG
// if (index==15){ // 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.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<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=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"); // 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("[%d] : 0x%08X\n", index,sio2.packet.sendArray3[index]);
PAD_LOG("\n");
// } // }
#endif
} //0->15 } //0->15
u32 sio2_getSend3(u32 index) {return sio2.packet.sendArray3[index];} //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)); sio2_fifoIn(PSXMu8(madr));
madr++; madr++;
if(sio2.packet.sendSize == BUFSIZE) { if(sio2.packet.sendSize == BUFSIZE)
HW_DMA11_MADR = madr; goto finished;
PSX_INT(IopEvt_Dma11,(size>>2)); // Interrupts should always occur at the end
return;
}
} }
} }
finished:
HW_DMA11_MADR = madr; HW_DMA11_MADR = madr;
PSX_INT(IopEvt_Dma11,(size>>2)); // Interrupts should always occur at the end PSX_INT(IopEvt_Dma11,(size>>2)); // Interrupts should always occur at the end
} }

View File

@ -23,12 +23,12 @@
_sio sio; _sio sio;
static FILE * MemoryCard1, * MemoryCard2; static FILE * MemoryCard1=NULL, * MemoryCard2=NULL;
static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d };
// Memory Card Specs : Sector size etc. // 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 // 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) // feeding them through the IOP's branch test. (see SIO.H for details)
@ -68,7 +68,10 @@ void sioInit()
{ {
memzero_obj(sio); memzero_obj(sio);
if( MemoryCard1 == NULL )
MemoryCard1 = LoadMcd(1); MemoryCard1 = LoadMcd(1);
if( MemoryCard2 == NULL )
MemoryCard2 = LoadMcd(2); MemoryCard2 = LoadMcd(2);
// Transfer(?) Ready and the Buffer is Empty // Transfer(?) Ready and the Buffer is Empty
@ -81,6 +84,9 @@ void psxSIOShutdown()
{ {
if(MemoryCard1) fclose(MemoryCard1); if(MemoryCard1) fclose(MemoryCard1);
if(MemoryCard2) fclose(MemoryCard2); if(MemoryCard2) fclose(MemoryCard2);
MemoryCard1 = NULL;
MemoryCard2 = NULL;
} }
u8 sioRead8() { u8 sioRead8() {
@ -538,23 +544,32 @@ void SaveState::sioFreeze()
*************** MEMORY CARD SPECIFIC FUNCTIONS ***************** *************** 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; FILE *f;
if (mcd == 1) { str = (mcd == 1) ? Config.Mcd1 : Config.Mcd2;
strcpy(str, Config.Mcd1);
} else { if( str.empty() )
strcpy(str, Config.Mcd2); Path::Combine( str, MEMCARDS_DIR, fmt_string( "Mcd00%d.ps2", mcd ) );
}
if (*str == 0) sprintf(str, MEMCARDS_DIR "/Mcd00%d.ps2", mcd); if( !Path::Exists(str) )
f = fopen(str, "r+b"); CreateMcd(str.c_str());
#ifdef WIN32
NTFS_CompressFile( str.c_str() );
#endif
f = fopen(str.c_str(), "r+b");
if (f == NULL) { if (f == NULL) {
CreateMcd(str); Msgbox::Alert("Failed loading MemCard from file: %hs", params &str);
f = fopen(str, "r+b");
}
if (f == NULL) {
Msgbox::Alert("Failed loading MemCard %s", params str);
return NULL; return NULL;
} }
@ -573,76 +588,51 @@ void SeekMcd(FILE *f, u32 adr) {
fseek(f, adr, SEEK_SET); fseek(f, adr, SEEK_SET);
} }
void ReadMcd(int mcd, u8 *data, u32 adr, int size) { void ReadMcd(int mcd, u8 *data, u32 adr, int size)
if(mcd == 1)
{ {
if (MemoryCard1 == NULL) { FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2;
if (mcfp == NULL) {
memset(data, 0, size); memset(data, 0, size);
return; return;
} }
SeekMcd(MemoryCard1, adr); SeekMcd(mcfp, adr);
fread(data, 1, size, MemoryCard1); fread(data, 1, size, mcfp);
}
else
{
if (MemoryCard2 == NULL) {
memset(data, 0, size);
return;
}
SeekMcd(MemoryCard2, adr);
fread(data, 1, size, MemoryCard2);
}
} }
void SaveMcd(int mcd, const u8 *data, u32 adr, int size) { void SaveMcd(int mcd, const u8 *data, u32 adr, int size)
if(mcd == 1)
{ {
SeekMcd(MemoryCard1, adr); FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2;
SeekMcd(mcfp, adr);
u8 *currentdata = (u8 *)malloc(size); u8 *currentdata = (u8 *)malloc(size);
fread(currentdata, 1, size, MemoryCard1); fread(currentdata, 1, size, mcfp);
for (int i=0; i<size; i++) for (int i=0; i<size; i++)
{ {
if ((currentdata[i] & data[i]) != data[i]) if ((currentdata[i] & data[i]) != data[i])
Console::Notice("MemoryCard : writing odd data"); Console::Notice("MemoryCard : writing odd data");
currentdata[i] &= data[i]; currentdata[i] &= data[i];
} }
SeekMcd(MemoryCard1, adr); SeekMcd(mcfp, adr);
fwrite(currentdata, 1, size, MemoryCard1); fwrite(currentdata, 1, size, mcfp);
}
else free(currentdata);
{
SeekMcd(MemoryCard2, adr);
u8 *currentdata = (u8 *)malloc(size);
fread(currentdata, 1, size, MemoryCard2);
for (int i=0; i<size; i++)
{
if ((currentdata[i] & data[i]) != data[i])
Console::Notice("MemoryCard : writing odd data");
currentdata[i] &= data[i];
}
SeekMcd(MemoryCard2, adr);
fwrite(currentdata, 1, size, MemoryCard2);
}
} }
void EraseMcd(int mcd, u32 adr) { void EraseMcd(int mcd, u32 adr)
{
u8 data[528*16]; u8 data[528*16];
memset8_obj<0xff>(data); // clears to -1's memset8_obj<0xff>(data); // clears to -1's
if(mcd == 1)
{ FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2;
SeekMcd(MemoryCard1, adr); SeekMcd(mcfp, adr);
fwrite(data, 1, 528*16, MemoryCard1); fwrite(data, 1, 528*16, mcfp);
}
else
{
SeekMcd(MemoryCard2, adr);
fwrite(data, 1, 528*16, MemoryCard2);
}
} }
void CreateMcd(char *mcd) { void CreateMcd(const char *mcd)
{
FILE *fp; FILE *fp;
int i=0, j=0; int i=0, j=0;
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};

View File

@ -101,7 +101,7 @@ FILE *LoadMcd(int mcd);
void ReadMcd(int mcd, u8 *data, u32 adr, int size); void ReadMcd(int mcd, u8 *data, u32 adr, int size);
void SaveMcd(int mcd, const u8 *data, u32 adr, int size); void SaveMcd(int mcd, const u8 *data, u32 adr, int size);
void EraseMcd(int mcd, u32 adr); void EraseMcd(int mcd, u32 adr);
void CreateMcd(char *mcd); void CreateMcd(const char *mcd);
struct McdBlock { struct McdBlock {
char Title[48]; char Title[48];

View File

@ -2594,6 +2594,10 @@
RelativePath="..\..\ThreadTools.cpp" RelativePath="..\..\ThreadTools.cpp"
> >
</File> </File>
<File
RelativePath="..\WinCompressNTFS.cpp"
>
</File>
<File <File
RelativePath="..\WinThreads.cpp" RelativePath="..\WinThreads.cpp"
> >

View File

@ -99,8 +99,22 @@ extern int g_SaveGSStream;
// sets the contents of the Pcsx2 status bar... // sets the contents of the Pcsx2 status bar...
void StatusBar_Notice( const std::string& text ); extern void StatusBar_Notice( const std::string& text );
void StatusBar_SetMsg( 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 #endif

View File

@ -757,6 +757,11 @@ bool SysInit()
CreateDirectory(MEMCARDS_DIR, NULL); CreateDirectory(MEMCARDS_DIR, NULL);
CreateDirectory(SSTATES_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 ) if( IsDevBuild && emuLog == NULL && g_TestRun.plogname != NULL )
emuLog = fopen(g_TestRun.plogname, "w"); emuLog = fopen(g_TestRun.plogname, "w");