* 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
This commit is contained in:
Jake.Stine 2010-07-01 15:08:12 +00:00
parent a9b8160d9e
commit 483c6878a4
17 changed files with 281 additions and 229 deletions

View File

@ -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();

View File

@ -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; i<PluginId_Count; ++i )
@ -1449,7 +1456,17 @@ bool PluginManager::AreLoaded() const
return true;
}
bool PluginManager::AreAnyLoaded() const
bool SysCorePlugins::AreOpen() const
{
ScopedLock lock( m_mtx_PluginStatus );
const PluginInfo* pi = tbl_PluginInfo; do {
if( !IsOpen(pi->id) ) return false;
} while( ++pi, pi->shortname != NULL );
return true;
}
bool SysCorePlugins::AreAnyLoaded() const
{
ScopedLock lock( m_mtx_PluginStatus );
for( int i=0; i<PluginId_Count; ++i )
@ -1460,7 +1477,7 @@ bool PluginManager::AreAnyLoaded() const
return false;
}
bool PluginManager::AreAnyInitialized() const
bool SysCorePlugins::AreAnyInitialized() const
{
ScopedLock lock( m_mtx_PluginStatus );
const PluginInfo* pi = tbl_PluginInfo; do {
@ -1470,27 +1487,27 @@ bool PluginManager::AreAnyInitialized() const
return false;
}
bool PluginManager::IsOpen( PluginsEnum_t pid ) const
bool SysCorePlugins::IsOpen( PluginsEnum_t pid ) const
{
pxAssume( (uint)pid < PluginId_Count );
ScopedLock lock( m_mtx_PluginStatus );
return m_info[pid] && m_info[pid]->IsOpened;
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 );

View File

@ -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<PluginStatus_t> 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:

View File

@ -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();

View File

@ -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();

View File

@ -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();
}

View File

@ -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();

View File

@ -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
}

View File

@ -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();

View File

@ -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" );

View File

@ -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

View File

@ -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()
{

View File

@ -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.

View File

@ -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();
};
// --------------------------------------------------------------------------------------

View File

@ -479,7 +479,9 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
PushEventHandler( &wxGetApp().GetRecentIsoManager() );
SetDropTarget( new IsoDropTarget( this ) );
ApplyCoreStatus();
ApplySettings();
}
MainEmuFrame::~MainEmuFrame() throw()

View File

@ -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)

View File

@ -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 );