Some bugfixes to suspend/resume and changing plugin options on the fly.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2915 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-04-27 15:18:25 +00:00
parent df60f016c8
commit bd76de1a8b
5 changed files with 94 additions and 89 deletions

View File

@ -400,8 +400,9 @@ SaveSinglePluginHelper::SaveSinglePluginHelper( PluginsEnum_t pid )
SaveSinglePluginHelper::~SaveSinglePluginHelper() throw() SaveSinglePluginHelper::~SaveSinglePluginHelper() throw()
{ {
try bool allowResume = true;
{
try {
if( m_validstate ) if( m_validstate )
{ {
Console.WriteLn( Color_Green, L"Recovering single plugin: " + tbl_PluginInfo[m_pid].GetShortname() ); Console.WriteLn( Color_Green, L"Recovering single plugin: " + tbl_PluginInfo[m_pid].GetShortname() );
@ -413,7 +414,19 @@ SaveSinglePluginHelper::~SaveSinglePluginHelper() throw()
s_DisableGsWindow = false; s_DisableGsWindow = false;
} }
DESTRUCTOR_CATCHALL; catch( BaseException& ex )
{
allowResume = false;
Console.Error( "Unhandled BaseException in %s (ignored!):", __pxFUNCTION__ );
Console.Error( ex.FormatDiagnosticMessage() );
}
catch( std::exception& ex )
{
allowResume = false;
Console.Error( "Unhandled std::exception in %s (ignored!):", __pxFUNCTION__ );
Console.Error( ex.what() );
}
s_DisableGsWindow = false; s_DisableGsWindow = false;
if( allowResume ) m_scoped_pause.AllowResume();
} }

View File

@ -275,14 +275,62 @@ enum
}; };
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// SysExecEvent_FullStop // BaseSysExecEvent_ScopedCore
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class SysExecEvent_FullStop : public SysExecEvent class BaseSysExecEvent_ScopedCore : public SysExecEvent
{ {
protected: protected:
SynchronousActionState* m_resume; SynchronousActionState* m_resume;
Threading::Mutex* m_mtx_resume; Threading::Mutex* m_mtx_resume;
public:
virtual ~BaseSysExecEvent_ScopedCore() throw() {}
protected:
BaseSysExecEvent_ScopedCore( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: SysExecEvent( sync )
{
m_resume = resume_sync;
m_mtx_resume = mtx_resume;
}
void _post_and_wait( IScopedCoreThread& core )
{
PostResult();
if( m_resume )
{
ScopedLock lock( m_mtx_resume );
// If the sender of the message requests a non-blocking resume, then we need
// to deallocate the m_sync object, since the sender will likely leave scope and
// invalidate it.
switch( m_resume->WaitForResult() )
{
case FullStop_BlockingResume:
if( m_sync ) m_sync->ClearResult();
core.AllowResume();
break;
case FullStop_NonblockingResume:
m_sync = NULL;
core.AllowResume();
break;
case FullStop_SkipResume:
m_sync = NULL;
break;
}
}
}
};
// --------------------------------------------------------------------------------------
// SysExecEvent_FullStop
// --------------------------------------------------------------------------------------
class SysExecEvent_FullStop : public BaseSysExecEvent_ScopedCore
{
public: public:
virtual ~SysExecEvent_FullStop() throw() {} virtual ~SysExecEvent_FullStop() throw() {}
SysExecEvent_FullStop* Clone() const SysExecEvent_FullStop* Clone() const
@ -291,46 +339,16 @@ public:
} }
SysExecEvent_FullStop( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL ) SysExecEvent_FullStop( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: SysExecEvent( sync ) : BaseSysExecEvent_ScopedCore( sync, resume_sync, mtx_resume ) { }
{
m_resume = resume_sync;
m_mtx_resume = mtx_resume;
}
SysExecEvent_FullStop( SynchronousActionState& sync, SynchronousActionState& resume_sync, Threading::Mutex& mtx_resume ) SysExecEvent_FullStop( SynchronousActionState& sync, SynchronousActionState& resume_sync, Threading::Mutex& mtx_resume )
: SysExecEvent( sync ) : BaseSysExecEvent_ScopedCore( &sync, &resume_sync, &mtx_resume ) { }
{
m_resume = &resume_sync;
m_mtx_resume = &mtx_resume;
}
protected: protected:
void _DoInvoke() void _DoInvoke()
{ {
ScopedCoreThreadClose closed_core; ScopedCoreThreadClose closed_core;
PostResult(); _post_and_wait(closed_core);
if( m_resume )
{
ScopedLock lock( m_mtx_resume );
// If the sender of the message requests a non-blocking resume, then we need
// to deallocate the m_sync object, since the sender will likely leave scope and
// invalidate it.
switch( m_resume->WaitForResult() )
{
case FullStop_SkipResume: return;
case FullStop_BlockingResume:
if( m_sync ) m_sync->ClearResult();
break;
case FullStop_NonblockingResume:
m_sync = NULL;
break;
}
}
closed_core.AllowResume(); closed_core.AllowResume();
} }
}; };
@ -338,12 +356,8 @@ protected:
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// SysExecEvent_FullStop // SysExecEvent_FullStop
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class SysExecEvent_Pause : public SysExecEvent class SysExecEvent_Pause : public BaseSysExecEvent_ScopedCore
{ {
protected:
SynchronousActionState* m_resume;
Threading::Mutex* m_mtx_resume;
public: public:
virtual ~SysExecEvent_Pause() throw() {} virtual ~SysExecEvent_Pause() throw() {}
SysExecEvent_Pause* Clone() const SysExecEvent_Pause* Clone() const
@ -352,46 +366,16 @@ public:
} }
SysExecEvent_Pause( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL ) SysExecEvent_Pause( SynchronousActionState* sync=NULL, SynchronousActionState* resume_sync=NULL, Threading::Mutex* mtx_resume=NULL )
: SysExecEvent( sync ) : BaseSysExecEvent_ScopedCore( sync, resume_sync, mtx_resume ) { }
{
m_resume = resume_sync;
m_mtx_resume = mtx_resume;
}
SysExecEvent_Pause( SynchronousActionState& sync, SynchronousActionState& resume_sync, Threading::Mutex& mtx_resume ) SysExecEvent_Pause( SynchronousActionState& sync, SynchronousActionState& resume_sync, Threading::Mutex& mtx_resume )
: SysExecEvent( sync ) : BaseSysExecEvent_ScopedCore( &sync, &resume_sync, &mtx_resume ) { }
{
m_resume = &resume_sync;
m_mtx_resume = &mtx_resume;
}
protected: protected:
void _DoInvoke() void _DoInvoke()
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
PostResult(); _post_and_wait(paused_core);
if( m_resume )
{
ScopedLock lock( m_mtx_resume );
// If the sender of the message requests a non-blocking resume, then we need
// to deallocate the m_sync object, since the sender will likely leave scope and
// invalidate it.
switch( m_resume->WaitForResult() )
{
case FullStop_SkipResume: return;
case FullStop_BlockingResume:
if( m_sync ) m_sync->ClearResult();
break;
case FullStop_NonblockingResume:
m_sync = NULL;
break;
}
}
paused_core.AllowResume(); paused_core.AllowResume();
} }
}; };

View File

@ -143,6 +143,7 @@ public:
bool IsPaused() const { return GetMenuBar()->IsChecked( MenuId_Sys_SuspendResume ); } bool IsPaused() const { return GetMenuBar()->IsChecked( MenuId_Sys_SuspendResume ); }
void UpdateIsoSrcSelection(); void UpdateIsoSrcSelection();
void RemoveCdvdMenu(); void RemoveCdvdMenu();
void EnableMenuItem( int id, bool enable );
protected: protected:
void ApplySettings(); void ApplySettings();

View File

@ -448,7 +448,7 @@ void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent &event)
// has responded (it updates status after the plugins are loaded and emulation has // has responded (it updates status after the plugins are loaded and emulation has
// engaged successfully). // engaged successfully).
GetMenuBar()->Enable( MenuId_Sys_SuspendResume, false ); EnableMenuItem( MenuId_Sys_SuspendResume, false );
GetSysExecutorThread().PostEvent( new SysExecEvent_ToggleSuspend() ); GetSysExecutorThread().PostEvent( new SysExecEvent_ToggleSuspend() );
} }

View File

@ -17,11 +17,19 @@
#include "Mainframe.h" #include "Mainframe.h"
#include "GSFrame.h" #include "GSFrame.h"
// This is necessary because this stupid wxWdigets thing has implicit debug errors
// in the FindItem call that asserts if the menu options are missing. This is bad
// mojo for configurable/dynamic menus. >_<
void MainEmuFrame::EnableMenuItem( int id, bool enable )
{
if( wxMenuItem* item = m_menubar.FindItem(id) )
item->Enable( enable );
}
static void _SaveLoadStuff( bool enabled ) static void _SaveLoadStuff( bool enabled )
{ {
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_LoadStates, enabled ); sMainFrame.EnableMenuItem( MenuId_Sys_LoadStates, enabled );
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_SaveStates, enabled ); sMainFrame.EnableMenuItem( MenuId_Sys_SaveStates, enabled );
} }
// Updates the enable/disable status of all System related controls: menus, toolbars, // Updates the enable/disable status of all System related controls: menus, toolbars,
@ -35,11 +43,10 @@ void UI_UpdateSysControls()
_SaveLoadStuff( true ); _SaveLoadStuff( true );
} }
void UI_DisableSysReset() void UI_DisableSysReset()
{ {
if( wxGetApp().PostMethodMyself( UI_DisableSysReset ) ) return; if( wxGetApp().PostMethodMyself( UI_DisableSysReset ) ) return;
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Restart, false ); sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
_SaveLoadStuff( false ); _SaveLoadStuff( false );
} }
@ -48,16 +55,16 @@ void UI_DisableSysShutdown()
{ {
if( wxGetApp().PostMethodMyself( &UI_DisableSysShutdown ) ) return; if( wxGetApp().PostMethodMyself( &UI_DisableSysShutdown ) ) return;
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Restart, false ); sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Shutdown, false ); sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, false );
} }
void UI_EnableSysShutdown() void UI_EnableSysShutdown()
{ {
if( wxGetApp().PostMethodMyself( &UI_EnableSysShutdown ) ) return; if( wxGetApp().PostMethodMyself( &UI_EnableSysShutdown ) ) return;
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Restart, true ); sMainFrame.EnableMenuItem( MenuId_Sys_Restart, true );
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Shutdown, true ); sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, true );
} }
@ -65,16 +72,16 @@ void UI_DisableSysActions()
{ {
if( wxGetApp().PostMethodMyself( &UI_DisableSysShutdown ) ) return; if( wxGetApp().PostMethodMyself( &UI_DisableSysShutdown ) ) return;
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Restart, false ); sMainFrame.EnableMenuItem( MenuId_Sys_Restart, false );
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Shutdown, false ); sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, false );
} }
void UI_EnableSysActions() void UI_EnableSysActions()
{ {
if( wxGetApp().PostMethodMyself( &UI_EnableSysShutdown ) ) return; if( wxGetApp().PostMethodMyself( &UI_EnableSysShutdown ) ) return;
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Restart, true ); sMainFrame.EnableMenuItem( MenuId_Sys_Restart, true );
sMainFrame.GetMenuBar()->Enable( MenuId_Sys_Shutdown, true ); sMainFrame.EnableMenuItem( MenuId_Sys_Shutdown, true );
} }