mirror of https://github.com/PCSX2/pcsx2.git
Mostly-new host exception system (host meaning the C++ / SEH exceptions, not the VM's PS2/MIPS exceptions). Main purpose is to make specifying diagnostic and end-user messages more sane. Secondary goal was to remove the need for C++ multiple and virtual inheritance, which are buggy in MSVC still, and problematic even when they aren't buggy.
I also re-implemented R5900 runtime exception handling for TLB Miss and such (devbuilds only, for now). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3335 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
f058e38f5b
commit
1c7fc3e176
|
@ -122,7 +122,7 @@ extern pxDoAssertFnType* pxDoAssert;
|
||||||
# define pxAssertDev(cond, msg) pxAssertRel(cond, msg)
|
# define pxAssertDev(cond, msg) pxAssertRel(cond, msg)
|
||||||
|
|
||||||
# define pxAssumeMsg(cond, msg) (__assume(cond))
|
# define pxAssumeMsg(cond, msg) (__assume(cond))
|
||||||
# define pxAssumeDev(cond, msg) pxAssumeMsg(cond, msg)
|
# define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
|
||||||
|
|
||||||
# define pxFail(msg) (__assume(false))
|
# define pxFail(msg) (__assume(false))
|
||||||
# define pxFailDev(msg) pxAssumeDev(false, msg)
|
# define pxFailDev(msg) pxAssumeDev(false, msg)
|
||||||
|
|
|
@ -108,6 +108,30 @@ static const pxEnumEnd_t pxEnumEnd = {};
|
||||||
classname& operator=(const classname&)
|
classname& operator=(const classname&)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// ScopedBool - Makes sure a boolean is set back to FALSE when current scope is left
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Exception-safe way of tracking entry and exit of various functions of execution zones.
|
||||||
|
//
|
||||||
|
class ScopedBool
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool* m_boolme;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScopedBool(bool& boolme)
|
||||||
|
{
|
||||||
|
boolme = true;
|
||||||
|
m_boolme = &boolme;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedBool() throw()
|
||||||
|
{
|
||||||
|
m_boolme = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// macro provided for tagging translation strings, without actually running them through the
|
// macro provided for tagging translation strings, without actually running them through the
|
||||||
// translator (which the _() does automatically, and sometimes we don't want that). This is
|
// translator (which the _() does automatically, and sometimes we don't want that). This is
|
||||||
|
|
|
@ -66,7 +66,6 @@ namespace Exception
|
||||||
protected:
|
protected:
|
||||||
wxString m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
|
wxString m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
|
||||||
wxString m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
|
wxString m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
|
||||||
wxString m_stacktrace; // contains the stack trace string dump (unimplemented)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode.
|
virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode.
|
||||||
|
@ -77,23 +76,20 @@ namespace Exception
|
||||||
wxString& DiagMsg() { return m_message_diag; }
|
wxString& DiagMsg() { return m_message_diag; }
|
||||||
wxString& UserMsg() { return m_message_user; }
|
wxString& UserMsg() { return m_message_user; }
|
||||||
|
|
||||||
|
BaseException& SetBothMsgs( const char* msg_diag );
|
||||||
|
BaseException& SetDiagMsg( const wxString& msg_diag );
|
||||||
|
BaseException& SetUserMsg( const wxString& msg_user );
|
||||||
|
|
||||||
// Returns a message suitable for diagnostic / logging purposes.
|
// Returns a message suitable for diagnostic / logging purposes.
|
||||||
// This message is always in English, and includes a full stack trace.
|
// This message is always in English, and includes a full stack trace.
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
|
||||||
// Returns a message suitable for end-user display.
|
// Returns a message suitable for end-user display.
|
||||||
// This message is usually meant for display in a user popup or such.
|
// This message is usually meant for display in a user popup or such.
|
||||||
virtual wxString FormatDisplayMessage() const { return m_message_user; }
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
|
||||||
virtual void Rethrow() const=0;
|
virtual void Rethrow() const=0;
|
||||||
virtual BaseException* Clone() const=0;
|
virtual BaseException* Clone() const=0;
|
||||||
|
|
||||||
protected:
|
|
||||||
// Construction using two pre-formatted pre-translated messages
|
|
||||||
void InitBaseEx( const wxString& msg_eng, const wxString& msg_xlt );
|
|
||||||
|
|
||||||
// Construction using one translation key.
|
|
||||||
void InitBaseEx( const char* msg_eng );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -118,6 +114,9 @@ namespace Exception
|
||||||
virtual u32 GetPc() const=0;
|
virtual u32 GetPc() const=0;
|
||||||
virtual bool IsDelaySlot() const=0;
|
virtual bool IsDelaySlot() const=0;
|
||||||
virtual wxString Message() const { return m_message; }
|
virtual wxString Message() const { return m_message; }
|
||||||
|
|
||||||
|
virtual void Rethrow() const=0;
|
||||||
|
virtual Ps2Generic* Clone() const=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some helper macros for defining the standard constructors of internationalized constructors
|
// Some helper macros for defining the standard constructors of internationalized constructors
|
||||||
|
@ -129,46 +128,44 @@ namespace Exception
|
||||||
// it will be optionally translated.
|
// it will be optionally translated.
|
||||||
//
|
//
|
||||||
// BUGZ?? I'd rather use 'classname' on the Clone() prototype, but for some reason it generates
|
// BUGZ?? I'd rather use 'classname' on the Clone() prototype, but for some reason it generates
|
||||||
// ambiguity errors on virtual inheritence (it really shouldn't!). So I have to force it to the
|
// ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
|
||||||
// BaseException base class. Not sure if this is Stupid Standard Tricks or Stupid MSVC Tricks. --air
|
// BaseException base class. Not sure if this is Stupid Standard Tricks or Stupid MSVC Tricks. --air
|
||||||
//
|
//
|
||||||
// (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
|
// (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
|
||||||
//
|
//
|
||||||
#define DEFINE_EXCEPTION_COPYTORS( classname ) \
|
#define DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
|
||||||
virtual ~classname() throw() {} \
|
private: \
|
||||||
virtual void Rethrow() const { throw *this; } \
|
typedef parent _parent; \
|
||||||
virtual BaseException* Clone() const { return new classname( *this ); }
|
public: \
|
||||||
|
|
||||||
// This is here because MSVC's support for covariant return types on Clone() is broken, and will
|
|
||||||
// not work with virtual class inheritance (see DEFINE_EXCEPTION_COPYTORS for details)
|
|
||||||
#define DEFINE_EXCEPTION_COPYTORS_COVARIANT( classname ) \
|
|
||||||
virtual ~classname() throw() {} \
|
virtual ~classname() throw() {} \
|
||||||
virtual void Rethrow() const { throw *this; } \
|
virtual void Rethrow() const { throw *this; } \
|
||||||
virtual classname* Clone() const { return new classname( *this ); }
|
virtual classname* Clone() const { return new classname( *this ); }
|
||||||
|
|
||||||
#define DEFINE_RUNTIME_EXCEPTION( classname, defmsg ) \
|
#define DEFINE_EXCEPTION_MESSAGES( classname ) \
|
||||||
DEFINE_EXCEPTION_COPYTORS( classname ) \
|
public: \
|
||||||
\
|
classname& SetBothMsgs( const char* msg_diag ) { BaseException::SetBothMsgs(msg_diag); return *this; } \
|
||||||
explicit classname( const char* msg=defmsg ) { BaseException::InitBaseEx( msg ); } \
|
classname& SetDiagMsg( const wxString& msg_diag ) { m_message_diag = msg_diag; return *this; } \
|
||||||
explicit classname( const wxString& msg_eng, const wxString& msg_xlt ) { BaseException::InitBaseEx( msg_eng, msg_xlt); }
|
classname& SetUserMsg( const wxString& msg_user ) { m_message_user = msg_user; return *this; }
|
||||||
|
|
||||||
|
#define DEFINE_RUNTIME_EXCEPTION( classname, parent, message ) \
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
|
||||||
|
classname() { SetDiagMsg(wxT(message)); } \
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( classname )
|
||||||
|
|
||||||
#define DEFINE_LOGIC_EXCEPTION( classname, defmsg ) \
|
|
||||||
DEFINE_EXCEPTION_COPYTORS( classname ) \
|
|
||||||
\
|
|
||||||
explicit classname( const char* msg=defmsg ) { BaseException::InitBaseEx( msg ); } \
|
|
||||||
explicit classname( const wxString& msg_eng ) { BaseException::InitBaseEx( msg_eng, wxEmptyString ); }
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
// RuntimeError - Generalized Exceptions with Recoverable Traits!
|
// RuntimeError - Generalized Exceptions with Recoverable Traits!
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class RuntimeError : public virtual BaseException
|
class RuntimeError : public BaseException
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( RuntimeError, BaseException )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( RuntimeError )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool IsSilent;
|
bool IsSilent;
|
||||||
public:
|
|
||||||
DEFINE_RUNTIME_EXCEPTION( RuntimeError, wxLt("An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter.") )
|
|
||||||
|
|
||||||
|
RuntimeError() { IsSilent = false; }
|
||||||
RuntimeError( const std::runtime_error& ex, const wxString& prefix=wxEmptyString );
|
RuntimeError( const std::runtime_error& ex, const wxString& prefix=wxEmptyString );
|
||||||
RuntimeError( const std::exception& ex, const wxString& prefix=wxEmptyString );
|
RuntimeError( const std::exception& ex, const wxString& prefix=wxEmptyString );
|
||||||
};
|
};
|
||||||
|
@ -182,18 +179,12 @@ namespace Exception
|
||||||
//
|
//
|
||||||
// I chose to have this exception derive from RuntimeError, since if one is thrown from outside
|
// I chose to have this exception derive from RuntimeError, since if one is thrown from outside
|
||||||
// an App message loop we'll still want it to be handled in a reasonably graceful manner.
|
// an App message loop we'll still want it to be handled in a reasonably graceful manner.
|
||||||
class CancelEvent : public virtual RuntimeError
|
class CancelEvent : public RuntimeError
|
||||||
{
|
{
|
||||||
|
DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, "No reason given." )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_EXCEPTION_COPYTORS( CancelEvent )
|
explicit CancelEvent( const wxString& logmsg )
|
||||||
|
|
||||||
explicit CancelEvent( const char* logmsg )
|
|
||||||
{
|
|
||||||
m_message_diag = fromUTF8( logmsg );
|
|
||||||
// overridden message formatters only use the diagnostic version...
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit CancelEvent( const wxString& logmsg=L"No reason given." )
|
|
||||||
{
|
{
|
||||||
m_message_diag = logmsg;
|
m_message_diag = logmsg;
|
||||||
// overridden message formatters only use the diagnostic version...
|
// overridden message formatters only use the diagnostic version...
|
||||||
|
@ -203,38 +194,33 @@ namespace Exception
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
class ObjectIsNull : public virtual CancelEvent
|
// OutOfMemory
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
// This exception has a custom-formatted Diagnostic string. The parameter give when constructing
|
||||||
|
// the exception is a block/alloc name, which is used as a formatting parameter in the diagnostic
|
||||||
|
// output. The default diagnostic message is "Out of memory exception, while allocating the %s."
|
||||||
|
// where %s is filled in with the block name.
|
||||||
|
//
|
||||||
|
// The user string is not custom-formatted, and should contain *NO* %s tags.
|
||||||
|
//
|
||||||
|
class OutOfMemory : public RuntimeError
|
||||||
{
|
{
|
||||||
|
DEFINE_RUNTIME_EXCEPTION( OutOfMemory, RuntimeError, wxLt("Out of memory?!") )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxString ObjectName;
|
wxString AllocDescription;
|
||||||
|
|
||||||
DEFINE_EXCEPTION_COPYTORS( ObjectIsNull )
|
public:
|
||||||
|
OutOfMemory( const wxString& allocdesc );
|
||||||
explicit ObjectIsNull( const char* objname="unspecified" )
|
|
||||||
{
|
|
||||||
m_message_diag = fromUTF8( objname );
|
|
||||||
// overridden message formatters only use the diagnostic version...
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
// OutOfMemory / InvalidOperation / InvalidArgument / ParseError
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class OutOfMemory : public virtual RuntimeError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_RUNTIME_EXCEPTION( OutOfMemory, wxLt("Out of Memory") )
|
|
||||||
};
|
|
||||||
|
|
||||||
class ParseError : public RuntimeError
|
class ParseError : public RuntimeError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, "Parse error" );
|
||||||
DEFINE_RUNTIME_EXCEPTION( ParseError, "Parse error" );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
@ -245,16 +231,15 @@ namespace Exception
|
||||||
// This exception is a specific type of OutOfMemory error that isn't "really" an out of
|
// This exception is a specific type of OutOfMemory error that isn't "really" an out of
|
||||||
// memory error. More likely it's caused by a plugin or driver reserving a range of memory
|
// memory error. More likely it's caused by a plugin or driver reserving a range of memory
|
||||||
// we'd really like to have access to.
|
// we'd really like to have access to.
|
||||||
class VirtualMemoryMapConflict : public virtual OutOfMemory
|
class VirtualMemoryMapConflict : public OutOfMemory
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, OutOfMemory, wxLt("Virtual memory map confict: Unable to claim specific required memory regions.") )
|
||||||
DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, wxLt("Virtual memory map confict: Unable to claim specific required memory regions.") )
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class HardwareDeficiency : public virtual RuntimeError
|
class HardwareDeficiency : public RuntimeError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, wxLt("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
|
DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, wxLt("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
@ -262,51 +247,28 @@ namespace Exception
|
||||||
// Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
|
// Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define DEFINE_STREAM_EXCEPTION( classname, defmsg ) \
|
#define DEFINE_STREAM_EXCEPTION_ACCESSORS( classname ) \
|
||||||
DEFINE_EXCEPTION_COPYTORS( classname ) \
|
virtual classname& SetStreamName( const wxString& name ) { StreamName = name; return *this; } \
|
||||||
\
|
virtual classname& SetStreamName( const char* name ) { StreamName = fromUTF8(name); return *this; }
|
||||||
explicit classname( const wxString& objname=wxString(), const char* msg=defmsg ) \
|
|
||||||
{ \
|
#define DEFINE_STREAM_EXCEPTION( classname, parent, message ) \
|
||||||
BaseException::InitBaseEx( msg ); \
|
DEFINE_RUNTIME_EXCEPTION( classname, parent, message ) \
|
||||||
StreamName = objname; \
|
classname( const wxString& filename ) { \
|
||||||
|
StreamName = filename; \
|
||||||
|
SetBothMsgs(message); \
|
||||||
} \
|
} \
|
||||||
explicit classname( const wxString& objname, const wxString& msg_eng, const wxString& msg_xlt ) \
|
DEFINE_STREAM_EXCEPTION_ACCESSORS( classname )
|
||||||
{ \
|
|
||||||
BaseException::InitBaseEx( msg_eng, msg_xlt ); \
|
|
||||||
StreamName = objname; \
|
|
||||||
} \
|
|
||||||
explicit classname( const char* objname, const char* msg=defmsg ) \
|
|
||||||
{ \
|
|
||||||
BaseException::InitBaseEx( msg ); \
|
|
||||||
StreamName = fromUTF8( objname ); \
|
|
||||||
} \
|
|
||||||
explicit classname( const char* objname, const wxString& msg_eng, const wxString& msg_xlt ) \
|
|
||||||
{ \
|
|
||||||
BaseException::InitBaseEx( msg_eng, msg_xlt ); \
|
|
||||||
StreamName = fromUTF8( objname ); \
|
|
||||||
} \
|
|
||||||
explicit classname( const char* objname, const wxString& msg_eng ) \
|
|
||||||
{ \
|
|
||||||
BaseException::InitBaseEx( msg_eng, msg_eng ); \
|
|
||||||
StreamName = fromUTF8( objname ); \
|
|
||||||
} \
|
|
||||||
explicit classname( const wxString& objname, const wxString& msg_eng ) \
|
|
||||||
{ \
|
|
||||||
BaseException::InitBaseEx( msg_eng, msg_eng ); \
|
|
||||||
StreamName = objname; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic stream error. Contains the name of the stream and a message.
|
// Generic stream error. Contains the name of the stream and a message.
|
||||||
// This exception is usually thrown via derived classes, except in the (rare) case of a
|
// This exception is usually thrown via derived classes, except in the (rare) case of a
|
||||||
// generic / unknown error.
|
// generic / unknown error.
|
||||||
//
|
//
|
||||||
class Stream : public virtual RuntimeError
|
class Stream : public RuntimeError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_STREAM_EXCEPTION( Stream, RuntimeError, wxLt("General file operation error.") )
|
||||||
wxString StreamName; // name of the stream (if applicable)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_STREAM_EXCEPTION( Stream, "General file operation error." )
|
wxString StreamName; // name of the stream (if applicable)
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
@ -316,42 +278,40 @@ namespace Exception
|
||||||
// connection, or anything else that would indicate a failure to read the data after the
|
// connection, or anything else that would indicate a failure to read the data after the
|
||||||
// stream was successfully opened.
|
// stream was successfully opened.
|
||||||
//
|
//
|
||||||
class BadStream : public virtual Stream
|
class BadStream : public Stream
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_STREAM_EXCEPTION( BadStream, Stream, wxLt("File data is corrupted or incomplete, or the stream connection closed unexpectedly.") )
|
||||||
DEFINE_STREAM_EXCEPTION( BadStream, wxLt("File data is corrupted or incomplete, or the stream connection closed unexpectedly.") )
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A generic exception for odd-ball stream creation errors.
|
// A generic exception for odd-ball stream creation errors.
|
||||||
//
|
//
|
||||||
class CannotCreateStream : public virtual Stream
|
class CannotCreateStream : public Stream
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_STREAM_EXCEPTION( CannotCreateStream, Stream, wxLt("File could not be created or opened.") )
|
||||||
DEFINE_STREAM_EXCEPTION( CannotCreateStream, wxLt("File could not be created or opened.") )
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Exception thrown when an attempt to open a non-existent file is made.
|
// Exception thrown when an attempt to open a non-existent file is made.
|
||||||
// (this exception can also mean file permissions are invalid)
|
// (this exception can also mean file permissions are invalid)
|
||||||
//
|
//
|
||||||
class FileNotFound : public virtual CannotCreateStream
|
class FileNotFound : public CannotCreateStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DEFINE_STREAM_EXCEPTION( FileNotFound, wxLt("File not found.") )
|
DEFINE_STREAM_EXCEPTION( FileNotFound, CannotCreateStream, wxLt("File not found.") )
|
||||||
};
|
};
|
||||||
|
|
||||||
class AccessDenied : public virtual CannotCreateStream
|
class AccessDenied : public CannotCreateStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DEFINE_STREAM_EXCEPTION( AccessDenied, wxLt("Permission denied to file.") )
|
DEFINE_STREAM_EXCEPTION( AccessDenied, CannotCreateStream, wxLt("Permission denied to file.") )
|
||||||
};
|
};
|
||||||
|
|
||||||
// EndOfStream can be used either as an error, or used just as a shortcut for manual
|
// EndOfStream can be used either as an error, or used just as a shortcut for manual
|
||||||
// feof checks.
|
// feof checks.
|
||||||
//
|
//
|
||||||
class EndOfStream : public virtual Stream
|
class EndOfStream : public Stream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DEFINE_STREAM_EXCEPTION( EndOfStream, wxLt("Unexpected end of file or stream.") );
|
DEFINE_STREAM_EXCEPTION( EndOfStream, Stream, wxLt("Unexpected end of file or stream.") );
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
|
@ -360,13 +320,14 @@ namespace Exception
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class WinApiError : public RuntimeError
|
class WinApiError : public RuntimeError
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( WinApiError, RuntimeError )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( WinApiError )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int ErrorId;
|
int ErrorId;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_EXCEPTION_COPYTORS( WinApiError )
|
WinApiError();
|
||||||
|
|
||||||
WinApiError( const char* msg="" );
|
|
||||||
|
|
||||||
wxString GetMsgFromWindows() const;
|
wxString GetMsgFromWindows() const;
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
|
|
@ -233,8 +233,8 @@ template< int Precision >
|
||||||
FixedInt<Precision> FixedInt<Precision>::FromString( const wxString parseFrom )
|
FixedInt<Precision> FixedInt<Precision>::FromString( const wxString parseFrom )
|
||||||
{
|
{
|
||||||
FixedInt<Precision> dest;
|
FixedInt<Precision> dest;
|
||||||
if( !TryFromString( dest, parseFrom ) ) throw Exception::ParseError(
|
if( !TryFromString( dest, parseFrom ) ) throw Exception::ParseError()
|
||||||
wxsFormat(L"Parse error on FixedInt<%d>::FromString", Precision), wxEmptyString
|
.SetDiagMsg(wxsFormat(L"Parse error on FixedInt<%d>::FromString", Precision));
|
||||||
);
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,30 +22,6 @@
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// IThread - Interface for the public access to pxThread.
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Class usage: Can be used for allowing safe nullification of a thread handle. Rather
|
|
||||||
// than being NULL'd, the handle can be mapped to an IThread implementation which acts
|
|
||||||
// as a do-nothing placebo or an assertion generator.
|
|
||||||
//
|
|
||||||
class IThread
|
|
||||||
{
|
|
||||||
DeclareNoncopyableObject(IThread);
|
|
||||||
|
|
||||||
public:
|
|
||||||
IThread() {}
|
|
||||||
virtual ~IThread() throw() {}
|
|
||||||
|
|
||||||
virtual bool IsSelf() const { return false; }
|
|
||||||
virtual bool IsRunning() { return false; }
|
|
||||||
|
|
||||||
virtual void Start() {}
|
|
||||||
virtual void Cancel( bool isBlocking = true ) {}
|
|
||||||
virtual void Block() {}
|
|
||||||
virtual bool Detach() { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ThreadDeleteEvent
|
// ThreadDeleteEvent
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -109,7 +85,7 @@ namespace Threading
|
||||||
// no dependency options for ensuring correct static var initializations). Use heap
|
// no dependency options for ensuring correct static var initializations). Use heap
|
||||||
// allocation to create thread objects instead.
|
// allocation to create thread objects instead.
|
||||||
//
|
//
|
||||||
class pxThread : public virtual IThread
|
class pxThread
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(pxThread);
|
DeclareNoncopyableObject(pxThread);
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ protected:
|
||||||
m_size = initSize;
|
m_size = initSize;
|
||||||
|
|
||||||
if( m_ptr == NULL )
|
if( m_ptr == NULL )
|
||||||
throw Exception::OutOfMemory();
|
throw Exception::OutOfMemory(name + wxsFormat(L" (SafeArray::constructor) [size=%d]", initSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual T* _virtual_realloc( int newsize )
|
virtual T* _virtual_realloc( int newsize )
|
||||||
|
@ -138,7 +138,7 @@ public:
|
||||||
m_size = initialSize;
|
m_size = initialSize;
|
||||||
|
|
||||||
if( (initialSize != 0) && (m_ptr == NULL) )
|
if( (initialSize != 0) && (m_ptr == NULL) )
|
||||||
throw Exception::OutOfMemory();
|
throw Exception::OutOfMemory(name + wxsFormat(L" (SafeArray::constructor) [size=%d]", initialSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears the contents of the array to zero, and frees all memory allocations.
|
// Clears the contents of the array to zero, and frees all memory allocations.
|
||||||
|
@ -163,17 +163,10 @@ public:
|
||||||
|
|
||||||
m_ptr = _virtual_realloc( newsize );
|
m_ptr = _virtual_realloc( newsize );
|
||||||
if( m_ptr == NULL )
|
if( m_ptr == NULL )
|
||||||
{
|
throw Exception::OutOfMemory(Name +
|
||||||
throw Exception::OutOfMemory(
|
wxsFormat(L" (SafeArray::ExactAlloc) [oldsize=%d] [newsize=%d]", m_size, newsize)
|
||||||
wxsFormat( // english (for diagnostic)
|
|
||||||
L"Out-of-memory on SafeArray block re-allocation.\n"
|
|
||||||
L"Old size: %d bytes, New size: %d bytes.",
|
|
||||||
m_size, newsize
|
|
||||||
),
|
|
||||||
// internationalized!
|
|
||||||
wxsFormat( _("Out of memory, trying to allocate %d bytes."), newsize )
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
m_size = newsize;
|
m_size = newsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,24 +255,27 @@ public:
|
||||||
safe_free( m_ptr );
|
safe_free( m_ptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit SafeList( const wxChar* name=L"Unnamed" ) :
|
explicit SafeList( const wxChar* name=L"Unnamed" )
|
||||||
Name( name )
|
: Name( name )
|
||||||
, ChunkSize( DefaultChunkSize )
|
|
||||||
, m_ptr( NULL )
|
|
||||||
, m_allocsize( 0 )
|
|
||||||
, m_length( 0 )
|
|
||||||
{
|
{
|
||||||
|
ChunkSize = DefaultChunkSize;
|
||||||
|
m_ptr = NULL;
|
||||||
|
m_allocsize = 0;
|
||||||
|
m_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit SafeList( int initialSize, const wxChar* name=L"Unnamed" ) :
|
explicit SafeList( int initialSize, const wxChar* name=L"Unnamed" )
|
||||||
Name( name )
|
: Name( name )
|
||||||
, ChunkSize( DefaultChunkSize )
|
|
||||||
, m_ptr( (T*)malloc( initialSize * sizeof(T) ) )
|
|
||||||
, m_allocsize( initialSize )
|
|
||||||
, m_length( 0 )
|
|
||||||
{
|
{
|
||||||
|
ChunkSize = DefaultChunkSize;
|
||||||
|
m_allocsize = initialSize;
|
||||||
|
m_length = 0;
|
||||||
|
m_ptr = (T*)malloc( initialSize * sizeof(T) );
|
||||||
|
|
||||||
if( m_ptr == NULL )
|
if( m_ptr == NULL )
|
||||||
throw Exception::OutOfMemory();
|
throw Exception::OutOfMemory(Name +
|
||||||
|
wxsFormat(L" (SafeList::Constructor) [length=%d]", m_length)
|
||||||
|
);
|
||||||
|
|
||||||
for( int i=0; i<m_allocsize; ++i )
|
for( int i=0; i<m_allocsize; ++i )
|
||||||
{
|
{
|
||||||
|
@ -310,18 +306,9 @@ public:
|
||||||
const int newalloc = blockSize + ChunkSize;
|
const int newalloc = blockSize + ChunkSize;
|
||||||
m_ptr = _virtual_realloc( newalloc );
|
m_ptr = _virtual_realloc( newalloc );
|
||||||
if( m_ptr == NULL )
|
if( m_ptr == NULL )
|
||||||
{
|
throw Exception::OutOfMemory(Name +
|
||||||
throw Exception::OutOfMemory(
|
wxsFormat(L" (SafeList::MakeRoomFor) [oldlen=%d] [newlen=%d]", m_length, blockSize)
|
||||||
// English Diagnostic message:
|
|
||||||
wxsFormat(
|
|
||||||
L"Out-of-memory on SafeList block re-allocation.\n"
|
|
||||||
L"Name: %s, Old size: %d bytes, New size: %d bytes",
|
|
||||||
Name.c_str(), m_allocsize, newalloc
|
|
||||||
),
|
|
||||||
|
|
||||||
wxsFormat( _("Out of memory, trying to allocate %d bytes."), newalloc )
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
for( ; m_allocsize<newalloc; ++m_allocsize )
|
for( ; m_allocsize<newalloc; ++m_allocsize )
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,23 +63,30 @@ namespace Threading
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
class BaseThreadError : public virtual RuntimeError
|
class BaseThreadError : public RuntimeError
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( BaseThreadError, RuntimeError )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( BaseThreadError )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Threading::pxThread* m_thread;
|
Threading::pxThread* m_thread;
|
||||||
|
|
||||||
DEFINE_EXCEPTION_COPYTORS( BaseThreadError )
|
protected:
|
||||||
|
BaseThreadError() {
|
||||||
explicit BaseThreadError( Threading::pxThread* _thread=NULL )
|
m_thread = NULL;
|
||||||
{
|
|
||||||
m_thread = _thread;
|
|
||||||
BaseException::InitBaseEx( "Unspecified thread error" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseThreadError( Threading::pxThread& _thread )
|
public:
|
||||||
|
explicit BaseThreadError( Threading::pxThread* _thread )
|
||||||
|
{
|
||||||
|
m_thread = _thread;
|
||||||
|
m_message_diag = L"An unspecified thread-related error occurred (thread=%s)";
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit BaseThreadError( Threading::pxThread& _thread )
|
||||||
{
|
{
|
||||||
m_thread = &_thread;
|
m_thread = &_thread;
|
||||||
BaseException::InitBaseEx( "Unspecified thread error" );
|
m_message_diag = L"An unspecified thread-related error occurred (thread=%s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
@ -89,27 +96,21 @@ namespace Exception
|
||||||
const Threading::pxThread& Thread() const;
|
const Threading::pxThread& Thread() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadCreationError : public virtual BaseThreadError
|
class ThreadCreationError : public BaseThreadError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS( ThreadCreationError, BaseThreadError )
|
||||||
DEFINE_EXCEPTION_COPYTORS( ThreadCreationError )
|
|
||||||
|
|
||||||
explicit ThreadCreationError( Threading::pxThread* _thread=NULL, const char* msg="Creation of thread '%s' failed." )
|
public:
|
||||||
|
explicit ThreadCreationError( Threading::pxThread* _thread )
|
||||||
{
|
{
|
||||||
m_thread = _thread;
|
m_thread = _thread;
|
||||||
BaseException::InitBaseEx( msg );
|
SetBothMsgs( "Thread creation failure. An unspecified error occurred while trying to create the %s thread." );
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadCreationError( Threading::pxThread& _thread, const char* msg="Creation of thread '%s' failed." )
|
explicit ThreadCreationError( Threading::pxThread& _thread )
|
||||||
{
|
{
|
||||||
m_thread = &_thread;
|
m_thread = &_thread;
|
||||||
BaseException::InitBaseEx( msg );
|
SetBothMsgs( "Thread creation failure. An unspecified error occurred while trying to create the %s thread." );
|
||||||
}
|
|
||||||
|
|
||||||
ThreadCreationError( Threading::pxThread& _thread, const wxString& msg_diag, const wxString& msg_user )
|
|
||||||
{
|
|
||||||
m_thread = &_thread;
|
|
||||||
BaseException::InitBaseEx( msg_diag, msg_user );
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ T* Threading::TlsVariable<T>::GetPtr() const
|
||||||
{
|
{
|
||||||
pthread_setspecific( m_thread_key, result = (T*)_aligned_malloc( sizeof(T), 16 ) );
|
pthread_setspecific( m_thread_key, result = (T*)_aligned_malloc( sizeof(T), 16 ) );
|
||||||
if( result == NULL )
|
if( result == NULL )
|
||||||
throw Exception::OutOfMemory( "Out of memory allocating thread local storage variable." );
|
throw Exception::OutOfMemory( L"Out of memory allocating thread local storage variable." );
|
||||||
*result = m_initval;
|
*result = m_initval;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -23,14 +23,9 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wxString GetEnglish( const char* msg )
|
static wxString GetTranslation( const char* msg )
|
||||||
{
|
{
|
||||||
return fromUTF8(msg);
|
return msg ? wxGetTranslation( fromUTF8(msg) ) : wxString();
|
||||||
}
|
|
||||||
|
|
||||||
wxString GetTranslation( const char* msg )
|
|
||||||
{
|
|
||||||
return wxGetTranslation( fromUTF8(msg) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -132,71 +127,91 @@ __forceinline void pxOnAssert( const DiagnosticOrigin& origin, const char* msg)
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Exception Namespace Implementations (Format message handlers for general exceptions)
|
// BaseException (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
BaseException::~BaseException() throw() {}
|
BaseException::~BaseException() throw() {}
|
||||||
|
|
||||||
void BaseException::InitBaseEx( const wxString& msg_eng, const wxString& msg_xlt )
|
BaseException& BaseException::SetBothMsgs( const char* msg_diag )
|
||||||
{
|
{
|
||||||
m_message_diag = msg_eng;
|
m_message_user = GetTranslation( msg_diag );
|
||||||
m_message_user = msg_xlt.IsEmpty() ? msg_eng : msg_xlt;
|
return SetDiagMsg( fromUTF8(msg_diag) );
|
||||||
|
|
||||||
// Linux/GCC exception handling is still suspect (this is likely to do with GCC more
|
|
||||||
// than linux), and fails to propagate exceptions up the stack from EErec code. This
|
|
||||||
// could likely be because of the EErec using EBP. So to ensure the user at least
|
|
||||||
// gets a log of the error, we output to console here in the constructor.
|
|
||||||
|
|
||||||
#ifdef __LINUX__
|
|
||||||
//wxLogError( msg_eng.c_str() );
|
|
||||||
Console.Error( msg_eng );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// given message is assumed to be a translation key, and will be stored in translated
|
BaseException& BaseException::SetDiagMsg( const wxString& msg_diag )
|
||||||
// and untranslated forms.
|
|
||||||
void BaseException::InitBaseEx( const char* msg_eng )
|
|
||||||
{
|
{
|
||||||
m_message_diag = GetEnglish( msg_eng );
|
m_message_diag = msg_diag;
|
||||||
m_message_user = GetTranslation( msg_eng );
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __LINUX__
|
BaseException& BaseException::SetUserMsg( const wxString& msg_user )
|
||||||
//wxLogError( m_message_diag.c_str() );
|
{
|
||||||
Console.Error( msg_eng );
|
m_message_user = msg_user;
|
||||||
#endif
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString BaseException::FormatDiagnosticMessage() const
|
wxString BaseException::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
return m_message_diag + L"\n\n" + m_stacktrace;
|
return m_message_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
wxString BaseException::FormatDisplayMessage() const
|
||||||
|
{
|
||||||
|
return m_message_user.IsEmpty() ? m_message_diag : m_message_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Exception::RuntimeError (implementations)
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
Exception::RuntimeError::RuntimeError( const std::runtime_error& ex, const wxString& prefix )
|
Exception::RuntimeError::RuntimeError( const std::runtime_error& ex, const wxString& prefix )
|
||||||
{
|
{
|
||||||
|
IsSilent = false;
|
||||||
|
|
||||||
const wxString msg( wxsFormat( L"STL Runtime Error%s: %s",
|
const wxString msg( wxsFormat( L"STL Runtime Error%s: %s",
|
||||||
(prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
|
(prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
|
||||||
fromUTF8( ex.what() ).c_str()
|
fromUTF8( ex.what() ).c_str()
|
||||||
) );
|
) );
|
||||||
|
|
||||||
BaseException::InitBaseEx( msg, msg );
|
SetDiagMsg( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
Exception::RuntimeError::RuntimeError( const std::exception& ex, const wxString& prefix )
|
Exception::RuntimeError::RuntimeError( const std::exception& ex, const wxString& prefix )
|
||||||
{
|
{
|
||||||
|
IsSilent = false;
|
||||||
|
|
||||||
const wxString msg( wxsFormat( L"STL Exception%s: %s",
|
const wxString msg( wxsFormat( L"STL Exception%s: %s",
|
||||||
(prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
|
(prefix.IsEmpty() ? prefix.c_str() : wxsFormat(L" (%s)", prefix.c_str()).c_str()),
|
||||||
fromUTF8( ex.what() ).c_str()
|
fromUTF8( ex.what() ).c_str()
|
||||||
) );
|
) );
|
||||||
|
|
||||||
BaseException::InitBaseEx( msg, msg );
|
SetDiagMsg( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Exception::OutOfMemory (implementations)
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
Exception::OutOfMemory::OutOfMemory( const wxString& allocdesc )
|
||||||
|
{
|
||||||
|
AllocDescription = allocdesc;
|
||||||
|
m_message_diag = L"Out of memory exception, while allocating the %s.";
|
||||||
|
m_message_user = _("Memory allocation failure! Your system has insufficient memory or resources to meet PCSX2's lofty needs.");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::OutOfMemory::FormatDiagnosticMessage() const
|
||||||
|
{
|
||||||
|
return wxsFormat(m_message_diag, AllocDescription.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::OutOfMemory::FormatDisplayMessage() const
|
||||||
|
{
|
||||||
|
if (m_message_user.IsEmpty()) return FormatDisplayMessage();
|
||||||
|
return m_message_user + wxsFormat( L"\n\nInternal allocation descriptor: %s", AllocDescription.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
wxString Exception::CancelEvent::FormatDiagnosticMessage() const
|
wxString Exception::CancelEvent::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
// FIXME: This should probably just log a single line from the stacktrace.. ?
|
|
||||||
return L"Action canceled: " + m_message_diag;
|
return L"Action canceled: " + m_message_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,35 +220,20 @@ wxString Exception::CancelEvent::FormatDisplayMessage() const
|
||||||
return L"Action canceled: " + m_message_diag;
|
return L"Action canceled: " + m_message_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
wxString Exception::ObjectIsNull::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
return wxsFormat(
|
|
||||||
L"reference to '%s' failed : handle is null.",
|
|
||||||
m_message_diag.c_str()
|
|
||||||
) + m_stacktrace;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString Exception::ObjectIsNull::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
return wxsFormat(
|
|
||||||
L"reference to '%s' failed : handle is null.",
|
|
||||||
m_message_diag.c_str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
wxString Exception::Stream::FormatDiagnosticMessage() const
|
wxString Exception::Stream::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
return wxsFormat(
|
return wxsFormat(
|
||||||
L"Stream exception: %s\n\tFile/Object: %s",
|
L"%s\n\tFile/Object: %s",
|
||||||
m_message_diag.c_str(), StreamName.c_str()
|
m_message_diag.c_str(), StreamName.c_str()
|
||||||
) + m_stacktrace;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::Stream::FormatDisplayMessage() const
|
wxString Exception::Stream::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
return m_message_user + L"\n\n" +
|
wxString retval( m_message_user );
|
||||||
wxsFormat( _("Name: %s"), StreamName.c_str() );
|
if (!StreamName.IsEmpty())
|
||||||
|
retval += L"\n\n" + wxsFormat( _("Path: %s"), StreamName.c_str() );
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ Threading::MutexRecursive::MutexRecursive() : Mutex( false )
|
||||||
if( _InterlockedIncrement( &_attr_refcount ) == 1 )
|
if( _InterlockedIncrement( &_attr_refcount ) == 1 )
|
||||||
{
|
{
|
||||||
if( 0 != pthread_mutexattr_init( &_attr_recursive ) )
|
if( 0 != pthread_mutexattr_init( &_attr_recursive ) )
|
||||||
throw Exception::OutOfMemory( "Out of memory error initializing the Mutex attributes for recursive mutexing." );
|
throw Exception::OutOfMemory(L"Recursive mutexing attributes");
|
||||||
|
|
||||||
pthread_mutexattr_settype( &_attr_recursive, PTHREAD_MUTEX_RECURSIVE );
|
pthread_mutexattr_settype( &_attr_recursive, PTHREAD_MUTEX_RECURSIVE );
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ void Threading::pxThread::Start()
|
||||||
RethrowException();
|
RethrowException();
|
||||||
|
|
||||||
// And if the thread threw nothing of its own:
|
// And if the thread threw nothing of its own:
|
||||||
throw Exception::ThreadCreationError( this, "(%s thread) Start error: created thread never posted startup semaphore." );
|
throw Exception::ThreadCreationError( this ).SetDiagMsg( L"Thread creation error: %s thread never posted startup semaphore." );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event Rationale (above): Performing this semaphore wait on the created thread is "slow" in the
|
// Event Rationale (above): Performing this semaphore wait on the created thread is "slow" in the
|
||||||
|
|
|
@ -201,3 +201,35 @@ wxString GetOSVersionString()
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Exception::WinApiError (implementations)
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
Exception::WinApiError::WinApiError()
|
||||||
|
{
|
||||||
|
ErrorId = GetLastError();
|
||||||
|
m_message_diag = L"Unspecified Windows API error.";
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::WinApiError::GetMsgFromWindows() const
|
||||||
|
{
|
||||||
|
if (!ErrorId) return L"No valid error number was assigned to this exception!";
|
||||||
|
|
||||||
|
const DWORD BUF_LEN = 2048;
|
||||||
|
TCHAR t_Msg[BUF_LEN];
|
||||||
|
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, ErrorId, 0, t_Msg, BUF_LEN, 0))
|
||||||
|
return wxsFormat( L"Win32 Error #%d: %s", ErrorId, t_Msg );
|
||||||
|
|
||||||
|
return wxsFormat( L"Win32 Error #%d (no text msg available)", ErrorId );
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::WinApiError::FormatDisplayMessage() const
|
||||||
|
{
|
||||||
|
return m_message_user + L"\n\n" + GetMsgFromWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Exception::WinApiError::FormatDiagnosticMessage() const
|
||||||
|
{
|
||||||
|
return m_message_diag + L"\n\t" + GetMsgFromWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,12 +96,7 @@ FILE *_cdvdOpenMechaVer()
|
||||||
Console.Warning("MEC File Not Found , Creating Blank File");
|
Console.Warning("MEC File Not Found , Creating Blank File");
|
||||||
fd = fopen(file, "wb");
|
fd = fopen(file, "wb");
|
||||||
if (fd == NULL)
|
if (fd == NULL)
|
||||||
{
|
throw Exception::CannotCreateStream(mecfile.GetFullPath());
|
||||||
Console.Error( "MEC File Creation failed!" );
|
|
||||||
throw Exception::CannotCreateStream( file );
|
|
||||||
//Msgbox::Alert( "_cdvdOpenMechaVer: Error creating %s", file);
|
|
||||||
//exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fputc(0x03, fd);
|
fputc(0x03, fd);
|
||||||
fputc(0x06, fd);
|
fputc(0x06, fd);
|
||||||
|
@ -136,10 +131,8 @@ FILE *_cdvdOpenNVM()
|
||||||
Console.Warning("NVM File Not Found , Creating Blank File");
|
Console.Warning("NVM File Not Found , Creating Blank File");
|
||||||
fd = fopen(file, "wb");
|
fd = fopen(file, "wb");
|
||||||
if (fd == NULL)
|
if (fd == NULL)
|
||||||
{
|
throw Exception::CannotCreateStream(nvmfile.GetFullPath());
|
||||||
Console.Error( "NVM File Creation failed!" );
|
|
||||||
throw Exception::CannotCreateStream( file );
|
|
||||||
}
|
|
||||||
for (int i=0; i<1024; i++) fputc(0, fd);
|
for (int i=0; i<1024; i++) fputc(0, fd);
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -809,7 +802,7 @@ __forceinline void cdvdReadInterrupt()
|
||||||
|
|
||||||
// Any other value besides 0 should be considered invalid here (wtf is that wacky
|
// Any other value besides 0 should be considered invalid here (wtf is that wacky
|
||||||
// plugin trying to do?)
|
// plugin trying to do?)
|
||||||
jASSUME( cdvd.RErr == 0 );
|
pxAssume( cdvd.RErr == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdvdReadSector() == -1)
|
if (cdvdReadSector() == -1)
|
||||||
|
|
|
@ -94,7 +94,8 @@ IsoDirectory::IsoDirectory(SectorSource& r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isValid )
|
if( !isValid )
|
||||||
throw Exception::FileNotFound( "IsoFS", "Root directory not found on ISO image." );
|
throw Exception::FileNotFound(L"IsoFS") // FIXME: Should report the name of the ISO here...
|
||||||
|
.SetDiagMsg(L"IsoFS could not find the root directory on the ISO image.");
|
||||||
|
|
||||||
DevCon.WriteLn( L"(IsoFS) Filesystem is " + FStype_ToString() );
|
DevCon.WriteLn( L"(IsoFS) Filesystem is " + FStype_ToString() );
|
||||||
Init( rootDirEntry );
|
Init( rootDirEntry );
|
||||||
|
@ -153,7 +154,7 @@ int IsoDirectory::GetIndexOf(const wxString& fileName) const
|
||||||
if(files[i].name == fileName) return i;
|
if(files[i].name == fileName) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Exception::FileNotFound( fileName );
|
throw Exception::FileNotFound(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IsoFileDescriptor& IsoDirectory::GetEntry(const wxString& fileName) const
|
const IsoFileDescriptor& IsoDirectory::GetEntry(const wxString& fileName) const
|
||||||
|
|
|
@ -242,7 +242,7 @@ bool ElfObject::hasHeaders() { return (hasProgramHeaders() && hasSectionHeaders(
|
||||||
void ElfObject::readIso(IsoFile file)
|
void ElfObject::readIso(IsoFile file)
|
||||||
{
|
{
|
||||||
int rsize = file.read(data.GetPtr(), data.GetSizeInBytes());
|
int rsize = file.read(data.GetPtr(), data.GetSizeInBytes());
|
||||||
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream( filename );
|
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfObject::readFile()
|
void ElfObject::readFile()
|
||||||
|
@ -257,19 +257,19 @@ void ElfObject::readFile()
|
||||||
rsize = fread(data.GetPtr(), 1, data.GetSizeInBytes(), f);
|
rsize = fread(data.GetPtr(), 1, data.GetSizeInBytes(), f);
|
||||||
fclose( f );
|
fclose( f );
|
||||||
|
|
||||||
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream( filename );
|
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElfObject::checkElfSize(s64 elfsize)
|
void ElfObject::checkElfSize(s64 elfsize)
|
||||||
{
|
{
|
||||||
if (elfsize > 0xfffffff)
|
if (elfsize > 0xfffffff)
|
||||||
throw Exception::BadStream( filename, wxLt("Illegal ELF file size, over 2GB!") );
|
throw Exception::BadStream(filename).SetBothMsgs(wxLt("Illegal ELF file size over 2GB!"));
|
||||||
|
|
||||||
if (elfsize == -1)
|
if (elfsize == -1)
|
||||||
throw Exception::BadStream( filename, wxLt("Elf file does not exist! ") );
|
throw Exception::BadStream(filename).SetBothMsgs(wxLt("ELF file does not exist!"));
|
||||||
|
|
||||||
if (elfsize == 0)
|
if (elfsize == 0)
|
||||||
throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") );
|
throw Exception::BadStream(filename).SetBothMsgs(wxLt("Unexpected end of ELF file."));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ElfObject::getCRC()
|
u32 ElfObject::getCRC()
|
||||||
|
@ -473,12 +473,14 @@ int GetPS2ElfName( wxString& name )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception::BadStream&)
|
catch (Exception::BadStream& ex)
|
||||||
{
|
{
|
||||||
|
Console.Error(ex.FormatDiagnosticMessage());
|
||||||
return 0; // ISO error
|
return 0; // ISO error
|
||||||
}
|
}
|
||||||
catch( Exception::FileNotFound& )
|
catch( Exception::FileNotFound& ex )
|
||||||
{
|
{
|
||||||
|
Console.Warning(ex.FormatDiagnosticMessage());
|
||||||
return 0; // no SYSTEM.CNF, not a PS1/PS2 disc.
|
return 0; // no SYSTEM.CNF, not a PS1/PS2 disc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#include "R5900OpcodeTables.h"
|
#include "R5900OpcodeTables.h"
|
||||||
|
#include "R5900Exceptions.h"
|
||||||
#include "System/SysThreads.h"
|
#include "System/SysThreads.h"
|
||||||
|
|
||||||
#include "Elfheader.h"
|
#include "Elfheader.h"
|
||||||
|
@ -419,6 +420,12 @@ static void intClear(u32 Addr, u32 Size)
|
||||||
static void intShutdown() {
|
static void intShutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void intThrowException( const BaseR5900Exception& ex )
|
||||||
|
{
|
||||||
|
// No tricks needed; C++ stack unwnding shoud suffice for MSW and GCC alike.
|
||||||
|
ex.Rethrow();
|
||||||
|
}
|
||||||
|
|
||||||
R5900cpu intCpu =
|
R5900cpu intCpu =
|
||||||
{
|
{
|
||||||
intAlloc,
|
intAlloc,
|
||||||
|
@ -429,5 +436,6 @@ R5900cpu intCpu =
|
||||||
intExecute,
|
intExecute,
|
||||||
|
|
||||||
intCheckExecutionState,
|
intCheckExecutionState,
|
||||||
|
intThrowException,
|
||||||
intClear,
|
intClear,
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,7 +38,7 @@ void psxMemAlloc()
|
||||||
m_psxAllMem = vtlb_malloc( m_psxMemSize, 4096 );
|
m_psxAllMem = vtlb_malloc( m_psxMemSize, 4096 );
|
||||||
|
|
||||||
if( m_psxAllMem == NULL)
|
if( m_psxAllMem == NULL)
|
||||||
throw Exception::OutOfMemory( "psxMemAlloc > failed allocating memory for the IOP processor." );
|
throw Exception::OutOfMemory( L"IOP system ram (and roms)" );
|
||||||
|
|
||||||
u8* curpos = m_psxAllMem;
|
u8* curpos = m_psxAllMem;
|
||||||
psxM = curpos; curpos += Ps2MemSize::IopRam;
|
psxM = curpos; curpos += Ps2MemSize::IopRam;
|
||||||
|
@ -54,8 +54,8 @@ void psxMemAlloc()
|
||||||
// which is performed by MemInit and PsxMemInit()
|
// which is performed by MemInit and PsxMemInit()
|
||||||
void psxMemReset()
|
void psxMemReset()
|
||||||
{
|
{
|
||||||
jASSUME( psxMemWLUT != NULL );
|
pxAssume( psxMemWLUT != NULL );
|
||||||
jASSUME( m_psxAllMem != NULL );
|
pxAssume( m_psxAllMem != NULL );
|
||||||
|
|
||||||
DbgCon.WriteLn( "IOP Resetting physical ram..." );
|
DbgCon.WriteLn( "IOP Resetting physical ram..." );
|
||||||
|
|
||||||
|
|
|
@ -936,10 +936,11 @@ void SysMtgsThread::WaitForOpen()
|
||||||
RethrowException();
|
RethrowException();
|
||||||
|
|
||||||
// Not opened yet, and no exceptions. Weird? You decide!
|
// Not opened yet, and no exceptions. Weird? You decide!
|
||||||
// TODO : implement a user confirmation to cancel the action and exit the
|
// [TODO] : implement a user confirmation to cancel the action and exit the
|
||||||
// emulator forcefully, or to continue waiting on the GS.
|
// emulator forcefully, or to continue waiting on the GS.
|
||||||
|
|
||||||
throw Exception::PluginOpenError( PluginId_GS, "The MTGS thread has become unresponsive while waiting for the GS plugin to open." );
|
throw Exception::PluginOpenError( PluginId_GS )
|
||||||
|
.SetBothMsgs(wxLt("The MTGS thread has become unresponsive while waiting for the GS plugin to open."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -639,7 +639,7 @@ void memAlloc()
|
||||||
m_psAllMem = vtlb_malloc( m_allMemSize, 4096 );
|
m_psAllMem = vtlb_malloc( m_allMemSize, 4096 );
|
||||||
|
|
||||||
if( m_psAllMem == NULL)
|
if( m_psAllMem == NULL)
|
||||||
throw Exception::OutOfMemory( "memAlloc > failed to allocate PS2's base ram/rom/scratchpad." );
|
throw Exception::OutOfMemory( L"memAlloc > failed to allocate PS2's base ram/rom/scratchpad." );
|
||||||
|
|
||||||
u8* curpos = m_psAllMem;
|
u8* curpos = m_psAllMem;
|
||||||
psM = curpos; curpos += Ps2MemSize::Base;
|
psM = curpos; curpos += Ps2MemSize::Base;
|
||||||
|
|
|
@ -617,18 +617,22 @@ PluginManager *g_plugins = NULL;
|
||||||
// Plugin-related Exception Implementations
|
// Plugin-related Exception Implementations
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid, const wxString& objname, const char* eng )
|
Exception::PluginOpenError::PluginOpenError( PluginsEnum_t pid )
|
||||||
{
|
{
|
||||||
BaseException::InitBaseEx( eng );
|
|
||||||
StreamName = objname;
|
|
||||||
PluginId = pid;
|
PluginId = pid;
|
||||||
|
m_message_diag = L"%s plugin failed to open!";
|
||||||
|
m_message_user = L"%s plugin failed to open. Your computer may have insufficient resources, or incompatible hardware/drivers.";
|
||||||
}
|
}
|
||||||
|
|
||||||
Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid, const wxString& objname,
|
Exception::PluginInitError::PluginInitError( PluginsEnum_t pid )
|
||||||
const wxString& eng_msg, const wxString& xlt_msg )
|
{
|
||||||
|
PluginId = pid;
|
||||||
|
m_message_diag = L"%s plugin initialization failed!";
|
||||||
|
m_message_user = L"%s plugin failed to initialize. Your system may have insufficient memory or resources needed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid )
|
||||||
{
|
{
|
||||||
BaseException::InitBaseEx( eng_msg, xlt_msg );
|
|
||||||
StreamName = objname;
|
|
||||||
PluginId = pid;
|
PluginId = pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +663,7 @@ wxString Exception::FreezePluginFailure::FormatDiagnosticMessage() const
|
||||||
return wxsFormat(
|
return wxsFormat(
|
||||||
L"%s plugin returned an error while saving the state.\n\n",
|
L"%s plugin returned an error while saving the state.\n\n",
|
||||||
tbl_PluginInfo[PluginId].shortname
|
tbl_PluginInfo[PluginId].shortname
|
||||||
) + m_stacktrace;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::FreezePluginFailure::FormatDisplayMessage() const
|
wxString Exception::FreezePluginFailure::FormatDisplayMessage() const
|
||||||
|
@ -673,7 +677,7 @@ wxString Exception::ThawPluginFailure::FormatDiagnosticMessage() const
|
||||||
return wxsFormat(
|
return wxsFormat(
|
||||||
L"%s plugin returned an error while loading the state.\n\n",
|
L"%s plugin returned an error while loading the state.\n\n",
|
||||||
tbl_PluginInfo[PluginId].shortname
|
tbl_PluginInfo[PluginId].shortname
|
||||||
) + m_stacktrace;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::ThawPluginFailure::FormatDisplayMessage() const
|
wxString Exception::ThawPluginFailure::FormatDisplayMessage() const
|
||||||
|
@ -726,17 +730,15 @@ PluginManager::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxStrin
|
||||||
IsOpened = false;
|
IsOpened = false;
|
||||||
|
|
||||||
if( Filename.IsEmpty() )
|
if( Filename.IsEmpty() )
|
||||||
throw Exception::PluginInitError( pid, "Empty plugin filename." );
|
throw Exception::PluginInitError( pid ).SetDiagMsg( L"Empty plugin filename" );
|
||||||
|
|
||||||
if( !wxFile::Exists( Filename ) )
|
if( !wxFile::Exists( Filename ) )
|
||||||
throw Exception::PluginLoadError( pid, srcfile,
|
throw Exception::PluginLoadError( pid ).SetStreamName(srcfile)
|
||||||
wxLt("The configured %s plugin file was not found")
|
.SetBothMsgs(wxLt("The configured %s plugin file was not found"));
|
||||||
);
|
|
||||||
|
|
||||||
if( !Lib.Load( Filename ) )
|
if( !Lib.Load( Filename ) )
|
||||||
throw Exception::PluginLoadError( pid, Filename,
|
throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
|
||||||
wxLt("The configured %s plugin file is not a valid dynamic library")
|
.SetBothMsgs(wxLt("The configured %s plugin file is not a valid dynamic library"));
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Try to enumerate the new v2.0 plugin interface first.
|
// Try to enumerate the new v2.0 plugin interface first.
|
||||||
|
@ -752,10 +754,9 @@ PluginManager::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxStrin
|
||||||
_PS2EsetEmuVersion SetEmuVersion = (_PS2EsetEmuVersion) Lib.GetSymbol( L"PS2EsetEmuVersion" );
|
_PS2EsetEmuVersion SetEmuVersion = (_PS2EsetEmuVersion) Lib.GetSymbol( L"PS2EsetEmuVersion" );
|
||||||
|
|
||||||
if( GetLibName == NULL || GetLibVersion2 == NULL )
|
if( GetLibName == NULL || GetLibVersion2 == NULL )
|
||||||
throw Exception::PluginLoadError( pid, Filename,
|
throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
|
||||||
L"\nMethod binding failure on GetLibName or GetLibVersion2.\n",
|
.SetDiagMsg(L"%s plugin init failed: Method binding failure on GetLibName or GetLibVersion2.")
|
||||||
_( "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." )
|
.SetUserMsg(_( "The configured %s plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2."));
|
||||||
);
|
|
||||||
|
|
||||||
if( SetEmuVersion != NULL )
|
if( SetEmuVersion != NULL )
|
||||||
SetEmuVersion( "PCSX2", (0ul << 24) | (9ul<<16) | (7ul<<8) | 0 );
|
SetEmuVersion( "PCSX2", (0ul << 24) | (9ul<<16) | (7ul<<8) | 0 );
|
||||||
|
@ -778,10 +779,9 @@ PluginManager::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxStrin
|
||||||
|
|
||||||
int testres = CommonBindings.Test();
|
int testres = CommonBindings.Test();
|
||||||
if( testres != 0 )
|
if( testres != 0 )
|
||||||
throw Exception::PluginLoadError( pid, Filename,
|
throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
|
||||||
wxsFormat( L"Plugin Test failure, return code: %d", testres ),
|
.SetDiagMsg(wxsFormat( L"Plugin Test failure, return code: %d", testres ))
|
||||||
_( "The plugin reports that your hardware or software/drivers are not supported." )
|
.SetUserMsg(_("The plugin reports that your hardware or software/drivers are not supported."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginManager::PluginStatus_t::BindCommon( PluginsEnum_t pid )
|
void PluginManager::PluginStatus_t::BindCommon( PluginsEnum_t pid )
|
||||||
|
@ -800,10 +800,9 @@ void PluginManager::PluginStatus_t::BindCommon( PluginsEnum_t pid )
|
||||||
|
|
||||||
if( *target == NULL )
|
if( *target == NULL )
|
||||||
{
|
{
|
||||||
throw Exception::PluginLoadError( pid, Filename,
|
throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
|
||||||
wxsFormat( L"\nMethod binding failure on: %s\n", current->GetMethodName( pid ).c_str() ),
|
.SetDiagMsg(wxsFormat( L"\nMethod binding failure on: %s\n", current->GetMethodName( pid ).c_str() ))
|
||||||
_( "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." )
|
.SetUserMsg(_("Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target++;
|
target++;
|
||||||
|
@ -827,10 +826,9 @@ void PluginManager::PluginStatus_t::BindRequired( PluginsEnum_t pid )
|
||||||
|
|
||||||
if( *(current->Dest) == NULL )
|
if( *(current->Dest) == NULL )
|
||||||
{
|
{
|
||||||
throw Exception::PluginLoadError( pid, Filename,
|
throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
|
||||||
wxsFormat( L"\nMethod binding failure on: %s\n", current->GetMethodName().c_str() ),
|
.SetDiagMsg(wxsFormat( L"\n%s plugin init error; Method binding failed: %s\n", current->GetMethodName().c_str() ))
|
||||||
_( "Configured plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." )
|
.SetUserMsg(_( "Configured %s plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current++;
|
current++;
|
||||||
|
@ -929,7 +927,7 @@ void PluginManager::Load( const wxString (&folders)[PluginId_Count] )
|
||||||
if( m_mcdPlugin == NULL )
|
if( m_mcdPlugin == NULL )
|
||||||
{
|
{
|
||||||
// fixme: use plugin's GetLastError (not implemented yet!)
|
// fixme: use plugin's GetLastError (not implemented yet!)
|
||||||
throw Exception::PluginLoadError( PluginId_Mcd, wxEmptyString, "Internal Memorycard Plugin failed to load." );
|
throw Exception::PluginLoadError( PluginId_Mcd ).SetDiagMsg(L"Internal Memorycard Plugin failed to load.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SendLogFolder();
|
SendLogFolder();
|
||||||
|
@ -1246,7 +1244,8 @@ void PluginManager::Init()
|
||||||
if( SysPlugins.Mcd == NULL )
|
if( SysPlugins.Mcd == NULL )
|
||||||
{
|
{
|
||||||
// fixme: use plugin's GetLastError (not implemented yet!)
|
// fixme: use plugin's GetLastError (not implemented yet!)
|
||||||
throw Exception::PluginInitError( PluginId_Mcd, "Internal Memorycard Plugin failed to initialize." );
|
throw Exception::PluginInitError( PluginId_Mcd )
|
||||||
|
.SetBothMsgs(wxLt("Internal Memorycard Plugin failed to initialize."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,24 +55,21 @@ struct PluginInfo
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
// Exception thrown when a corrupted or truncated savestate is encountered.
|
// Exception thrown when a corrupted or truncated savestate is encountered.
|
||||||
class SaveStateLoadError : public virtual BadStream
|
class SaveStateLoadError : public BadStream
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_STREAM_EXCEPTION( SaveStateLoadError, BadStream, wxLt("The savestate appears to be corrupt or incomplete.") )
|
||||||
DEFINE_STREAM_EXCEPTION( SaveStateLoadError, wxLt("Load failed: The savestate appears to be corrupt or incomplete.") )
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PluginError : public virtual RuntimeError
|
class PluginError : public RuntimeError
|
||||||
{
|
{
|
||||||
|
DEFINE_RUNTIME_EXCEPTION( PluginError, RuntimeError, "Generic plugin error")
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PluginsEnum_t PluginId;
|
PluginsEnum_t PluginId;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_EXCEPTION_COPYTORS( PluginError )
|
explicit PluginError( PluginsEnum_t pid )
|
||||||
|
|
||||||
PluginError() {}
|
|
||||||
PluginError( PluginsEnum_t pid, const char* msg="Generic plugin error" )
|
|
||||||
{
|
{
|
||||||
BaseException::InitBaseEx( msg );
|
|
||||||
PluginId = pid;
|
PluginId = pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,15 +80,22 @@ namespace Exception
|
||||||
// Plugin load errors occur when initially trying to load plugins during the
|
// Plugin load errors occur when initially trying to load plugins during the
|
||||||
// creation of a PluginManager object. The error may either be due to non-existence,
|
// creation of a PluginManager object. The error may either be due to non-existence,
|
||||||
// corruption, or incompatible versioning.
|
// corruption, or incompatible versioning.
|
||||||
class PluginLoadError : public virtual PluginError, public virtual BadStream
|
class PluginLoadError : public PluginError
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( PluginLoadError, PluginError )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( PluginLoadError )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_EXCEPTION_COPYTORS_COVARIANT( PluginLoadError )
|
wxString StreamName;
|
||||||
|
|
||||||
PluginLoadError( PluginsEnum_t pid, const wxString& objname, const char* eng );
|
protected:
|
||||||
|
PluginLoadError() {}
|
||||||
|
|
||||||
PluginLoadError( PluginsEnum_t pid, const wxString& objname,
|
public:
|
||||||
const wxString& eng_msg, const wxString& xlt_msg );
|
PluginLoadError( PluginsEnum_t pid );
|
||||||
|
|
||||||
|
virtual PluginLoadError& SetStreamName( const wxString& name ) { StreamName = name; return *this; } \
|
||||||
|
virtual PluginLoadError& SetStreamName( const char* name ) { StreamName = fromUTF8(name); return *this; }
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
@ -100,44 +104,46 @@ namespace Exception
|
||||||
// Thrown when a plugin fails it's init() callback. The meaning of this error is entirely
|
// Thrown when a plugin fails it's init() callback. The meaning of this error is entirely
|
||||||
// dependent on the plugin and, in most cases probably never happens (most plugins do little
|
// dependent on the plugin and, in most cases probably never happens (most plugins do little
|
||||||
// more than a couple basic memory reservations during init)
|
// more than a couple basic memory reservations during init)
|
||||||
class PluginInitError : public virtual PluginError
|
class PluginInitError : public PluginError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS( PluginInitError, PluginError )
|
||||||
DEFINE_EXCEPTION_COPYTORS_COVARIANT( PluginInitError )
|
DEFINE_EXCEPTION_MESSAGES( PluginInitError )
|
||||||
|
|
||||||
explicit PluginInitError( PluginsEnum_t pid,
|
protected:
|
||||||
const char* msg=wxLt("%s plugin failed to initialize. Your system may have insufficient memory or resources needed.") )
|
PluginInitError() {}
|
||||||
{
|
|
||||||
BaseException::InitBaseEx( msg );
|
public:
|
||||||
PluginId = pid;
|
PluginInitError( PluginsEnum_t pid );
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Plugin failed to open. Typically this is a non-critical error that means the plugin has
|
// Plugin failed to open. Typically this is a non-critical error that means the plugin has
|
||||||
// not been configured properly by the user, but may also be indicative of a system
|
// not been configured properly by the user, but may also be indicative of a system
|
||||||
class PluginOpenError : public virtual PluginError
|
class PluginOpenError : public PluginError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS( PluginOpenError, PluginError )
|
||||||
DEFINE_EXCEPTION_COPYTORS_COVARIANT( PluginOpenError )
|
DEFINE_EXCEPTION_MESSAGES( PluginOpenError )
|
||||||
|
|
||||||
explicit PluginOpenError( PluginsEnum_t pid,
|
protected:
|
||||||
const char* msg=wxLt("%s plugin failed to open. Your computer may have insufficient resources, or incompatible hardware/drivers.") )
|
PluginOpenError() {}
|
||||||
{
|
|
||||||
BaseException::InitBaseEx( msg );
|
public:
|
||||||
PluginId = pid;
|
explicit PluginOpenError( PluginsEnum_t pid );
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This exception is thrown when a plugin returns an error while trying to save itself.
|
// This exception is thrown when a plugin returns an error while trying to save itself.
|
||||||
// Typically this should be a very rare occurance since a plugin typically shoudn't
|
// Typically this should be a very rare occurance since a plugin typically shoudn't
|
||||||
// be doing memory allocations or file access during state saving.
|
// be doing memory allocations or file access during state saving.
|
||||||
//
|
//
|
||||||
class FreezePluginFailure : public virtual PluginError
|
class FreezePluginFailure : public PluginError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS( FreezePluginFailure, PluginError )
|
||||||
DEFINE_EXCEPTION_COPYTORS( FreezePluginFailure )
|
DEFINE_EXCEPTION_MESSAGES( FreezePluginFailure )
|
||||||
|
|
||||||
explicit FreezePluginFailure( PluginsEnum_t pid)
|
protected:
|
||||||
|
FreezePluginFailure() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FreezePluginFailure( PluginsEnum_t pid )
|
||||||
{
|
{
|
||||||
PluginId = pid;
|
PluginId = pid;
|
||||||
}
|
}
|
||||||
|
@ -146,11 +152,18 @@ namespace Exception
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThawPluginFailure : public virtual PluginError, public virtual SaveStateLoadError
|
class ThawPluginFailure : public SaveStateLoadError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS( ThawPluginFailure, SaveStateLoadError )
|
||||||
DEFINE_EXCEPTION_COPYTORS( ThawPluginFailure )
|
DEFINE_EXCEPTION_MESSAGES( ThawPluginFailure )
|
||||||
|
|
||||||
|
public:
|
||||||
|
PluginsEnum_t PluginId;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ThawPluginFailure() {}
|
||||||
|
|
||||||
|
public:
|
||||||
explicit ThawPluginFailure( PluginsEnum_t pid )
|
explicit ThawPluginFailure( PluginsEnum_t pid )
|
||||||
{
|
{
|
||||||
PluginId = pid;
|
PluginId = pid;
|
||||||
|
|
|
@ -50,9 +50,6 @@ static const uint eeWaitCycles = 3072;
|
||||||
|
|
||||||
bool eeEventTestIsActive = false;
|
bool eeEventTestIsActive = false;
|
||||||
|
|
||||||
R5900Exception::BaseExcept::~BaseExcept() throw (){}
|
|
||||||
|
|
||||||
|
|
||||||
void cpuReset()
|
void cpuReset()
|
||||||
{
|
{
|
||||||
if( GetMTGS().IsOpen() )
|
if( GetMTGS().IsOpen() )
|
||||||
|
@ -367,7 +364,7 @@ u32 g_nextBranchCycle = 0;
|
||||||
// and the recompiler. (moved here to help alleviate redundant code)
|
// and the recompiler. (moved here to help alleviate redundant code)
|
||||||
__forceinline void _cpuBranchTest_Shared()
|
__forceinline void _cpuBranchTest_Shared()
|
||||||
{
|
{
|
||||||
eeEventTestIsActive = true;
|
ScopedBool etest(eeEventTestIsActive);
|
||||||
g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;
|
g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;
|
||||||
|
|
||||||
// ---- Counters -------------
|
// ---- Counters -------------
|
||||||
|
@ -475,8 +472,6 @@ __forceinline void _cpuBranchTest_Shared()
|
||||||
// Apply vsync and other counter nextCycles
|
// Apply vsync and other counter nextCycles
|
||||||
cpuSetNextBranch( nextsCounter, nextCounter );
|
cpuSetNextBranch( nextsCounter, nextCounter );
|
||||||
|
|
||||||
eeEventTestIsActive = false;
|
|
||||||
|
|
||||||
// ---- INTC / DMAC Exceptions -----------------
|
// ---- INTC / DMAC Exceptions -----------------
|
||||||
// Raise the INTC and DMAC interrupts here, which usually throw exceptions.
|
// Raise the INTC and DMAC interrupts here, which usually throw exceptions.
|
||||||
// This should be done last since the IOP and the VU0 can raise several EE
|
// This should be done last since the IOP and the VU0 can raise several EE
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
class BaseR5900Exception;
|
||||||
#ifndef __LINUX__
|
|
||||||
#pragma region Recompiler Stuffs
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Recompiler Stuffs
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
// This code section contains recompiler vars that are used in "shared" code. Placing
|
// This code section contains recompiler vars that are used in "shared" code. Placing
|
||||||
// them in iR5900.h would mean having to include that into more files than I care to
|
// them in iR5900.h would mean having to include that into more files than I care to
|
||||||
// right now, so we're sticking them here for now until a better solution comes along.
|
// right now, so we're sticking them here for now until a better solution comes along.
|
||||||
|
@ -39,12 +39,10 @@ namespace Exception
|
||||||
explicit ExitCpuExecute() { }
|
explicit ExitCpuExecute() { }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#ifndef __LINUX__
|
|
||||||
#pragma endregion
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
// --------------------------------------------------------------------------------------
|
||||||
// EE Bios function name tables.
|
// EE Bios function name tables.
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
namespace R5900 {
|
namespace R5900 {
|
||||||
extern const char* const bios[256];
|
extern const char* const bios[256];
|
||||||
}
|
}
|
||||||
|
@ -349,6 +347,11 @@ struct R5900cpu
|
||||||
//
|
//
|
||||||
void (*CheckExecutionState)();
|
void (*CheckExecutionState)();
|
||||||
|
|
||||||
|
// Safely throws host exceptions from executing code (either recompiled or interpreted).
|
||||||
|
// If this function is called outside the context of the CPU's code execution, then the
|
||||||
|
// given exception will be re-thrown automatically.
|
||||||
|
void (*ThrowException)( const BaseR5900Exception& ex );
|
||||||
|
|
||||||
// Manual recompiled code cache clear; typically useful to recompilers only. Size is
|
// Manual recompiled code cache clear; typically useful to recompilers only. Size is
|
||||||
// in MIPS words (32 bits). Dev note: this callback is nearly obsolete, and might be
|
// in MIPS words (32 bits). Dev note: this callback is nearly obsolete, and might be
|
||||||
// better off replaced with some generic API callbacks from VTLB block protection.
|
// better off replaced with some generic API callbacks from VTLB block protection.
|
||||||
|
|
|
@ -13,60 +13,65 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _R5900_EXCEPTIONS_H_
|
#pragma once
|
||||||
#define _R5900_EXCEPTIONS_H_
|
|
||||||
|
|
||||||
namespace R5900Exception
|
// --------------------------------------------------------------------------------------
|
||||||
|
// BaseR5900Exception
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Abstract base class for R5900 exceptions; contains the cpuRegs instance at the
|
||||||
|
// time the exception is raised.
|
||||||
|
//
|
||||||
|
// Translation note: EE Emulation exceptions are untranslated only. There's really no
|
||||||
|
// point in providing translations for this hardcore mess. :)
|
||||||
|
//
|
||||||
|
class BaseR5900Exception : public Exception::Ps2Generic
|
||||||
{
|
{
|
||||||
using Exception::Ps2Generic;
|
DEFINE_EXCEPTION_COPYTORS(BaseR5900Exception, Exception::Ps2Generic)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
public:
|
||||||
// Abstract base class for R5900 exceptions; contains the cpuRegs instance at the
|
|
||||||
// time the exception is raised.
|
|
||||||
//
|
|
||||||
// Translation note: EE Emulation exceptions are untranslated only. There's really no
|
|
||||||
// point in providing translations for this hardcore mess. :)
|
|
||||||
//
|
|
||||||
class BaseExcept : public virtual Ps2Generic
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
cpuRegisters cpuState;
|
cpuRegisters cpuState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~BaseExcept() throw()=0;
|
|
||||||
|
|
||||||
u32 GetPc() const { return cpuState.pc; }
|
u32 GetPc() const { return cpuState.pc; }
|
||||||
bool IsDelaySlot() const { return !!cpuState.IsDelaySlot; }
|
bool IsDelaySlot() const { return !!cpuState.IsDelaySlot; }
|
||||||
|
|
||||||
protected:
|
wxString& Message() { return m_message; }
|
||||||
|
wxString FormatMessage() const
|
||||||
|
{
|
||||||
|
return wxsFormat(L"(EE pc:%8.8X) ", cpuRegs.pc) + m_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
void Init( const wxString& msg )
|
void Init( const wxString& msg )
|
||||||
{
|
{
|
||||||
m_message = L"(EE) " + msg;
|
m_message = msg;;
|
||||||
cpuState = cpuRegs;
|
cpuState = cpuRegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init( const char*msg )
|
void Init( const char* msg )
|
||||||
{
|
{
|
||||||
m_message = fromUTF8( msg );
|
m_message = fromUTF8( msg );
|
||||||
cpuState = cpuRegs;
|
cpuState = cpuRegs;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
namespace R5900Exception
|
||||||
//
|
{
|
||||||
class BaseAddressError : public BaseExcept
|
// --------------------------------------------------------------------------------------
|
||||||
|
// BaseAddressError
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
class BaseAddressError : public BaseR5900Exception
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS(BaseAddressError, BaseR5900Exception)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool OnWrite;
|
bool OnWrite;
|
||||||
u32 Address;
|
u32 Address;
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~BaseAddressError() throw() {}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Init( u32 ps2addr, bool onWrite, const wxString& msg )
|
void Init( u32 ps2addr, bool onWrite, const wxString& msg )
|
||||||
{
|
{
|
||||||
BaseExcept::Init( wxsFormat( msg+L", addr=0x%x [%s]", ps2addr, onWrite ? L"store" : L"load" ) );
|
_parent::Init( wxsFormat( msg+L", addr=0x%x [%s]", ps2addr, onWrite ? L"store" : L"load" ) );
|
||||||
OnWrite = onWrite;
|
OnWrite = onWrite;
|
||||||
Address = ps2addr;
|
Address = ps2addr;
|
||||||
}
|
}
|
||||||
|
@ -76,54 +81,46 @@ namespace R5900Exception
|
||||||
class AddressError : public BaseAddressError
|
class AddressError : public BaseAddressError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~AddressError() throw() {}
|
|
||||||
|
|
||||||
AddressError( u32 ps2addr, bool onWrite )
|
AddressError( u32 ps2addr, bool onWrite )
|
||||||
{
|
{
|
||||||
BaseAddressError::Init( ps2addr, onWrite, L"Address error" );
|
BaseAddressError::Init( ps2addr, onWrite, L"Address error" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
class TLBMiss : public BaseAddressError
|
class TLBMiss : public BaseAddressError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS(TLBMiss, BaseAddressError)
|
||||||
virtual ~TLBMiss() throw() {}
|
|
||||||
|
|
||||||
|
public:
|
||||||
TLBMiss( u32 ps2addr, bool onWrite )
|
TLBMiss( u32 ps2addr, bool onWrite )
|
||||||
{
|
{
|
||||||
BaseAddressError::Init( ps2addr, onWrite, L"TLB Miss" );
|
BaseAddressError::Init( ps2addr, onWrite, L"TLB Miss" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
class BusError : public BaseAddressError
|
class BusError : public BaseAddressError
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS(BusError, BaseAddressError)
|
||||||
virtual ~BusError() throw() {}
|
|
||||||
|
|
||||||
|
public:
|
||||||
BusError( u32 ps2addr, bool onWrite )
|
BusError( u32 ps2addr, bool onWrite )
|
||||||
{
|
{
|
||||||
BaseAddressError::Init( ps2addr, onWrite, L"Bus Error" );
|
BaseAddressError::Init( ps2addr, onWrite, L"Bus Error" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
class Trap : public BaseR5900Exception
|
||||||
//
|
|
||||||
class Trap : public BaseExcept
|
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS(Trap, BaseR5900Exception)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u16 TrapCode;
|
u16 TrapCode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Trap() throw() {}
|
|
||||||
|
|
||||||
// Generates a trap for immediate-style Trap opcodes
|
// Generates a trap for immediate-style Trap opcodes
|
||||||
Trap()
|
Trap()
|
||||||
{
|
{
|
||||||
BaseExcept::Init( "Trap" );
|
_parent::Init( "Trap" );
|
||||||
TrapCode = 0;
|
TrapCode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,24 +128,19 @@ namespace R5900Exception
|
||||||
// error code in the opcode
|
// error code in the opcode
|
||||||
explicit Trap( u16 trapcode )
|
explicit Trap( u16 trapcode )
|
||||||
{
|
{
|
||||||
BaseExcept::Init( "Trap" ),
|
_parent::Init( "Trap" ),
|
||||||
TrapCode = trapcode;
|
TrapCode = trapcode;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
class DebugBreakpoint : public BaseR5900Exception
|
||||||
//
|
|
||||||
class DebugBreakpoint : public BaseExcept
|
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS(DebugBreakpoint, BaseR5900Exception)
|
||||||
virtual ~DebugBreakpoint() throw() {}
|
|
||||||
|
|
||||||
|
public:
|
||||||
explicit DebugBreakpoint()
|
explicit DebugBreakpoint()
|
||||||
{
|
{
|
||||||
BaseExcept::Init( "Debug Breakpoint" );
|
_parent::Init( "Debug Breakpoint" );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -94,11 +94,9 @@ 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" );
|
wxString msg( L"Savestate data corruption detected while reading tag: " + fromUTF8(src) );
|
||||||
throw Exception::SaveStateLoadError(
|
pxFail( msg );
|
||||||
// Untranslated diagnostic msg (use default msg for translation)
|
throw Exception::SaveStateLoadError().SetDiagMsg(msg);
|
||||||
L"Savestate data corruption detected while reading tag: " + fromUTF8(src)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,10 +227,9 @@ 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::SaveStateLoadError( wxEmptyString,
|
throw Exception::SaveStateLoadError()
|
||||||
wxsFormat( L"Invalid size encountered on section '%s'.", sectname ),
|
.SetDiagMsg(wxsFormat(L"Invalid size encountered on section '%s'.", sectname ))
|
||||||
_("The savestate data is invalid or corrupted.")
|
.SetUserMsg(_("The savestate data is invalid or corrupted."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,10 +255,9 @@ bool SaveStateBase::FreezeSection( int seek_section )
|
||||||
|
|
||||||
if( sectlen != 128 )
|
if( sectlen != 128 )
|
||||||
{
|
{
|
||||||
throw Exception::SaveStateLoadError( wxEmptyString,
|
throw Exception::SaveStateLoadError()
|
||||||
L"Invalid size encountered on BiosVersion section.",
|
.SetDiagMsg(L"Invalid size encountered on BiosVersion section.")
|
||||||
_("The savestate data is invalid or corrupted.")
|
.SetUserMsg(_("The savestate data is invalid or corrupted."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isSeeking )
|
if( isSeeking )
|
||||||
|
@ -281,10 +277,9 @@ bool SaveStateBase::FreezeSection( int seek_section )
|
||||||
Freeze( sectlen );
|
Freeze( sectlen );
|
||||||
if( sectlen != MainMemorySizeInBytes )
|
if( sectlen != MainMemorySizeInBytes )
|
||||||
{
|
{
|
||||||
throw Exception::SaveStateLoadError( wxEmptyString,
|
throw Exception::SaveStateLoadError()
|
||||||
L"Invalid size encountered on MainMemory section.",
|
.SetDiagMsg(L"Invalid size encountered on MainMemory section.")
|
||||||
_("The savestate data is invalid or corrupted.")
|
.SetUserMsg(_("The savestate data is invalid or corrupted."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isSeeking )
|
if( isSeeking )
|
||||||
|
|
|
@ -58,17 +58,20 @@ namespace Exception
|
||||||
|
|
||||||
// thrown when the savestate being loaded isn't supported.
|
// thrown when the savestate being loaded isn't supported.
|
||||||
//
|
//
|
||||||
class UnsupportedStateVersion : public virtual SaveStateLoadError
|
class UnsupportedStateVersion : public SaveStateLoadError
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( UnsupportedStateVersion, SaveStateLoadError )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( UnsupportedStateVersion )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u32 Version; // version number of the unsupported state.
|
u32 Version; // version number of the unsupported state.
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
DEFINE_EXCEPTION_COPYTORS( UnsupportedStateVersion )
|
UnsupportedStateVersion() {}
|
||||||
|
|
||||||
explicit UnsupportedStateVersion( int version, const wxString& objname=wxEmptyString )
|
public:
|
||||||
|
explicit UnsupportedStateVersion( int version )
|
||||||
{
|
{
|
||||||
StreamName = objname;
|
|
||||||
Version = version;
|
Version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,18 +83,21 @@ namespace Exception
|
||||||
// CRC returned by the Cdvd driver.
|
// CRC returned by the Cdvd driver.
|
||||||
// [feature not implemented yet]
|
// [feature not implemented yet]
|
||||||
//
|
//
|
||||||
class StateCrcMismatch : public virtual SaveStateLoadError
|
class StateCrcMismatch : public SaveStateLoadError
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( StateCrcMismatch, SaveStateLoadError )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( StateCrcMismatch )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u32 Crc_Savestate;
|
u32 Crc_Savestate;
|
||||||
u32 Crc_Cdvd;
|
u32 Crc_Cdvd;
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
DEFINE_EXCEPTION_COPYTORS( StateCrcMismatch )
|
StateCrcMismatch() {}
|
||||||
|
|
||||||
explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd, const wxString& objname=wxEmptyString )
|
public:
|
||||||
|
StateCrcMismatch( u32 crc_save, u32 crc_cdvd )
|
||||||
{
|
{
|
||||||
StreamName = objname;
|
|
||||||
Crc_Savestate = crc_save;
|
Crc_Savestate = crc_save;
|
||||||
Crc_Cdvd = crc_cdvd;
|
Crc_Cdvd = crc_cdvd;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,7 @@ class CpuInitializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopedPtr<CpuType> MyCpu;
|
ScopedPtr<CpuType> MyCpu;
|
||||||
|
ScopedPtr<BaseException> ExThrown;
|
||||||
|
|
||||||
CpuInitializer();
|
CpuInitializer();
|
||||||
virtual ~CpuInitializer() throw();
|
virtual ~CpuInitializer() throw();
|
||||||
|
@ -199,14 +200,14 @@ CpuInitializer< CpuType >::CpuInitializer()
|
||||||
catch( Exception::RuntimeError& ex )
|
catch( Exception::RuntimeError& ex )
|
||||||
{
|
{
|
||||||
Console.Error( L"CPU provider error:\n\t" + ex.FormatDiagnosticMessage() );
|
Console.Error( L"CPU provider error:\n\t" + ex.FormatDiagnosticMessage() );
|
||||||
if( MyCpu )
|
|
||||||
MyCpu = NULL;
|
MyCpu = NULL;
|
||||||
|
ExThrown = ex.Clone();
|
||||||
}
|
}
|
||||||
catch( std::runtime_error& ex )
|
catch( std::runtime_error& ex )
|
||||||
{
|
{
|
||||||
Console.Error( L"CPU provider error (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
|
Console.Error( L"CPU provider error (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
|
||||||
if( MyCpu )
|
|
||||||
MyCpu = NULL;
|
MyCpu = NULL;
|
||||||
|
ExThrown = new Exception::RuntimeError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,9 +254,6 @@ SysCoreAllocations::SysCoreAllocations()
|
||||||
|
|
||||||
Console.WriteLn( "Initializing PS2 virtual machine..." );
|
Console.WriteLn( "Initializing PS2 virtual machine..." );
|
||||||
|
|
||||||
m_RecSuccessEE = false;
|
|
||||||
m_RecSuccessIOP = false;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vtlb_Core_Alloc();
|
vtlb_Core_Alloc();
|
||||||
|
@ -266,8 +264,7 @@ SysCoreAllocations::SysCoreAllocations()
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
catch( Exception::OutOfMemory& ex )
|
catch( Exception::OutOfMemory& ex )
|
||||||
{
|
{
|
||||||
wxString newmsg( ex.UserMsg() + L"\n\n" + GetMemoryErrorVM() );
|
ex.UserMsg() += L"\n\n" + GetMemoryErrorVM();
|
||||||
ex.UserMsg() = newmsg;
|
|
||||||
CleanupMess();
|
CleanupMess();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@ -278,12 +275,12 @@ SysCoreAllocations::SysCoreAllocations()
|
||||||
// re-throw std::bad_alloc as something more friendly. This is needed since
|
// re-throw std::bad_alloc as something more friendly. This is needed since
|
||||||
// much of the code uses new/delete internally, which throw std::bad_alloc on fail.
|
// much of the code uses new/delete internally, which throw std::bad_alloc on fail.
|
||||||
|
|
||||||
throw Exception::OutOfMemory(
|
throw Exception::OutOfMemory()
|
||||||
|
.SetDiagMsg(
|
||||||
L"std::bad_alloc caught while trying to allocate memory for the PS2 Virtual Machine.\n"
|
L"std::bad_alloc caught while trying to allocate memory for the PS2 Virtual Machine.\n"
|
||||||
L"Error Details: " + fromUTF8( ex.what() ),
|
L"Error Details: " + fromUTF8( ex.what() )
|
||||||
|
)
|
||||||
GetMemoryErrorVM() // translated
|
.SetUserMsg(GetMemoryErrorVM()); // translated
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLn( "Allocating memory for recompilers..." );
|
Console.WriteLn( "Allocating memory for recompilers..." );
|
||||||
|
@ -292,20 +289,20 @@ SysCoreAllocations::SysCoreAllocations()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
recCpu.Allocate();
|
recCpu.Allocate();
|
||||||
m_RecSuccessEE = true;
|
|
||||||
}
|
}
|
||||||
catch( Exception::RuntimeError& ex )
|
catch( Exception::RuntimeError& ex )
|
||||||
{
|
{
|
||||||
|
m_RecExceptionEE = ex.Clone();
|
||||||
Console.Error( L"EE Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
|
Console.Error( L"EE Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
|
||||||
recCpu.Shutdown();
|
recCpu.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
psxRec.Allocate();
|
psxRec.Allocate();
|
||||||
m_RecSuccessIOP = true;
|
|
||||||
}
|
}
|
||||||
catch( Exception::RuntimeError& ex )
|
catch( Exception::RuntimeError& ex )
|
||||||
{
|
{
|
||||||
|
m_RecExceptionIOP = ex.Clone();
|
||||||
Console.Error( L"IOP Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
|
Console.Error( L"IOP Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
|
||||||
psxRec.Shutdown();
|
psxRec.Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -320,9 +317,13 @@ SysCoreAllocations::SysCoreAllocations()
|
||||||
|
|
||||||
bool SysCoreAllocations::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
|
bool SysCoreAllocations::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
|
||||||
bool SysCoreAllocations::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
|
bool SysCoreAllocations::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
|
||||||
|
BaseException* SysCoreAllocations::GetException_MicroVU0() const { return CpuProviders->microVU0.ExThrown; }
|
||||||
|
BaseException* SysCoreAllocations::GetException_MicroVU1() const { return CpuProviders->microVU1.ExThrown; }
|
||||||
|
|
||||||
bool SysCoreAllocations::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
|
bool SysCoreAllocations::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
|
||||||
bool SysCoreAllocations::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
|
bool SysCoreAllocations::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
|
||||||
|
BaseException* SysCoreAllocations::GetException_SuperVU0() const { return CpuProviders->superVU0.ExThrown; }
|
||||||
|
BaseException* SysCoreAllocations::GetException_SuperVU1() const { return CpuProviders->superVU1.ExThrown; }
|
||||||
|
|
||||||
|
|
||||||
void SysCoreAllocations::CleanupMess() throw()
|
void SysCoreAllocations::CleanupMess() throw()
|
||||||
|
|
|
@ -31,8 +31,8 @@ class SysCoreAllocations
|
||||||
protected:
|
protected:
|
||||||
ScopedPtr<CpuInitializerSet> CpuProviders;
|
ScopedPtr<CpuInitializerSet> CpuProviders;
|
||||||
|
|
||||||
bool m_RecSuccessEE:1;
|
ScopedPtr<BaseException> m_RecExceptionEE;
|
||||||
bool m_RecSuccessIOP:1;
|
ScopedPtr<BaseException> m_RecExceptionIOP;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SysCoreAllocations();
|
SysCoreAllocations();
|
||||||
|
@ -42,14 +42,21 @@ public:
|
||||||
|
|
||||||
bool HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const;
|
bool HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const;
|
||||||
|
|
||||||
bool IsRecAvailable_EE() const { return m_RecSuccessEE; }
|
bool IsRecAvailable_EE() const { return !m_RecExceptionEE; }
|
||||||
bool IsRecAvailable_IOP() const { return m_RecSuccessIOP; }
|
bool IsRecAvailable_IOP() const { return !m_RecExceptionIOP; }
|
||||||
|
|
||||||
|
BaseException* GetException_EE() const { return m_RecExceptionEE; }
|
||||||
|
BaseException* GetException_IOP() const { return m_RecExceptionIOP; }
|
||||||
|
|
||||||
bool IsRecAvailable_MicroVU0() const;
|
bool IsRecAvailable_MicroVU0() const;
|
||||||
bool IsRecAvailable_MicroVU1() const;
|
bool IsRecAvailable_MicroVU1() const;
|
||||||
|
BaseException* GetException_MicroVU0() const;
|
||||||
|
BaseException* GetException_MicroVU1() const;
|
||||||
|
|
||||||
bool IsRecAvailable_SuperVU0() const;
|
bool IsRecAvailable_SuperVU0() const;
|
||||||
bool IsRecAvailable_SuperVU1() const;
|
bool IsRecAvailable_SuperVU1() const;
|
||||||
|
BaseException* GetException_SuperVU0() const;
|
||||||
|
BaseException* GetException_SuperVU1() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CleanupMess() throw();
|
void CleanupMess() throw();
|
||||||
|
|
|
@ -81,7 +81,8 @@ void SysThreadBase::OnStart()
|
||||||
//
|
//
|
||||||
void SysThreadBase::Suspend( bool isBlocking )
|
void SysThreadBase::Suspend( bool isBlocking )
|
||||||
{
|
{
|
||||||
if( IsSelf() || !IsRunning() ) return;
|
if (!pxAssertDev(!IsSelf(),"Suspend/Resume are not allowed from this thread.")) return;
|
||||||
|
if (!IsRunning()) return;
|
||||||
|
|
||||||
// shortcut ExecMode check to avoid deadlocking on redundant calls to Suspend issued
|
// shortcut ExecMode check to avoid deadlocking on redundant calls to Suspend issued
|
||||||
// from Resume or OnResumeReady code.
|
// from Resume or OnResumeReady code.
|
||||||
|
@ -98,7 +99,7 @@ void SysThreadBase::Suspend( bool isBlocking )
|
||||||
case ExecMode_Pausing:
|
case ExecMode_Pausing:
|
||||||
case ExecMode_Paused:
|
case ExecMode_Paused:
|
||||||
if( !isBlocking )
|
if( !isBlocking )
|
||||||
throw Exception::CancelEvent( "Cannot suspend in non-blocking fashion: Another thread is pausing the VM state." );
|
throw Exception::CancelEvent( L"Cannot suspend in non-blocking fashion: Another thread is pausing the VM state." );
|
||||||
|
|
||||||
m_ExecMode = ExecMode_Closing;
|
m_ExecMode = ExecMode_Closing;
|
||||||
m_sem_Resume.Post();
|
m_sem_Resume.Post();
|
||||||
|
@ -182,7 +183,7 @@ void SysThreadBase::Resume()
|
||||||
{
|
{
|
||||||
Start();
|
Start();
|
||||||
if( !m_running || (m_ExecMode == ExecMode_NoThreadYet) )
|
if( !m_running || (m_ExecMode == ExecMode_NoThreadYet) )
|
||||||
throw Exception::ThreadCreationError();
|
throw Exception::ThreadCreationError(this);
|
||||||
if( m_ExecMode == ExecMode_Opened ) return;
|
if( m_ExecMode == ExecMode_Opened ) return;
|
||||||
}
|
}
|
||||||
// fall through...
|
// fall through...
|
||||||
|
|
|
@ -31,9 +31,9 @@ void vuMicroMemAlloc()
|
||||||
m_vuAllMem = vtlb_malloc( m_vuMemSize, 16 );
|
m_vuAllMem = vtlb_malloc( m_vuMemSize, 16 );
|
||||||
|
|
||||||
if( m_vuAllMem == NULL )
|
if( m_vuAllMem == NULL )
|
||||||
throw Exception::OutOfMemory( "vuMicroMemInit > Failed to allocate VUmicro memory." );
|
throw Exception::OutOfMemory( L"VU0 and VU1 on-chip memory" );
|
||||||
|
|
||||||
jASSUME( sizeof( VURegs ) <= 0x800 );
|
pxAssume( sizeof( VURegs ) <= 0x800 );
|
||||||
|
|
||||||
u8* curpos = m_vuAllMem;
|
u8* curpos = m_vuAllMem;
|
||||||
VU0.Micro = curpos; curpos += 0x1000;
|
VU0.Micro = curpos; curpos += 0x1000;
|
||||||
|
@ -55,8 +55,8 @@ void vuMicroMemShutdown()
|
||||||
|
|
||||||
void vuMicroMemReset()
|
void vuMicroMemReset()
|
||||||
{
|
{
|
||||||
jASSUME( VU0.Mem != NULL );
|
pxAssume( VU0.Mem != NULL );
|
||||||
jASSUME( VU1.Mem != NULL );
|
pxAssume( VU1.Mem != NULL );
|
||||||
|
|
||||||
memMapVUmicro();
|
memMapVUmicro();
|
||||||
|
|
||||||
|
@ -107,8 +107,8 @@ void SaveStateBase::vuMicroFreeze()
|
||||||
{
|
{
|
||||||
FreezeTag( "vuMicro" );
|
FreezeTag( "vuMicro" );
|
||||||
|
|
||||||
jASSUME( VU0.Mem != NULL );
|
pxAssume( VU0.Mem != NULL );
|
||||||
jASSUME( VU1.Mem != NULL );
|
pxAssume( VU1.Mem != NULL );
|
||||||
|
|
||||||
Freeze(VU0.ACC);
|
Freeze(VU0.ACC);
|
||||||
Freeze(VU0.code);
|
Freeze(VU0.code);
|
||||||
|
|
|
@ -58,7 +58,7 @@ CompressThread_gzip::~CompressThread_gzip() throw()
|
||||||
void CompressThread_gzip::Write( const void* data, size_t size )
|
void CompressThread_gzip::Write( const void* data, size_t size )
|
||||||
{
|
{
|
||||||
if( gzwrite( m_gzfp, data, size ) == 0 )
|
if( gzwrite( m_gzfp, data, size ) == 0 )
|
||||||
throw Exception::BadStream( m_filename, "Write to zip file failed." );
|
throw Exception::BadStream( m_filename ).SetDiagMsg(L"Write to zip file failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressThread_gzip::ExecuteTaskInThread()
|
void CompressThread_gzip::ExecuteTaskInThread()
|
||||||
|
@ -104,7 +104,9 @@ void CompressThread_gzip::ExecuteTaskInThread()
|
||||||
m_gzfp = NULL;
|
m_gzfp = NULL;
|
||||||
|
|
||||||
if( !wxRenameFile( tempfile, m_filename, true ) )
|
if( !wxRenameFile( tempfile, m_filename, true ) )
|
||||||
throw Exception::BadStream( m_filename, "Failed to move or copy the temporary archive to the destination filename." );
|
throw Exception::BadStream( m_filename )
|
||||||
|
.SetDiagMsg(L"Failed to move or copy the temporary archive to the destination filename.")
|
||||||
|
.SetUserMsg(_("The savestate was not properly saved. The temporary file was created successfully but could not be moved to its final resting place."));
|
||||||
|
|
||||||
Console.WriteLn( "(gzipThread) Data saved to disk without error." );
|
Console.WriteLn( "(gzipThread) Data saved to disk without error." );
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,15 +154,14 @@ namespace Exception
|
||||||
// Exception used to perform an "errorless" termination of the app during OnInit
|
// Exception used to perform an "errorless" termination of the app during OnInit
|
||||||
// procedures. This happens when a user cancels out of startup prompts/wizards.
|
// procedures. This happens when a user cancels out of startup prompts/wizards.
|
||||||
//
|
//
|
||||||
class StartupAborted : public BaseException
|
class StartupAborted : public CancelEvent
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_RUNTIME_EXCEPTION( StartupAborted, CancelEvent, "Startup initialization was aborted by the user." )
|
||||||
DEFINE_EXCEPTION_COPYTORS( StartupAborted )
|
|
||||||
|
|
||||||
StartupAborted( const wxString& msg_eng=L"Startup initialization was aborted by the user." )
|
public:
|
||||||
|
StartupAborted( const wxString& reason )
|
||||||
{
|
{
|
||||||
// english messages only for this exception.
|
m_message_diag = L"Startup aborted: " + reason;
|
||||||
BaseException::InitBaseEx( msg_eng, msg_eng );
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -755,7 +755,7 @@ void AppConfig_OnChangedSettingsFolder( bool overwrite )
|
||||||
if( overwrite )
|
if( overwrite )
|
||||||
{
|
{
|
||||||
if( wxFileExists( iniFilename ) && !wxRemoveFile( iniFilename ) )
|
if( wxFileExists( iniFilename ) && !wxRemoveFile( iniFilename ) )
|
||||||
throw Exception::AccessDenied( "Failed to overwrite settings; permission to file was denied." );
|
throw Exception::AccessDenied(iniFilename).SetBothMsgs(wxLt("Failed to overwrite existing settings file; permission was denied."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind into wxConfigBase to allow wx to use our config internally, and delete whatever
|
// Bind into wxConfigBase to allow wx to use our config internally, and delete whatever
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "CDVD/CDVD.h"
|
#include "CDVD/CDVD.h"
|
||||||
#include "Elfheader.h"
|
#include "Elfheader.h"
|
||||||
#include "Patch.h"
|
#include "Patch.h"
|
||||||
|
#include "R5900Exceptions.h"
|
||||||
|
|
||||||
__aligned16 SysMtgsThread mtgsThread;
|
__aligned16 SysMtgsThread mtgsThread;
|
||||||
__aligned16 AppCoreThread CoreThread;
|
__aligned16 AppCoreThread CoreThread;
|
||||||
|
@ -108,7 +109,13 @@ static void _Suspend()
|
||||||
|
|
||||||
void AppCoreThread::Suspend( bool isBlocking )
|
void AppCoreThread::Suspend( bool isBlocking )
|
||||||
{
|
{
|
||||||
if( !GetSysExecutorThread().ProcessMethodSelf( _Suspend ) )
|
if (IsSelf())
|
||||||
|
{
|
||||||
|
// this should never fail...
|
||||||
|
bool result = GetSysExecutorThread().Rpc_TryInvokeAsync( _Suspend );
|
||||||
|
pxAssert(result);
|
||||||
|
}
|
||||||
|
else if (!GetSysExecutorThread().Rpc_TryInvoke( _Suspend ))
|
||||||
_parent::Suspend(true);
|
_parent::Suspend(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,12 +399,44 @@ void AppCoreThread::UploadStateCopy( const VmStateBuffer& copy )
|
||||||
paused_core.AllowResume();
|
paused_core.AllowResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint m_except_threshold = 0;
|
||||||
|
|
||||||
void AppCoreThread::ExecuteTaskInThread()
|
void AppCoreThread::ExecuteTaskInThread()
|
||||||
{
|
{
|
||||||
PostCoreStatus( CoreThread_Started );
|
PostCoreStatus( CoreThread_Started );
|
||||||
|
m_except_threshold = 0;
|
||||||
_parent::ExecuteTaskInThread();
|
_parent::ExecuteTaskInThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppCoreThread::DoCpuExecute()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
_parent::DoCpuExecute();
|
||||||
|
}
|
||||||
|
catch (BaseR5900Exception& ex)
|
||||||
|
{
|
||||||
|
Console.Error( ex.FormatMessage() );
|
||||||
|
|
||||||
|
// [TODO] : Debugger Hook!
|
||||||
|
|
||||||
|
if( ++m_except_threshold > 6 )
|
||||||
|
{
|
||||||
|
// If too many TLB Misses occur, we're probably going to crash and
|
||||||
|
// the game is probably running miserably.
|
||||||
|
|
||||||
|
m_except_threshold = 0;
|
||||||
|
//Suspend();
|
||||||
|
|
||||||
|
// [TODO] Issue error dialog to the user here...
|
||||||
|
Console.Error( "Too many execution errors. VM execution has been suspended!" );
|
||||||
|
|
||||||
|
// Hack: this keeps the EE thread from running more code while the SysExecutor
|
||||||
|
// thread catches up and signals it for suspension.
|
||||||
|
m_ExecMode = ExecMode_Closing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// BaseSysExecEvent_ScopedCore / SysExecEvent_CoreThreadClose / SysExecEvent_CoreThreadPause
|
// BaseSysExecEvent_ScopedCore / SysExecEvent_CoreThreadClose / SysExecEvent_CoreThreadPause
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -142,6 +142,8 @@ public:
|
||||||
virtual void UploadStateCopy( const VmStateBuffer& copy );
|
virtual void UploadStateCopy( const VmStateBuffer& copy );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void DoCpuExecute();
|
||||||
|
|
||||||
virtual void OnResumeReady();
|
virtual void OnResumeReady();
|
||||||
virtual void OnResumeInThread( bool IsSuspended );
|
virtual void OnResumeInThread( bool IsSuspended );
|
||||||
virtual void OnSuspendInThread();
|
virtual void OnSuspendInThread();
|
||||||
|
|
|
@ -48,8 +48,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
AppGameDatabase() {}
|
AppGameDatabase() {}
|
||||||
virtual ~AppGameDatabase() throw() {
|
virtual ~AppGameDatabase() throw() {
|
||||||
// deque deletes its contents automatically.
|
Console.WriteLn( "(GameDB) Unloading..." );
|
||||||
Console.WriteLn( "(GameDB) Destroying..." );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AppGameDatabase& LoadFromFile(const wxString& file = L"GameIndex.dbf", const wxString& key = L"Serial" );
|
AppGameDatabase& LoadFromFile(const wxString& file = L"GameIndex.dbf", const wxString& key = L"Serial" );
|
||||||
|
|
|
@ -138,7 +138,7 @@ void Pcsx2App::ReadUserModeSettings()
|
||||||
// first time startup, so give the user the choice of user mode:
|
// first time startup, so give the user the choice of user mode:
|
||||||
FirstTimeWizard wiz( NULL );
|
FirstTimeWizard wiz( NULL );
|
||||||
if( !wiz.RunWizard( wiz.GetUsermodePage() ) )
|
if( !wiz.RunWizard( wiz.GetUsermodePage() ) )
|
||||||
throw Exception::StartupAborted( L"Startup aborted: User canceled FirstTime Wizard." );
|
throw Exception::StartupAborted( L"User canceled FirstTime Wizard." );
|
||||||
|
|
||||||
// Save user's new settings
|
// Save user's new settings
|
||||||
IniSaver saver( *conf_usermode );
|
IniSaver saver( *conf_usermode );
|
||||||
|
@ -166,7 +166,7 @@ void Pcsx2App::ReadUserModeSettings()
|
||||||
// If we skip this check, it's very likely that actions like creating Memory Cards will fail.
|
// If we skip this check, it's very likely that actions like creating Memory Cards will fail.
|
||||||
FirstTimeWizard wiz( NULL );
|
FirstTimeWizard wiz( NULL );
|
||||||
if( !wiz.RunWizard( /*wiz.GetPostUsermodePage()*/ wiz.GetUsermodePage() ) )
|
if( !wiz.RunWizard( /*wiz.GetPostUsermodePage()*/ wiz.GetUsermodePage() ) )
|
||||||
throw Exception::StartupAborted( L"Startup aborted: User canceled Configuration Wizard." );
|
throw Exception::StartupAborted( L"User canceled Configuration Wizard." );
|
||||||
|
|
||||||
// Save user's new settings
|
// Save user's new settings
|
||||||
IniSaver saver( *conf_usermode );
|
IniSaver saver( *conf_usermode );
|
||||||
|
@ -193,7 +193,9 @@ void Pcsx2App::DetectCpuAndUserMode()
|
||||||
{
|
{
|
||||||
// Note: due to memcpy_fast, we need minimum MMX even for interpreters. This will
|
// Note: due to memcpy_fast, we need minimum MMX even for interpreters. This will
|
||||||
// hopefully change later once we have a dynamically recompiled memcpy.
|
// hopefully change later once we have a dynamically recompiled memcpy.
|
||||||
throw Exception::HardwareDeficiency(L"MMX Extensions not available.", _("PCSX2 requires cpu with MMX instruction to run."));
|
throw Exception::HardwareDeficiency()
|
||||||
|
.SetDiagMsg(L"Critical Failure: MMX Extensions not available.")
|
||||||
|
.SetUserMsg(_("MMX extensions are not available. PCSX2 requires cpu with MMX extension support to run."));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadUserModeSettings();
|
ReadUserModeSettings();
|
||||||
|
@ -260,8 +262,8 @@ void Pcsx2App::AllocateCoreStuffs()
|
||||||
wxDialogWithHelpers exconf( NULL, _("PCSX2 Recompiler Error(s)") );
|
wxDialogWithHelpers exconf( NULL, _("PCSX2 Recompiler Error(s)") );
|
||||||
|
|
||||||
exconf += 12;
|
exconf += 12;
|
||||||
exconf += exconf.Heading( pxE( ".Popup:RecompilerInit",
|
exconf += exconf.Heading( pxE( ".Popup:RecompilerInit:Header",
|
||||||
L"Warning: Some of the configured PS2 recompilers failed to initialize and will not be available for this session:\n" )
|
L"Warning: Some of the configured PS2 recompilers failed to initialize and have been disabled:" )
|
||||||
);
|
);
|
||||||
|
|
||||||
wxTextCtrl* scrollableTextArea = new wxTextCtrl(
|
wxTextCtrl* scrollableTextArea = new wxTextCtrl(
|
||||||
|
@ -269,63 +271,55 @@ void Pcsx2App::AllocateCoreStuffs()
|
||||||
wxTE_READONLY | wxTE_MULTILINE | wxTE_WORDWRAP
|
wxTE_READONLY | wxTE_MULTILINE | wxTE_WORDWRAP
|
||||||
);
|
);
|
||||||
|
|
||||||
exconf += scrollableTextArea | pxSizerFlags::StdExpand();
|
exconf += 6;
|
||||||
|
exconf += scrollableTextArea | pxExpand.Border(wxALL, 16);
|
||||||
|
|
||||||
if( !m_CoreAllocs->IsRecAvailable_EE() )
|
if( BaseException* ex = m_CoreAllocs->GetException_EE() )
|
||||||
{
|
{
|
||||||
scrollableTextArea->AppendText( L"* R5900 (EE)\n\n" );
|
scrollableTextArea->AppendText( L"* R5900 (EE)\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
|
||||||
|
|
||||||
g_Conf->EmuOptions.Recompiler.EnableEE = false;
|
g_Conf->EmuOptions.Recompiler.EnableEE = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_CoreAllocs->IsRecAvailable_IOP() )
|
if( BaseException* ex = m_CoreAllocs->GetException_IOP() )
|
||||||
{
|
{
|
||||||
scrollableTextArea->AppendText( L"* R3000A (IOP)\n\n" );
|
scrollableTextArea->AppendText( L"* R3000A (IOP)\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
|
||||||
g_Conf->EmuOptions.Recompiler.EnableIOP = false;
|
g_Conf->EmuOptions.Recompiler.EnableIOP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_CoreAllocs->IsRecAvailable_MicroVU0() ) {
|
if( BaseException* ex = m_CoreAllocs->GetException_MicroVU0() )
|
||||||
scrollableTextArea->AppendText( L"* microVU0\n\n" );
|
{
|
||||||
|
scrollableTextArea->AppendText( L"* microVU0\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
|
||||||
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = false;
|
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = false;
|
||||||
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && m_CoreAllocs->IsRecAvailable_SuperVU0();
|
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && m_CoreAllocs->IsRecAvailable_SuperVU0();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_CoreAllocs->IsRecAvailable_MicroVU1() )
|
if( BaseException* ex = m_CoreAllocs->GetException_MicroVU1() )
|
||||||
{
|
{
|
||||||
scrollableTextArea->AppendText( L"* microVU1\n\n" );
|
scrollableTextArea->AppendText( L"* microVU1\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
|
||||||
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = false;
|
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = false;
|
||||||
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && m_CoreAllocs->IsRecAvailable_SuperVU1();
|
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && m_CoreAllocs->IsRecAvailable_SuperVU1();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_CoreAllocs->IsRecAvailable_SuperVU0() )
|
if( BaseException* ex = m_CoreAllocs->GetException_SuperVU0() )
|
||||||
{
|
{
|
||||||
scrollableTextArea->AppendText( L"* SuperVU0\n\n" );
|
scrollableTextArea->AppendText( L"* SuperVU0\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
|
||||||
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = m_CoreAllocs->IsRecAvailable_MicroVU0();
|
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = m_CoreAllocs->IsRecAvailable_MicroVU0();
|
||||||
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && g_Conf->EmuOptions.Recompiler.UseMicroVU0;
|
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && g_Conf->EmuOptions.Recompiler.UseMicroVU0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_CoreAllocs->IsRecAvailable_SuperVU1() )
|
if( BaseException* ex = m_CoreAllocs->GetException_SuperVU1() )
|
||||||
{
|
{
|
||||||
scrollableTextArea->AppendText( L"* SuperVU1\n\n" );
|
scrollableTextArea->AppendText( L"* SuperVU1\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
|
||||||
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = m_CoreAllocs->IsRecAvailable_MicroVU1();
|
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = m_CoreAllocs->IsRecAvailable_MicroVU1();
|
||||||
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && g_Conf->EmuOptions.Recompiler.UseMicroVU1;
|
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && g_Conf->EmuOptions.Recompiler.UseMicroVU1;
|
||||||
}
|
}
|
||||||
|
|
||||||
exconf += new ModalButtonPanel( &exconf, MsgButtons().OK() ) | pxSizerFlags::StdCenter();
|
exconf += exconf.Heading( pxE(".Popup:RecompilerInit:Footer",
|
||||||
|
L"Note: Recompilers are not necessary for PCSX2 to run, however they typically improve emulation speed substantially. "
|
||||||
|
L"You may have to manually re-enable the recompilers listed above, if you resolve the errors." )
|
||||||
|
);
|
||||||
|
|
||||||
exconf.ShowModal();
|
pxIssueConfirmation( exconf, MsgButtons().OK() );
|
||||||
|
|
||||||
// Failures can be SSE-related OR memory related. Should do per-cpu error reports instead...
|
|
||||||
|
|
||||||
/*message += pxE( ".Popup Error:EmuCore:MemoryForRecs",
|
|
||||||
L"These errors are the result of memory allocation failures (see the program log for details). "
|
|
||||||
L"Closing out some memory hogging background tasks may resolve this error.\n\n"
|
|
||||||
L"These recompilers have been disabled and interpreters will be used in their place. "
|
|
||||||
L"Interpreters can be very slow, so don't get too excited. Press OK to continue or CANCEL to close PCSX2."
|
|
||||||
);*/
|
|
||||||
|
|
||||||
//if( !Msgbox::OkCancel( message, _("PCSX2 Initialization Error"), wxICON_ERROR ) )
|
|
||||||
// return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,33 +37,28 @@ namespace Exception
|
||||||
//
|
//
|
||||||
class CannotApplySettings : public BaseException
|
class CannotApplySettings : public BaseException
|
||||||
{
|
{
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( CannotApplySettings, BaseException )
|
||||||
|
DEFINE_EXCEPTION_MESSAGES( CannotApplySettings )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool IsVerbose;
|
bool IsVerbose;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BaseApplicableConfigPanel* m_Panel;
|
BaseApplicableConfigPanel* m_Panel;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CannotApplySettings() { IsVerbose = true; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_EXCEPTION_COPYTORS( CannotApplySettings )
|
explicit CannotApplySettings( BaseApplicableConfigPanel* thispanel )
|
||||||
|
|
||||||
explicit CannotApplySettings( BaseApplicableConfigPanel* thispanel, const char* msg=wxLt("Cannot apply new settings, one of the settings is invalid."), bool isVerbose = true )
|
|
||||||
{
|
{
|
||||||
BaseException::InitBaseEx( msg );
|
SetBothMsgs(wxLt("Cannot apply new settings, one of the settings is invalid."));
|
||||||
m_Panel = thispanel;
|
|
||||||
IsVerbose = isVerbose;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit CannotApplySettings( BaseApplicableConfigPanel* thispanel, const wxString& msg_eng, const wxString& msg_xlt )
|
|
||||||
{
|
|
||||||
BaseException::InitBaseEx( msg_eng, msg_xlt );
|
|
||||||
m_Panel = thispanel;
|
m_Panel = thispanel;
|
||||||
IsVerbose = true;
|
IsVerbose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseApplicableConfigPanel* GetPanel()
|
virtual CannotApplySettings& Quiet() { IsVerbose = false; return *this; }
|
||||||
{
|
BaseApplicableConfigPanel* GetPanel() { return m_Panel; }
|
||||||
return m_Panel;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ CpuUsageProviderMSW::CpuUsageProviderMSW()
|
||||||
throw Exception::RuntimeError( "(CpuUsageProviderMSW) CoInitializeSecurity failed: No good security packages! .. whatever tht means." );
|
throw Exception::RuntimeError( "(CpuUsageProviderMSW) CoInitializeSecurity failed: No good security packages! .. whatever tht means." );
|
||||||
|
|
||||||
case E_OUTOFMEMORY:
|
case E_OUTOFMEMORY:
|
||||||
throw Exception::OutOfMemory( "(CpuUsageProviderMSW) Out of Memory error returned during call to CoInitializeSecurity." );
|
throw Exception::OutOfMemory( L"(CpuUsageProviderMSW) Out of Memory error returned during call to CoInitializeSecurity." );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Exception::RuntimeError( wxsFormat( L"(CpuUsageProviderMSW) CoInitializeSecurity failed with an unknown error code: %d", hr ), wxEmptyString );
|
throw Exception::RuntimeError( wxsFormat( L"(CpuUsageProviderMSW) CoInitializeSecurity failed with an unknown error code: %d", hr ), wxEmptyString );
|
||||||
|
@ -221,7 +221,7 @@ void CpuUsageProviderMSW::UpdateStats()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WBEM_E_OUT_OF_MEMORY:
|
case WBEM_E_OUT_OF_MEMORY:
|
||||||
throw Exception::OutOfMemory( "(CpuUsageProviderMSW) Out of Memory Enumerating WMI Object." );
|
throw Exception::OutOfMemory( L"(CpuUsageProviderMSW) Out of Memory Enumerating WMI Object." );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Exception::RuntimeError( wxsFormat( L"(CpuUsageProviderMSW) WMI Object Enumeration failed with an unknown error code: %d", hRes ), wxEmptyString );
|
throw Exception::RuntimeError( wxsFormat( L"(CpuUsageProviderMSW) WMI Object Enumeration failed with an unknown error code: %d", hRes ), wxEmptyString );
|
||||||
|
|
|
@ -104,14 +104,13 @@ bool FirstTimeWizard::UsermodePage::PrepForApply()
|
||||||
if( path.FileExists() )
|
if( path.FileExists() )
|
||||||
{
|
{
|
||||||
// FIXME: There's already a file by the same name.. not sure what we should do here.
|
// FIXME: There's already a file by the same name.. not sure what we should do here.
|
||||||
throw Exception::BadStream( path.ToString(),
|
throw Exception::BadStream( path.ToString() )
|
||||||
L"Targeted documents folder is already occupied by a file.",
|
.SetDiagMsg(L"Targeted documents folder is already occupied by a file.")
|
||||||
pxE( ".Error:DocsFolderFileConflict",
|
.SetUserMsg(pxE( ".Error:DocsFolderFileConflict",
|
||||||
L"PCSX2 cannot create a documents folder in the requested location. "
|
L"PCSX2 cannot create a documents folder in the requested location. "
|
||||||
L"The path name matches an existing file. Delete the file or change the documents location, "
|
L"The path name matches an existing file. Delete the file or change the documents location, "
|
||||||
L"and then try again."
|
L"and then try again."
|
||||||
)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !path.Exists() )
|
if( !path.Exists() )
|
||||||
|
|
|
@ -308,7 +308,18 @@ void pxEvtHandler::ProcessEvent( SysExecEvent* evt )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pxEvtHandler::ProcessMethodSelf( FnType_Void* method )
|
bool pxEvtHandler::Rpc_TryInvokeAsync( FnType_Void* method )
|
||||||
|
{
|
||||||
|
if( wxThread::GetCurrentId() != m_OwnerThreadId )
|
||||||
|
{
|
||||||
|
PostEvent( new SysExecEvent_MethodVoid(method) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pxEvtHandler::Rpc_TryInvoke( FnType_Void* method )
|
||||||
{
|
{
|
||||||
if( wxThread::GetCurrentId() != m_OwnerThreadId )
|
if( wxThread::GetCurrentId() != m_OwnerThreadId )
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,6 @@ void GSPanel::InitDefaultAccelerators()
|
||||||
m_Accels->Map( AAC( WXK_F8 ).Shift(), "Sys_TakeSnapshot");
|
m_Accels->Map( AAC( WXK_F8 ).Shift(), "Sys_TakeSnapshot");
|
||||||
m_Accels->Map( AAC( WXK_F8 ).Shift().Cmd(), "Sys_TakeSnapshot");
|
m_Accels->Map( AAC( WXK_F8 ).Shift().Cmd(), "Sys_TakeSnapshot");
|
||||||
m_Accels->Map( AAC( WXK_F9 ), "Sys_RenderswitchToggle");
|
m_Accels->Map( AAC( WXK_F9 ), "Sys_RenderswitchToggle");
|
||||||
m_Accels->Map( AAC( WXK_F9 ), "Sys_RenderswitchToggle" );
|
|
||||||
|
|
||||||
//m_Accels->Map( AAC( WXK_F10 ), "Sys_LoggingToggle" );
|
//m_Accels->Map( AAC( WXK_F10 ), "Sys_LoggingToggle" );
|
||||||
m_Accels->Map( AAC( WXK_F11 ), "Sys_FreezeGS" );
|
m_Accels->Map( AAC( WXK_F11 ), "Sys_FreezeGS" );
|
||||||
|
|
|
@ -121,16 +121,12 @@ void Panels::BiosSelectorPanel::Apply()
|
||||||
int sel = m_ComboBox->GetSelection();
|
int sel = m_ComboBox->GetSelection();
|
||||||
if( sel == wxNOT_FOUND )
|
if( sel == wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
throw Exception::CannotApplySettings( this,
|
throw Exception::CannotApplySettings(this)
|
||||||
// English Log
|
.SetDiagMsg(L"User did not specify a valid BIOS selection.")
|
||||||
L"User did not specify a valid BIOS selection.",
|
.SetUserMsg( pxE( ".Error:BIOS:InvalidSelection",
|
||||||
|
|
||||||
// Translated
|
|
||||||
pxE( ".Error:BIOS:InvalidSelection",
|
|
||||||
L"Please select a valid BIOS. If you are unable to make a valid selection "
|
L"Please select a valid BIOS. If you are unable to make a valid selection "
|
||||||
L"then press cancel to close the Configuration panel."
|
L"then press cancel to close the Configuration panel."
|
||||||
)
|
) );
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Conf->BaseFilenames.Bios = (*m_BiosList)[(int)m_ComboBox->GetClientData(sel)];
|
g_Conf->BaseFilenames.Bios = (*m_BiosList)[(int)m_ComboBox->GetClientData(sel)];
|
||||||
|
|
|
@ -142,10 +142,9 @@ void Panels::GSWindowSettingsPanel::Apply()
|
||||||
long xr, yr;
|
long xr, yr;
|
||||||
|
|
||||||
if( !m_text_WindowWidth->GetValue().ToLong( &xr ) || !m_text_WindowHeight->GetValue().ToLong( &yr ) )
|
if( !m_text_WindowWidth->GetValue().ToLong( &xr ) || !m_text_WindowHeight->GetValue().ToLong( &yr ) )
|
||||||
throw Exception::CannotApplySettings( this,
|
throw Exception::CannotApplySettings( this )
|
||||||
L"User submitted non-numeric window size parameters!",
|
.SetDiagMsg(L"User submitted non-numeric window size parameters!")
|
||||||
_("Invalid window dimensions specified: Size cannot contain non-numeric digits! >_<")
|
.SetUserMsg(_("Invalid window dimensions specified: Size cannot contain non-numeric digits! >_<"));
|
||||||
);
|
|
||||||
|
|
||||||
appconf.WindowSize.x = xr;
|
appconf.WindowSize.x = xr;
|
||||||
appconf.WindowSize.y = yr;
|
appconf.WindowSize.y = yr;
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace Exception
|
||||||
class NotEnumerablePlugin : public BadStream
|
class NotEnumerablePlugin : public BadStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DEFINE_STREAM_EXCEPTION( NotEnumerablePlugin, wxLt("File is not a PCSX2 plugin") );
|
DEFINE_STREAM_EXCEPTION( NotEnumerablePlugin, BadStream, wxLt("File is not a PCSX2 plugin") );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
: m_plugpath( plugpath )
|
: m_plugpath( plugpath )
|
||||||
{
|
{
|
||||||
if( !m_plugin.Load( m_plugpath ) )
|
if( !m_plugin.Load( m_plugpath ) )
|
||||||
throw Exception::BadStream( m_plugpath, "File is not a valid dynamic library." );
|
throw Exception::BadStream( m_plugpath ).SetBothMsgs("File is not a valid dynamic library.");
|
||||||
|
|
||||||
wxDoNotLogInThisScope please;
|
wxDoNotLogInThisScope please;
|
||||||
m_GetLibType = (_PS2EgetLibType)m_plugin.GetSymbol( L"PS2EgetLibType" );
|
m_GetLibType = (_PS2EgetLibType)m_plugin.GetSymbol( L"PS2EgetLibType" );
|
||||||
|
@ -241,7 +241,8 @@ void ApplyOverValidStateEvent::InvokeEvent()
|
||||||
int result = pxIssueConfirmation( dialog, MsgButtons().OK().Cancel(), L"PluginSelector:ConfirmShutdown" );
|
int result = pxIssueConfirmation( dialog, MsgButtons().OK().Cancel(), L"PluginSelector:ConfirmShutdown" );
|
||||||
|
|
||||||
if( result == wxID_CANCEL )
|
if( result == wxID_CANCEL )
|
||||||
throw Exception::CannotApplySettings( m_owner->GetApplicableConfigPanel(), "Cannot apply settings: canceled by user because plugins changed while the emulation state was active.", false );
|
throw Exception::CannotApplySettings( m_owner->GetApplicableConfigPanel() ).Quiet()
|
||||||
|
.SetDiagMsg(L"Cannot apply settings: canceled by user because plugins changed while the emulation state was active.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -465,13 +466,9 @@ void Panels::PluginSelectorPanel::Apply()
|
||||||
{
|
{
|
||||||
wxString plugname( pi->GetShortname() );
|
wxString plugname( pi->GetShortname() );
|
||||||
|
|
||||||
throw Exception::CannotApplySettings( this,
|
throw Exception::CannotApplySettings( this )
|
||||||
// English Log
|
.SetDiagMsg(wxsFormat( L"PluginSelectorPanel: Invalid or missing selection for the %s plugin.", plugname.c_str()) )
|
||||||
wxsFormat( L"PluginSelectorPanel: Invalid or missing selection for the %s plugin.", plugname.c_str() ),
|
.SetUserMsg(wxsFormat( L"Please select a valid plugin for the %s.", plugname.c_str() ) + L"\n\n" + GetApplyFailedMsg() );
|
||||||
|
|
||||||
// Translated
|
|
||||||
wxsFormat( L"Please select a valid plugin for the %s.", plugname.c_str() ) + L"\n\n" + GetApplyFailedMsg()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Conf->BaseFilenames.Plugins[pid] = GetFilename((int)m_ComponentBoxes->Get(pid).GetClientData(sel));
|
g_Conf->BaseFilenames.Plugins[pid] = GetFilename((int)m_ComponentBoxes->Get(pid).GetClientData(sel));
|
||||||
|
@ -498,7 +495,7 @@ void Panels::PluginSelectorPanel::Apply()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if( wxID_CANCEL == ApplyPluginsDialog( this ).ShowModal() )
|
if( wxID_CANCEL == ApplyPluginsDialog( this ).ShowModal() )
|
||||||
throw Exception::CannotApplySettings( this, "User canceled plugin load process.", false );
|
throw Exception::CannotApplySettings( this ).Quiet().SetDiagMsg(L"User canceled plugin load process.");
|
||||||
}
|
}
|
||||||
catch( Exception::PluginError& ex )
|
catch( Exception::PluginError& ex )
|
||||||
{
|
{
|
||||||
|
@ -506,15 +503,12 @@ void Panels::PluginSelectorPanel::Apply()
|
||||||
|
|
||||||
wxString plugname( tbl_PluginInfo[ex.PluginId].GetShortname() );
|
wxString plugname( tbl_PluginInfo[ex.PluginId].GetShortname() );
|
||||||
|
|
||||||
throw Exception::CannotApplySettings( this,
|
throw Exception::CannotApplySettings( this )
|
||||||
// Diagnostic
|
.SetDiagMsg(ex.FormatDiagnosticMessage())
|
||||||
ex.FormatDiagnosticMessage(),
|
.SetUserMsg(wxsFormat(
|
||||||
|
_("The selected %s plugin failed to load.\n\nReason: %s\n\n"),
|
||||||
// Translated
|
|
||||||
wxsFormat( _("The selected %s plugin failed to load.\n\nReason: %s\n\n"),
|
|
||||||
plugname.c_str(), ex.FormatDisplayMessage().c_str()
|
plugname.c_str(), ex.FormatDisplayMessage().c_str()
|
||||||
) + GetApplyFailedMsg()
|
) + GetApplyFailedMsg());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,9 +144,12 @@ void Panels::FramelimiterPanel::Apply()
|
||||||
}
|
}
|
||||||
catch( Exception::ParseError& )
|
catch( Exception::ParseError& )
|
||||||
{
|
{
|
||||||
throw Exception::CannotApplySettings( this,
|
throw Exception::CannotApplySettings( this )
|
||||||
wxLt("Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics.")
|
.SetDiagMsg(wxsFormat(
|
||||||
);
|
L"Error while parsing either NTSC or PAL framerate settings.\n\tNTSC Input = %s\n\tPAL Input = %s",
|
||||||
|
m_text_BaseNtsc->GetValue(), m_text_BasePal->GetValue()
|
||||||
|
) )
|
||||||
|
.SetUserMsg(_("Error while parsing either NTSC or PAL framerate settings. Settings must be valid floating point numerics."));
|
||||||
}
|
}
|
||||||
|
|
||||||
appfps.SanityCheck();
|
appfps.SanityCheck();
|
||||||
|
|
|
@ -40,25 +40,41 @@ static void SaveStateFile_ReadHeader( IStreamReader& thr )
|
||||||
thr.Read( ident );
|
thr.Read( ident );
|
||||||
|
|
||||||
if( strcmp(SavestateIdentString, ident) )
|
if( strcmp(SavestateIdentString, ident) )
|
||||||
throw Exception::SaveStateLoadError( thr.GetStreamName(),
|
throw Exception::SaveStateLoadError( thr.GetStreamName() )
|
||||||
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
|
.SetDiagMsg(wxsFormat( L"Unrecognized file signature while loading savestate. [sig = %s]", ident ))
|
||||||
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
|
.SetUserMsg(_("This is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2."));
|
||||||
);
|
|
||||||
|
|
||||||
u32 savever;
|
u32 savever;
|
||||||
thr.Read( savever );
|
thr.Read( savever );
|
||||||
|
|
||||||
if( (savever >> 16) != (g_SaveVersion >> 16) )
|
// Major version mismatch. Means we can't load this savestate at all. Support for it
|
||||||
throw Exception::SaveStateLoadError( thr.GetStreamName(),
|
// was removed entirely.
|
||||||
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
|
|
||||||
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
|
|
||||||
);
|
|
||||||
|
|
||||||
if( savever > g_SaveVersion )
|
if( savever > g_SaveVersion )
|
||||||
throw Exception::SaveStateLoadError( thr.GetStreamName(),
|
throw Exception::SaveStateLoadError( thr.GetStreamName() )
|
||||||
wxsFormat( L"Unrecognized file signature while loading savestate: %s", ident ),
|
.SetDiagMsg(wxsFormat( L"Savestate uses an unsupported or unknown savestate version.\n(PCSX2 ver=%d, state ver=%d)", g_SaveVersion, savever ))
|
||||||
_("File is not a valid PCSX2 savestate, or is from an older unsupported version of PCSX2.")
|
.SetUserMsg(_("Cannot load this savestate. The state is from an incompatible edition of PCSX2 that is either newer than this version, or is no longer supported."));
|
||||||
);
|
|
||||||
|
// check for a "minor" version incompatibility; which happens if the savestate being loaded is a newer version
|
||||||
|
// than the emulator recognizes. 99% chance that trying to load it will just corrupt emulation or crash.
|
||||||
|
if( (savever >> 16) != (g_SaveVersion >> 16) )
|
||||||
|
throw Exception::SaveStateLoadError( thr.GetStreamName() )
|
||||||
|
.SetDiagMsg(wxsFormat( L"Savestate uses an unknown (future?!) savestate version.\n(PCSX2 ver=%d, state ver=%d)", g_SaveVersion, savever ))
|
||||||
|
.SetUserMsg(_("Cannot load this savestate. The state is an unsupported version, likely created by a newer edition of PCSX2."));
|
||||||
|
};
|
||||||
|
|
||||||
|
class gzError : public Exception::BadStream
|
||||||
|
{
|
||||||
|
DEFINE_STREAM_EXCEPTION( gzError, BadStream, wxLt("Invalid or corrupted gzip archive") )
|
||||||
|
};
|
||||||
|
|
||||||
|
class gzReadError : public gzError
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class gzWriteError : public gzError
|
||||||
|
{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -79,7 +95,7 @@ public:
|
||||||
: m_filename( filename )
|
: m_filename( filename )
|
||||||
{
|
{
|
||||||
if( NULL == (m_gzfp = gzopen( m_filename.ToUTF8(), "rb" )) )
|
if( NULL == (m_gzfp = gzopen( m_filename.ToUTF8(), "rb" )) )
|
||||||
throw Exception::CannotCreateStream( m_filename, "Cannot open file for reading." );
|
throw Exception::CannotCreateStream( m_filename ).SetDiagMsg(L"Cannot open file for reading.");
|
||||||
|
|
||||||
#if defined(ZLIB_VERNUM) && (ZLIB_VERNUM >= 0x1240)
|
#if defined(ZLIB_VERNUM) && (ZLIB_VERNUM >= 0x1240)
|
||||||
gzbuffer(m_gzfp, 0x100000); // 1mb buffer for zlib internal operations
|
gzbuffer(m_gzfp, 0x100000); // 1mb buffer for zlib internal operations
|
||||||
|
@ -97,7 +113,8 @@ public:
|
||||||
{
|
{
|
||||||
int result = gzread( m_gzfp, dest, size );
|
int result = gzread( m_gzfp, dest, size );
|
||||||
if( result == -1)
|
if( result == -1)
|
||||||
throw Exception::BadStream( m_filename, "Data read failed: Invalid or corrupted gzip archive." );
|
//throw Exception::gzError( m_filename );
|
||||||
|
throw Exception::BadStream( m_filename ).SetBothMsgs(wxLt("Data read failed: Invalid or corrupted gzip archive."));
|
||||||
|
|
||||||
if( (size_t)result < size )
|
if( (size_t)result < size )
|
||||||
throw Exception::EndOfStream( m_filename );
|
throw Exception::EndOfStream( m_filename );
|
||||||
|
@ -136,7 +153,9 @@ protected:
|
||||||
ScopedCoreThreadPause paused_core;
|
ScopedCoreThreadPause paused_core;
|
||||||
|
|
||||||
if( !SysHasValidState() )
|
if( !SysHasValidState() )
|
||||||
throw Exception::RuntimeError( L"Cannot complete state freeze request; the virtual machine state is reset.", _("You'll need to start a new virtual machine before you can save its state.") );
|
throw Exception::RuntimeError()
|
||||||
|
.SetDiagMsg(L"SysExecEvent_DownloadState: Cannot freeze/download an invalid VM state!")
|
||||||
|
.SetUserMsg(L"There is no active virtual machine state to download or save." );
|
||||||
|
|
||||||
memSavingState(m_dest_buffer).FreezeAll();
|
memSavingState(m_dest_buffer).FreezeAll();
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,8 @@ public:
|
||||||
void ProcessEvent( SysExecEvent* evt );
|
void ProcessEvent( SysExecEvent* evt );
|
||||||
void ProcessEvent( SysExecEvent& evt );
|
void ProcessEvent( SysExecEvent& evt );
|
||||||
|
|
||||||
bool ProcessMethodSelf( FnType_Void* method );
|
bool Rpc_TryInvokeAsync( FnType_Void* method );
|
||||||
|
bool Rpc_TryInvoke( FnType_Void* method );
|
||||||
void SetActiveThread();
|
void SetActiveThread();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -227,9 +228,14 @@ public:
|
||||||
void ProcessEvent( SysExecEvent* evt );
|
void ProcessEvent( SysExecEvent* evt );
|
||||||
void ProcessEvent( SysExecEvent& evt );
|
void ProcessEvent( SysExecEvent& evt );
|
||||||
|
|
||||||
bool ProcessMethodSelf( void (*evt)() )
|
bool Rpc_TryInvokeAsync( void (*evt)() )
|
||||||
{
|
{
|
||||||
return m_EvtHandler ? m_EvtHandler->ProcessMethodSelf( evt ) : false;
|
return m_EvtHandler ? m_EvtHandler->Rpc_TryInvokeAsync( evt ) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rpc_TryInvoke( void (*evt)() )
|
||||||
|
{
|
||||||
|
return m_EvtHandler ? m_EvtHandler->Rpc_TryInvoke( evt ) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -23,8 +23,9 @@
|
||||||
|
|
||||||
#define DIRENTRY_SIZE 16
|
#define DIRENTRY_SIZE 16
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
// --------------------------------------------------------------------------------------
|
||||||
// romdir structure (packing required!)
|
// romdir structure (packing required!)
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# pragma pack(1)
|
# pragma pack(1)
|
||||||
|
@ -41,20 +42,16 @@ struct romdir
|
||||||
# pragma pack()
|
# pragma pack()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
u32 BiosVersion; // Used in Memory, Misc, CDVD
|
u32 BiosVersion; // Used in Memory, Misc, CDVD
|
||||||
|
|
||||||
Exception::BiosLoadFailed::BiosLoadFailed( const wxString& filename, const wxString& msg_diag, const wxString& msg_user )
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Exception::BiosLoadFailed (implementations)
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
Exception::BiosLoadFailed::BiosLoadFailed( const wxString& filename )
|
||||||
{
|
{
|
||||||
wxString diag( msg_user.IsEmpty() ?
|
m_message_diag = L"BIOS has not been configured, or the configuration has been corrupted.";
|
||||||
L"BIOS has not been configured, or the configuration has been corrupted." : msg_user
|
m_message_user = _("The PS2 BIOS could not be loaded. The BIOS has not been configured, or the configuration has been corrupted. Please re-configure.");
|
||||||
);
|
|
||||||
wxString user( msg_user.IsEmpty() ?
|
|
||||||
_("The PS2 BIOS has not been configured, or the configuration has been corrupted. Please re-configure.") : msg_user.c_str()
|
|
||||||
);
|
|
||||||
|
|
||||||
BaseException::InitBaseEx( diag, user );
|
|
||||||
StreamName = filename;
|
StreamName = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,10 +153,9 @@ void LoadBIOS()
|
||||||
s64 filesize = Path::GetFileSize( Bios );
|
s64 filesize = Path::GetFileSize( Bios );
|
||||||
if( filesize <= 0 )
|
if( filesize <= 0 )
|
||||||
{
|
{
|
||||||
throw Exception::BiosLoadFailed( Bios,
|
throw Exception::BiosLoadFailed( Bios )
|
||||||
L"Configured BIOS file does not exist.",
|
.SetDiagMsg(L"Configured BIOS file does not exist.")
|
||||||
_("The configured BIOS file does not exist. Please re-configure.")
|
.SetUserMsg(_("The configured BIOS file does not exist. Please re-configure."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxFile fp( Bios );
|
wxFile fp( Bios );
|
||||||
|
@ -168,10 +164,9 @@ void LoadBIOS()
|
||||||
BiosVersion = GetBiosVersion();
|
BiosVersion = GetBiosVersion();
|
||||||
if( BiosVersion == -1 )
|
if( BiosVersion == -1 )
|
||||||
{
|
{
|
||||||
throw Exception::BiosLoadFailed( Bios,
|
throw Exception::BiosLoadFailed( Bios )
|
||||||
L"Configured BIOS file is not a valid PS2 BIOS.",
|
.SetDiagMsg(L"Configured BIOS file is not a valid PS2 BIOS.")
|
||||||
_("The configured BIOS file is not a valid PS2 BIOS. Please re-configure.")
|
.SetUserMsg(_("The configured BIOS file is not a valid PS2 BIOS. Please re-configure."));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLn("Bios Version %d.%d", BiosVersion >> 8, BiosVersion & 0xff);
|
Console.WriteLn("Bios Version %d.%d", BiosVersion >> 8, BiosVersion & 0xff);
|
||||||
|
|
|
@ -19,12 +19,12 @@ namespace Exception
|
||||||
{
|
{
|
||||||
class BiosLoadFailed : public FileNotFound
|
class BiosLoadFailed : public FileNotFound
|
||||||
{
|
{
|
||||||
public:
|
DEFINE_EXCEPTION_COPYTORS( BiosLoadFailed, FileNotFound )
|
||||||
DEFINE_EXCEPTION_COPYTORS( BiosLoadFailed )
|
DEFINE_EXCEPTION_MESSAGES( BiosLoadFailed )
|
||||||
|
DEFINE_STREAM_EXCEPTION_ACCESSORS( BiosLoadFailed )
|
||||||
|
|
||||||
explicit BiosLoadFailed( const wxString& filename,
|
public:
|
||||||
const wxString& msg_diag=wxEmptyString,
|
BiosLoadFailed( const wxString& streamName );
|
||||||
const wxString& msg_user=wxEmptyString );
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ using namespace vtlb_private;
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
#define verify(x) {if (!(x)) { (*(u8*)0)=3; }}
|
#define verify(x) {if (!(x)) { (*(u8*)0)=3; }}
|
||||||
#else
|
#else
|
||||||
#define verify jASSUME
|
#define verify pxAssume
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace vtlb_private
|
namespace vtlb_private
|
||||||
|
@ -221,32 +221,35 @@ void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value)
|
||||||
MemOp_w1<128,mem128_t>(mem,value);
|
MemOp_w1<128,mem128_t>(mem,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
// ===========================================================================================
|
||||||
// Error / TLB Miss Handlers
|
// Error / TLB Miss Handlers
|
||||||
|
// ===========================================================================================
|
||||||
|
// Important: Throwing exceptions isn't reliable *yet* because memory ops don't flush
|
||||||
|
// the PC prior to invoking the indirect handlers. That feature will likely be added to
|
||||||
|
// debug and dev builds soon, and later on to release builds as well.
|
||||||
//
|
//
|
||||||
|
|
||||||
static const char* _getModeStr( u32 mode )
|
|
||||||
{
|
|
||||||
return (mode==0) ? "read" : "write";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generates a tlbMiss Exception
|
// Generates a tlbMiss Exception
|
||||||
// Note: Don't throw exceptions yet, they cause a crash when otherwise
|
|
||||||
// there would be a (slight) chance the game continues (rama).
|
|
||||||
static __forceinline void vtlb_Miss(u32 addr,u32 mode)
|
static __forceinline void vtlb_Miss(u32 addr,u32 mode)
|
||||||
{
|
{
|
||||||
Console.Error( "vtlb miss : addr 0x%X, mode %d [%s]", addr, mode, _getModeStr(mode) );
|
if( IsDevBuild )
|
||||||
//verify(false);
|
Cpu->ThrowException( R5900Exception::TLBMiss( addr, !!mode ) );
|
||||||
//throw R5900Exception::TLBMiss( addr, !!mode );
|
else
|
||||||
|
Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just dies a horrible death for now.
|
// BusError exception: more serious than a TLB miss. If properly emulated the PS2 kernel
|
||||||
// Eventually should generate a BusError exception.
|
// itself would invoke a diagnostic/assertion screen that displays the cpu state at the
|
||||||
|
// time of the exception.
|
||||||
static __forceinline void vtlb_BusError(u32 addr,u32 mode)
|
static __forceinline void vtlb_BusError(u32 addr,u32 mode)
|
||||||
{
|
{
|
||||||
Console.Error( "vtlb bus error : addr 0x%X, mode %d\n", addr, _getModeStr(mode) );
|
// Throwing exceptions isn't reliable *yet* because memory ops don't flush
|
||||||
//verify(false);
|
// the PC prior to invoking the indirect handlers.
|
||||||
throw R5900Exception::BusError( addr, !!mode );
|
|
||||||
|
if( IsDevBuild )
|
||||||
|
Cpu->ThrowException( R5900Exception::BusError( addr, !!mode ) );
|
||||||
|
else
|
||||||
|
Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
|
||||||
}
|
}
|
||||||
|
|
||||||
///// Virtual Mapping Errors (TLB Miss)
|
///// Virtual Mapping Errors (TLB Miss)
|
||||||
|
@ -307,8 +310,9 @@ void __fastcall vtlbDefaultPhyWrite64(u32 addr,const mem64_t* data) { Console.Er
|
||||||
void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data) { Console.Error("vtlbDefaultPhyWrite128: 0x%X",addr); verify(false); }
|
void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data) { Console.Error("vtlbDefaultPhyWrite128: 0x%X",addr); verify(false); }
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
// ===========================================================================================
|
||||||
// VTLB Public API -- Init/Term/RegisterHandler stuff
|
// VTLB Public API -- Init/Term/RegisterHandler stuff
|
||||||
|
// ===========================================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
// Assigns or re-assigns the callbacks for a VTLB memory handler. The handler defines specific behavior
|
// Assigns or re-assigns the callbacks for a VTLB memory handler. The handler defines specific behavior
|
||||||
|
@ -582,7 +586,7 @@ void vtlb_Core_Alloc()
|
||||||
// Win32 just needs this, since malloc always maps below 2GB.
|
// Win32 just needs this, since malloc always maps below 2GB.
|
||||||
vtlbdata.alloc_base = (u8*)_aligned_malloc( VTLB_ALLOC_SIZE, 4096 );
|
vtlbdata.alloc_base = (u8*)_aligned_malloc( VTLB_ALLOC_SIZE, 4096 );
|
||||||
if( vtlbdata.alloc_base == NULL )
|
if( vtlbdata.alloc_base == NULL )
|
||||||
throw Exception::OutOfMemory( "Fatal Error: could not allocate 42Meg buffer for PS2's mappable system ram." );
|
throw Exception::OutOfMemory( L"PS2 mappable system ram (42 megs)" );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,30 +26,28 @@ void StreamException_ThrowFromErrno( const wxString& streamname, errno_t errcode
|
||||||
{
|
{
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
pxFailDev( L"Invalid argument" );
|
pxFailDev( L"Invalid argument" );
|
||||||
throw Exception::Stream( streamname, "Invalid argument" );
|
throw Exception::Stream( streamname ).SetDiagMsg(L"Invalid argument" );
|
||||||
|
|
||||||
case EACCES: // Access denied!
|
case EACCES: // Access denied!
|
||||||
throw Exception::AccessDenied( streamname );
|
throw Exception::AccessDenied( streamname );
|
||||||
|
|
||||||
case EMFILE: // Too many open files!
|
case EMFILE: // Too many open files!
|
||||||
throw Exception::CannotCreateStream( streamname, "Too many open files" ); // File handle allocation failure
|
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"Too many open files"); // File handle allocation failure
|
||||||
|
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
throw Exception::CannotCreateStream( streamname, "File already exists" );
|
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"File already exists");
|
||||||
|
|
||||||
case ENOENT: // File not found!
|
case ENOENT: // File not found!
|
||||||
throw Exception::FileNotFound( streamname );
|
throw Exception::FileNotFound( streamname );
|
||||||
|
|
||||||
case EPIPE:
|
case EPIPE:
|
||||||
throw Exception::BadStream( streamname, "Broken pipe" );
|
throw Exception::BadStream( streamname ).SetDiagMsg(L"Broken pipe");
|
||||||
|
|
||||||
case EBADF:
|
case EBADF:
|
||||||
throw Exception::BadStream( streamname, "Bad file number" );
|
throw Exception::BadStream( streamname ).SetDiagMsg(L"Bad file number");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Exception::Stream( streamname,
|
throw Exception::Stream( streamname ).SetDiagMsg(wxsFormat( L"General file/stream error [errno: %d]", errcode ));
|
||||||
wxsFormat( L"General file/stream error [errno: %d]", errcode )
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,22 +68,20 @@ void StreamException_ThrowLastError( const wxString& streamname, HANDLE result )
|
||||||
throw Exception::FileNotFound( streamname );
|
throw Exception::FileNotFound( streamname );
|
||||||
|
|
||||||
case ERROR_TOO_MANY_OPEN_FILES:
|
case ERROR_TOO_MANY_OPEN_FILES:
|
||||||
throw Exception::CannotCreateStream( streamname, "Too many open files" );
|
throw Exception::CannotCreateStream( streamname ).SetDiagMsg(L"Too many open files");
|
||||||
|
|
||||||
case ERROR_ACCESS_DENIED:
|
case ERROR_ACCESS_DENIED:
|
||||||
throw Exception::AccessDenied( streamname );
|
throw Exception::AccessDenied( streamname );
|
||||||
|
|
||||||
case ERROR_INVALID_HANDLE:
|
case ERROR_INVALID_HANDLE:
|
||||||
throw Exception::BadStream( streamname, "Stream object or handle is invalid" );
|
throw Exception::BadStream( streamname ).SetDiagMsg(L"Stream object or handle is invalid");
|
||||||
|
|
||||||
case ERROR_SHARING_VIOLATION:
|
case ERROR_SHARING_VIOLATION:
|
||||||
throw Exception::AccessDenied( streamname, "Sharing violation" );
|
throw Exception::AccessDenied( streamname ).SetDiagMsg(L"Sharing violation");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw Exception::Stream( streamname,
|
throw Exception::Stream( streamname ).SetDiagMsg(wxsFormat( L"General Win32 File/stream error [GetLastError: %d]", error ));
|
||||||
wxsFormat( L"General Win32 File/stream error [GetLastError: %d]", error )
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,35 +19,6 @@
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "ConsoleLogger.h"
|
#include "ConsoleLogger.h"
|
||||||
|
|
||||||
Exception::WinApiError::WinApiError( const char* msg )
|
|
||||||
{
|
|
||||||
ErrorId = GetLastError();
|
|
||||||
BaseException::InitBaseEx( msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString Exception::WinApiError::GetMsgFromWindows() const
|
|
||||||
{
|
|
||||||
if (!ErrorId)
|
|
||||||
return wxString();
|
|
||||||
|
|
||||||
const DWORD BUF_LEN = 2048;
|
|
||||||
TCHAR t_Msg[BUF_LEN];
|
|
||||||
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, ErrorId, 0, t_Msg, BUF_LEN, 0))
|
|
||||||
return wxsFormat( L"Win32 Error #%d: %s", ErrorId, t_Msg );
|
|
||||||
|
|
||||||
return wxsFormat( L"Win32 Error #%d (no text msg available)", ErrorId );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString Exception::WinApiError::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
return m_message_user + L"\n\n" + GetMsgFromWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString Exception::WinApiError::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
return m_message_diag + L"\n\t" + GetMsgFromWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Win32 Console Pipes
|
// Win32 Console Pipes
|
||||||
// As a courtesy and convenience, we redirect stdout/stderr to the console and logfile.
|
// As a courtesy and convenience, we redirect stdout/stderr to the console and logfile.
|
||||||
|
@ -102,7 +73,7 @@ protected:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Exception::WinApiError( "ReadFile from pipe failed." );
|
throw Exception::WinApiError().SetDiagMsg(L"ReadFile from pipe failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if( u32_Read <= 3 )
|
if( u32_Read <= 3 )
|
||||||
|
@ -120,7 +91,7 @@ protected:
|
||||||
{
|
{
|
||||||
Yield();
|
Yield();
|
||||||
if( !PeekNamedPipe(m_outpipe, 0, 0, 0, &u32_avail, 0) )
|
if( !PeekNamedPipe(m_outpipe, 0, 0, 0, &u32_avail, 0) )
|
||||||
throw Exception::WinApiError( "Error peeking Pipe." );
|
throw Exception::WinApiError().SetDiagMsg(L"Error peeking Pipe.");
|
||||||
|
|
||||||
if( u32_avail == 0 ) break;
|
if( u32_avail == 0 ) break;
|
||||||
|
|
||||||
|
@ -190,10 +161,10 @@ WinPipeRedirection::WinPipeRedirection( FILE* stdstream )
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if( 0 == CreatePipe( &m_readpipe, &m_writepipe, NULL, 0 ) )
|
if( 0 == CreatePipe( &m_readpipe, &m_writepipe, NULL, 0 ) )
|
||||||
throw Exception::WinApiError( "CreatePipe failed." );
|
throw Exception::WinApiError().SetDiagMsg(L"CreatePipe failed.");
|
||||||
|
|
||||||
if( 0 == SetStdHandle( m_stdhandle, m_writepipe ) )
|
if( 0 == SetStdHandle( m_stdhandle, m_writepipe ) )
|
||||||
throw Exception::WinApiError( "SetStdHandle failed." );
|
throw Exception::WinApiError().SetDiagMsg(L"SetStdHandle failed.");
|
||||||
|
|
||||||
// Note: Don't use GetStdHandle to "confirm" the handle.
|
// Note: Don't use GetStdHandle to "confirm" the handle.
|
||||||
//
|
//
|
||||||
|
@ -224,7 +195,7 @@ WinPipeRedirection::WinPipeRedirection( FILE* stdstream )
|
||||||
// the constructor, so re-pack a new exception:
|
// the constructor, so re-pack a new exception:
|
||||||
|
|
||||||
Cleanup();
|
Cleanup();
|
||||||
throw Exception::RuntimeError( ex.FormatDiagnosticMessage(), ex.FormatDisplayMessage() );
|
throw Exception::RuntimeError().SetDiagMsg( ex.FormatDiagnosticMessage() ).SetUserMsg( ex.FormatDisplayMessage() );
|
||||||
}
|
}
|
||||||
catch( BaseException& ex )
|
catch( BaseException& ex )
|
||||||
{
|
{
|
||||||
|
|
|
@ -772,7 +772,7 @@ static void recAlloc()
|
||||||
recMem = (u8*)SysMmapEx( 0x28000000, RECMEM_SIZE, 0, "recAlloc(R3000a)" );
|
recMem = (u8*)SysMmapEx( 0x28000000, RECMEM_SIZE, 0, "recAlloc(R3000a)" );
|
||||||
|
|
||||||
if( recMem == NULL )
|
if( recMem == NULL )
|
||||||
throw Exception::OutOfMemory( "R3000a Init > failed to allocate memory for the recompiler." );
|
throw Exception::OutOfMemory( L"R3000A recompiled code cache" );
|
||||||
|
|
||||||
// Goal: Allocate BASEBLOCKs for every possible branch target in IOP memory.
|
// Goal: Allocate BASEBLOCKs for every possible branch target in IOP memory.
|
||||||
// Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are
|
// Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are
|
||||||
|
@ -782,7 +782,7 @@ static void recAlloc()
|
||||||
m_recBlockAlloc = (u8*)_aligned_malloc( m_recBlockAllocSize, 4096 );
|
m_recBlockAlloc = (u8*)_aligned_malloc( m_recBlockAllocSize, 4096 );
|
||||||
|
|
||||||
if( m_recBlockAlloc == NULL )
|
if( m_recBlockAlloc == NULL )
|
||||||
throw Exception::OutOfMemory( "R3000a Init > Failed to allocate memory for baseblock lookup tables." );
|
throw Exception::OutOfMemory( L"R3000A BASEBLOCK lookup tables" );
|
||||||
|
|
||||||
u8* curpos = m_recBlockAlloc;
|
u8* curpos = m_recBlockAlloc;
|
||||||
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::IopRam / 4) * sizeof(BASEBLOCK);
|
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::IopRam / 4) * sizeof(BASEBLOCK);
|
||||||
|
@ -796,7 +796,7 @@ static void recAlloc()
|
||||||
}
|
}
|
||||||
|
|
||||||
if( s_pInstCache == NULL )
|
if( s_pInstCache == NULL )
|
||||||
throw Exception::OutOfMemory( "R3000a Init > Failed to allocate memory for pInstCache." );
|
throw Exception::OutOfMemory( L"R3000 InstCache." );
|
||||||
|
|
||||||
ProfilerRegisterSource( "IOP Rec", recMem, RECMEM_SIZE );
|
ProfilerRegisterSource( "IOP Rec", recMem, RECMEM_SIZE );
|
||||||
_DynGen_Dispatchers();
|
_DynGen_Dispatchers();
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
|
|
||||||
|
#include "R5900Exceptions.h"
|
||||||
#include "R5900OpcodeTables.h"
|
#include "R5900OpcodeTables.h"
|
||||||
#include "iR5900.h"
|
#include "iR5900.h"
|
||||||
|
|
||||||
|
@ -61,6 +63,8 @@ bool g_cpuFlushedPC, g_recompilingDelaySlot, g_maySignalException;
|
||||||
#define X86
|
#define X86
|
||||||
static const int RECCONSTBUF_SIZE = 16384 * 2; // 64 bit consts in 32 bit units
|
static const int RECCONSTBUF_SIZE = 16384 * 2; // 64 bit consts in 32 bit units
|
||||||
|
|
||||||
|
static ScopedPtr<BaseR5900Exception> m_vmException;
|
||||||
|
|
||||||
static u8 *recMem = NULL; // the recompiled blocks will be here
|
static u8 *recMem = NULL; // the recompiled blocks will be here
|
||||||
static u32* recConstBuf = NULL; // 64-bit pseudo-immediates
|
static u32* recConstBuf = NULL; // 64-bit pseudo-immediates
|
||||||
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
|
static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here
|
||||||
|
@ -534,10 +538,9 @@ static const uint m_recBlockAllocSize =
|
||||||
|
|
||||||
static void recThrowHardwareDeficiency( const wxChar* extFail )
|
static void recThrowHardwareDeficiency( const wxChar* extFail )
|
||||||
{
|
{
|
||||||
throw Exception::HardwareDeficiency(
|
throw Exception::HardwareDeficiency()
|
||||||
wxsFormat( L"R5900-32 recompiler init failed: %s is not available.", extFail),
|
.SetDiagMsg(wxsFormat( L"R5900-32 recompiler init failed: %s is not available.", extFail))
|
||||||
wxsFormat(_("%s Extensions not found. The R5900-32 recompiler requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail )
|
.SetUserMsg(wxsFormat(_("%s Extensions not found. The R5900-32 recompiler requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail ));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void recAlloc()
|
static void recAlloc()
|
||||||
|
@ -569,7 +572,7 @@ static void recAlloc()
|
||||||
}
|
}
|
||||||
|
|
||||||
if( recMem == NULL )
|
if( recMem == NULL )
|
||||||
throw Exception::OutOfMemory( "R5900-32: Out of memory allocating recompiled code buffer." );
|
throw Exception::OutOfMemory( L"R5900-32 recompiled code cache" );
|
||||||
|
|
||||||
// Goal: Allocate BASEBLOCKs for every possible branch target in PS2 memory.
|
// Goal: Allocate BASEBLOCKs for every possible branch target in PS2 memory.
|
||||||
// Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are
|
// Any 4-byte aligned address makes a valid branch target as per MIPS design (all instructions are
|
||||||
|
@ -579,7 +582,7 @@ static void recAlloc()
|
||||||
m_recBlockAlloc = (u8*) _aligned_malloc( m_recBlockAllocSize, 4096 );
|
m_recBlockAlloc = (u8*) _aligned_malloc( m_recBlockAllocSize, 4096 );
|
||||||
|
|
||||||
if( m_recBlockAlloc == NULL )
|
if( m_recBlockAlloc == NULL )
|
||||||
throw Exception::OutOfMemory( "R5900-32: Out of memory allocating BASEBLOCK tables." );
|
throw Exception::OutOfMemory( L"R5900-32 BASEBLOCK tables" );
|
||||||
|
|
||||||
u8* curpos = m_recBlockAlloc;
|
u8* curpos = m_recBlockAlloc;
|
||||||
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
|
recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
|
||||||
|
@ -595,7 +598,7 @@ static void recAlloc()
|
||||||
}
|
}
|
||||||
|
|
||||||
if( s_pInstCache == NULL )
|
if( s_pInstCache == NULL )
|
||||||
throw Exception::OutOfMemory( "R5900-32: Out of memory allocating InstCache." );
|
throw Exception::OutOfMemory( L"R5900-32 InstCache" );
|
||||||
|
|
||||||
// No errors.. Proceed with initialization:
|
// No errors.. Proceed with initialization:
|
||||||
|
|
||||||
|
@ -722,12 +725,14 @@ static void recExitExecution()
|
||||||
|
|
||||||
static void recCheckExecutionState()
|
static void recCheckExecutionState()
|
||||||
{
|
{
|
||||||
if( eeRecIsReset || GetCoreThread().HasPendingStateChangeRequest() )
|
if( eeRecIsReset || m_vmException || GetCoreThread().HasPendingStateChangeRequest() )
|
||||||
{
|
{
|
||||||
recExitExecution();
|
recExitExecution();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool m_recExecutingCode = false;
|
||||||
|
|
||||||
static void recExecute()
|
static void recExecute()
|
||||||
{
|
{
|
||||||
// Implementation Notes:
|
// Implementation Notes:
|
||||||
|
@ -735,7 +740,9 @@ static void recExecute()
|
||||||
|
|
||||||
#if PCSX2_SEH
|
#if PCSX2_SEH
|
||||||
eeRecIsReset = false;
|
eeRecIsReset = false;
|
||||||
|
m_vmException = NULL;
|
||||||
g_EEFreezeRegs = true;
|
g_EEFreezeRegs = true;
|
||||||
|
ScopedBool executing(m_recExecutingCode);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
EnterRecompiledCode();
|
EnterRecompiledCode();
|
||||||
|
@ -766,6 +773,8 @@ static void recExecute()
|
||||||
pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
|
pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(m_vmException) m_vmException->Rethrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
@ -1813,6 +1822,18 @@ StartRecomp:
|
||||||
s_pCurBlockEx = NULL;
|
s_pCurBlockEx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The only *safe* way to throw exceptions from the context of recompiled code.
|
||||||
|
// The exception is cached and the recompiler is exited safely using either an
|
||||||
|
// SEH unwind (MSW) or setjmp/longjmp (GCC).
|
||||||
|
void recThrowException( const BaseR5900Exception& ex )
|
||||||
|
{
|
||||||
|
if (!m_recExecutingCode) ex.Rethrow();
|
||||||
|
|
||||||
|
m_vmException = ex.Clone();
|
||||||
|
recExitExecution();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
R5900cpu recCpu =
|
R5900cpu recCpu =
|
||||||
{
|
{
|
||||||
recAlloc,
|
recAlloc,
|
||||||
|
@ -1823,5 +1844,6 @@ R5900cpu recCpu =
|
||||||
recExecute,
|
recExecute,
|
||||||
|
|
||||||
recCheckExecutionState,
|
recCheckExecutionState,
|
||||||
|
recThrowException,
|
||||||
recClear,
|
recClear,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include <deque>
|
||||||
#include "microVU.h"
|
#include "microVU.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -64,10 +65,9 @@ const __aligned(32) mVU_Globals mVUglob = {
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
_f void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) {
|
_f void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) {
|
||||||
throw Exception::HardwareDeficiency(
|
throw Exception::HardwareDeficiency()
|
||||||
wxsFormat( L"microVU%d recompiler init failed: %s is not available.", vuIndex, extFail),
|
.SetDiagMsg(wxsFormat(L"microVU%d recompiler init failed: %s is not available.", vuIndex, extFail))
|
||||||
wxsFormat(_("%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail )
|
.SetUserMsg(wxsFormat(_("%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail ));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only run this once per VU! ;)
|
// Only run this once per VU! ;)
|
||||||
|
@ -96,7 +96,7 @@ _f void mVUinit(VURegs* vuRegsPtr, int vuIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mVU->dispCache = SysMmapEx(NULL, mVUdispCacheSize, 0, (mVU->index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher"));
|
mVU->dispCache = SysMmapEx(NULL, mVUdispCacheSize, 0, (mVU->index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher"));
|
||||||
if (!mVU->dispCache) throw Exception::OutOfMemory("microVU Error: Failed to allocate dispatcher memory!");
|
if (!mVU->dispCache) throw Exception::OutOfMemory( mVU->index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" );
|
||||||
memset(mVU->dispCache, 0xcc, mVUdispCacheSize);
|
memset(mVU->dispCache, 0xcc, mVUdispCacheSize);
|
||||||
|
|
||||||
// Setup Entrance/Exit Points
|
// Setup Entrance/Exit Points
|
||||||
|
@ -165,12 +165,8 @@ void mVUresizeCache(mV, u32 size) {
|
||||||
if (size > (u32)mVUcacheMaxSize) { if (mVU->cacheSize==mVUcacheMaxSize) return; size = mVUcacheMaxSize; }
|
if (size > (u32)mVUcacheMaxSize) { if (mVU->cacheSize==mVUcacheMaxSize) return; size = mVUcacheMaxSize; }
|
||||||
if (mVU->cache) Console.WriteLn(Color_Green, "microVU%d: Attempting to resize Cache [%dmb]", mVU->index, size/_1mb);
|
if (mVU->cache) Console.WriteLn(Color_Green, "microVU%d: Attempting to resize Cache [%dmb]", mVU->index, size/_1mb);
|
||||||
|
|
||||||
// Give SysMmapEx a NULL and let the OS pick the memory for us: mVU can work with any
|
u8* cache = SysMmapEx(NULL, size, 0, (mVU->index ? "Micro VU1 RecCache" : "Micro VU0 RecCache"));
|
||||||
// address the operating system gives us, and unlike the EE/IOP there's not much convenience
|
if(!cache && !mVU->cache) throw Exception::OutOfMemory( wxsFormat( L"Micro VU%d recompiled code cache", mVU->index) );
|
||||||
// to debugging if the address is known anyway due to mVU's complex memory layouts (caching).
|
|
||||||
|
|
||||||
u8* cache = SysMmapEx(NULL, size, 0, (mVU->index ? "Micro VU1" : "Micro VU0"));
|
|
||||||
if(!cache && !mVU->cache) throw Exception::OutOfMemory("microVU Error: Failed to allocate recompiler memory!");
|
|
||||||
if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); return; }
|
if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); return; }
|
||||||
if (mVU->cache) {
|
if (mVU->cache) {
|
||||||
HostSys::Munmap(mVU->cache, mVU->cacheSize);
|
HostSys::Munmap(mVU->cache, mVU->cacheSize);
|
||||||
|
@ -272,7 +268,7 @@ _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||||
microProgramQuick& quick = mVU->prog.quick[startPC/8];
|
microProgramQuick& quick = mVU->prog.quick[startPC/8];
|
||||||
microProgramList& list = mVU->prog.prog [startPC/8];
|
microProgramList& list = mVU->prog.prog [startPC/8];
|
||||||
if(!quick.prog) { // If null, we need to search for new program
|
if(!quick.prog) { // If null, we need to search for new program
|
||||||
deque<microProgram*>::iterator it = list.list->begin();
|
deque<microProgram*>::iterator it( list.list->begin() );
|
||||||
for ( ; it != list.list->end(); it++) {
|
for ( ; it != list.list->end(); it++) {
|
||||||
if (mVUcmpProg<vuIndex>(*it[0], 0)) {
|
if (mVUcmpProg<vuIndex>(*it[0], 0)) {
|
||||||
quick.block = it[0]->block[startPC/8];
|
quick.block = it[0]->block[startPC/8];
|
||||||
|
@ -282,7 +278,13 @@ _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||||
return mVUentryGet(mVU, quick.block, startPC, pState);
|
return mVUentryGet(mVU, quick.block, startPC, pState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If cleared and program not found, make a new program instance
|
// If cleared and program not found, make a new program instance
|
||||||
|
// Exception note: It's bad news if the recompiler throws any exceptions, so we have a clause to
|
||||||
|
// assert if an exception occurs. The rec should be pretty much exception safe, except for
|
||||||
|
// critical errors that would result in a crash regardless.
|
||||||
|
|
||||||
|
try {
|
||||||
mVU->prog.cleared = 0;
|
mVU->prog.cleared = 0;
|
||||||
mVU->prog.isSame = 1;
|
mVU->prog.isSame = 1;
|
||||||
mVU->prog.cur = mVUcreateProg<vuIndex>(startPC/8);
|
mVU->prog.cur = mVUcreateProg<vuIndex>(startPC/8);
|
||||||
|
@ -290,7 +292,16 @@ _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||||
quick.block = mVU->prog.cur->block[startPC/8];
|
quick.block = mVU->prog.cur->block[startPC/8];
|
||||||
quick.prog = mVU->prog.cur;
|
quick.prog = mVU->prog.cur;
|
||||||
list.list->push_front(mVU->prog.cur);
|
list.list->push_front(mVU->prog.cur);
|
||||||
|
|
||||||
return entryPoint;
|
return entryPoint;
|
||||||
|
|
||||||
|
} catch( BaseException& ex ) {
|
||||||
|
pxFailDev( wxsFormat(L"microVU%d recompiler exception: " + ex.FormatDiagnosticMessage(), mVU->index) );
|
||||||
|
} catch( std::exception& ex ) {
|
||||||
|
pxFailDev( wxsFormat(L"microVU%d recompiler exception: " + Exception::RuntimeError(ex).FormatDiagnosticMessage(), mVU->index) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
// If list.quick, then we've already found and recompiled the program ;)
|
// If list.quick, then we've already found and recompiled the program ;)
|
||||||
mVU->prog.isSame = -1;
|
mVU->prog.isSame = -1;
|
||||||
|
|
|
@ -33,7 +33,7 @@ protected:
|
||||||
|
|
||||||
void alloc(int size) {
|
void alloc(int size) {
|
||||||
mData = SysMmapEx(NULL, size, 0, "nVif_BlockBuffer");
|
mData = SysMmapEx(NULL, size, 0, "nVif_BlockBuffer");
|
||||||
if (!mData) throw Exception::OutOfMemory("nVif Error: Failed to allocate recompiler memory!");
|
if (!mData) throw Exception::OutOfMemory(L"nVif recompiled code buffer (nVif_BlockBuffer)");
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
void dealloc(u8* &dPtr, int size) {
|
void dealloc(u8* &dPtr, int size) {
|
||||||
|
|
|
@ -83,8 +83,7 @@ public:
|
||||||
|
|
||||||
if( bucket.Chain = (T*)_aligned_realloc( bucket.Chain, sizeof(T)*(bucket.Size+1), 16), bucket.Chain==NULL ) {
|
if( bucket.Chain = (T*)_aligned_realloc( bucket.Chain, sizeof(T)*(bucket.Size+1), 16), bucket.Chain==NULL ) {
|
||||||
throw Exception::OutOfMemory(
|
throw Exception::OutOfMemory(
|
||||||
wxsFormat(L"Out of memory re-allocating hash bucket (bucket size=%d)", bucket.Size+1),
|
wxsFormat(L"HashBucket Chain (bucket size=%d)", bucket.Size+1)
|
||||||
wxEmptyString
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
memcpy_const(&bucket.Chain[bucket.Size++], &dataPtr, sizeof(T));
|
memcpy_const(&bucket.Chain[bucket.Size++], &dataPtr, sizeof(T));
|
||||||
|
|
|
@ -2008,6 +2008,8 @@ void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
|
||||||
size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff);
|
size = GIFPath_ParseTagQuick(GIF_PATH_1, data, diff);
|
||||||
pDest = &Path1Buffer[Path1WritePos*16];
|
pDest = &Path1Buffer[Path1WritePos*16];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pxAssumeMsg((Path1WritePos+size < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!");
|
pxAssumeMsg((Path1WritePos+size < sizeof(Path1Buffer)), "XGKick Buffer Overflow detected on Path1Buffer!");
|
||||||
|
|
||||||
//DevCon.Warning("Storing size %x PATH 1", size);
|
//DevCon.Warning("Storing size %x PATH 1", size);
|
||||||
|
|
|
@ -360,13 +360,13 @@ static void SuperVUAlloc(int vuindex)
|
||||||
|
|
||||||
if (s_recVUMem == NULL)
|
if (s_recVUMem == NULL)
|
||||||
{
|
{
|
||||||
throw Exception::VirtualMemoryMapConflict(
|
throw Exception::VirtualMemoryMapConflict()
|
||||||
// untranslated diagnostic msg, use exception's default for translation
|
.SetDiagMsg(wxsFormat( L"SuperVU failed to allocate virtual memory below 256MB." ))
|
||||||
wxsFormat( L"SuperVU failed to allocate virtual memory below 256MB." ),
|
.SetUserMsg(pxE( ".Error:superVU:VirtualMemoryAlloc",
|
||||||
|
L"Out of Memory (sorta): The SuperVU recompiler was unable to reserve the specific memory "
|
||||||
// Translated message
|
L"ranges required, and will not be available for use. This is not a critical error, since "
|
||||||
_("Out of Memory (sorta): The SuperVU recompiler was unable to reserve the specific memory ranges required.")
|
L"the sVU rec is obsolete, and you should use microVU instead anyway. :)"
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfilerRegisterSource("sVU Rec", s_recVUMem, VU_EXESIZE);
|
ProfilerRegisterSource("sVU Rec", s_recVUMem, VU_EXESIZE);
|
||||||
|
@ -453,7 +453,7 @@ void SuperVUReset(int vuindex)
|
||||||
if (s_recVUMem == NULL)
|
if (s_recVUMem == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//jASSUME( s_recVUMem != NULL );
|
//pxAssume( s_recVUMem != NULL );
|
||||||
|
|
||||||
if (vuindex < 0)
|
if (vuindex < 0)
|
||||||
{
|
{
|
||||||
|
@ -470,7 +470,6 @@ void SuperVUReset(int vuindex)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DbgCon.WriteLn("SuperVU [VU%d]: Resetting the recs and junk", vuindex);
|
DbgCon.WriteLn("SuperVU [VU%d]: Resetting the recs and junk", vuindex);
|
||||||
list<VuFunctionHeader*>::iterator it;
|
|
||||||
if (recVUHeaders[vuindex]) memset(recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex] / 8));
|
if (recVUHeaders[vuindex]) memset(recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex] / 8));
|
||||||
if (recVUBlocks[vuindex]) memset(recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex] / 8));
|
if (recVUBlocks[vuindex]) memset(recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex] / 8));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue