diff --git a/common/src/Utilities/ThreadTools.cpp b/common/src/Utilities/ThreadTools.cpp index 6d1922479c..3b6bcb702b 100644 --- a/common/src/Utilities/ThreadTools.cpp +++ b/common/src/Utilities/ThreadTools.cpp @@ -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,8 +108,7 @@ namespace Threading if( _InterlockedExchange( &m_detached, true ) ) { - if( m_running ) - Console::Notice( "Threading Warning: Attempted to cancel detached thread; Ignoring..." ); + 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 diff --git a/pcsx2/CDVD/CDVDisoReader.cpp b/pcsx2/CDVD/CDVDisoReader.cpp index d4057125a3..bc48564f2e 100644 --- a/pcsx2/CDVD/CDVDisoReader.cpp +++ b/pcsx2/CDVD/CDVDisoReader.cpp @@ -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); } } diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index 07b20f68ab..44a79d68ce 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -450,7 +450,7 @@ __forceinline void rcntUpdate_vSync() { eeRecIsReset = false; cpuSetBranch(); - throw Exception::RecompilerReset(); + throw Exception::ForceDispatcherReg(); } VSyncEnd(vsyncCounter.sCycle); diff --git a/pcsx2/GS.h b/pcsx2/GS.h index ae22b7d731..a973b3e93a 100644 --- a/pcsx2/GS.h +++ b/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(); }; diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 5fc0e136de..6000034e05 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -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. diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index 9f589e990f..42d124cc30 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -717,18 +717,10 @@ static bool OpenPlugin_CDVD() static bool OpenPlugin_GS() { - if( mtgsThread == NULL ) - { - mtgsOpen(); // mtgsOpen raises its own exception on error - return true; - } + if( mtgsThread != NULL ) 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 + mtgsOpen(); // mtgsOpen raises its own exception on error + return true; } static bool OpenPlugin_PAD() @@ -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; - } + // force-close PAD before GS, because the PAD depends on the GS window. + Close( PluginId_PAD ); + safe_delete( mtgsThread ); } 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 ) diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index 1c3330836e..8661cd57b9 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -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[]; diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 8e7b27d315..b3a17032bb 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -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"); diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index fa84be41ab..c038201876 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -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__ diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 1b3c21982f..8f51433f43 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -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(); diff --git a/pcsx2/System.h b/pcsx2/System.h index a6d162aad4..96fe45d8fc 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -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 ); diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index 6ea31d8aaf..5a64e6f26d 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -319,7 +319,7 @@ protected: wxKeyEvent m_kevt; public: - AppEmuThread( const wxString& elf_file=wxEmptyString ); + AppEmuThread(); virtual ~AppEmuThread() { } virtual void Resume(); diff --git a/pcsx2/gui/MainMenuClicks.cpp b/pcsx2/gui/MainMenuClicks.cpp index 43733ae280..eafa4c1598 100644 --- a/pcsx2/gui/MainMenuClicks.cpp +++ b/pcsx2/gui/MainMenuClicks.cpp @@ -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 ); diff --git a/pcsx2/gui/main.cpp b/pcsx2/gui/main.cpp index 390f47fb2d..a7fc557820 100644 --- a/pcsx2/gui/main.cpp +++ b/pcsx2/gui/main.cpp @@ -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 ); } diff --git a/pcsx2/ps2/CoreEmuThread.cpp b/pcsx2/ps2/CoreEmuThread.cpp index 51f4861358..b3a2927528 100644 --- a/pcsx2/ps2/CoreEmuThread.cpp +++ b/pcsx2/ps2/CoreEmuThread.cpp @@ -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() diff --git a/pcsx2/ps2/CoreEmuThread.h b/pcsx2/ps2/CoreEmuThread.h index 9cc6726a70..6f99af8e26 100644 --- a/pcsx2/ps2/CoreEmuThread.h +++ b/pcsx2/ps2/CoreEmuThread.h @@ -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); } diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index b3c763ca08..161aebc4b8 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -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,51 +579,57 @@ static void recExecute() g_EEFreezeRegs = true; - while( true ) + try { - try + while( true ) { -#ifdef _MSC_VER - - __asm + try { - push ebx - push esi - push edi - push ebp + #ifdef _MSC_VER - call DispatcherReg + __asm + { + push ebx + push esi + push edi + push ebp - pop ebp - pop edi - pop esi - pop ebx + call DispatcherReg + + pop ebp + pop edi + pop esi + pop ebx + } + + #else // _MSC_VER + + __asm__ + ( + ".intel_syntax noprefix\n" + "push ebx\n" + "push esi\n" + "push edi\n" + "push ebp\n" + + "call DispatcherReg\n" + + "pop ebp\n" + "pop edi\n" + "pop esi\n" + "pop ebx\n" + ".att_syntax\n" + ); + #endif + } + catch( Exception::ForceDispatcherReg& ) + { } - -#else // _MSC_VER - - __asm__ - ( - ".intel_syntax noprefix\n" - "push ebx\n" - "push esi\n" - "push edi\n" - "push ebp\n" - - "call DispatcherReg\n" - - "pop ebp\n" - "pop edi\n" - "pop esi\n" - "pop ebx\n" - ".att_syntax\n" - ); -#endif - } - catch( Exception::RecompilerReset& ) - { } } + 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;