From c17455c702da41746ef0181bfa8ad316813fce2e Mon Sep 17 00:00:00 2001
From: "Jake.Stine" <Jake.Stine@96395faa-99c1-11dd-bbfe-3dabce05a288>
Date: Mon, 14 Dec 2009 12:18:55 +0000
Subject: [PATCH] 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
---
 common/include/Pcsx2Defs.h                 |  11 +-
 common/include/Utilities/Assertions.h      | 150 +++++++---
 common/include/Utilities/Exceptions.h      |  36 +--
 common/include/Utilities/Threading.h       |  14 +-
 common/include/Utilities/pxCheckBox.h      |   7 +
 common/include/Utilities/pxRadioPanel.h    |   3 +-
 common/include/Utilities/pxStaticText.h    |   8 +
 common/include/Utilities/wxGuiTools.h      | 119 ++++++--
 common/include/x86emitter/tools.h          |   2 +-
 common/src/Utilities/Exceptions.cpp        |  71 +++--
 common/src/Utilities/ThreadTools.cpp       | 226 ++++++++++----
 common/src/Utilities/pxCheckBox.cpp        |   5 +
 common/src/Utilities/pxRadioPanel.cpp      |  18 +-
 common/src/Utilities/pxStaticText.cpp      |   5 +
 common/src/Utilities/wxGuiTools.cpp        |  42 ++-
 common/src/Utilities/wxHelpers.cpp         | 102 ++++++-
 common/src/Utilities/x86/MemcpyFast.cpp    |   4 +-
 pcsx2/CDVD/CDVD.cpp                        |   2 +-
 pcsx2/Counters.cpp                         |   2 +-
 pcsx2/Interpreter.cpp                      |  11 +-
 pcsx2/PluginManager.cpp                    |  10 +-
 pcsx2/R5900.cpp                            |   5 -
 pcsx2/RecoverySystem.cpp                   | 173 +++++------
 pcsx2/SaveState.h                          |   4 +-
 pcsx2/System.cpp                           |  14 +-
 pcsx2/System.h                             |   6 +-
 pcsx2/System/SysCoreThread.cpp             | 105 +++++--
 pcsx2/System/SysThreadBase.cpp             |  19 +-
 pcsx2/System/SysThreads.h                  |  20 +-
 pcsx2/VU0micro.cpp                         |   6 +-
 pcsx2/VUmicro.h                            |   7 +-
 pcsx2/Vif0Dma.cpp                          |   8 +-
 pcsx2/Vif1Dma.cpp                          |  10 +-
 pcsx2/VifDma.cpp                           |  20 +-
 pcsx2/gui/App.h                            |  19 +-
 pcsx2/gui/AppAssert.cpp                    | 153 ++++++----
 pcsx2/gui/AppConfig.cpp                    |   4 +-
 pcsx2/gui/AppConfig.h                      |   2 +-
 pcsx2/gui/AppCoreThread.cpp                |  10 +
 pcsx2/gui/AppInit.cpp                      | 124 ++++++--
 pcsx2/gui/AppMain.cpp                      | 149 +++++-----
 pcsx2/gui/ConsoleLogger.cpp                |  15 +-
 pcsx2/gui/ConsoleLogger.h                  |   2 +-
 pcsx2/gui/Dialogs/AboutBoxDialog.cpp       |  42 +--
 pcsx2/gui/Dialogs/AssertionDialog.cpp      |  67 +++++
 pcsx2/gui/Dialogs/ConfigurationDialog.cpp  |  25 +-
 pcsx2/gui/Dialogs/ConfigurationDialog.h    |  11 +-
 pcsx2/gui/Dialogs/ConfirmationDialogs.cpp  | 218 +++++++++-----
 pcsx2/gui/Dialogs/FirstTimeWizard.cpp      |  49 ++--
 pcsx2/gui/Dialogs/ImportSettingsDialog.cpp |  26 +-
 pcsx2/gui/Dialogs/LogOptionsDialog.cpp     |   6 +-
 pcsx2/gui/Dialogs/LogOptionsDialog.h       |   5 +-
 pcsx2/gui/Dialogs/ModalPopups.h            | 103 +++----
 pcsx2/gui/Dialogs/PickUserModeDialog.cpp   |   8 +-
 pcsx2/gui/FrameForGS.cpp                   |  37 ++-
 pcsx2/gui/IniInterface.cpp                 |   6 +-
 pcsx2/gui/IsoDropTarget.cpp                |  22 +-
 pcsx2/gui/MainFrame.h                      |   3 +
 pcsx2/gui/MainMenuClicks.cpp               |  34 ++-
 pcsx2/gui/MessageBoxes.cpp                 | 325 ++++++++++++++-------
 pcsx2/gui/Panels/CpuPanel.cpp              |  21 +-
 pcsx2/gui/Panels/PluginSelectorPanel.cpp   |  42 ++-
 pcsx2/gui/RecentIsoList.cpp                |   4 +-
 pcsx2/gui/i18n.cpp                         |   2 +-
 pcsx2/gui/pxLogTextCtrl.cpp                |  27 +-
 pcsx2/windows/VCprojects/pcsx2_2008.vcproj |   4 +
 pcsx2/windows/WinCompressNTFS.cpp          |   5 +-
 pcsx2/windows/WinConsolePipe.cpp           |  49 +++-
 pcsx2/x86/ix86-32/iR5900-32.cpp            | 157 +++++-----
 pcsx2/x86/microVU.cpp                      |  89 +++---
 pcsx2/x86/microVU_Misc.h                   |   4 +-
 71 files changed, 1996 insertions(+), 1118 deletions(-)
 create mode 100644 pcsx2/gui/Dialogs/AssertionDialog.cpp

diff --git a/common/include/Pcsx2Defs.h b/common/include/Pcsx2Defs.h
index d0ee44a3ff..0ea3cdcaba 100644
--- a/common/include/Pcsx2Defs.h
+++ b/common/include/Pcsx2Defs.h
@@ -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
 
diff --git a/common/include/Utilities/Assertions.h b/common/include/Utilities/Assertions.h
index bafc2b9d93..7d9c916852 100644
--- a/common/include/Utilities/Assertions.h
+++ b/common/include/Utilities/Assertions.h
@@ -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
diff --git a/common/include/Utilities/Exceptions.h b/common/include/Utilities/Exceptions.h
index bee8eac33c..df2f2fec9a 100644
--- a/common/include/Utilities/Exceptions.h
+++ b/common/include/Utilities/Exceptions.h
@@ -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:
diff --git a/common/include/Utilities/Threading.h b/common/include/Utilities/Threading.h
index d0ce327de2..d9018c7ea5 100644
--- a/common/include/Utilities/Threading.h
+++ b/common/include/Utilities/Threading.h
@@ -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 );
diff --git a/common/include/Utilities/pxCheckBox.h b/common/include/Utilities/pxCheckBox.h
index 1c22d6c43c..9fda5589d5 100644
--- a/common/include/Utilities/pxCheckBox.h
+++ b/common/include/Utilities/pxCheckBox.h
@@ -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 );
+}
diff --git a/common/include/Utilities/pxRadioPanel.h b/common/include/Utilities/pxRadioPanel.h
index d546687374..1d1a98d029 100644
--- a/common/include/Utilities/pxRadioPanel.h
+++ b/common/include/Utilities/pxRadioPanel.h
@@ -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;
diff --git a/common/include/Utilities/pxStaticText.h b/common/include/Utilities/pxStaticText.h
index df79a30b5c..aa2d6196ea 100644
--- a/common/include/Utilities/pxStaticText.h
+++ b/common/include/Utilities/pxStaticText.h
@@ -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
 // --------------------------------------------------------------------------------------
diff --git a/common/include/Utilities/wxGuiTools.h b/common/include/Utilities/wxGuiTools.h
index 7317bf8656..3b09bb2dfe 100644
--- a/common/include/Utilities/wxGuiTools.h
+++ b/common/include/Utilities/wxGuiTools.h
@@ -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
diff --git a/common/include/x86emitter/tools.h b/common/include/x86emitter/tools.h
index c9772295db..a460005100 100644
--- a/common/include/x86emitter/tools.h
+++ b/common/include/x86emitter/tools.h
@@ -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
 
diff --git a/common/src/Utilities/Exceptions.cpp b/common/src/Utilities/Exceptions.cpp
index 1fdde1c735..e838e6294b 100644
--- a/common/src/Utilities/Exceptions.cpp
+++ b/common/src/Utilities/Exceptions.cpp
@@ -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) );
 }
 
 
diff --git a/common/src/Utilities/ThreadTools.cpp b/common/src/Utilities/ThreadTools.cpp
index 8236a50db9..ef696e7624 100644
--- a/common/src/Utilities/ThreadTools.cpp
+++ b/common/src/Utilities/ThreadTools.cpp
@@ -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)
diff --git a/common/src/Utilities/pxCheckBox.cpp b/common/src/Utilities/pxCheckBox.cpp
index 4663b06788..300b752974 100644
--- a/common/src/Utilities/pxCheckBox.cpp
+++ b/common/src/Utilities/pxCheckBox.cpp
@@ -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() );
+}
diff --git a/common/src/Utilities/pxRadioPanel.cpp b/common/src/Utilities/pxRadioPanel.cpp
index 3af711786e..920e1b979c 100644
--- a/common/src/Utilities/pxRadioPanel.cpp
+++ b/common/src/Utilities/pxRadioPanel.cpp
@@ -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;
diff --git a/common/src/Utilities/pxStaticText.cpp b/common/src/Utilities/pxStaticText.cpp
index d52f1d7fd7..28ddf7e0fb 100644
--- a/common/src/Utilities/pxStaticText.cpp
+++ b/common/src/Utilities/pxStaticText.cpp
@@ -131,3 +131,8 @@ void operator+=( wxSizer& target, pxStaticText& src )
 {
 	src.AddTo( target );
 }
+
+void operator+=( wxSizer* target, pxStaticText& src )
+{
+	src.AddTo( target );
+}
diff --git a/common/src/Utilities/wxGuiTools.cpp b/common/src/Utilities/wxGuiTools.cpp
index 37e53f2ea2..4348e773bb 100644
--- a/common/src/Utilities/wxGuiTools.cpp
+++ b/common/src/Utilities/wxGuiTools.cpp
@@ -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
+	);
+}
diff --git a/common/src/Utilities/wxHelpers.cpp b/common/src/Utilities/wxHelpers.cpp
index 32d6c711ef..d97f4ee15f 100644
--- a/common/src/Utilities/wxHelpers.cpp
+++ b/common/src/Utilities/wxHelpers.cpp
@@ -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();
 
diff --git a/common/src/Utilities/x86/MemcpyFast.cpp b/common/src/Utilities/x86/MemcpyFast.cpp
index 949d735caa..c89af64980 100644
--- a/common/src/Utilities/x86/MemcpyFast.cpp
+++ b/common/src/Utilities/x86/MemcpyFast.cpp
@@ -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
diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp
index 3e8702bb00..7958d78634 100644
--- a/pcsx2/CDVD/CDVD.cpp
+++ b/pcsx2/CDVD/CDVD.cpp
@@ -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;
 	}
diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp
index 536b668835..f5cceed009 100644
--- a/pcsx2/Counters.cpp
+++ b/pcsx2/Counters.cpp
@@ -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 );
 
diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp
index d57a9a3a4b..b8c39320c4 100644
--- a/pcsx2/Interpreter.cpp
+++ b/pcsx2/Interpreter.cpp
@@ -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()
diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp
index c8de501e21..56b13c0609 100644
--- a/pcsx2/PluginManager.cpp
+++ b/pcsx2/PluginManager.cpp
@@ -680,7 +680,7 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
 		Console.WriteLn( L"Binding %s\t: %s ", tbl_PluginInfo[pid].GetShortname().c_str(), folders[pid].c_str() );
 
 		if( folders[pid].IsEmpty() )
-			throw Exception::InvalidArgument( "Empty plugin filename." );
+			throw Exception::PluginInitError( pi->id, "Empty plugin filename." );
 
 		m_info[pid].Filename = folders[pid];
 
@@ -985,6 +985,14 @@ void PluginManager::Close( PluginsEnum_t pid )
 
 void PluginManager::Close( bool closegs )
 {
+	// Spam stopper:  If all plugins are already closed, then return before writing any logs. >_<
+
+	const PluginInfo* pi = tbl_PluginInfo; do {
+		if( m_info[pi->id].IsOpened && (closegs || (pi->id != PluginId_GS)) ) break;
+	} while( ++pi, pi->shortname != NULL );
+
+	if( pi->shortname == NULL ) return;
+
 	DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." );
 
 	// Close plugins in reverse order of the initialization procedure.
diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp
index a0bc0ca8ae..9c44bed69d 100644
--- a/pcsx2/R5900.cpp
+++ b/pcsx2/R5900.cpp
@@ -39,7 +39,6 @@ R5900cpu *Cpu = NULL;
 
 bool g_ExecBiosHack = false; // set if the BIOS has already been executed
 
-static bool cpuIsInitialized = false;
 static const uint eeWaitCycles = 3072;
 
 bool eeEventTestIsActive = false;
@@ -52,10 +51,6 @@ void cpuReset()
 	if( GetMTGS().IsOpen() )
 		GetMTGS().WaitGS();		// GS better be done processing before we reset the EE, just in case.
 
-	SysClearExecutionCache();
-
-	cpuIsInitialized = true;
-
 	memReset();
 	psxMemReset();
 	vuMicroMemReset();
diff --git a/pcsx2/RecoverySystem.cpp b/pcsx2/RecoverySystem.cpp
index ce37e796b2..b79088be68 100644
--- a/pcsx2/RecoverySystem.cpp
+++ b/pcsx2/RecoverySystem.cpp
@@ -3,7 +3,7 @@
  *
  *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
  *  of the GNU Lesser General Public License as published by the Free Software Found-
- *  ation, either version 3 of the License, or (at your option) any later version.
+ *  ation, either version 3 of te License, or (at your option) any later version.
  *
  *  PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
@@ -22,8 +22,11 @@
 
 class _BaseStateThread;
 
+// Used to hold the current state backup (fullcopy of PS2 memory and plugin states).
 static SafeArray<u8> state_buffer;
 
+_BaseStateThread* current_state_thread = NULL;
+
 // Simple lock boolean for the state buffer being in use by a thread.
 static NonblockingMutex state_buffer_lock;
 
@@ -56,9 +59,22 @@ class _BaseStateThread : public PersistentThread
 protected:
 	EventListenerBinding<AppEventType> m_bind_OnExit;
 
+	bool	m_isStarted;
+
+	// Holds the pause/suspend state of the emulator when the state load/stave chain of action is started,
+	// so that the proper state can be restoed automatically on completion.
+	bool	m_resume_when_done;
+
 public:
 	virtual ~_BaseStateThread() throw()
 	{
+		if( !m_isStarted ) return;
+
+		// Assertion fails because C++ changes the 'this' pointer to the base class since
+		// derived classes have been deallocated at this point the destructor!
+
+		//pxAssumeDev( current_state_thread == this, wxCharNull );
+		current_state_thread = NULL;
 		state_buffer_lock.Release();		// just in case;
 	}
 
@@ -67,14 +83,18 @@ protected:
 		m_bind_OnExit( wxGetApp().Source_AppStatus(), EventListener<AppEventType>( this, StateThread_OnAppStatus ) )
 	{
 		Callback_FreezeFinished = onFinished;
-		m_name = L"StateThread::" + fromUTF8(name);
+		m_name					= L"StateThread::" + fromUTF8(name);
+		m_isStarted				= false;
+		m_resume_when_done		= false;
 	}
 
 	void OnStart()
 	{
 		if( !state_buffer_lock.TryAcquire() )
 			throw Exception::CancelEvent( m_name + L"request ignored: state copy buffer is already locked!" );
-			
+
+		current_state_thread = this;
+		m_isStarted = true;
 		_parent::OnStart();
 	}
 
@@ -83,6 +103,7 @@ protected:
 		wxCommandEvent evt( pxEVT_FreezeThreadFinished );
 		evt.SetClientData( this );
 		evt.SetInt( type );
+		evt.SetExtraLong( m_resume_when_done );
 		wxGetApp().AddPendingEvent( evt );
 	}
 
@@ -107,7 +128,7 @@ protected:
 	{
 		_parent::OnStart();
 		++sys_resume_lock;
-		CoreThread.Pause();
+		m_resume_when_done = CoreThread.Pause();
 	}
 
 	void ExecuteTaskInThread()
@@ -122,43 +143,6 @@ protected:
 	}
 };
 
-// --------------------------------------------------------------------------------------
-//   StateThread_Thaw
-// --------------------------------------------------------------------------------------
-class StateThread_Thaw : public _BaseStateThread
-{
-	typedef _BaseStateThread _parent;
-
-public:
-	StateThread_Thaw( FnType_OnThreadComplete* onFinished ) : _BaseStateThread( "Thaw", onFinished ) { }
-	
-protected:
-	void OnStart()
-	{
-		_parent::OnStart();
-
-		if( state_buffer.IsDisposed() )
-		{
-			state_buffer_lock.Release();
-			throw Exception::RuntimeError( "ThawState request made, but no valid state exists!" );
-		}
-
-		++sys_resume_lock;
-		CoreThread.Pause();
-	}
-
-	void ExecuteTaskInThread()
-	{
-		memLoadingState( state_buffer ).FreezeAll();
-	}
-	
-	void OnCleanupInThread()
-	{
-		SendFinishEvent( StateThreadAction_Restore );
-		_parent::OnCleanupInThread();
-	}
-};
-
 // --------------------------------------------------------------------------------------
 //   StateThread_ZipToDisk
 // --------------------------------------------------------------------------------------
@@ -171,14 +155,15 @@ protected:
 	gzFile			m_gzfp;
 
 public:
-	StateThread_ZipToDisk( FnType_OnThreadComplete* onFinished, const wxString& file ) :
-		_BaseStateThread( "ZipToDisk", onFinished )
-	,	m_filename( file )
-	,	m_gzfp( NULL )
+	StateThread_ZipToDisk( FnType_OnThreadComplete* onFinished, bool resume_done, const wxString& file )
+		: _BaseStateThread( "ZipToDisk", onFinished )
+		, m_filename( file )
 	{
+		m_gzfp				= NULL;
+		m_resume_when_done	= resume_done;
 	}
 
-	~StateThread_ZipToDisk() throw()
+	virtual ~StateThread_ZipToDisk() throw()
 	{
 		if( m_gzfp != NULL ) gzclose( m_gzfp );
 	}
@@ -232,15 +217,16 @@ protected:
 	bool			m_finished;
 	
 public:
-	StateThread_UnzipFromDisk( FnType_OnThreadComplete* onFinished, const wxString& file ) :
-		_BaseStateThread( "UnzipFromDisk", onFinished )
-	,	m_filename( file )
-	,	m_gzfp( NULL )
-	,	m_finished( false )
+	StateThread_UnzipFromDisk( FnType_OnThreadComplete* onFinished, bool resume_done, const wxString& file )
+		: _BaseStateThread( "UnzipFromDisk", onFinished )
+		, m_filename( file )
 	{
+		m_gzfp				= NULL;
+		m_finished			= false;
+		m_resume_when_done	= resume_done;
 	}
 
-	~StateThread_UnzipFromDisk() throw()
+	virtual ~StateThread_UnzipFromDisk() throw()
 	{
 		if( m_gzfp != NULL ) gzclose( m_gzfp );
 	}
@@ -297,32 +283,17 @@ void Pcsx2App::OnFreezeThreadFinished( wxCommandEvent& evt )
 	}
 	
 	if( fn_tmp != NULL ) fn_tmp( evt );
-
-	//m_evtsrc_FreezeThreadFinished.Dispatch( evt );
 }
 
-void OnFinished_Resume( const wxCommandEvent& evt )
+static void OnFinished_Resume( const wxCommandEvent& evt )
 {
-	if( evt.GetInt() == StateThreadAction_Restore )
-	{
-		// Successfully restored state, so remove the copy.  Don't remove it sooner
-		// because the thread may have failed with some exception/error.
-
-		state_buffer.Dispose();
-		SysClearExecutionCache();
-	}
-
-	CoreThread.Resume();
-}
-
-void OnFinished_Dispose( const wxCommandEvent& evt )
-{
-	state_buffer.Dispose();
+	CoreThread.RecoverState();
+	if( evt.GetExtraLong() ) CoreThread.Resume();
 }
 
 static wxString zip_dest_filename;
 
-void OnFinished_ZipToDisk( const wxCommandEvent& evt )
+static void OnFinished_ZipToDisk( const wxCommandEvent& evt )
 {
 	if( !pxAssertDev( evt.GetInt() == StateThreadAction_Create, "Unexpected StateThreadAction value, aborting save." ) ) return;
 
@@ -331,21 +302,13 @@ void OnFinished_ZipToDisk( const wxCommandEvent& evt )
 		Console.Warning( "Cannot save state to disk: empty filename specified." );
 		return;
 	}
-		
+
 	// Phase 2: Record to disk!!
-	(new StateThread_ZipToDisk( OnFinished_Dispose, zip_dest_filename ))->Start();
+	(new StateThread_ZipToDisk( NULL, !!evt.GetExtraLong(), zip_dest_filename ))->Start();
 	
 	CoreThread.Resume();
 }
 
-void OnFinished_Restore( const wxCommandEvent& evt )
-{
-	if( !pxAssertDev( evt.GetInt() == StateThreadAction_UnzipFromDisk, "Unexpected StateThreadAction value, aborting restore." ) ) return;
-
-	// Phase 2: Restore over existing VM state!!
-	(new StateThread_Thaw( OnFinished_Resume ))->Start();
-}
-
 
 // =====================================================================================================
 //  StateCopy Public Interface
@@ -362,8 +325,8 @@ void StateCopy_SaveToFile( const wxString& file )
 void StateCopy_LoadFromFile( const wxString& file )
 {
 	if( state_buffer_lock.IsLocked() ) return;
-	CoreThread.Pause();
-	(new StateThread_UnzipFromDisk( OnFinished_Restore, file ))->Start();
+	bool resume_when_done = CoreThread.Pause();
+	(new StateThread_UnzipFromDisk( OnFinished_Resume, resume_when_done, file ))->Start();
 }
 
 // Saves recovery state info to the given saveslot, or saves the active emulation state
@@ -394,13 +357,13 @@ void StateCopy_LoadFromSlot( uint slot )
 	Console.WriteLn( Color_StrongGreen, "Loading savestate from slot %d...", slot );
 	Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", file.c_str() );
 
-	CoreThread.Pause();
-	(new StateThread_UnzipFromDisk( OnFinished_Restore, file ))->Start();
+	bool resume_when_done = CoreThread.Pause();
+	(new StateThread_UnzipFromDisk( OnFinished_Resume, resume_when_done, file ))->Start();
 }
 
 bool StateCopy_IsValid()
 {
-	return !state_buffer.IsDisposed();
+return !state_buffer.IsDisposed();
 }
 
 const SafeArray<u8>* StateCopy_GetBuffer()
@@ -412,20 +375,45 @@ const SafeArray<u8>* StateCopy_GetBuffer()
 void StateCopy_FreezeToMem()
 {
 	if( state_buffer_lock.IsLocked() ) return;
-	(new StateThread_Freeze( OnFinished_Restore ))->Start();
+	(new StateThread_Freeze( OnFinished_Resume ))->Start();
 }
 
-void StateCopy_ThawFromMem()
+static void _acquire_and_block()
 {
-	if( state_buffer_lock.IsLocked() ) return;
-	new StateThread_Thaw( OnFinished_Restore );
+	if( state_buffer_lock.TryAcquire() ) return;
+
+	/*
+	// If the state buffer is locked and we're being called from the main thread then we need
+	// to cancel the current action.  This is needed because state_buffer_lock is only updated
+	// from events handled on the main thread.
+
+	if( wxThread::IsMain() )
+		throw Exception::CancelEvent( "Blocking ThawFromMem canceled due to existing state buffer lock." );
+	else*/
+	{
+		pxAssume( current_state_thread != NULL );
+		do  {
+			current_state_thread->Block();
+			wxGetApp().ProcessPendingEvents();		// Trying this for now, may or may not work due to recursive pitfalls (see above)
+		} while ( !state_buffer_lock.TryAcquire() );
+	}
 }
 
-void State_ThawFromMem_Blocking()
+void StateCopy_FreezeToMem_Blocking()
 {
-	if( !state_buffer_lock.TryAcquire() )
+	_acquire_and_block();
+
+	memSavingState( state_buffer ).FreezeAll();
+	state_buffer_lock.Release();
+}
+
+// Copies the saved state into the active VM, and automatically free's the saved state data.
+void StateCopy_ThawFromMem_Blocking()
+{
+	_acquire_and_block();
 
 	memLoadingState( state_buffer ).FreezeAll();
+	state_buffer.Dispose();
 	state_buffer_lock.Release();
 }
 
@@ -439,3 +427,4 @@ bool StateCopy_IsBusy()
 {
 	return state_buffer_lock.IsLocked();
 }
+   
\ No newline at end of file
diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h
index a2da5563db..85e27c6a9d 100644
--- a/pcsx2/SaveState.h
+++ b/pcsx2/SaveState.h
@@ -204,7 +204,9 @@ public:
 extern bool StateCopy_IsValid();
 
 extern void StateCopy_FreezeToMem();
-extern void StateCopy_ThawFromMem();
+extern void StateCopy_FreezeToMem_Blocking();
+extern void StateCopy_ThawFromMem_Blocking();
+
 extern void StateCopy_SaveToFile( const wxString& file );
 extern void StateCopy_LoadFromFile( const wxString& file );
 extern void StateCopy_SaveToSlot( uint num );
diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp
index bacb59245d..ac93877e56 100644
--- a/pcsx2/System.cpp
+++ b/pcsx2/System.cpp
@@ -57,7 +57,7 @@ TraceLogFilters& SetTraceConfig()
 
 
 // This function should be called once during program execution.
-void SysDetect()
+void SysLogMachineCaps()
 {
 	Console.WriteLn( Color_StrongGreen, "PCSX2 %d.%d.%d.r%d %s - compiled on " __DATE__, PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
 		SVN_REV, SVN_MODS ? "(modded)" : ""
@@ -66,8 +66,6 @@ void SysDetect()
 	Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion);
 	Console.Newline();
 
-	cpudetectInit();
-
 	Console.WriteLn( Color_StrongBlack, "x86-32 Init:" );
 	
 	Console.Indent().WriteLn(
@@ -149,13 +147,15 @@ CpuInitializer< CpuType >::CpuInitializer()
 	}
 	catch( Exception::RuntimeError& ex )
 	{
-		Console.Error( L"MicroVU0 Recompiler Allocation Failed:\n" + ex.FormatDiagnosticMessage() );
-		MyCpu->Shutdown();
+		Console.Error( L"CPU provider error:\n\t" + ex.FormatDiagnosticMessage() );
+		if( MyCpu )
+			MyCpu = NULL;
 	}
 	catch( std::runtime_error& ex )
 	{
-		Console.Error( L"MicroVU0 Recompiler Allocation Failed (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
-		MyCpu->Shutdown();
+		Console.Error( L"CPU provider error (STL Exception)\n\tDetails:" + fromUTF8( ex.what() ) );
+		if( MyCpu )
+			MyCpu = NULL;
 	}
 }
 
diff --git a/pcsx2/System.h b/pcsx2/System.h
index a7a3100e52..b151375433 100644
--- a/pcsx2/System.h
+++ b/pcsx2/System.h
@@ -62,7 +62,7 @@ protected:
 // implemented by the provisioning interface.
 extern SysCoreAllocations& GetSysCoreAlloc();
 
-extern void SysDetect();				// Detects cpu type and fills cpuInfo structs.
+extern void SysLogMachineCaps();				// Detects cpu type and fills cpuInfo structs.
 extern void SysClearExecutionCache();	// clears recompiled execution caches!
 
 
@@ -106,6 +106,7 @@ extern void NTFS_CompressFile( const wxString& file, bool compressStatus=true );
 //
 
 class pxMessageBoxEvent;
+class pxAssertionEvent;
 
 namespace Msgbox
 {
@@ -116,10 +117,9 @@ namespace Msgbox
 	extern bool YesNo( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=wxICON_QUESTION );
 
 	extern int  Assertion( const wxString& text, const wxString& stacktrace );
-	extern void Except( const Exception::BaseException& src );
 }
 
 BEGIN_DECLARE_EVENT_TYPES()
 	DECLARE_EVENT_TYPE( pxEVT_MSGBOX, -1 )
-	DECLARE_EVENT_TYPE( pxEVT_CallStackBox, -1 )
+	DECLARE_EVENT_TYPE( pxEVT_ASSERTION, -1 )
 END_DECLARE_EVENT_TYPES()
diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp
index dc975e0ae3..e0030cdeb4 100644
--- a/pcsx2/System/SysCoreThread.cpp
+++ b/pcsx2/System/SysCoreThread.cpp
@@ -56,6 +56,18 @@ void SysCoreThread::Cancel( bool isBlocking )
 {
 	m_CoreCancelDamnit = true;
 	_parent::Cancel();
+	ReleaseResumeLock();
+}
+
+bool SysCoreThread::Cancel( const wxTimeSpan& span )
+{
+	m_CoreCancelDamnit = true;
+	if( _parent::Cancel( span ) )
+	{
+		ReleaseResumeLock();
+		return true;
+	}
+	return false;
 }
 
 void SysCoreThread::Start()
@@ -78,21 +90,26 @@ void SysCoreThread::Start()
 void SysCoreThread::OnResumeReady()
 {
 	if( m_resetVirtualMachine )
-	{
-		cpuReset();
-		m_resetVirtualMachine	= false;
-		m_hasValidState			= false;
-	}
+		m_hasValidState = false;
 	
 	if( !m_hasValidState )
 		m_resetRecompilers = true;
 }
 
+// Tells the thread to recover from the in-memory state copy when it resumes.  (thread must be
+// resumed manually).
+void SysCoreThread::RecoverState()
+{
+	Pause();
+	m_resetVirtualMachine	= true;
+	m_hasValidState			= false;
+}
+
 void SysCoreThread::Reset()
 {
 	Suspend();
-	m_resetVirtualMachine = true;
-	m_hasValidState = false;
+	m_resetVirtualMachine	= true;
+	m_hasValidState			= false;
 }
 
 // This function *will* reset the emulator in order to allow the specified elf file to
@@ -159,7 +176,8 @@ void SysCoreThread::ApplySettings( const Pcsx2Config& src )
 
 	ScopedCoreThreadPause sys_paused;
 
-	m_resetRecompilers		= ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
+	m_resetRecompilers		= ( src.Cpu != EmuConfig.Cpu ) || ( src.Recompiler != EmuConfig.Recompiler ) ||
+							  ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
 	m_resetProfilers		= ( src.Profiler != EmuConfig.Profiler );
 	m_resetVsyncTimers		= ( src.GS != EmuConfig.GS );
 	
@@ -213,10 +231,50 @@ struct ScopedBool_ClearOnError
 	void Success() { m_success = true; }
 };
 
+void SysCoreThread::_reset_stuff_as_needed()
+{
+	if( m_resetVirtualMachine || m_resetRecompilers || m_resetProfilers )
+	{
+		SysClearExecutionCache();
+		memBindConditionalHandlers();
+		m_resetRecompilers		= false;
+		m_resetProfilers		= false;
+	}
+
+	if( m_resetVirtualMachine )
+	{
+		cpuReset();
+		m_resetVirtualMachine	= false;
+		m_resetRecompilers		= true;
+	}
+
+	if( m_resetVsyncTimers )
+	{
+		UpdateVSyncRate();
+		frameLimitReset();
+		m_resetVsyncTimers = false;
+	}
+	
+	SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR );
+}
+
 void SysCoreThread::CpuInitializeMess()
 {
 	if( m_hasValidState ) return;
 
+	if( StateCopy_IsValid() )
+	{
+		// Automatic recovery system if a state exists in memory.  This is executed here
+		// in order to ensure the plugins are in the proper (loaded/opened) state.
+
+		SysClearExecutionCache();
+		StateCopy_ThawFromMem_Blocking();
+
+		m_hasValidState			= true;
+		m_resetVirtualMachine	= false;
+		return;
+	}
+
 	_reset_stuff_as_needed();
 
 	ScopedBool_ClearOnError sbcoe( m_hasValidState );
@@ -262,24 +320,6 @@ void SysCoreThread::CpuInitializeMess()
 	sbcoe.Success();
 }
 
-void SysCoreThread::_reset_stuff_as_needed()
-{
-	if( m_resetRecompilers || m_resetProfilers )
-	{
-		SysClearExecutionCache();
-		memBindConditionalHandlers();
-		m_resetRecompilers = false;
-		m_resetProfilers = false;
-	}
-
-	if( m_resetVsyncTimers )
-	{
-		UpdateVSyncRate();
-		frameLimitReset();
-		m_resetVsyncTimers = false;
-	}
-}
-
 // Called by the VsyncInThread() if a valid keyEvent is pending and is unhandled by other
 // PS2 core plugins.
 void SysCoreThread::DispatchKeyEventToUI( const keyEvent& evt )
@@ -315,10 +355,11 @@ void SysCoreThread::StateCheckInThread()
 {
 	GetMTGS().RethrowException();
 	_parent::StateCheckInThread();
+
 	if( !m_hasValidState )
 		throw Exception::RuntimeError( "Invalid emulation state detected; Virtual machine threads have been cancelled." );
 
-	_reset_stuff_as_needed();
+	_reset_stuff_as_needed();		// kinda redundant but could catch unexpected threaded state changes...
 }
 
 void SysCoreThread::ExecuteTaskInThread()
@@ -330,9 +371,10 @@ void SysCoreThread::ExecuteTaskInThread()
 	m_mxcsr_saved.bitmask = _mm_getcsr();
 	
 	PCSX2_PAGEFAULT_PROTECT {
-		StateCheckInThread();
-		SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR );
-		Cpu->Execute();
+		do {
+			StateCheckInThread();
+			Cpu->Execute();
+		} while( true );
 	} PCSX2_PAGEFAULT_EXCEPT;
 }
 
@@ -347,8 +389,7 @@ void SysCoreThread::OnResumeInThread( bool isSuspended )
 	if( g_plugins != NULL )
 		g_plugins->Open();
 
-	if( isSuspended )
-		CpuInitializeMess();
+	CpuInitializeMess();
 }
 
 
diff --git a/pcsx2/System/SysThreadBase.cpp b/pcsx2/System/SysThreadBase.cpp
index 2e3a70db96..27497fd8f9 100644
--- a/pcsx2/System/SysThreadBase.cpp
+++ b/pcsx2/System/SysThreadBase.cpp
@@ -36,22 +36,9 @@ SysThreadBase::~SysThreadBase() throw()
 void SysThreadBase::Start()
 {
 	_parent::Start();
-	m_ExecMode = ExecMode_Closing;
 
 	Sleep( 1 );
 
-	if( !m_ResumeEvent.WaitWithoutYield( wxTimeSpan(0, 0, 1, 500) ) )
-	{
-		RethrowException();
-		if( pxAssertDev( m_ExecMode == ExecMode_Closing, "Unexpected thread status during SysThread startup." ) )
-		{
-			throw Exception::ThreadCreationError( *this,
-				L"Timeout occurred while attempting to start the '%s' thread.",
-				wxEmptyString
-			);
-		}
-	}
-
 	pxAssertDev( (m_ExecMode == ExecMode_Closing) || (m_ExecMode == ExecMode_Closed),
 		"Unexpected thread status during SysThread startup."
 	);
@@ -118,7 +105,7 @@ bool SysThreadBase::Suspend( bool isBlocking )
 			break;
 		}
 
-		pxAssertDev( m_ExecMode == ExecMode_Closing, "ExecMode should be nothing other than Closing..." );
+		pxAssumeDev( m_ExecMode == ExecMode_Closing, "ExecMode should be nothing other than Closing..." );
 		m_sem_event.Post();
 	}
 
@@ -164,7 +151,7 @@ bool SysThreadBase::Pause()
 			retval = true;
 		}
 
-		pxAssertDev( m_ExecMode == ExecMode_Pausing, "ExecMode should be nothing other than Pausing..." );
+		pxAssumeDev( m_ExecMode == ExecMode_Pausing, "ExecMode should be nothing other than Pausing..." );
 
 		m_sem_event.Post();
 	}
@@ -247,7 +234,7 @@ void SysThreadBase::OnStartInThread()
 {
 	m_RunningLock.Acquire();
 	_parent::OnStartInThread();
-	m_ResumeEvent.Post();
+	m_ExecMode = ExecMode_Closing;
 }
 
 void SysThreadBase::OnCleanupInThread()
diff --git a/pcsx2/System/SysThreads.h b/pcsx2/System/SysThreads.h
index 3cdd1947c7..1e625e82c0 100644
--- a/pcsx2/System/SysThreads.h
+++ b/pcsx2/System/SysThreads.h
@@ -20,22 +20,6 @@
 
 using namespace Threading;
 
-
-#if !PCSX2_SEH
-#	include <setjmp.h>
-
-	// Platforms without SEH need to use SetJmp / LongJmp to deal with exiting the recompiled
-	// code execution pipelines in an efficient manner, since standard C++ exceptions cannot
-	// unwind across dynamically recompiled code.
-
-	enum
-	{
-		SetJmp_Dispatcher = 1,
-		SetJmp_Exit,
-	};
-
-#endif
-
 // --------------------------------------------------------------------------------------
 //  ISysThread
 // --------------------------------------------------------------------------------------
@@ -208,8 +192,10 @@ public:
 	virtual void ApplySettings( const Pcsx2Config& src );
 	virtual void OnResumeReady();
 	virtual void Reset();
+	virtual void RecoverState();
 	virtual void Cancel( bool isBlocking=true );
-
+	virtual bool Cancel( const wxTimeSpan& timeout );
+	
 	bool HasValidState()
 	{
 		return m_hasValidState;
diff --git a/pcsx2/VU0micro.cpp b/pcsx2/VU0micro.cpp
index 5be613d9cf..189e9d18bb 100644
--- a/pcsx2/VU0micro.cpp
+++ b/pcsx2/VU0micro.cpp
@@ -65,14 +65,12 @@ void __fastcall vu0ExecMicro(u32 addr) {
 }
 
 void VU0unknown() {
-	assert(0);
-	
+	pxFailDev("Unknown VU micromode opcode called");
 	CPU_LOG("Unknown VU micromode opcode called"); 
 }  
 
 void VU0regsunknown(_VURegsNum *VUregsn) {
-	assert(0);
-	
+	pxFailDev("Unknown VU micromode opcode called");
 	CPU_LOG("Unknown VU micromode opcode called"); 
 }  
  
diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h
index ab348a895c..1a81b9f85d 100644
--- a/pcsx2/VUmicro.h
+++ b/pcsx2/VUmicro.h
@@ -39,7 +39,7 @@ public:
 	// this boolean indicates to some generic logging facilities if the VU's registers
 	// are valid for logging or not. (see DisVU1Micro.cpp, etc)  [kinda hacky, might
 	// be removed in the future]
-	bool IsInterpreter;
+	bool	IsInterpreter;
 
 public:
 	BaseCpuProvider()
@@ -105,6 +105,7 @@ public:
 
 protected:
 	BaseVUmicroCPU() {}
+	virtual ~BaseVUmicroCPU() throw() {}
 };
 
 
@@ -115,6 +116,7 @@ class InterpVU0 : public BaseVUmicroCPU
 {
 public:
 	InterpVU0();
+	virtual ~InterpVU0() throw() { Shutdown(); }
 
 	const char* GetShortName() const	{ return "intVU0"; }
 	wxString GetLongName() const		{ return L"VU0 Interpreter"; }
@@ -132,6 +134,7 @@ class InterpVU1 : public BaseVUmicroCPU
 {
 public:
 	InterpVU1();
+	virtual ~InterpVU1() throw() { Shutdown(); }
 
 	const char* GetShortName() const	{ return "intVU1"; }
 	wxString GetLongName() const		{ return L"VU1 Interpreter"; }
@@ -152,6 +155,7 @@ class recMicroVU0 : public BaseVUmicroCPU
 {
 public:
 	recMicroVU0();
+	virtual ~recMicroVU0() throw()  { Shutdown(); }
 
 	const char* GetShortName() const	{ return "mVU0"; }
 	wxString GetLongName() const		{ return L"microVU0 Recompiler"; }
@@ -169,6 +173,7 @@ class recMicroVU1 : public BaseVUmicroCPU
 {
 public:
 	recMicroVU1();
+	virtual ~recMicroVU1() throw() { Shutdown(); }
 
 	const char* GetShortName() const	{ return "mVU1"; }
 	wxString GetLongName() const		{ return L"microVU1 Recompiler"; }
diff --git a/pcsx2/Vif0Dma.cpp b/pcsx2/Vif0Dma.cpp
index 5ff8c6d029..53c5316352 100644
--- a/pcsx2/Vif0Dma.cpp
+++ b/pcsx2/Vif0Dma.cpp
@@ -130,9 +130,9 @@ static int __fastcall Vif0TransSTRow(u32 *data)  // STROW
 
 	u32* pmem = &vif0Regs->r0 + (vif0.tag.addr << 2);
 	u32* pmem2 = g_vifmask.Row0 + vif0.tag.addr;
-	pxAssert(vif0.tag.addr < 4);
+	pxAssume(vif0.tag.addr < 4);
 	ret = min(4 - vif0.tag.addr, vif0.vifpacketsize);
-	pxAssert(ret > 0);
+	pxAssume(ret > 0);
 
 	switch (ret)
 	{
@@ -752,7 +752,7 @@ void vif0Write32(u32 mem, u32 value)
 		case VIF0_R1:
 		case VIF0_R2:
 		case VIF0_R3:
-			pxAssert((mem&0xf) == 0);
+			pxAssume((mem&0xf) == 0);
 			g_vifmask.Row0[(mem>>4) & 3] = value;
 			break;
 
@@ -760,7 +760,7 @@ void vif0Write32(u32 mem, u32 value)
 		case VIF0_C1:
 		case VIF0_C2:
 		case VIF0_C3:
-			pxAssert((mem&0xf) == 0);
+			pxAssume((mem&0xf) == 0);
 			g_vifmask.Col0[(mem>>4) & 3] = value;
 			break;
 
diff --git a/pcsx2/Vif1Dma.cpp b/pcsx2/Vif1Dma.cpp
index fff6ca0405..01231ca75e 100644
--- a/pcsx2/Vif1Dma.cpp
+++ b/pcsx2/Vif1Dma.cpp
@@ -112,7 +112,7 @@ static __forceinline void vif1mpgTransfer(u32 addr, u32 *data, int size)
 			fwrite(data, 1, size*4, f);
 			fclose(f);
 		}*/
-	pxAssert(VU1.Micro > 0);
+	pxAssume(VU1.Micro > 0);
 	if (memcmp(VU1.Micro + addr, data, size << 2))
 	{
 		CpuVU1->Clear(addr, size << 2); // Clear before writing! :/
@@ -148,9 +148,9 @@ static int __fastcall Vif1TransSTRow(u32 *data)  // STROW
 
 	u32* pmem = &vif1Regs->r0 + (vif1.tag.addr << 2);
 	u32* pmem2 = g_vifmask.Row1 + vif1.tag.addr;
-	pxAssert(vif1.tag.addr < 4);
+	pxAssume(vif1.tag.addr < 4);
 	ret = min(4 - vif1.tag.addr, vif1.vifpacketsize);
-	pxAssert(ret > 0);
+	pxAssume(ret > 0);
 
 	switch (ret)
 	{
@@ -1143,7 +1143,7 @@ void vif1Write32(u32 mem, u32 value)
 		case VIF1_R1:
 		case VIF1_R2:
 		case VIF1_R3:
-			pxAssert((mem&0xf) == 0);
+			pxAssume((mem&0xf) == 0);
 			g_vifmask.Row1[(mem>>4) & 3] = value;
 			break;
 
@@ -1151,7 +1151,7 @@ void vif1Write32(u32 mem, u32 value)
 		case VIF1_C1:
 		case VIF1_C2:
 		case VIF1_C3:
-			pxAssert((mem&0xf) == 0);
+			pxAssume((mem&0xf) == 0);
 			g_vifmask.Col1[(mem>>4) & 3] = value;
 			break;
 
diff --git a/pcsx2/VifDma.cpp b/pcsx2/VifDma.cpp
index 6a941e92aa..2ed529de1a 100644
--- a/pcsx2/VifDma.cpp
+++ b/pcsx2/VifDma.cpp
@@ -283,9 +283,7 @@ template<const u32 VIFdmanum> u32 VIFalign(u32 *data, vifCode *v, u32 size)
 		vif = &vif1;
 		vifRow = g_vifmask.Row1;
 	}
-#ifdef PCSX2_DEBUG
-	pxAssert(v->addr < memsize);
-#endif
+	pxAssume(v->addr < memsize);
 
 	dest = (u32*)(VU->Mem + v->addr);
 
@@ -476,9 +474,7 @@ template<const u32 VIFdmanum> void VIFunpack(u32 *data, vifCode *v, u32 size)
 	u32 tempsize = 0;
 	const u32 memlimit = vif_size(VIFdmanum);
 
-#ifdef PCSX2_DEBUG
-	u32 memsize = memlimit;
-#endif
+	pxDebugCode( u32 memsize = memlimit );
 
 	_mm_prefetch((char*)data, _MM_HINT_NTA);
 
@@ -489,9 +485,7 @@ template<const u32 VIFdmanum> void VIFunpack(u32 *data, vifCode *v, u32 size)
 		vifMaskRegs = g_vif0Masks;
 		vif = &vif0;
 		vifRow = g_vifmask.Row0;
-#ifdef PCSX2_DEBUG
-		pxAssert(v->addr < memsize);
-#endif
+		pxDebugCode( pxAssume(v->addr < memsize) );
 	}
 	else
 	{
@@ -501,9 +495,7 @@ template<const u32 VIFdmanum> void VIFunpack(u32 *data, vifCode *v, u32 size)
 		vifMaskRegs = g_vif1Masks;
 		vif = &vif1;
 		vifRow = g_vifmask.Row1;
-#ifdef PCSX2_DEBUG
-		pxAssert(v->addr < memsize);
-#endif
+		pxDebugCode( pxAssume(v->addr < memsize) );
 	}
 
 	dest = (u32*)(VU->Mem + v->addr);
@@ -523,9 +515,7 @@ template<const u32 VIFdmanum> void VIFunpack(u32 *data, vifCode *v, u32 size)
 
 	size <<= 2;
 
-#ifdef PCSX2_DEBUG
-	memsize = size;
-#endif
+	pxDebugCode( memsize = size );
 
 	if (vifRegs->cycle.cl >= vifRegs->cycle.wl)   // skipping write
 	{
diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h
index 3261c18c31..ded5d1bbb2 100644
--- a/pcsx2/gui/App.h
+++ b/pcsx2/gui/App.h
@@ -38,7 +38,6 @@ class AppCoreThread;
 #include "System.h"
 #include "System/SysThreads.h"
 
-
 typedef void FnType_OnThreadComplete(const wxCommandEvent& evt);
 
 BEGIN_DECLARE_EVENT_TYPES()
@@ -151,14 +150,6 @@ enum MenuIdentifiers
 	MenuId_Config_ResetAll,
 };
 
-enum DialogIdentifiers
-{
-	DialogId_CoreSettings = 0x800,
-	DialogId_BiosSelector,
-	DialogId_LogOptions,
-	DialogId_About,
-};
-
 enum AppEventType
 {
 	// Maybe this will be expanded upon later..?
@@ -331,9 +322,9 @@ struct MsgboxEventResult
 	Semaphore	WaitForMe;
 	int			result;
 
-	MsgboxEventResult() :
-		WaitForMe(), result( 0 )
+	MsgboxEventResult()
 	{
+		result = 0;
 	}
 };
 
@@ -406,7 +397,7 @@ public:
 
 	void PostPadKey( wxKeyEvent& evt );
 	void PostMenuAction( MenuIdentifiers menu_id ) const;
-	int  ThreadedModalDialog( DialogIdentifiers dialogId );
+	int  IssueModalDialog( const wxString& dlgName );
 
 	bool PrepForExit( bool canCancel );
 
@@ -532,6 +523,7 @@ public:
 	virtual bool Suspend( bool isBlocking=true );
 	virtual void Resume();
 	virtual void Reset();
+	virtual void Cancel( bool isBlocking=true );
 	virtual void StateCheckInThread();
 	virtual void ApplySettings( const Pcsx2Config& src );
 	virtual void ChangeCdvdSource( CDVD_SourceType type );
@@ -610,6 +602,9 @@ public:
 	virtual ~SaveSinglePluginHelper() throw();
 };
 
+
+extern pxDoAssertFnType AppDoAssert;
+
 // --------------------------------------------------------------------------------------
 //  External App-related Globals and Shortcuts
 // --------------------------------------------------------------------------------------
diff --git a/pcsx2/gui/AppAssert.cpp b/pcsx2/gui/AppAssert.cpp
index 5597c14471..dcfb867390 100644
--- a/pcsx2/gui/AppAssert.cpp
+++ b/pcsx2/gui/AppAssert.cpp
@@ -18,18 +18,27 @@
 
 #include <wx/stackwalk.h>
 
-
-static wxString pxGetStackTrace()
+static wxString pxGetStackTrace( const FnChar_t* calledFrom )
 {
     wxString stackTrace;
 
     class StackDump : public wxStackWalker
     {
 	protected:
-		wxString m_stackTrace;
+		wxString		m_stackTrace;
+		wxString		m_srcFuncName;
+		bool			m_ignoreDone;
+		int				m_skipped;
 
     public:
-        StackDump() { }
+        StackDump( const FnChar_t* src_function_name )
+        {
+			if( src_function_name != NULL )
+				m_srcFuncName = fromUTF8(src_function_name);
+
+			m_ignoreDone	= false;
+			m_skipped		= 0;
+        }
 
         const wxString& GetStackTrace() const { return m_stackTrace; }
 
@@ -38,92 +47,108 @@ static wxString pxGetStackTrace()
         {
 			wxString name( frame.GetName() );
 			if( name.IsEmpty() )
+			{
 				name = wxsFormat( L"%p ", frame.GetAddress() );
+			}
+			/*else if( m_srcFuncName.IsEmpty() || m_srcFuncName == name )
+			{
+				// FIXME: This logic isn't reliable yet.
+				// It's possible for our debug information to not match the function names returned by
+				// __pxFUNCTION__ (might happen in linux a lot, and could happen in win32 due to
+				// inlining on Dev aserts).  The better approach is a system the queues up all the
+				// stacktrace info in individual wxStrings, and does a two-pass check -- first pass
+				// for the function name and, if not found, a second pass that just skips the first
+				// few stack entries.
+				
+				// It's important we only walk the stack once because Linux (argh, always linux!) has
+				// a really god aweful slow stack walker.
+				
+				// I'm not doing it right now because I've worked on this mess enough for one week. --air
 
-            m_stackTrace += wxString::Format( L"[%02d] %-46s ",
-				wx_truncate_cast(int, frame.GetLevel()), name.c_str()
+				m_ignoreDone = true;
+			}
+
+			if( !m_ignoreDone )
+			{
+				m_skipped++;
+				return;
+			}*/
+
+			//wxString briefName;
+			wxString essenName;
+			
+			if( frame.HasSourceLocation() )
+			{
+				wxFileName wxfn(frame.GetFileName());
+				//briefName.Printf( L"(%s:%d)", wxfn.GetFullName().c_str(), frame.GetLine() );
+
+				wxfn.SetVolume( wxEmptyString );
+				int count = wxfn.GetDirCount();
+				for( int i=0; i<2; ++i )
+					wxfn.RemoveDir(0);
+
+				essenName.Printf( L"%s:%d", wxfn.GetFullPath().c_str(), frame.GetLine() );
+			}
+
+            m_stackTrace += wxString::Format( L"[%02d] %-44s %s\n",
+				frame.GetLevel()-m_skipped,
+				name.c_str(),
+				essenName.c_str()
 			);
-
-            if ( frame.HasSourceLocation() )
-                m_stackTrace += wxsFormat( L"%s:%d", frame.GetFileName().c_str(), frame.GetLine() );
-
-            m_stackTrace += L'\n';
         }
     };
 
-	// [TODO] : Replace this with a textbox dialog setup.
-    static const int maxLines = 20;
-
-    StackDump dump;
-    dump.Walk(2, maxLines); // don't show OnAssert() call itself
-    stackTrace = dump.GetStackTrace();
-
-    const int count = stackTrace.Freq( L'\n' );
-    for ( int i = 0; i < count - maxLines; i++ )
-        stackTrace = stackTrace.BeforeLast( L'\n' );
-
-    return stackTrace;
+    StackDump dump( calledFrom );
+    dump.Walk( 3 );
+    return dump.GetStackTrace();
 }
 
-static __threadlocal bool _reentrant_lock = false;
-
 #ifdef __WXDEBUG__
 
+static __threadlocal int _reentrant_lock = 0;
+
 // This override of wx's implementation provides thread safe assertion message reporting.  If we aren't
 // on the main gui thread then the assertion message box needs to be passed off to the main gui thread
 // via messages.
 void Pcsx2App::OnAssertFailure( const wxChar *file, int line, const wxChar *func, const wxChar *cond, const wxChar *msg )
 {
-	// Used to allow the user to suppress future assertions during this application's session.
-	static bool disableAsserts = false;
-	if( disableAsserts ) return;
+	// Re-entrant assertions are bad mojo -- trap immediately.
+	RecursionGuard guard( _reentrant_lock );
+	if( guard.IsReentrant() ) wxTrap();
 
-	if( _reentrant_lock )
+	wxCharBuffer bleh( wxString(func).ToUTF8() );
+	if( AppDoAssert( DiagnosticOrigin( file, line, bleh, cond ), msg ) )
 	{
-		// Re-entrant assertions are bad mojo -- trap immediately.
 		wxTrap();
 	}
+}
 
-	_reentrant_lock = true;
+#endif
 
-	wxString dbgmsg;
-	dbgmsg.reserve( 2048 );
+bool AppDoAssert( const DiagnosticOrigin& origin, const wxChar *msg )
+{
+	// Used to allow the user to suppress future assertions during this application's session.
+	static bool disableAsserts = false;
+	if( disableAsserts ) return false;
 
-	wxString message;
-	if( msg == NULL )
-		message = cond;
-	else
-		message.Printf( L"%s (%s)", msg, cond );
-
-	// make life easier for people using VC++ IDE by using this format, which allows double-click
-	// response times from the Output window...
-	dbgmsg.Printf( L"%s(%d) : assertion failed%s%s: %s\n", file, line,
-		(func==NULL) ? wxEmptyString : L" in ", 
-		(func==NULL) ? wxEmptyString : func, 
-		message.c_str()
-	);
-
-	wxString trace( L"Call stack:\n" + pxGetStackTrace() );
+	wxString trace( pxGetStackTrace(origin.function) );
+	wxString dbgmsg( origin.ToString( msg ) );
 
 	wxMessageOutputDebug().Printf( dbgmsg );
+
 	Console.Error( dbgmsg );
 	Console.WriteLn( trace );
 
-	int retval = Msgbox::Assertion( dbgmsg, trace );
-	
-	switch( retval )
-	{
-		case wxID_YES:
-			wxTrap();
-		break;
-		
-		case wxID_NO: break;
-		
-		case wxID_CANCEL:		// ignores future assertions.
-			disableAsserts = true;
-		break;
-	}
+	wxString windowmsg( L"Assertion failed: " );
+	if( msg != NULL )
+		windowmsg += msg;
+	else if( origin.condition != NULL )
+		windowmsg += origin.condition;
 
-	_reentrant_lock = false;
+	int retval = Msgbox::Assertion( windowmsg, dbgmsg + L"\nStacktrace:\n" + trace );
+	
+	if( retval == wxID_YES ) return true;
+	if( retval == wxID_IGNORE ) disableAsserts = true;
+	
+	return false;
 }
-#endif
diff --git a/pcsx2/gui/AppConfig.cpp b/pcsx2/gui/AppConfig.cpp
index 8d18c17e04..3c41be2310 100644
--- a/pcsx2/gui/AppConfig.cpp
+++ b/pcsx2/gui/AppConfig.cpp
@@ -312,7 +312,7 @@ AppConfig::AppConfig()
 	, DeskTheme( L"default" )
 {
 	LanguageId			= wxLANGUAGE_DEFAULT;
-	RecentFileCount		= 6;
+	RecentIsoCount		= 12;
 	Listbook_ImageSize	= 32;
 	Toolbar_ImageSize	= 24;
 	Toolbar_ShowLabels	= true;
@@ -378,7 +378,7 @@ void AppConfig::LoadSaveRootItems( IniInterface& ini )
 	IniEntry( MainGuiPosition );
 	IniEntry( SettingsTabName );
 	ini.EnumEntry( L"LanguageId", LanguageId, NULL, defaults.LanguageId );
-	IniEntry( RecentFileCount );
+	IniEntry( RecentIsoCount );
 	IniEntry( DeskTheme );
 	IniEntry( Listbook_ImageSize );
 	IniEntry( Toolbar_ImageSize );
diff --git a/pcsx2/gui/AppConfig.h b/pcsx2/gui/AppConfig.h
index 8eb272bbc2..7c6c385372 100644
--- a/pcsx2/gui/AppConfig.h
+++ b/pcsx2/gui/AppConfig.h
@@ -154,7 +154,7 @@ public:
 	// Current language in use (correlates to a wxWidgets wxLANGUAGE specifier)
 	wxLanguage	LanguageId;
 
-	int			RecentFileCount;		// number of files displayed in the Recent Isos list.
+	int			RecentIsoCount;		// number of files displayed in the Recent Isos list.
 
 	// String value describing the desktop theme to use for pcsk2 (icons and background images)
 	// The theme name is used to look up files in the themes folder (relative to the executable).
diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp
index 1eaab5a48a..1855bff585 100644
--- a/pcsx2/gui/AppCoreThread.cpp
+++ b/pcsx2/gui/AppCoreThread.cpp
@@ -28,6 +28,16 @@ AppCoreThread::AppCoreThread() : SysCoreThread()
 
 AppCoreThread::~AppCoreThread() throw()
 {
+	AppCoreThread::Cancel();
+}
+
+void AppCoreThread::Cancel( bool isBlocking )
+{
+	if( !_parent::Cancel( wxTimeSpan( 0,0,1,0 ) ) )
+	{
+		// Possible deadlock!
+		throw Exception::ThreadTimedOut( this );
+	}
 }
 
 void AppCoreThread::Reset()
diff --git a/pcsx2/gui/AppInit.cpp b/pcsx2/gui/AppInit.cpp
index c5feea509a..5edb0bf61c 100644
--- a/pcsx2/gui/AppInit.cpp
+++ b/pcsx2/gui/AppInit.cpp
@@ -45,6 +45,32 @@ namespace Exception
 	};
 }
 
+static void CpuCheckSSE2()
+{
+	if( x86caps.hasStreamingSIMD2Extensions ) return;
+
+	// Only check once per process session:
+	static bool checked = false;
+	if( checked ) return;
+	checked = true;
+
+	wxDialogWithHelpers exconf( NULL, _("PCSX2 - SSE2 Recommended"), wxVERTICAL );
+
+	exconf += exconf.Heading( pxE( ".Error:Startup:NoSSE2",
+		L"Warning: Your computer does not support SSE2, which is required by many PCSX2 recompilers and plugins. "
+		L"Your options will be limited and emulation will be *very* slow." )
+	);
+
+	pxIssueConfirmation( exconf, MsgButtons().OK(), L"Error:Startup:NoSSE2" );
+
+	// Auto-disable anything that needs SSE2:
+
+	g_Conf->EmuOptions.Cpu.Recompiler.EnableEE	= false;
+	g_Conf->EmuOptions.Cpu.Recompiler.EnableVU0	= false;
+	g_Conf->EmuOptions.Cpu.Recompiler.EnableVU1	= false;
+}
+
+
 void Pcsx2App::OpenWizardConsole()
 {
 	if( !IsDebugBuild ) return;
@@ -81,8 +107,7 @@ void Pcsx2App::ReadUserModeSettings()
 
 	if (IOP_ENABLE_SIF_HACK == 1)
 	{
-		wxDialogWithHelpers hackedVersion( NULL, wxID_ANY, _("It will devour your young! - PCSX2 Shub-Niggurath edition"), false );
-		hackedVersion.SetIdealWidth( 575 );
+		wxDialogWithHelpers hackedVersion( NULL, _("It will devour your young! - PCSX2 Shub-Niggurath edition"), wxVERTICAL );
 
 		hackedVersion.SetSizer( new wxBoxSizer( wxVERTICAL ) );
 		hackedVersion += new pxStaticText( &hackedVersion,
@@ -92,8 +117,6 @@ void Pcsx2App::ReadUserModeSettings()
 		);
 		
 		hackedVersion += new wxButton( &hackedVersion, wxID_OK ) | pxSizerFlags::StdCenter();
-		hackedVersion.Fit();
-		hackedVersion.CentreOnScreen();
 		hackedVersion.ShowModal();
 	}
 
@@ -101,8 +124,7 @@ void Pcsx2App::ReadUserModeSettings()
 	{
 		// Pre-Alpha Warning!  Why didn't I think to add this sooner?!
 		
-		wxDialogWithHelpers preAlpha( NULL, wxID_ANY, _("It might devour your kittens! - PCSX2 0.9.7 Pre-Alpha"), false );
-		preAlpha.SetIdealWidth( 575 );
+		wxDialogWithHelpers preAlpha( NULL, _("It might devour your kittens! - PCSX2 0.9.7 Pre-Alpha"), wxVERTICAL );
 
 		preAlpha.SetSizer( new wxBoxSizer( wxVERTICAL ) );
 		preAlpha += new pxStaticText( &preAlpha,
@@ -113,8 +135,6 @@ void Pcsx2App::ReadUserModeSettings()
 		);
 		
 		preAlpha += new wxButton( &preAlpha, wxID_OK ) | pxSizerFlags::StdCenter();
-		preAlpha.Fit();
-		preAlpha.CentreOnScreen();
 		preAlpha.ShowModal();
 	
 		// first time startup, so give the user the choice of user mode:
@@ -243,6 +263,15 @@ typedef void (wxEvtHandler::*pxMessageBoxEventFunction)(pxMessageBoxEvent&);
 // ------------------------------------------------------------------------
 bool Pcsx2App::OnInit()
 {
+#define pxMessageBoxEventThing(func) \
+	(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
+
+	Connect( pxEVT_MSGBOX,			pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
+	Connect( pxEVT_ASSERTION,		pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
+	Connect( pxEVT_OpenModalDialog,	wxCommandEventHandler( Pcsx2App::OnOpenModalDialog ) );
+
+	pxDoAssert = AppDoAssert;
+
 	g_Conf = new AppConfig();
 	EnableAllLogging();
 
@@ -253,12 +282,6 @@ bool Pcsx2App::OnInit()
 	m_StderrRedirHandle = NewPipeRedir(stderr);
 	wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
 
-#define pxMessageBoxEventThing(func) \
-	(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
-
-	Connect( pxEVT_MSGBOX,			pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
-	Connect( pxEVT_CallStackBox,	pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
-	Connect( pxEVT_OpenModalDialog,	wxCommandEventHandler( Pcsx2App::OnOpenModalDialog ) );
 	Connect( pxEVT_ReloadPlugins,	wxCommandEventHandler( Pcsx2App::OnReloadPlugins ) );
 	Connect( pxEVT_SysExecute,		wxCommandEventHandler( Pcsx2App::OnSysExecute ) );
 
@@ -286,9 +309,21 @@ bool Pcsx2App::OnInit()
 
 		m_Resources = new pxAppResources();
 
+		cpudetectInit();
+
+		if( !x86caps.hasMultimediaExtensions )
+		{
+			// Note: due to memcpy_fast, we need minimum MMX even for interpreters.  This will
+			// hopefully change later once we have a dynamically recompiled memcpy.
+			Msgbox::Alert( _("PCSX2 requires cpu with MMX instruction to run.  Press OK to close."), _("PCSX2 - MMX Required") );
+			return false;
+		}
+
 		ReadUserModeSettings();
 		AppConfig_OnChangedSettingsFolder();
 
+		CpuCheckSSE2();
+
 	    m_MainFrame = new MainEmuFrame( NULL, L"PCSX2" );
 		m_MainFrame->PushEventHandler( &GetRecentIsoList() );
 
@@ -307,7 +342,8 @@ bool Pcsx2App::OnInit()
 		SetExitOnFrameDelete( true );	// but being explicit doesn't hurt...
 	    m_MainFrame->Show();
 
-		SysDetect();
+		SysLogMachineCaps();
+
 		AppApplySettings();
 
 #ifdef __WXMSW__
@@ -317,47 +353,72 @@ bool Pcsx2App::OnInit()
 
 		m_CoreAllocs = new SysCoreAllocations();
 
+
 		if( m_CoreAllocs->HadSomeFailures( g_Conf->EmuOptions.Cpu.Recompiler ) )
 		{
 			// HadSomeFailures only returns 'true' if an *enabled* cpu type fails to init.  If
 			// the user already has all interps configured, for example, then no point in
 			// popping up this dialog.
+			
+			wxDialogWithHelpers exconf( NULL, _("PCSX2 Recompiler Error(s)"), wxVERTICAL );
 
-			// TODO : This should be redone using the ExtensibleConfirmation, and a sub-window
-			// (static text or something with a vertical scrollbar).
+			exconf += 12;
+			exconf += exconf.Heading( pxE( ".Error:RecompilerInit",
+				L"Warning: Some of the configured PS2 recompilers failed to initialize and will not be available for this session:\n" )
+			);
 
-			wxString message( _("The following cpu recompilers failed to initialize and will not be available:\n\n") );
+			wxTextCtrl* scrollableTextArea = new wxTextCtrl(
+				&exconf, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
+				wxTE_READONLY | wxTE_MULTILINE | wxTE_WORDWRAP
+			);
 
+			exconf += scrollableTextArea	| pxSizerFlags::StdExpand();
+			
 			if( !m_CoreAllocs->IsRecAvailable_EE() )
 			{
-				message += L"\t* R5900 (EE)\n";
+				scrollableTextArea->AppendText( L"* R5900 (EE)\n\n" );
+
+				g_Conf->EmuOptions.Recompiler.EnableEE = false;
 			}
 
 			if( !m_CoreAllocs->IsRecAvailable_IOP() )
 			{
-				message += L"\t* R3000A (IOP)\n";
+				scrollableTextArea->AppendText( L"* R3000A (IOP)\n\n" );
+				g_Conf->EmuOptions.Recompiler.EnableIOP = false;
 			}
 
 			if( !m_CoreAllocs->IsRecAvailable_MicroVU0() )
 			{
-				message += L"\t* microVU0\n";
+				scrollableTextArea->AppendText( L"* microVU0\n\n" );
+				g_Conf->EmuOptions.Recompiler.UseMicroVU0	= false;
+				g_Conf->EmuOptions.Recompiler.EnableVU0		= g_Conf->EmuOptions.Recompiler.EnableVU0 && m_CoreAllocs->IsRecAvailable_SuperVU0();
 			}
 
 			if( !m_CoreAllocs->IsRecAvailable_MicroVU1() )
 			{
-				message += L"\t* microVU1\n";
+				scrollableTextArea->AppendText( L"* microVU1\n\n" );
+				g_Conf->EmuOptions.Recompiler.UseMicroVU1	= false;
+				g_Conf->EmuOptions.Recompiler.EnableVU1		= g_Conf->EmuOptions.Recompiler.EnableVU1 && m_CoreAllocs->IsRecAvailable_SuperVU1();
 			}
 
 			if( !m_CoreAllocs->IsRecAvailable_SuperVU0() )
 			{
-				message += L"\t* SuperVU0\n";
+				scrollableTextArea->AppendText( L"* SuperVU0\n\n" );
+				g_Conf->EmuOptions.Recompiler.UseMicroVU0	= m_CoreAllocs->IsRecAvailable_MicroVU0();
+				g_Conf->EmuOptions.Recompiler.EnableVU0		= g_Conf->EmuOptions.Recompiler.EnableVU0 && g_Conf->EmuOptions.Recompiler.UseMicroVU0;
 			}
 
 			if( !m_CoreAllocs->IsRecAvailable_SuperVU1() )
 			{
-				message += L"\t* SuperVU1\n";
+				scrollableTextArea->AppendText( L"* SuperVU1\n\n" );
+				g_Conf->EmuOptions.Recompiler.UseMicroVU1	= m_CoreAllocs->IsRecAvailable_MicroVU1();
+				g_Conf->EmuOptions.Recompiler.EnableVU1		= g_Conf->EmuOptions.Recompiler.EnableVU1 && g_Conf->EmuOptions.Recompiler.UseMicroVU1;
 			}
 
+			exconf += new ModalButtonPanel( &exconf, MsgButtons().OK() ) | pxSizerFlags::StdCenter();
+
+			exconf.ShowModal();
+
 			// Failures can be SSE-related OR memory related.  Should do per-cpu error reports instead...
 
 			/*message += pxE( ".Popup Error:EmuCore:MemoryForRecs",
@@ -367,8 +428,8 @@ bool Pcsx2App::OnInit()
 				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;
+			//if( !Msgbox::OkCancel( message, _("PCSX2 Initialization Error"), wxICON_ERROR ) )
+			//	return false;
 		}
 
 		LoadPluginsPassive( NULL );
@@ -408,13 +469,16 @@ void Pcsx2App::CleanupMess()
 		if( m_CorePlugins )
 			m_CorePlugins->Shutdown();
 	}
+	catch( Exception::ThreadTimedOut& )		{ throw; }
+	catch( Exception::CancelEvent& )		{ throw; }
 	catch( Exception::RuntimeError& ex )
 	{
 		// Handle runtime errors gracefully during shutdown.  Mostly these are things
 		// that we just don't care about by now, and just want to "get 'er done!" so
 		// we can exit the app. ;)
 
-		Console.Error( ex.FormatDiagnosticMessage() );
+		Console.Error( L"Runtime exception handled during CleanupMess:\n" );
+		Console.Indent().Error( ex.FormatDiagnosticMessage() );
 	}
 	
 	// Notice: deleting the plugin manager (unloading plugins) here causes Lilypad to crash,
@@ -427,6 +491,8 @@ void Pcsx2App::CleanupMess()
 
 	while( wxGetLocale() != NULL )
 		delete wxGetLocale();
+
+	pxDoAssert = pxAssertImpl_LogIt;
 }
 
 Pcsx2App::Pcsx2App() 
@@ -441,6 +507,8 @@ Pcsx2App::Pcsx2App()
 
 Pcsx2App::~Pcsx2App()
 {
+	pxDoAssert = pxAssertImpl_LogIt;
+
 	// Typically OnExit cleans everything up before we get here, *unless* we cancel
 	// out of program startup in OnInit (return false) -- then remaining cleanup needs
 	// to happen here in the destructor.
@@ -485,6 +553,6 @@ struct CrtDebugBreak
 	}
 };
 
-//CrtDebugBreak breakAt( 4327 );
+//CrtDebugBreak breakAt( 1175 );
 
 #endif
\ No newline at end of file
diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp
index 1440b4cc68..db5a82ae51 100644
--- a/pcsx2/gui/AppMain.cpp
+++ b/pcsx2/gui/AppMain.cpp
@@ -53,7 +53,7 @@ ConfigOverrides			OverrideOptions;
 
 static bool HandlePluginError( Exception::PluginError& ex )
 {
-	if( pxDialogExists( DialogId_CoreSettings ) ) return true;
+	if( pxDialogExists( L"CoreSettings" ) ) return true;
 
 	bool result = Msgbox::OkCancel( ex.FormatDisplayMessage() +
 		_("\n\nPress Ok to go to the Plugin Configuration Panel.")
@@ -64,7 +64,7 @@ static bool HandlePluginError( Exception::PluginError& ex )
 		g_Conf->SettingsTabName = L"Plugins";
 
 		// fixme: Send a message to the panel to select the failed plugin.
-		if( Dialogs::ConfigurationDialog().ShowModal() == wxID_CANCEL )
+		if( wxGetApp().IssueModalDialog( Dialogs::ConfigurationDialog::GetNameStatic() ) == wxID_CANCEL )
 			return false;
 	}
 	return result;
@@ -101,18 +101,6 @@ void Pcsx2App::PostPadKey( wxKeyEvent& evt )
 	}
 }
 
-int Pcsx2App::ThreadedModalDialog( DialogIdentifiers dialogId )
-{
-	AffinityAssert_AllowFromMain();
-
-	MsgboxEventResult result;
-	wxCommandEvent joe( pxEVT_OpenModalDialog, dialogId );
-	joe.SetClientData( &result );
-	AddPendingEvent( joe );
-	result.WaitForMe.WaitNoCancel();
-	return result.result;
-}
-
 // ----------------------------------------------------------------------------
 //         Pcsx2App Event Handlers
 // ----------------------------------------------------------------------------
@@ -130,54 +118,69 @@ void Pcsx2App::OnCoreThreadStatus( wxCommandEvent& evt )
 
 void Pcsx2App::OnOpenModalDialog( wxCommandEvent& evt )
 {
-	using namespace Dialogs;
+	pxAssertDev( !evt.GetString().IsEmpty(), wxNullChar );
 
-	MsgboxEventResult& evtres( *((MsgboxEventResult*)evt.GetClientData()) );
-	switch( evt.GetId() )
+	MsgboxEventResult* evtres = (MsgboxEventResult*)evt.GetClientData();
+
+	wxWindowID result = IssueModalDialog( evt.GetString() );
+
+	if( evtres != NULL )
 	{
-		case DialogId_CoreSettings:
-		{
-			static int _guard = 0;
-			RecursionGuard guard( _guard );
-			if( guard.IsReentrant() ) return;
-			evtres.result = ConfigurationDialog().ShowModal();
-		}
-		break;
-
-		case DialogId_BiosSelector:
-		{
-			static int _guard = 0;
-			RecursionGuard guard( _guard );
-			if( guard.IsReentrant() ) return;
-			evtres.result = BiosSelectorDialog().ShowModal();
-		}
-		break;
-
-		case DialogId_LogOptions:
-		{
-			static int _guard = 0;
-			RecursionGuard guard( _guard );
-			if( guard.IsReentrant() ) return;
-			evtres.result = LogOptionsDialog().ShowModal();
-		}
-		break;
-
-		case DialogId_About:
-		{
-			static int _guard = 0;
-			RecursionGuard guard( _guard );
-			if( guard.IsReentrant() ) return;
-			evtres.result = AboutBoxDialog().ShowModal();
-		}
-		break;
+		evtres->result = result;
+		evtres->WaitForMe.Post();
 	}
-
-	evtres.WaitForMe.Post();
 }
 
-void Pcsx2App::OnMessageBox( pxMessageBoxEvent& evt )
+int Pcsx2App::IssueModalDialog( const wxString& dlgName )
 {
-	Msgbox::OnEvent( evt );
+	if( dlgName.IsEmpty() ) return wxID_CANCEL;
+	
+	if( !wxThread::IsMain() )
+	{
+		MsgboxEventResult result;
+		wxCommandEvent joe( pxEVT_OpenModalDialog );
+		joe.SetString( dlgName );
+		joe.SetClientData( &result );
+		AddPendingEvent( joe );
+		result.WaitForMe.WaitNoCancel();
+		return result.result;
+	}
+	
+	if( wxWindow* window = wxFindWindowByName( dlgName ) )
+	{
+		if( wxIsKindOf( window, wxDialog ) )
+		{
+			wxDialog* dialog = (wxDialog*)window;
+
+			window->SetFocus();
+			
+			// It's legal to call ShowModal on a non-modal dialog, therefore making
+			// it modal in nature for the needs of whatever other thread of action wants
+			// to block against it:
+
+			if( !dialog->IsModal() )
+			{
+				int result = dialog->ShowModal();
+				dialog->Destroy();
+				return result;
+			}
+		}
+	}
+	else
+	{
+		using namespace Dialogs;
+
+		if( dlgName == ConfigurationDialog::GetNameStatic() )
+			return ConfigurationDialog().ShowModal();
+		if( dlgName == BiosSelectorDialog::GetNameStatic() )
+			return BiosSelectorDialog().ShowModal();
+		if( dlgName == LogOptionsDialog::GetNameStatic() )
+			return LogOptionsDialog().ShowModal();
+		if( dlgName == AboutBoxDialog::GetNameStatic() )
+			return AboutBoxDialog().ShowModal();
+	}
+	
+	return wxID_CANCEL;
 }
 
 HashTools::HashMap<int, const GlobalCommandDescriptor*> GlobalAccels( 0, 0xffffffff );
@@ -227,15 +230,14 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
 	// ----------------------------------------------------------------------------
 	catch( Exception::BiosLoadFailed& ex )
 	{
-		bool result = Dialogs::ExtensibleConfirmation( NULL, ConfButtons().OK().Cancel(),
-			L"PS2 BIOS Error",
-			ex.FormatDisplayMessage() + BIOS_GetMsg_Required() + _("\nPress Ok to go to the BIOS Configuration Panel.")
-		).ShowModal() != wxID_CANCEL;
-
-		if( !result )
+		wxDialogWithHelpers dialog( NULL, _("PS2 BIOS Error"), wxVERTICAL );
+		dialog += dialog.Heading( ex.FormatDisplayMessage() + BIOS_GetMsg_Required() + _("\nPress Ok to go to the BIOS Configuration Panel.") );
+		dialog += new ModalButtonPanel( &dialog, MsgButtons().OKCancel() );
+		
+		if( dialog.ShowModal() == wxID_CANCEL )
 			Console.Warning( "User denied option to re-configure BIOS." );
 
-		if( Dialogs::BiosSelectorDialog().ShowModal() != wxID_CANCEL )
+		if( IssueModalDialog( Dialogs::BiosSelectorDialog::GetNameStatic() ) != wxID_CANCEL )
 		{
 			SysExecute();
 		}
@@ -268,15 +270,22 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
 	// ----------------------------------------------------------------------------
 	catch( Exception::ThreadTimedOut& ex )
 	{
+		// [TODO]  Bind a listener to the CoreThread status, and automatically close the dialog
+		// if the thread starts responding while we're waiting (not hard in fact, but I'm getting
+		// a little tired, so maybe later!)  --air
+	
 		Console.Warning( ex.FormatDiagnosticMessage() );
-		int result = Dialogs::ExtensibleConfirmation( NULL, ConfButtons().Ignore().Cancel().Custom( _("Terminate") ),
-			_("PCSX2 Unresponsive Thread"), ex.FormatDisplayMessage() + L"\n\n" +
+		wxDialogWithHelpers dialog( NULL, _("PCSX2 Unresponsive Thread"), wxVERTICAL );
+		
+		dialog += dialog.Heading( ex.FormatDisplayMessage() + L"\n\n" +
 			pxE( ".Popup Error:Thread Deadlock Actions",
 				L"'Ignore' to continue waiting for the thread to respond.\n"
 				L"'Cancel' to attempt to cancel the thread.\n"
 				L"'Terminate' to quit PCSX2 immediately.\n"
 			)
-		).ShowModal();
+		);
+
+		int result = pxIssueConfirmation( dialog, MsgButtons().Ignore().Cancel().Custom( _("Terminate") ) );
 		
 		if( result == pxID_CUSTOM )
 		{
@@ -386,14 +395,14 @@ int Pcsx2App::OnExit()
 // is a matter of programmer preference).
 MainEmuFrame& Pcsx2App::GetMainFrame() const
 {
-	pxAssert( ((uptr)GetTopWindow()) == ((uptr)m_MainFrame) );
-	pxAssert( m_MainFrame != NULL );
+	pxAssume( ((uptr)GetTopWindow()) == ((uptr)m_MainFrame) );
+	pxAssume( m_MainFrame != NULL );
 	return *m_MainFrame;
 }
 
 GSFrame& Pcsx2App::GetGSFrame() const
 {
-	pxAssert( m_gsFrame != NULL );
+	pxAssume( m_gsFrame != NULL );
 	return *m_gsFrame;
 }
 
@@ -594,6 +603,8 @@ void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
 // Full system reset stops the core thread and unloads all core plugins *completely*.
 void Pcsx2App::SysReset()
 {
+	StateCopy_Clear();
+
 	CoreThread.Reset();
 	CoreThread.ReleaseResumeLock();
 	m_CorePlugins = NULL;
diff --git a/pcsx2/gui/ConsoleLogger.cpp b/pcsx2/gui/ConsoleLogger.cpp
index d49e14d87a..8b181725c3 100644
--- a/pcsx2/gui/ConsoleLogger.cpp
+++ b/pcsx2/gui/ConsoleLogger.cpp
@@ -176,8 +176,15 @@ ConsoleLogFrame::ColorArray::~ColorArray()
 
 void ConsoleLogFrame::ColorArray::Create( int fontsize )
 {
-	const wxFont fixed( fontsize, wxMODERN, wxNORMAL, wxNORMAL );
-	const wxFont fixedB( fontsize, wxMODERN, wxNORMAL, wxBOLD );
+	// pxGetFixedFont selects Andale Mono on Win32, which is nice visually but
+	// unfortunately has inconsistently spaced bold versions, so it's not good
+	// for our console.
+
+	const wxFont fixed( pxGetFixedFont( fontsize ) );
+	const wxFont fixedB( pxGetFixedFont( fontsize+1, wxBOLD ) );
+	
+	//const wxFont fixed( fontsize, wxMODERN, wxNORMAL, wxNORMAL );
+	//const wxFont fixedB( fontsize, wxMODERN, wxNORMAL, wxBOLD );
 
 	// Standard R, G, B format:
 	new (&m_table[Color_Default])		wxTextAttr( wxColor(   0,   0,   0 ), wxNullColour, fixed );
@@ -262,6 +269,10 @@ ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, A
 	m_TextCtrl.SetBackgroundColour( wxColor( 230, 235, 242 ) );
 	m_TextCtrl.SetDefaultStyle( m_ColorTable[DefaultConsoleColor] );
 
+	// SetDefaultStyle only sets the style of text in the control.  We need to
+	// also set the font of the control, so that sizing logic knows what font we use:
+	m_TextCtrl.SetFont( m_ColorTable[DefaultConsoleColor].GetFont() );
+
 	wxMenu& menuLog		(*new wxMenu());
 	wxMenu& menuAppear	(*new wxMenu());
 	wxMenu& menuSources	(*new wxMenu());
diff --git a/pcsx2/gui/ConsoleLogger.h b/pcsx2/gui/ConsoleLogger.h
index 5e8a827539..586826948d 100644
--- a/pcsx2/gui/ConsoleLogger.h
+++ b/pcsx2/gui/ConsoleLogger.h
@@ -96,10 +96,10 @@ protected:
 	EventListenerBinding<PluginEventType>	m_Listener_CorePluginStatus;
 
 #ifdef __WXMSW__
-	int		m_win32_StupidRefreshTricks;
 	int		m_win32_LinesPerPage;
 	int		m_win32_LinesPerScroll;
 #endif
+	bool	m_IsPaused;
 	bool	m_FreezeWrites;
 
 public:
diff --git a/pcsx2/gui/Dialogs/AboutBoxDialog.cpp b/pcsx2/gui/Dialogs/AboutBoxDialog.cpp
index b79dce20d0..c050e48e92 100644
--- a/pcsx2/gui/Dialogs/AboutBoxDialog.cpp
+++ b/pcsx2/gui/Dialogs/AboutBoxDialog.cpp
@@ -25,6 +25,8 @@
 #include <wx/mstream.h>
 #include <wx/hyperlink.h>
 
+using namespace pxSizerFlags;
+
 namespace Dialogs
 {
 	// Helper class for creating wxStaticText labels which are aligned to center.
@@ -45,11 +47,14 @@ namespace Dialogs
 //  AboutBoxDialog  Implementation
 // --------------------------------------------------------------------------------------
 
-Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
-	wxDialogWithHelpers( parent, id, _("About PCSX2"), false ),
-	m_bitmap_dualshock( this, wxID_ANY, wxBitmap( EmbeddedImage<res_Dualshock>().Get() ),
-		wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN )
+Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent )
+	: wxDialogWithHelpers( parent, _("About PCSX2"), wxVERTICAL )
+	, m_bitmap_dualshock( this, wxID_ANY, wxBitmap( EmbeddedImage<res_Dualshock>().Get() ),
+		wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN
+	)
 {
+	SetName( GetNameStatic() );
+
 	static const wxString LabelAuthors = fromUTF8(
 		"Developers"
 		"\n\n"
@@ -80,10 +85,6 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
 		"F|RES, MrBrown, razorblade, Seta-san, Skarmeth, feal87"
 	);
 
-	SetSizer( new wxBoxSizer( wxVERTICAL ) );
-
-	*this += Text(_("PCSX2  -  Playstation 2 Emulator"));
-
 	// This sizer holds text of the authors and a logo!
 	wxBoxSizer& AuthLogoSizer = *new wxBoxSizer( wxHORIZONTAL );
 
@@ -99,18 +100,21 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
 	label_auth->Wrap( 340 );
 	label_greets->Wrap( 200 );
 
-	aboutUs.Add( label_auth, pxSizerFlags::StdExpand() );
-	contribs.Add( label_greets, pxSizerFlags::StdExpand() );
+	aboutUs		+= label_auth		| StdExpand();
+	contribs	+= label_greets		| StdExpand();
 
-	AuthLogoSizer.Add( &aboutUs );
-	AuthLogoSizer.AddSpacer( 7 );
-	AuthLogoSizer.Add( &contribs );
+	AuthLogoSizer	+= aboutUs;
+	AuthLogoSizer	+= 7;
+	AuthLogoSizer	+= contribs;
 
 	ContribSizer.AddStretchSpacer( 1 );
-	ContribSizer.Add( &m_bitmap_dualshock, pxSizerFlags::StdSpace() );
+	ContribSizer	+= m_bitmap_dualshock	| StdSpace();
 	ContribSizer.AddStretchSpacer( 1 );
 
-	*this	+= AuthLogoSizer	| pxSizerFlags::StdSpace();
+	// Main (top-level) layout 
+
+	*this	+= Text(_("PCSX2  -  Playstation 2 Emulator"));
+	*this	+= AuthLogoSizer										| StdSpace();
 
 	*this	+= new wxHyperlinkCtrl( this, wxID_ANY,
 		_("Pcsx2 Official Website and Forums"), L"http://www.pcsx2.net"
@@ -120,10 +124,6 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
 		_("Pcsx2 Official Svn Repository at Googlecode"), L"http://code.google.com/p/pcsx2"
 	) | wxSizerFlags(1).Center().Border( wxALL, 3 );
 
-	*this	+= ContribSizer		| pxSizerFlags::StdExpand();
-
-	*this	+= new wxButton( this, wxID_OK, L"I've seen enough") | pxSizerFlags::StdCenter();
-
-	Fit();
-	CenterOnScreen();
+	*this	+= ContribSizer											| StdExpand();
+	*this	+= new wxButton( this, wxID_OK, L"I've seen enough")	| StdCenter();
 }
diff --git a/pcsx2/gui/Dialogs/AssertionDialog.cpp b/pcsx2/gui/Dialogs/AssertionDialog.cpp
new file mode 100644
index 0000000000..7517bb6101
--- /dev/null
+++ b/pcsx2/gui/Dialogs/AssertionDialog.cpp
@@ -0,0 +1,67 @@
+/*  PCSX2 - PS2 Emulator for PCs
+ *  Copyright (C) 2002-2009  PCSX2 Dev Team
+ *
+ *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ *  of the GNU Lesser General Public License as published by the Free Software Found-
+ *  ation, either version 3 of the License, or (at your option) any later version.
+ *
+ *  PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *  PURPOSE.  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with PCSX2.
+ *  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PrecompiledHeader.h"
+#include "App.h"
+#include "Dialogs/ModalPopups.h"
+
+using namespace pxSizerFlags;
+
+Dialogs::AssertionDialog::AssertionDialog( const wxString& text, const wxString& stacktrace )
+	: wxDialogWithHelpers( NULL, _("PCSX2 Assertion Failure"), false, !stacktrace.IsEmpty() )
+{
+	m_idealWidth = 720;
+
+	wxFlexGridSizer* flexgrid = new wxFlexGridSizer( 1 );
+	flexgrid->AddGrowableCol( 0 );
+	SetSizer( flexgrid );
+
+	wxTextCtrl* traceArea = NULL;
+
+	if( !stacktrace.IsEmpty() )
+	{
+		flexgrid->AddGrowableRow( 1 );
+
+		traceArea = new wxTextCtrl(
+			this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
+			wxTE_READONLY | wxTE_MULTILINE | wxTE_RICH2 | wxHSCROLL
+		);
+
+		traceArea->SetDefaultStyle( wxTextAttr( wxNullColour, wxNullColour, pxGetFixedFont() ) );
+		traceArea->SetFont( pxGetFixedFont() );
+
+		int fonty;
+		traceArea->GetTextExtent( L"blaH yeah", NULL, &fonty );
+
+		traceArea->WriteText( stacktrace );
+		traceArea->SetMinSize( wxSize( GetIdealWidth()-24, (fonty+1)*18 ) );
+		traceArea->ShowPosition(0);
+	}
+
+	*this += Heading( text );
+
+	if( traceArea != NULL ) *this += traceArea | pxExpand.Border(wxTOP|wxLEFT|wxRIGHT,8);
+
+	*this += Heading(
+		L"\nDo you want to stop the program [Yes/No]?"
+		L"\nOr press [Ignore] to suppress further assertions."
+	);
+
+	*this += new ModalButtonPanel( this, MsgButtons().YesNo().Ignore() ) | StdCenter();
+
+	if( wxWindow* idyes = FindWindowById( wxID_YES ) )
+		idyes->SetFocus();
+}
+
diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.cpp b/pcsx2/gui/Dialogs/ConfigurationDialog.cpp
index 1355dc7468..7abd217d59 100644
--- a/pcsx2/gui/Dialogs/ConfigurationDialog.cpp
+++ b/pcsx2/gui/Dialogs/ConfigurationDialog.cpp
@@ -55,10 +55,12 @@ void Dialogs::ConfigurationDialog::AddPage( const char* label, int iconid )
 		( labelstr == g_Conf->SettingsTabName ), iconid );
 }
 
-Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent, int id )
-	: wxDialogWithHelpers( parent, id, _("PCSX2 Configuration"), true )
+Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent )
+	: wxDialogWithHelpers( parent, _("PCSX2 Configuration"), true )
 	, m_listbook( *new wxListbook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, s_orient ) )
 {
+	SetName( GetNameStatic() );
+
 	m_idealWidth = 600;
 
 	m_listbook.SetImageList( &wxGetApp().GetImgList_Config() );
@@ -85,9 +87,6 @@ Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent, int id )
 
 	FindWindow( wxID_APPLY )->Disable();
 
-	Fit();
-	CenterOnScreen();
-
 #ifdef __WXMSW__
 	// Depending on Windows version and user appearance settings, the default icon spacing can be
 	// way over generous.  This little bit of Win32-specific code ensures proper icon spacing, scaled
@@ -103,6 +102,8 @@ Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent, int id )
 	Connect( wxID_APPLY,	wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigurationDialog::OnApply_Click ) );
 	Connect( wxID_SAVE,		wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ConfigurationDialog::OnScreenshot_Click ) );
 
+	Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler(ConfigurationDialog::OnCloseWindow) );
+	
 	// ----------------------------------------------------------------------------
 	// Bind a variety of standard "something probably changed" events.  If the user invokes
 	// any of these, we'll automatically de-gray the Apply button for this dialog box. :)
@@ -126,6 +127,12 @@ Dialogs::ConfigurationDialog::~ConfigurationDialog() throw()
 	g_ApplyState.DoCleanup();
 }
 
+void Dialogs::ConfigurationDialog::OnCloseWindow( wxCloseEvent& evt )
+{
+	if( !IsModal() ) Destroy();
+	evt.Skip();
+}
+
 void Dialogs::ConfigurationDialog::OnOk_Click( wxCommandEvent& evt )
 {
 	if( g_ApplyState.ApplyAll() )
@@ -133,8 +140,6 @@ void Dialogs::ConfigurationDialog::OnOk_Click( wxCommandEvent& evt )
 		FindWindow( wxID_APPLY )->Disable();
 		g_Conf->SettingsTabName = m_labels[m_listbook.GetSelection()];
 		AppSaveSettings();
-
-		Close();
 		evt.Skip();
 	}
 }
@@ -181,9 +186,11 @@ void Dialogs::ConfigurationDialog::OnScreenshot_Click( wxCommandEvent& evt )
 }
 
 // ----------------------------------------------------------------------------
-Dialogs::BiosSelectorDialog::BiosSelectorDialog( wxWindow* parent, int id )
-	: wxDialogWithHelpers( parent, id, _("BIOS Selector"), false )
+Dialogs::BiosSelectorDialog::BiosSelectorDialog( wxWindow* parent )
+	: wxDialogWithHelpers( parent, _("BIOS Selector"), false )
 {
+	SetName( GetNameStatic() );
+
 	m_idealWidth = 500;
 
 	wxBoxSizer& bleh( *new wxBoxSizer( wxVERTICAL ) );
diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.h b/pcsx2/gui/Dialogs/ConfigurationDialog.h
index 82b21fe6d2..3b93469f83 100644
--- a/pcsx2/gui/Dialogs/ConfigurationDialog.h
+++ b/pcsx2/gui/Dialogs/ConfigurationDialog.h
@@ -33,7 +33,9 @@ namespace Dialogs
 
 	public:
 		virtual ~ConfigurationDialog() throw();
-		ConfigurationDialog(wxWindow* parent=NULL, int id=DialogId_CoreSettings);
+		ConfigurationDialog(wxWindow* parent=NULL);
+
+		static const wxChar* GetNameStatic() { return L"Dialog:CoreSettings"; }
 
 	protected:
 		template< typename T >
@@ -43,6 +45,8 @@ namespace Dialogs
 		void OnCancel_Click( wxCommandEvent& evt );
 		void OnApply_Click( wxCommandEvent& evt );
 		void OnScreenshot_Click( wxCommandEvent& evt );
+		
+		void OnCloseWindow( wxCloseEvent& evt );
 
 		virtual void OnSomethingChanged( wxCommandEvent& evt )
 		{
@@ -54,14 +58,15 @@ namespace Dialogs
 		}
 	};
 
-
 	class BiosSelectorDialog : public wxDialogWithHelpers
 	{
 	protected:
 
 	public:
 		virtual ~BiosSelectorDialog()  throw() {}
-		BiosSelectorDialog( wxWindow* parent=NULL, int id=DialogId_BiosSelector );
+		BiosSelectorDialog( wxWindow* parent=NULL );
+
+		static const wxChar* GetNameStatic() { return L"Dialog:BiosSelector"; }
 
 	protected:
 		void OnOk_Click( wxCommandEvent& evt );
diff --git a/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp b/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp
index 1f15bb26ee..bb6e4bfda2 100644
--- a/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp
+++ b/pcsx2/gui/Dialogs/ConfirmationDialogs.cpp
@@ -20,7 +20,9 @@
 #include "ModalPopups.h"
 #include "Utilities/StringHelpers.h"
 
-bool ConfButtons::Allows( wxWindowID id ) const
+using namespace pxSizerFlags;
+
+bool MsgButtons::Allows( wxWindowID id ) const
 {
 	switch( id )
 	{
@@ -63,7 +65,7 @@ static wxString ResultToString( int result )
 	return wxEmptyString;
 }
 
-static wxWindowID ParseThatResult( const wxString& src, const ConfButtons& validTypes )
+static wxWindowID ParseThatResult( const wxString& src, const MsgButtons& validTypes )
 {
 	if( !pxAssert( !src.IsEmpty() ) ) return wxID_ANY;
 
@@ -85,7 +87,53 @@ static wxWindowID ParseThatResult( const wxString& src, const ConfButtons& valid
 	return wxID_ANY;
 }
 
-wxWindowID Dialogs::IssueConfirmation( ExtensibleConfirmation& confirmDlg, const wxString& disablerKey )
+static bool pxTrySetFocus( wxWindow& parent, wxWindowID id )
+{
+	if( wxWindow* found = parent.FindWindowById( id ) )
+	{
+		found->SetFocus();
+		return true;
+	}
+
+	return false;
+}
+
+static bool pxTrySetFocus( wxWindow* parent, wxWindowID id )
+{
+	if( parent == NULL ) return false;
+	pxTrySetFocus( *parent, id );
+}
+
+void MsgButtons::SetBestFocus( wxWindow& dialog ) const
+{
+	if( HasOK()			&& pxTrySetFocus( dialog, wxID_OK ) ) return;
+	if( HasNo()			&& pxTrySetFocus( dialog, wxID_NO ) ) return;
+	if( HasClose()		&& pxTrySetFocus( dialog, wxID_CLOSE ) ) return;
+	if( HasRetry()		&& pxTrySetFocus( dialog, wxID_RETRY ) ) return;
+	
+	// Other confirmational types of buttons must be explicitly focused by the user or
+	// by an implementing dialog.  We won't do it here implicitly because accidental
+	// "on focus" typed keys could invoke really unwanted actions.
+	
+	// (typically close/ok/retry/etc. aren't so bad that accidental clicking does terrible things)
+}
+
+void MsgButtons::SetBestFocus( wxWindow* dialog ) const
+{
+	if( dialog == NULL ) return;
+	SetBestFocus( *dialog );
+}
+
+
+wxWindowID pxIssueConfirmation( wxDialogWithHelpers& confirmDlg, const MsgButtons& buttons )
+{
+	confirmDlg += new ModalButtonPanel( &confirmDlg, buttons ) | pxCenter.Border( wxTOP, 8 );
+	buttons.SetBestFocus( confirmDlg );
+	return confirmDlg.ShowModal();
+}
+
+
+wxWindowID pxIssueConfirmation( wxDialogWithHelpers& confirmDlg, const MsgButtons& buttons, const wxString& disablerKey )
 {
 	wxConfigBase* cfg = GetAppConfig();
 
@@ -112,135 +160,143 @@ wxWindowID Dialogs::IssueConfirmation( ExtensibleConfirmation& confirmDlg, const
 			result = split[0];
 			if( result == L"disabled" || result == L"off" || result == L"no" )
 			{
-				int result = ParseThatResult( split[1], confirmDlg.GetButtons() );
+				int result = ParseThatResult( split[1], buttons );
 				if( result != wxID_ANY ) return result;
 			}
 		}
 	}
 
-	if( cfg == NULL ) return confirmDlg.ShowModal();
-
-	// Add an option that allows the user to disable this popup from showing again.
-	// (and if the config hasn't been initialized yet, then assume the dialog as non-disablable)
-
-	pxCheckBox&	DisablerCtrl( *new pxCheckBox(&confirmDlg, _("Do not show this dialog again.")) );
-	confirmDlg.GetExtensibleSizer().Add( &DisablerCtrl, wxSizerFlags().Centre() );
-
-	if( confirmDlg.GetButtons() != ConfButtons().OK() )
-		pxSetToolTip(&DisablerCtrl, _("Disables this popup and whatever response you select here will be automatically used from now on."));
-	else
-		pxSetToolTip(&DisablerCtrl, _("The popup will not be shown again.  This setting can be undone from the settings panels."));
-
-	confirmDlg.Fit();
-
-	int modalResult = confirmDlg.ShowModal();
-
-	wxString cfgResult = ResultToString( modalResult );
-	if( DisablerCtrl.IsChecked() && !cfgResult.IsEmpty() )
+	pxCheckBox*	DisablerCtrl = NULL;
+	if( cfg != NULL )
 	{
-		cfg->SetPath( L"/PopupDisablers" );
-		cfg->Write( disablerKey, L"disabled," + cfgResult );
-		cfg->SetPath( L"/" );
+		// Add an option that allows the user to disable this popup from showing again.
+		// (and if the config hasn't been initialized yet, then assume the dialog as non-disablable)
+
+		DisablerCtrl = new pxCheckBox(&confirmDlg, _("Do not show this dialog again."));
+
+		confirmDlg += 8;
+		confirmDlg += DisablerCtrl | wxSF.Centre();
+
+		if( buttons != MsgButtons().OK() )
+			pxSetToolTip(DisablerCtrl, _("Disables this popup and whatever response you select here will be automatically used from now on."));
+		else
+			pxSetToolTip(DisablerCtrl, _("The popup will not be shown again.  This setting can be undone from the settings panels."));
+
+	}
+
+	int modalResult = pxIssueConfirmation( confirmDlg, buttons );
+
+	if( cfg != NULL )
+	{
+		wxString cfgResult = ResultToString( modalResult );
+		if( DisablerCtrl->IsChecked() && !cfgResult.IsEmpty() )
+		{
+			cfg->SetPath( L"/PopupDisablers" );
+			cfg->Write( disablerKey, L"disabled," + cfgResult );
+			cfg->SetPath( L"/" );
+			cfg->Flush();
+		}
 	}
 	return modalResult;
 }
 
-Dialogs::ExtensibleConfirmation::ExtensibleConfirmation( wxWindow* parent, const ConfButtons& type, const wxString& title, const wxString& msg )
-	: wxDialogWithHelpers( parent, wxID_ANY, title, false )
-	, m_ExtensibleSizer( *new wxBoxSizer( wxVERTICAL ) )
-	, m_ButtonSizer( *new wxBoxSizer( wxHORIZONTAL ) )
+ModalButtonPanel::ModalButtonPanel( wxWindow* parent, const MsgButtons& buttons )
+	: wxPanelWithHelpers( parent, wxHORIZONTAL )
 {
-	m_Buttons		= type;
-	m_idealWidth	= 500;
-
-	SetSizer( new wxBoxSizer(wxVERTICAL) );
-
 	// Populate the Button Sizer.
 	// We prefer this over the built-in wxWidgets ButtonSizer stuff used for other types of
 	// dialogs because we offer more button types, and we don't want the MSW default behavior
 	// of right-justified buttons.
 
-	if( type.HasCustom() )
-		AddCustomButton( pxID_CUSTOM, type.GetCustomLabel() );
-	
+	if( buttons.HasCustom() )
+		AddCustomButton( pxID_CUSTOM, buttons.GetCustomLabel() );
+
 	// Order of wxID_RESET and custom button have been picked fairly arbitrarily, since there's
 	// no standard governing those.
 
-	#ifdef __WXGTK__
+#ifdef __WXGTK__
 	// GTK+ / Linux inverts OK/CANCEL order -- cancel / no first, OK / Yes later. >_<
-	if( type.HasCancel() )
+	if( buttons.HasCancel() )
 		AddActionButton( wxID_CANCEL );
 
-	if( type.HasNo() )
+	if( buttons.HasNo() )
 	{
 		AddActionButton( wxID_NO );
-		if( type.AllowsToAll() ) AddActionButton( wxID_NOTOALL );
+		if( buttons.AllowsToAll() ) AddActionButton( wxID_NOTOALL );
 	}
-	if( type.HasOK() || type.HasYes() )			// Extra space between Affirm and Cancel Actions
-		m_ButtonSizer.Add(0, 0, 1, wxEXPAND, 0);
-	#endif
 
-	if( type.HasOK() )
+	if( buttons.HasIgnore() )
+		AddCustomButton( wxID_IGNORE, _("Ignore") );
+
+	if( buttons.HasOK() || buttons.HasYes() )			// Extra space between Affirm and Cancel Actions
+		GetSizer()->Add(0, 0, 1, wxEXPAND, 0);
+#endif
+
+	if( buttons.HasOK() )
 		AddActionButton( wxID_OK );
 
-	if( type.HasYes() )
+	if( buttons.HasYes() )
 	{
 		AddActionButton( wxID_YES );
-		if( type.AllowsToAll() )
+		if( buttons.AllowsToAll() )
 			AddActionButton( wxID_YESTOALL );
 	}
 
-	if( type.HasReset() )
+#ifdef __WXGTK__
+	if( buttons.HasRetry() )
+		AddActionButton( wxID_RETRY );
+
+	if( buttons.HasAbort() )
+		AddActionButton( wxID_ABORT );
+#else
+	if( buttons.HasAbort() )
+		AddActionButton( wxID_ABORT );
+
+	if( buttons.HasRetry() )
+		AddActionButton( wxID_RETRY );
+#endif
+
+	if( buttons.HasReset() )
 		AddCustomButton( wxID_RESET, _("Reset") );
 
-	if( type.HasClose() )
+	if( buttons.HasClose() )
 		AddActionButton( wxID_CLOSE );
 
-	#ifndef __WXGTK__
-	if( type.HasNo() || type.HasCancel() )		// Extra space between Affirm and Cancel Actions
-		m_ButtonSizer.Add(0, 0, 1, wxEXPAND, 0);
-
-	if( type.HasNo() )
+#ifndef __WXGTK__
+	if( buttons.HasNo() )
 	{
 		AddActionButton( wxID_NO );
-		if( type.AllowsToAll() )
+		if( buttons.AllowsToAll() )
 			AddActionButton( wxID_NOTOALL );
 	}
 
-	if( type.HasCancel() )
+	if( buttons.HasIgnore() )
+		AddCustomButton( wxID_IGNORE, _("Ignore") );
+
+	if( buttons.HasCancel() )
 		AddActionButton( wxID_CANCEL );
-	#endif
-
-	// --------------------------------
-	//    Finalize Sizers and Layout
-	// --------------------------------
-
-	// Add the message padded some (StdCenter gives us a 5 pt padding).  Helps emphasize it a bit.
-	wxBoxSizer& msgPadSizer( *new wxBoxSizer(wxVERTICAL) );
-	msgPadSizer += Heading( msg );
-
-	*this	+= msgPadSizer			| pxSizerFlags::StdCenter();
-	*this	+= m_ExtensibleSizer	| pxCentre;
-	*this	+= m_ButtonSizer		| pxSizerFlags::StdCenter();
-
-	Fit();
-	CenterOnScreen();
+#endif
 }
 
-void Dialogs::ExtensibleConfirmation::OnActionButtonClicked( wxCommandEvent& evt )
+void ModalButtonPanel::OnActionButtonClicked( wxCommandEvent& evt )
 {
-	EndModal( evt.GetId() );
+	evt.Skip();
+	wxWindow* toplevel = wxGetTopLevelParent( this );
+	if( toplevel != NULL && wxIsKindOf(toplevel, wxDialog) )
+		((wxDialog*)toplevel)->EndModal( evt.GetId() );
 }
 
-void Dialogs::ExtensibleConfirmation::AddCustomButton( wxWindowID id, const wxString& label )
+void ModalButtonPanel::AddCustomButton( wxWindowID id, const wxString& label )
 {
-	m_ButtonSizer.Add( new wxButton( this, id, label ), pxSizerFlags::StdButton() )->SetProportion( 6 );
-	Connect( id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ExtensibleConfirmation::OnActionButtonClicked ) );
+	*this += new wxButton( this, id, label ) | StdButton().Proportion(6);
+	Connect( id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ModalButtonPanel::OnActionButtonClicked ) );
 }
 
-void Dialogs::ExtensibleConfirmation::AddActionButton( wxWindowID id )
+// This is for buttons that are defined internally by wxWidgets, such as wxID_CANCEL, wxID_ABORT, etc.
+// wxWidgets will assign the labels and stuff for us. :D
+void ModalButtonPanel::AddActionButton( wxWindowID id )
 {
-	m_ButtonSizer.Add( new wxButton( this, id ), pxSizerFlags::StdButton() )->SetProportion( 6 );
-	Connect( id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ExtensibleConfirmation::OnActionButtonClicked ) );
+	*this += new wxButton( this, id ) | StdButton().Proportion(6);
+	Connect( id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ModalButtonPanel::OnActionButtonClicked ) );
 }
 
diff --git a/pcsx2/gui/Dialogs/FirstTimeWizard.cpp b/pcsx2/gui/Dialogs/FirstTimeWizard.cpp
index 22704c082b..5c852abc3f 100644
--- a/pcsx2/gui/Dialogs/FirstTimeWizard.cpp
+++ b/pcsx2/gui/Dialogs/FirstTimeWizard.cpp
@@ -22,6 +22,7 @@
 #include <wx/file.h>
 
 using namespace Panels;
+using namespace pxSizerFlags;
 
 template< typename T >
 static T& MakeWizWidget( int pageid, wxWizardPage* src )
@@ -48,8 +49,6 @@ Panels::SettingsDirPickerPanel::SettingsDirPickerPanel( wxWindow* parent ) :
 			), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE
 		), wxSizerFlags().Expand().Border( wxBOTTOM, 6 )
 	);
-
-	//SetSizerAndFit( GetSizer(), false );
 }
 
 // ----------------------------------------------------------------------------
@@ -58,24 +57,22 @@ FirstTimeWizard::UsermodePage::UsermodePage( wxWizard* parent ) :
 {
 	SetSizer( new wxBoxSizer( wxVERTICAL ) );
 
-	wxPanelWithHelpers* panel = new wxPanelWithHelpers( this, wxVERTICAL );
-	panel->SetIdealWidth( 640 );
-	wxSizer& s_panel( *panel->GetSizer() );
+	wxPanelWithHelpers& panel( *new wxPanelWithHelpers( this, wxVERTICAL ) );
+	panel.SetIdealWidth( 640 );
 
-	m_dirpick_settings	= new SettingsDirPickerPanel( panel );
-	m_panel_LangSel		= new LanguageSelectionPanel( panel );
-	m_panel_UserSel		= new UsermodeSelectionPanel( panel );
+	m_dirpick_settings	= new SettingsDirPickerPanel( &panel );
+	m_panel_LangSel		= new LanguageSelectionPanel( &panel );
+	m_panel_UserSel		= new UsermodeSelectionPanel( &panel );
 
-	(new pxStaticHeading( panel, _("PCSX2 is starting from a new or unknown folder and needs to be configured.") ))
-		->AddTo( s_panel );
+	panel += panel.Heading(_("PCSX2 is starting from a new or unknown folder and needs to be configured."));
 
-	s_panel.Add( m_panel_LangSel, pxSizerFlags::StdCenter() );
-	s_panel.Add( m_panel_UserSel, wxSizerFlags().Expand().Border( wxALL, 8 ) );
+	panel += m_panel_LangSel		| StdCenter();
+	panel += m_panel_UserSel		| pxExpand.Border( wxALL, 8 );
 
-	s_panel.AddSpacer( 6 );
-	s_panel.Add( m_dirpick_settings, pxSizerFlags::SubGroup() );
+	panel += 6;
+	panel += m_dirpick_settings		| SubGroup();
 
-	GetSizer()->Add( panel, wxSizerFlags().Expand() );
+	panel += panel					| pxExpand;
 
 	Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED,	wxCommandEventHandler(FirstTimeWizard::UsermodePage::OnUsermodeChanged) );
 }
@@ -98,14 +95,13 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent )
 	, m_panel_BiosSel	( MakeWizWidget<BiosSelectorPanel>( 2, &m_page_bios ) )
 {
 	// Page 2 - Plugins Panel
-	wxBoxSizer& pluginSizer( *new wxBoxSizer( wxVERTICAL ) );
-	pluginSizer.Add( &m_panel_PluginSel, pxSizerFlags::StdExpand() );
-	m_page_plugins.SetSizer( &pluginSizer );
-
 	// Page 3 - Bios Panel
-	wxBoxSizer& biosSizer( *new wxBoxSizer( wxVERTICAL ) );
-	biosSizer.Add( &m_panel_BiosSel, pxSizerFlags::StdExpand() );
-	m_page_bios.SetSizer( &biosSizer );
+
+	m_page_plugins.	SetSizer( new wxBoxSizer( wxVERTICAL ) );
+	m_page_bios.	SetSizer( new wxBoxSizer( wxVERTICAL ) );
+
+	m_page_plugins	+= m_panel_PluginSel		| StdExpand();
+	m_page_bios		+= m_panel_BiosSel			| StdExpand();
 
 	// Assign page indexes as client data
 	m_page_usermode.SetClientData	( (void*)0 );
@@ -117,8 +113,13 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent )
 	m_page_usermode.SetNext	( &m_page_plugins );
 	m_page_plugins.SetNext	( &m_page_bios );
 
-	GetPageAreaSizer()->Add( &m_page_usermode );
-	GetPageAreaSizer()->Add( &m_page_plugins );
+	GetPageAreaSizer() += m_page_usermode;
+	GetPageAreaSizer() += m_page_plugins;
+
+	// this doesn't descent from wxDialogWithHelpers, so we need to explicitly
+	// fit and center it. :(
+
+	Fit();
 	CenterOnScreen();
 
 	Connect( wxEVT_WIZARD_PAGE_CHANGED,		wxWizardEventHandler( FirstTimeWizard::OnPageChanged ) );
diff --git a/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp b/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp
index 569118a202..4f5557c661 100644
--- a/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp
+++ b/pcsx2/gui/Dialogs/ImportSettingsDialog.cpp
@@ -18,8 +18,10 @@
 
 #include "ModalPopups.h"
 
+using namespace pxSizerFlags;
+
 Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent )
-	: wxDialogWithHelpers( parent, wxID_ANY, _("Import Existing Settings?"), false )
+	: wxDialogWithHelpers( parent, _("Import Existing Settings?"), wxVERTICAL )
 {
 	m_idealWidth = 440;
 
@@ -28,7 +30,6 @@ Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent )
 		L"Would you like to import these settings or overwrite them with PCSX2 default values?"
 		L"\n\n(or press Cancel to select a different settings folder)" )
 	);
-	heading->SetMinSize( wxSize( m_idealWidth-8, wxDefaultCoord ) );
 
 	wxBoxSizer& s_buttons = *new wxBoxSizer( wxHORIZONTAL );
 	wxButton* b_import	= new wxButton( this, wxID_ANY, _("Import") );
@@ -37,19 +38,16 @@ Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent )
 	// --------------------------------------------------------------------
 	// Layout Some Shizat...
 
-	wxBoxSizer& sizer( *new wxBoxSizer( wxVERTICAL ) );
+	s_buttons += b_import	| StdButton();
+	s_buttons += 16;
+	s_buttons += b_over		| StdButton();
+	s_buttons += 16;
+	s_buttons += new wxButton( this, wxID_CANCEL ) | StdButton();
 
-	s_buttons.Add( b_import,pxSizerFlags::StdButton() );
-	s_buttons.AddSpacer( 16 );
-	s_buttons.Add( b_over,	pxSizerFlags::StdButton() );
-	s_buttons.AddSpacer( 16 );
-	s_buttons.Add( new wxButton( this, wxID_CANCEL ), pxSizerFlags::StdButton() );
-
-	sizer.AddSpacer( 4 );
-	heading->AddTo( sizer );
-	sizer.AddSpacer( 12 );
-	sizer.Add( &s_buttons, pxSizerFlags::StdCenter() );
-	SetSizerAndFit( &sizer );
+	*this += 4;
+	*this += heading;
+	*this += 12;
+	*this += &s_buttons		| StdCenter();
 
 	Connect( b_import->GetId(),	wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ImportSettingsDialog::OnImport_Click) );
 	Connect( b_over->GetId(),	wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ImportSettingsDialog::OnOverwrite_Click) );
diff --git a/pcsx2/gui/Dialogs/LogOptionsDialog.cpp b/pcsx2/gui/Dialogs/LogOptionsDialog.cpp
index 0350813702..68c60b09a6 100644
--- a/pcsx2/gui/Dialogs/LogOptionsDialog.cpp
+++ b/pcsx2/gui/Dialogs/LogOptionsDialog.cpp
@@ -21,9 +21,11 @@
 
 using namespace Panels;
 
-Dialogs::LogOptionsDialog::LogOptionsDialog( wxWindow* parent, int id )
-	: wxDialogWithHelpers( parent, id, _("High Volume Logging"), true )
+Dialogs::LogOptionsDialog::LogOptionsDialog( wxWindow* parent )
+	: wxDialogWithHelpers( parent, _("Trace Logging"), true )
 {
+	SetName( GetNameStatic() );
+
 	m_idealWidth = 480;
 
 	wxBoxSizer& mainsizer = *new wxBoxSizer( wxVERTICAL );
diff --git a/pcsx2/gui/Dialogs/LogOptionsDialog.h b/pcsx2/gui/Dialogs/LogOptionsDialog.h
index e2ac7f8708..35f77ae71a 100644
--- a/pcsx2/gui/Dialogs/LogOptionsDialog.h
+++ b/pcsx2/gui/Dialogs/LogOptionsDialog.h
@@ -28,8 +28,11 @@ namespace Dialogs {
 class LogOptionsDialog: public wxDialogWithHelpers
 {
 public:
-	LogOptionsDialog( wxWindow* parent=NULL, int id=DialogId_LogOptions );
+	LogOptionsDialog( wxWindow* parent=NULL );
+	virtual ~LogOptionsDialog() throw() { }
 	
+	static const wxChar* GetNameStatic() { return L"Dialog:TraceLogSettings"; }
+
 protected:
 	void OnOk_Click( wxCommandEvent& evt );
 	void OnApply_Click( wxCommandEvent& evt );
diff --git a/pcsx2/gui/Dialogs/ModalPopups.h b/pcsx2/gui/Dialogs/ModalPopups.h
index 18e01251a5..0433852978 100644
--- a/pcsx2/gui/Dialogs/ModalPopups.h
+++ b/pcsx2/gui/Dialogs/ModalPopups.h
@@ -66,7 +66,7 @@ protected:
 	virtual void OnDoubleClicked( wxCommandEvent& evt );
 };
 
-class ConfButtons
+class MsgButtons
 {
 protected:
 	BITFIELD32()
@@ -87,29 +87,29 @@ protected:
 	wxString m_CustomLabel;
 
 public:
-	ConfButtons() : bitset( 0 ) { }
+	MsgButtons() : bitset( 0 ) { }
 
-	ConfButtons& OK()		{ m_OK			= true; return *this; }
-	ConfButtons& Cancel()	{ m_Cancel		= true; return *this; }
-	ConfButtons& Apply()	{ m_Apply		= true; return *this; }
-	ConfButtons& Yes()		{ m_Yes			= true; return *this; }
-	ConfButtons& No()		{ m_No			= true; return *this; }
-	ConfButtons& ToAll()	{ m_AllowToAll	= true; return *this; }
+	MsgButtons& OK()		{ m_OK			= true; return *this; }
+	MsgButtons& Cancel()	{ m_Cancel		= true; return *this; }
+	MsgButtons& Apply()		{ m_Apply		= true; return *this; }
+	MsgButtons& Yes()		{ m_Yes			= true; return *this; }
+	MsgButtons& No()		{ m_No			= true; return *this; }
+	MsgButtons& ToAll()		{ m_AllowToAll	= true; return *this; }
 
-	ConfButtons& Abort()	{ m_Abort		= true; return *this; }
-	ConfButtons& Retry()	{ m_Retry		= true; return *this; }
-	ConfButtons& Ignore()	{ m_Ignore		= true; return *this; }
-	ConfButtons& Reset()	{ m_Reset		= true; return *this; }
-	ConfButtons& Close()	{ m_Close		= true; return *this; }
+	MsgButtons& Abort()		{ m_Abort		= true; return *this; }
+	MsgButtons& Retry()		{ m_Retry		= true; return *this; }
+	MsgButtons& Ignore()	{ m_Ignore		= true; return *this; }
+	MsgButtons& Reset()		{ m_Reset		= true; return *this; }
+	MsgButtons& Close()		{ m_Close		= true; return *this; }
 
-	ConfButtons& Custom( const wxString& label)
+	MsgButtons& Custom( const wxString& label)
 	{
 		m_CustomLabel = label;
 		return *this;
 	}
 
-	ConfButtons& OKCancel()	{ m_OK = m_Cancel = true; return *this; }
-	ConfButtons& YesNo()	{ m_Yes = m_No = true; return *this; }
+	MsgButtons& OKCancel()	{ m_OK = m_Cancel = true; return *this; }
+	MsgButtons& YesNo()		{ m_Yes = m_No = true; return *this; }
 		
 	bool HasOK() const		{ return m_OK; }
 	bool HasCancel() const	{ return m_Cancel; }
@@ -128,29 +128,45 @@ public:
 	const wxString& GetCustomLabel() const { return m_CustomLabel; }
 
 	bool Allows( wxWindowID id ) const;
+	void SetBestFocus( wxWindow* dialog ) const;
+	void SetBestFocus( wxWindow& dialog ) const;
 
-	bool operator ==( const ConfButtons& right ) const
+	bool operator ==( const MsgButtons& right ) const
 	{
 		return OpEqu( bitset );
 	}
 
-	bool operator !=( const ConfButtons& right ) const
+	bool operator !=( const MsgButtons& right ) const
 	{
 		return !OpEqu( bitset );
 	}
 };
 
+class ModalButtonPanel : public wxPanelWithHelpers
+{
+public:
+	ModalButtonPanel( wxWindow* window, const MsgButtons& buttons );
+	virtual ~ModalButtonPanel() throw() { }
+
+	virtual void AddActionButton( wxWindowID id );
+	virtual void AddCustomButton( wxWindowID id, const wxString& label );
+
+	virtual void OnActionButtonClicked( wxCommandEvent& evt );
+};
+
 namespace Dialogs
 {
 	class AboutBoxDialog: public wxDialogWithHelpers
 	{
-	public:
-		AboutBoxDialog( wxWindow* parent=NULL, int id=DialogId_About );
-		virtual ~AboutBoxDialog() throw() {}
-
 	protected:
 		//wxStaticBitmap m_bitmap_logo;
 		wxStaticBitmap m_bitmap_dualshock;
+
+	public:
+		AboutBoxDialog( wxWindow* parent=NULL );
+		virtual ~AboutBoxDialog() throw() {}
+
+		static const wxChar* GetNameStatic() { return L"Dialog:AboutBox"; }
 	};
 
 	
@@ -161,7 +177,7 @@ namespace Dialogs
 		Panels::LanguageSelectionPanel* m_panel_langsel;
 
 	public:
-		PickUserModeDialog( wxWindow* parent, int id=wxID_ANY );
+		PickUserModeDialog( wxWindow* parent );
 		virtual ~PickUserModeDialog() throw() {}
 
 	protected:
@@ -180,42 +196,15 @@ namespace Dialogs
 		void OnOverwrite_Click( wxCommandEvent& evt );
 	};
 
-
-	// --------------------------------------------------------------------------------------
-	//  ExtensibleConfirmation Dialog
-	// --------------------------------------------------------------------------------------
-	// Purpose: This dialog is a simple framework for providing common popups that have three
-	// main sections of content:
-	//
-	//          [Upper Paragraph]
-	//     [Optional Interior Content]
-	//         [OK] [CANCEL] [ETC]
-	//
-	// The Upper Paragraph and buttons are specified in the constructor.  The Interior Content
-	// can be added by fetching the ExtensibleSizer provided by th created dialog.  Add your
-	// content, dance around a bit, call Fit(), and then ShowModal. :)
-
-	class ExtensibleConfirmation : public wxDialogWithHelpers
+	class AssertionDialog : public wxDialogWithHelpers
 	{
-	protected:
-		wxBoxSizer&		m_ExtensibleSizer;
-		wxBoxSizer&		m_ButtonSizer;
-
-		ConfButtons		m_Buttons;
-
 	public:
-		ExtensibleConfirmation( wxWindow* parent, const ConfButtons& type, const wxString& title, const wxString& msg );
-		virtual ~ExtensibleConfirmation() throw() {}
-
-		const ConfButtons& GetButtons() const { return m_Buttons; }
-		virtual wxBoxSizer& GetExtensibleSizer() const { return m_ExtensibleSizer; }
-
-	protected:
-		virtual void AddActionButton( wxWindowID id );
-		virtual void AddCustomButton( wxWindowID id, const wxString& label );
-		virtual void OnActionButtonClicked( wxCommandEvent& evt );
+		AssertionDialog( const wxString& text, const wxString& stacktrace );
+		virtual ~AssertionDialog() throw() {}
+		
+		
 	};
-
-	wxWindowID IssueConfirmation( ExtensibleConfirmation& confirmDlg, const wxString& disablerKey );
 }
 
+wxWindowID pxIssueConfirmation( wxDialogWithHelpers& confirmDlg, const MsgButtons& buttons );
+wxWindowID pxIssueConfirmation( wxDialogWithHelpers& confirmDlg, const MsgButtons& buttons, const wxString& disablerKey );
diff --git a/pcsx2/gui/Dialogs/PickUserModeDialog.cpp b/pcsx2/gui/Dialogs/PickUserModeDialog.cpp
index 9172a78a6e..45ae7d88cb 100644
--- a/pcsx2/gui/Dialogs/PickUserModeDialog.cpp
+++ b/pcsx2/gui/Dialogs/PickUserModeDialog.cpp
@@ -20,21 +20,17 @@
 
 using namespace Panels;
 
-Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id )
-	: wxDialogWithHelpers( parent, id, _("PCSX2 First Time configuration"), false )
+Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent )
+	: wxDialogWithHelpers( parent, _("PCSX2 First Time configuration"), wxVERTICAL )
 {
 	m_panel_usersel = new UsermodeSelectionPanel( this, false );
 	m_panel_langsel = new LanguageSelectionPanel( this );
 
-	SetSizer( new wxBoxSizer( wxVERTICAL ) );
-
 	*this	+= new pxStaticHeading( this, _("PCSX2 is starting from a new or unknown folder and needs to be configured.") );
 	*this	+= m_panel_langsel	| pxSizerFlags::StdCenter();
 	*this	+= m_panel_usersel	| wxSizerFlags().Expand().Border( wxALL, 8 );
 
 	AddOkCancel( *GetSizer() );
-	Fit();
-	CenterOnScreen();
 
 	Connect( wxID_OK,		wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PickUserModeDialog::OnOk_Click ) );
 	// TODO : Add a command event handler for language changes, that dynamically re-update contents of this window.
diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp
index e4cce855b4..679aaef28b 100644
--- a/pcsx2/gui/FrameForGS.cpp
+++ b/pcsx2/gui/FrameForGS.cpp
@@ -49,8 +49,9 @@ GSPanel::GSPanel( wxWindow* parent )
 	, m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener<int>	( this, OnSettingsApplied ) )
 	, m_HideMouseTimer( this )
 {
-	m_CursorShown = true;
-
+	m_CursorShown	= true;
+	m_HasFocus		= false;
+	
 	if ( !wxWindow::Create(parent, wxID_ANY) )
 		throw Exception::RuntimeError( "GSPanel constructor esplode!!" );
 
@@ -68,6 +69,9 @@ GSPanel::GSPanel( wxWindow* parent )
 	Connect( wxEVT_SIZE,			wxSizeEventHandler	(GSPanel::OnResize) );
 	Connect( wxEVT_KEY_DOWN,		wxKeyEventHandler	(GSPanel::OnKeyDown) );
 
+	Connect( wxEVT_SET_FOCUS,		wxFocusEventHandler(GSPanel::OnFocus) );
+	Connect( wxEVT_KILL_FOCUS,		wxFocusEventHandler(GSPanel::OnFocusLost) );
+
 	Connect(wxEVT_MIDDLE_DOWN,		wxMouseEventHandler(GSPanel::OnShowMouse) );
 	Connect(wxEVT_MIDDLE_UP,		wxMouseEventHandler(GSPanel::OnShowMouse) );
 	Connect(wxEVT_RIGHT_DOWN,		wxMouseEventHandler(GSPanel::OnShowMouse) );
@@ -131,6 +135,7 @@ void GSPanel::DoResize()
 
 void GSPanel::OnResize(wxSizeEvent& event)
 {
+	if( IsBeingDeleted() ) return;
 	DoResize();
 	//Console.Error( "Size? %d x %d", GetSize().x, GetSize().y );
 	//event.
@@ -144,12 +149,14 @@ void GSPanel::OnCloseWindow(wxCloseEvent& evt)
 
 void GSPanel::OnShowMouse( wxMouseEvent& evt )
 {
+	if( IsBeingDeleted() ) return;
 	evt.Skip();
 	DoShowMouse();
 }
 
 void GSPanel::OnHideMouseTimeout( wxTimerEvent& evt )
 {
+	if( IsBeingDeleted() || !m_HasFocus ) return;
 	if( CoreThread.GetExecutionMode() != SysThreadBase::ExecMode_Opened ) return;
 
 	SetCursor( wxCursor( wxCURSOR_BLANK ) );
@@ -180,6 +187,26 @@ void GSPanel::OnKeyDown( wxKeyEvent& evt )
 	}
 }
 
+void GSPanel::OnFocus( wxFocusEvent& evt )
+{
+	evt.Skip();
+	m_HasFocus = true;
+	
+	if( g_Conf->GSWindow.AlwaysHideMouse )
+	{
+		SetCursor( wxCursor(wxCURSOR_BLANK) );
+		m_CursorShown = false;
+	}
+	else
+		DoShowMouse();
+}
+
+void GSPanel::OnFocusLost( wxFocusEvent& evt )
+{
+	evt.Skip();
+	m_HasFocus = false;
+	DoShowMouse();
+}
 
 void __evt_fastcall GSPanel::OnSettingsApplied( void* obj, int& evt )
 {
@@ -234,12 +261,18 @@ wxWindow* GSFrame::GetViewport()
 
 void GSFrame::OnActivate( wxActivateEvent& evt )
 {
+	if( IsBeingDeleted() ) return;
+
 	evt.Skip();
 	if( wxWindow* gsPanel = FindWindowByName(L"GSPanel") ) gsPanel->SetFocus();
 }
 
 void GSFrame::OnMove( wxMoveEvent& evt )
 {
+	if( IsBeingDeleted() ) return;
+
+	evt.Skip();
+
 	// evt.GetPosition() returns the client area position, not the window frame position.
 	if( !IsMaximized() && IsVisible() )
 		g_Conf->GSWindow.WindowPos	= GetScreenPosition();
diff --git a/pcsx2/gui/IniInterface.cpp b/pcsx2/gui/IniInterface.cpp
index 70ffce709b..6d32e03289 100644
--- a/pcsx2/gui/IniInterface.cpp
+++ b/pcsx2/gui/IniInterface.cpp
@@ -61,11 +61,7 @@ void IniInterface::Flush()
 IniScopedGroup::IniScopedGroup( IniInterface& mommy, const wxString& group ) :
 	m_mom( mommy )
 {
-	if( IsDevBuild )
-	{
-		if( wxStringTokenize( group, L"/" ).Count() > 1 )
-			throw Exception::InvalidArgument( "Cannot nest more than one group deep per instance of IniScopedGroup." );
-	}
+	pxAssertDev( wxStringTokenize( group, L"/" ).Count() <= 1, L"Cannot nest more than one group deep per instance of IniScopedGroup." );
 	m_mom.SetPath( group );
 }
 
diff --git a/pcsx2/gui/IsoDropTarget.cpp b/pcsx2/gui/IsoDropTarget.cpp
index 9e68b7a4a1..738ab89124 100644
--- a/pcsx2/gui/IsoDropTarget.cpp
+++ b/pcsx2/gui/IsoDropTarget.cpp
@@ -38,10 +38,9 @@ bool IsoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filen
 
 	if( filenames.GetCount() > 1 )
 	{
-		Dialogs::ExtensibleConfirmation( m_WindowBound, ConfButtons().Cancel(),
-			_("Drag and Drop Error"),
-			_("It is an error to drop multiple files onto a PCSX2 window.  One at a time please, thank you.")
-		);
+		wxDialogWithHelpers dialog( m_WindowBound, _("Drag and Drop Error"), wxVERTICAL );
+		dialog += dialog.Heading( _("It is an error to drop multiple files onto a PCSX2 window.  One at a time please, thank you.") );
+		pxIssueConfirmation( dialog, MsgButtons().Cancel() );
 		return false;
 	}
 
@@ -69,13 +68,14 @@ bool IsoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filen
 		bool confirmed = true;
 		if( SysHasValidState() )
 		{
-			Dialogs::ExtensibleConfirmation dialog( m_WindowBound, ConfButtons().Reset().Cancel(),
-				_("Confirm PS2 Reset"),
+			wxDialogWithHelpers dialog( m_WindowBound, _("Confirm PS2 Reset"), wxVERTICAL );
+			
+			dialog += dialog.Heading(
 				_("You have dropped the following ELF binary into PCSX2:\n\n") +
 				filenames[0] + L"\n\n" + GetMsg_ConfirmSysReset()
 			);
 
-			confirmed = (Dialogs::IssueConfirmation( dialog, L"DragDrop:BootELF" ) != wxID_CANCEL);
+			confirmed = (pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel(), L"DragDrop:BootELF" ) != wxID_CANCEL);
 		}
 
 		if( confirmed )
@@ -111,14 +111,14 @@ bool IsoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filen
 
 		if( SysHasValidState() )
 		{
-			Dialogs::ExtensibleConfirmation dialog( m_WindowBound, ConfButtons().Reset().Cancel().Custom(_("Swap Disc")),
-				_("Confirm PS2 Reset"),
-				_("You have dropped the following ISO image into PCSX2:\n\n") +
+			wxDialogWithHelpers dialog( m_WindowBound, _("Confirm PS2 Reset"), wxVERTICAL );
+						
+			dialog += dialog.Heading(_("You have dropped the following ISO image into PCSX2:\n\n") +
 				filenames[0] + L"\n\n" +
 				_("Do you want to swap discs or boot the new image (via system reset)?")
 			);
 
-			result = Dialogs::IssueConfirmation( dialog, L"DragDrop:BootIso" );
+			result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc")), L"DragDrop:BootIso" );
 		}
 
 		if( result != wxID_CANCEL )
diff --git a/pcsx2/gui/MainFrame.h b/pcsx2/gui/MainFrame.h
index fbf8a39093..57f3355846 100644
--- a/pcsx2/gui/MainFrame.h
+++ b/pcsx2/gui/MainFrame.h
@@ -31,6 +31,7 @@ protected:
 	EventListenerBinding<int>	m_Listener_SettingsApplied;
 	wxTimer						m_HideMouseTimer;
 	bool						m_CursorShown;
+	bool						m_HasFocus;
 
 public:
 	GSPanel( wxWindow* parent );
@@ -49,6 +50,8 @@ protected:
 	void OnShowMouse( wxMouseEvent& evt );
 	void OnHideMouseTimeout( wxTimerEvent& evt );
 	void OnKeyDown( wxKeyEvent& evt );
+	void OnFocus( wxFocusEvent& evt );
+	void OnFocusLost( wxFocusEvent& evt );
 };
 
 // --------------------------------------------------------------------------------------
diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp
index 49b0fad77c..cac19d967d 100644
--- a/pcsx2/gui/MainMenuClicks.cpp
+++ b/pcsx2/gui/MainMenuClicks.cpp
@@ -28,6 +28,15 @@
 
 using namespace Dialogs;
 
+template<typename DialogType>
+void AppOpenDialog( wxWindow* parent )
+{
+	if( wxWindow* window = wxFindWindowByName( DialogType::GetNameStatic() ) )
+		window->SetFocus();
+	else
+		(new DialogType( parent ))->Show();
+}
+
 extern wxString GetMsg_ConfirmSysReset();
 
 void MainEmuFrame::SaveEmuOptions()
@@ -41,12 +50,12 @@ void MainEmuFrame::SaveEmuOptions()
 
 void MainEmuFrame::Menu_ConfigSettings_Click(wxCommandEvent &event)
 {
-	Dialogs::ConfigurationDialog( this ).ShowModal();
+	AppOpenDialog<ConfigurationDialog>( this );
 }
 
 void MainEmuFrame::Menu_SelectBios_Click(wxCommandEvent &event)
 {
-	Dialogs::BiosSelectorDialog( this ).ShowModal();
+	AppOpenDialog<BiosSelectorDialog>( this );
 }
 
 void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event )
@@ -118,11 +127,14 @@ void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
 			// User has an iso selected from a previous run, but it doesn't exist anymore.
 			// Issue a courtesy popup and then an Iso Selector to choose a new one.
 			
-			Dialogs::ExtensibleConfirmation( this, ConfButtons().OK(), _("ISO file not found!"),
+			wxDialogWithHelpers dialog( this, _("ISO file not found!"), wxVERTICAL );
+			dialog += dialog.Heading(
 				_("An error occurred while trying to open the file:\n\n") + g_Conf->CurrentIso + L"\n\n" + 
 				_("Error: The configured ISO file does not exist.  Click OK to select a new ISO source for CDVD.")
-			).ShowModal();
-			
+			);
+
+			pxIssueConfirmation( dialog, MsgButtons().OK() );
+
 			selector = true;
 		}
 		
@@ -141,11 +153,9 @@ void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
 
 	if( SysHasValidState() )
 	{
-		ExtensibleConfirmation dialog( this, ConfButtons().Yes().Cancel(),
-			_("Confirm PS2 Reset"), GetMsg_ConfirmSysReset()
-		);
-		
-		bool confirmed = (IssueConfirmation( dialog, L"BootCdvd:ConfirmReset" ) != wxID_CANCEL);
+		wxDialogWithHelpers dialog( this, _("Confirm PS2 Reset"), wxVERTICAL );
+		dialog += dialog.Heading( GetMsg_ConfirmSysReset() );
+		bool confirmed = (pxIssueConfirmation( dialog, MsgButtons().Yes().Cancel(), L"BootCdvd:ConfirmReset" ) != wxID_CANCEL);
 
 		if( !confirmed )
 		{
@@ -290,7 +300,7 @@ void MainEmuFrame::Menu_Debug_MemoryDump_Click(wxCommandEvent &event)
 
 void MainEmuFrame::Menu_Debug_Logging_Click(wxCommandEvent &event)
 {
-	LogOptionsDialog( this, wxID_ANY ).ShowModal();
+	AppOpenDialog<LogOptionsDialog>( this );
 }
 
 void MainEmuFrame::Menu_ShowConsole(wxCommandEvent &event)
@@ -316,5 +326,5 @@ void MainEmuFrame::Menu_PrintCDVD_Info(wxCommandEvent &event)
 
 void MainEmuFrame::Menu_ShowAboutBox(wxCommandEvent &event)
 {
-	AboutBoxDialog( this, wxID_ANY ).ShowModal();
+	AppOpenDialog<AboutBoxDialog>( this );
 }
diff --git a/pcsx2/gui/MessageBoxes.cpp b/pcsx2/gui/MessageBoxes.cpp
index 40d78b4e25..887d95f0d2 100644
--- a/pcsx2/gui/MessageBoxes.cpp
+++ b/pcsx2/gui/MessageBoxes.cpp
@@ -15,130 +15,277 @@
 
 #include "PrecompiledHeader.h"
 #include "App.h"
+#include "Dialogs/ModalPopups.h"
 
 DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
-DEFINE_EVENT_TYPE( pxEVT_CallStackBox );
+DEFINE_EVENT_TYPE( pxEVT_ASSERTION );
 
 using namespace Threading;
+using namespace pxSizerFlags;
 
-// Thread Safety: Must be called from the GUI thread ONLY.
-static int pxMessageDialog( const wxString& content, const wxString& caption, long flags )
+// Thread Safety: Must be called from the GUI thread ONLY.  Will assert otherwise.
+//
+// [TODO] Add support for icons?
+//
+static int pxMessageDialog( const wxString& caption, const wxString& content, const MsgButtons& buttons )
 {
-	if( IsDevBuild && !wxThread::IsMain() )
-		throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
+	if( !AffinityAssert_AllowFromMain() ) return wxID_CANCEL;
 
-	// fixme: If the emulator is currently active and is running in fullscreen mode, then we
-	// need to either:
+	// fixme: If the emulator is currently active and is running in exclusive mode (forced
+	// fullscreen), then we need to either:
 	//  1) Exit fullscreen mode before issuing the popup.
 	//  2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it.
 	//
 	// And in either case the emulation should be paused/suspended for the user.
 
-	return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
+	wxDialogWithHelpers dialog( NULL, caption, wxVERTICAL );
+	dialog += dialog.Heading( content );
+	return pxIssueConfirmation( dialog, buttons );
 }
 
-// Thread Safety: Must be called from the GUI thread ONLY.
-// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and
-// uses fixed-width (modern) fonts.
-static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags )
+class BaseMessageBoxEvent : public wxEvent
 {
-	if( IsDevBuild && !wxThread::IsMain() )
-		throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
+	DECLARE_DYNAMIC_CLASS_NO_ASSIGN(BaseMessageBoxEvent)
 
-	return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
-}
+protected:
+	MsgboxEventResult*	m_Instdata;
+	wxString			m_Content;
+
+public:
+	explicit BaseMessageBoxEvent( int msgtype=pxEVT_MSGBOX, const wxString& content=wxEmptyString )
+		: wxEvent( 0, msgtype )
+		, m_Content( content )
+	{
+		m_Instdata = NULL;
+	}
+
+	virtual ~BaseMessageBoxEvent() throw() { }
+	virtual BaseMessageBoxEvent *Clone() const { return new BaseMessageBoxEvent(*this); }
+
+	BaseMessageBoxEvent( MsgboxEventResult& instdata, const wxString& content )
+		: wxEvent( 0, pxEVT_MSGBOX )
+		, m_Instdata( &instdata )
+		, m_Content( content )
+	{
+	}
+
+	BaseMessageBoxEvent( const wxString& content )
+		: wxEvent( 0, pxEVT_MSGBOX )
+		, m_Instdata( NULL )
+		, m_Content( content )
+	{
+	}
+
+	BaseMessageBoxEvent( const BaseMessageBoxEvent& event )
+		: wxEvent( event )
+		, m_Instdata( event.m_Instdata )
+		, m_Content( event.m_Content )
+	{
+	}
+
+	BaseMessageBoxEvent& SetInstData( MsgboxEventResult& instdata )
+	{
+		m_Instdata = &instdata;
+		return *this;
+	}
+
+	// Thread Safety: Must be called from the GUI thread ONLY.
+	virtual void IssueDialog()
+	{
+		AffinityAssert_AllowFromMain();
+
+		int result = _DoDialog();
+
+		if( m_Instdata != NULL )
+		{
+			m_Instdata->result = result;
+			m_Instdata->WaitForMe.Post();
+		}
+	}
+
+protected:
+	virtual int _DoDialog() const
+	{
+		pxFailDev( "Abstract Base MessageBox Event." );
+		return wxID_CANCEL;
+	}
+};
 
 // --------------------------------------------------------------------------------------
 //  pxMessageBoxEvent
 // --------------------------------------------------------------------------------------
-class pxMessageBoxEvent : public wxEvent
+// This event type is used to transfer message boxes to the main UI thread, and return the
+// result of the box.  It's the only way a message box can be issued from non-main threads
+// with complete safety in wx2.8.
+//
+// For simplicity sake this message box only supports two basic designs.  The main design
+// is a generic message box with confirmation buttons of your choosing.  Additionally you
+// can specify a "scrollableContent" text string, which is added into a read-only richtext
+// control similar to the console logs and such.
+//
+// Future consideration: If wxWidgets 3.0 has improved thread safety, then it should probably
+// be reasonable for it to work with a more flexable model where the dialog can be created
+// on a child thread, passed to the main thread, where ShowModal() is run (keeping the nested
+// message pumps on the main thread where they belong).  But so far this is not possible,
+// because of various subtle issues in wx2.8 design.
+//
+class pxMessageBoxEvent : public BaseMessageBoxEvent
 {
-protected:
-	MsgboxEventResult&	m_Instdata;
-	wxString			m_Title;
-	wxString			m_Content;
-	long				m_Flags;
+	typedef BaseMessageBoxEvent _parent;
+	DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
 
+protected:
+	wxString			m_Title;
+	MsgButtons			m_Buttons;
+	
 public:
-	pxMessageBoxEvent()
-		: wxEvent( 0, pxEVT_MSGBOX )
-		, m_Instdata( *(MsgboxEventResult*)NULL )
-		, m_Title()
-		, m_Content()
+	pxMessageBoxEvent( int msgtype=pxEVT_MSGBOX )
+		: BaseMessageBoxEvent( msgtype )
 	{
-		m_Flags = 0;
 	}
 
-	pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags )
-		: wxEvent( 0, pxEVT_MSGBOX )
-		, m_Instdata( instdata )
+	virtual ~pxMessageBoxEvent() throw() { }
+	virtual pxMessageBoxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
+
+	pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, const MsgButtons& buttons )
+		: BaseMessageBoxEvent( instdata, content )
 		, m_Title( title )
-		, m_Content( content )
+		, m_Buttons( buttons )
+	{
+	}
+
+	pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons )
+		: BaseMessageBoxEvent( content )
+		, m_Title( title )
+		, m_Buttons( buttons )
 	{
-		m_Flags = flags;
 	}
 
 	pxMessageBoxEvent( const pxMessageBoxEvent& event )
-		: wxEvent( event )
-		, m_Instdata( event.m_Instdata )
+		: BaseMessageBoxEvent( event )
 		, m_Title( event.m_Title )
-		, m_Content( event.m_Content )
+		, m_Buttons( event.m_Buttons )
 	{
-		m_Flags = event.m_Flags;
 	}
 
-	// Thread Safety: Must be called from the GUI thread ONLY.
-	void DoTheDialog()
+	pxMessageBoxEvent& SetInstData( MsgboxEventResult& instdata )
 	{
-		int result;
-
-		if( m_id == pxEVT_MSGBOX )
-			result = pxMessageDialog( m_Content, m_Title, m_Flags );
-		else
-			result = pxCallstackDialog( m_Content, m_Title, m_Flags );
-		m_Instdata.result = result;
-		m_Instdata.WaitForMe.Post();
+		_parent::SetInstData( instdata );
+		return *this;
 	}
 
-	virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
-
-private:
-	DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
+protected:
+	virtual int _DoDialog() const
+	{
+		return pxMessageDialog( m_Content, m_Title, m_Buttons );
+	}
 };
 
-IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent )
+// --------------------------------------------------------------------------------------
+//  pxAssertionEvent
+// --------------------------------------------------------------------------------------
+class pxAssertionEvent : public BaseMessageBoxEvent
+{
+	typedef BaseMessageBoxEvent _parent;
+	DECLARE_DYNAMIC_CLASS_NO_ASSIGN( pxAssertionEvent )
+
+protected:
+	wxString	m_Stacktrace;
+
+public:
+	pxAssertionEvent()
+		: BaseMessageBoxEvent( pxEVT_ASSERTION )
+	{
+	}
+	
+	virtual ~pxAssertionEvent() throw() { }
+
+	virtual pxAssertionEvent *Clone() const { return new pxAssertionEvent(*this); }
+
+	pxAssertionEvent( MsgboxEventResult& instdata, const wxString& content, const wxString& trace )
+		: BaseMessageBoxEvent( pxEVT_ASSERTION )
+		, m_Stacktrace( trace )
+	{
+	}
+
+	pxAssertionEvent( const wxString& content, const wxString& trace )
+		: BaseMessageBoxEvent( pxEVT_ASSERTION, content )
+		, m_Stacktrace( trace )
+	{
+	}
+
+	pxAssertionEvent( const pxAssertionEvent& event )
+		: BaseMessageBoxEvent( event )
+		, m_Stacktrace( event.m_Stacktrace )
+	{
+	}
+
+	pxAssertionEvent& SetInstData( MsgboxEventResult& instdata )
+	{
+		_parent::SetInstData( instdata );
+		return *this;
+	}
+
+	pxAssertionEvent& SetStacktrace( const wxString& trace )
+	{
+		m_Stacktrace = trace;
+		return *this;
+	}
+
+protected:
+	virtual int _DoDialog() const
+	{
+		return Dialogs::AssertionDialog( m_Content, m_Stacktrace ).ShowModal();
+	}
+};
+
+IMPLEMENT_DYNAMIC_CLASS( BaseMessageBoxEvent, wxEvent )
+IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, BaseMessageBoxEvent )
+IMPLEMENT_DYNAMIC_CLASS( pxAssertionEvent, BaseMessageBoxEvent )
 
 namespace Msgbox
 {
-	// parameters:
-	//   flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
-	//
-	static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX )
+	static int ThreadedMessageBox( BaseMessageBoxEvent& evt )
+	{
+		MsgboxEventResult instdat;
+		evt.SetInstData( instdat );
+
+		if( wxThread::IsMain() )
+		{
+			// main thread can handle the message immediately.
+			wxGetApp().ProcessEvent( evt );
+		}
+		else
+		{
+			// Not on main thread, must post the message there for handling instead:
+			wxGetApp().AddPendingEvent( evt );
+			instdat.WaitForMe.WaitNoCancel();		// Important! disable cancellation since we're using local stack vars.
+		}
+		return instdat.result;
+	}
+
+	static int ThreadedMessageBox( const wxString& title, const wxString& content, const MsgButtons& buttons )
 	{
 		// must pass the message to the main gui thread, and then stall this thread, to avoid
 		// threaded chaos where our thread keeps running while the popup is awaiting input.
 
 		MsgboxEventResult instdat;
-		pxMessageBoxEvent tevt( instdat, title, content, flags );
+		pxMessageBoxEvent tevt( instdat, title, content, buttons );
 		wxGetApp().AddPendingEvent( tevt );
 		instdat.WaitForMe.WaitNoCancel();		// Important! disable cancellation since we're using local stack vars.
 		return instdat.result;
 	}
 
-	void OnEvent( pxMessageBoxEvent& evt )
-	{
-		evt.DoTheDialog();
-	}
-
 	// Pops up an alert Dialog Box with a singular "OK" button.
 	// Always returns false.
 	bool Alert( const wxString& text, const wxString& caption, int icon )
 	{
-		icon |= wxOK;
+		MsgButtons buttons( MsgButtons().OK() );
+
 		if( wxThread::IsMain() )
-			pxMessageDialog( text, caption, icon );
+			pxMessageDialog( caption, text, buttons );
 		else
-			ThreadedMessageBox( text, caption, icon );
+			ThreadedMessageBox( caption, text, buttons );
 		return false;
 	}
 
@@ -146,60 +293,40 @@ namespace Msgbox
 	// true if OK, false if cancel.
 	bool OkCancel( const wxString& text, const wxString& caption, int icon )
 	{
-		icon |= wxOK | wxCANCEL;
+		MsgButtons buttons( MsgButtons().OKCancel() );
+
 		if( wxThread::IsMain() )
 		{
-			return wxID_OK == pxMessageDialog( text, caption, icon );
+			return wxID_OK == pxMessageDialog( caption, text, buttons );
 		}
 		else
 		{
-			return wxID_OK == ThreadedMessageBox( text, caption, icon );
+			return wxID_OK == ThreadedMessageBox( caption, text, buttons );
 		}
 	}
 
 	bool YesNo( const wxString& text, const wxString& caption, int icon )
 	{
-		icon |= wxYES_NO;
-		if( wxThread::IsMain() )
-		{
-			return wxID_YES == pxMessageDialog( text, caption, icon );
-		}
-		else
-		{
-			return wxID_YES == ThreadedMessageBox( text, caption, icon );
-		}
-	}
-
-	// [TODO] : This should probably be a fancier looking dialog box with the stacktrace
-	// displayed inside a wxTextCtrl.
-	static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons )
-	{
-		buttons |= wxICON_STOP;
-
-		wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt );
+		MsgButtons buttons( MsgButtons().YesNo() );
 
 		if( wxThread::IsMain() )
 		{
-			return pxCallstackDialog( text, caption, buttons );
+			return wxID_YES == pxMessageDialog( caption, text, buttons );
 		}
 		else
 		{
-			return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox );
+			return wxID_YES == ThreadedMessageBox( caption, text, buttons );
 		}
 	}
 
 	int Assertion( const wxString& text, const wxString& stacktrace )
 	{
-		return CallStack( text, stacktrace,
-			L"\nDo you want to stop the program?"
-			L"\nOr press [Cancel] to suppress further assertions.",
-			L"PCSX2 Assertion Failure",
-			wxYES_NO | wxCANCEL
-		);
-	}
-
-	void Except( const Exception::BaseException& src )
-	{
-		CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK );
+		pxAssertionEvent tevt( text, stacktrace );
+		return ThreadedMessageBox( tevt );
 	}
 }
+
+void Pcsx2App::OnMessageBox( pxMessageBoxEvent& evt )
+{
+	evt.IssueDialog();
+}
diff --git a/pcsx2/gui/Panels/CpuPanel.cpp b/pcsx2/gui/Panels/CpuPanel.cpp
index dcecdc4e29..4af176ed6f 100644
--- a/pcsx2/gui/Panels/CpuPanel.cpp
+++ b/pcsx2/gui/Panels/CpuPanel.cpp
@@ -46,8 +46,8 @@ Panels::BaseAdvancedCpuOptions::BaseAdvancedCpuOptions( wxWindow* parent )
 
 	// Highlight Default Options:
 	
-	m_RoundModePanel->SetDefault( 3 );
-	m_ClampModePanel->SetDefault( 1 );
+	m_RoundModePanel->SetDefaultItem( 3 );
+	m_ClampModePanel->SetDefaultItem( 1 );
 
 	// ---------------------------------
 	//    The Fitting And Sizing Area
@@ -146,8 +146,8 @@ Panels::CpuPanelEE::CpuPanelEE( wxWindow* parent )
 	};
 
 	
-	m_panel_RecEE	= &(new pxRadioPanel( this, tbl_CpuTypes_EE ))->SetDefault( 1 );
-	m_panel_RecIOP	= &(new pxRadioPanel( this, tbl_CpuTypes_IOP ))->SetDefault( 1 );
+	m_panel_RecEE	= &(new pxRadioPanel( this, tbl_CpuTypes_EE ))->SetDefaultItem( 1 );
+	m_panel_RecIOP	= &(new pxRadioPanel( this, tbl_CpuTypes_IOP ))->SetDefaultItem( 1 );
 
 	m_panel_RecEE->Realize();
 	m_panel_RecIOP->Realize();
@@ -193,8 +193,8 @@ Panels::CpuPanelVU::CpuPanelVU( wxWindow* parent )
 		.SetToolTip(_("Useful for diagnosing bugs or clamping issues in the new mVU recompiler."))
 	};
 
-	m_panel_VU0 = &(new pxRadioPanel( this, tbl_CpuTypes_VU ))	->SetDefault( 1 );
-	m_panel_VU1 = &(new pxRadioPanel( this, tbl_CpuTypes_VU ))	->SetDefault( 1 );
+	m_panel_VU0 = &(new pxRadioPanel( this, tbl_CpuTypes_VU ))	->SetDefaultItem( 1 );
+	m_panel_VU1 = &(new pxRadioPanel( this, tbl_CpuTypes_VU ))	->SetDefaultItem( 1 );
 
 	m_panel_VU0->Realize();
 	m_panel_VU1->Realize();
@@ -233,6 +233,9 @@ void Panels::CpuPanelEE::Apply()
 
 void Panels::CpuPanelEE::OnSettingsChanged()
 {
+	m_panel_RecEE->Enable( x86caps.hasStreamingSIMD2Extensions );
+	m_panel_RecIOP->Enable( x86caps.hasStreamingSIMD2Extensions );
+
 	const Pcsx2Config::RecompilerOptions& recOps( g_Conf->EmuOptions.Cpu.Recompiler );
 	m_panel_RecEE->SetSelection( (int)recOps.EnableEE );
 	m_panel_RecIOP->SetSelection( (int)recOps.EnableIOP );
@@ -250,6 +253,12 @@ void Panels::CpuPanelVU::Apply()
 
 void Panels::CpuPanelVU::OnSettingsChanged()
 {
+	m_panel_VU0->EnableItem( 1, x86caps.hasStreamingSIMD2Extensions );
+	m_panel_VU0->EnableItem( 2, x86caps.hasStreamingSIMD2Extensions );
+
+	m_panel_VU1->EnableItem( 1, x86caps.hasStreamingSIMD2Extensions );
+	m_panel_VU1->EnableItem( 2, x86caps.hasStreamingSIMD2Extensions );
+
 	Pcsx2Config::RecompilerOptions& recOps( g_Conf->EmuOptions.Cpu.Recompiler );
 	if( recOps.UseMicroVU0 )
 		m_panel_VU0->SetSelection( recOps.EnableVU0 ? 1 : 0 );
diff --git a/pcsx2/gui/Panels/PluginSelectorPanel.cpp b/pcsx2/gui/Panels/PluginSelectorPanel.cpp
index 0e2a541f16..4f8229eede 100644
--- a/pcsx2/gui/Panels/PluginSelectorPanel.cpp
+++ b/pcsx2/gui/Panels/PluginSelectorPanel.cpp
@@ -16,6 +16,7 @@
 #include "PrecompiledHeader.h"
 #include "App.h"
 #include "Plugins.h"
+#include "SaveState.h"
 #include "Utilities/ScopedPtr.h"
 #include "ConfigurationPanels.h"
 #include "Dialogs/ModalPopups.h"
@@ -309,37 +310,43 @@ void Panels::PluginSelectorPanel::Apply()
 			break;
 	} while( ++pi, pi->shortname != NULL );
 
+	bool isSuspended = false;
+
 	if( pi->shortname != NULL )
 	{
 		if( CoreThread.IsRunning() )
 		{
 			// [TODO] : Post notice that this shuts down existing emulation, and may not safely recover.
-			Dialogs::ExtensibleConfirmation dialog( this, ConfButtons().OK().Cancel(),
-
-				_("Shutdown PS2 virtual machine?"),
-
-				pxE( ".Popup:PluginSelector:ConfirmShutdown",
-					L"Warning!  Changing plugins requires a complete shutdown and reset of the PS2 virtual machine. "
-					L"PCSX2 will attempt to save and restore the state, but if the newly selected plugins are "
-					L"incompatible the recovery may fail, and current progress will be lost."
-					L"\n\n"
-					L"Are you sure you want to apply settings now?"
-				)
-			);
+			wxDialogWithHelpers dialog( this, _("Shutdown PS2 virtual machine?"), wxVERTICAL );
 			
-			int result = Dialogs::IssueConfirmation( dialog, L"PluginSelector:ConfirmShutdown" );
+			dialog += dialog.Heading( pxE( ".Popup:PluginSelector:ConfirmShutdown",
+				L"Warning!  Changing plugins requires a complete shutdown and reset of the PS2 virtual machine. "
+				L"PCSX2 will attempt to save and restore the state, but if the newly selected plugins are "
+				L"incompatible the recovery may fail, and current progress will be lost."
+				L"\n\n"
+				L"Are you sure you want to apply settings now?"
+			) );
+
+			int result = pxIssueConfirmation( dialog, MsgButtons().OK().Cancel(), L"PluginSelector:ConfirmShutdown" );
 
 			if( result == wxID_CANCEL )
 				throw Exception::CannotApplySettings( this, "Cannot apply settings: canceled by user because plugins changed while the emulation state was active.", false );
+
+			// FIXME : We only actually have to save plugins here, except the recovery code
+			// in SysCoreThread isn't quite set up yet to handle that (I think...) --air
+
+			isSuspended = CoreThread.Suspend();
+			StateCopy_FreezeToMem_Blocking();
 		}
 
-		sApp.SysReset();
+		// Don't use SysShutdown, it clears the StateCopy.
+		CoreThread.Cancel();
+		wxGetApp().m_CorePlugins = NULL;
 	}
 
 	if( !wxGetApp().m_CorePlugins )
 	{
-		try
-		{
+		try {
 			LoadPluginsImmediate();
 		}
 		catch( Exception::PluginError& ex )
@@ -359,6 +366,8 @@ void Panels::PluginSelectorPanel::Apply()
 			);
 		}
 	}
+
+	if( isSuspended ) CoreThread.Resume();
 }
 
 void Panels::PluginSelectorPanel::CancelRefresh()
@@ -591,6 +600,7 @@ void Panels::PluginSelectorPanel::EnumThread::ExecuteTaskInThread()
 {
 	DevCon.WriteLn( "Plugin Enumeration Thread started..." );
 
+	Sleep( 15 );		// give the window some time to paint.
 	YieldToMain();
 
 	for( int curidx=0; curidx < m_master.FileCount(); ++curidx )
diff --git a/pcsx2/gui/RecentIsoList.cpp b/pcsx2/gui/RecentIsoList.cpp
index d621dd23e7..31e10b8dd3 100644
--- a/pcsx2/gui/RecentIsoList.cpp
+++ b/pcsx2/gui/RecentIsoList.cpp
@@ -26,7 +26,7 @@
 
 RecentIsoManager::RecentIsoManager( wxMenu* menu )
 	: m_Menu( menu )
-	, m_MaxLength( g_Conf->RecentFileCount )
+	, m_MaxLength( g_Conf->RecentIsoCount )
 	, m_Listener_SettingsLoadSave	( wxGetApp().Source_SettingsLoadSave(), EventListener<IniInterface>( this, OnSettingsLoadSave ) )
 	, m_Listener_SettingsApplied	( wxGetApp().Source_SettingsApplied(), EventListener<int>( this, OnSettingsApplied ) )
 {
@@ -166,7 +166,7 @@ void RecentIsoManager::DoSettingsLoadSave( IniInterface& ini )
 	{
 		RemoveAllFromMenu();
 		
-		m_MaxLength = g_Conf->RecentFileCount;
+		m_MaxLength = g_Conf->RecentIsoCount;
 		IniScopedGroup groupie( ini, L"RecentIso" );
 		for( uint i=0; i<m_MaxLength; ++i )
 		{
diff --git a/pcsx2/gui/i18n.cpp b/pcsx2/gui/i18n.cpp
index b30487e32c..38269d617b 100644
--- a/pcsx2/gui/i18n.cpp
+++ b/pcsx2/gui/i18n.cpp
@@ -141,7 +141,7 @@ const wxChar* __fastcall pxGetTranslation( const wxChar* message )
 		if( wxStrlen( message ) > 96 )
 		{
 			Console.Warning( "pxGetTranslation: Long message detected, maybe use pxE() instead?" );
-			Console.Indent().WriteLn( Color_Green, L"Message: %s", message );
+			Console.WriteLn( Color_Green, L"Message: %s", message );
 		}
 	}
 	return wxGetTranslation( message );
diff --git a/pcsx2/gui/pxLogTextCtrl.cpp b/pcsx2/gui/pxLogTextCtrl.cpp
index 861e755742..7879af1ecc 100644
--- a/pcsx2/gui/pxLogTextCtrl.cpp
+++ b/pcsx2/gui/pxLogTextCtrl.cpp
@@ -31,7 +31,6 @@ void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxComma
 
 	if( mframe->HasWriteLock() ) return;
 	::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
-	mframe->m_win32_StupidRefreshTricks = 0;
 #endif
 }
 
@@ -45,7 +44,6 @@ void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginE
 
 	if( mframe->HasWriteLock() ) return;
 	::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
-	mframe->m_win32_StupidRefreshTricks = 0;
 #endif
 }
 
@@ -58,10 +56,11 @@ pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent )
 	, m_Listener_CorePluginStatus	( wxGetApp().Source_CorePluginStatus(), EventListener<PluginEventType>	( this, OnCorePluginStatusChanged ) )
 {
 #ifdef __WXMSW__
-	m_win32_StupidRefreshTricks	= 0;
-	m_win32_LinesPerScroll		= 10;
+	m_win32_LinesPerScroll	= 10;
+	m_win32_LinesPerPage	= 0;
 #endif
-	m_FreezeWrites				= false;
+	m_IsPaused				= false;
+	m_FreezeWrites			= false;
 
 	Connect( wxEVT_SCROLLWIN_THUMBTRACK,	wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) );
 	Connect( wxEVT_SCROLLWIN_THUMBRELEASE,	wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) );
@@ -85,14 +84,12 @@ void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
 	int fonty;
 	GetTextExtent( L"blaH yeah", NULL, &fonty );
 	m_win32_LinesPerPage	= (ctrly / fonty) + 1;
-	m_win32_LinesPerScroll	= m_win32_LinesPerPage * 0.25;
+	m_win32_LinesPerScroll	= m_win32_LinesPerPage * 0.40;
 #endif
 
 	evt.Skip();
 }
 
-bool m_IsPaused = false;
-
 void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt)
 {
 	//Console.Warning( "Thumb Tracking!!!" );
@@ -131,16 +128,12 @@ void pxLogTextCtrl::ConcludeIssue( int lines )
 	// makes logging very slow, so we only send the message for status changes, so that the
 	// log aligns itself nicely when we pause emulation or when errors occur.
 
-	//m_win32_StupidRefreshTricks += lines;
-	//if( m_win32_StupidRefreshTricks > m_win32_LinesPerScroll )
-	{
-		wxTextPos showpos = XYToPosition( 1, GetNumberOfLines()-m_win32_LinesPerScroll );
-		if( showpos > 0 )
-			ShowPosition( showpos );
+	wxTextPos showpos = XYToPosition( 1, GetNumberOfLines()-m_win32_LinesPerScroll );
+	if( showpos > 0 )
+		ShowPosition( showpos );
 
-		m_win32_StupidRefreshTricks = 0;
-		//::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
-	}
+	//::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
 #endif
 
 }
+
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index 9e68d69425..92e16e5956 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -1847,6 +1847,10 @@
 					RelativePath="..\..\gui\AdvancedDialog.h"
 					>
 				</File>
+				<File
+					RelativePath="..\..\gui\Dialogs\AssertionDialog.cpp"
+					>
+				</File>
 				<File
 					RelativePath="..\..\gui\Dialogs\ConfigurationDialog.cpp"
 					>
diff --git a/pcsx2/windows/WinCompressNTFS.cpp b/pcsx2/windows/WinCompressNTFS.cpp
index b20d7d453a..0fc53ee1bd 100644
--- a/pcsx2/windows/WinCompressNTFS.cpp
+++ b/pcsx2/windows/WinCompressNTFS.cpp
@@ -25,7 +25,8 @@ void StreamException_ThrowFromErrno( const wxString& streamname, errno_t errcode
 	switch( errcode )
 	{
 		case EINVAL:
-			throw Exception::InvalidArgument( "Invalid argument" );
+			pxFailDev( L"Invalid argument" );
+			throw Exception::Stream( streamname, "Invalid argument" );
 
 		case EACCES:	// Access denied!
 			throw Exception::AccessDenied( streamname );
@@ -75,7 +76,7 @@ void StreamException_ThrowLastError( const wxString& streamname, HANDLE result )
 			throw Exception::AccessDenied( streamname );
 
 		case ERROR_INVALID_HANDLE:
-			throw Exception::InvalidOperation( "Stream object or handle is invalid" );
+			throw Exception::BadStream( streamname, "Stream object or handle is invalid" );
 
 		case ERROR_SHARING_VIOLATION:
 			throw Exception::AccessDenied( streamname, "Sharing violation" );
diff --git a/pcsx2/windows/WinConsolePipe.cpp b/pcsx2/windows/WinConsolePipe.cpp
index eecb18bb61..5f82d11d09 100644
--- a/pcsx2/windows/WinConsolePipe.cpp
+++ b/pcsx2/windows/WinConsolePipe.cpp
@@ -99,7 +99,7 @@ public:
 protected:
 	void ExecuteTaskInThread()
 	{
-		SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
+		::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
 		if( m_outpipe == INVALID_HANDLE_VALUE ) return;
 
 		try
@@ -112,7 +112,7 @@ protected:
 				if( !ReadFile(m_outpipe, s8_Buf, sizeof(s8_Buf)-1, &u32_Read, NULL) )
 				{
 					DWORD result = GetLastError();
-					if( result == ERROR_HANDLE_EOF ) break;
+					if( result == ERROR_HANDLE_EOF || result == ERROR_BROKEN_PIPE ) break;
 					if( result == ERROR_IO_PENDING )
 					{
 						Yield( 10 );
@@ -172,6 +172,10 @@ class WinPipeRedirection : public PipeRedirectionBase
 	DeclareNoncopyableObject( WinPipeRedirection );
 
 protected:
+	DWORD		m_stdhandle;
+	FILE*		m_stdfp;
+	FILE		m_stdfp_copy;
+
 	HANDLE		m_readpipe;
 	HANDLE		m_writepipe;
 	int			m_crtFile;
@@ -187,21 +191,25 @@ public:
 };
 
 WinPipeRedirection::WinPipeRedirection( FILE* stdstream )
-	: m_readpipe(INVALID_HANDLE_VALUE)
-	, m_writepipe(INVALID_HANDLE_VALUE)
-	, m_crtFile(-1)
-	, m_fp(NULL)
-	, m_Thread( m_readpipe, (stdstream == stderr) ? Color_Red : Color_Black )
+	: m_Thread( m_readpipe, (stdstream == stderr) ? Color_Red : Color_Black )
 {
+	m_stdhandle		= ( stdstream == stderr ) ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE;
+	m_stdfp			= stdstream;
+	m_stdfp_copy	= *stdstream;
+
+	m_readpipe		= INVALID_HANDLE_VALUE;
+	m_writepipe		= INVALID_HANDLE_VALUE;
+	m_crtFile		= -1;
+	m_fp			= NULL;
+
+	pxAssume( (stdstream == stderr) || (stdstream == stdout) );
+
 	try
 	{
-		pxAssert( (stdstream == stderr) || (stdstream == stdout) );
-		DWORD stdhandle = ( stdstream == stderr ) ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE;
-
 		if( 0 == CreatePipe( &m_readpipe, &m_writepipe, NULL, 0 ) )
 			throw Exception::Win32Error( "CreatePipe failed." );
 
-		if( 0 == SetStdHandle( stdhandle, m_writepipe ) )
+		if( 0 == SetStdHandle( m_stdhandle, m_writepipe ) )
 			throw Exception::Win32Error( "SetStdHandle failed." );
 
 		// Note: Don't use GetStdHandle to "confirm" the handle.
@@ -222,11 +230,19 @@ WinPipeRedirection::WinPipeRedirection( FILE* stdstream )
 		if( m_fp == NULL )
 			throw Exception::RuntimeError( "_fdopen returned NULL." );
 
-		*stdstream = *m_fp;
+		*m_stdfp = *m_fp;		// omg hack.  but it works >_<
 		setvbuf( stdstream, NULL, _IONBF, 0 );
 
 		m_Thread.Start();
 	}
+	catch( Exception::BaseThreadError& ex )
+	{
+		// thread object will become invalid because of scoping after we leave
+		// the constructor, so re-pack a new exception:
+		
+		Cleanup();
+		throw Exception::RuntimeError( ex.FormatDiagnosticMessage(), ex.FormatDisplayMessage() );
+	}
 	catch( Exception::BaseException& ex )
 	{
 		Cleanup();
@@ -235,6 +251,9 @@ WinPipeRedirection::WinPipeRedirection( FILE* stdstream )
 	}
 	catch( ... )
 	{
+		// C++ doesn't execute the object destructor automatically, because it's fail++
+		// (and I'm *not* encapsulating each handle into its own object >_<)
+
 		Cleanup();
 		throw;
 	}
@@ -247,6 +266,12 @@ WinPipeRedirection::~WinPipeRedirection()
 
 void WinPipeRedirection::Cleanup() throw()
 {
+	// restore the old handle we so graciously hacked earlier ;)
+	//  (or don't and suffer CRT crashes!  ahaha!)
+
+	if( m_stdfp != NULL )
+		*m_stdfp = m_stdfp_copy;
+	
 	// Cleanup Order Notes:
 	//  * The redirection thread is most likely blocking on ReadFile(), so we can't Cancel yet, lest we deadlock --
 	//    Closing the writepipe (either directly or through the fp/crt handles) issues an EOF to the thread,
diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp
index 9519a45c0a..7930d156e5 100644
--- a/pcsx2/x86/ix86-32/iR5900-32.cpp
+++ b/pcsx2/x86/ix86-32/iR5900-32.cpp
@@ -495,31 +495,44 @@ static const uint m_recBlockAllocSize =
 	(((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK))
 +	RECCONSTBUF_SIZE * sizeof(u32) + Ps2MemSize::Base;
 
+static void recThrowHardwareDeficiency( const wxChar* extFail )
+{
+	throw Exception::HardwareDeficiency(
+		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 )
+	);
+}
+
 static void recAlloc()
 {
 	// Hardware Requirements Check...
 
-	if ( !( x86caps.hasMultimediaExtensions  ) )
-		throw Exception::HardwareDeficiency( "Processor doesn't support MMX" );
+	if ( !x86caps.hasMultimediaExtensions )
+		recThrowHardwareDeficiency( L"MMX" );
 
-	if ( !( x86caps.hasStreamingSIMDExtensions ) )
-		throw Exception::HardwareDeficiency( "Processor doesn't support SSE" );
+	if ( !x86caps.hasStreamingSIMDExtensions )
+		recThrowHardwareDeficiency( L"SSE" );
 
-	if ( !( x86caps.hasStreamingSIMD2Extensions ) )
-		throw Exception::HardwareDeficiency( "Processor doesn't support SSE2" );
+	if ( !x86caps.hasStreamingSIMD2Extensions )
+		recThrowHardwareDeficiency( L"SSE2" );
 
 	if( recMem == NULL )
 	{
-		// Note: the VUrec depends on being able to grab an allocation below the 0x10000000 line,
-		// so we give the EErec an address above that to try first as it's basemem address, hence
-		// the 0x20000000 pick.
+		// It's handy to have a constant base address for the EE recompiler buffer, since it
+		// allows me to key in the address directly in the debugger, and also recognize EE
+		// recompiled code from user-provisioned stack traces.  But besides those, the recompiler
+		// has no actual restrictions on where it's compiled code buffer is located.
+
+		// Note: the SuperVU recompiler depends on being able to grab an allocation below the
+		// 0x10000000 line, so we give the EErec an address above that to try first as it's
+		// basemem address, hence the 0x20000000 pick.
 
 		const uint cachememsize = REC_CACHEMEM+0x1000;
 		recMem = (u8*)SysMmapEx( 0x20000000, cachememsize, 0, "recAlloc(R5900)" );
 	}
 
 	if( recMem == NULL )
-		throw Exception::OutOfMemory( "R5900-32 > failed to allocate recompiler memory." );
+		throw Exception::OutOfMemory( "R5900-32: Out of memory allocating recompiled code buffer." );
 
 	// 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
@@ -529,14 +542,14 @@ static void recAlloc()
 		m_recBlockAlloc = (u8*) _aligned_malloc( m_recBlockAllocSize, 4096 );
 
 	if( m_recBlockAlloc == NULL )
-		throw Exception::OutOfMemory( "R5900-32 Init > Failed to allocate memory for BASEBLOCK tables." );
+		throw Exception::OutOfMemory( "R5900-32: Out of memory allocating BASEBLOCK tables." );
 
 	u8* curpos = m_recBlockAlloc;
-	recRAM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
-	recROM = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK);
-	recROM1 = (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);
-	recConstBuf = (u32*)curpos; curpos += RECCONSTBUF_SIZE * sizeof(u32);
-	recRAMCopy = (u32*)curpos;
+	recRAM		= (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Base / 4) * sizeof(BASEBLOCK);
+	recROM		= (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom / 4) * sizeof(BASEBLOCK);
+	recROM1		= (BASEBLOCK*)curpos; curpos += (Ps2MemSize::Rom1 / 4) * sizeof(BASEBLOCK);
+	recConstBuf	= (u32*)curpos; curpos += RECCONSTBUF_SIZE * sizeof(u32);
+	recRAMCopy	= (u32*)curpos;
 
 	if( s_pInstCache == NULL )
 	{
@@ -545,7 +558,7 @@ static void recAlloc()
 	}
 
 	if( s_pInstCache == NULL )
-		throw Exception::OutOfMemory( "R5900-32 Init > failed to allocate memory for pInstCache." );
+		throw Exception::OutOfMemory( "R5900-32: Out of memory allocating InstCache." );
 
 	// No errors.. Proceed with initialization:
 
@@ -564,11 +577,13 @@ struct ManualPageTracking
 static __aligned16 u16 manual_page[Ps2MemSize::Base >> 12];
 static __aligned16 u8 manual_counter[Ps2MemSize::Base >> 12];
 
-static bool eeRecIsReset = false;
+static u32 eeRecIsReset = 0;
 
 ////////////////////////////////////////////////////
 void recResetEE( void )
 {
+	if( AtomicExchange( eeRecIsReset, true ) ) return;
+
 	Console.WriteLn( Color_StrongBlack, "Issuing EE/iR5900-32 Recompiler Reset" );
 
 	maxrecmem = 0;
@@ -630,7 +645,6 @@ void recResetEE( void )
 	x86FpuState = FPU_STATE;
 
 	branch = 0;
-	eeRecIsReset = true;
 }
 
 static void recShutdown( void )
@@ -656,26 +670,21 @@ static jmp_buf		m_SetJmp_StateCheck;
 
 static void recCheckExecutionState()
 {
-#if PCSX2_SEH
-	SysCoreThread::Get().StateCheckInThread();
-
-	if( eeRecIsReset )
-		throw Exception::ForceDispatcherReg();
-#else
-
-	// Without SEH we'll need to hop to a safehouse point outside the scope of recompiled
-	// code.  C++ exceptions can't cross the mighty chasm in the stackframe that the recompiler
-	// creates.  However, the longjump is slow so we only want to do one when absolutely
-	// necessary:
-
 	pxAssert( !eeRecIsReset );		// should only be changed during suspended thread states
 
-	if( SysCoreThread::Get().HasPendingStateChangeRequest() )
+	if( GetCoreThread().HasPendingStateChangeRequest() )
 	{
-		longjmp( m_SetJmp_StateCheck, SetJmp_Dispatcher );
-	}
+#if PCSX2_SEH
+		throw Exception::ForceDispatcherReg();
+#else
+		// Without SEH we'll need to hop to a safehouse point outside the scope of recompiled
+		// code.  C++ exceptions can't cross the mighty chasm in the stackframe that the recompiler
+		// creates.  However, the longjump is slow so we only want to do one when absolutely
+		// necessary:
 
+		longjmp( m_SetJmp_StateCheck, 1 );
 #endif
+	}
 }
 
 static void recExecute()
@@ -684,64 +693,36 @@ static void recExecute()
 	// [TODO] fix this comment to explain various code entry/exit points, when I'm not so tired!
 
 #if PCSX2_SEH
-	try {
-		while( true )
-		{
-			eeRecIsReset = false;
-			g_EEFreezeRegs = true;
+	eeRecIsReset = false;
+	g_EEFreezeRegs = true;
 
-			try {
-				EnterRecompiledCode();
-			}
-			catch( Exception::ForceDispatcherReg& ) { }
-		}
+	try {
+		EnterRecompiledCode();
 	}
-	catch( Exception::ExitRecExecute& ) {}
+	catch( Exception::ForceDispatcherReg& ) { }
 
 #else
 
-	switch( setjmp( m_SetJmp_StateCheck ) )
+	int oldstate;
+
+	if( !setjmp( m_SetJmp_StateCheck ) )
 	{
-		case 0:		// first run, fall through to Dispatcher
-		case SetJmp_Dispatcher:
-			while( true )
-			{
-				int oldstate;
+		eeRecIsReset = false;
+		g_EEFreezeRegs = true;
 
-				// Important! Most of the console logging and such has cancel points in it.  This is great
-				// in Windows, where SEH lets us safely kill a thread from anywhere we want.  This is bad
-				// in Linux, which cannot have a C++ exception cross the recompiler.  Hence the changing
-				// of the cancelstate here!
+		// Important! Most of the console logging and such has cancel points in it.  This is great
+		// in Windows, where SEH lets us safely kill a thread from anywhere we want.  This is bad
+		// in Linux, which cannot have a C++ exception cross the recompiler.  Hence the changing
+		// of the cancelstate here!
 
-				pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
-				SysCoreThread::Get().StateCheckInThread();
-				pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
-
-				eeRecIsReset = false;
-
-				#ifdef _WIN32
-				__try {
-				#endif
-
-					EnterRecompiledCode();
-
-				#ifdef _WIN32
-				} __finally
-				{
-					// This assertion is designed to help me troubleshoot the setjmp behavior from Win32.
-					// If the recompiler throws an unhandled SEH exception with SEH support disabled (which
-					// is typically a pthread_cancel) then this will fire and let me know.
-
-					// FIXME: Doesn't work because SEH is remarkably clever and executes the _finally block
-					// even when I use longjmp to restart the loop.  Maybe a workaround exists? :/
-
-					//pxFailDev( "Recompiler threw an SEH exception with SEH disabled; possibly due to pthread_cancel." );
-				}
-				#endif
-			}
-		break;
-
-		case SetJmp_Exit: break;
+		pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
+		EnterRecompiledCode();
+		
+		// Generally unreachable code here ...
+	}
+	else
+	{
+		pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
 	}
 #endif
 }
@@ -858,7 +839,7 @@ static void recExitExecution()
 #if PCSX2_SEH
 	throw Exception::ExitRecExecute();
 #else
-	longjmp( m_SetJmp_StateCheck, SetJmp_Exit );
+	longjmp( m_SetJmp_StateCheck, 1 );
 #endif
 }
 
@@ -1319,7 +1300,7 @@ static void __fastcall recRecompile( const u32 startpc )
     if (dumplog & 4) iDumpRegisters(startpc, 0);
 #endif
 
-	pxAssert( startpc );
+	pxAssume( startpc );
 
 	// if recPtr reached the mem limit reset whole mem
 	if ( ( (uptr)recPtr - (uptr)recMem ) >= REC_CACHEMEM-0x40000 || dumplog == 0xffffffff) {
@@ -1348,7 +1329,7 @@ static void __fastcall recRecompile( const u32 startpc )
 
 	s_pCurBlockEx = recBlocks.New(HWADDR(startpc), (uptr)recPtr);
 
-	pxAssert(s_pCurBlockEx);
+	pxAssume(s_pCurBlockEx);
 
 	branch = 0;
 
@@ -1359,7 +1340,7 @@ static void __fastcall recRecompile( const u32 startpc )
 	g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
 	g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
 	g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0;
-	pxAssert( g_cpuConstRegs[0].UD[0] == 0 );
+	pxAssume( g_cpuConstRegs[0].UD[0] == 0 );
 
 	_initX86regs();
 	_initXMMregs();
diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp
index e7b88c94fa..3818c49e83 100644
--- a/pcsx2/x86/microVU.cpp
+++ b/pcsx2/x86/microVU.cpp
@@ -67,20 +67,20 @@ const __aligned(32) mVU_Globals mVUglob = {
 // Micro VU - Main Functions
 //------------------------------------------------------------------
 
-microVUt(void) mVUthrowHardwareDeficiency( const wxChar* extFail )
+microVUt(void) mVUthrowHardwareDeficiency( const wxChar* extFail, int vuIndex )
 {
 	throw Exception::HardwareDeficiency(
-		L"microVU init error: SSE1 is not available!",
-		wxsFormat(_("%s Extensions not found.  microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), L"SSE" )
+		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 )
 	);
 }
 
 // Only run this once per VU! ;)
 microVUt(void) mVUinit(VURegs* vuRegsPtr, int vuIndex) {
 
-	if(!x86caps.hasMultimediaExtensions)		mVUthrowHardwareDeficiency( L"MMX" );
-	if(!x86caps.hasStreamingSIMDExtensions)		mVUthrowHardwareDeficiency( L"SSE" );
-	if(!x86caps.hasStreamingSIMD2Extensions)	mVUthrowHardwareDeficiency( L"SSE2" );
+	if(!x86caps.hasMultimediaExtensions)		mVUthrowHardwareDeficiency( L"MMX", vuIndex );
+	if(!x86caps.hasStreamingSIMDExtensions)		mVUthrowHardwareDeficiency( L"SSE", vuIndex );
+	if(!x86caps.hasStreamingSIMD2Extensions)	mVUthrowHardwareDeficiency( L"SSE2", vuIndex );
 
 	microVU* mVU = mVUx;
 	memset(&mVU->prog, 0, sizeof(mVU->prog));
@@ -182,17 +182,19 @@ microVUt(void) mVUclear(mV, u32 addr, u32 size) {
 // Clears program data
 microVUf(void) mVUclearProg(int progIndex) {
 	microVU* mVU = mVUx;
-	mVUprogI.used	   = 0;
-	mVUprogI.isDead    = 1;
-	mVUprogI.isOld	   = 1;
-	mVUprogI.frame	   = mVU->prog.curFrame;
-	for (int j = 0; j <= mVUprogI.ranges.max; j++) {
-		mVUprogI.ranges.range[j][0]	= -1; // Set range to 
-		mVUprogI.ranges.range[j][1]	= -1; // indeterminable status
-		mVUprogI.ranges.total		= -1;
+	microProgram& program = mVU->prog.prog[progIndex];
+
+	program.used		= 0;
+	program.isDead		= 1;
+	program.isOld		= 1;
+	program.frame		= mVU->prog.curFrame;
+	for (int j = 0; j <= program.ranges.max; j++) {
+		program.ranges.range[j][0]	= -1; // Set range to 
+		program.ranges.range[j][1]	= -1; // indeterminable status
+		program.ranges.total		= -1;
 	}
 	for (u32 i = 0; i < (mVU->progSize / 2); i++) {
-		safe_delete(mVUprogI.block[i]);
+		safe_delete(program.block[i]);
 	}
 }
 
@@ -322,6 +324,9 @@ microVUf(int) mVUsearchProg() {
 	return 1; // If !cleared, then we're still on the same program as last-time ;)
 }
 
+static u32 mvu0_allocated = 0;
+static u32 mvu1_allocated = 0;
+
 // --------------------------------------------------------------------------------------
 //  recMicroVU0
 // --------------------------------------------------------------------------------------
@@ -331,13 +336,21 @@ recMicroVU0::recMicroVU0() {
 }
 
 void recMicroVU0::Allocate() {
-	if( AtomicIncrement( m_AllocCount ) == 0 )
-		mVUinit( &VU0, 0 );
+	if( m_AllocCount == 0 )
+	{
+		++m_AllocCount;
+		if( AtomicExchange( mvu0_allocated, 1 ) == 0 )
+			mVUinit( &VU0, 0 );
+	}
 }
 
 void recMicroVU0::Shutdown() throw() {
-	if( AtomicDecrement( m_AllocCount ) == 0 )
-		mVUclose(&microVU0);
+	if( m_AllocCount > 0 )
+	{
+		--m_AllocCount;
+		if( AtomicExchange( mvu0_allocated, 0 ) == 1 )
+			mVUclose(&microVU0);
+	}
 }
 
 void recMicroVU0::Reset() {
@@ -356,7 +369,7 @@ void recMicroVU0::ExecuteBlock() {
 }
 
 void recMicroVU0::Clear(u32 addr, u32 size) {
-	pxAssert( m_AllocCount );		// please allocate me first! :|
+	pxAssert( mvu0_allocated );		// please allocate me first! :|
 	mVUclear(&microVU0, addr, size); 
 }
 
@@ -367,32 +380,35 @@ void recMicroVU0::Vsync() throw() {
 // --------------------------------------------------------------------------------------
 //  recMicroVU1
 // --------------------------------------------------------------------------------------
-recMicroVU1::recMicroVU1()
-{
+recMicroVU1::recMicroVU1() {
 	IsInterpreter = false;
 }
 
-void recMicroVU1::Allocate()
-{
-	if( AtomicIncrement( m_AllocCount ) == 0 )
-		mVUinit( &VU1, 1 );
+void recMicroVU1::Allocate() {
+	if( m_AllocCount == 0 )
+	{
+		++m_AllocCount;
+		if( AtomicExchange( mvu1_allocated, 1 ) == 0 )
+			mVUinit( &VU1, 1 );
+	}
 }
 
-void recMicroVU1::Shutdown() throw()
-{
-	if( AtomicDecrement( m_AllocCount ) == 0 )
-		mVUclose(&microVU1);
+void recMicroVU1::Shutdown() throw() {
+	if( m_AllocCount > 0 )
+	{
+		--m_AllocCount;
+		if( AtomicExchange( mvu1_allocated, 0 ) == 1 )
+			mVUclose(&microVU1);
+	}
 }
 
-void recMicroVU1::Reset()
-{
+void recMicroVU1::Reset() {
 	if( !pxAssertDev( m_AllocCount, "MicroVU1 CPU Provider has not been allocated prior to reset!" ) ) return;
 	mVUreset(&microVU1);
 }
 
-void recMicroVU1::ExecuteBlock()
-{
-	pxAssert( m_AllocCount );		// please allocate me first! :|
+void recMicroVU1::ExecuteBlock() {
+	pxAssert( mvu1_allocated );		// please allocate me first! :|
 
 	if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
 	pxAssert( (VU1.VI[REG_TPC].UL&7) == 0 );
@@ -402,8 +418,7 @@ void recMicroVU1::ExecuteBlock()
 	XMMRegisters::Thaw();
 }
 
-void recMicroVU1::Clear(u32 addr, u32 size)
-{
+void recMicroVU1::Clear(u32 addr, u32 size) {
 	pxAssert( m_AllocCount );		// please allocate me first! :|
 	mVUclear(&microVU1, addr, size); 
 }
diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h
index 1177cad6f0..bf3782970a 100644
--- a/pcsx2/x86/microVU_Misc.h
+++ b/pcsx2/x86/microVU_Misc.h
@@ -121,8 +121,8 @@ extern const __aligned(32) mVU_Globals mVUglob;
 // Function/Template Stuff
 #define mVUx (vuIndex ? &microVU1 : &microVU0)
 #define mVUop(opName)	static void opName (mP)
-#define microVUr(aType) __recInline aType
-#define microVUt(aType) __forceinline aType
+#define microVUr(aType) static __recInline aType
+#define microVUt(aType) static __forceinline aType
 #define microVUx(aType) template<int vuIndex> aType
 #define microVUf(aType) template<int vuIndex> __forceinline aType