mirror of https://github.com/PCSX2/pcsx2.git
More thread sync fixes (these mostly only showed up on linux, because of threads starting a lot slower); fixed by including a startup signal to let the creating thread know when the worker has aquired its persistent locks.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2029 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
6b0c9cfdfe
commit
877f59a255
|
@ -237,8 +237,8 @@ void mtgsThreadObject::OpenPlugin()
|
||||||
|
|
||||||
void mtgsThreadObject::ExecuteTaskInThread()
|
void mtgsThreadObject::ExecuteTaskInThread()
|
||||||
{
|
{
|
||||||
// Required by the underlying SysThreadBase class (is unlocked on exit)
|
|
||||||
m_RunningLock.Lock();
|
m_RunningLock.Lock();
|
||||||
|
m_StartupEvent.Post();
|
||||||
|
|
||||||
#ifdef RINGBUF_DEBUG_STACK
|
#ifdef RINGBUF_DEBUG_STACK
|
||||||
PacketTagType prevCmd;
|
PacketTagType prevCmd;
|
||||||
|
@ -247,7 +247,7 @@ void mtgsThreadObject::ExecuteTaskInThread()
|
||||||
pthread_cleanup_push( _clean_close_gs, this );
|
pthread_cleanup_push( _clean_close_gs, this );
|
||||||
while( true )
|
while( true )
|
||||||
{
|
{
|
||||||
m_sem_event.WaitRaw(); // ... because this does a cancel test itself..
|
m_sem_event.WaitRaw(); // ... because this does a cancel test itself..
|
||||||
StateCheckInThread( false ); // false disables cancel test here!
|
StateCheckInThread( false ); // false disables cancel test here!
|
||||||
|
|
||||||
m_RingBufferIsBusy = true;
|
m_RingBufferIsBusy = true;
|
||||||
|
@ -389,7 +389,7 @@ void mtgsThreadObject::ExecuteTaskInThread()
|
||||||
case GS_RINGTYPE_MODECHANGE:
|
case GS_RINGTYPE_MODECHANGE:
|
||||||
_gs_ChangeTimings( tag.data[0], tag.data[1] );
|
_gs_ChangeTimings( tag.data[0], tag.data[1] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GS_RINGTYPE_CRC:
|
case GS_RINGTYPE_CRC:
|
||||||
GSsetGameCRC( tag.data[0], 0 );
|
GSsetGameCRC( tag.data[0], 0 );
|
||||||
break;
|
break;
|
||||||
|
@ -397,7 +397,7 @@ void mtgsThreadObject::ExecuteTaskInThread()
|
||||||
case GS_RINGTYPE_STARTTIME:
|
case GS_RINGTYPE_STARTTIME:
|
||||||
m_iSlowStart += tag.data[0];
|
m_iSlowStart += tag.data[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
default:
|
default:
|
||||||
Console.Error("GSThreadProc, bad packet (%x) at m_RingPos: %x, m_WritePos: %x", tag.command, m_RingPos, m_WritePos);
|
Console.Error("GSThreadProc, bad packet (%x) at m_RingPos: %x, m_WritePos: %x", tag.command, m_RingPos, m_WritePos);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
@ -47,6 +47,7 @@ void SysThreadBase::Start()
|
||||||
_parent::Start();
|
_parent::Start();
|
||||||
m_ExecMode = ExecMode_Closing;
|
m_ExecMode = ExecMode_Closing;
|
||||||
m_sem_event.Post();
|
m_sem_event.Post();
|
||||||
|
m_StartupEvent.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ void SysThreadBase::OnStart()
|
||||||
if( !pxAssertDev( m_ExecMode == ExecMode_NoThreadYet, "SysSustainableThread:Start(): Invalid execution mode" ) ) return;
|
if( !pxAssertDev( m_ExecMode == ExecMode_NoThreadYet, "SysSustainableThread:Start(): Invalid execution mode" ) ) return;
|
||||||
|
|
||||||
m_ResumeEvent.Reset();
|
m_ResumeEvent.Reset();
|
||||||
|
m_StartupEvent.Reset();
|
||||||
FrankenMutex( m_ExecModeMutex );
|
FrankenMutex( m_ExecModeMutex );
|
||||||
FrankenMutex( m_RunningLock );
|
FrankenMutex( m_RunningLock );
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ void SysThreadBase::OnStart()
|
||||||
bool SysThreadBase::Suspend( bool isBlocking )
|
bool SysThreadBase::Suspend( bool isBlocking )
|
||||||
{
|
{
|
||||||
if( IsSelf() || !IsRunning() ) return false;
|
if( IsSelf() || !IsRunning() ) return false;
|
||||||
|
|
||||||
// shortcut ExecMode check to avoid deadlocking on redundant calls to Suspend issued
|
// shortcut ExecMode check to avoid deadlocking on redundant calls to Suspend issued
|
||||||
// from Resume or OnResumeReady code.
|
// from Resume or OnResumeReady code.
|
||||||
if( m_ExecMode == ExecMode_Closed ) return false;
|
if( m_ExecMode == ExecMode_Closed ) return false;
|
||||||
|
@ -152,7 +154,7 @@ bool SysThreadBase::Pause()
|
||||||
// Resumes the core execution state, or does nothing is the core is already running. If
|
// Resumes the core execution state, or does nothing is the core is already running. If
|
||||||
// settings were changed, resets will be performed as needed and emulation state resumed from
|
// settings were changed, resets will be performed as needed and emulation state resumed from
|
||||||
// memory savestates.
|
// memory savestates.
|
||||||
//
|
//
|
||||||
// Note that this is considered a non-blocking action. Most times the state is safely resumed
|
// Note that this is considered a non-blocking action. Most times the state is safely resumed
|
||||||
// on return, but in the case of re-entrant or nested message handling the function may return
|
// on return, but in the case of re-entrant or nested message handling the function may return
|
||||||
// before the thread has resumed. If you need explicit behavior tied to the completion of the
|
// before the thread has resumed. If you need explicit behavior tied to the completion of the
|
||||||
|
@ -171,20 +173,13 @@ void SysThreadBase::Resume()
|
||||||
|
|
||||||
ScopedLock locker( m_ExecModeMutex );
|
ScopedLock locker( m_ExecModeMutex );
|
||||||
|
|
||||||
// Recursion guard is needed because of the non-blocking Wait if the state
|
|
||||||
// is Suspending/Closing. Processed events could recurse into Resume, and we'll
|
|
||||||
// want to silently ignore them.
|
|
||||||
|
|
||||||
//RecursionGuard guard( m_resume_guard );
|
|
||||||
//if( guard.IsReentrant() ) return;
|
|
||||||
|
|
||||||
switch( m_ExecMode )
|
switch( m_ExecMode )
|
||||||
{
|
{
|
||||||
case ExecMode_Opened: return;
|
case ExecMode_Opened: return;
|
||||||
|
|
||||||
case ExecMode_NoThreadYet:
|
case ExecMode_NoThreadYet:
|
||||||
Start();
|
Start();
|
||||||
m_ExecMode = ExecMode_Closing;
|
|
||||||
// fall through...
|
// fall through...
|
||||||
|
|
||||||
case ExecMode_Closing:
|
case ExecMode_Closing:
|
||||||
|
@ -192,14 +187,12 @@ void SysThreadBase::Resume()
|
||||||
// we need to make sure and wait for the emuThread to enter a fully suspended
|
// we need to make sure and wait for the emuThread to enter a fully suspended
|
||||||
// state before continuing...
|
// state before continuing...
|
||||||
|
|
||||||
//locker.Unlock(); // no deadlocks please, thanks. :)
|
|
||||||
m_RunningLock.Wait();
|
m_RunningLock.Wait();
|
||||||
//locker.Lock();
|
|
||||||
|
|
||||||
// The entire state coming out of a Wait is indeterminate because of user input
|
// The entire state coming out of a Wait is indeterminate because of user input
|
||||||
// and pending messages being handled. If something doesn't feel right, we should
|
// and pending messages being handled. If something doesn't feel right, we should
|
||||||
// abort.
|
// abort.
|
||||||
|
|
||||||
if( (m_ExecMode != ExecMode_Closed) && (m_ExecMode != ExecMode_Paused) ) return;
|
if( (m_ExecMode != ExecMode_Closed) && (m_ExecMode != ExecMode_Paused) ) return;
|
||||||
if( g_plugins == NULL ) return;
|
if( g_plugins == NULL ) return;
|
||||||
break;
|
break;
|
||||||
|
@ -269,9 +262,9 @@ void SysThreadBase::StateCheckInThread( bool isCancelable )
|
||||||
OnSuspendInThread();
|
OnSuspendInThread();
|
||||||
m_ExecMode = ExecMode_Closed;
|
m_ExecMode = ExecMode_Closed;
|
||||||
m_RunningLock.Unlock();
|
m_RunningLock.Unlock();
|
||||||
}
|
}
|
||||||
// fallthrough...
|
// fallthrough...
|
||||||
|
|
||||||
case ExecMode_Closed:
|
case ExecMode_Closed:
|
||||||
while( m_ExecMode == ExecMode_Closed )
|
while( m_ExecMode == ExecMode_Closed )
|
||||||
m_ResumeEvent.WaitRaw();
|
m_ResumeEvent.WaitRaw();
|
||||||
|
@ -279,7 +272,7 @@ void SysThreadBase::StateCheckInThread( bool isCancelable )
|
||||||
m_RunningLock.Lock();
|
m_RunningLock.Lock();
|
||||||
OnResumeInThread( true );
|
OnResumeInThread( true );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
jNO_DEFAULT;
|
jNO_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,7 +347,7 @@ void SysCoreThread::ApplySettings( const Pcsx2Config& src )
|
||||||
|
|
||||||
m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
|
m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks );
|
||||||
m_resetProfilers = (src.Profiler != EmuConfig.Profiler );
|
m_resetProfilers = (src.Profiler != EmuConfig.Profiler );
|
||||||
|
|
||||||
const_cast<Pcsx2Config&>(EmuConfig) = src;
|
const_cast<Pcsx2Config&>(EmuConfig) = src;
|
||||||
|
|
||||||
if( resumeWhenDone ) Resume();
|
if( resumeWhenDone ) Resume();
|
||||||
|
@ -373,7 +366,7 @@ SysCoreThread& SysCoreThread::Get()
|
||||||
void SysCoreThread::CpuInitializeMess()
|
void SysCoreThread::CpuInitializeMess()
|
||||||
{
|
{
|
||||||
if( m_hasValidState ) return;
|
if( m_hasValidState ) return;
|
||||||
|
|
||||||
wxString elf_file;
|
wxString elf_file;
|
||||||
if( EmuConfig.SkipBiosSplash )
|
if( EmuConfig.SkipBiosSplash )
|
||||||
{
|
{
|
||||||
|
@ -434,7 +427,9 @@ void SysCoreThread::CpuExecute()
|
||||||
void SysCoreThread::ExecuteTaskInThread()
|
void SysCoreThread::ExecuteTaskInThread()
|
||||||
{
|
{
|
||||||
m_RunningLock.Lock();
|
m_RunningLock.Lock();
|
||||||
|
|
||||||
tls_coreThread = this;
|
tls_coreThread = this;
|
||||||
|
m_StartupEvent.Post();
|
||||||
|
|
||||||
m_sem_event.WaitRaw();
|
m_sem_event.WaitRaw();
|
||||||
StateCheckInThread();
|
StateCheckInThread();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
@ -44,7 +44,7 @@ protected:
|
||||||
// Thread has not been created yet. Typically this is the same as IsRunning()
|
// Thread has not been created yet. Typically this is the same as IsRunning()
|
||||||
// returning FALSE.
|
// returning FALSE.
|
||||||
ExecMode_NoThreadYet,
|
ExecMode_NoThreadYet,
|
||||||
|
|
||||||
// Close signal has been sent to the thread, but the thread's response is still
|
// Close signal has been sent to the thread, but the thread's response is still
|
||||||
// pending (thread is busy/running).
|
// pending (thread is busy/running).
|
||||||
ExecMode_Closing,
|
ExecMode_Closing,
|
||||||
|
@ -55,11 +55,11 @@ protected:
|
||||||
|
|
||||||
// Thread is active and running, with pluigns in an "open" state.
|
// Thread is active and running, with pluigns in an "open" state.
|
||||||
ExecMode_Opened,
|
ExecMode_Opened,
|
||||||
|
|
||||||
// Pause signal has been sent to the thread, but the thread's response is still
|
// Pause signal has been sent to the thread, but the thread's response is still
|
||||||
// pending (thread is busy/running).
|
// pending (thread is busy/running).
|
||||||
ExecMode_Pausing,
|
ExecMode_Pausing,
|
||||||
|
|
||||||
// Thread is safely paused, with plugins in an "open" state, and waiting for a
|
// Thread is safely paused, with plugins in an "open" state, and waiting for a
|
||||||
// resume/open signal.
|
// resume/open signal.
|
||||||
ExecMode_Paused,
|
ExecMode_Paused,
|
||||||
|
@ -73,7 +73,12 @@ protected:
|
||||||
|
|
||||||
// Used to wake up the thread from sleeping when it's in a suspended state.
|
// Used to wake up the thread from sleeping when it's in a suspended state.
|
||||||
Semaphore m_ResumeEvent;
|
Semaphore m_ResumeEvent;
|
||||||
|
|
||||||
|
// Used to signal the creating thread that the worker has entered the running state.
|
||||||
|
// This is necessary because until the thread has established itself, locking against
|
||||||
|
// m_RunningLock isn't a reliable synchronization tool.
|
||||||
|
Semaphore m_StartupEvent;
|
||||||
|
|
||||||
// Locked whenever the thread is not in a suspended state (either closed or paused).
|
// Locked whenever the thread is not in a suspended state (either closed or paused).
|
||||||
// Issue a Wait against this mutex for performing actions that require the thread
|
// Issue a Wait against this mutex for performing actions that require the thread
|
||||||
// to be suspended.
|
// to be suspended.
|
||||||
|
@ -92,7 +97,7 @@ public:
|
||||||
{
|
{
|
||||||
return m_ExecMode > ExecMode_Closed;
|
return m_ExecMode > ExecMode_Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsClosed() const { return !IsOpen(); }
|
bool IsClosed() const { return !IsOpen(); }
|
||||||
|
|
||||||
ExecutionMode GetExecutionMode() const { return m_ExecMode; }
|
ExecutionMode GetExecutionMode() const { return m_ExecMode; }
|
||||||
|
@ -101,7 +106,7 @@ public:
|
||||||
virtual bool Suspend( bool isBlocking = true );
|
virtual bool Suspend( bool isBlocking = true );
|
||||||
virtual void Resume();
|
virtual void Resume();
|
||||||
virtual bool Pause();
|
virtual bool Pause();
|
||||||
|
|
||||||
virtual void StateCheckInThread( bool isCancelable = true );
|
virtual void StateCheckInThread( bool isCancelable = true );
|
||||||
virtual void OnCleanupInThread();
|
virtual void OnCleanupInThread();
|
||||||
|
|
||||||
|
@ -123,7 +128,7 @@ protected:
|
||||||
// thread, requesting this thread suspend itself temporarily). After this is called,
|
// thread, requesting this thread suspend itself temporarily). After this is called,
|
||||||
// the thread enters a waiting state on the m_ResumeEvent semaphore.
|
// the thread enters a waiting state on the m_ResumeEvent semaphore.
|
||||||
virtual void OnSuspendInThread()=0;
|
virtual void OnSuspendInThread()=0;
|
||||||
|
|
||||||
// Extending classes should implement this, but should not call it. The parent class
|
// Extending classes should implement this, but should not call it. The parent class
|
||||||
// handles invocation by the following guidelines: Called *in thread* from StateCheckInThread()
|
// handles invocation by the following guidelines: Called *in thread* from StateCheckInThread()
|
||||||
// prior to pausing the thread (ie, when Pause() has been called on a separate thread,
|
// prior to pausing the thread (ie, when Pause() has been called on a separate thread,
|
||||||
|
@ -163,7 +168,7 @@ public:
|
||||||
virtual void ApplySettings( const Pcsx2Config& src );
|
virtual void ApplySettings( const Pcsx2Config& src );
|
||||||
virtual void OnResumeReady();
|
virtual void OnResumeReady();
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
|
||||||
bool HasValidState()
|
bool HasValidState()
|
||||||
{
|
{
|
||||||
return m_hasValidState;
|
return m_hasValidState;
|
||||||
|
|
|
@ -41,7 +41,7 @@ bool AppCoreThread::Suspend( bool isBlocking )
|
||||||
m_kevt.m_shiftDown = false;
|
m_kevt.m_shiftDown = false;
|
||||||
m_kevt.m_controlDown = false;
|
m_kevt.m_controlDown = false;
|
||||||
m_kevt.m_altDown = false;
|
m_kevt.m_altDown = false;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,8 @@ void AppCoreThread::Resume()
|
||||||
evt.SetInt( CoreStatus_Suspended );
|
evt.SetInt( CoreStatus_Suspended );
|
||||||
wxGetApp().AddPendingEvent( evt );
|
wxGetApp().AddPendingEvent( evt );
|
||||||
|
|
||||||
sApp.SysExecute();
|
if( (m_ExecMode != ExecMode_Closing) || (m_ExecMode != ExecMode_Pausing) )
|
||||||
|
sApp.SysExecute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ void AppCoreThread::OnResumeReady()
|
||||||
void AppCoreThread::OnResumeInThread( bool isSuspended )
|
void AppCoreThread::OnResumeInThread( bool isSuspended )
|
||||||
{
|
{
|
||||||
_parent::OnResumeInThread( isSuspended );
|
_parent::OnResumeInThread( isSuspended );
|
||||||
|
|
||||||
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
wxCommandEvent evt( pxEVT_CoreThreadStatus );
|
||||||
evt.SetInt( CoreStatus_Resumed );
|
evt.SetInt( CoreStatus_Resumed );
|
||||||
wxGetApp().AddPendingEvent( evt );
|
wxGetApp().AddPendingEvent( evt );
|
||||||
|
|
|
@ -280,7 +280,7 @@ void MainEmuFrame::OnSettingsLoadSave( void* obj, const IniInterface& evt )
|
||||||
{
|
{
|
||||||
if( obj == NULL ) return;
|
if( obj == NULL ) return;
|
||||||
MainEmuFrame* mframe = (MainEmuFrame*)obj;
|
MainEmuFrame* mframe = (MainEmuFrame*)obj;
|
||||||
|
|
||||||
// FIXME: Evil const cast hack!
|
// FIXME: Evil const cast hack!
|
||||||
mframe->LoadSaveRecentIsoList( const_cast<IniInterface&>(evt) );
|
mframe->LoadSaveRecentIsoList( const_cast<IniInterface&>(evt) );
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
|
||||||
m_SaveStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Save01 ) ),
|
m_SaveStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Save01 ) ),
|
||||||
|
|
||||||
m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, MenuId_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) ),
|
m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, MenuId_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) ),
|
||||||
|
|
||||||
m_Listener_CoreThreadStatus( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener( this, OnCoreThreadStatusChanged ) ),
|
m_Listener_CoreThreadStatus( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener( this, OnCoreThreadStatusChanged ) ),
|
||||||
m_Listener_CorePluginStatus( wxGetApp().Source_CorePluginStatus(), CmdEvt_Listener( this, OnCorePluginStatusChanged ) ),
|
m_Listener_CorePluginStatus( wxGetApp().Source_CorePluginStatus(), CmdEvt_Listener( this, OnCorePluginStatusChanged ) ),
|
||||||
m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener<int>( this, OnSettingsApplied ) ),
|
m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener<int>( this, OnSettingsApplied ) ),
|
||||||
|
@ -518,6 +518,8 @@ void MainEmuFrame::ReloadRecentLists()
|
||||||
|
|
||||||
void MainEmuFrame::ApplyCoreStatus()
|
void MainEmuFrame::ApplyCoreStatus()
|
||||||
{
|
{
|
||||||
|
bool valstate = SysHasValidState();
|
||||||
|
|
||||||
GetMenuBar()->Enable( MenuId_Sys_SuspendResume, SysHasValidState() );
|
GetMenuBar()->Enable( MenuId_Sys_SuspendResume, SysHasValidState() );
|
||||||
GetMenuBar()->Enable( MenuId_Sys_Reset, SysHasValidState() || (g_plugins!=NULL) );
|
GetMenuBar()->Enable( MenuId_Sys_Reset, SysHasValidState() || (g_plugins!=NULL) );
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||||
*
|
*
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
@ -70,7 +70,7 @@ bool MainEmuFrame::_DoSelectIsoBrowser()
|
||||||
UpdateIsoSrcFile();
|
UpdateIsoSrcFile();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
|
||||||
{
|
{
|
||||||
CoreThread.Suspend();
|
CoreThread.Suspend();
|
||||||
|
|
||||||
if( !wxFileExists( g_Conf->CurrentIso ) )
|
if( (g_Conf->CdvdSource == CDVDsrc_Iso) && !wxFileExists(g_Conf->CurrentIso) )
|
||||||
{
|
{
|
||||||
if( !_DoSelectIsoBrowser() )
|
if( !_DoSelectIsoBrowser() )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue