mirror of https://github.com/PCSX2/pcsx2.git
* Call PADupdate from MTGS thread when using legacy GSopen -- Should fix Linux Pad instabilities.
* Fixed a savestate loading bug, when loading states made with different sets/versions of plugins. DevNote: * Moved some old PS2E types to PS2Edefs, since the new v2 plugin API won't use them (freezeData, keyEvent). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2380 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
203979c16b
commit
408dbd7256
|
@ -48,6 +48,29 @@
|
||||||
|
|
||||||
#include "Pcsx2Defs.h"
|
#include "Pcsx2Defs.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// freeze modes:
|
||||||
|
#define FREEZE_LOAD 0
|
||||||
|
#define FREEZE_SAVE 1
|
||||||
|
#define FREEZE_SIZE 2
|
||||||
|
|
||||||
|
// event values:
|
||||||
|
#define KEYPRESS 1
|
||||||
|
#define KEYRELEASE 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
s8 *data;
|
||||||
|
} freezeData;
|
||||||
|
|
||||||
|
typedef struct _keyEvent {
|
||||||
|
u32 key;
|
||||||
|
u32 evt;
|
||||||
|
} keyEvent;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \
|
#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \
|
||||||
defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \
|
defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \
|
||||||
defined(USBdefs) || defined(FWdefs)
|
defined(USBdefs) || defined(FWdefs)
|
||||||
|
@ -172,11 +195,6 @@ typedef int (*DEV9handler)(void);
|
||||||
typedef void (*USBcallback)(int cycles);
|
typedef void (*USBcallback)(int cycles);
|
||||||
typedef int (*USBhandler)(void);
|
typedef int (*USBhandler)(void);
|
||||||
|
|
||||||
// freeze modes:
|
|
||||||
#define FREEZE_LOAD 0
|
|
||||||
#define FREEZE_SAVE 1
|
|
||||||
#define FREEZE_SIZE 2
|
|
||||||
|
|
||||||
typedef struct _GSdriverInfo {
|
typedef struct _GSdriverInfo {
|
||||||
char name[8];
|
char name[8];
|
||||||
void *common;
|
void *common;
|
||||||
|
|
|
@ -287,20 +287,4 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int size;
|
|
||||||
s8 *data;
|
|
||||||
} freezeData;
|
|
||||||
|
|
||||||
// event values:
|
|
||||||
#define KEYPRESS 1
|
|
||||||
#define KEYRELEASE 2
|
|
||||||
|
|
||||||
typedef struct _keyEvent {
|
|
||||||
u32 key;
|
|
||||||
u32 evt;
|
|
||||||
} keyEvent;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -337,62 +337,4 @@ namespace Exception
|
||||||
public:
|
public:
|
||||||
DEFINE_STREAM_EXCEPTION( EndOfStream, wxLt("Unexpected end of file or stream.") );
|
DEFINE_STREAM_EXCEPTION( EndOfStream, wxLt("Unexpected end of file or stream.") );
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
// Savestate Exceptions:
|
|
||||||
// BadSavedState / FreezePluginFailure / StateLoadError / UnsupportedStateVersion /
|
|
||||||
// StateCrcMismatch
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Exception thrown when a corrupted or truncated savestate is encountered.
|
|
||||||
//
|
|
||||||
class BadSavedState : public virtual BadStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_STREAM_EXCEPTION( BadSavedState, wxLt("Savestate data is corrupted or incomplete.") )
|
|
||||||
};
|
|
||||||
|
|
||||||
// thrown when the savestate being loaded isn't supported.
|
|
||||||
//
|
|
||||||
class UnsupportedStateVersion : public virtual BadSavedState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 Version; // version number of the unsupported state.
|
|
||||||
|
|
||||||
public:
|
|
||||||
DEFINE_EXCEPTION_COPYTORS( UnsupportedStateVersion )
|
|
||||||
|
|
||||||
explicit UnsupportedStateVersion( int version, const wxString& objname=wxEmptyString )
|
|
||||||
{
|
|
||||||
StreamName = objname;
|
|
||||||
Version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
|
||||||
virtual wxString FormatDisplayMessage() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A recoverable exception thrown when the CRC of the savestate does not match the
|
|
||||||
// CRC returned by the Cdvd driver.
|
|
||||||
// [feature not implemented yet]
|
|
||||||
//
|
|
||||||
class StateCrcMismatch : public virtual BadSavedState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 Crc_Savestate;
|
|
||||||
u32 Crc_Cdvd;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DEFINE_EXCEPTION_COPYTORS( StateCrcMismatch )
|
|
||||||
|
|
||||||
explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd, const wxString& objname=wxEmptyString )
|
|
||||||
{
|
|
||||||
StreamName = objname;
|
|
||||||
Crc_Savestate = crc_save;
|
|
||||||
Crc_Cdvd = crc_cdvd;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
|
||||||
virtual wxString FormatDisplayMessage() const;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,41 +190,3 @@ wxString Exception::Stream::FormatDisplayMessage() const
|
||||||
wxsFormat( _("Name: %s"), StreamName.c_str() );
|
wxsFormat( _("Name: %s"), StreamName.c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
wxString Exception::UnsupportedStateVersion::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
// Note: no stacktrace needed for this one...
|
|
||||||
return wxsFormat( L"Unknown or unsupported savestate version: 0x%x", Version );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString Exception::UnsupportedStateVersion::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
// m_message_user contains a recoverable savestate error which is helpful to the user.
|
|
||||||
return wxsFormat(
|
|
||||||
m_message_user + L"\n\n" +
|
|
||||||
wxsFormat( _("Cannot load savestate. It is of an unknown or unsupported version."), Version )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
wxString Exception::StateCrcMismatch::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
// Note: no stacktrace needed for this one...
|
|
||||||
return wxsFormat(
|
|
||||||
L"Game/CDVD does not match the savestate CRC.\n"
|
|
||||||
L"\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n",
|
|
||||||
Crc_Savestate, Crc_Cdvd
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString Exception::StateCrcMismatch::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
return wxsFormat(
|
|
||||||
m_message_user + L"\n\n" +
|
|
||||||
wxsFormat(
|
|
||||||
L"Savestate game/crc mismatch. Cdvd CRC: 0x%X Game CRC: 0x%X\n",
|
|
||||||
Crc_Savestate, Crc_Cdvd
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -370,6 +370,11 @@ void SysMtgsThread::ExecuteTaskInThread()
|
||||||
GSvsync(tag.data[0]);
|
GSvsync(tag.data[0]);
|
||||||
gsFrameSkip();
|
gsFrameSkip();
|
||||||
|
|
||||||
|
// if we're not using GSOpen2, then the GS window is on this thread (MTGS thread),
|
||||||
|
// so we need to call PADupdate from here.
|
||||||
|
if( (GSopen2 == NULL) && (PADupdate != NULL) )
|
||||||
|
PADupdate(0);
|
||||||
|
|
||||||
StateCheckInThread();
|
StateCheckInThread();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -123,7 +123,12 @@ struct LegacyApi_OptMethod
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static s32 CALLBACK fallback_freeze(int mode, freezeData *data) { data->size = 0; return 0; }
|
static s32 CALLBACK fallback_freeze(int mode, freezeData *data)
|
||||||
|
{
|
||||||
|
if( mode == FREEZE_SIZE ) data->size = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void CALLBACK fallback_keyEvent(keyEvent *ev) {}
|
static void CALLBACK fallback_keyEvent(keyEvent *ev) {}
|
||||||
static void CALLBACK fallback_setSettingsDir(const char* dir) {}
|
static void CALLBACK fallback_setSettingsDir(const char* dir) {}
|
||||||
static void CALLBACK fallback_configure() {}
|
static void CALLBACK fallback_configure() {}
|
||||||
|
|
|
@ -23,6 +23,17 @@
|
||||||
|
|
||||||
#include <wx/dynlib.h>
|
#include <wx/dynlib.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
// Disabling C4673: throwing 'Exception::Blah' the following types will not be considered at the catch site
|
||||||
|
// The warning is bugged, and happens even though we're properly inheriting classes with
|
||||||
|
// 'virtual' qualifiers. But since the warning is potentially useful elsewhere, I disable
|
||||||
|
// it only for the scope of these exceptions.
|
||||||
|
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4673)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct PluginInfo
|
struct PluginInfo
|
||||||
{
|
{
|
||||||
const char* shortname;
|
const char* shortname;
|
||||||
|
@ -36,22 +47,18 @@ struct PluginInfo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
|
|
||||||
// Disabling C4673: throwing 'Exception::Blah' the following types will not be considered at the catch site
|
|
||||||
// The warning is bugged, and happens even though we're properly inheriting classes with
|
|
||||||
// 'virtual' qualifiers. But since the warning is potentially useful elsewhere, I disable
|
|
||||||
// it only for the scope of these exceptions.
|
|
||||||
|
|
||||||
# pragma warning(push)
|
|
||||||
# pragma warning(disable:4673)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Plugin-related Exceptions
|
// Plugin-related Exceptions
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
|
// Exception thrown when a corrupted or truncated savestate is encountered.
|
||||||
|
class SaveStateLoadError : public virtual BadStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DEFINE_STREAM_EXCEPTION( SaveStateLoadError, wxLt("Savestate data is corrupted or incomplete.") )
|
||||||
|
};
|
||||||
|
|
||||||
class PluginError : public virtual RuntimeError
|
class PluginError : public virtual RuntimeError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -137,7 +144,7 @@ namespace Exception
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThawPluginFailure : public virtual PluginError, public virtual BadSavedState
|
class ThawPluginFailure : public virtual PluginError, public virtual SaveStateLoadError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DEFINE_EXCEPTION_COPYTORS( ThawPluginFailure )
|
DEFINE_EXCEPTION_COPYTORS( ThawPluginFailure )
|
||||||
|
|
|
@ -37,6 +37,13 @@ int sys_resume_lock = 0;
|
||||||
|
|
||||||
static FnType_OnThreadComplete* Callback_FreezeFinished = NULL;
|
static FnType_OnThreadComplete* Callback_FreezeFinished = NULL;
|
||||||
|
|
||||||
|
static bool StateCopy_ForceClear()
|
||||||
|
{
|
||||||
|
sys_resume_lock = 0;
|
||||||
|
state_buffer_lock.Release();
|
||||||
|
state_buffer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
static void __evt_fastcall StateThread_OnAppStatus( void* thr, AppEventType& stat )
|
static void __evt_fastcall StateThread_OnAppStatus( void* thr, AppEventType& stat )
|
||||||
{
|
{
|
||||||
if( (thr == NULL) || (stat != AppStatus_Exiting) ) return;
|
if( (thr == NULL) || (stat != AppStatus_Exiting) ) return;
|
||||||
|
@ -378,43 +385,58 @@ void StateCopy_FreezeToMem()
|
||||||
(new StateThread_Freeze( OnFinished_Resume ))->Start();
|
(new StateThread_Freeze( OnFinished_Resume ))->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _acquire_and_block()
|
class Acquire_And_Block
|
||||||
{
|
{
|
||||||
if( state_buffer_lock.TryAcquire() ) return;
|
protected:
|
||||||
|
bool m_DisposeWhenFinished;
|
||||||
|
bool m_Acquired;
|
||||||
|
|
||||||
/*
|
public:
|
||||||
// If the state buffer is locked and we're being called from the main thread then we need
|
Acquire_And_Block( bool dispose )
|
||||||
// to cancel the current action. This is needed because state_buffer_lock is only updated
|
|
||||||
// from events handled on the main thread.
|
|
||||||
|
|
||||||
if( wxThread::IsMain() )
|
|
||||||
throw Exception::CancelEvent( "Blocking ThawFromMem canceled due to existing state buffer lock." );
|
|
||||||
else*/
|
|
||||||
{
|
{
|
||||||
pxAssume( current_state_thread != NULL );
|
m_DisposeWhenFinished = dispose;
|
||||||
do {
|
m_Acquired = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// If the state buffer is locked and we're being called from the main thread then we need
|
||||||
|
// to cancel the current action. This is needed because state_buffer_lock is only updated
|
||||||
|
// from events handled on the main thread.
|
||||||
|
|
||||||
|
if( wxThread::IsMain() )
|
||||||
|
throw Exception::CancelEvent( "Blocking ThawFromMem canceled due to existing state buffer lock." );
|
||||||
|
else*/
|
||||||
|
|
||||||
|
while ( !state_buffer_lock.TryAcquire() )
|
||||||
|
{
|
||||||
|
pxAssume( current_state_thread != NULL );
|
||||||
current_state_thread->Block();
|
current_state_thread->Block();
|
||||||
wxGetApp().ProcessPendingEvents(); // Trying this for now, may or may not work due to recursive pitfalls (see above)
|
wxGetApp().ProcessPendingEvents(); // Trying this for now, may or may not work due to recursive pitfalls (see above)
|
||||||
} while ( !state_buffer_lock.TryAcquire() );
|
};
|
||||||
|
|
||||||
|
m_Acquired = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
virtual ~Acquire_And_Block() throw()
|
||||||
|
{
|
||||||
|
if( m_DisposeWhenFinished )
|
||||||
|
state_buffer.Dispose();
|
||||||
|
|
||||||
|
if( m_Acquired )
|
||||||
|
state_buffer_lock.Release();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void StateCopy_FreezeToMem_Blocking()
|
void StateCopy_FreezeToMem_Blocking()
|
||||||
{
|
{
|
||||||
_acquire_and_block();
|
Acquire_And_Block blocker( false );
|
||||||
|
|
||||||
memSavingState( state_buffer ).FreezeAll();
|
memSavingState( state_buffer ).FreezeAll();
|
||||||
state_buffer_lock.Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the saved state into the active VM, and automatically free's the saved state data.
|
// Copies the saved state into the active VM, and automatically free's the saved state data.
|
||||||
void StateCopy_ThawFromMem_Blocking()
|
void StateCopy_ThawFromMem_Blocking()
|
||||||
{
|
{
|
||||||
_acquire_and_block();
|
Acquire_And_Block blocker( true );
|
||||||
|
|
||||||
memLoadingState( state_buffer ).FreezeAll();
|
memLoadingState( state_buffer ).FreezeAll();
|
||||||
state_buffer.Dispose();
|
|
||||||
state_buffer_lock.Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateCopy_Clear()
|
void StateCopy_Clear()
|
||||||
|
@ -427,4 +449,3 @@ bool StateCopy_IsBusy()
|
||||||
{
|
{
|
||||||
return state_buffer_lock.IsLocked();
|
return state_buffer_lock.IsLocked();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using namespace R5900;
|
using namespace R5900;
|
||||||
|
|
||||||
|
|
||||||
static void PreLoadPrep()
|
static void PreLoadPrep()
|
||||||
{
|
{
|
||||||
SysClearExecutionCache();
|
SysClearExecutionCache();
|
||||||
|
@ -45,14 +46,14 @@ wxString SaveStateBase::GetFilename( int slot )
|
||||||
wxsFormat( L"%8.8X.%3.3d", ElfCRC, slot )).GetFullPath();
|
wxsFormat( L"%8.8X.%3.3d", ElfCRC, slot )).GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveStateBase::SaveStateBase( SafeArray<u8>& memblock ) :
|
SaveStateBase::SaveStateBase( SafeArray<u8>& memblock )
|
||||||
m_memory( memblock )
|
: m_memory( memblock )
|
||||||
, m_version( g_SaveVersion )
|
|
||||||
, m_idx( 0 )
|
|
||||||
, m_sectid( FreezeId_Unknown )
|
|
||||||
, m_pid( PluginId_GS )
|
|
||||||
, m_DidBios( false )
|
|
||||||
{
|
{
|
||||||
|
m_version = g_SaveVersion;
|
||||||
|
m_idx = 0;
|
||||||
|
m_sectid = FreezeId_Unknown;
|
||||||
|
m_pid = PluginId_GS;
|
||||||
|
m_DidBios = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveStateBase::PrepBlock( int size )
|
void SaveStateBase::PrepBlock( int size )
|
||||||
|
@ -63,7 +64,7 @@ void SaveStateBase::PrepBlock( int size )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( m_memory.GetSizeInBytes() < end )
|
if( m_memory.GetSizeInBytes() < end )
|
||||||
throw Exception::BadSavedState();
|
throw Exception::SaveStateLoadError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ void SaveStateBase::FreezeTag( const char* src )
|
||||||
if( strcmp( m_tagspace, src ) != 0 )
|
if( strcmp( m_tagspace, src ) != 0 )
|
||||||
{
|
{
|
||||||
pxFail( "Savestate data corruption detected while reading tag" );
|
pxFail( "Savestate data corruption detected while reading tag" );
|
||||||
throw Exception::BadSavedState(
|
throw Exception::SaveStateLoadError(
|
||||||
// Untranslated diagnostic msg (use default msg for translation)
|
// Untranslated diagnostic msg (use default msg for translation)
|
||||||
L"Savestate data corruption detected while reading tag: " + fromUTF8(src)
|
L"Savestate data corruption detected while reading tag: " + fromUTF8(src)
|
||||||
);
|
);
|
||||||
|
@ -205,7 +206,7 @@ void SaveStateBase::WritebackSectionLength( int seekpos, int sectlen, const wxCh
|
||||||
{
|
{
|
||||||
if( sectlen != realsectsize ) // if they don't match then we have a problem, jim.
|
if( sectlen != realsectsize ) // if they don't match then we have a problem, jim.
|
||||||
{
|
{
|
||||||
throw Exception::BadSavedState( wxEmptyString,
|
throw Exception::SaveStateLoadError( wxEmptyString,
|
||||||
wxsFormat( L"Invalid size encountered on section '%s'.", sectname ),
|
wxsFormat( L"Invalid size encountered on section '%s'.", sectname ),
|
||||||
_("The savestate data is invalid or corrupted.")
|
_("The savestate data is invalid or corrupted.")
|
||||||
);
|
);
|
||||||
|
@ -234,7 +235,7 @@ bool SaveStateBase::FreezeSection( int seek_section )
|
||||||
|
|
||||||
if( sectlen != 128 )
|
if( sectlen != 128 )
|
||||||
{
|
{
|
||||||
throw Exception::BadSavedState( wxEmptyString,
|
throw Exception::SaveStateLoadError( wxEmptyString,
|
||||||
L"Invalid size encountered on BiosVersion section.",
|
L"Invalid size encountered on BiosVersion section.",
|
||||||
_("The savestate data is invalid or corrupted.")
|
_("The savestate data is invalid or corrupted.")
|
||||||
);
|
);
|
||||||
|
@ -257,7 +258,7 @@ bool SaveStateBase::FreezeSection( int seek_section )
|
||||||
Freeze( sectlen );
|
Freeze( sectlen );
|
||||||
if( sectlen != MainMemorySizeInBytes )
|
if( sectlen != MainMemorySizeInBytes )
|
||||||
{
|
{
|
||||||
throw Exception::BadSavedState( wxEmptyString,
|
throw Exception::SaveStateLoadError( wxEmptyString,
|
||||||
L"Invalid size encountered on MainMemory section.",
|
L"Invalid size encountered on MainMemory section.",
|
||||||
_("The savestate data is invalid or corrupted.")
|
_("The savestate data is invalid or corrupted.")
|
||||||
);
|
);
|
||||||
|
@ -302,7 +303,7 @@ bool SaveStateBase::FreezeSection( int seek_section )
|
||||||
else
|
else
|
||||||
g_plugins->Freeze( (PluginsEnum_t)m_pid, *this );
|
g_plugins->Freeze( (PluginsEnum_t)m_pid, *this );
|
||||||
|
|
||||||
WritebackSectionLength( seekpos, sectlen, L"HardwareRegisters" );
|
WritebackSectionLength( seekpos, sectlen, L"Plugins" );
|
||||||
|
|
||||||
// following increments only affect Saving mode, which needs to be sure to save all
|
// following increments only affect Saving mode, which needs to be sure to save all
|
||||||
// plugins (order doesn't matter but sequential is easy enough. (ignored by Loading mode)
|
// plugins (order doesn't matter but sequential is easy enough. (ignored by Loading mode)
|
||||||
|
@ -411,3 +412,42 @@ bool memLoadingState::SeekToSection( PluginsEnum_t pid )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// SaveState Exception Messages
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wxString Exception::UnsupportedStateVersion::FormatDiagnosticMessage() const
|
||||||
|
{
|
||||||
|
// Note: no stacktrace needed for this one...
|
||||||
|
return wxsFormat( L"Unknown or unsupported savestate version: 0x%x", Version );
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::UnsupportedStateVersion::FormatDisplayMessage() const
|
||||||
|
{
|
||||||
|
// m_message_user contains a recoverable savestate error which is helpful to the user.
|
||||||
|
return wxsFormat(
|
||||||
|
m_message_user + L"\n\n" +
|
||||||
|
wxsFormat( _("Cannot load savestate. It is of an unknown or unsupported version."), Version )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::StateCrcMismatch::FormatDiagnosticMessage() const
|
||||||
|
{
|
||||||
|
// Note: no stacktrace needed for this one...
|
||||||
|
return wxsFormat(
|
||||||
|
L"Game/CDVD does not match the savestate CRC.\n"
|
||||||
|
L"\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n",
|
||||||
|
Crc_Savestate, Crc_Cdvd
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::StateCrcMismatch::FormatDisplayMessage() const
|
||||||
|
{
|
||||||
|
return wxsFormat(
|
||||||
|
m_message_user + L"\n\n" +
|
||||||
|
wxsFormat(
|
||||||
|
L"Savestate game/crc mismatch. Cdvd CRC: 0x%X Game CRC: 0x%X\n",
|
||||||
|
Crc_Savestate, Crc_Cdvd
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -50,6 +50,58 @@ enum FreezeSectionId
|
||||||
FreezeId_Unknown,
|
FreezeId_Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Exception
|
||||||
|
{
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
// Savestate Exceptions:
|
||||||
|
// UnsupportedStateVersion / StateCrcMismatch
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// thrown when the savestate being loaded isn't supported.
|
||||||
|
//
|
||||||
|
class UnsupportedStateVersion : public virtual SaveStateLoadError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
u32 Version; // version number of the unsupported state.
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( UnsupportedStateVersion )
|
||||||
|
|
||||||
|
explicit UnsupportedStateVersion( int version, const wxString& objname=wxEmptyString )
|
||||||
|
{
|
||||||
|
StreamName = objname;
|
||||||
|
Version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A recoverable exception thrown when the CRC of the savestate does not match the
|
||||||
|
// CRC returned by the Cdvd driver.
|
||||||
|
// [feature not implemented yet]
|
||||||
|
//
|
||||||
|
class StateCrcMismatch : public virtual SaveStateLoadError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
u32 Crc_Savestate;
|
||||||
|
u32 Crc_Cdvd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( StateCrcMismatch )
|
||||||
|
|
||||||
|
explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd, const wxString& objname=wxEmptyString )
|
||||||
|
{
|
||||||
|
StreamName = objname;
|
||||||
|
Crc_Savestate = crc_save;
|
||||||
|
Crc_Cdvd = crc_cdvd;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// SaveStateBase class
|
// SaveStateBase class
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -207,7 +207,11 @@ void Pcsx2App::OnLogicalVsync( wxCommandEvent& evt )
|
||||||
{
|
{
|
||||||
if( !SysHasValidState() || g_plugins == NULL ) return;
|
if( !SysHasValidState() || g_plugins == NULL ) return;
|
||||||
|
|
||||||
if( PADupdate != NULL ) PADupdate(0);
|
// Only call PADupdate here if we're using GSopen2. Legacy GSopen plugins have the
|
||||||
|
// GS window belonging to the MTGS thread.
|
||||||
|
if( (PADupdate != NULL) && (GSopen2 != NULL) && (m_gsFrame != NULL) )
|
||||||
|
PADupdate(0);
|
||||||
|
|
||||||
const keyEvent* ev = PADkeyEvent();
|
const keyEvent* ev = PADkeyEvent();
|
||||||
|
|
||||||
if( (ev != NULL) && (ev->key != 0) )
|
if( (ev != NULL) && (ev->key != 0) )
|
||||||
|
@ -369,6 +373,12 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
Console.Warning( "User canceled BIOS configuration." );
|
Console.Warning( "User canceled BIOS configuration." );
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
catch( Exception::SaveStateLoadError& ex)
|
||||||
|
{
|
||||||
|
// Saved state load failed.
|
||||||
|
Console.Warning( ex.FormatDiagnosticMessage() );
|
||||||
|
CoreThread.Resume();
|
||||||
|
}
|
||||||
catch( Exception::PluginInitError& ex )
|
catch( Exception::PluginInitError& ex )
|
||||||
{
|
{
|
||||||
if( m_CorePlugins ) m_CorePlugins->Shutdown();
|
if( m_CorePlugins ) m_CorePlugins->Shutdown();
|
||||||
|
@ -430,14 +440,6 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
|
||||||
{
|
{
|
||||||
Console.Warning( ex.FormatDiagnosticMessage() );
|
Console.Warning( ex.FormatDiagnosticMessage() );
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
catch( Exception::BadSavedState& ex)
|
|
||||||
{
|
|
||||||
// Saved state load failed.
|
|
||||||
Console.Warning( ex.FormatDiagnosticMessage() );
|
|
||||||
CoreThread.Resume();
|
|
||||||
}
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
catch( Exception::RuntimeError& ex )
|
catch( Exception::RuntimeError& ex )
|
||||||
{
|
{
|
||||||
// Runtime errors which have been unhandled should still be safe to recover from,
|
// Runtime errors which have been unhandled should still be safe to recover from,
|
||||||
|
|
Loading…
Reference in New Issue