* Added /gui/AppRes.cpp : contains resource management code that used to be in /gui/App.cpp.
 * Redid disk/linux console logging to be both thread safe and crash-safe.
 * Cleaned up plugin init/open exception handlers
 * Was forced to implement a manual version of wxEventLoop because of a critical design flaw in wxWidgets' message loop exception handler.


git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1727 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-09-02 11:22:16 +00:00
parent 600f7b2207
commit f7a44a7af2
17 changed files with 826 additions and 636 deletions

View File

@ -263,8 +263,7 @@ static void DetectDiskType()
// //
void CDVDsys_ChangeSource( CDVD_SourceType type ) void CDVDsys_ChangeSource( CDVD_SourceType type )
{ {
if( g_plugins != NULL ) GetPluginManager().Close( PluginId_CDVD );
g_plugins->Close( PluginId_CDVD );
switch( type ) switch( type )
{ {

View File

@ -19,6 +19,7 @@
#pragma once #pragma once
extern FILE *emuLog; extern FILE *emuLog;
extern wxString emuLogName;
extern char* disVU0MicroUF(u32 code, u32 pc); extern char* disVU0MicroUF(u32 code, u32 pc);
extern char* disVU0MicroLF(u32 code, u32 pc); extern char* disVU0MicroLF(u32 code, u32 pc);

View File

@ -268,6 +268,7 @@
<Unit filename="../gui/AppAssert.cpp" /> <Unit filename="../gui/AppAssert.cpp" />
<Unit filename="../gui/AppConfig.cpp" /> <Unit filename="../gui/AppConfig.cpp" />
<Unit filename="../gui/AppConfig.h" /> <Unit filename="../gui/AppConfig.h" />
<Unit filename="../gui/AppRes.cpp" />
<Unit filename="../gui/CheckedStaticBox.cpp" /> <Unit filename="../gui/CheckedStaticBox.cpp" />
<Unit filename="../gui/CheckedStaticBox.h" /> <Unit filename="../gui/CheckedStaticBox.h" />
<Unit filename="../gui/ConsoleLogger.cpp" /> <Unit filename="../gui/ConsoleLogger.cpp" />

View File

@ -214,7 +214,7 @@ void mtgsThreadObject::Start()
m_sem_InitDone.Wait(); m_sem_InitDone.Wait();
if( m_returncode != 0 ) // means the thread failed to init the GS plugin if( m_returncode != 0 ) // means the thread failed to init the GS plugin
throw Exception::PluginFailure( "GS", wxLt("%s plugin failed to open.") ); throw Exception::PluginOpenError( PluginId_GS );
} }
mtgsThreadObject::~mtgsThreadObject() mtgsThreadObject::~mtgsThreadObject()
@ -507,7 +507,7 @@ sptr mtgsThreadObject::ExecuteTask()
GSsetBaseMem( m_gsMem ); GSsetBaseMem( m_gsMem );
GSirqCallback( NULL ); GSirqCallback( NULL );
g_plugins->Open( PluginId_GS ); GetPluginManager().Open( PluginId_GS );
Console::WriteLn( "MTGS > GSopen Finished, return code: 0x%x", params m_returncode ); Console::WriteLn( "MTGS > GSopen Finished, return code: 0x%x", params m_returncode );
@ -629,7 +629,7 @@ sptr mtgsThreadObject::ExecuteTask()
{ {
freezeData* data = (freezeData*)(*(uptr*)&tag.data[1]); freezeData* data = (freezeData*)(*(uptr*)&tag.data[1]);
int mode = tag.data[0]; int mode = tag.data[0];
g_plugins->Freeze( PluginId_GS, mode, data ); GetPluginManager().Freeze( PluginId_GS, mode, data );
break; break;
} }
@ -667,7 +667,7 @@ sptr mtgsThreadObject::ExecuteTask()
break; break;
case GS_RINGTYPE_QUIT: case GS_RINGTYPE_QUIT:
g_plugins->Close( PluginId_GS ); GetPluginManager().Close( PluginId_GS );
m_sem_Quitter.Post(); m_sem_Quitter.Post();
return 0; return 0;

View File

@ -210,7 +210,7 @@ void LoadGSState(const wxString& file)
if (ret != 0) if (ret != 0)
{ {
delete f; delete f;
throw Exception::PluginFailure( "GS" ); throw Exception::PluginOpenError( PluginId_GS );
} }
ret = PADopen((void *)&pDsp); ret = PADopen((void *)&pDsp);

View File

@ -527,14 +527,14 @@ PluginManager *g_plugins = NULL;
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
Exception::InvalidPluginConfigured::InvalidPluginConfigured( PluginsEnum_t pid, const wxString& objname, const char* eng ) Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid, const wxString& objname, const char* eng )
{ {
BaseException::InitBaseEx( eng ); BaseException::InitBaseEx( eng );
StreamName = objname; StreamName = objname;
PluginId = pid; PluginId = pid;
} }
Exception::InvalidPluginConfigured::InvalidPluginConfigured( PluginsEnum_t pid, const wxString& objname, Exception::PluginLoadError::PluginLoadError( PluginsEnum_t pid, const wxString& objname,
const wxString& eng_msg, const wxString& xlt_msg ) const wxString& eng_msg, const wxString& xlt_msg )
{ {
BaseException::InitBaseEx( eng_msg, xlt_msg ); BaseException::InitBaseEx( eng_msg, xlt_msg );
@ -542,17 +542,26 @@ Exception::InvalidPluginConfigured::InvalidPluginConfigured( PluginsEnum_t pid,
PluginId = pid; PluginId = pid;
} }
wxString Exception::PluginFailure::FormatDiagnosticMessage() const wxString Exception::PluginLoadError::FormatDiagnosticMessage() const
{ {
return wxsFormat( return wxsFormat( m_message_diag, tbl_PluginInfo[PluginId].GetShortname() ) +
L"%s plugin has encountered an error.\n\n", L"\n\n" + StreamName;
plugin_name.c_str()
) + m_stacktrace;
} }
wxString Exception::PluginFailure::FormatDisplayMessage() const wxString Exception::PluginLoadError::FormatDisplayMessage() const
{ {
return wxsFormat( m_message_user, plugin_name.c_str() ); return wxsFormat( m_message_user, tbl_PluginInfo[PluginId].GetShortname() ) +
L"\n\n" + StreamName;
}
wxString Exception::PluginError::FormatDiagnosticMessage() const
{
return wxsFormat( m_message_diag, tbl_PluginInfo[PluginId].GetShortname() );
}
wxString Exception::PluginError::FormatDisplayMessage() const
{
return wxsFormat( m_message_user, tbl_PluginInfo[PluginId].GetShortname() );
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -570,14 +579,13 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
m_info[pid].Filename = folders[pid]; m_info[pid].Filename = folders[pid];
if( !wxFile::Exists( folders[pid] ) ) if( !wxFile::Exists( folders[pid] ) )
throw Exception::InvalidPluginConfigured( pid, folders[pid], throw Exception::PluginLoadError( pid, folders[pid],
L"Plugin file not found", wxLt("The configured %s plugin file was not found")
_("The configured plugin file was not found")
); );
if( !m_info[pid].Lib.Load( folders[pid] ) ) if( !m_info[pid].Lib.Load( folders[pid] ) )
throw Exception::InvalidPluginConfigured( pid, folders[pid], throw Exception::PluginLoadError( pid, folders[pid],
wxLt("Configured plugin file is not a valid dynamic library") wxLt("The configured %s plugin file is not a valid dynamic library")
); );
// Try to enumerate the new v2.0 plugin interface first. // Try to enumerate the new v2.0 plugin interface first.
@ -625,8 +633,8 @@ void PluginManager::BindCommon( PluginsEnum_t pid )
if( *target == NULL ) if( *target == NULL )
{ {
throw Exception::InvalidPluginConfigured( pid, m_info[pid].Filename, throw Exception::PluginLoadError( pid, m_info[pid].Filename,
wxLt( "Configured plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." ) ); wxLt( "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." ) );
} }
target++; target++;
@ -650,7 +658,7 @@ void PluginManager::BindRequired( PluginsEnum_t pid )
if( *(current->Dest) == NULL ) if( *(current->Dest) == NULL )
{ {
throw Exception::InvalidPluginConfigured( pid, m_info[pid].Filename, throw Exception::PluginLoadError( pid, m_info[pid].Filename,
wxLt( "Configured plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." ) ); wxLt( "Configured plugin is not a valid PCSX2 plugin, or is for an older unsupported version of PCSX2." ) );
} }
@ -766,7 +774,7 @@ void PluginManager::Open( PluginsEnum_t pid )
case PluginId_DEV9: result = OpenPlugin_DEV9(); break; case PluginId_DEV9: result = OpenPlugin_DEV9(); break;
} }
if( !result ) if( !result )
throw Exception::PluginFailure( tbl_PluginInfo[pid].shortname, wxLt("%s plugin failed to open.") ); throw Exception::PluginOpenError( pid );
m_info[pid].IsOpened = true; m_info[pid].IsOpened = true;
} }
@ -829,7 +837,7 @@ void PluginManager::Init()
if( m_info[pid].IsInitialized ) continue; if( m_info[pid].IsInitialized ) continue;
m_info[pid].IsInitialized = true; m_info[pid].IsInitialized = true;
if( 0 != m_info[pid].CommonBindings.Init() ) if( 0 != m_info[pid].CommonBindings.Init() )
throw Exception::PluginFailure( tbl_PluginInfo[pid].shortname, wxLt( "%s plugin: Initialization Failure" ) ); throw Exception::PluginInitError( pid );
} }
} }

View File

@ -52,35 +52,57 @@ namespace Exception
BaseException::InitBaseEx( msg ); BaseException::InitBaseEx( msg );
PluginId = pid; PluginId = pid;
} }
};
class PluginFailure : public virtual RuntimeError
{
public:
wxString plugin_name; // name of the plugin
public:
DEFINE_EXCEPTION_COPYTORS( PluginFailure )
explicit PluginFailure( const char* plugin, const char* msg="%s plugin encountered a critical error" )
{
BaseException::InitBaseEx( msg );
plugin_name = wxString::FromUTF8( plugin );
}
virtual wxString FormatDiagnosticMessage() const; virtual wxString FormatDiagnosticMessage() const;
virtual wxString FormatDisplayMessage() const; virtual wxString FormatDisplayMessage() const;
}; };
class InvalidPluginConfigured : public virtual PluginError, public virtual BadStream // Plugin load errors occur when initially trying to load plugins durign the
// creation of a PluginManager object. The error may either be due to non-existence,
// corruption, or incompatible versioning.
class PluginLoadError : public virtual PluginError, public virtual BadStream
{ {
public: public:
DEFINE_EXCEPTION_COPYTORS( InvalidPluginConfigured ) DEFINE_EXCEPTION_COPYTORS( PluginLoadError )
InvalidPluginConfigured( PluginsEnum_t pid, const wxString& objname, const char* eng ); PluginLoadError( PluginsEnum_t pid, const wxString& objname, const char* eng );
InvalidPluginConfigured( PluginsEnum_t pid, const wxString& objname, PluginLoadError( PluginsEnum_t pid, const wxString& objname,
const wxString& eng_msg, const wxString& xlt_msg ); const wxString& eng_msg, const wxString& xlt_msg );
virtual wxString FormatDiagnosticMessage() const;
virtual wxString FormatDisplayMessage() const;
};
// Thrown when a plugin fails it's init() callback. The meaning of this error is entirely
// dependent on the plugin and, in most cases probably never happens (most plugins do little
// more than a couple basic memory reservations during init)
class PluginInitError : public virtual PluginError
{
public:
DEFINE_EXCEPTION_COPYTORS( PluginInitError )
explicit PluginInitError( PluginsEnum_t pid,
const char* msg=wxLt("%s plugin failed to initialize. Your system may have insufficient memory or resources needed.") )
{
BaseException::InitBaseEx( msg );
PluginId = pid;
}
};
// Plugin failed to open. Typically this is a non-critical error that means the plugin has
// not been configured properly by the user, but may also be indicative of a system
class PluginOpenError : public virtual PluginError
{
public:
DEFINE_EXCEPTION_COPYTORS( PluginOpenError )
explicit PluginOpenError( PluginsEnum_t pid,
const char* msg=wxLt("%s plugin failed to open. Your computer may have insufficient resources, or incompatible hardware/drivers.") )
{
BaseException::InitBaseEx( msg );
PluginId = pid;
}
}; };
}; };

View File

@ -35,6 +35,7 @@
using namespace R5900; using namespace R5900;
FILE *emuLog; FILE *emuLog;
wxString emuLogName;
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
LogSources varLog; LogSources varLog;

View File

@ -180,6 +180,22 @@ protected:
void OnMessageBox( pxMessageBoxEvent& evt ); void OnMessageBox( pxMessageBoxEvent& evt );
void CleanupMess(); void CleanupMess();
void OpenWizardConsole(); void OpenWizardConsole();
int MainLoop();
// ----------------------------------------------------------------------------
// Override wx default exception handling behavior
// ----------------------------------------------------------------------------
// Just rethrow exceptions in the main loop, so that we can handle them properly in our
// custom catch clauses in OnRun(). (ranting note: wtf is the point of this functionality
// in wx? Why would anyone ever want a generic catch-all exception handler that *isn't*
// the unhandled exception handler? Using this as anything besides a re-throw is terrible
// program design and shouldn't even be allowed -- air)
bool OnExceptionInMainLoop() { throw; }
// Just rethrow unhandled exceptions to cause immediate debugger fail.
void OnUnhandledException() { throw; }
}; };
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////

View File

@ -22,6 +22,7 @@
#include "Plugins.h" #include "Plugins.h"
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include "DebugTools/Debug.h"
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// PathDefs Namespace -- contains default values for various pcsx2 path names and locations. // PathDefs Namespace -- contains default values for various pcsx2 path names and locations.
@ -630,5 +631,21 @@ void AppConfig_ReloadGlobalSettings( bool overwrite )
g_Conf->Apply(); g_Conf->Apply();
g_Conf->Folders.Logs.Mkdir(); g_Conf->Folders.Logs.Mkdir();
wxString newlogname( Path::Combine( g_Conf->Folders.Logs.ToString(), L"emuLog.txt" ) );
if( emuLog != NULL )
{
if( emuLogName != newlogname )
{
fclose( emuLog );
emuLog = NULL;
}
} }
if( emuLog == NULL )
{
emuLogName = newlogname;
emuLog = fopen( emuLogName.ToUTF8().data(), "wb" );
}
}

167
pcsx2/gui/AppRes.cpp Normal file
View File

@ -0,0 +1,167 @@
/* 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 "MainFrame.h"
#include <wx/zipstrm.h>
#include <wx/wfstream.h>
#include "Resources/EmbeddedImage.h"
#include "Resources/BackgroundLogo.h"
#include "Resources/ConfigIcon_Cpu.h"
#include "Resources/ConfigIcon_Video.h"
#include "Resources/ConfigIcon_Speedhacks.h"
#include "Resources/ConfigIcon_Gamefixes.h"
#include "Resources/ConfigIcon_Paths.h"
#include "Resources/ConfigIcon_Plugins.h"
// ------------------------------------------------------------------------
const wxImage& LoadImageAny(
wxImage& dest, bool useTheme, wxFileName& base, const wxChar* filename, IEmbeddedImage& onFail )
{
if( useTheme )
{
base.SetName( filename );
base.SetExt( L"png" );
if( base.FileExists() )
{
if( dest.LoadFile( base.GetFullPath() ) ) return dest;
}
base.SetExt( L"jpg" );
if( base.FileExists() )
{
if( dest.LoadFile( base.GetFullPath() ) ) return dest;
}
base.SetExt( L"bmp" );
if( base.FileExists() )
{
if( dest.LoadFile( base.GetFullPath() ) ) return dest;
}
}
return dest = onFail.Get();
}
// ------------------------------------------------------------------------
const wxBitmap& Pcsx2App::GetLogoBitmap()
{
if( m_Bitmap_Logo != NULL )
return *m_Bitmap_Logo;
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if( useTheme )
{
wxDirName theme( PathDefs::GetThemes() + g_Conf->DeskTheme );
wxFileName zipped( theme.GetFilename() );
zipped.SetExt( L"zip" );
if( zipped.FileExists() )
{
// loading theme from zipfile.
//wxFileInputStream stream( zipped.ToString() )
//wxZipInputStream zstream( stream );
Console::Error( "Loading themes from zipfile is not supported yet.\nFalling back on default theme." );
}
// Overrides zipfile settings (fix when zipfile support added)
mess = theme.ToString();
}
wxImage img;
EmbeddedImage<png_BackgroundLogo> temp; // because gcc can't allow non-const temporaries.
LoadImageAny( img, useTheme, mess, L"BackgroundLogo", temp );
m_Bitmap_Logo = new wxBitmap( img );
return *m_Bitmap_Logo;
}
// ------------------------------------------------------------------------
wxImageList& Pcsx2App::GetImgList_Config()
{
if( !m_ConfigImagesAreLoaded )
{
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if( useTheme )
{
wxDirName theme( PathDefs::GetThemes() + g_Conf->DeskTheme );
mess = theme.ToString();
}
wxImage img;
// GCC Specific: wxT() macro is required when using string token pasting. For some reason L
// generates syntax errors. >_<
#undef FancyLoadMacro
#define FancyLoadMacro( name ) \
{ \
EmbeddedImage<png_ConfigIcon_##name> temp( g_Conf->Listbook_ImageSize, g_Conf->Listbook_ImageSize ); \
m_ImageId.Config.name = m_ConfigImages.Add( LoadImageAny( \
img, useTheme, mess, L"ConfigIcon_" wxT(#name), temp ) \
); \
}
FancyLoadMacro( Paths );
FancyLoadMacro( Plugins );
FancyLoadMacro( Gamefixes );
FancyLoadMacro( Speedhacks );
FancyLoadMacro( Video );
FancyLoadMacro( Cpu );
}
m_ConfigImagesAreLoaded = true;
return m_ConfigImages;
}
// ------------------------------------------------------------------------
wxImageList& Pcsx2App::GetImgList_Toolbars()
{
if( m_ToolbarImages == NULL )
{
const int imgSize = g_Conf->Toolbar_ImageSize ? 64 : 32;
m_ToolbarImages = new wxImageList( imgSize, imgSize );
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if( useTheme )
{
wxDirName theme( PathDefs::GetThemes() + g_Conf->DeskTheme );
mess = theme.ToString();
}
wxImage img;
#undef FancyLoadMacro
#define FancyLoadMacro( name ) \
{ \
EmbeddedImage<png_ToolbarIcon_##name> temp( imgSize, imgSize ); \
m_ImageId.Toolbars.name = m_ConfigImages.Add( LoadImageAny( img, useTheme, mess, L"ToolbarIcon" wxT(#name), temp ) ); \
}
}
return *m_ToolbarImages;
}

View File

@ -314,19 +314,6 @@ void ConsoleLogFrame::ClearColor()
void ConsoleLogFrame::Write( const wxString& text ) void ConsoleLogFrame::Write( const wxString& text )
{ {
// Many platforms still do not provide thread-safe implementations of
// fputs or printf, so they need to be implemented here.
// fixme: these really should go in the global message handler but I haven't time to
// do that right now.
if( emuLog != NULL )
fputs( text.ToUTF8().data(), emuLog );
// Linux has a handy dandy universal console...
// [TODO] make this a configurable option? Do we care? :)
#ifdef __LINUX__
printf( (L"PCSX2 > " + text).ToUTF8().data() );
#endif
// remove selection (WriteText is in fact ReplaceSelection) // remove selection (WriteText is in fact ReplaceSelection)
// TODO : Optimize this to only replace selection if some selection // TODO : Optimize this to only replace selection if some selection
// messages have been received since the last write. // messages have been received since the last write.
@ -572,7 +559,34 @@ void ConsoleLogFrame::DoMessage()
namespace Console namespace Console
{ {
// thread-local console color storage. // thread-local console color storage.
__threadlocal Colors th_CurrentColor = DefaultConsoleColor; static __threadlocal Colors th_CurrentColor = DefaultConsoleColor;
static Threading::MutexLock immediate_log_lock;
// performs immediate thread-safe (mutex locked) logging to disk and to the Linux console.
// Many platforms still do not provide thread-safe implementations of fputs or printf, so
// they are implemented here using a mutex lock for maximum safety.
static void _immediate_logger( const char* src )
{
ScopedLock locker( immediate_log_lock );
if( emuLog != NULL )
fputs( src, emuLog ); // fputs does not do automatic newlines, so it's ok!
// Linux has a handy dandy universal console...
// [TODO] make this a configurable option? Do we care? :)
#ifdef __LINUX__
// puts does automatic newlines, which we don't want here
fputs( L"PCSX2 > ", stdout );
fputs( src, stdout );
#endif
}
static void _immediate_logger( const wxString& src )
{
_immediate_logger( src.ToUTF8().data() );
}
void __fastcall SetTitle( const wxString& title ) void __fastcall SetTitle( const wxString& title )
{ {
@ -593,6 +607,8 @@ namespace Console
bool Newline() bool Newline()
{ {
_immediate_logger( "\n" );
wxCommandEvent evt( wxEVT_LOG_Newline ); wxCommandEvent evt( wxEVT_LOG_Newline );
wxGetApp().ProgramLog_PostEvent( evt ); wxGetApp().ProgramLog_PostEvent( evt );
wxGetApp().ProgramLog_CountMsg(); wxGetApp().ProgramLog_CountMsg();
@ -602,6 +618,8 @@ namespace Console
bool __fastcall Write( const char* fmt ) bool __fastcall Write( const char* fmt )
{ {
_immediate_logger( fmt );
wxCommandEvent evt( wxEVT_LOG_Write ); wxCommandEvent evt( wxEVT_LOG_Write );
evt.SetString( wxString::FromAscii( fmt ) ); evt.SetString( wxString::FromAscii( fmt ) );
evt.SetExtraLong( th_CurrentColor ); evt.SetExtraLong( th_CurrentColor );
@ -613,6 +631,8 @@ namespace Console
bool __fastcall Write( const wxString& fmt ) bool __fastcall Write( const wxString& fmt )
{ {
_immediate_logger( fmt );
wxCommandEvent evt( wxEVT_LOG_Write ); wxCommandEvent evt( wxEVT_LOG_Write );
evt.SetString( fmt ); evt.SetString( fmt );
evt.SetExtraLong( th_CurrentColor ); evt.SetExtraLong( th_CurrentColor );
@ -624,11 +644,14 @@ namespace Console
bool __fastcall WriteLn( const char* fmt ) bool __fastcall WriteLn( const char* fmt )
{ {
const wxString fmtline( wxString::FromAscii( fmt ) + L"\n" );
_immediate_logger( fmtline );
// Implementation note: I've duplicated Write+Newline behavior here to avoid polluting // Implementation note: I've duplicated Write+Newline behavior here to avoid polluting
// the message pump with lots of erroneous messages (Newlines can be bound into Write message). // the message pump with lots of erroneous messages (Newlines can be bound into Write message).
wxCommandEvent evt( wxEVT_LOG_Write ); wxCommandEvent evt( wxEVT_LOG_Write );
evt.SetString( wxString::FromAscii( fmt ) + L"\n" ); evt.SetString( fmtline );
evt.SetExtraLong( th_CurrentColor ); evt.SetExtraLong( th_CurrentColor );
wxGetApp().ProgramLog_PostEvent( evt ); wxGetApp().ProgramLog_PostEvent( evt );
wxGetApp().ProgramLog_CountMsg(); wxGetApp().ProgramLog_CountMsg();
@ -638,11 +661,14 @@ namespace Console
bool __fastcall WriteLn( const wxString& fmt ) bool __fastcall WriteLn( const wxString& fmt )
{ {
const wxString fmtline( fmt + L"\n" );
_immediate_logger( fmtline );
// Implementation note: I've duplicated Write+Newline behavior here to avoid polluting // Implementation note: I've duplicated Write+Newline behavior here to avoid polluting
// the message pump with lots of erroneous messages (Newlines can be bound into Write message). // the message pump with lots of erroneous messages (Newlines can be bound into Write message).
wxCommandEvent evt( wxEVT_LOG_Write ); wxCommandEvent evt( wxEVT_LOG_Write );
evt.SetString( fmt + L"\n" ); evt.SetString( fmtline );
evt.SetExtraLong( th_CurrentColor ); evt.SetExtraLong( th_CurrentColor );
wxGetApp().ProgramLog_PostEvent( evt ); wxGetApp().ProgramLog_PostEvent( evt );
wxGetApp().ProgramLog_CountMsg(); wxGetApp().ProgramLog_CountMsg();

View File

@ -98,7 +98,7 @@ namespace HostGui
SysSuspend(); SysSuspend();
StateRecovery::MakeGsOnly(); StateRecovery::MakeGsOnly();
g_plugins->Close( PluginId_GS ); GetPluginManager().Close( PluginId_GS );
renderswitch = !renderswitch; renderswitch = !renderswitch;
StateRecovery::Recover(); StateRecovery::Recover();

View File

@ -89,6 +89,7 @@ void MainEmuFrame::Menu_RunIso_Click(wxCommandEvent &event)
} }
} }
InitPlugins();
SysExecute( new AppEmuThread( elf_file ), CDVDsrc_Iso ); SysExecute( new AppEmuThread( elf_file ), CDVDsrc_Iso );
} }
@ -109,6 +110,7 @@ void MainEmuFrame::Menu_RunWithoutDisc_Click(wxCommandEvent &event)
} }
SysEndExecution(); SysEndExecution();
InitPlugins();
SysExecute( new AppEmuThread(), CDVDsrc_NoDisc ); SysExecute( new AppEmuThread(), CDVDsrc_NoDisc );
} }

View File

@ -91,10 +91,7 @@ public:
m_type = m_GetLibType(); m_type = m_GetLibType();
} }
// Parameters: bool CheckVersion( PluginsEnum_t pluginTypeIndex ) const
// pluginTypeIndex - Value from 1 to 8 which represents the plugin's index.
//
bool CheckVersion( int pluginTypeIndex ) const
{ {
const PluginInfo& info( tbl_PluginInfo[pluginTypeIndex] ); const PluginInfo& info( tbl_PluginInfo[pluginTypeIndex] );
if( m_type & info.typemask ) if( m_type & info.typemask )
@ -436,36 +433,37 @@ void Panels::PluginSelectorPanel::EnumThread::Cancel()
sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask() sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask()
{ {
DevCon::WriteLn( "Plugin Enumeration Thread started..." ); DevCon::Status( "Plugin Enumeration Thread started..." );
Sleep( 10 ); // gives the gui thread some time to refresh Sleep( 10 ); // gives the gui thread some time to refresh
for( int curidx=0; curidx < m_master.FileCount(); ++curidx ) for( int curidx=0; curidx < m_master.FileCount(); ++curidx )
{ {
if( m_cancel ) return 0; if( m_cancel ) return 0;
DbgCon::WriteLn( L"Enumerating Plugin: " + m_master.GetFilename( curidx ) );
Results[curidx].TypeMask = 0;
try try
{ {
PluginEnumerator penum( m_master.GetFilename( curidx ) );
EnumeratedPluginInfo& result( Results[curidx] ); EnumeratedPluginInfo& result( Results[curidx] );
result.TypeMask = 0;
PluginEnumerator penum( m_master.GetFilename( curidx ) );
result.Name = penum.GetName(); result.Name = penum.GetName();
for( int pidx=0; pidx<NumPluginTypes; ++pidx ) for( int pidx=0; pidx<PluginId_Count; ++pidx )
{ {
result.TypeMask |= tbl_PluginInfo[pidx].typemask; const PluginsEnum_t pid = (PluginsEnum_t)pidx;
if( penum.CheckVersion( pidx ) ) result.TypeMask |= tbl_PluginInfo[pid].typemask;
if( penum.CheckVersion( pid ) )
{ {
result.PassedTest |= tbl_PluginInfo[pidx].typemask; result.PassedTest |= tbl_PluginInfo[pid].typemask;
penum.GetVersionString( result.Version[pidx], pidx ); penum.GetVersionString( result.Version[pid], pidx );
} }
} }
} }
catch( Exception::BadStream& ex ) catch( Exception::BadStream& ex )
{ {
Console::Status( ex.FormatDiagnosticMessage() ); Console::Status( ex.FormatDiagnosticMessage() );
} }
pthread_testcancel(); pthread_testcancel();
@ -478,6 +476,6 @@ sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask()
wxCommandEvent done( wxEVT_EnumerationFinished ); wxCommandEvent done( wxEVT_EnumerationFinished );
m_master.GetEventHandler()->AddPendingEvent( done ); m_master.GetEventHandler()->AddPendingEvent( done );
DevCon::WriteLn( "Plugin Enumeration Thread complete!" ); DevCon::Status( "Plugin Enumeration Thread complete!" );
return 0; return 0;
} }

View File

@ -23,14 +23,11 @@
#include "Plugins.h" #include "Plugins.h"
#include "Dialogs/ModalPopups.h" #include "Dialogs/ModalPopups.h"
#include "Utilities/ScopedPtr.h" #include "Utilities/ScopedPtr.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/BackgroundLogo.h"
#include <wx/cmdline.h> #include <wx/cmdline.h>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <wx/evtloop.h>
IMPLEMENT_APP(Pcsx2App) IMPLEMENT_APP(Pcsx2App)
@ -310,6 +307,78 @@ void Pcsx2App::CleanupMess()
safe_delete( g_Conf ); safe_delete( g_Conf );
} }
static int pxRunningEventLoopCount = 0;
class pxEvtLoop : public wxEventLoop
{
protected:
struct pxRunningEventLoopCounter
{
pxRunningEventLoopCounter() { pxRunningEventLoopCount++; }
~pxRunningEventLoopCounter() { pxRunningEventLoopCount--; }
};
public:
virtual int Run()
{
// event loops are not recursive, you need to create another loop!
wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
wxEventLoopActivator activate(wx_static_cast(wxEventLoop *, this));
#if defined(__WXMSW__) && wxUSE_THREADS
pxRunningEventLoopCounter evtLoopCounter;
#endif // __WXMSW__
while( true )
{
try
{
while( !m_shouldExit )
{
// give ourselves the possibility to do whatever we want!
OnNextIteration();
while( Pending() )
{
if( !Dispatch() )
{
m_shouldExit = true;
break;
}
}
if( wxTheApp )
wxTheApp->ProcessIdle();
}
break;
}
// ----------------------------------------------------------------------------
catch( Exception::PluginError& ex )
{
}
// ----------------------------------------------------------------------------
catch( Exception::RuntimeError& ex )
{
// Runtime errors which have been unhandled should still be safe to recover from,
// so lets issue a message to the user and then continue the message pump.
Console::Error( ex.FormatDiagnosticMessage() );
Msgbox::Alert( ex.FormatDisplayMessage() );
}
}
}
};
// This overload performs universal exception handling for specific types of recoverable
// errors that can be thrown from a multitude of events.
int Pcsx2App::MainLoop()
{
assert( m_mainLoop == NULL );
m_mainLoop = new pxEvtLoop();
return m_mainLoop->Run();
}
// Common exit handler which can be called from any event (though really it should // Common exit handler which can be called from any event (though really it should
// be called only from CloseWindow handlers since that's the more appropriate way // be called only from CloseWindow handlers since that's the more appropriate way
// to handle window closures) // to handle window closures)
@ -320,6 +389,7 @@ bool Pcsx2App::PrepForExit()
int Pcsx2App::OnExit() int Pcsx2App::OnExit()
{ {
m_ProgramLogBox = NULL;
MemoryCard::Shutdown(); MemoryCard::Shutdown();
if( g_Conf != NULL ) if( g_Conf != NULL )
@ -345,146 +415,4 @@ Pcsx2App::~Pcsx2App()
CleanupMess(); CleanupMess();
} }
#include <wx/zipstrm.h>
#include <wx/wfstream.h>
// ------------------------------------------------------------------------
const wxImage& LoadImageAny(
wxImage& dest, bool useTheme, wxFileName& base, const wxChar* filename, IEmbeddedImage& onFail )
{
if( useTheme )
{
base.SetName( filename );
base.SetExt( L"png" );
if( base.FileExists() )
{
if( dest.LoadFile( base.GetFullPath() ) ) return dest;
}
base.SetExt( L"jpg" );
if( base.FileExists() )
{
if( dest.LoadFile( base.GetFullPath() ) ) return dest;
}
base.SetExt( L"bmp" );
if( base.FileExists() )
{
if( dest.LoadFile( base.GetFullPath() ) ) return dest;
}
}
return dest = onFail.Get();
}
// ------------------------------------------------------------------------
const wxBitmap& Pcsx2App::GetLogoBitmap()
{
if( m_Bitmap_Logo != NULL )
return *m_Bitmap_Logo;
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if( useTheme )
{
wxDirName theme( PathDefs::GetThemes() + g_Conf->DeskTheme );
wxFileName zipped( theme.GetFilename() );
zipped.SetExt( L"zip" );
if( zipped.FileExists() )
{
// loading theme from zipfile.
//wxFileInputStream stream( zipped.ToString() )
//wxZipInputStream zstream( stream );
Console::Error( "Loading themes from zipfile is not supported yet.\nFalling back on default theme." );
}
// Overrides zipfile settings (fix when zipfile support added)
mess = theme.ToString();
}
wxImage img;
EmbeddedImage<png_BackgroundLogo> temp; // because gcc can't allow non-const temporaries.
LoadImageAny( img, useTheme, mess, L"BackgroundLogo", temp );
m_Bitmap_Logo = new wxBitmap( img );
return *m_Bitmap_Logo;
}
#include "Resources/ConfigIcon_Cpu.h"
#include "Resources/ConfigIcon_Video.h"
#include "Resources/ConfigIcon_Speedhacks.h"
#include "Resources/ConfigIcon_Gamefixes.h"
#include "Resources/ConfigIcon_Paths.h"
#include "Resources/ConfigIcon_Plugins.h"
// ------------------------------------------------------------------------
wxImageList& Pcsx2App::GetImgList_Config()
{
if( !m_ConfigImagesAreLoaded )
{
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if( useTheme )
{
wxDirName theme( PathDefs::GetThemes() + g_Conf->DeskTheme );
mess = theme.ToString();
}
wxImage img;
// GCC Specific: wxT() macro is required when using string token pasting. For some reason L
// generates syntax errors. >_<
#undef FancyLoadMacro
#define FancyLoadMacro( name ) \
{ \
EmbeddedImage<png_ConfigIcon_##name> temp( g_Conf->Listbook_ImageSize, g_Conf->Listbook_ImageSize ); \
m_ImageId.Config.name = m_ConfigImages.Add( LoadImageAny( \
img, useTheme, mess, L"ConfigIcon_" wxT(#name), temp ) \
); \
}
FancyLoadMacro( Paths );
FancyLoadMacro( Plugins );
FancyLoadMacro( Gamefixes );
FancyLoadMacro( Speedhacks );
FancyLoadMacro( Video );
FancyLoadMacro( Cpu );
}
m_ConfigImagesAreLoaded = true;
return m_ConfigImages;
}
// ------------------------------------------------------------------------
wxImageList& Pcsx2App::GetImgList_Toolbars()
{
if( m_ToolbarImages == NULL )
{
const int imgSize = g_Conf->Toolbar_ImageSize ? 64 : 32;
m_ToolbarImages = new wxImageList( imgSize, imgSize );
wxFileName mess;
bool useTheme = (g_Conf->DeskTheme != L"default");
if( useTheme )
{
wxDirName theme( PathDefs::GetThemes() + g_Conf->DeskTheme );
mess = theme.ToString();
}
wxImage img;
#undef FancyLoadMacro
#define FancyLoadMacro( name ) \
{ \
EmbeddedImage<png_ToolbarIcon_##name> temp( imgSize, imgSize ); \
m_ImageId.Toolbars.name = m_ConfigImages.Add( LoadImageAny( img, useTheme, mess, L"ToolbarIcon" wxT(#name), temp ) ); \
}
}
return *m_ToolbarImages;
}

View File

@ -1914,6 +1914,10 @@
RelativePath="..\..\gui\AppConfig.cpp" RelativePath="..\..\gui\AppConfig.cpp"
> >
</File> </File>
<File
RelativePath="..\..\gui\AppRes.cpp"
>
</File>
<File <File
RelativePath="..\..\gui\CheckedStaticBox.cpp" RelativePath="..\..\gui\CheckedStaticBox.cpp"
> >