mirror of https://github.com/PCSX2/pcsx2.git
wxgui: Redid a bunch of the wxWidgets assertion handlers so that they're thread-safe, and fixed the wxLogError stuff to pipe through to the PCSX2 console (better than it spamming popup errors, and also makes it thread safe as well).
.. oh, and it successfully boots the BIOS now, suing the 'Boot Without Disc' menu option. :D git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1682 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
9303bc5bf2
commit
c73375366f
|
@ -75,6 +75,8 @@ extern void vSyncDebugStuff( uint frame );
|
||||||
# error PCSX2 - Unsupported operating system platform.
|
# error PCSX2 - Unsupported operating system platform.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class pxMessageBoxEvent;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Different types of message boxes that the emulator can employ from the friendly confines
|
// Different types of message boxes that the emulator can employ from the friendly confines
|
||||||
// of it's blissful unawareness of whatever GUI it runs under. :) All message boxes exhibit
|
// of it's blissful unawareness of whatever GUI it runs under. :) All message boxes exhibit
|
||||||
|
@ -83,18 +85,18 @@ extern void vSyncDebugStuff( uint frame );
|
||||||
//
|
//
|
||||||
namespace Msgbox
|
namespace Msgbox
|
||||||
{
|
{
|
||||||
extern void OnEvent( wxCommandEvent& evt );
|
extern void OnEvent( pxMessageBoxEvent& evt );
|
||||||
|
|
||||||
// Pops up an alert Dialog Box with a singular "OK" button.
|
extern bool Alert( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=wxICON_EXCLAMATION );
|
||||||
// Always returns false. Replacement for SysMessage.
|
extern bool OkCancel( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=0 );
|
||||||
extern bool Alert( const wxString& text );
|
extern bool YesNo( const wxString& text, const wxString& caption=L"PCSX2 Message", int icon=wxICON_QUESTION );
|
||||||
|
|
||||||
// Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
|
extern int Assertion( const wxString& text, const wxString& stacktrace );
|
||||||
// true if OK, false if cancel.
|
extern void Except( const Exception::BaseException& src );
|
||||||
extern bool OkCancel( const wxString& text );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_DECLARE_EVENT_TYPES()
|
BEGIN_DECLARE_EVENT_TYPES()
|
||||||
DECLARE_EVENT_TYPE( pxEVT_MSGBOX, -1 );
|
DECLARE_EVENT_TYPE( pxEVT_MSGBOX, -1 );
|
||||||
|
DECLARE_EVENT_TYPE( pxEVT_CallStackBox, -1 );
|
||||||
END_DECLARE_EVENT_TYPES()
|
END_DECLARE_EVENT_TYPES()
|
||||||
|
|
||||||
|
|
145
pcsx2/gui/App.h
145
pcsx2/gui/App.h
|
@ -23,138 +23,19 @@
|
||||||
#include <wx/imaglist.h>
|
#include <wx/imaglist.h>
|
||||||
#include <wx/docview.h>
|
#include <wx/docview.h>
|
||||||
|
|
||||||
|
#include <wx/apptrait.h>
|
||||||
|
|
||||||
#include "AppConfig.h"
|
#include "AppConfig.h"
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
|
#include "ConsoleLogger.h"
|
||||||
|
|
||||||
using namespace Threading;
|
|
||||||
|
|
||||||
class MainEmuFrame;
|
|
||||||
class IniInterface;
|
class IniInterface;
|
||||||
class LogWriteEvent;
|
|
||||||
|
|
||||||
extern wxFileHistory* g_RecentIsoList;
|
extern wxFileHistory* g_RecentIsoList;
|
||||||
|
|
||||||
DECLARE_EVENT_TYPE(wxEVT_DockConsole, -1);
|
|
||||||
|
|
||||||
extern wxRect wxGetDisplayArea();
|
extern wxRect wxGetDisplayArea();
|
||||||
extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos );
|
extern bool pxIsValidWindowPosition( const wxWindow& window, const wxPoint& windowPos );
|
||||||
|
|
||||||
static const bool EnableThreadedLoggingTest = false; //true;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ConsoleThreadTest -- useful class for unit testing the thread safety and general performance
|
|
||||||
// of the console logger.
|
|
||||||
//
|
|
||||||
class ConsoleTestThread : public PersistentThread
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
volatile bool m_done;
|
|
||||||
sptr ExecuteTask();
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConsoleTestThread() :
|
|
||||||
m_done( false )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~ConsoleTestThread()
|
|
||||||
{
|
|
||||||
m_done = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
class ConsoleLogFrame : public wxFrame
|
|
||||||
{
|
|
||||||
DeclareNoncopyableObject(ConsoleLogFrame)
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef AppConfig::ConsoleLogOptions ConLogConfig;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class ColorArray
|
|
||||||
{
|
|
||||||
DeclareNoncopyableObject(ColorArray)
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SafeArray<wxTextAttr> m_table;
|
|
||||||
wxTextAttr m_color_default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~ColorArray();
|
|
||||||
ColorArray( int fontsize=8 );
|
|
||||||
|
|
||||||
void Create( int fontsize );
|
|
||||||
void Cleanup();
|
|
||||||
|
|
||||||
void SetFont( const wxFont& font );
|
|
||||||
void SetFont( int fontsize );
|
|
||||||
|
|
||||||
const wxTextAttr& operator[]( Console::Colors coloridx ) const
|
|
||||||
{
|
|
||||||
return m_table[(int)coloridx];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ConLogConfig m_conf;
|
|
||||||
wxTextCtrl& m_TextCtrl;
|
|
||||||
ColorArray m_ColorTable;
|
|
||||||
Console::Colors m_curcolor;
|
|
||||||
volatile long m_msgcounter; // used to track queued messages and throttle load placed on the gui message pump
|
|
||||||
|
|
||||||
Semaphore m_semaphore;
|
|
||||||
|
|
||||||
// Threaded log spammer, useful for testing console logging performance.
|
|
||||||
ConsoleTestThread* m_threadlogger;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// ctor & dtor
|
|
||||||
ConsoleLogFrame( MainEmuFrame *pParent, const wxString& szTitle, const ConLogConfig& options );
|
|
||||||
virtual ~ConsoleLogFrame();
|
|
||||||
|
|
||||||
virtual void Write( const wxString& text );
|
|
||||||
virtual void SetColor( Console::Colors color );
|
|
||||||
virtual void ClearColor();
|
|
||||||
virtual void DockedMove();
|
|
||||||
|
|
||||||
// Retreives the current configuration options settings for this box.
|
|
||||||
// (settings change if the user moves the window or changes the font size)
|
|
||||||
const ConLogConfig& GetConfig() const { return m_conf; }
|
|
||||||
|
|
||||||
void Write( Console::Colors color, const wxString& text );
|
|
||||||
void Newline();
|
|
||||||
void CountMessage();
|
|
||||||
void DoMessage();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// menu callbacks
|
|
||||||
virtual void OnOpen (wxMenuEvent& event);
|
|
||||||
virtual void OnClose(wxMenuEvent& event);
|
|
||||||
virtual void OnSave (wxMenuEvent& event);
|
|
||||||
virtual void OnClear(wxMenuEvent& event);
|
|
||||||
|
|
||||||
void OnFontSize(wxMenuEvent& event);
|
|
||||||
|
|
||||||
virtual void OnCloseWindow(wxCloseEvent& event);
|
|
||||||
|
|
||||||
void OnWrite( wxCommandEvent& event );
|
|
||||||
void OnNewline( wxCommandEvent& event );
|
|
||||||
void OnSetTitle( wxCommandEvent& event );
|
|
||||||
void OnDockedMove( wxCommandEvent& event );
|
|
||||||
void OnSemaphoreWait( wxCommandEvent& event );
|
|
||||||
|
|
||||||
// common part of OnClose() and OnCloseWindow()
|
|
||||||
virtual void DoClose();
|
|
||||||
|
|
||||||
void OnMoveAround( wxMoveEvent& evt );
|
|
||||||
void OnResize( wxSizeEvent& evt );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct AppImageIds
|
struct AppImageIds
|
||||||
|
@ -199,6 +80,20 @@ struct AppImageIds
|
||||||
} Toolbars;
|
} Toolbars;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
class pxAppTraits : public wxGUIAppTraits
|
||||||
|
{
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
public:
|
||||||
|
virtual bool ShowAssertDialog(const wxString& msg);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual wxString GetAssertStackTrace();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
class Pcsx2App : public wxApp
|
class Pcsx2App : public wxApp
|
||||||
|
@ -228,6 +123,8 @@ public:
|
||||||
|
|
||||||
bool PrepForExit();
|
bool PrepForExit();
|
||||||
|
|
||||||
|
void OnAssertFailure( const wxChar *file, int line, const wxChar *func, const wxChar *cond, const wxChar *msg );
|
||||||
|
|
||||||
const wxBitmap& GetLogoBitmap();
|
const wxBitmap& GetLogoBitmap();
|
||||||
wxImageList& GetImgList_Config();
|
wxImageList& GetImgList_Config();
|
||||||
wxImageList& GetImgList_Toolbars();
|
wxImageList& GetImgList_Toolbars();
|
||||||
|
@ -282,8 +179,10 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void ReadUserModeSettings();
|
void ReadUserModeSettings();
|
||||||
bool TryOpenConfigCwd();
|
bool TryOpenConfigCwd();
|
||||||
void OnMessageBox( wxCommandEvent& evt );
|
void OnMessageBox( pxMessageBoxEvent& evt );
|
||||||
void CleanupMess();
|
void CleanupMess();
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_APP(Pcsx2App)
|
DECLARE_APP(Pcsx2App)
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
|
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
#include "App.h"
|
||||||
|
|
||||||
|
#include <wx/stackwalk.h>
|
||||||
|
|
||||||
|
|
||||||
|
static wxString pxGetStackTrace()
|
||||||
|
{
|
||||||
|
wxString stackTrace;
|
||||||
|
|
||||||
|
class StackDump : public wxStackWalker
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
wxString m_stackTrace;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StackDump() { }
|
||||||
|
|
||||||
|
const wxString& GetStackTrace() const { return m_stackTrace; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void OnStackFrame(const wxStackFrame& frame)
|
||||||
|
{
|
||||||
|
wxString name( frame.GetName() );
|
||||||
|
if( name.IsEmpty() )
|
||||||
|
name = wxsFormat( L"%p ", frame.GetAddress() );
|
||||||
|
|
||||||
|
m_stackTrace += wxString::Format( L"[%02d] %-46s ",
|
||||||
|
wx_truncate_cast(int, frame.GetLevel()), name.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString pxAppTraits::GetAssertStackTrace()
|
||||||
|
{
|
||||||
|
return pxGetStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
static __threadlocal bool _reentrant_lock = false;
|
||||||
|
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
if( _reentrant_lock )
|
||||||
|
{
|
||||||
|
// Re-entrant assertions are bad mojo -- trap immediately.
|
||||||
|
wxTrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
_reentrant_lock = true;
|
||||||
|
|
||||||
|
// Used to allow the user to suppress future assertions during this application's session.
|
||||||
|
static bool disableAsserts = false;
|
||||||
|
|
||||||
|
wxString dbgmsg;
|
||||||
|
dbgmsg.reserve( 2048 );
|
||||||
|
|
||||||
|
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", file, line,
|
||||||
|
(func==NULL) ? L"" : L" in ",
|
||||||
|
(func==NULL) ? L"" : func,
|
||||||
|
message.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
wxString trace( L"Call stack:\n" + pxGetStackTrace() );
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
_reentrant_lock = false;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -25,26 +25,82 @@
|
||||||
#include <wx/file.h>
|
#include <wx/file.h>
|
||||||
#include <wx/textfile.h>
|
#include <wx/textfile.h>
|
||||||
|
|
||||||
// This code was 'borrowed' from wxWidgets built in console log class and then heavily
|
// Custom ConsoleLogger, because the built-in wxWidgets one is poop.
|
||||||
// modified to suite our needs. I would have used some crafty subclassing instead except
|
|
||||||
// who ever wrote the code of wxWidgets had a peculiar love of the 'private' keyword,
|
|
||||||
// thus killing any possibility of subclassing in a useful manner. (sigh)
|
|
||||||
|
|
||||||
BEGIN_DECLARE_EVENT_TYPES()
|
BEGIN_DECLARE_EVENT_TYPES()
|
||||||
DECLARE_EVENT_TYPE(wxEVT_LOG_Write, -1)
|
DECLARE_EVENT_TYPE(wxEVT_LOG_Write, -1)
|
||||||
DECLARE_EVENT_TYPE(wxEVT_LOG_Newline, -1)
|
DECLARE_EVENT_TYPE(wxEVT_LOG_Newline, -1)
|
||||||
DECLARE_EVENT_TYPE(wxEVT_SetTitleText, -1)
|
DECLARE_EVENT_TYPE(wxEVT_SetTitleText, -1)
|
||||||
DECLARE_EVENT_TYPE(wxEVT_SemaphoreWait, -1);
|
DECLARE_EVENT_TYPE(wxEVT_SemaphoreWait, -1)
|
||||||
END_DECLARE_EVENT_TYPES()
|
END_DECLARE_EVENT_TYPES()
|
||||||
|
|
||||||
DEFINE_EVENT_TYPE(wxEVT_LOG_Write)
|
DEFINE_EVENT_TYPE(wxEVT_LOG_Write)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_LOG_Newline)
|
DEFINE_EVENT_TYPE(wxEVT_LOG_Newline)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_SetTitleText)
|
DEFINE_EVENT_TYPE(wxEVT_SetTitleText)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_DockConsole)
|
DEFINE_EVENT_TYPE(wxEVT_DockConsole)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_SemaphoreWait);
|
DEFINE_EVENT_TYPE(wxEVT_SemaphoreWait)
|
||||||
|
|
||||||
using Console::Colors;
|
using Console::Colors;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
void pxLogConsole::DoLog( wxLogLevel level, const wxChar *szString, time_t t )
|
||||||
|
{
|
||||||
|
switch ( level )
|
||||||
|
{
|
||||||
|
case wxLOG_Trace:
|
||||||
|
case wxLOG_Debug:
|
||||||
|
if( IsDebugBuild )
|
||||||
|
{
|
||||||
|
wxString str;
|
||||||
|
TimeStamp( &str );
|
||||||
|
str += szString;
|
||||||
|
|
||||||
|
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
|
||||||
|
// don't prepend debug/trace here: it goes to the
|
||||||
|
// debug window anyhow
|
||||||
|
str += wxT("\r\n");
|
||||||
|
OutputDebugString(str);
|
||||||
|
#else
|
||||||
|
// send them to stderr
|
||||||
|
wxFprintf(stderr, wxT("[%s] %s\n"),
|
||||||
|
level == wxLOG_Trace ? wxT("Trace")
|
||||||
|
: wxT("Debug"),
|
||||||
|
str.c_str());
|
||||||
|
fflush(stderr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOG_FatalError:
|
||||||
|
// This one is unused by wx, and unused by PCSX2 (we prefer exceptions, thanks).
|
||||||
|
DevAssert( false, "Stop using FatalError and use assertions or exceptions instead." );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOG_Status:
|
||||||
|
// Also unsed by wx, and unused by PCSX2 also (we prefer direct API calls to our main window!)
|
||||||
|
DevAssert( false, "Stop using wxLogStatus just access the Pcsx2App functions directly instead." );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOG_Info:
|
||||||
|
if ( !GetVerbose() ) return;
|
||||||
|
// fallthrough!
|
||||||
|
|
||||||
|
case wxLOG_Message:
|
||||||
|
Console::WriteLn( wxString(L"wx > ") + szString );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOG_Error:
|
||||||
|
Console::Error( wxString(L"wx > ") + szString );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOG_Warning:
|
||||||
|
Console::Notice( wxString(L"wx > ") + szString );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
sptr ConsoleTestThread::ExecuteTask()
|
sptr ConsoleTestThread::ExecuteTask()
|
||||||
{
|
{
|
||||||
|
@ -603,72 +659,199 @@ namespace Console
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define wxEVT_BOX_ALERT 78
|
DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
|
||||||
|
DEFINE_EVENT_TYPE( pxEVT_CallStackBox );
|
||||||
|
|
||||||
using namespace Threading;
|
using namespace Threading;
|
||||||
|
|
||||||
DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
|
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||||
|
static int pxMessageDialog( const wxString& content, const wxString& caption, long flags )
|
||||||
namespace Msgbox
|
|
||||||
{
|
{
|
||||||
struct InstanceData
|
if( IsDevBuild && !wxThread::IsMain() )
|
||||||
|
throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
|
||||||
|
|
||||||
|
// fixme: If the emulator is currently active and is running in fullscreen mode, 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
if( IsDevBuild && !wxThread::IsMain() )
|
||||||
|
throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
|
||||||
|
|
||||||
|
return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MsgboxEventResult
|
||||||
{
|
{
|
||||||
Semaphore WaitForMe;
|
Semaphore WaitForMe;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
InstanceData() :
|
MsgboxEventResult() :
|
||||||
WaitForMe(), result( 0 )
|
WaitForMe(), result( 0 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class pxMessageBoxEvent : public wxEvent
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
MsgboxEventResult& m_Instdata;
|
||||||
|
wxString m_Title;
|
||||||
|
wxString m_Content;
|
||||||
|
long m_Flags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
pxMessageBoxEvent() :
|
||||||
|
wxEvent( 0, pxEVT_MSGBOX )
|
||||||
|
, m_Instdata( *(MsgboxEventResult*)NULL )
|
||||||
|
, m_Title()
|
||||||
|
, m_Content()
|
||||||
|
, m_Flags( 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags ) :
|
||||||
|
wxEvent( 0, pxEVT_MSGBOX )
|
||||||
|
, m_Instdata( instdata )
|
||||||
|
, m_Title( title )
|
||||||
|
, m_Content( content )
|
||||||
|
, m_Flags( flags )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
pxMessageBoxEvent( const pxMessageBoxEvent& event ) :
|
||||||
|
wxEvent( event )
|
||||||
|
, m_Instdata( event.m_Instdata )
|
||||||
|
, m_Title( event.m_Title )
|
||||||
|
, m_Content( event.m_Content )
|
||||||
|
, m_Flags( event.m_Flags )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||||
|
void DoTheDialog()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent )
|
||||||
|
|
||||||
|
namespace Msgbox
|
||||||
|
{
|
||||||
// parameters:
|
// parameters:
|
||||||
// flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
|
// flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
|
||||||
//
|
//
|
||||||
static int ThreadedMessageBox( int flags, const wxString& text )
|
static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX )
|
||||||
{
|
{
|
||||||
// must pass the message to the main gui thread, and then stall this thread, to avoid
|
// 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.
|
// threaded chaos where our thread keeps running while the popup is awaiting input.
|
||||||
|
|
||||||
InstanceData instdat;
|
MsgboxEventResult instdat;
|
||||||
wxCommandEvent tevt( pxEVT_MSGBOX );
|
pxMessageBoxEvent tevt( instdat, title, content, flags );
|
||||||
tevt.SetString( text );
|
|
||||||
tevt.SetClientData( &instdat );
|
|
||||||
tevt.SetExtraLong( flags );
|
|
||||||
wxGetApp().AddPendingEvent( tevt );
|
wxGetApp().AddPendingEvent( tevt );
|
||||||
instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
|
instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
|
||||||
return instdat.result;
|
return instdat.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnEvent( wxCommandEvent& evt )
|
void OnEvent( pxMessageBoxEvent& evt )
|
||||||
{
|
{
|
||||||
// Must be called from the GUI thread ONLY.
|
evt.DoTheDialog();
|
||||||
wxASSERT( wxThread::IsMain() );
|
|
||||||
|
|
||||||
int result = Alert( evt.GetString() );
|
|
||||||
InstanceData* instdat = (InstanceData*)evt.GetClientData();
|
|
||||||
instdat->result = result;
|
|
||||||
instdat->WaitForMe.Post();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Alert( const wxString& text )
|
// 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;
|
||||||
if( wxThread::IsMain() )
|
if( wxThread::IsMain() )
|
||||||
wxMessageBox( text, L"Pcsx2 Message", wxOK, wxGetApp().GetTopWindow() );
|
pxMessageDialog( text, caption, icon );
|
||||||
else
|
else
|
||||||
ThreadedMessageBox( wxOK, text );
|
ThreadedMessageBox( text, caption, icon );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OkCancel( const wxString& text )
|
// Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
|
||||||
|
// true if OK, false if cancel.
|
||||||
|
bool OkCancel( const wxString& text, const wxString& caption, int icon )
|
||||||
{
|
{
|
||||||
|
icon |= wxOK | wxCANCEL;
|
||||||
if( wxThread::IsMain() )
|
if( wxThread::IsMain() )
|
||||||
{
|
{
|
||||||
return wxOK == wxMessageBox( text, L"Pcsx2 Message", wxOK | wxCANCEL, wxGetApp().GetTopWindow() );
|
return wxID_OK == pxMessageDialog( text, caption, icon );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return wxOK == ThreadedMessageBox( wxOK | wxCANCEL, text );
|
return wxID_OK == ThreadedMessageBox( text, caption, icon );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
if( wxThread::IsMain() )
|
||||||
|
{
|
||||||
|
return pxCallstackDialog( text, caption, buttons );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.DisplayMessage(), src.LogMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
/* Pcsx2 - Pc Ps2 Emulator
|
||||||
|
* Copyright (C) 2002-2009 Pcsx2 Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
DECLARE_EVENT_TYPE(wxEVT_DockConsole, -1);
|
||||||
|
|
||||||
|
static const bool EnableThreadedLoggingTest = false; //true;
|
||||||
|
|
||||||
|
using namespace Threading;
|
||||||
|
|
||||||
|
class MainEmuFrame;
|
||||||
|
class LogWriteEvent;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// pxLogConsole
|
||||||
|
// This is a custom logging facility that pipes wxLog messages to our very own console
|
||||||
|
// log window.
|
||||||
|
//
|
||||||
|
class pxLogConsole : public wxLog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
pxLogConsole() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ConsoleThreadTest -- useful class for unit testing the thread safety and general performance
|
||||||
|
// of the console logger.
|
||||||
|
//
|
||||||
|
class ConsoleTestThread : public PersistentThread
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
volatile bool m_done;
|
||||||
|
sptr ExecuteTask();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConsoleTestThread() :
|
||||||
|
m_done( false )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ConsoleTestThread()
|
||||||
|
{
|
||||||
|
m_done = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
class ConsoleLogFrame : public wxFrame
|
||||||
|
{
|
||||||
|
DeclareNoncopyableObject(ConsoleLogFrame)
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef AppConfig::ConsoleLogOptions ConLogConfig;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class ColorArray
|
||||||
|
{
|
||||||
|
DeclareNoncopyableObject(ColorArray)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SafeArray<wxTextAttr> m_table;
|
||||||
|
wxTextAttr m_color_default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~ColorArray();
|
||||||
|
ColorArray( int fontsize=8 );
|
||||||
|
|
||||||
|
void Create( int fontsize );
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
void SetFont( const wxFont& font );
|
||||||
|
void SetFont( int fontsize );
|
||||||
|
|
||||||
|
const wxTextAttr& operator[]( Console::Colors coloridx ) const
|
||||||
|
{
|
||||||
|
return m_table[(int)coloridx];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ConLogConfig m_conf;
|
||||||
|
wxTextCtrl& m_TextCtrl;
|
||||||
|
ColorArray m_ColorTable;
|
||||||
|
Console::Colors m_curcolor;
|
||||||
|
volatile long m_msgcounter; // used to track queued messages and throttle load placed on the gui message pump
|
||||||
|
|
||||||
|
Semaphore m_semaphore;
|
||||||
|
|
||||||
|
// Threaded log spammer, useful for testing console logging performance.
|
||||||
|
ConsoleTestThread* m_threadlogger;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// ctor & dtor
|
||||||
|
ConsoleLogFrame( MainEmuFrame *pParent, const wxString& szTitle, const ConLogConfig& options );
|
||||||
|
virtual ~ConsoleLogFrame();
|
||||||
|
|
||||||
|
virtual void Write( const wxString& text );
|
||||||
|
virtual void SetColor( Console::Colors color );
|
||||||
|
virtual void ClearColor();
|
||||||
|
virtual void DockedMove();
|
||||||
|
|
||||||
|
// Retrieves the current configuration options settings for this box.
|
||||||
|
// (settings change if the user moves the window or changes the font size)
|
||||||
|
const ConLogConfig& GetConfig() const { return m_conf; }
|
||||||
|
|
||||||
|
void Write( Console::Colors color, const wxString& text );
|
||||||
|
void Newline();
|
||||||
|
void CountMessage();
|
||||||
|
void DoMessage();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// menu callbacks
|
||||||
|
virtual void OnOpen (wxMenuEvent& event);
|
||||||
|
virtual void OnClose(wxMenuEvent& event);
|
||||||
|
virtual void OnSave (wxMenuEvent& event);
|
||||||
|
virtual void OnClear(wxMenuEvent& event);
|
||||||
|
|
||||||
|
void OnFontSize(wxMenuEvent& event);
|
||||||
|
|
||||||
|
virtual void OnCloseWindow(wxCloseEvent& event);
|
||||||
|
|
||||||
|
void OnWrite( wxCommandEvent& event );
|
||||||
|
void OnNewline( wxCommandEvent& event );
|
||||||
|
void OnSetTitle( wxCommandEvent& event );
|
||||||
|
void OnDockedMove( wxCommandEvent& event );
|
||||||
|
void OnSemaphoreWait( wxCommandEvent& event );
|
||||||
|
|
||||||
|
// common part of OnClose() and OnCloseWindow()
|
||||||
|
virtual void DoClose();
|
||||||
|
|
||||||
|
void OnMoveAround( wxMoveEvent& evt );
|
||||||
|
void OnResize( wxSizeEvent& evt );
|
||||||
|
};
|
||||||
|
|
|
@ -141,6 +141,8 @@ bool Pcsx2App::OnCmdLineParsed(wxCmdLineParser& parser)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (wxEvtHandler::*pxMessageBoxEventFunction)(pxMessageBoxEvent&);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool Pcsx2App::OnInit()
|
bool Pcsx2App::OnInit()
|
||||||
{
|
{
|
||||||
|
@ -150,8 +152,6 @@ bool Pcsx2App::OnInit()
|
||||||
g_Conf = new AppConfig();
|
g_Conf = new AppConfig();
|
||||||
g_EmuThread = new CoreEmuThread();
|
g_EmuThread = new CoreEmuThread();
|
||||||
|
|
||||||
delete wxMessageOutput::Set( new wxMessageOutputDebug() );
|
|
||||||
|
|
||||||
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
||||||
|
|
||||||
// User/Admin Mode Dual Setup:
|
// User/Admin Mode Dual Setup:
|
||||||
|
@ -168,6 +168,7 @@ bool Pcsx2App::OnInit()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ReadUserModeSettings();
|
ReadUserModeSettings();
|
||||||
|
delete wxLog::SetActiveTarget( new pxLogConsole() );
|
||||||
|
|
||||||
AppConfig_ReloadGlobalSettings();
|
AppConfig_ReloadGlobalSettings();
|
||||||
|
|
||||||
|
@ -189,12 +190,16 @@ bool Pcsx2App::OnInit()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connect( pxEVT_MSGBOX, wxCommandEventHandler( Pcsx2App::OnMessageBox ) );
|
#define pxMessageBoxEventThing(func) \
|
||||||
|
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
|
||||||
|
|
||||||
|
Connect( pxEVT_MSGBOX, pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
|
||||||
|
Connect( pxEVT_CallStackBox,pxMessageBoxEventThing( Pcsx2App::OnMessageBox ) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pcsx2App::OnMessageBox( wxCommandEvent& evt )
|
void Pcsx2App::OnMessageBox( pxMessageBoxEvent& evt )
|
||||||
{
|
{
|
||||||
Msgbox::OnEvent( evt );
|
Msgbox::OnEvent( evt );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1903,7 +1903,7 @@
|
||||||
Name="HostGUI"
|
Name="HostGUI"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\gui\App.h"
|
RelativePath="..\..\gui\AppAssert.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
@ -1914,18 +1914,10 @@
|
||||||
RelativePath="..\..\gui\CheckedStaticBox.cpp"
|
RelativePath="..\..\gui\CheckedStaticBox.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\gui\CheckedStaticBox.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\gui\ConsoleLogger.cpp"
|
RelativePath="..\..\gui\ConsoleLogger.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\gui\Resources\EmbeddedImage.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\gui\HostGui.cpp"
|
RelativePath="..\..\gui\HostGui.cpp"
|
||||||
>
|
>
|
||||||
|
@ -1942,10 +1934,6 @@
|
||||||
RelativePath="..\..\gui\IniInterface.cpp"
|
RelativePath="..\..\gui\IniInterface.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\gui\IniInterface.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\gui\main.cpp"
|
RelativePath="..\..\gui\main.cpp"
|
||||||
>
|
>
|
||||||
|
@ -1954,10 +1942,6 @@
|
||||||
RelativePath="..\..\gui\MainFrame.cpp"
|
RelativePath="..\..\gui\MainFrame.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\gui\MainFrame.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\gui\MainMenuClicks.cpp"
|
RelativePath="..\..\gui\MainMenuClicks.cpp"
|
||||||
>
|
>
|
||||||
|
@ -1966,10 +1950,6 @@
|
||||||
RelativePath="..\..\gui\wxHelpers.cpp"
|
RelativePath="..\..\gui\wxHelpers.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\gui\wxHelpers.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<Filter
|
<Filter
|
||||||
Name="Dialogs"
|
Name="Dialogs"
|
||||||
>
|
>
|
||||||
|
@ -2118,6 +2098,38 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Include"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\App.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\CheckedStaticBox.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\ConsoleLogger.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\Resources\EmbeddedImage.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\IniInterface.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\MainFrame.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\gui\wxHelpers.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="HostSystem"
|
Name="HostSystem"
|
||||||
|
|
|
@ -616,10 +616,19 @@ static void __naked DispatcherEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
void recExecute()
|
void recExecute()
|
||||||
|
{
|
||||||
|
g_EEFreezeRegs = true;
|
||||||
|
|
||||||
|
// Enter an endless loop, which is only escapable via C++ exception handling.
|
||||||
|
// The loop is needed because some things in the rec use "ret" as a shortcut to
|
||||||
|
// invoking DispatcherReg. These things are code bits which are called infrequently,
|
||||||
|
// such as dyna_block_discard and dyna_page_reset.
|
||||||
|
|
||||||
|
while( true )
|
||||||
{
|
{
|
||||||
// Optimization note : Compared pushad against manually pushing the regs one-by-one.
|
// Optimization note : Compared pushad against manually pushing the regs one-by-one.
|
||||||
// Manually pushing is faster, especially on Core2's and such. :)
|
// Manually pushing is faster, especially on Core2's and such. :)
|
||||||
g_EEFreezeRegs = true;
|
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
push ebx
|
push ebx
|
||||||
|
@ -634,6 +643,7 @@ void recExecute()
|
||||||
pop esi
|
pop esi
|
||||||
pop ebx
|
pop ebx
|
||||||
}
|
}
|
||||||
|
}
|
||||||
g_EEFreezeRegs = false;
|
g_EEFreezeRegs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue