User Interface code cleanups and bugfixes. some highlights:

* Configuration panels are all modal-less now, so that you can open the config panel and leave it open while running games.
 * Handful of thread sync improvements.
 * Fixed on-the-fly interpreter/recompiler configuration.
 * Fixed plugin hotswapping (mostly works, but still a little funny at times)
 * All new assertion dialogs and popup message handlers.
 * RecentIsoList defaults to 12 instead of 6

Dev Notes:
 * I had to create a new set of assertion functions called pxAssume*.  Originally I hoped to avoid that complexity, and just use a single one-assert-fits-all case, but turned out blanketly using __assume() for all assertion cases wasn't reliable.
 * wxGuiTools: Replaced the operator, with operator& -- the latter has proper order of precedence, the former required () to scope correctly. >_<

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2339 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine
2009-12-14 12:18:55 +00:00
parent cc65a5cd02
commit c17455c702
71 changed files with 1996 additions and 1118 deletions
+9 -2
View File
@@ -126,6 +126,13 @@
# endif
#endif
#ifdef PCSX2_DEBUG
# define pxDebugCode(code) code
#else
# define pxDebugCode(code)
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// __aligned / __aligned16 / __pagealigned
//
@@ -201,8 +208,8 @@ static const int __pagesize = PCSX2_PAGESIZE;
// Don't know if there are Visual C++ equivalents of these.
# define __hot
# define __cold
# define likely(x) x
# define unlikely(x) x
# define likely(x) (!!(x))
# define unlikely(x) (!!(x))
# define CALLBACK __stdcall
+110 -40
View File
@@ -15,60 +15,136 @@
#pragma once
#ifndef __pxFUNCTION__
#if defined(__GNUG__)
# define __pxFUNCTION__ __PRETTY_FUNCTION__
#else
# define __pxFUNCTION__ __FUNCTION__
#endif
#endif
#ifndef wxNullChar
# define wxNullChar ((wxChar*)NULL)
#endif
// FnChar_t - function name char type; typedef'd in case it ever changes between compilers
// (ie, a compiler decides to wchar_t it instead of char/UTF8).
typedef char FnChar_t;
// --------------------------------------------------------------------------------------
// DiagnosticOrigin
// --------------------------------------------------------------------------------------
struct DiagnosticOrigin
{
const wxChar* srcfile;
const FnChar_t* function;
const wxChar* condition;
int line;
DiagnosticOrigin( const wxChar *_file, int _line, const FnChar_t *_func, const wxChar* _cond = NULL )
: srcfile( _file )
, function( _func )
, condition( _cond )
, line( _line )
{
}
wxString ToString( const wxChar* msg=NULL ) const;
};
// Returns ture if the assertion is to trap into the debugger, or false if execution
// of the program should continue unimpeded.
typedef bool pxDoAssertFnType(const DiagnosticOrigin& origin, const wxChar *msg);
extern pxDoAssertFnType pxAssertImpl_LogIt;
extern pxDoAssertFnType* pxDoAssert;
// ----------------------------------------------------------------------------------------
// pxAssert / pxAssertDev / pxFail / pxFailDev
// pxAssert / pxAssertDev
// ----------------------------------------------------------------------------------------
// Standard "nothrow" assertions. All assertions act as valid conditional statements that
// return the result of the specified conditional; useful for handling failed assertions in
// a "graceful" fashion when utilizing the "ignore" feature of assertion debugging.
// These macros are mostly intended for "pseudo-weak" assumptions within code, most often for
// testing threaded user interface code (threading of the UI is a prime example since often
// even very robust assertions can fail in very rare conditions, due to the complex variety
// of ways the user can invoke UI events).
//
// Performance: All assertion types optimize into __assume()/likely() directives in Release
// builds. If using assertions as part of a conditional, the conditional code *will* not
// be optimized out, so use conditionals with caution.
// All macros return TRUE if the assertion succeeds, or FALSE if the assertion failed
// (thus matching the condition of the assertion itself).
//
// pxAssertDev is an assertion tool for Devel builds, intended for sanity checking and/or
// bounds checking variables in areas which are not performance critical. Another common
// use is for checking thread affinity on utility functions.
//
// Credits Notes: These macros are based on a combination of wxASSERT, MSVCRT's assert
// and the ATL's Assertion/Assumption macros. the best of all worlds!
// Credits: These macros are based on a combination of wxASSERT, MSVCRT's assert and the
// ATL's Assertion/Assumption macros. the best of all worlds!
// --------------------------------------------------------------------------------------
// pxAssume / pxAssumeDev / pxFail / pxFailDev
// --------------------------------------------------------------------------------------
// Assumptions are like "extra rigid" assertions, which should never fail under any circum-
// stance in release build optimized code.
//
// Performance: All assumption/fail types optimize into __assume()/likely() directives in
// Release builds (non-dev varieties optimize as such in Devel builds as well). If using
#define pxDiagSpot DiagnosticOrigin( __TFILE__, __LINE__, __pxFUNCTION__ )
#define pxAssertSpot(cond) DiagnosticOrigin( __TFILE__, __LINE__, __pxFUNCTION__, _T(#cond) )
// pxAssertRel ->
// Special release-mode assertion. Limited use since stack traces in release mode builds
// (especially with LTCG) are highly suspect. But when troubleshooting crashes that only
// rear ugly heads in optimized builds, this is one of the few tools we have.
#define pxAssertRel(cond, msg) ( (likely(cond)) || (pxOnAssert(pxAssertSpot(cond), msg), false) )
#define pxAssumeMsg(cond, msg) ((void) ( (!likely(cond)) && (pxOnAssert(pxAssertSpot(cond), msg), false) ))
#if defined(PCSX2_DEBUG)
# define pxAssertMsg(cond, msg) ( (!!(cond)) || \
(pxOnAssert(__TFILE__, __LINE__, __WXFUNCTION__, _T(#cond), msg), likely(cond)) )
# define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
# define pxAssertDev(cond, msg) pxAssertMsg(cond, msg)
# define pxAssertDev(cond,msg) pxAssertMsg(cond, msg)
# define pxAssume(cond) pxAssumeMsg(cond, wxNullChar)
# define pxAssumeDev(cond, msg) pxAssumeMsg(cond, msg)
# define pxFail(msg) pxAssertMsg(false, msg)
# define pxFailDev(msg) pxAssertDev(false, msg)
# define pxFail(msg) pxAssumeMsg(false, msg)
# define pxFailDev(msg) pxAssumeDev(false, msg)
#elif defined(PCSX2_DEVBUILD)
// Devel builds use __assume for standard assertions and call pxOnAssertDevel
// for AssertDev brand assertions (which typically throws a LogicError exception).
# define pxAssertMsg(cond, msg) (__assume(cond), likely(cond))
# define pxAssertMsg(cond, msg) (likely(cond))
# define pxAssertDev(cond, msg) pxAssertRel(cond, msg)
# define pxAssertDev(cond, msg) ( (!!(cond)) || \
(pxOnAssert(__TFILE__, __LINE__, __WXFUNCTION__, _T(#cond), msg), likely(cond)) )
# define pxAssume(cond) (__assume(cond))
# define pxAssumeDev(cond, msg) pxAssumeMsg(cond, msg)
# define pxFail(msg) (__assume(false), false)
# define pxFailDev(msg ) pxAssertDev(false, msg)
# define pxFail(msg) (__assume(false))
# define pxFailDev(msg) pxAssumeDev(false, msg)
#else
// Release Builds just use __assume as an optimization, and return the conditional
// as a result (which is optimized to nil if unused).
# define pxAssertMsg(cond, msg) (__assume(cond), likely(cond))
# define pxAssertDev(cond, msg) (__assume(cond), likely(cond))
# define pxFail(msg) (__assume(false), false)
# define pxFailDev(msg) (__assume(false), false)
# define pxAssertMsg(cond, msg) (likely(cond))
# define pxAssertDev(cond, msg) (likely(cond))
# define pxAssume(cond) (__assume(cond))
# define pxAssumeDev(cond, msg) (__assume(cond))
# define pxFail(msg) (__assume(false))
# define pxFailDev(msg) (__assume(false))
#endif
#define pxAssert(cond) pxAssertMsg(cond, (wxChar*)NULL)
#define pxAssert(cond) pxAssertMsg(cond, wxNullChar)
#define pxAssertRelease( cond, msg )
// Performs an unsigned index bounds check, and generates a debug assertion if the check fails.
// For stricter checking in Devel builds as well as debug builds (but possibly slower), use
@@ -81,8 +157,8 @@
wxsFormat( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
extern void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const wxChar* msg);
extern void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const char* msg);
extern void pxOnAssert( const DiagnosticOrigin& origin, const wxChar* msg=NULL );
extern void pxOnAssert( const DiagnosticOrigin& origin, const char* msg );
//////////////////////////////////////////////////////////////////////////////////////////
// jNO_DEFAULT -- disables the default case in a switch, which improves switch optimization
@@ -92,29 +168,23 @@ extern void pxOnAssert( const wxChar* file, int line, const char* func, const wx
// in the 'default:' case of a switch tells the compiler that the case is unreachable, so
// that it will not generate any code, LUTs, or conditionals to handle it.
//
// * In debug builds the default case will cause an assertion.
// * In devel builds the default case will cause a LogicError exception (C++ only)
// (either meaning the jNO_DEFAULT has been used incorrectly, and that the default case is in
// fact used and needs to be handled).
//
// MSVC Note: To stacktrace LogicError exceptions, add Exception::LogicError to the C++ First-
// Chance Exception list (under Debug->Exceptions menu).
// * In debug/devel builds the default case will cause an assertion.
//
#ifndef jNO_DEFAULT
#if defined(__cplusplus) && defined(PCSX2_DEVBUILD)
# define jNO_DEFAULT \
default: \
{ \
pxFailDev( "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)" ); \
break; \
}
default: \
{ \
pxFailDev( "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)" ); \
break; \
}
#else
# define jNO_DEFAULT \
default: \
{ \
jASSUME(0); \
break; \
}
default: \
{ \
jASSUME(0); \
break; \
}
#endif
#endif
+3 -33
View File
@@ -38,11 +38,7 @@
Console.Error( ex.what() ); \
}
#ifdef __GNUG__
# define DESTRUCTOR_CATCHALL __DESTRUCTOR_CATCHALL( __PRETTY_FUNCTION__ )
#else
# define DESTRUCTOR_CATCHALL __DESTRUCTOR_CATCHALL( __FUNCTION__ )
#endif
#define DESTRUCTOR_CATCHALL __DESTRUCTOR_CATCHALL( __pxFUNCTION__ )
namespace Exception
{
@@ -56,7 +52,7 @@ namespace Exception
// catch clause can optionally modify them and then re-throw to a top-level handler.
//
// Note, this class is "abstract" which means you shouldn't use it directly like, ever.
// Use Exception::RuntimeError or Exception::LogicError instead for generic exceptions.
// Use Exception::RuntimeError instead for generic exceptions.
//
// Because exceptions are the (only!) really useful example of multiple inheritance,
// this class has only a trivial constructor, and must be manually initialized using
@@ -150,7 +146,7 @@ namespace Exception
explicit classname( const wxString& msg_eng ) { BaseException::InitBaseEx( msg_eng, wxEmptyString ); }
// ---------------------------------------------------------------------------------------
// RuntimeError / LogicError - Generalized Exceptions
// RuntimeError - Generalized Exceptions with Recoverable Traits!
// ---------------------------------------------------------------------------------------
class RuntimeError : public virtual BaseException
@@ -161,14 +157,6 @@ namespace Exception
DEFINE_RUNTIME_EXCEPTION( RuntimeError, wxLt("An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter.") )
};
// LogicErrors do not need translated versions, since they are typically obscure, and the
// user wouldn't benefit from being able to understand them anyway. :)
class LogicError : public virtual BaseException
{
public:
DEFINE_LOGIC_EXCEPTION( LogicError, wxLt("An unhandled logic error has occurred.") )
};
// --------------------------------------------------------------------------------------
// CancelAppEvent - Exception for canceling an event in a non-verbose fashion
// --------------------------------------------------------------------------------------
@@ -227,24 +215,6 @@ namespace Exception
DEFINE_RUNTIME_EXCEPTION( OutOfMemory, wxLt("Out of Memory") )
};
// This exception thrown any time an operation is attempted when an object
// is in an uninitialized state.
//
class InvalidOperation : public virtual LogicError
{
public:
DEFINE_LOGIC_EXCEPTION( InvalidOperation, "Attempted method call is invalid for the current object or program state." )
};
// This exception thrown any time an operation is attempted when an object
// is in an uninitialized state.
//
class InvalidArgument : public virtual LogicError
{
public:
DEFINE_LOGIC_EXCEPTION( InvalidArgument, "Invalid argument passed to a function." )
};
class ParseError : public RuntimeError
{
public:
+9 -5
View File
@@ -32,6 +32,9 @@ class wxTimeSpan;
namespace Threading
{
class PersistentThread;
PersistentThread* pxGetCurrentThread();
wxString pxGetCurrentThreadName();
}
namespace Exception
@@ -346,12 +349,11 @@ namespace Threading
DeclareNoncopyableObject(PersistentThread);
protected:
typedef int (*PlainJoeFP)();
wxString m_name; // diagnostic name for our thread.
pthread_t m_thread;
Semaphore m_sem_event; // general wait event that's needed by most threads.
Semaphore m_sem_event; // general wait event that's needed by most threads
Semaphore m_sem_startup; // startup sync tool
Mutex m_lock_InThread; // used for canceling and closing threads in a deadlock-safe manner
MutexLockRecursive m_lock_start; // used to lock the Start() code from starting simultaneous threads accidentally.
@@ -369,6 +371,7 @@ namespace Threading
virtual void Start();
virtual void Cancel( bool isBlocking = true );
virtual bool Cancel( const wxTimeSpan& timeout );
virtual bool Detach();
virtual void Block();
virtual void RethrowException() const;
@@ -419,12 +422,13 @@ namespace Threading
void FrankenMutex( Mutex& mutex );
bool AffinityAssert_AllowFromSelf() const;
bool AffinityAssert_DisallowFromSelf() const;
bool AffinityAssert_AllowFromSelf( const DiagnosticOrigin& origin ) const;
bool AffinityAssert_DisallowFromSelf( const DiagnosticOrigin& origin ) const;
// ----------------------------------------------------------------------------
// Section of methods for internal use only.
bool _basecancel();
void _selfRunningTest( const wxChar* name ) const;
void _DoSetThreadName( const wxString& name );
void _DoSetThreadName( const char* name );
+7
View File
@@ -58,9 +58,16 @@ protected:
extern void operator+=( wxSizer& target, pxCheckBox* src );
extern void operator+=( wxSizer& target, pxCheckBox& src );
extern void operator+=( wxSizer* target, pxCheckBox& src );
template<>
inline void operator+=( wxSizer& target, const pxWindowAndFlags<pxCheckBox>& src )
{
target.Add( src.window, src.flags );
}
template<>
inline void operator+=( wxSizer* target, const pxWindowAndFlags<pxCheckBox>& src )
{
target->Add( src.window, src.flags );
}
+2 -1
View File
@@ -111,7 +111,8 @@ public:
pxRadioPanel& SetToolTip( int idx, const wxString& tip );
pxRadioPanel& SetSelection( int idx );
pxRadioPanel& SetDefault( int idx );
pxRadioPanel& SetDefaultItem( int idx );
pxRadioPanel& EnableItem( int idx, bool enable=true );
int GetSelection() const;
wxWindowID GetSelectionId() const;
+8
View File
@@ -86,6 +86,7 @@ protected:
extern void operator+=( wxSizer& target, pxStaticText* src );
extern void operator+=( wxSizer& target, pxStaticText& src );
extern void operator+=( wxSizer* target, pxStaticText& src );
template<>
inline void operator+=( wxSizer& target, const pxWindowAndFlags<pxStaticText>& src )
@@ -94,6 +95,13 @@ inline void operator+=( wxSizer& target, const pxWindowAndFlags<pxStaticText>& s
//target.Add( src.window, src.flags );
}
template<>
inline void operator+=( wxSizer* target, const pxWindowAndFlags<pxStaticText>& src )
{
src.window->AddTo( target, src.flags );
//target.Add( src.window, src.flags );
}
// --------------------------------------------------------------------------------------
// pxStaticHeading
// --------------------------------------------------------------------------------------
+102 -17
View File
@@ -52,15 +52,25 @@ struct pxAlignmentType
wxSizerFlags Apply( wxSizerFlags flags=wxSizerFlags() ) const;
wxSizerFlags operator& ( const wxSizerFlags& _flgs ) const
{
return Apply( _flgs );
}
wxSizerFlags Border( int dir, int padding ) const
{
return Apply().Border( dir, padding );
}
wxSizerFlags Proportion( int prop ) const
{
return Apply().Proportion( intval );
}
operator wxSizerFlags() const
{
return Apply();
}
wxSizerFlags operator | ( const wxSizerFlags& _flgs )
{
return Apply( _flgs );
}
};
struct pxStretchType
@@ -78,15 +88,47 @@ struct pxStretchType
wxSizerFlags Apply( wxSizerFlags flags=wxSizerFlags() ) const;
wxSizerFlags operator& ( const wxSizerFlags& _flgs ) const
{
return Apply( _flgs );
}
wxSizerFlags Border( int dir, int padding ) const
{
return Apply().Border( dir, padding );
}
wxSizerFlags Proportion( int prop ) const
{
return Apply().Proportion( intval );
}
operator wxSizerFlags() const
{
return Apply();
}
};
wxSizerFlags operator | ( const wxSizerFlags& _flgs )
class pxProportion
{
int intval;
pxProportion( int prop )
{
intval = prop;
}
wxSizerFlags Apply( wxSizerFlags flags=wxSizerFlags() ) const;
wxSizerFlags operator& ( const wxSizerFlags& _flgs ) const
{
return Apply( _flgs );
}
operator wxSizerFlags() const
{
return Apply();
}
};
extern const pxAlignmentType
@@ -128,8 +170,7 @@ struct pxWindowAndFlags
};
extern wxSizerFlags operator , ( const wxSizerFlags& _flgs, const wxSizerFlags& _flgs2 ); //pxAlignmentType align );
//extern wxSizerFlags operator , ( const wxSizerFlags& _flgs, pxStretchType stretch );
extern wxSizerFlags operator& ( const wxSizerFlags& _flgs, const wxSizerFlags& _flgs2 );
template< typename WinType >
pxWindowAndFlags<WinType> operator | ( WinType* _win, const wxSizerFlags& _flgs )
@@ -162,9 +203,13 @@ extern void operator+=( wxSizer& target, wxSizer* src );
extern void operator+=( wxSizer& target, wxWindow& src );
extern void operator+=( wxSizer& target, wxSizer& src );
extern void operator+=( wxSizer* target, wxWindow& src );
extern void operator+=( wxSizer* target, wxSizer& src );
extern void operator+=( wxSizer& target, int spacer );
extern void operator+=( wxWindow& target, int spacer );
// ----------------------------------------------------------------------------
// Important: This template is needed in order to retain window type information and
// invoke the proper overloaded version of += (which is used by pxStaticText and other
// classes to perform special actions when added to sizers).
@@ -178,6 +223,14 @@ void operator+=( wxWindow& target, WinType* src )
template< typename WinType >
void operator+=( wxWindow& target, WinType& src )
{
if( !pxAssert( target.GetSizer() != NULL ) ) return;
*target.GetSizer() += src;
}
template< typename WinType >
void operator+=( wxWindow& target, const pxWindowAndFlags<WinType>& src )
{
if( !pxAssert( target.GetSizer() != NULL ) ) return;
*target.GetSizer() += src;
}
@@ -187,11 +240,31 @@ void operator+=( wxSizer& target, const pxWindowAndFlags<WinType>& src )
target.Add( src.window, src.flags );
}
// ----------------------------------------------------------------------------
// Pointer Versions! (note that C++ requires one of the two operator params be a
// "poper" object type (non-pointer), so that's why some of these are missing.
template< typename WinType >
void operator+=( wxWindow& target, const pxWindowAndFlags<WinType>& src )
void operator+=( wxWindow* target, WinType& src )
{
if( !pxAssert( target.GetSizer() != NULL ) ) return;
*target.GetSizer() += src;
if( !pxAssert( target != NULL ) ) return;
if( !pxAssert( target->GetSizer() != NULL ) ) return;
*target->GetSizer() += src;
}
template< typename WinType >
void operator+=( wxWindow* target, const pxWindowAndFlags<WinType>& src )
{
if( !pxAssert( target != NULL ) ) return;
if( !pxAssert( target->GetSizer() != NULL ) ) return;
*target->GetSizer() += src;
}
template< typename WinType >
void operator+=( wxSizer* target, const pxWindowAndFlags<WinType>& src )
{
if( !pxAssert( target != NULL ) ) return;
target.Add( src.window, src.flags );
}
// ----------------------------------------------------------------------------
@@ -230,19 +303,29 @@ protected:
public:
wxDialogWithHelpers();
wxDialogWithHelpers(wxWindow* parent, int id, const wxString& title, bool hasContextHelp, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize );
wxDialogWithHelpers(wxWindow* parent, const wxString& title, bool hasContextHelp=false, bool resizable=false );
wxDialogWithHelpers(wxWindow* parent, const wxString& title, wxOrientation orient);
virtual ~wxDialogWithHelpers() throw();
void AddOkCancel( wxSizer& sizer, bool hasApply=false );
pxStaticText* Text( const wxString& label );
pxStaticHeading* Heading( const wxString& label );
void Init();
void AddOkCancel( wxSizer& sizer, bool hasApply=false );
virtual void SmartCenterFit();
virtual int ShowModal();
virtual bool Show( bool show=true );
virtual pxStaticText* Text( const wxString& label );
virtual pxStaticHeading* Heading( const wxString& label );
virtual wxDialogWithHelpers& SetIdealWidth( int newWidth ) { m_idealWidth = newWidth; return *this; }
wxDialogWithHelpers& SetIdealWidth( int newWidth ) { m_idealWidth = newWidth; return *this; }
int GetIdealWidth() const { return m_idealWidth; }
bool HasIdealWidth() const { return m_idealWidth != wxDefaultCoord; }
protected:
void OnActivate(wxActivateEvent& evt);
void OnOkCancel(wxCommandEvent& evt);
void OnCloseWindow(wxCloseEvent& event);
};
// --------------------------------------------------------------------------------------
@@ -412,7 +495,7 @@ public:
//////////////////////////////////////////////////////////////////////////////////////////////
extern bool pxDialogExists( wxWindowID id );
extern bool pxDialogExists( const wxString& name );
extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos );
extern wxRect wxGetDisplayArea();
@@ -420,5 +503,7 @@ extern wxString pxFormatToolTipText( wxWindow* wind, const wxString& src );
extern void pxSetToolTip( wxWindow* wind, const wxString& src );
extern void pxSetToolTip( wxWindow& wind, const wxString& src );
extern wxFont pxGetFixedFont( int ptsize=8, int weight=wxNORMAL );
#endif
+1 -1
View File
@@ -40,7 +40,7 @@ struct x86CPU_INFO
u32 PhysicalCores;
u32 LogicalCores;
char VendorName[16]; // Vendor/Creator ID
char VendorName[16]; // Vendor/Creator ID
char TypeName[20]; // cpu type
char FamilyName[50]; // the original cpu name
+51 -20
View File
@@ -16,6 +16,7 @@
#include "PrecompiledHeader.h"
#include <wx/app.h>
#include "Threading.h"
wxString GetEnglish( const char* msg )
{
@@ -42,36 +43,66 @@ wxString GetTranslation( const char* msg )
// That's ok. What we don't want is the *same* thread recurse-asserting.
static __threadlocal int s_assert_guard = 0;
DEVASSERT_INLINE void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const wxChar* msg)
{
#ifdef PCSX2_DEVBUILD
RecursionGuard guard( s_assert_guard );
if( guard.IsReentrant() ) return;
pxDoAssertFnType* pxDoAssert = pxAssertImpl_LogIt;
if( wxTheApp == NULL )
// make life easier for people using VC++ IDE by using this format, which allows double-click
// response times from the Output window...
wxString DiagnosticOrigin::ToString( const wxChar* msg ) const
{
wxString message;
message.reserve( 2048 );
message.Printf( L"%s(%d) : assertion failed:\n", srcfile, line );
if( function != NULL )
message += L" Function: " + fromUTF8(function) + L"\n";
message += L" Thread: " + Threading::pxGetCurrentThreadName() + L"\n";
if( condition != NULL )
message += L" Condition: " + wxString(condition) + L"\n";
if( msg != NULL )
message += L" Message: " + wxString(msg) + L"\n";
return message;
}
bool pxAssertImpl_LogIt( const DiagnosticOrigin& origin, const wxChar *msg )
{
wxLogError( origin.ToString( msg ) );
return false;
}
DEVASSERT_INLINE void pxOnAssert( const DiagnosticOrigin& origin, const wxChar* msg )
{
RecursionGuard guard( s_assert_guard );
if( guard.IsReentrant() ) { return wxTrap(); }
// wxWidgets doesn't come with debug builds on some Linux distros, and other distros make
// it difficult to use the debug build (compilation failures). To handle these I've had to
// bypass the internal wxWidgets assertion handler entirely, since it may not exist even if
// PCSX2 itself is compiled in debug mode (assertions enabled).
bool trapit;
if( pxDoAssert == NULL )
{
// Note: Format uses MSVC's syntax for output window hotlinking.
wxLogError( wxsFormat( L"%s(%d): Assertion failed in %s: %s\n",
file, line, fromUTF8(func).c_str(), msg )
);
trapit = pxAssertImpl_LogIt( origin, msg );
}
else
{
#ifdef __WXDEBUG__
wxTheApp->OnAssertFailure( file, line, fromUTF8(func), cond, msg );
#elif wxUSE_GUI
// FIXME: this should create a popup dialog for devel builds.
wxLogError( msg );
#else
wxLogError( msg );
#endif
trapit = pxDoAssert( origin, msg );
}
#endif
if( trapit ) { wxTrap(); }
}
__forceinline void pxOnAssert( const wxChar* file, int line, const char* func, const wxChar* cond, const char* msg)
__forceinline void pxOnAssert( const DiagnosticOrigin& origin, const char* msg)
{
pxOnAssert( file, line, func, cond, fromUTF8(msg) );
pxOnAssert( origin, fromUTF8(msg) );
}
+172 -54
View File
@@ -37,6 +37,61 @@ const wxTimeSpan Threading::def_yieldgui_interval( 0, 0, 0, 100 );
// three second interval for deadlock protection on waitgui.
const wxTimeSpan Threading::def_deadlock_timeout( 0, 0, 3, 0 );
//static __threadlocal PersistentThread* tls_current_thread = NULL;
static pthread_key_t curthread_key = NULL;
static s32 total_key_count = 0;
static Mutex total_key_lock;
static void make_curthread_key()
{
ScopedLock lock( total_key_lock );
if( total_key_count++ != 0 ) return;
if( 0 != pthread_key_create(&curthread_key, NULL) )
{
Console.Error( "Thread key creation failed (probably out of memory >_<)" );
curthread_key = NULL;
}
}
static void unmake_curthread_key()
{
ScopedLock lock( total_key_lock );
if( --total_key_count > 0 ) return;
if( curthread_key != NULL )
pthread_key_delete( curthread_key );
curthread_key = NULL;
}
// Returns a handle to the current persistent thread. If the current thread does not belong
// to the PersistentThread table, NULL is returned. Since the main/ui thread is not created
// through PersistentThread it will also return NULL. Callers can use wxThread::IsMain() to
// test if the NULL thread is the main thread.
PersistentThread* Threading::pxGetCurrentThread()
{
return (curthread_key==NULL) ? NULL : (PersistentThread*)pthread_getspecific( curthread_key );
}
// returns the name of the current thread, or "Unknown" if the thread is neither a PersistentThread
// nor the Main/UI thread.
wxString Threading::pxGetCurrentThreadName()
{
if( PersistentThread* thr = pxGetCurrentThread() )
{
return thr->GetName();
}
else if( wxThread::IsMain() )
{
return L"Main/UI";
}
return L"Unknown";
}
// (intended for internal use only)
// Returns true if the Wait is recursive, or false if the Wait is safe and should be
// handled via normal yielding methods.
@@ -81,7 +136,7 @@ Threading::PersistentThread::PersistentThread()
// This destructor performs basic "last chance" cleanup, which is a blocking join
// against the thread. Extending classes should almost always implement their own
// thread closure process, since any PersistentThread will, by design, not terminate
// unless it has been properly canceled.
// unless it has been properly canceled (resulting in deadlock).
//
// Thread safety: This class must not be deleted from its own thread. That would be
// like marrying your sister, and then cheating on her with your daughter.
@@ -116,14 +171,24 @@ Threading::PersistentThread::~PersistentThread() throw()
DESTRUCTOR_CATCHALL
}
bool Threading::PersistentThread::AffinityAssert_AllowFromSelf() const
bool Threading::PersistentThread::AffinityAssert_AllowFromSelf( const DiagnosticOrigin& origin ) const
{
return pxAssertMsg( IsSelf(), wxsFormat( L"Thread affinity violation: Call allowed from '%s' thread only.", m_name.c_str() ) );
if( IsSelf() ) return true;
if( IsDevBuild )
pxOnAssert( origin, wxsFormat( L"Thread affinity violation: Call allowed from '%s' thread only.", m_name.c_str() ) );
return false;
}
bool Threading::PersistentThread::AffinityAssert_DisallowFromSelf() const
bool Threading::PersistentThread::AffinityAssert_DisallowFromSelf( const DiagnosticOrigin& origin ) const
{
return pxAssertMsg( !IsSelf(), wxsFormat( L"Thread affinity violation: Call is *not* allowed from '%s' thread.", m_name.c_str() ) );
if( !IsSelf() ) return true;
if( IsDevBuild )
pxOnAssert( origin, wxsFormat( L"Thread affinity violation: Call is *not* allowed from '%s' thread.", m_name.c_str() ) );
return false;
}
void Threading::PersistentThread::FrankenMutex( Mutex& mutex )
@@ -157,7 +222,29 @@ void Threading::PersistentThread::Start()
m_except = NULL;
if( pthread_create( &m_thread, NULL, _internal_callback, this ) != 0 )
throw Exception::ThreadCreationError();
throw Exception::ThreadCreationError( this );
if( !m_sem_startup.WaitWithoutYield( wxTimeSpan( 0, 0, 3, 0 ) ) )
{
RethrowException();
// And if the thread threw nothing of its own:
throw Exception::ThreadCreationError( this, "(%s thread) Start error: created thread never posted startup semaphore." );
}
// Event Rationale (above): Performing this semaphore wait on the created thread is "slow" in the
// sense that it stalls the calling thread completely until the new thread is created
// (which may not always be desirable). But too bad. In order to safely use 'running' locks
// and detachment management, this *has* to be done. By rule, starting new threads shouldn't
// be done very often anyway, hence the concept of Threadpooling for rapidly rotating tasks.
// (and indeed, this semaphore wait might, in fact, be very swift compared to other kernel
// overhead in starting threads).
// (this could also be done using operating system specific calls, since any threaded OS has
// functions that allow us to see if a thread is running or not, and to block against it even if
// it's been detached -- removing the need for m_lock_InThread and the semaphore wait above. But
// pthreads kinda lacks that stuff, since pthread_join() has no timeout option making it im-
// possible to safely block against a running thread)
}
// Returns: TRUE if the detachment was performed, or FALSE if the thread was
@@ -165,13 +252,28 @@ void Threading::PersistentThread::Start()
// This function should not be called from the owner thread.
bool Threading::PersistentThread::Detach()
{
AffinityAssert_DisallowFromSelf();
AffinityAssert_DisallowFromSelf(pxDiagSpot);
if( _InterlockedExchange( &m_detached, true ) ) return false;
pthread_detach( m_thread );
return true;
}
bool Threading::PersistentThread::_basecancel()
{
// Prevent simultaneous startup and cancel:
if( !m_running ) return false;
if( m_detached )
{
Console.Warning( "(Thread Warning) Ignoring attempted cancellation of detached thread." );
return false;
}
pthread_cancel( m_thread );
return true;
}
// Remarks:
// Provision of non-blocking Cancel() is probably academic, since destroying a PersistentThread
// object performs a blocking Cancel regardless of if you explicitly do a non-blocking Cancel()
@@ -183,33 +285,40 @@ bool Threading::PersistentThread::Detach()
// Parameters:
// isBlocking - indicates if the Cancel action should block for thread completion or not.
//
// Exceptions raised by the blocking thread will be re-thrown into the main thread. If isBlocking
// is false then no exceptions will occur.
//
void Threading::PersistentThread::Cancel( bool isBlocking )
{
AffinityAssert_DisallowFromSelf();
AffinityAssert_DisallowFromSelf( pxDiagSpot );
{
// Prevent simultaneous startup and cancel:
ScopedLock startlock( m_lock_start );
if( !m_running ) return;
// Prevent simultaneous startup and cancel, necessary to avoid
ScopedLock startlock( m_lock_start );
if( m_detached )
{
Console.Warning( "(Thread Warning) Ignoring attempted cancellation of detached thread." );
return;
}
pthread_cancel( m_thread );
}
if( !_basecancel() ) return;
if( isBlocking )
{
// FIXME: Add deadlock detection and handling here... ?
m_lock_InThread.Wait();
WaitOnSelf( m_lock_InThread );
Detach();
}
}
bool Threading::PersistentThread::Cancel( const wxTimeSpan& timespan )
{
AffinityAssert_DisallowFromSelf( pxDiagSpot );
// Prevent simultaneous startup and cancel:
ScopedLock startlock( m_lock_start );
if( !_basecancel() ) return true;
if( !WaitOnSelf( m_lock_InThread, timespan ) ) return false;
Detach();
return true;
}
// Blocks execution of the calling thread until this thread completes its task. The
// caller should make sure to signal the thread to exit, or else blocking may deadlock the
// calling thread. Classes which extend PersistentThread should override this method
@@ -218,10 +327,12 @@ void Threading::PersistentThread::Cancel( bool isBlocking )
// Returns the return code of the thread.
// This method is roughly the equivalent of pthread_join().
//
// Exceptions raised by the blocking thread will be re-thrown into the main thread.
//
void Threading::PersistentThread::Block()
{
AffinityAssert_DisallowFromSelf();
m_lock_InThread.Wait();
AffinityAssert_DisallowFromSelf(pxDiagSpot);
WaitOnSelf( m_lock_InThread );
}
bool Threading::PersistentThread::IsSelf() const
@@ -277,7 +388,7 @@ void Threading::PersistentThread::_selfRunningTest( const wxChar* name ) const
//
void Threading::PersistentThread::WaitOnSelf( Semaphore& sem ) const
{
if( !AffinityAssert_DisallowFromSelf() ) return;
if( !AffinityAssert_DisallowFromSelf(pxDiagSpot) ) return;
while( true )
{
@@ -301,7 +412,7 @@ void Threading::PersistentThread::WaitOnSelf( Semaphore& sem ) const
//
void Threading::PersistentThread::WaitOnSelf( Mutex& mutex ) const
{
if( !AffinityAssert_DisallowFromSelf() ) return;
if( !AffinityAssert_DisallowFromSelf(pxDiagSpot) ) return;
while( true )
{
@@ -314,7 +425,7 @@ static const wxTimeSpan SelfWaitInterval( 0,0,0,333 );
bool Threading::PersistentThread::WaitOnSelf( Semaphore& sem, const wxTimeSpan& timeout ) const
{
if( !AffinityAssert_DisallowFromSelf() ) return true;
if( !AffinityAssert_DisallowFromSelf(pxDiagSpot) ) return true;
wxTimeSpan runningout( timeout );
@@ -330,7 +441,7 @@ bool Threading::PersistentThread::WaitOnSelf( Semaphore& sem, const wxTimeSpan&
bool Threading::PersistentThread::WaitOnSelf( Mutex& mutex, const wxTimeSpan& timeout ) const
{
if( !AffinityAssert_DisallowFromSelf() ) return true;
if( !AffinityAssert_DisallowFromSelf(pxDiagSpot) ) return true;
wxTimeSpan runningout( timeout );
@@ -350,7 +461,7 @@ bool Threading::PersistentThread::WaitOnSelf( Mutex& mutex, const wxTimeSpan& ti
// and cleanup, or use the DoThreadCleanup() override to perform resource cleanup).
void Threading::PersistentThread::TestCancel() const
{
AffinityAssert_AllowFromSelf();
AffinityAssert_AllowFromSelf(pxDiagSpot);
pthread_testcancel();
}
@@ -393,24 +504,16 @@ void Threading::PersistentThread::_try_virtual_invoke( void (PersistentThread::*
}
#ifndef PCSX2_DEVBUILD
// ----------------------------------------------------------------------------
// Allow logic errors to propagate out of the thread in release builds, so that they might be
// handled in non-fatal ways. On Devbuilds let them loose, so that they produce debug stack
// traces and such.
catch( std::logic_error& ex )
// Bleh... don't bother with std::exception. runtime_error should catch anything
// useful coming out of the core STL libraries anyway, and these are best handled by
// the MSVC debugger (or by silent random annoying fail on debug-less linux).
/*catch( std::logic_error& ex )
{
throw Exception::LogicError( wxsFormat( L"(thread: %s) STL Logic Error: %s\n\t%s",
throw Exception::BaseException( wxsFormat( L"(thread: %s) STL Logic Error: %s\n\t%s",
GetName().c_str(), fromUTF8( ex.what() ).c_str() )
);
}
catch( Exception::LogicError& ex )
{
m_except = ex.Clone();
m_except->DiagMsg() = wxsFormat( L"(thread:%s) ", GetName().c_str() ) + m_except->DiagMsg();
}
// ----------------------------------------------------------------------------
// Bleh... don't bother with std::exception. std::logic_error and runtime_error should catch
// anything coming out of the core STL libraries anyway.
/*catch( std::exception& ex )
catch( std::exception& ex )
{
throw Exception::BaseException( wxsFormat( L"(thread: %s) STL exception: %s\n\t%s",
GetName().c_str(), fromUTF8( ex.what() ).c_str() )
@@ -431,7 +534,7 @@ void Threading::PersistentThread::_try_virtual_invoke( void (PersistentThread::*
// OnCleanupInThread() to extend cleanup functionality.
void Threading::PersistentThread::_ThreadCleanup()
{
AffinityAssert_AllowFromSelf();
AffinityAssert_AllowFromSelf(pxDiagSpot);
_try_virtual_invoke( &PersistentThread::OnCleanupInThread );
m_lock_InThread.Release();
}
@@ -442,42 +545,59 @@ wxString Threading::PersistentThread::GetName() const
}
// This override is called by PeristentThread when the thread is first created, prior to
// calling ExecuteTaskInThread. This is useful primarily for "base" classes that extend
// from PersistentThread, giving them the ability to bind startup code to all threads that
// derive from them. (the alternative would have been to make ExecuteTaskInThread a
// private member, and provide a new Task executor by a different name).
// calling ExecuteTaskInThread, and after the initial InThread lock has been claimed.
// This code is also executed within a "safe" environment, where the creating thread is
// blocked against m_sem_event. Make sure to do any necessary variable setup here, without
// worry that the calling thread might attempt to test the status of those variables
// before initialization has completed.
//
void Threading::PersistentThread::OnStartInThread()
{
m_running = true;
m_detached = false;
m_running = true;
}
void Threading::PersistentThread::_internal_execute()
{
m_lock_InThread.Acquire();
OnStartInThread();
_DoSetThreadName( m_name );
make_curthread_key();
if( curthread_key != NULL )
pthread_setspecific( curthread_key, this );
OnStartInThread();
m_sem_startup.Post();
_try_virtual_invoke( &PersistentThread::ExecuteTaskInThread );
}
// Called by Start, prior to actual starting of the thread, and after any previous
// running thread has been canceled or detached.
void Threading::PersistentThread::OnStart()
{
FrankenMutex( m_lock_InThread );
m_sem_event.Reset();
m_sem_startup.Reset();
}
// Extending classes that override this method shoul always call it last from their
// personal implementations.
void Threading::PersistentThread::OnCleanupInThread()
{
m_running = false;
if( curthread_key != NULL )
pthread_setspecific( curthread_key, NULL );
unmake_curthread_key();
}
// passed into pthread_create, and is used to dispatch the thread's object oriented
// callback function
void* Threading::PersistentThread::_internal_callback( void* itsme )
{
pxAssert( itsme != NULL );
if( !pxAssertDev( itsme != NULL, wxNullChar ) ) return NULL;
PersistentThread& owner = *((PersistentThread*)itsme);
pthread_cleanup_push( _pt_callback_cleanup, itsme );
@@ -493,8 +613,6 @@ void Threading::PersistentThread::_DoSetThreadName( const wxString& name )
void Threading::PersistentThread::_DoSetThreadName( const char* name )
{
if( !AffinityAssert_AllowFromSelf() ) return;
// This feature needs Windows headers and MSVC's SEH support:
#if defined(_WINDOWS_) && defined (_MSC_VER)
+5
View File
@@ -81,3 +81,8 @@ void operator+=( wxSizer& target, pxCheckBox& src )
{
target.Add( &src, wxSF.Expand() );
}
void operator+=( wxSizer* target, pxCheckBox& src )
{
target->Add( &src, wxSF.Expand() );
}
+16 -2
View File
@@ -149,13 +149,13 @@ void pxRadioPanel::_RealizeDefaultOption()
}
}
pxRadioPanel& pxRadioPanel::SetDefault( int idx )
pxRadioPanel& pxRadioPanel::SetDefaultItem( int idx )
{
if( idx == m_DefaultIdx ) return *this;
if( m_IsRealized && m_DefaultIdx != -1 )
{
wxFont def( GetFont() );
wxFont def(GetFont());
m_objects[m_DefaultIdx].LabelObj->SetFont( def );
m_objects[m_DefaultIdx].LabelObj->SetForegroundColour( GetForegroundColour() );
}
@@ -166,6 +166,20 @@ pxRadioPanel& pxRadioPanel::SetDefault( int idx )
return *this;
}
pxRadioPanel& pxRadioPanel::EnableItem( int idx, bool enable )
{
pxAssertDev( m_IsRealized, "RadioPanel must be realized first, prior to enabling or disabling individual items." );
if( m_objects[idx].LabelObj )
m_objects[idx].LabelObj->Enable( enable );
if( m_objects[idx].SubTextObj )
m_objects[idx].SubTextObj->Enable( enable );
return *this;
}
int pxRadioPanel::GetSelection() const
{
if( !VerifyRealizedState() ) return 0;
+5
View File
@@ -131,3 +131,8 @@ void operator+=( wxSizer& target, pxStaticText& src )
{
src.AddTo( target );
}
void operator+=( wxSizer* target, pxStaticText& src )
{
src.AddTo( target );
}
+36 -6
View File
@@ -99,7 +99,12 @@ wxSizerFlags pxStretchType::Apply( wxSizerFlags flags ) const
return flags;
}
wxSizerFlags operator , ( const wxSizerFlags& _flgs, const wxSizerFlags& _flgs2 )
wxSizerFlags pxProportion::Apply( wxSizerFlags flags ) const
{
return flags.Proportion( intval );
}
wxSizerFlags operator& ( const wxSizerFlags& _flgs, const wxSizerFlags& _flgs2 )
{
//return align.Apply( _flgs );
wxSizerFlags retval;
@@ -118,11 +123,8 @@ wxSizerFlags operator , ( const wxSizerFlags& _flgs, const wxSizerFlags& _flgs2
return retval;
}
/*wxSizerFlags operator | ( const wxSizerFlags& _flgs, pxStretchType stretch )
{
return stretch.Apply( _flgs );
}*/
// ----------------------------------------------------------------------------
// Reference/Handle versions!
void operator+=( wxSizer& target, wxWindow* src )
{
@@ -148,6 +150,23 @@ void operator+=( wxSizer& target, int spacer )
{
target.AddSpacer( spacer );
}
// ----------------------------------------------------------------------------
// Pointer versions! (note that C++ requires one of the two operator params be a
// "poper" object type (non-pointer), so that's why there's only a couple of these.
void operator+=( wxSizer* target, wxWindow& src )
{
if( !pxAssert( target != NULL ) ) return;
target->Add( &src );
}
void operator+=( wxSizer* target, wxSizer& src )
{
if( !pxAssert( target != NULL ) ) return;
target->Add( &src );
}
// ----------------------------------------------------------------------------
void operator+=( wxWindow& target, int spacer )
{
@@ -431,3 +450,14 @@ void pxSetToolTip( wxWindow& wind, const wxString& src )
{
pxSetToolTip( &wind, src );
}
wxFont pxGetFixedFont( int ptsize, int weight )
{
return wxFont(
ptsize, wxMODERN, wxNORMAL, weight, false,
#ifdef __WXMSW__
L"Lucida Console" // better than courier new (win32 only)
#endif
);
}
+86 -16
View File
@@ -28,13 +28,9 @@ using namespace pxSizerFlags;
// wxDialogWithHelpers Class Implementations
// =====================================================================================================
HashTools::HashMap< wxWindowID, int > m_DialogIdents( 0, wxID_ANY );
bool pxDialogExists( wxWindowID id )
bool pxDialogExists( const wxString& name )
{
int dest = 0;
m_DialogIdents.TryGetValue( id, dest );
return (dest > 0);
return wxFindWindowByName( name ) != NULL;
}
// --------------------------------------------------------------------------------------
@@ -44,20 +40,41 @@ IMPLEMENT_DYNAMIC_CLASS(wxDialogWithHelpers, wxDialog)
wxDialogWithHelpers::wxDialogWithHelpers()
{
m_idealWidth = wxDefaultCoord;
m_hasContextHelp = false;
m_extraButtonSizer = NULL;
Init();
}
wxDialogWithHelpers::wxDialogWithHelpers( wxWindow* parent, int id, const wxString& title, bool hasContextHelp, const wxPoint& pos, const wxSize& size )
: wxDialog( parent, id, title, pos, size , wxDEFAULT_DIALOG_STYLE) //, (wxCAPTION | wxMAXIMIZE | wxCLOSE_BOX | wxRESIZE_BORDER) ), // flags for resizable dialogs, currently unused.
wxDialogWithHelpers::wxDialogWithHelpers( wxWindow* parent, const wxString& title, bool hasContextHelp, bool resizable )
: wxDialog( parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | (resizable ? wxRESIZE_BORDER : 0)
)
{
++m_DialogIdents[GetId()];
m_hasContextHelp = hasContextHelp;
Init();
}
wxDialogWithHelpers::wxDialogWithHelpers(wxWindow* parent, const wxString& title, wxOrientation orient)
: wxDialog( parent, wxID_ANY, title )
{
m_hasContextHelp = false;
SetSizer( new wxBoxSizer( orient ) );
Init();
m_idealWidth = 500;
*this += StdPadding;
}
wxDialogWithHelpers::~wxDialogWithHelpers() throw()
{
}
void wxDialogWithHelpers::Init()
{
m_idealWidth = wxDefaultCoord;
m_extraButtonSizer = NULL;
m_hasContextHelp = hasContextHelp;
if( m_hasContextHelp )
delete wxHelpProvider::Set( new wxSimpleHelpProvider() );
@@ -65,14 +82,54 @@ wxDialogWithHelpers::wxDialogWithHelpers( wxWindow* parent, int id, const wxStr
// indicate that it should, so I presume the problem is in wxWidgets and that (hopefully!)
// an updated version will fix it later. I tried to fix it using a manual Connect but it
// didn't do any good. (problem could also be my Co-Linux / x-window manager)
//Connect( wxEVT_ACTIVATE, wxActivateEventHandler(wxDialogWithHelpers::OnActivate) );
Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (wxDialogWithHelpers::OnOkCancel) );
Connect( wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (wxDialogWithHelpers::OnOkCancel) );
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler (wxDialogWithHelpers::OnCloseWindow) );
}
wxDialogWithHelpers::~wxDialogWithHelpers() throw()
void wxDialogWithHelpers::SmartCenterFit()
{
--m_DialogIdents[GetId()];
pxAssert( m_DialogIdents[GetId()] >= 0 );
Fit();
// Smart positioning logic! If our parent window is larger than our window by some
// good amount, then we center on that. If not, center relative to the screen. This
// avoids the popup automatically eclipsing the parent window (which happens in PCSX2
// a lot since the main window is small).
bool centerfail = true;
if( wxWindow* parent = GetParent() )
{
const wxSize parentSize( parent->GetSize() );
if( (parentSize.x > ((int)GetSize().x * 1.75)) && (parentSize.y > ((int)GetSize().y * 1.75)) )
{
CenterOnParent();
centerfail = false;
}
}
if( centerfail ) CenterOnScreen();
}
// Overrides wxDialog behavior to include automatic Fit() and CenterOnParent/Screen. The centering
// is based on a heuristic the centers against the parent window if the parent window is at least
// 75% larger than the fitted dialog.
int wxDialogWithHelpers::ShowModal()
{
SmartCenterFit();
return wxDialog::ShowModal();
}
// Overrides wxDialog behavior to include automatic Fit() and CenterOnParent/Screen. The centering
// is based on a heuristic the centers against the parent window if the parent window is at least
// 75% larger than the fitted dialog.
bool wxDialogWithHelpers::Show( bool show )
{
if( show ) SmartCenterFit();
return wxDialog::Show( show );
}
pxStaticText* wxDialogWithHelpers::Text( const wxString& label )
@@ -85,6 +142,19 @@ pxStaticHeading* wxDialogWithHelpers::Heading( const wxString& label )
return new pxStaticHeading( this, label );
}
void wxDialogWithHelpers::OnCloseWindow( wxCloseEvent& evt )
{
if( !IsModal() ) Destroy();
evt.Skip();
}
void wxDialogWithHelpers::OnOkCancel( wxCommandEvent& evt )
{
Close();
evt.Skip();
}
void wxDialogWithHelpers::OnActivate(wxActivateEvent& evt)
{
//evt.Skip();
@@ -119,7 +189,7 @@ void wxDialogWithHelpers::AddOkCancel( wxSizer &sizer, bool hasApply )
flex.AddGrowableCol( 1, 15 );
flex += m_extraButtonSizer | pxAlignLeft;
flex += s_buttons | pxExpand, pxCenter;
flex += s_buttons | (pxExpand & pxCenter);
sizer += flex | StdExpand();
+2 -2
View File
@@ -592,7 +592,7 @@ $memcpy_final:
// (zerofrog)
u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize)
{
assert( (cmpsize&7) == 0 );
pxAssert( (cmpsize&7) == 0 );
__asm {
push esi
@@ -766,7 +766,7 @@ End:
// returns the xor of all elements, cmpsize has to be mult of 8
void memxor_mmx(void* dst, const void* src1, int cmpsize)
{
assert( (cmpsize&7) == 0 );
pxAssert( (cmpsize&7) == 0 );
__asm {
mov ecx, cmpsize
+1 -1
View File
@@ -745,7 +745,7 @@ __forceinline void cdvdReadInterrupt()
// An arbitrary delay of some number of cycles probably makes more sense here,
// but for now it's based on the cdvd.ReadTime value. -- air
assert((int)cdvd.ReadTime > 0 );
pxAssume((int)cdvd.ReadTime > 0 );
CDVDREAD_INT(cdvd.ReadTime/4);
return;
}
+1 -1
View File
@@ -340,7 +340,7 @@ static __forceinline void frameLimit()
static __forceinline void VSyncStart(u32 sCycle)
{
Cpu->CheckExecutionState();
SysCoreThread::Get().VsyncInThread();
GetCoreThread().VsyncInThread();
EECNT_LOG( "///////// EE COUNTER VSYNC START (frame: %6d) \\\\\\\\\\\\\\\\\\\\ ", iFrame );
+6 -5
View File
@@ -382,15 +382,16 @@ static void intExecute()
// Mem protection should be handled by the caller here so that it can be
// done in a more optimized fashion.
while( true )
{
execI();
}
try {
while( true )
execI();
} catch( Exception::ForceDispatcherReg& ) { }
}
static void intCheckExecutionState()
{
SysCoreThread::Get().StateCheckInThread();
if( GetCoreThread().HasPendingStateChangeRequest() )
throw Exception::ForceDispatcherReg();
}
static void intStep()

Some files were not shown because too many files have changed in this diff Show More