mirror of https://github.com/PCSX2/pcsx2.git
* Implemented Skip Bios (settings still not saved tho)
* Fixed a bug in how I was (not) handling pthreads return codes. It's errno you need to check, *not* the function's return value. ;) * Changed MTGS over to use the pthread_cleanup api. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1779 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
50446e6930
commit
976d5ec539
|
@ -62,9 +62,9 @@ namespace Threading
|
|||
if( !_InterlockedExchange( &m_detached, true ) )
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) );
|
||||
m_sem_finished.WaitGui();
|
||||
#else
|
||||
m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) );
|
||||
m_sem_finished.Wait();
|
||||
#endif
|
||||
m_running = false;
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ namespace Threading
|
|||
void PersistentThread::Start()
|
||||
{
|
||||
if( m_running ) return;
|
||||
m_sem_finished.Reset();
|
||||
if( pthread_create( &m_thread, NULL, _internal_callback, this ) != 0 )
|
||||
throw Exception::ThreadCreationError();
|
||||
|
||||
|
@ -107,7 +108,6 @@ namespace Threading
|
|||
|
||||
if( _InterlockedExchange( &m_detached, true ) )
|
||||
{
|
||||
if( m_running )
|
||||
Console::Notice( "Threading Warning: Attempted to cancel detached thread; Ignoring..." );
|
||||
return;
|
||||
}
|
||||
|
@ -118,9 +118,9 @@ namespace Threading
|
|||
if( isBlocking )
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) );
|
||||
m_sem_finished.WaitGui();
|
||||
#else
|
||||
m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) );
|
||||
m_sem_finished.Wait();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -152,9 +152,9 @@ namespace Threading
|
|||
DevAssert( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." );
|
||||
|
||||
#if wxUSE_GUI
|
||||
m_sem_finished.WaitGui( wxTimeSpan( 0, 0, 3 ) );
|
||||
m_sem_finished.WaitGui();
|
||||
#else
|
||||
m_sem_finished.Wait( wxTimeSpan( 0, 0, 3 ) );
|
||||
m_sem_finished.Wait();
|
||||
#endif
|
||||
return m_returncode;
|
||||
}
|
||||
|
@ -189,6 +189,7 @@ namespace Threading
|
|||
{
|
||||
wxASSERT( IsSelf() ); // only allowed from our own thread, thanks.
|
||||
_InterlockedExchange( &m_running, false );
|
||||
m_sem_finished.Post();
|
||||
}
|
||||
|
||||
void* PersistentThread::_internal_callback( void* itsme )
|
||||
|
@ -280,7 +281,7 @@ namespace Threading
|
|||
|
||||
do {
|
||||
wxTheApp->ProcessPendingEvents();
|
||||
} while( sem_timedwait( &sema, &ts_msec_200 ) == ETIMEDOUT );
|
||||
} while( (sem_timedwait( &sema, &ts_msec_200 ) == -1) && (errno == ETIMEDOUT) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +301,7 @@ namespace Threading
|
|||
static const wxTimeSpan pass( 0, 0, 0, 200 );
|
||||
do {
|
||||
wxTheApp->ProcessPendingEvents();
|
||||
if( sem_timedwait( &sema, &ts_msec_200 ) != ETIMEDOUT )
|
||||
if( (sem_timedwait( &sema, &ts_msec_200 ) == -1) && (errno == ETIMEDOUT) )
|
||||
break;
|
||||
countdown -= pass;
|
||||
} while( countdown.GetMilliseconds() > 0 );
|
||||
|
@ -318,7 +319,7 @@ namespace Threading
|
|||
bool Semaphore::Wait( const wxTimeSpan& timeout )
|
||||
{
|
||||
const timespec fail = { timeout.GetSeconds().GetLo(), 0 };
|
||||
return sem_timedwait( &sema, &fail ) != ETIMEDOUT;
|
||||
return sem_timedwait( &sema, &fail ) != -1;
|
||||
}
|
||||
|
||||
// Performs an uncancellable wait on a semaphore; restoring the thread's previous cancel state
|
||||
|
|
|
@ -128,9 +128,9 @@ static void FindLayer1Start()
|
|||
{
|
||||
// search for it
|
||||
int off = iso->blockofs;
|
||||
u8 tempbuffer[2352];
|
||||
u8 tempbuffer[CD_FRAMESIZE_RAW];
|
||||
|
||||
Console::Status("CDVD ISO: searching for layer1...");
|
||||
Console::Status("CDVDiso: searching for layer1...");
|
||||
//tempbuffer = (u8*)malloc(CD_FRAMESIZE_RAW);
|
||||
for (layer1start = (iso->blocks / 2 - 0x10) & ~0xf; layer1start < 0x200010; layer1start += 16)
|
||||
{
|
||||
|
@ -148,11 +148,12 @@ static void FindLayer1Start()
|
|||
|
||||
if(layer1start == 0x200010)
|
||||
{
|
||||
Console::Status("Couldn't find second layer on dual layer... ignoring\n");
|
||||
Console::Status("\tCouldn't find second layer on dual layer... ignoring");
|
||||
layer1start=-2;
|
||||
}
|
||||
|
||||
if(layer1start>=0) Console::Status("found at 0x%8.8x\n", params layer1start);
|
||||
if(layer1start>=0)
|
||||
Console::Status("\tfound at 0x%8.8x", params layer1start);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -450,7 +450,7 @@ __forceinline void rcntUpdate_vSync()
|
|||
{
|
||||
eeRecIsReset = false;
|
||||
cpuSetBranch();
|
||||
throw Exception::RecompilerReset();
|
||||
throw Exception::ForceDispatcherReg();
|
||||
}
|
||||
|
||||
VSyncEnd(vsyncCounter.sCycle);
|
||||
|
|
18
pcsx2/GS.h
18
pcsx2/GS.h
|
@ -180,10 +180,6 @@ protected:
|
|||
// used to regulate thread startup and gsInit
|
||||
Threading::Semaphore m_sem_InitDone;
|
||||
|
||||
// used for quitting the ringbuffer thread only -- is posted by the ringbuffer when
|
||||
// a QUIT message is processed (signals that the GS has been closed).
|
||||
Threading::Semaphore m_sem_Quitter;
|
||||
|
||||
Threading::MutexLock m_lock_RingRestart;
|
||||
|
||||
// used to keep multiple threads from sending packets to the ringbuffer concurrently.
|
||||
|
@ -251,17 +247,7 @@ public:
|
|||
|
||||
void PostVsyncEnd( bool updategs );
|
||||
|
||||
uptr FnPtr_SimplePacket() const
|
||||
{
|
||||
#ifndef __LINUX__
|
||||
__asm mov eax, SendSimplePacket
|
||||
#else
|
||||
__asm__ (".intel_syntax noprefix\n"
|
||||
"mov eax, SendSimplePacket\n"
|
||||
".att_syntax\n");
|
||||
#endif
|
||||
//return (uptr)&SendSimplePacket;
|
||||
}
|
||||
void _close_gs();
|
||||
|
||||
protected:
|
||||
// Saves MMX/XMM regs, posts an event to the mtgsThread flag and releases a timeslice.
|
||||
|
@ -279,7 +265,7 @@ protected:
|
|||
// Used internally by SendSimplePacket type functions
|
||||
uint _PrepForSimplePacket();
|
||||
void _FinishSimplePacket( uint future_writepos );
|
||||
|
||||
void _RingbufferLoop();
|
||||
sptr ExecuteTask();
|
||||
};
|
||||
|
||||
|
|
|
@ -222,13 +222,13 @@ mtgsThreadObject::~mtgsThreadObject()
|
|||
mtgsThreadObject::Cancel();
|
||||
}
|
||||
|
||||
// Closes the GS "forcefully" without waiting for it to finish rendering it's pending
|
||||
// queue of GS data.
|
||||
void mtgsThreadObject::Cancel()
|
||||
{
|
||||
SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 );
|
||||
SetEvent();
|
||||
m_sem_Quitter.Wait( wxTimeSpan( 0, 0, 5, 0 ) );
|
||||
Sleep( 2 );
|
||||
PersistentThread::Cancel( true );
|
||||
//SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 );
|
||||
//SetEvent();
|
||||
PersistentThread::Cancel();
|
||||
}
|
||||
|
||||
void mtgsThreadObject::Reset()
|
||||
|
@ -498,24 +498,22 @@ struct PacketTagType
|
|||
u32 data[3];
|
||||
};
|
||||
|
||||
sptr mtgsThreadObject::ExecuteTask()
|
||||
extern bool renderswitch;
|
||||
|
||||
void mtgsThreadObject::_close_gs()
|
||||
{
|
||||
memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(PS2MEM_GS) );
|
||||
GSsetBaseMem( m_gsMem );
|
||||
GSirqCallback( NULL );
|
||||
if( g_plugins != NULL )
|
||||
g_plugins->m_info[PluginId_GS].CommonBindings.Close();
|
||||
}
|
||||
|
||||
GetPluginManager().Open( PluginId_GS );
|
||||
|
||||
DbgCon::WriteLn( "MTGS: GSopen Finished, return code: 0x%x", params m_returncode );
|
||||
|
||||
GSCSRr = 0x551B4000; // 0x55190000
|
||||
m_sem_InitDone.Post();
|
||||
if (m_returncode != 0) { return m_returncode; } // error msg will be issued to the user by Plugins.c
|
||||
|
||||
#ifdef RINGBUF_DEBUG_STACK
|
||||
PacketTagType prevCmd;
|
||||
#endif
|
||||
static void _clean_close_gs( void* obj )
|
||||
{
|
||||
((mtgsThreadObject*)obj)->_close_gs();
|
||||
}
|
||||
|
||||
void mtgsThreadObject::_RingbufferLoop()
|
||||
{
|
||||
pthread_cleanup_push( _clean_close_gs, this );
|
||||
while( true )
|
||||
{
|
||||
m_sem_event.Wait();
|
||||
|
@ -526,7 +524,7 @@ sptr mtgsThreadObject::ExecuteTask()
|
|||
// ever be modified by this thread.
|
||||
while( m_RingPos != volatize(m_WritePos))
|
||||
{
|
||||
assert( m_RingPos < m_RingBufferSize );
|
||||
wxASSERT( m_RingPos < m_RingBufferSize );
|
||||
|
||||
const PacketTagType& tag = (PacketTagType&)m_RingBuffer[m_RingPos];
|
||||
u32 ringposinc = 1;
|
||||
|
@ -540,7 +538,7 @@ sptr mtgsThreadObject::ExecuteTask()
|
|||
{
|
||||
Console::Error( "MTGS Ringbuffer Critical Failure ---> %x to %x (prevCmd: %x)\n", params stackpos, m_RingPos, prevCmd.command );
|
||||
}
|
||||
assert( stackpos == m_RingPos );
|
||||
wxASSERT( stackpos == m_RingPos );
|
||||
prevCmd = tag;
|
||||
ringposStack.pop_back();
|
||||
m_lock_Stack.Unlock();
|
||||
|
@ -664,14 +662,14 @@ sptr mtgsThreadObject::ExecuteTask()
|
|||
break;
|
||||
|
||||
case GS_RINGTYPE_QUIT:
|
||||
GetPluginManager().Close( PluginId_GS );
|
||||
m_sem_Quitter.Post();
|
||||
return 0;
|
||||
// have to use some low level code, because all the standard Close api does is
|
||||
// trigger this very ringbuffer message!
|
||||
return;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
default:
|
||||
Console::Error("GSThreadProc, bad packet (%x) at m_RingPos: %x, m_WritePos: %x", params tag.command, m_RingPos, m_WritePos);
|
||||
assert(0);
|
||||
wxASSERT_MSG( false, L"Bad packet encountered in the MTGS Ringbuffer." );
|
||||
m_RingPos = m_WritePos;
|
||||
continue;
|
||||
#else
|
||||
|
@ -681,12 +679,35 @@ sptr mtgsThreadObject::ExecuteTask()
|
|||
}
|
||||
|
||||
uint newringpos = m_RingPos + ringposinc;
|
||||
assert( newringpos <= m_RingBufferSize );
|
||||
wxASSERT( newringpos <= m_RingBufferSize );
|
||||
newringpos &= m_RingBufferMask;
|
||||
AtomicExchange( m_RingPos, newringpos );
|
||||
}
|
||||
AtomicExchange( m_RingBufferIsBusy, 0 );
|
||||
}
|
||||
pthread_cleanup_pop( true );
|
||||
}
|
||||
|
||||
sptr mtgsThreadObject::ExecuteTask()
|
||||
{
|
||||
memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(PS2MEM_GS) );
|
||||
GSsetBaseMem( m_gsMem );
|
||||
GSirqCallback( NULL );
|
||||
|
||||
Console::WriteLn( (wxString)L"\t\tForced software switch: " + (renderswitch ? L"Enabled" : L"Disabled") );
|
||||
m_returncode = GSopen( (void*)&pDsp, "PCSX2", renderswitch ? 2 : 1 );
|
||||
DevCon::WriteLn( "MTGS: GSopen Finished, return code: 0x%x", params m_returncode );
|
||||
|
||||
GSCSRr = 0x551B4000; // 0x55190000
|
||||
m_sem_InitDone.Post();
|
||||
if (m_returncode != 0) { return m_returncode; } // error msg will be issued to the user by Plugins.c
|
||||
|
||||
#ifdef RINGBUF_DEBUG_STACK
|
||||
PacketTagType prevCmd;
|
||||
#endif
|
||||
|
||||
_RingbufferLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Waits for the GS to empty out the entire ring buffer contents.
|
||||
|
|
|
@ -717,20 +717,12 @@ static bool OpenPlugin_CDVD()
|
|||
|
||||
static bool OpenPlugin_GS()
|
||||
{
|
||||
if( mtgsThread == NULL )
|
||||
{
|
||||
if( mtgsThread != NULL ) return true;
|
||||
|
||||
mtgsOpen(); // mtgsOpen raises its own exception on error
|
||||
return true;
|
||||
}
|
||||
|
||||
if( !mtgsThread->IsSelf() ) return true; // already opened?
|
||||
|
||||
return !GSopen( (void*)&pDsp, "PCSX2", renderswitch ? 2 : 1 );
|
||||
|
||||
// Note: renderswitch is us abusing the isMultiThread parameter for that so
|
||||
// we don't need a new callback
|
||||
}
|
||||
|
||||
static bool OpenPlugin_PAD()
|
||||
{
|
||||
return !PADopen( (void*)&pDsp );
|
||||
|
@ -815,29 +807,22 @@ void PluginManager::Open()
|
|||
void PluginManager::Close( PluginsEnum_t pid )
|
||||
{
|
||||
if( !m_info[pid].IsOpened ) return;
|
||||
|
||||
DevCon::Status( "\tClosing %s", params tbl_PluginInfo[pid].shortname );
|
||||
|
||||
if( pid == PluginId_GS )
|
||||
{
|
||||
if( mtgsThread == NULL ) return;
|
||||
|
||||
if( !mtgsThread->IsSelf() )
|
||||
{
|
||||
// force-close PAD before GS, because the PAD depends on the GS window.
|
||||
Close( PluginId_PAD );
|
||||
|
||||
safe_delete( mtgsThread );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( pid == PluginId_CDVD )
|
||||
{
|
||||
DoCDVDclose();
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_info[pid].CommonBindings.Close();
|
||||
|
||||
m_info[pid].IsOpened = false;
|
||||
m_info[pid].CommonBindings.Close();
|
||||
}
|
||||
|
||||
void PluginManager::Close( bool closegs )
|
||||
|
|
|
@ -137,6 +137,7 @@ struct LegacyPluginAPI_Common
|
|||
};
|
||||
|
||||
class SaveState;
|
||||
class mtgsThreadObject;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// IPluginManager
|
||||
|
@ -228,6 +229,8 @@ protected:
|
|||
void BindCommon( PluginsEnum_t pid );
|
||||
void BindRequired( PluginsEnum_t pid );
|
||||
void BindOptional( PluginsEnum_t pid );
|
||||
|
||||
friend class mtgsThreadObject;
|
||||
};
|
||||
|
||||
extern const PluginInfo tbl_PluginInfo[];
|
||||
|
|
|
@ -560,6 +560,7 @@ void cpuExecuteBios()
|
|||
|
||||
Console::Status( "Executing Bios Stub..." );
|
||||
|
||||
PCSX2_MEM_PROTECT_BEGIN();
|
||||
g_ExecBiosHack = true;
|
||||
while( cpuRegs.pc != 0x00200008 &&
|
||||
cpuRegs.pc != 0x00100008 )
|
||||
|
@ -567,6 +568,7 @@ void cpuExecuteBios()
|
|||
Cpu->Execute();
|
||||
}
|
||||
g_ExecBiosHack = false;
|
||||
PCSX2_MEM_PROTECT_END();
|
||||
|
||||
// {
|
||||
// FILE* f = fopen("eebios.bin", "wb");
|
||||
|
|
|
@ -36,10 +36,16 @@ namespace Exception
|
|||
// Implementation Note: this exception has no meaningful type information and we don't
|
||||
// care to have it be caught by any BaseException handlers lying about, so let's not
|
||||
// derive from BaseException :D
|
||||
class RecompilerReset
|
||||
class ForceDispatcherReg
|
||||
{
|
||||
public:
|
||||
explicit RecompilerReset() { }
|
||||
explicit ForceDispatcherReg() { }
|
||||
};
|
||||
|
||||
class ExitRecExecute
|
||||
{
|
||||
public:
|
||||
explicit ExitRecExecute() { }
|
||||
};
|
||||
}
|
||||
#ifndef __LINUX__
|
||||
|
|
|
@ -362,9 +362,9 @@ void SysLoadState( const wxString& file )
|
|||
GSsetGameCRC(ElfCRC, g_ZeroGSOptions);
|
||||
}
|
||||
|
||||
void SysReset()
|
||||
void SysShutdown()
|
||||
{
|
||||
Console::Status( _("Resetting...") );
|
||||
Console::Status( "Resetting..." );
|
||||
|
||||
safe_delete( g_EmuThread );
|
||||
GetPluginManager().Shutdown();
|
||||
|
|
|
@ -33,7 +33,7 @@ class CoreEmuThread;
|
|||
|
||||
extern bool SysInit();
|
||||
extern void SysDetect(); // Detects cpu type and fills cpuInfo structs.
|
||||
extern void SysReset(); // Resets the various PS2 cpus, sub-systems, and recompilers.
|
||||
extern void SysShutdown(); // Resets the various PS2 cpus, sub-systems, and recompilers.
|
||||
|
||||
extern void SysExecute( CoreEmuThread* newThread );
|
||||
extern void SysExecute( CoreEmuThread* newThread, CDVD_SourceType cdvdsrc );
|
||||
|
|
|
@ -319,7 +319,7 @@ protected:
|
|||
wxKeyEvent m_kevt;
|
||||
|
||||
public:
|
||||
AppEmuThread( const wxString& elf_file=wxEmptyString );
|
||||
AppEmuThread();
|
||||
virtual ~AppEmuThread() { }
|
||||
|
||||
virtual void Resume();
|
||||
|
|
|
@ -111,6 +111,8 @@ void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
|
|||
SysEndExecution();
|
||||
InitPlugins();
|
||||
|
||||
EmuConfig.SkipBiosSplash = GetMenuBar()->IsChecked( MenuId_SkipBiosToggle );
|
||||
|
||||
CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso );
|
||||
SysExecute( new AppEmuThread(), g_Conf->CdvdSource );
|
||||
}
|
||||
|
@ -134,33 +136,8 @@ void MainEmuFrame::Menu_RunIso_Click( wxCommandEvent &event )
|
|||
|
||||
SysEndExecution();
|
||||
|
||||
wxString elf_file;
|
||||
if( EmuConfig.SkipBiosSplash )
|
||||
{
|
||||
// Fetch the ELF filename and CD type from the CDVD provider.
|
||||
wxString ename( g_Conf->CurrentIso );
|
||||
int result = GetPS2ElfName( ename );
|
||||
switch( result )
|
||||
{
|
||||
case 0:
|
||||
Msgbox::Alert( _("Boot failed: CDVD image is not a PS1 or PS2 game.") );
|
||||
return;
|
||||
|
||||
case 1:
|
||||
Msgbox::Alert( _("Boot failed: PCSX2 does not support emulation of PS1 games.") );
|
||||
return;
|
||||
|
||||
case 2:
|
||||
// PS2 game. Valid!
|
||||
elf_file = ename;
|
||||
break;
|
||||
|
||||
jNO_DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
InitPlugins();
|
||||
SysExecute( new AppEmuThread( elf_file ), CDVDsrc_Iso );
|
||||
SysExecute( new AppEmuThread(), CDVDsrc_Iso );
|
||||
}
|
||||
|
||||
/*void MainEmuFrame::Menu_RunWithoutDisc_Click(wxCommandEvent &event)
|
||||
|
@ -218,13 +195,13 @@ void MainEmuFrame::Menu_SaveStateOther_Click(wxCommandEvent &event)
|
|||
|
||||
void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event)
|
||||
{
|
||||
SysReset();
|
||||
SysShutdown();
|
||||
Close();
|
||||
}
|
||||
|
||||
void MainEmuFrame::Menu_EmuClose_Click(wxCommandEvent &event)
|
||||
{
|
||||
SysReset();
|
||||
SysEndExecution();
|
||||
GetMenuBar()->Check( MenuId_Emu_Pause, false );
|
||||
}
|
||||
|
||||
|
@ -239,7 +216,7 @@ void MainEmuFrame::Menu_EmuPause_Click(wxCommandEvent &event)
|
|||
void MainEmuFrame::Menu_EmuReset_Click(wxCommandEvent &event)
|
||||
{
|
||||
bool wasRunning = EmulationInProgress();
|
||||
SysReset();
|
||||
SysShutdown();
|
||||
|
||||
GetMenuBar()->Check( MenuId_Emu_Pause, false );
|
||||
|
||||
|
|
|
@ -59,9 +59,9 @@ namespace Exception
|
|||
};
|
||||
}
|
||||
|
||||
AppEmuThread::AppEmuThread( const wxString& elf_file ) :
|
||||
m_kevt()
|
||||
, CoreEmuThread( elf_file )
|
||||
AppEmuThread::AppEmuThread() :
|
||||
CoreEmuThread()
|
||||
, m_kevt()
|
||||
{
|
||||
MemoryCard::Init();
|
||||
}
|
||||
|
@ -414,7 +414,7 @@ void Pcsx2App::OnMessageBox( pxMessageBoxEvent& evt )
|
|||
|
||||
void Pcsx2App::CleanupMess()
|
||||
{
|
||||
SysReset();
|
||||
SysShutdown();
|
||||
safe_delete( m_Bitmap_Logo );
|
||||
safe_delete( g_Conf );
|
||||
}
|
||||
|
|
|
@ -43,9 +43,6 @@ void CoreEmuThread::CpuInitializeMess()
|
|||
SysClearExecutionCache();
|
||||
GetPluginManager().Open();
|
||||
|
||||
if( GSsetGameCRC != NULL )
|
||||
GSsetGameCRC( ElfCRC, 0 );
|
||||
|
||||
if( StateRecovery::HasState() )
|
||||
{
|
||||
// no need to boot bios or detect CDs when loading savestates.
|
||||
|
@ -56,7 +53,30 @@ void CoreEmuThread::CpuInitializeMess()
|
|||
}
|
||||
else
|
||||
{
|
||||
if( !m_elf_file.IsEmpty() )
|
||||
wxString elf_file;
|
||||
if( EmuConfig.SkipBiosSplash )
|
||||
{
|
||||
// Fetch the ELF filename and CD type from the CDVD provider.
|
||||
wxString ename;
|
||||
int result = GetPS2ElfName( ename );
|
||||
switch( result )
|
||||
{
|
||||
case 0:
|
||||
throw Exception::RuntimeError( wxLt("Fast Boot failed: CDVD image is not a PS1 or PS2 game.") );
|
||||
|
||||
case 1:
|
||||
throw Exception::RuntimeError( wxLt("Fast Boot failed: PCSX2 does not support emulation of PS1 games.") );
|
||||
|
||||
case 2:
|
||||
// PS2 game. Valid!
|
||||
elf_file = ename;
|
||||
break;
|
||||
|
||||
jNO_DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
if( !elf_file.IsEmpty() )
|
||||
{
|
||||
// Skip Bios Hack -- Runs the PS2 BIOS stub, and then manually loads the ELF
|
||||
// executable data, and injects the cpuRegs.pc with the address of the
|
||||
|
@ -66,9 +86,12 @@ void CoreEmuThread::CpuInitializeMess()
|
|||
// (though not recommended for games because of rare ill side effects).
|
||||
|
||||
cpuExecuteBios();
|
||||
loadElfFile( m_elf_file );
|
||||
loadElfFile( elf_file );
|
||||
}
|
||||
}
|
||||
|
||||
if( GSsetGameCRC != NULL )
|
||||
GSsetGameCRC( ElfCRC, 0 );
|
||||
}
|
||||
|
||||
// special macro which disables inlining on functions that require their own function stackframe.
|
||||
|
@ -140,14 +163,13 @@ void CoreEmuThread::StateCheck()
|
|||
}
|
||||
}
|
||||
|
||||
CoreEmuThread::CoreEmuThread( const wxString& elf_file ) :
|
||||
CoreEmuThread::CoreEmuThread() :
|
||||
m_ExecMode( ExecMode_Idle )
|
||||
, m_ResumeEvent()
|
||||
, m_SuspendEvent()
|
||||
, m_resetRecompilers( false )
|
||||
, m_resetProfilers( false )
|
||||
|
||||
, m_elf_file( elf_file )
|
||||
, m_lock_ExecMode()
|
||||
{
|
||||
PersistentThread::Start();
|
||||
|
@ -156,8 +178,8 @@ CoreEmuThread::CoreEmuThread( const wxString& elf_file ) :
|
|||
// Invoked by the pthread_exit or pthread_cancel
|
||||
void CoreEmuThread::DoThreadCleanup()
|
||||
{
|
||||
PersistentThread::DoThreadCleanup();
|
||||
GetPluginManager().Close();
|
||||
PersistentThread::DoThreadCleanup();
|
||||
}
|
||||
|
||||
CoreEmuThread::~CoreEmuThread()
|
||||
|
|
|
@ -45,15 +45,13 @@ protected:
|
|||
bool m_resetRecompilers;
|
||||
bool m_resetProfilers;
|
||||
|
||||
const wxString m_elf_file;
|
||||
|
||||
MutexLock m_lock_ExecMode;
|
||||
|
||||
public:
|
||||
static CoreEmuThread& Get();
|
||||
|
||||
public:
|
||||
explicit CoreEmuThread( const wxString& elf_file=wxEmptyString );
|
||||
explicit CoreEmuThread();
|
||||
virtual ~CoreEmuThread();
|
||||
|
||||
bool IsSuspended() const { return (m_ExecMode == ExecMode_Suspended); }
|
||||
|
|
|
@ -288,7 +288,7 @@ u32* recGetImm64(u32 hi, u32 lo)
|
|||
if (recConstBufPtr >= recConstBuf + RECCONSTBUF_SIZE)
|
||||
{
|
||||
Console::Status( "EErec const buffer filled; Resetting..." );
|
||||
throw Exception::RecompilerReset();
|
||||
throw Exception::ForceDispatcherReg();
|
||||
|
||||
/*for (u32 *p = recConstBuf; p < recConstBuf + RECCONSTBUF_SIZE; p += 2)
|
||||
{
|
||||
|
@ -579,6 +579,8 @@ static void recExecute()
|
|||
|
||||
g_EEFreezeRegs = true;
|
||||
|
||||
try
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
try
|
||||
|
@ -620,10 +622,14 @@ static void recExecute()
|
|||
);
|
||||
#endif
|
||||
}
|
||||
catch( Exception::RecompilerReset& )
|
||||
catch( Exception::ForceDispatcherReg& )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception::ExitRecExecute& )
|
||||
{
|
||||
}
|
||||
|
||||
g_EEFreezeRegs = false;
|
||||
}
|
||||
|
@ -750,27 +756,21 @@ void recClear(u32 addr, u32 size)
|
|||
ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4);
|
||||
}
|
||||
|
||||
static void ExitRec()
|
||||
{
|
||||
throw Exception::ExitRecExecute();
|
||||
}
|
||||
|
||||
// check for end of bios
|
||||
void CheckForBIOSEnd()
|
||||
{
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.pc);
|
||||
xMOV( eax, &cpuRegs.pc );
|
||||
|
||||
CMP32ItoR(EAX, 0x00200008);
|
||||
j8Ptr[0] = JE8(0);
|
||||
xCMP( eax, 0x00200008 );
|
||||
xJE( ExitRec );
|
||||
|
||||
CMP32ItoR(EAX, 0x00100008);
|
||||
j8Ptr[1] = JE8(0);
|
||||
|
||||
// return
|
||||
j8Ptr[2] = JMP8(0);
|
||||
|
||||
x86SetJ8( j8Ptr[0] );
|
||||
x86SetJ8( j8Ptr[1] );
|
||||
|
||||
// bios end
|
||||
RET();
|
||||
|
||||
x86SetJ8( j8Ptr[2] );
|
||||
xCMP( eax, 0x00100008 );
|
||||
xJE( ExitRec );
|
||||
}
|
||||
|
||||
static int *s_pCode;
|
||||
|
|
Loading…
Reference in New Issue