From 483c6878a4d9ac79941dac29fdb61d81c0075b5e Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Thu, 1 Jul 2010 15:08:12 +0000 Subject: [PATCH] UI: * Added more thread checks when closing the program, to avoid occasional crashes or hangs. * Close the GS window on shutdown or critical errors. * Fixed part of Issue 679 (excessive CDVDiso popup errors) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3357 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CDVD/CDVDaccess.cpp | 3 +- pcsx2/PluginManager.cpp | 147 ++++++++++++++++++--------------- pcsx2/Plugins.h | 34 ++++---- pcsx2/System/SysCoreThread.cpp | 3 +- pcsx2/gui/App.h | 3 +- pcsx2/gui/AppCorePlugins.cpp | 106 +++++++++++++++--------- pcsx2/gui/AppCorePlugins.h | 20 ++--- pcsx2/gui/AppCoreThread.cpp | 69 +++++++++++----- pcsx2/gui/AppCoreThread.h | 2 +- pcsx2/gui/AppInit.cpp | 9 +- pcsx2/gui/AppMain.cpp | 43 ++-------- pcsx2/gui/ExecutorThread.cpp | 8 +- pcsx2/gui/FrameForGS.cpp | 14 +++- pcsx2/gui/GSFrame.h | 3 + pcsx2/gui/MainFrame.cpp | 2 + pcsx2/gui/MainMenuClicks.cpp | 26 +----- pcsx2/gui/pxEventThread.h | 18 +++- 17 files changed, 281 insertions(+), 229 deletions(-) diff --git a/pcsx2/CDVD/CDVDaccess.cpp b/pcsx2/CDVD/CDVDaccess.cpp index 7e5a2717af..5e6b8f387c 100644 --- a/pcsx2/CDVD/CDVDaccess.cpp +++ b/pcsx2/CDVD/CDVDaccess.cpp @@ -332,7 +332,8 @@ bool DoCDVDopen() m_SourceFilename[m_CurrentSourceType].ToUTF8() : (char*)NULL ); - if( ret == -1 ) return false; + if( ret == -1 ) return false; // error! (handled by caller) + if( ret == 1 ) throw Exception::CancelEvent(L"User canceled the CDVD plugin's open dialog."); int cdtype = DoCDVDdetectDiskType(); diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 089286fa43..1997ccbde3 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -611,7 +611,7 @@ static const LegacyApi_OptMethod* const s_MethMessOpt[] = s_MethMessOpt_DEV9 }; -PluginManager *g_plugins = NULL; +SysCorePlugins *g_plugins = NULL; // --------------------------------------------------------------------------------- // Plugin-related Exception Implementations @@ -721,7 +721,7 @@ static void PS2E_CALLBACK pcsx2_OSD_WriteLn( int icon, const char* msg ) // --------------------------------------------------------------------------------- // PluginStatus_t Implementations // --------------------------------------------------------------------------------- -PluginManager::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxString& srcfile ) +SysCorePlugins::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxString& srcfile ) : Filename( srcfile ) { pid = _pid; @@ -784,7 +784,7 @@ PluginManager::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxStrin .SetUserMsg(_("The plugin reports that your hardware or software/drivers are not supported.")); } -void PluginManager::PluginStatus_t::BindCommon( PluginsEnum_t pid ) +void SysCorePlugins::PluginStatus_t::BindCommon( PluginsEnum_t pid ) { const LegacyApi_CommonMethod* current = s_MethMessCommon; VoidMethod** target = (VoidMethod**)&CommonBindings; @@ -810,7 +810,7 @@ void PluginManager::PluginStatus_t::BindCommon( PluginsEnum_t pid ) } } -void PluginManager::PluginStatus_t::BindRequired( PluginsEnum_t pid ) +void SysCorePlugins::PluginStatus_t::BindRequired( PluginsEnum_t pid ) { const LegacyApi_ReqMethod* current = s_MethMessReq[pid]; const wxDynamicLibrary& lib = Lib; @@ -835,7 +835,7 @@ void PluginManager::PluginStatus_t::BindRequired( PluginsEnum_t pid ) } } -void PluginManager::PluginStatus_t::BindOptional( PluginsEnum_t pid ) +void SysCorePlugins::PluginStatus_t::BindOptional( PluginsEnum_t pid ) { const LegacyApi_OptMethod* current = s_MethMessOpt[pid]; const wxDynamicLibrary& lib = Lib; @@ -850,14 +850,14 @@ void PluginManager::PluginStatus_t::BindOptional( PluginsEnum_t pid ) } // ===================================================================================== -// PluginManager Implementations +// SysCorePlugins Implementations // ===================================================================================== -PluginManager::PluginManager() +SysCorePlugins::SysCorePlugins() { } -PluginManager::~PluginManager() throw() +SysCorePlugins::~SysCorePlugins() throw() { try { @@ -868,7 +868,7 @@ PluginManager::~PluginManager() throw() // All library unloading done automatically by wx. } -void PluginManager::Load( PluginsEnum_t pid, const wxString& srcfile ) +void SysCorePlugins::Load( PluginsEnum_t pid, const wxString& srcfile ) { ScopedLock lock( m_mtx_PluginStatus ); pxAssume( (uint)pid < PluginId_Count ); @@ -876,7 +876,7 @@ void PluginManager::Load( PluginsEnum_t pid, const wxString& srcfile ) m_info[pid] = new PluginStatus_t( pid, srcfile ); } -void PluginManager::Load( const wxString (&folders)[PluginId_Count] ) +void SysCorePlugins::Load( const wxString (&folders)[PluginId_Count] ) { if( !NeedsLoad() ) return; @@ -934,14 +934,14 @@ void PluginManager::Load( const wxString (&folders)[PluginId_Count] ) SendSettingsFolder(); } -void PluginManager::Unload(PluginsEnum_t pid) +void SysCorePlugins::Unload(PluginsEnum_t pid) { ScopedLock lock( m_mtx_PluginStatus ); pxAssume( (uint)pid < PluginId_Count ); m_info[pid].Delete(); } -void PluginManager::Unload() +void SysCorePlugins::Unload() { if( NeedsShutdown() ) Console.Warning( "(SysCorePlugins) Warning: Unloading plugins prior to shutdown!" ); @@ -967,23 +967,23 @@ extern void spu2DMA4Irq(); extern void spu2DMA7Irq(); extern void spu2Irq(); -bool PluginManager::OpenPlugin_CDVD() +bool SysCorePlugins::OpenPlugin_CDVD() { return DoCDVDopen(); } -bool PluginManager::OpenPlugin_GS() +bool SysCorePlugins::OpenPlugin_GS() { GetMTGS().Resume(); return true; } -bool PluginManager::OpenPlugin_PAD() +bool SysCorePlugins::OpenPlugin_PAD() { return !PADopen( (void*)&pDsp ); } -bool PluginManager::OpenPlugin_SPU2() +bool SysCorePlugins::OpenPlugin_SPU2() { if( SPU2open((void*)&pDsp) ) return false; @@ -997,7 +997,7 @@ bool PluginManager::OpenPlugin_SPU2() return true; } -bool PluginManager::OpenPlugin_DEV9() +bool SysCorePlugins::OpenPlugin_DEV9() { dev9Handler = NULL; @@ -1007,7 +1007,7 @@ bool PluginManager::OpenPlugin_DEV9() return true; } -bool PluginManager::OpenPlugin_USB() +bool SysCorePlugins::OpenPlugin_USB() { usbHandler = NULL; @@ -1019,14 +1019,14 @@ bool PluginManager::OpenPlugin_USB() return true; } -bool PluginManager::OpenPlugin_FW() +bool SysCorePlugins::OpenPlugin_FW() { if( FWopen((void*)&pDsp) ) return false; FWirqCallback( fwIrq ); return true; } -bool PluginManager::OpenPlugin_Mcd() +bool SysCorePlugins::OpenPlugin_Mcd() { ScopedLock lock( m_mtx_PluginStatus ); @@ -1037,7 +1037,7 @@ bool PluginManager::OpenPlugin_Mcd() return true; } -void PluginManager::Open( PluginsEnum_t pid ) +void SysCorePlugins::Open( PluginsEnum_t pid ) { pxAssume( (uint)pid < PluginId_Count ); if( IsOpen(pid) ) return; @@ -1066,7 +1066,7 @@ void PluginManager::Open( PluginsEnum_t pid ) if( m_info[pid] ) m_info[pid]->IsOpened = true; } -void PluginManager::Open() +void SysCorePlugins::Open() { Init(); @@ -1095,13 +1095,13 @@ void PluginManager::Open() Console.WriteLn( Color_StrongBlue, "Plugins opened successfully." ); } -void PluginManager::_generalclose( PluginsEnum_t pid ) +void SysCorePlugins::_generalclose( PluginsEnum_t pid ) { ScopedLock lock( m_mtx_PluginStatus ); if( m_info[pid] ) m_info[pid]->CommonBindings.Close(); } -void PluginManager::ClosePlugin_GS() +void SysCorePlugins::ClosePlugin_GS() { // old-skool: force-close PAD before GS, because the PAD depends on the GS window. @@ -1114,43 +1114,43 @@ void PluginManager::ClosePlugin_GS() } } -void PluginManager::ClosePlugin_CDVD() +void SysCorePlugins::ClosePlugin_CDVD() { DoCDVDclose(); } -void PluginManager::ClosePlugin_PAD() +void SysCorePlugins::ClosePlugin_PAD() { _generalclose( PluginId_PAD ); } -void PluginManager::ClosePlugin_SPU2() +void SysCorePlugins::ClosePlugin_SPU2() { _generalclose( PluginId_SPU2 ); } -void PluginManager::ClosePlugin_DEV9() +void SysCorePlugins::ClosePlugin_DEV9() { _generalclose( PluginId_DEV9 ); } -void PluginManager::ClosePlugin_USB() +void SysCorePlugins::ClosePlugin_USB() { _generalclose( PluginId_USB ); } -void PluginManager::ClosePlugin_FW() +void SysCorePlugins::ClosePlugin_FW() { _generalclose( PluginId_FW ); } -void PluginManager::ClosePlugin_Mcd() +void SysCorePlugins::ClosePlugin_Mcd() { ScopedLock lock( m_mtx_PluginStatus ); if( SysPlugins.Mcd ) SysPlugins.Mcd->Base.EmuClose( (PS2E_THISPTR) SysPlugins.Mcd ); } -void PluginManager::Close( PluginsEnum_t pid ) +void SysCorePlugins::Close( PluginsEnum_t pid ) { pxAssume( (uint)pid < PluginId_Count ); @@ -1177,7 +1177,7 @@ void PluginManager::Close( PluginsEnum_t pid ) if( m_info[pid] ) m_info[pid]->IsOpened = false; } -void PluginManager::Close() +void SysCorePlugins::Close() { if( !NeedsClose() ) return; // Spam stopper; returns before writing any logs. >_< @@ -1198,7 +1198,7 @@ void PluginManager::Close() DbgCon.WriteLn( Color_StrongBlue, "Plugins closed successfully." ); } -void PluginManager::Init( PluginsEnum_t pid ) +void SysCorePlugins::Init( PluginsEnum_t pid ) { ScopedLock lock( m_mtx_PluginStatus ); @@ -1211,7 +1211,7 @@ void PluginManager::Init( PluginsEnum_t pid ) m_info[pid]->IsInitialized = true; } -void PluginManager::Shutdown( PluginsEnum_t pid ) +void SysCorePlugins::Shutdown( PluginsEnum_t pid ) { ScopedLock lock( m_mtx_PluginStatus ); @@ -1225,13 +1225,16 @@ void PluginManager::Shutdown( PluginsEnum_t pid ) // session. During a session emulation can be paused/resumed using Open/Close, and should be // terminated using Shutdown(). // +// Returns TRUE if an init was performed for any (or all) plugins. Returns FALSE if all +// plugins were already in an initialized state (no action taken). +// // In a purist emulation sense, Init() and Shutdown() should only ever need be called for when // the PS2's hardware has received a *full* hard reset. Soft resets typically should rely on // the PS2's bios/kernel to re-initialize hardware on the fly. // -void PluginManager::Init() +bool SysCorePlugins::Init() { - if( !NeedsInit() ) return; + if( !NeedsInit() ) return false; Console.WriteLn( Color_StrongBlue, "\nInitializing plugins..." ); const PluginInfo* pi = tbl_PluginInfo; do { @@ -1250,18 +1253,22 @@ void PluginManager::Init() } Console.WriteLn( Color_StrongBlue, "Plugins initialized successfully.\n" ); + + return true; } // Shuts down all plugins. Plugins are closed first, if necessary. +// Returns TRUE if a shutdown was performed for any (or all) plugins. Returns FALSE if all +// plugins were already in shutdown state (no action taken). // // In a purist emulation sense, Init() and Shutdown() should only ever need be called for when // the PS2's hardware has received a *full* hard reset. Soft resets typically should rely on // the PS2's bios/kernel to re-initialize hardware on the fly. // -void PluginManager::Shutdown() +bool SysCorePlugins::Shutdown() { - if( !NeedsShutdown() ) return; + if( !NeedsShutdown() ) return false; pxAssumeDev( !NeedsClose(), "Cannot shut down plugins prior to Close()" ); @@ -1286,11 +1293,13 @@ void PluginManager::Shutdown() } DbgCon.WriteLn( Color_StrongGreen, "Plugins shutdown successfully." ); + + return true; } // For internal use only, unless you're the MTGS. Then it's for you too! // Returns false if the plugin returned an error. -bool PluginManager::DoFreeze( PluginsEnum_t pid, int mode, freezeData* data ) +bool SysCorePlugins::DoFreeze( PluginsEnum_t pid, int mode, freezeData* data ) { if( (pid == PluginId_GS) && !GetMTGS().IsSelf() ) { @@ -1312,7 +1321,7 @@ bool PluginManager::DoFreeze( PluginsEnum_t pid, int mode, freezeData* data ) // as it has special handlers to ensure that GS freeze commands are executed appropriately on the // GS thread. // -void PluginManager::Freeze( PluginsEnum_t pid, SaveStateBase& state ) +void SysCorePlugins::Freeze( PluginsEnum_t pid, SaveStateBase& state ) { // No locking leeded -- DoFreeze locks as needed, and this avoids MTGS deadlock. //ScopedLock lock( m_mtx_PluginStatus ); @@ -1361,7 +1370,7 @@ void PluginManager::Freeze( PluginsEnum_t pid, SaveStateBase& state ) state.CommitBlock( fP.size ); } -bool PluginManager::KeyEvent( const keyEvent& evt ) +bool SysCorePlugins::KeyEvent( const keyEvent& evt ) { ScopedLock lock( m_mtx_PluginStatus ); @@ -1378,7 +1387,7 @@ bool PluginManager::KeyEvent( const keyEvent& evt ) return false; } -void PluginManager::SendSettingsFolder() +void SysCorePlugins::SendSettingsFolder() { ScopedLock lock( m_mtx_PluginStatus ); if( m_SettingsFolder.IsEmpty() ) return; @@ -1390,7 +1399,7 @@ void PluginManager::SendSettingsFolder() } while( ++pi, pi->shortname != NULL ); } -void PluginManager::SetSettingsFolder( const wxString& folder ) +void SysCorePlugins::SetSettingsFolder( const wxString& folder ) { ScopedLock lock( m_mtx_PluginStatus ); @@ -1402,10 +1411,9 @@ void PluginManager::SetSettingsFolder( const wxString& folder ) if( m_SettingsFolder == fixedfolder ) return; m_SettingsFolder = fixedfolder; - SendSettingsFolder(); } -void PluginManager::SendLogFolder() +void SysCorePlugins::SendLogFolder() { ScopedLock lock( m_mtx_PluginStatus ); if( m_LogFolder.IsEmpty() ) return; @@ -1413,11 +1421,11 @@ void PluginManager::SendLogFolder() pxToUTF8 utf8buffer( m_LogFolder ); const PluginInfo* pi = tbl_PluginInfo; do { - if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetLogFolder( utf8buffer ); + if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetLogDir( utf8buffer ); } while( ++pi, pi->shortname != NULL ); } -void PluginManager::SetLogFolder( const wxString& folder ) +void SysCorePlugins::SetLogFolder( const wxString& folder ) { ScopedLock lock( m_mtx_PluginStatus ); @@ -1429,16 +1437,15 @@ void PluginManager::SetLogFolder( const wxString& folder ) if( m_LogFolder == fixedfolder ) return; m_LogFolder = fixedfolder; - SendLogFolder(); } -void PluginManager::Configure( PluginsEnum_t pid ) +void SysCorePlugins::Configure( PluginsEnum_t pid ) { ScopedLock lock( m_mtx_PluginStatus ); if( m_info[pid] ) m_info[pid]->CommonBindings.Configure(); } -bool PluginManager::AreLoaded() const +bool SysCorePlugins::AreLoaded() const { ScopedLock lock( m_mtx_PluginStatus ); for( int i=0; iid) ) return false; + } while( ++pi, pi->shortname != NULL ); + + return true; +} + +bool SysCorePlugins::AreAnyLoaded() const { ScopedLock lock( m_mtx_PluginStatus ); for( int i=0; iIsOpened; + return m_info[pid] && m_info[pid]->IsInitialized && m_info[pid]->IsOpened; } -bool PluginManager::IsInitialized( PluginsEnum_t pid ) const +bool SysCorePlugins::IsInitialized( PluginsEnum_t pid ) const { pxAssume( (uint)pid < PluginId_Count ); ScopedLock lock( m_mtx_PluginStatus ); return m_info[pid] && m_info[pid]->IsInitialized; } -bool PluginManager::IsLoaded( PluginsEnum_t pid ) const +bool SysCorePlugins::IsLoaded( PluginsEnum_t pid ) const { pxAssume( (uint)pid < PluginId_Count ); return !!m_info[pid]; } -bool PluginManager::NeedsLoad() const +bool SysCorePlugins::NeedsLoad() const { const PluginInfo* pi = tbl_PluginInfo; do { if( !IsLoaded(pi->id) ) return true; @@ -1499,7 +1516,7 @@ bool PluginManager::NeedsLoad() const return false; } -bool PluginManager::NeedsUnload() const +bool SysCorePlugins::NeedsUnload() const { const PluginInfo* pi = tbl_PluginInfo; do { if( IsLoaded(pi->id) ) return true; @@ -1508,7 +1525,7 @@ bool PluginManager::NeedsUnload() const return false; } -bool PluginManager::NeedsInit() const +bool SysCorePlugins::NeedsInit() const { ScopedLock lock( m_mtx_PluginStatus ); @@ -1519,7 +1536,7 @@ bool PluginManager::NeedsInit() const return false; } -bool PluginManager::NeedsShutdown() const +bool SysCorePlugins::NeedsShutdown() const { ScopedLock lock( m_mtx_PluginStatus ); @@ -1530,7 +1547,7 @@ bool PluginManager::NeedsShutdown() const return false; } -bool PluginManager::NeedsOpen() const +bool SysCorePlugins::NeedsOpen() const { const PluginInfo* pi = tbl_PluginInfo; do { if( !IsOpen(pi->id) ) return true; @@ -1539,7 +1556,7 @@ bool PluginManager::NeedsOpen() const return false; } -bool PluginManager::NeedsClose() const +bool SysCorePlugins::NeedsClose() const { const PluginInfo* pi = tbl_PluginInfo; do { if( IsOpen(pi->id) ) return true; @@ -1548,14 +1565,14 @@ bool PluginManager::NeedsClose() const return false; } -const wxString PluginManager::GetName( PluginsEnum_t pid ) const +const wxString SysCorePlugins::GetName( PluginsEnum_t pid ) const { ScopedLock lock( m_mtx_PluginStatus ); pxAssume( (uint)pid < PluginId_Count ); return m_info[pid] ? m_info[pid]->Name : (wxString)_("Unloaded Plugin"); } -const wxString PluginManager::GetVersion( PluginsEnum_t pid ) const +const wxString SysCorePlugins::GetVersion( PluginsEnum_t pid ) const { ScopedLock lock( m_mtx_PluginStatus ); pxAssume( (uint)pid < PluginId_Count ); diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index e7dd9e6dd1..1b93631819 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -78,7 +78,7 @@ namespace Exception }; // Plugin load errors occur when initially trying to load plugins during the - // creation of a PluginManager object. The error may either be due to non-existence, + // creation of a SysCorePlugins object. The error may either be due to non-existence, // corruption, or incompatible versioning. class PluginLoadError : public PluginError { @@ -178,6 +178,8 @@ namespace Exception # pragma warning(pop) #endif +typedef void CALLBACK FnType_SetDir( const char* dir ); + // -------------------------------------------------------------------------------------- // LegacyPluginAPI_Common // -------------------------------------------------------------------------------------- @@ -193,8 +195,9 @@ struct LegacyPluginAPI_Common void (CALLBACK* Shutdown)(); void (CALLBACK* KeyEvent)( keyEvent* evt ); - void (CALLBACK* SetSettingsDir)( const char* dir ); - void (CALLBACK* SetLogFolder)( const char* dir ); + + FnType_SetDir* SetSettingsDir; + FnType_SetDir* SetLogDir; s32 (CALLBACK* Freeze)(int mode, freezeData *data); s32 (CALLBACK* Test)(); @@ -214,7 +217,7 @@ class SysMtgsThread; // PluginBindings // -------------------------------------------------------------------------------------- // This structure is intended to be the "future" of PCSX2's plugin interface, and will hopefully -// make the current PluginManager largely obsolete (with the exception of the general Load/Unload +// make the current SysCorePlugins largely obsolete (with the exception of the general Load/Unload // management facilities) // class SysPluginBindings @@ -235,18 +238,18 @@ public: void McdEraseBlock( uint port, uint slot, u32 adr ); u64 McdGetCRC( uint port, uint slot ); - friend class PluginManager; + friend class SysCorePlugins; }; extern SysPluginBindings SysPlugins; // -------------------------------------------------------------------------------------- -// PluginManager Class +// SysCorePlugins Class // -------------------------------------------------------------------------------------- // -class PluginManager +class SysCorePlugins { - DeclareNoncopyableObject( PluginManager ); + DeclareNoncopyableObject( SysCorePlugins ); protected: class PluginStatus_t @@ -292,8 +295,8 @@ public: // hack until we unsuck plugins... ScopedPtr m_info[PluginId_Count]; public: - PluginManager(); - virtual ~PluginManager() throw(); + SysCorePlugins(); + virtual ~SysCorePlugins() throw(); virtual void Load( PluginsEnum_t pid, const wxString& srcfile ); virtual void Load( const wxString (&folders)[PluginId_Count] ); @@ -301,15 +304,16 @@ public: virtual void Unload( PluginsEnum_t pid ); bool AreLoaded() const; + bool AreOpen() const; bool AreAnyLoaded() const; bool AreAnyInitialized() const; Threading::Mutex& GetMutex() { return m_mtx_PluginStatus; } - virtual void Init(); + virtual bool Init(); virtual void Init( PluginsEnum_t pid ); virtual void Shutdown( PluginsEnum_t pid ); - virtual void Shutdown(); + virtual bool Shutdown(); virtual void Open(); virtual void Open( PluginsEnum_t pid ); virtual void Close( PluginsEnum_t pid ); @@ -325,8 +329,8 @@ public: virtual bool KeyEvent( const keyEvent& evt ); virtual void Configure( PluginsEnum_t pid ); virtual void SetSettingsFolder( const wxString& folder ); + virtual void SetLogFolder( const wxString& folder ); virtual void SendSettingsFolder(); - virtual void SetLogFolder( const wxString& folder ); virtual void SendLogFolder(); @@ -370,10 +374,10 @@ extern const PluginInfo tbl_PluginInfo[]; // GetPluginManager() is a required external implementation. This function is *NOT* // provided by the PCSX2 core library. It provides an interface for the linking User -// Interface apps or DLLs to reference their own instance of PluginManager (also allowing +// Interface apps or DLLs to reference their own instance of SysCorePlugins (also allowing // them to extend the class and override virtual methods). -extern PluginManager& GetCorePlugins(); +extern SysCorePlugins& GetCorePlugins(); // Hack to expose internal MemoryCard plugin: diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index a295c7ed7c..88018707b3 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -260,7 +260,8 @@ void SysCoreThread::OnResumeInThread( bool isSuspended ) // Invoked by the pthread_exit or pthread_cancel. void SysCoreThread::OnCleanupInThread() { - m_hasActiveMachine = false; + m_hasActiveMachine = false; + m_resetVirtualMachine = true; GetCorePlugins().Close(); GetCorePlugins().Shutdown(); diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 7cee43a920..05baf9c7b0 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -494,7 +494,6 @@ public: void SysApplySettings(); void SysExecute(); void SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override=wxEmptyString ); - void SysShutdown(); void LogicalVsync(); GSFrame& GetGsFrame() const; @@ -693,7 +692,7 @@ extern MainEmuFrame* GetMainFramePtr(); extern __aligned16 AppCoreThread CoreThread; extern __aligned16 SysMtgsThread mtgsThread; -extern __aligned16 AppPluginManager CorePlugins; +extern __aligned16 AppCorePlugins CorePlugins; extern void UI_UpdateSysControls(); diff --git a/pcsx2/gui/AppCorePlugins.cpp b/pcsx2/gui/AppCorePlugins.cpp index 34b81714b0..6fb1b1d1a9 100644 --- a/pcsx2/gui/AppCorePlugins.cpp +++ b/pcsx2/gui/AppCorePlugins.cpp @@ -31,9 +31,9 @@ using namespace Threading; // the window shouldn't. This blocks it. :) static bool s_DisableGsWindow = false; -__aligned16 AppPluginManager CorePlugins; +__aligned16 AppCorePlugins CorePlugins; -PluginManager& GetCorePlugins() +SysCorePlugins& GetCorePlugins() { return CorePlugins; } @@ -97,8 +97,8 @@ static void ConvertPluginFilenames( wxString (&passins)[PluginId_Count] ) } while( ++pi, pi->shortname != NULL ); } -typedef void (AppPluginManager::*FnPtr_AppPluginManager)(); -typedef void (AppPluginManager::*FnPtr_AppPluginPid)( PluginsEnum_t pid ); +typedef void (AppCorePlugins::*FnPtr_AppPluginManager)(); +typedef void (AppCorePlugins::*FnPtr_AppPluginPid)( PluginsEnum_t pid ); // -------------------------------------------------------------------------------------- // SysExecEvent_AppPluginManager @@ -109,6 +109,7 @@ protected: FnPtr_AppPluginManager m_method; public: + wxString GetEventName() const { return L"CorePluginsMethod"; } virtual ~SysExecEvent_AppPluginManager() throw() {} SysExecEvent_AppPluginManager* Clone() const { return new SysExecEvent_AppPluginManager( *this ); } @@ -153,6 +154,9 @@ protected: } }; +// -------------------------------------------------------------------------------------- +// SinglePluginMethodEvent +// -------------------------------------------------------------------------------------- class SinglePluginMethodEvent : public pxActionEvent { typedef pxActionEvent _parent; @@ -184,7 +188,7 @@ IMPLEMENT_DYNAMIC_CLASS( LoadSinglePluginEvent, pxActionEvent ); IMPLEMENT_DYNAMIC_CLASS( SinglePluginMethodEvent, pxActionEvent ); // -------------------------------------------------------------------------------------- -// AppPluginManager +// AppCorePlugins // -------------------------------------------------------------------------------------- // // Thread Affinity Notes: @@ -199,15 +203,27 @@ IMPLEMENT_DYNAMIC_CLASS( SinglePluginMethodEvent, pxActionEvent ); // the main thread from being completely busy while plugins are loaded and initialized. // (responsiveness is bliss!!) -- air // -AppPluginManager::AppPluginManager() +AppCorePlugins::AppCorePlugins() { } -AppPluginManager::~AppPluginManager() throw() +AppCorePlugins::~AppCorePlugins() throw() { } -void AppPluginManager::Load( PluginsEnum_t pid, const wxString& srcfile ) +static void _SetSettingsFolder() +{ + if (wxGetApp().Rpc_TryInvoke( _SetSettingsFolder )) return; + CorePlugins.SetSettingsFolder( GetSettingsFolder().ToString() ); +} + +static void _SetLogFolder() +{ + if (wxGetApp().Rpc_TryInvoke( _SetLogFolder )) return; + CorePlugins.SetLogFolder( GetLogFolder().ToString() ); +} + +void AppCorePlugins::Load( PluginsEnum_t pid, const wxString& srcfile ) { if( !wxThread::IsMain() ) { @@ -220,11 +236,11 @@ void AppPluginManager::Load( PluginsEnum_t pid, const wxString& srcfile ) _parent::Load( pid, srcfile ); } -void AppPluginManager::Unload( PluginsEnum_t pid ) +void AppCorePlugins::Unload( PluginsEnum_t pid ) { if( !wxThread::IsMain() ) { - SinglePluginMethodEvent evt( &AppPluginManager::Unload, pid ); + SinglePluginMethodEvent evt( &AppCorePlugins::Unload, pid ); wxGetApp().ProcessAction( evt ); Sleep( 5 ); return; @@ -233,30 +249,33 @@ void AppPluginManager::Unload( PluginsEnum_t pid ) _parent::Unload( pid ); } -void AppPluginManager::Load( const wxString (&folders)[PluginId_Count] ) +void AppCorePlugins::Load( const wxString (&folders)[PluginId_Count] ) { if( !pxAssert(!AreLoaded()) ) return; - SetLogFolder( GetLogFolder().ToString() ); - SetSettingsFolder( GetSettingsFolder().ToString() ); + _SetLogFolder(); + SendLogFolder(); + + _SetSettingsFolder(); + SendSettingsFolder(); _parent::Load( folders ); PostPluginStatus( CorePlugins_Loaded ); } -void AppPluginManager::Unload() +void AppCorePlugins::Unload() { _parent::Unload(); PostPluginStatus( CorePlugins_Unloaded ); } -void AppPluginManager::Init( PluginsEnum_t pid ) +void AppCorePlugins::Init( PluginsEnum_t pid ) { if( !wxTheApp ) return; if( !wxThread::IsMain() ) { - SinglePluginMethodEvent evt(&AppPluginManager::Init, pid); + SinglePluginMethodEvent evt(&AppCorePlugins::Init, pid); wxGetApp().ProcessAction( evt ); Sleep( 5 ); return; @@ -265,11 +284,11 @@ void AppPluginManager::Init( PluginsEnum_t pid ) _parent::Init( pid ); } -void AppPluginManager::Shutdown( PluginsEnum_t pid ) +void AppCorePlugins::Shutdown( PluginsEnum_t pid ) { if( !wxThread::IsMain() && wxTheApp ) { - SinglePluginMethodEvent evt( &AppPluginManager::Shutdown, pid ); + SinglePluginMethodEvent evt( &AppCorePlugins::Shutdown, pid ); wxGetApp().ProcessAction( evt ); Sleep( 5 ); return; @@ -278,33 +297,38 @@ void AppPluginManager::Shutdown( PluginsEnum_t pid ) _parent::Shutdown( pid ); } -void AppPluginManager::Init() +bool AppCorePlugins::Init() { - SetLogFolder( GetLogFolder().ToString() ); - SetSettingsFolder( GetSettingsFolder().ToString() ); - _parent::Init(); - PostPluginStatus( CorePlugins_Init ); + if( !NeedsInit() ) return false; + + _SetLogFolder(); + SendLogFolder(); + + _SetSettingsFolder(); + SendSettingsFolder(); + + if (_parent::Init()) + { + PostPluginStatus( CorePlugins_Init ); + return true; + } + return false; } -void AppPluginManager::Shutdown() +bool AppCorePlugins::Shutdown() { - _parent::Shutdown(); - PostPluginStatus( CorePlugins_Shutdown ); - - // Precautionary, in case an error occurs during saving a single plugin. - sApp.CloseGsPanel(); + if (_parent::Shutdown()) + { + PostPluginStatus( CorePlugins_Shutdown ); + return true; + } + return false; } -void AppPluginManager::Close() +void AppCorePlugins::Close() { AffinityAssert_AllowFrom_CoreThread(); - /*if( !GetSysExecutorThread().IsSelf() ) - { - GetSysExecutorThread().ProcessEvent( new SysExecEvent_AppPluginManager( &AppPluginManager::Close ) ); - return; - }*/ - if( !NeedsClose() ) return; PostPluginStatus( CorePlugins_Closing ); @@ -312,13 +336,13 @@ void AppPluginManager::Close() PostPluginStatus( CorePlugins_Closed ); } -void AppPluginManager::Open() +void AppCorePlugins::Open() { AffinityAssert_AllowFrom_CoreThread(); /*if( !GetSysExecutorThread().IsSelf() ) { - GetSysExecutorThread().ProcessEvent( new SysExecEvent_AppPluginManager( &AppPluginManager::Open ) ); + GetSysExecutorThread().ProcessEvent( new SysExecEvent_AppPluginManager( &AppCorePlugins::Open ) ); return; }*/ @@ -333,7 +357,7 @@ void AppPluginManager::Open() } // Yay, this plugin is guaranteed to always be opened first and closed last. -bool AppPluginManager::OpenPlugin_GS() +bool AppCorePlugins::OpenPlugin_GS() { if( GSopen2 && !s_DisableGsWindow ) { @@ -349,10 +373,10 @@ bool AppPluginManager::OpenPlugin_GS() } // Yay, this plugin is guaranteed to always be opened first and closed last. -void AppPluginManager::ClosePlugin_GS() +void AppCorePlugins::ClosePlugin_GS() { _parent::ClosePlugin_GS(); - if( GetMTGS().IsSelf() && GSopen2 && CloseViewportWithPlugins ) sApp.CloseGsPanel(); + if( CloseViewportWithPlugins && GetMTGS().IsSelf() && GSopen2 ) sApp.CloseGsPanel(); } diff --git a/pcsx2/gui/AppCorePlugins.h b/pcsx2/gui/AppCorePlugins.h index 56f9c80d9f..16bc42cd83 100644 --- a/pcsx2/gui/AppCorePlugins.h +++ b/pcsx2/gui/AppCorePlugins.h @@ -18,31 +18,31 @@ #include "AppCommon.h" // -------------------------------------------------------------------------------------- -// AppPluginManager +// AppCorePlugins // -------------------------------------------------------------------------------------- -// This extension of PluginManager provides event listener sources for plugins -- loading, +// This extension of SysCorePlugins provides event listener sources for plugins -- loading, // unloading, open, close, shutdown, etc. // -// FIXME : Should this be made part of the PCSX2 core emulation? (integrated into PluginManager) +// FIXME : Should this be made part of the PCSX2 core emulation? (integrated into SysCorePlugins) // I'm undecided on if it makes sense more in that context or in this one (interface). // -class AppPluginManager : public PluginManager +class AppCorePlugins : public SysCorePlugins { - typedef PluginManager _parent; + typedef SysCorePlugins _parent; public: - AppPluginManager(); - virtual ~AppPluginManager() throw(); + AppCorePlugins(); + virtual ~AppCorePlugins() throw(); void Load( const wxString (&folders)[PluginId_Count] ); void Load( PluginsEnum_t pid, const wxString& srcfile ); void Unload( PluginsEnum_t pid ); void Unload(); - - void Init(); + + bool Init(); void Init( PluginsEnum_t pid ); void Shutdown( PluginsEnum_t pid ); - void Shutdown(); + bool Shutdown(); void Close(); void Open(); diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 00b16f6b08..18d7da4799 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -40,17 +40,28 @@ class SysExecEvent_InvokeCoreThreadMethod : public SysExecEvent { protected: FnPtr_CoreThreadMethod m_method; + bool m_IsCritical; public: wxString GetEventName() const { return L"CoreThreadMethod"; } virtual ~SysExecEvent_InvokeCoreThreadMethod() throw() {} SysExecEvent_InvokeCoreThreadMethod* Clone() const { return new SysExecEvent_InvokeCoreThreadMethod(*this); } + + bool AllowCancelOnExit() const { return false; } + bool IsCriticalEvent() const { return m_IsCritical; } - SysExecEvent_InvokeCoreThreadMethod( FnPtr_CoreThreadMethod method ) + SysExecEvent_InvokeCoreThreadMethod( FnPtr_CoreThreadMethod method, bool critical=false ) { m_method = method; + m_IsCritical = critical; } - + + SysExecEvent_InvokeCoreThreadMethod& Critical() + { + m_IsCritical = true; + return *this; + } + protected: void InvokeEvent() { @@ -58,14 +69,6 @@ protected: } }; -bool ProcessingMethodViaThread( FnPtr_CoreThreadMethod method ) -{ - if( GetSysExecutorThread().IsSelf() ) return false; - SysExecEvent_InvokeCoreThreadMethod evt( method ); - GetSysExecutorThread().ProcessEvent( evt ); - return false; -} - static void PostCoreStatus( CoreThreadStatus pevt ) { sApp.PostAction( CoreThreadStatusEvent( pevt ) ); @@ -84,17 +87,26 @@ AppCoreThread::~AppCoreThread() throw() _parent::Cancel(); // use parent's, skips thread affinity check. } -void AppCoreThread::Cancel( bool isBlocking ) +static void _Cancel() { - AffinityAssert_AllowFrom_SysExecutor(); - _parent::Cancel( wxTimeSpan(0, 0, 2, 0) ); + GetCoreThread().Cancel(); } -void AppCoreThread::Shutdown() +void AppCoreThread::Cancel( bool isBlocking ) { - AffinityAssert_AllowFrom_SysExecutor(); + if (GetSysExecutorThread().IsRunning() && !GetSysExecutorThread().Rpc_TryInvoke( _Cancel )) + _parent::Cancel( wxTimeSpan(0, 0, 4, 0) ); +} + +void AppCoreThread::Reset() +{ + if( !GetSysExecutorThread().IsSelf() ) + { + GetSysExecutorThread().PostEvent( SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Reset) ); + return; + } + _parent::Reset(); - CorePlugins.Shutdown(); } ExecutorThread& GetSysExecutorThread() @@ -121,18 +133,14 @@ void AppCoreThread::Suspend( bool isBlocking ) void AppCoreThread::Resume() { - //if( !AffinityAssert_AllowFrom_SysExecutor() ) return; if( !GetSysExecutorThread().IsSelf() ) { GetSysExecutorThread().PostEvent( SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Resume) ); return; } - //if( m_ExecMode == ExecMode_Opened ) return; - //if( !pxAssert( CorePlugins.AreLoaded() ) ) return; - + GetCorePlugins().Init(); _parent::Resume(); - } void AppCoreThread::ChangeCdvdSource() @@ -482,9 +490,28 @@ void SysExecEvent_CoreThreadClose::InvokeEvent() void SysExecEvent_CoreThreadPause::InvokeEvent() { +#ifdef PCSX2_DEVBUILD + bool CorePluginsAreOpen = GetCorePlugins().AreOpen(); + ScopedCoreThreadPause paused_core; + _post_and_wait(paused_core); + + // All plugins should be initialized and opened upon resuming from + // a paused state. If the thread that puased us changed plugin status, it should + // have used Close instead. + if( CorePluginsAreOpen ) + { + CorePluginsAreOpen = GetCorePlugins().AreOpen(); + pxAssumeDev( CorePluginsAreOpen, "Invalid plugin close/shutdown detected during paused CoreThread; please Stop/Suspend the core instead." ); + } + paused_core.AllowResume(); + +#else + ScopedCoreThreadPause paused_core; _post_and_wait(paused_core); paused_core.AllowResume(); + +#endif } diff --git a/pcsx2/gui/AppCoreThread.h b/pcsx2/gui/AppCoreThread.h index 3ec82844f6..7afd428925 100644 --- a/pcsx2/gui/AppCoreThread.h +++ b/pcsx2/gui/AppCoreThread.h @@ -133,7 +133,7 @@ public: virtual void Suspend( bool isBlocking=false ); virtual void Resume(); - virtual void Shutdown(); + virtual void Reset(); virtual void Cancel( bool isBlocking=true ); virtual bool StateCheckInThread(); virtual void ChangeCdvdSource(); diff --git a/pcsx2/gui/AppInit.cpp b/pcsx2/gui/AppInit.cpp index f2f52e31ce..f6588d9d2a 100644 --- a/pcsx2/gui/AppInit.cpp +++ b/pcsx2/gui/AppInit.cpp @@ -653,14 +653,11 @@ void Pcsx2App::PrepForExit() m_ScheduledTermination = true; DispatchEvent( AppStatus_Exiting ); + + CoreThread.Cancel(); SysExecutorThread.ShutdownQueue(); m_timer_Termination->Start( 500 ); - - // This should be called by OnExit(), but sometimes wxWidgets fails to call OnExit(), so - // do it here just in case (no harm anyway -- OnExit is the next logical step after - // CloseWindow returns true from the TopLevel window). - //CleanupRestartable(); } // This cleanup procedure can only be called when the App message pump is still active. @@ -669,7 +666,7 @@ void Pcsx2App::CleanupRestartable() { AffinityAssert_AllowFrom_MainUI(); - ShutdownPlugins(); + CoreThread.Cancel(); SysExecutorThread.ShutdownQueue(); IdleEventDispatcher( L"Cleanup" ); diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 5a10996d9f..7ff7825411 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -879,10 +879,10 @@ void Pcsx2App::CloseGsPanel() { if( AppRpc_TryInvoke( &Pcsx2App::CloseGsPanel ) ) return; - GSFrame* gsFrame = GetGsFramePtr(); - if( (gsFrame != NULL) && CloseViewportWithPlugins ) + if (CloseViewportWithPlugins) { - if( GSPanel* woot = gsFrame->GetViewport() ) + if (GSFrame* gsFrame = GetGsFramePtr()) + if (GSPanel* woot = gsFrame->GetViewport()) woot->Destroy(); } } @@ -966,7 +966,8 @@ protected: DbgCon.WriteLn( Color_Gray, "(SysExecute) received." ); - if( m_UseCDVDsrc ) CoreThread.Shutdown(); else CoreThread.Suspend(); + CoreThread.Reset(); + CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso ); if( m_UseCDVDsrc ) CDVDsys_ChangeSource( m_cdvdsrc_type ); @@ -980,8 +981,8 @@ protected: } }; -// Executes the emulator using a saved/existing virtual machine state and currently -// configured CDVD source device. +// This command performs a full closure of any existing VM state and starts a +// fresh VM with the requested sources. void Pcsx2App::SysExecute() { SysExecutorThread.PostEvent( new SysExecEvent_Execute() ); @@ -995,36 +996,6 @@ void Pcsx2App::SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override SysExecutorThread.PostEvent( new SysExecEvent_Execute(cdvdsrc, elf_override) ); } -// -------------------------------------------------------------------------------------- -// SysExecEvent_Shutdown -// -------------------------------------------------------------------------------------- -class SysExecEvent_Shutdown : public SysExecEvent -{ -public: - wxString GetEventName() const - { - return L"SysShutdown"; - } - - wxString GetEventMessage() const - { - return _("Resetting PS2 virtual machine..."); - } - -protected: - void InvokeEvent() - { - CoreThread.Shutdown(); - } - -}; - -// Full system reset stops the core thread and unloads all core plugins *completely*. -void Pcsx2App::SysShutdown() -{ - SysExecutorThread.PostEvent( new SysExecEvent_Shutdown() ); -} - // Returns true if there is a "valid" virtual machine state from the user's perspective. This // means the user has started the emulator and not issued a full reset. // Thread Safety: The state of the system can change in parallel to execution of the diff --git a/pcsx2/gui/ExecutorThread.cpp b/pcsx2/gui/ExecutorThread.cpp index 705e2d22d9..2976c45ebb 100644 --- a/pcsx2/gui/ExecutorThread.cpp +++ b/pcsx2/gui/ExecutorThread.cpp @@ -324,7 +324,7 @@ bool pxEvtHandler::Rpc_TryInvoke( FnType_Void* method ) if( wxThread::GetCurrentId() != m_OwnerThreadId ) { SynchronousActionState sync; - SysExecEvent_MethodVoid evt(method); + SysExecEvent_MethodVoid evt(method, true); evt.SetSyncState( sync ); PostEvent( evt ); sync.WaitForResult(); @@ -421,6 +421,12 @@ ExecutorThread::ExecutorThread( pxEvtHandler* evthandler ) m_EvtHandler = evthandler; } +bool ExecutorThread::IsRunning() const +{ + if( !m_EvtHandler ) return false; + return( !m_EvtHandler->IsShuttingDown() ); +} + // Exposes the internal pxEvtHandler::ShutdownQueue API. See pxEvtHandler for details. void ExecutorThread::ShutdownQueue() { diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 44be09d420..dd724c8bbb 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -317,11 +317,17 @@ void GSFrame::CoreThread_OnResumed() void GSFrame::CoreThread_OnSuspended() { - // Could stop the timer outright here, tho no harm in having an occasional - // update here or there, just in case some state info changes while emu is suspended. - m_timer_UpdateTitle.Start( TitleBarUpdateMs ); + if( !IsBeingDeleted() && g_Conf->GSWindow.CloseOnEsc ) Hide(); +} - if( g_Conf->GSWindow.CloseOnEsc ) Hide(); +void GSFrame::CoreThread_OnStopped() +{ + //if( !IsBeingDeleted() ) Destroy(); +} + +void GSFrame::CorePlugins_OnShutdown() +{ + if( !IsBeingDeleted() ) Destroy(); } // overrides base Show behavior. diff --git a/pcsx2/gui/GSFrame.h b/pcsx2/gui/GSFrame.h index b20f50f042..b70f34227e 100644 --- a/pcsx2/gui/GSFrame.h +++ b/pcsx2/gui/GSFrame.h @@ -77,6 +77,7 @@ protected: class GSFrame : public wxFrame , public EventListener_AppStatus , public EventListener_CoreThread + , public EventListener_Plugins { typedef wxFrame _parent; @@ -110,6 +111,8 @@ protected: void AppStatusEvent_OnSettingsApplied(); void CoreThread_OnResumed(); void CoreThread_OnSuspended(); + void CoreThread_OnStopped(); + void CorePlugins_OnShutdown(); }; // -------------------------------------------------------------------------------------- diff --git a/pcsx2/gui/MainFrame.cpp b/pcsx2/gui/MainFrame.cpp index b8372be8a0..822cb7532a 100644 --- a/pcsx2/gui/MainFrame.cpp +++ b/pcsx2/gui/MainFrame.cpp @@ -479,7 +479,9 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title) PushEventHandler( &wxGetApp().GetRecentIsoManager() ); SetDropTarget( new IsoDropTarget( this ) ); + ApplyCoreStatus(); + ApplySettings(); } MainEmuFrame::~MainEmuFrame() throw() diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index 8f1339a107..1217a15cc4 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -474,26 +474,6 @@ protected: } }; -class SysExecEvent_Restart : public SysExecEvent -{ -public: - virtual ~SysExecEvent_Restart() throw() {} - - wxString GetEventName() const { return L"SysRestart"; } - - wxString GetEventMessage() const - { - return _("Restarting PS2 Virtual Machine..."); - } - -protected: - void InvokeEvent() - { - sApp.SysShutdown(); - sApp.SysExecute(); - } -}; - void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent &event) { if( !SysHasValidState() ) return; @@ -509,15 +489,15 @@ void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SysReset_Click(wxCommandEvent &event) { UI_DisableSysReset(); - GetSysExecutorThread().PostEvent( new SysExecEvent_Restart() ); + sApp.SysExecute(); } void MainEmuFrame::Menu_SysShutdown_Click(wxCommandEvent &event) { - if( !SysHasValidState() && !CorePlugins.AreAnyInitialized() ) return; + //if( !SysHasValidState() && !CorePlugins.AreAnyInitialized() ) return; UI_DisableSysShutdown(); - sApp.SysShutdown(); + CoreThread.Reset(); } void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent &event) diff --git a/pcsx2/gui/pxEventThread.h b/pcsx2/gui/pxEventThread.h index af920a4372..7ceb5f38d1 100644 --- a/pcsx2/gui/pxEventThread.h +++ b/pcsx2/gui/pxEventThread.h @@ -107,6 +107,7 @@ class SysExecEvent_MethodVoid : public SysExecEvent { protected: FnType_Void* m_method; + bool m_IsCritical; public: wxString GetEventName() const { return L"MethodVoid"; } @@ -114,9 +115,21 @@ public: virtual ~SysExecEvent_MethodVoid() throw() {} SysExecEvent_MethodVoid* Clone() const { return new SysExecEvent_MethodVoid( *this ); } - explicit SysExecEvent_MethodVoid( FnType_Void* method = NULL ) + bool AllowCancelOnExit() const { return !m_IsCritical; } + bool IsCriticalEvent() const { return m_IsCritical; } + + // Hacky: I don't really like this Critical parameter mess, but I haven't thought + // of a better solution (yet). + explicit SysExecEvent_MethodVoid( FnType_Void* method = NULL, bool critical=false ) { m_method = method; + m_IsCritical = critical; + } + + SysExecEvent_MethodVoid& Critical() + { + m_IsCritical = true; + return *this; } protected: @@ -218,7 +231,8 @@ public: virtual ~ExecutorThread() throw() { } virtual void ShutdownQueue(); - + bool IsRunning() const; + void PostEvent( SysExecEvent* evt ); void PostEvent( const SysExecEvent& evt );