mirror of https://github.com/PCSX2/pcsx2.git
wxgui: Prepped the R5900 recompiler for the new wxWidgets-enhanced dedicated emulation thread design, and removed the old boolean-based re-entrant event checking mess.
Note: Nearly have a successfully booting branch! (bios crashes when it reaches CDVD api callbacks, should be a simple fix but it'll have to wait until later >_<) git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1680 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
307346e19e
commit
9303bc5bf2
|
@ -540,6 +540,7 @@ typedef void (CALLBACK* _GSmakeSnapshot2)(const char *path, int*, int);
|
||||||
//typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info);
|
//typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info);
|
||||||
|
|
||||||
// PAD
|
// PAD
|
||||||
|
typedef s32 (CALLBACK* _PADinit)(u32 flags);
|
||||||
typedef s32 (CALLBACK* _PADopen)(void *pDsp);
|
typedef s32 (CALLBACK* _PADopen)(void *pDsp);
|
||||||
typedef u8 (CALLBACK* _PADstartPoll)(int pad);
|
typedef u8 (CALLBACK* _PADstartPoll)(int pad);
|
||||||
typedef u8 (CALLBACK* _PADpoll)(u8 value);
|
typedef u8 (CALLBACK* _PADpoll)(u8 value);
|
||||||
|
|
|
@ -43,6 +43,8 @@ namespace Exception
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class wxTimeSpan;
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -74,7 +76,9 @@ namespace Threading
|
||||||
void Reset();
|
void Reset();
|
||||||
void Post();
|
void Post();
|
||||||
void Post( int multiple );
|
void Post( int multiple );
|
||||||
|
|
||||||
void Wait();
|
void Wait();
|
||||||
|
void Wait( const wxTimeSpan& timeout );
|
||||||
void WaitNoCancel();
|
void WaitNoCancel();
|
||||||
int Count();
|
int Count();
|
||||||
};
|
};
|
||||||
|
@ -107,7 +111,7 @@ namespace Threading
|
||||||
// PersistentThread - Helper class for the basics of starting/managing persistent threads.
|
// PersistentThread - Helper class for the basics of starting/managing persistent threads.
|
||||||
//
|
//
|
||||||
// Use this as a base class for your threaded procedure, and implement the 'int ExecuteTask()'
|
// Use this as a base class for your threaded procedure, and implement the 'int ExecuteTask()'
|
||||||
// method. Use Start() and Cancel() to start and shutdown the thread, and use m_post_event
|
// method. Use Start() and Cancel() to start and shutdown the thread, and use m_sem_event
|
||||||
// internally to post/receive events for the thread (make a public accessor for it in your
|
// internally to post/receive events for the thread (make a public accessor for it in your
|
||||||
// derived class if your thread utilizes the post).
|
// derived class if your thread utilizes the post).
|
||||||
//
|
//
|
||||||
|
@ -127,7 +131,7 @@ namespace Threading
|
||||||
sptr m_returncode; // value returned from the thread on close.
|
sptr m_returncode; // value returned from the thread on close.
|
||||||
|
|
||||||
bool m_running;
|
bool m_running;
|
||||||
Semaphore m_post_event; // general wait event that's needed by most threads.
|
Semaphore m_sem_event; // general wait event that's needed by most threads.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~PersistentThread();
|
virtual ~PersistentThread();
|
||||||
|
@ -259,7 +263,7 @@ namespace Threading
|
||||||
{
|
{
|
||||||
if( !m_running ) return m_returncode;
|
if( !m_running ) return m_returncode;
|
||||||
m_Done = true;
|
m_Done = true;
|
||||||
m_post_event.Post();
|
m_sem_event.Post();
|
||||||
return PersistentThread::Block();
|
return PersistentThread::Block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +274,7 @@ namespace Threading
|
||||||
jASSUME( m_running );
|
jASSUME( m_running );
|
||||||
m_TaskComplete = false;
|
m_TaskComplete = false;
|
||||||
m_post_TaskComplete.Reset();
|
m_post_TaskComplete.Reset();
|
||||||
m_post_event.Post();
|
m_sem_event.Post();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocks current thread execution pending the completion of the parallel task.
|
// Blocks current thread execution pending the completion of the parallel task.
|
||||||
|
@ -293,7 +297,7 @@ namespace Threading
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Wait for a job!
|
// Wait for a job!
|
||||||
m_post_event.Wait();
|
m_sem_event.Wait();
|
||||||
|
|
||||||
if( m_Done ) break;
|
if( m_Done ) break;
|
||||||
Task();
|
Task();
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "Threading.h"
|
#include "Threading.h"
|
||||||
|
|
||||||
|
#include <wx/datetime.h>
|
||||||
|
|
||||||
#ifdef __LINUX__
|
#ifdef __LINUX__
|
||||||
# include <signal.h> // for pthread_kill, which is in pthread.h on w32-pthreads
|
# include <signal.h> // for pthread_kill, which is in pthread.h on w32-pthreads
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,7 +33,7 @@ namespace Threading
|
||||||
m_thread()
|
m_thread()
|
||||||
, m_returncode( 0 )
|
, m_returncode( 0 )
|
||||||
, m_running( false )
|
, m_running( false )
|
||||||
, m_post_event()
|
, m_sem_event()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,22 +177,30 @@ namespace Threading
|
||||||
sem_post( &sema );
|
sem_post( &sema );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Valid on Win32 builds only!! Attempts to use it on Linux will result in unresolved
|
||||||
|
// external linker errors.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
void Semaphore::Post( int multiple )
|
void Semaphore::Post( int multiple )
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER)
|
|
||||||
sem_post_multiple( &sema, multiple );
|
sem_post_multiple( &sema, multiple );
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Semaphore::Wait()
|
void Semaphore::Wait()
|
||||||
{
|
{
|
||||||
sem_wait( &sema );
|
sem_wait( &sema );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Semaphore::Wait( const wxTimeSpan& timeout )
|
||||||
|
{
|
||||||
|
const timespec fail = { timeout.GetSeconds().GetLo(), 0 };
|
||||||
|
sem_timedwait( &sema, &fail );
|
||||||
|
}
|
||||||
|
|
||||||
// Performs an uncancellable wait on a semaphore; restoring the thread's previous cancel state
|
// Performs an uncancellable wait on a semaphore; restoring the thread's previous cancel state
|
||||||
// after the wait has completed. Useful for situations where the semaphore itself is stored on
|
// after the wait has completed. Useful for situations where the semaphore itself is stored on
|
||||||
// the stack and passed to another thread via GUI message or such, avoiding complications where
|
// the stack and passed to another thread via GUI message or such, avoiding complications where
|
||||||
// the thread might be cancelled and the stack value becomes invalid.
|
// the thread might be canceled and the stack value becomes invalid.
|
||||||
//
|
//
|
||||||
// Performance note: this function has quite a bit more overhead compared to Semaphore::Wait(), so
|
// Performance note: this function has quite a bit more overhead compared to Semaphore::Wait(), so
|
||||||
// consider manually specifying the thread as uncancellable and using Wait() instead if you need
|
// consider manually specifying the thread as uncancellable and using Wait() instead if you need
|
||||||
|
|
|
@ -107,12 +107,11 @@ void Win32::RealVersionInfo::InitVersionString()
|
||||||
int majorVersion = (DWORD)(LOBYTE(LOWORD(version)));
|
int majorVersion = (DWORD)(LOBYTE(LOWORD(version)));
|
||||||
int minorVersion = (DWORD)(HIBYTE(LOWORD(version)));
|
int minorVersion = (DWORD)(HIBYTE(LOWORD(version)));
|
||||||
|
|
||||||
RealVersionInfo really;
|
|
||||||
wxString verName( wxString::FromAscii( GetVersionName( minorVersion, majorVersion ) ) );
|
wxString verName( wxString::FromAscii( GetVersionName( minorVersion, majorVersion ) ) );
|
||||||
|
|
||||||
bool IsCompatMode = false;
|
bool IsCompatMode = false;
|
||||||
|
|
||||||
if( really.IsVista() )
|
if( IsVista() )
|
||||||
{
|
{
|
||||||
m_VersionString = L"Windows Vista";
|
m_VersionString = L"Windows Vista";
|
||||||
|
|
||||||
|
@ -131,7 +130,7 @@ void Win32::RealVersionInfo::InitVersionString()
|
||||||
else
|
else
|
||||||
m_VersionString += L" (32-bit)";
|
m_VersionString += L" (32-bit)";
|
||||||
}
|
}
|
||||||
else if( really.IsXP() )
|
else if( IsXP() )
|
||||||
{
|
{
|
||||||
m_VersionString = wxsFormat( L"Windows XP v%d.%d", majorVersion, minorVersion );
|
m_VersionString = wxsFormat( L"Windows XP v%d.%d", majorVersion, minorVersion );
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ class IniInterface;
|
||||||
|
|
||||||
enum PluginsEnum_t
|
enum PluginsEnum_t
|
||||||
{
|
{
|
||||||
PluginId_CDVD = 0,
|
PluginId_GS = 0,
|
||||||
PluginId_GS,
|
|
||||||
PluginId_PAD,
|
PluginId_PAD,
|
||||||
PluginId_SPU2,
|
PluginId_SPU2,
|
||||||
|
PluginId_CDVD,
|
||||||
PluginId_USB,
|
PluginId_USB,
|
||||||
PluginId_FW,
|
PluginId_FW,
|
||||||
PluginId_DEV9,
|
PluginId_DEV9,
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
#include "VUmicro.h"
|
#include "VUmicro.h"
|
||||||
|
#include "ps2/CoreEmuThread.h"
|
||||||
|
|
||||||
using namespace Threading;
|
using namespace Threading;
|
||||||
|
|
||||||
|
@ -436,10 +437,10 @@ __forceinline void rcntUpdate_hScanline()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline bool rcntUpdate_vSync()
|
__forceinline void rcntUpdate_vSync()
|
||||||
{
|
{
|
||||||
s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
|
s32 diff = (cpuRegs.cycle - vsyncCounter.sCycle);
|
||||||
if( diff < vsyncCounter.CycleT ) return false;
|
if( diff < vsyncCounter.CycleT ) return;
|
||||||
|
|
||||||
//iopBranchAction = 1;
|
//iopBranchAction = 1;
|
||||||
if (vsyncCounter.Mode == MODE_VSYNC)
|
if (vsyncCounter.Mode == MODE_VSYNC)
|
||||||
|
@ -449,8 +450,8 @@ __forceinline bool rcntUpdate_vSync()
|
||||||
vsyncCounter.sCycle += vSyncInfo.Blank;
|
vsyncCounter.sCycle += vSyncInfo.Blank;
|
||||||
vsyncCounter.CycleT = vSyncInfo.Render;
|
vsyncCounter.CycleT = vSyncInfo.Render;
|
||||||
vsyncCounter.Mode = MODE_VRENDER;
|
vsyncCounter.Mode = MODE_VRENDER;
|
||||||
|
|
||||||
return true;
|
CoreEmuThread::Get().StateCheck();
|
||||||
}
|
}
|
||||||
else // VSYNC end / VRENDER begin
|
else // VSYNC end / VRENDER begin
|
||||||
{
|
{
|
||||||
|
@ -477,7 +478,6 @@ __forceinline bool rcntUpdate_vSync()
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline void _cpuTestTarget( int i )
|
static __forceinline void _cpuTestTarget( int i )
|
||||||
|
@ -518,14 +518,14 @@ static __forceinline void _cpuTestOverflow( int i )
|
||||||
// forceinline note: this method is called from two locations, but one
|
// forceinline note: this method is called from two locations, but one
|
||||||
// of them is the interpreter, which doesn't count. ;) So might as
|
// of them is the interpreter, which doesn't count. ;) So might as
|
||||||
// well forceinline it!
|
// well forceinline it!
|
||||||
__forceinline bool rcntUpdate()
|
__forceinline void rcntUpdate()
|
||||||
{
|
{
|
||||||
bool retval = rcntUpdate_vSync();
|
rcntUpdate_vSync();
|
||||||
|
|
||||||
// Update counters so that we can perform overflow and target tests.
|
// Update counters so that we can perform overflow and target tests.
|
||||||
|
|
||||||
for (int i=0; i<=3; i++) {
|
for (int i=0; i<=3; i++)
|
||||||
|
{
|
||||||
// We want to count gated counters (except the hblank which exclude below, and are
|
// We want to count gated counters (except the hblank which exclude below, and are
|
||||||
// counted by the hblank timer instead)
|
// counted by the hblank timer instead)
|
||||||
|
|
||||||
|
@ -550,7 +550,6 @@ __forceinline bool rcntUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
cpuRcntSet();
|
cpuRcntSet();
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline void _rcntSetGate( int index )
|
static __forceinline void _rcntSetGate( int index )
|
||||||
|
@ -582,8 +581,8 @@ __forceinline void rcntStartGate(bool isVblank, u32 sCycle)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i <=3; i++) {
|
for (i=0; i <=3; i++)
|
||||||
|
{
|
||||||
//if ((mode == 0) && ((counters[i].mode & 0x83) == 0x83))
|
//if ((mode == 0) && ((counters[i].mode & 0x83) == 0x83))
|
||||||
if (!isVblank && counters[i].mode.IsCounting && (counters[i].mode.ClockSource == 3) )
|
if (!isVblank && counters[i].mode.IsCounting && (counters[i].mode.ClockSource == 3) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,8 +135,8 @@ extern s32 nextCounter; // delta until the next counter event (must be signed)
|
||||||
extern u32 nextsCounter;
|
extern u32 nextsCounter;
|
||||||
|
|
||||||
extern void rcntUpdate_hScanline();
|
extern void rcntUpdate_hScanline();
|
||||||
extern bool rcntUpdate_vSync();
|
extern void rcntUpdate_vSync();
|
||||||
extern bool rcntUpdate();
|
extern void rcntUpdate();
|
||||||
|
|
||||||
extern void rcntInit();
|
extern void rcntInit();
|
||||||
extern void rcntStartGate(bool mode, u32 sCycle);
|
extern void rcntStartGate(bool mode, u32 sCycle);
|
||||||
|
|
55
pcsx2/GS.cpp
55
pcsx2/GS.cpp
|
@ -30,8 +30,6 @@ using namespace Threading;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace R5900;
|
using namespace R5900;
|
||||||
|
|
||||||
static bool m_gsOpened = false;
|
|
||||||
|
|
||||||
u32 CSRw;
|
u32 CSRw;
|
||||||
|
|
||||||
PCSX2_ALIGNED16( u8 g_RealGSMem[0x2000] );
|
PCSX2_ALIGNED16( u8 g_RealGSMem[0x2000] );
|
||||||
|
@ -150,61 +148,10 @@ void gsInit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opens the gsRingbuffer thread.
|
|
||||||
s32 gsOpen()
|
|
||||||
{
|
|
||||||
if( m_gsOpened ) return 0;
|
|
||||||
|
|
||||||
//video
|
|
||||||
// Only bind the gsIrq if we're not running the MTGS.
|
|
||||||
// The MTGS simulates its own gsIrq in order to maintain proper sync.
|
|
||||||
|
|
||||||
m_gsOpened = mtgsOpen();
|
|
||||||
if( !m_gsOpened )
|
|
||||||
{
|
|
||||||
// MTGS failed to init or is disabled. Try the GS instead!
|
|
||||||
// ... and set the memptr again just in case (for switching between GS/MTGS on the fly)
|
|
||||||
|
|
||||||
GSsetBaseMem( PS2MEM_GS );
|
|
||||||
GSirqCallback( gsIrq );
|
|
||||||
|
|
||||||
m_gsOpened = !GSopen( &pDsp, "PCSX2", 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if( m_gsOpened )
|
|
||||||
{
|
|
||||||
gsOnModeChanged(
|
|
||||||
(Config.PsxType & 1) ? FRAMERATE_PAL : FRAMERATE_NTSC,
|
|
||||||
UpdateVSyncRate()
|
|
||||||
);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// FIXME : This is the gs/vsync tie-in for framelimiting, but it really
|
|
||||||
// needs to be called from the hotkey framelimiter enable/disable too.
|
|
||||||
|
|
||||||
if(GSsetFrameLimit == NULL)
|
|
||||||
{
|
|
||||||
DevCon::Notice("Notice: GS Plugin does not implement GSsetFrameLimit.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GSsetFrameLimit( EmuConfig.Video.EnableFrameLimiting );
|
|
||||||
}
|
|
||||||
|
|
||||||
return !m_gsOpened;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gsClose()
|
|
||||||
{
|
|
||||||
if( !m_gsOpened ) return;
|
|
||||||
m_gsOpened = false;
|
|
||||||
safe_delete( mtgsThread );
|
|
||||||
}
|
|
||||||
|
|
||||||
void gsReset()
|
void gsReset()
|
||||||
{
|
{
|
||||||
// Sanity check in case the plugin hasn't been initialized...
|
// Sanity check in case the plugin hasn't been initialized...
|
||||||
if( !m_gsOpened ) return;
|
if( mtgsThread == NULL ) return;
|
||||||
mtgsThread->Reset();
|
mtgsThread->Reset();
|
||||||
|
|
||||||
gsOnModeChanged(
|
gsOnModeChanged(
|
||||||
|
|
|
@ -178,7 +178,11 @@ protected:
|
||||||
uint m_WritePos; // cur pos ee thread is writing to
|
uint m_WritePos; // cur pos ee thread is writing to
|
||||||
|
|
||||||
// used to regulate thread startup and gsInit
|
// used to regulate thread startup and gsInit
|
||||||
Threading::Semaphore m_post_InitDone;
|
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;
|
Threading::MutexLock m_lock_RingRestart;
|
||||||
|
|
||||||
|
@ -282,8 +286,7 @@ protected:
|
||||||
extern mtgsThreadObject* mtgsThread;
|
extern mtgsThreadObject* mtgsThread;
|
||||||
|
|
||||||
void mtgsWaitGS();
|
void mtgsWaitGS();
|
||||||
bool mtgsOpen();
|
void mtgsOpen();
|
||||||
//void mtgsRingBufSimplePacket( s32 command, u32 data0, u32 data1, u32 data2 );
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Generalized GS Functions and Stuff
|
// Generalized GS Functions and Stuff
|
||||||
|
|
|
@ -74,8 +74,6 @@ static void execI()
|
||||||
opcode.interpret();
|
opcode.interpret();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EventRaised = false;
|
|
||||||
|
|
||||||
static __forceinline void _doBranch_shared(u32 tar)
|
static __forceinline void _doBranch_shared(u32 tar)
|
||||||
{
|
{
|
||||||
branch2 = cpuRegs.branch = 1;
|
branch2 = cpuRegs.branch = 1;
|
||||||
|
@ -96,7 +94,7 @@ static void __fastcall doBranch( u32 target )
|
||||||
_doBranch_shared( target );
|
_doBranch_shared( target );
|
||||||
cpuRegs.cycle += cpuBlockCycles >> 3;
|
cpuRegs.cycle += cpuBlockCycles >> 3;
|
||||||
cpuBlockCycles &= (1<<3)-1;
|
cpuBlockCycles &= (1<<3)-1;
|
||||||
EventRaised |= intEventTest();
|
intEventTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __fastcall intDoBranch(u32 target)
|
void __fastcall intDoBranch(u32 target)
|
||||||
|
@ -108,7 +106,7 @@ void __fastcall intDoBranch(u32 target)
|
||||||
{
|
{
|
||||||
cpuRegs.cycle += cpuBlockCycles >> 3;
|
cpuRegs.cycle += cpuBlockCycles >> 3;
|
||||||
cpuBlockCycles &= (1<<3)-1;
|
cpuBlockCycles &= (1<<3)-1;
|
||||||
EventRaised |= intEventTest();
|
intEventTest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,10 +369,10 @@ void intReset()
|
||||||
branch2 = 0;
|
branch2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intEventTest()
|
void intEventTest()
|
||||||
{
|
{
|
||||||
// Perform counters, ints, and IOP updates:
|
// Perform counters, ints, and IOP updates:
|
||||||
return _cpuBranchTest_Shared();
|
_cpuBranchTest_Shared();
|
||||||
}
|
}
|
||||||
|
|
||||||
void intExecute()
|
void intExecute()
|
||||||
|
@ -384,22 +382,12 @@ void intExecute()
|
||||||
// Mem protection should be handled by the caller here so that it can be
|
// Mem protection should be handled by the caller here so that it can be
|
||||||
// done in a more optimized fashion.
|
// done in a more optimized fashion.
|
||||||
|
|
||||||
EventRaised = false;
|
while( true )
|
||||||
|
|
||||||
while( !EventRaised )
|
|
||||||
{
|
{
|
||||||
execI();
|
execI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intExecuteBlock()
|
|
||||||
{
|
|
||||||
g_EEFreezeRegs = false;
|
|
||||||
|
|
||||||
branch2 = 0;
|
|
||||||
while (!branch2) execI();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void intStep()
|
static void intStep()
|
||||||
{
|
{
|
||||||
g_EEFreezeRegs = false;
|
g_EEFreezeRegs = false;
|
||||||
|
@ -418,7 +406,6 @@ R5900cpu intCpu = {
|
||||||
intReset,
|
intReset,
|
||||||
intStep,
|
intStep,
|
||||||
intExecute,
|
intExecute,
|
||||||
intExecuteBlock,
|
|
||||||
intClear,
|
intClear,
|
||||||
intShutdown
|
intShutdown
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include <wx/datetime.h>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "VU.h"
|
#include "VU.h"
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
|
@ -181,7 +182,7 @@ mtgsThreadObject::mtgsThreadObject() :
|
||||||
, m_RingPos( 0 )
|
, m_RingPos( 0 )
|
||||||
, m_WritePos( 0 )
|
, m_WritePos( 0 )
|
||||||
|
|
||||||
, m_post_InitDone()
|
, m_sem_InitDone()
|
||||||
, m_lock_RingRestart()
|
, m_lock_RingRestart()
|
||||||
, m_PacketLocker( true ) // true - makes it a recursive lock
|
, m_PacketLocker( true ) // true - makes it a recursive lock
|
||||||
|
|
||||||
|
@ -204,16 +205,16 @@ mtgsThreadObject::mtgsThreadObject() :
|
||||||
|
|
||||||
void mtgsThreadObject::Start()
|
void mtgsThreadObject::Start()
|
||||||
{
|
{
|
||||||
m_post_InitDone.Reset();
|
m_sem_InitDone.Reset();
|
||||||
PersistentThread::Start();
|
PersistentThread::Start();
|
||||||
|
|
||||||
// Wait for the thread to finish initialization (it runs GSopen, which can take
|
// Wait for the thread to finish initialization (it runs GSopen, which can take
|
||||||
// some time since it's creating a new window and all), and then check for errors.
|
// some time since it's creating a new window and all), and then check for errors.
|
||||||
|
|
||||||
m_post_InitDone.Wait();
|
m_sem_InitDone.Wait();
|
||||||
|
|
||||||
if( m_returncode != 0 ) // means the thread failed to init the GS plugin
|
if( m_returncode != 0 ) // means the thread failed to init the GS plugin
|
||||||
throw Exception::PluginFailure( "GS", wxLt("%s plugin initialization failed.") ); // plugin returned an error after having been asked very nicely to initialize itself." );
|
throw Exception::PluginFailure( "GS", wxLt("%s plugin failed to open.") );
|
||||||
}
|
}
|
||||||
|
|
||||||
mtgsThreadObject::~mtgsThreadObject()
|
mtgsThreadObject::~mtgsThreadObject()
|
||||||
|
@ -226,7 +227,9 @@ void mtgsThreadObject::Cancel()
|
||||||
Console::WriteLn( "MTGS > Closing GS thread..." );
|
Console::WriteLn( "MTGS > Closing GS thread..." );
|
||||||
SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 );
|
SendSimplePacket( GS_RINGTYPE_QUIT, 0, 0, 0 );
|
||||||
SetEvent();
|
SetEvent();
|
||||||
pthread_join( m_thread, NULL );
|
m_sem_Quitter.Wait( wxTimeSpan( 0, 0, 5, 0 ) );
|
||||||
|
Sleep( 2 );
|
||||||
|
PersistentThread::Cancel( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtgsThreadObject::Reset()
|
void mtgsThreadObject::Reset()
|
||||||
|
@ -495,11 +498,7 @@ struct PacketTagType
|
||||||
u32 command;
|
u32 command;
|
||||||
u32 data[3];
|
u32 data[3];
|
||||||
};
|
};
|
||||||
// Until such time as there is a Gsdx port for Linux, or a Linux plugin needs the functionality,
|
|
||||||
// lets only declare this for Windows.
|
|
||||||
#ifndef __LINUX__
|
|
||||||
extern bool renderswitch;
|
|
||||||
#endif
|
|
||||||
sptr mtgsThreadObject::ExecuteTask()
|
sptr mtgsThreadObject::ExecuteTask()
|
||||||
{
|
{
|
||||||
Console::WriteLn("MTGS > Thread Started, Opening GS Plugin...");
|
Console::WriteLn("MTGS > Thread Started, Opening GS Plugin...");
|
||||||
|
@ -507,19 +506,13 @@ sptr mtgsThreadObject::ExecuteTask()
|
||||||
memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(PS2MEM_GS) );
|
memcpy_aligned( m_gsMem, PS2MEM_GS, sizeof(PS2MEM_GS) );
|
||||||
GSsetBaseMem( m_gsMem );
|
GSsetBaseMem( m_gsMem );
|
||||||
GSirqCallback( NULL );
|
GSirqCallback( NULL );
|
||||||
|
|
||||||
#ifdef __LINUX__
|
g_plugins->Open( PluginId_GS );
|
||||||
m_returncode = GSopen((void *)&pDsp, "PCSX2", 1);
|
|
||||||
#else
|
|
||||||
//tells GSdx to go into dx9 sw if "renderswitch" is set. Abusing the isMultiThread int
|
|
||||||
//for that so we don't need a new callback
|
|
||||||
m_returncode = GSopen((void *)&pDsp, "PCSX2", renderswitch ? 2 : 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Console::WriteLn( "MTGS > GSopen Finished, return code: 0x%x", params m_returncode );
|
Console::WriteLn( "MTGS > GSopen Finished, return code: 0x%x", params m_returncode );
|
||||||
|
|
||||||
GSCSRr = 0x551B4000; // 0x55190000
|
GSCSRr = 0x551B4000; // 0x55190000
|
||||||
m_post_InitDone.Post();
|
m_sem_InitDone.Post();
|
||||||
if (m_returncode != 0) { return m_returncode; } // error msg will be issued to the user by Plugins.c
|
if (m_returncode != 0) { return m_returncode; } // error msg will be issued to the user by Plugins.c
|
||||||
|
|
||||||
#ifdef RINGBUF_DEBUG_STACK
|
#ifdef RINGBUF_DEBUG_STACK
|
||||||
|
@ -528,7 +521,7 @@ sptr mtgsThreadObject::ExecuteTask()
|
||||||
|
|
||||||
while( true )
|
while( true )
|
||||||
{
|
{
|
||||||
m_post_event.Wait();
|
m_sem_event.Wait();
|
||||||
|
|
||||||
AtomicExchange( m_RingBufferIsBusy, 1 );
|
AtomicExchange( m_RingBufferIsBusy, 1 );
|
||||||
|
|
||||||
|
@ -675,6 +668,7 @@ sptr mtgsThreadObject::ExecuteTask()
|
||||||
|
|
||||||
case GS_RINGTYPE_QUIT:
|
case GS_RINGTYPE_QUIT:
|
||||||
g_plugins->Close( PluginId_GS );
|
g_plugins->Close( PluginId_GS );
|
||||||
|
m_sem_Quitter.Post();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
@ -715,7 +709,7 @@ void mtgsThreadObject::WaitGS()
|
||||||
// For use in loops that wait on the GS thread to do certain things.
|
// For use in loops that wait on the GS thread to do certain things.
|
||||||
void mtgsThreadObject::SetEvent()
|
void mtgsThreadObject::SetEvent()
|
||||||
{
|
{
|
||||||
m_post_event.Post();
|
m_sem_event.Post();
|
||||||
m_CopyCommandTally = 0;
|
m_CopyCommandTally = 0;
|
||||||
m_CopyDataTally = 0;
|
m_CopyDataTally = 0;
|
||||||
}
|
}
|
||||||
|
@ -1087,23 +1081,30 @@ void mtgsWaitGS()
|
||||||
mtgsThread->WaitGS();
|
mtgsThread->WaitGS();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mtgsOpen()
|
// Exceptions:
|
||||||
|
// ThreadCreationError - Thready could not be created (indicates OS resource limitations)
|
||||||
|
// PluginFailure - GS plugin's "GSopen" call failed.
|
||||||
|
//
|
||||||
|
void mtgsOpen()
|
||||||
{
|
{
|
||||||
// better not be a thread already running, yo!
|
// better not be a thread already running, yo!
|
||||||
assert( mtgsThread == NULL );
|
assert( mtgsThread == NULL );
|
||||||
|
if( mtgsThread != NULL ) return;
|
||||||
|
|
||||||
|
mtgsThread = new mtgsThreadObject();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mtgsThread = new mtgsThreadObject();
|
|
||||||
mtgsThread->Start();
|
mtgsThread->Start();
|
||||||
}
|
}
|
||||||
catch( Exception::ThreadCreationError& )
|
catch( ... )
|
||||||
{
|
{
|
||||||
Console::Error( "MTGS > Thread creation failed!" );
|
// if the thread start fails for any reason then set the handle to null.
|
||||||
mtgsThread = NULL;
|
// The handle is used as a NULL test of thread running status, which is why
|
||||||
return false;
|
// we really need to do this. :)
|
||||||
|
safe_delete( mtgsThread );
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,14 @@ void MemoryCard::Load( uint mcd )
|
||||||
{
|
{
|
||||||
// Translation note: detailed description should mention that the memory card will be disabled
|
// Translation note: detailed description should mention that the memory card will be disabled
|
||||||
// for the duration of this session.
|
// for the duration of this session.
|
||||||
Msgbox::Alert( wxsFormat( _("Could not load MemoryCard from file: %s"), str.c_str() ) );
|
Msgbox::Alert( pxE( ".Popup:MemoryCard:FailedtoOpen",
|
||||||
|
wxsFormat(
|
||||||
|
L"Could not load or create a MemoryCard from the file:\n\n%s\n\n"
|
||||||
|
L"The MemoryCard in slot %d has been automatically disabled. You can correct the problem\n"
|
||||||
|
L"and re-enable the MemoryCard at any time using Config:MemoryCards from the main menu.",
|
||||||
|
str.c_str(), mcd
|
||||||
|
) )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +113,7 @@ void MemoryCard::Read( uint mcd, u8 *data, u32 adr, int size )
|
||||||
|
|
||||||
if( !mcfp.IsOpened() )
|
if( !mcfp.IsOpened() )
|
||||||
{
|
{
|
||||||
DevCon::Error( "MemoryCard > Ignoring attempted read from disabled card." );
|
DevCon::Error( "MemoryCard: Ignoring attempted read from disabled card." );
|
||||||
memset(data, 0, size);
|
memset(data, 0, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +128,7 @@ void MemoryCard::Save( uint mcd, const u8 *data, u32 adr, int size )
|
||||||
|
|
||||||
if( !mcfp.IsOpened() )
|
if( !mcfp.IsOpened() )
|
||||||
{
|
{
|
||||||
DevCon::Error( "MemoryCard > Ignoring attempted save/write to disabled card." );
|
DevCon::Error( "MemoryCard: Ignoring attempted save/write to disabled card." );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,12 +159,12 @@ void MemoryCard::Erase( uint mcd, u32 adr )
|
||||||
|
|
||||||
if( !mcfp.IsOpened() )
|
if( !mcfp.IsOpened() )
|
||||||
{
|
{
|
||||||
DevCon::Error( "MemoryCard > Ignoring seek for disabled card." );
|
DevCon::Error( "MemoryCard: Ignoring seek for disabled card." );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Seek(mcfp, adr);
|
Seek(mcfp, adr);
|
||||||
mcfp.Write( data, 528*16 );
|
mcfp.Write( data, sizeof(data) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,12 +179,7 @@ void MemoryCard::Create( const wxString& mcdFile )
|
||||||
memset8_obj<0xff>( effeffs );
|
memset8_obj<0xff>( effeffs );
|
||||||
|
|
||||||
for( uint i=0; i<16384; i++ )
|
for( uint i=0; i<16384; i++ )
|
||||||
{
|
fp.Write( effeffs, sizeof(effeffs) );
|
||||||
for( uint j=0; j<528; j++ )
|
|
||||||
fp.Write( effeffs, sizeof(effeffs) );
|
|
||||||
|
|
||||||
//for(j=0; j<16; j++) fputc(enc[j],fp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 MemoryCard::GetCRC( uint mcd )
|
u64 MemoryCard::GetCRC( uint mcd )
|
||||||
|
|
|
@ -48,7 +48,9 @@ using namespace std;
|
||||||
using namespace R5900;
|
using namespace R5900;
|
||||||
|
|
||||||
static int g_Pcsx2Recording = 0; // true 1 if recording video and sound
|
static int g_Pcsx2Recording = 0; // true 1 if recording video and sound
|
||||||
bool renderswitch = 0;
|
|
||||||
|
// renderswitch - tells GSdx to go into dx9 sw if "renderswitch" is set.
|
||||||
|
bool renderswitch = false;
|
||||||
|
|
||||||
struct KeyModifiers keymodifiers = {false, false, false, false};
|
struct KeyModifiers keymodifiers = {false, false, false, false};
|
||||||
|
|
||||||
|
@ -330,7 +332,11 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod)
|
||||||
case 9: //gsdx "on the fly" renderer switching
|
case 9: //gsdx "on the fly" renderer switching
|
||||||
StateRecovery::MakeGsOnly();
|
StateRecovery::MakeGsOnly();
|
||||||
g_EmulationInProgress = false;
|
g_EmulationInProgress = false;
|
||||||
CloseGS();
|
|
||||||
|
// close GS and PAD together, because the PAD depends on the GS window.
|
||||||
|
g_plugins->Close( PluginId_PAD );
|
||||||
|
safe_delete( mtgsThread );
|
||||||
|
|
||||||
renderswitch = !renderswitch;
|
renderswitch = !renderswitch;
|
||||||
StateRecovery::Recover();
|
StateRecovery::Recover();
|
||||||
HostGui::BeginExecution(); // also sets g_EmulationInProgress to true later
|
HostGui::BeginExecution(); // also sets g_EmulationInProgress to true later
|
||||||
|
|
1000
pcsx2/Plugins.cpp
1000
pcsx2/Plugins.cpp
File diff suppressed because it is too large
Load Diff
|
@ -16,8 +16,7 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __PLUGINS_H__
|
#pragma once
|
||||||
#define __PLUGINS_H__
|
|
||||||
|
|
||||||
#define PLUGINtypedefs
|
#define PLUGINtypedefs
|
||||||
#define PLUGINfuncs
|
#define PLUGINfuncs
|
||||||
|
@ -31,6 +30,11 @@ struct PluginInfo
|
||||||
PluginsEnum_t id;
|
PluginsEnum_t id;
|
||||||
int typemask;
|
int typemask;
|
||||||
int version; // minimum version required / supported
|
int version; // minimum version required / supported
|
||||||
|
|
||||||
|
wxString GetShortname() const
|
||||||
|
{
|
||||||
|
return wxString::FromUTF8( shortname );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
|
@ -60,6 +64,17 @@ struct LegacyPluginAPI_Common
|
||||||
s32 (CALLBACK* Test)();
|
s32 (CALLBACK* Test)();
|
||||||
void (CALLBACK* Configure)();
|
void (CALLBACK* Configure)();
|
||||||
void (CALLBACK* About)();
|
void (CALLBACK* About)();
|
||||||
|
|
||||||
|
LegacyPluginAPI_Common() :
|
||||||
|
Init ( NULL )
|
||||||
|
, Close ( NULL )
|
||||||
|
, Shutdown( NULL )
|
||||||
|
, Freeze ( NULL )
|
||||||
|
, Test ( NULL )
|
||||||
|
, Configure( NULL )
|
||||||
|
, About ( NULL )
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SaveState;
|
class SaveState;
|
||||||
|
@ -68,39 +83,52 @@ class SaveState;
|
||||||
//
|
//
|
||||||
class PluginManager
|
class PluginManager
|
||||||
{
|
{
|
||||||
|
DeclareNoncopyableObject( PluginManager )
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
struct PluginStatus_t
|
||||||
|
{
|
||||||
|
bool IsInitialized;
|
||||||
|
bool IsOpened;
|
||||||
|
wxString Filename;
|
||||||
|
|
||||||
|
LegacyPluginAPI_Common CommonBindings;
|
||||||
|
wxDynamicLibrary Lib;
|
||||||
|
|
||||||
|
PluginStatus_t() :
|
||||||
|
IsInitialized( false )
|
||||||
|
, IsOpened( false )
|
||||||
|
, Filename()
|
||||||
|
, CommonBindings()
|
||||||
|
, Lib()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
bool m_loaded;
|
|
||||||
|
|
||||||
bool m_IsInitialized[PluginId_Count];
|
PluginStatus_t m_info[PluginId_Count];
|
||||||
bool m_IsOpened[PluginId_Count];
|
|
||||||
|
|
||||||
LegacyPluginAPI_Common m_CommonBindings[PluginId_Count];
|
|
||||||
wxDynamicLibrary m_libs[PluginId_Count];
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~PluginManager();
|
~PluginManager();
|
||||||
PluginManager() :
|
|
||||||
m_initialized( false )
|
|
||||||
, m_loaded( false )
|
|
||||||
{
|
|
||||||
memzero_obj( m_IsInitialized );
|
|
||||||
memzero_obj( m_IsOpened );
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadPlugins();
|
void Init();
|
||||||
void UnloadPlugins();
|
void Shutdown();
|
||||||
|
|
||||||
void Init( PluginsEnum_t pid );
|
|
||||||
void Shutdown( PluginsEnum_t pid );
|
|
||||||
void Open( PluginsEnum_t pid );
|
void Open( PluginsEnum_t pid );
|
||||||
void Close( PluginsEnum_t pid );
|
void Close( PluginsEnum_t pid );
|
||||||
|
void Close();
|
||||||
|
|
||||||
void Freeze( PluginsEnum_t pid, int mode, freezeData* data );
|
void Freeze( PluginsEnum_t pid, int mode, freezeData* data );
|
||||||
void Freeze( PluginsEnum_t pid, SaveState& state );
|
void Freeze( PluginsEnum_t pid, SaveState& state );
|
||||||
void Freeze( SaveState& state );
|
void Freeze( SaveState& state );
|
||||||
|
|
||||||
|
friend PluginManager* PluginManager_Create( const wxString (&folders)[PluginId_Count] );
|
||||||
|
friend PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Internal constructor, should be called by Create only.
|
||||||
|
PluginManager( const wxString (&folders)[PluginId_Count] );
|
||||||
|
|
||||||
void BindCommon( PluginsEnum_t pid );
|
void BindCommon( PluginsEnum_t pid );
|
||||||
void BindRequired( PluginsEnum_t pid );
|
void BindRequired( PluginsEnum_t pid );
|
||||||
void BindOptional( PluginsEnum_t pid );
|
void BindOptional( PluginsEnum_t pid );
|
||||||
|
@ -112,16 +140,12 @@ extern PluginManager* g_plugins;
|
||||||
extern int EnumeratePluginsInFolder( const wxDirName& searchPath, wxArrayString* dest );
|
extern int EnumeratePluginsInFolder( const wxDirName& searchPath, wxArrayString* dest );
|
||||||
|
|
||||||
|
|
||||||
void LoadPlugins();
|
extern void LoadPlugins();
|
||||||
void ReleasePlugins();
|
extern void ReleasePlugins();
|
||||||
|
|
||||||
void OpenPlugins();
|
extern void InitPlugins();
|
||||||
void ClosePlugins( bool closegs );
|
extern void ShutdownPlugins();
|
||||||
void CloseGS();
|
|
||||||
|
|
||||||
void InitPlugins();
|
extern void OpenPlugins();
|
||||||
void ShutdownPlugins();
|
extern void ClosePlugins( bool closegs );
|
||||||
|
|
||||||
void PluginsResetGS();
|
|
||||||
|
|
||||||
#endif /* __PLUGINS_H__ */
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ u32 g_nextBranchCycle = 0;
|
||||||
|
|
||||||
// Shared portion of the branch test, called from both the Interpreter
|
// Shared portion of the branch test, called from both the Interpreter
|
||||||
// and the recompiler. (moved here to help alleviate redundant code)
|
// and the recompiler. (moved here to help alleviate redundant code)
|
||||||
__forceinline bool _cpuBranchTest_Shared()
|
__forceinline void _cpuBranchTest_Shared()
|
||||||
{
|
{
|
||||||
eeEventTestIsActive = true;
|
eeEventTestIsActive = true;
|
||||||
g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;
|
g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;
|
||||||
|
@ -373,12 +373,11 @@ __forceinline bool _cpuBranchTest_Shared()
|
||||||
iopBranchAction = true;
|
iopBranchAction = true;
|
||||||
|
|
||||||
// ---- Counters -------------
|
// ---- Counters -------------
|
||||||
bool vsyncEvent = false;
|
|
||||||
rcntUpdate_hScanline();
|
rcntUpdate_hScanline();
|
||||||
|
|
||||||
if( cpuTestCycle( nextsCounter, nextCounter ) )
|
if( cpuTestCycle( nextsCounter, nextCounter ) )
|
||||||
{
|
{
|
||||||
vsyncEvent = rcntUpdate();
|
rcntUpdate();
|
||||||
_cpuTestPERF();
|
_cpuTestPERF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,8 +489,6 @@ __forceinline bool _cpuBranchTest_Shared()
|
||||||
TESTINT(30, intcInterrupt);
|
TESTINT(30, intcInterrupt);
|
||||||
TESTINT(31, dmacInterrupt);
|
TESTINT(31, dmacInterrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vsyncEvent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__releaseinline void cpuTestINTCInts()
|
__releaseinline void cpuTestINTCInts()
|
||||||
|
@ -572,8 +569,7 @@ void cpuExecuteBios()
|
||||||
while( cpuRegs.pc != 0x00200008 &&
|
while( cpuRegs.pc != 0x00200008 &&
|
||||||
cpuRegs.pc != 0x00100008 )
|
cpuRegs.pc != 0x00100008 )
|
||||||
{
|
{
|
||||||
g_nextBranchCycle = cpuRegs.cycle;
|
Cpu->Execute();
|
||||||
Cpu->ExecuteBlock();
|
|
||||||
}
|
}
|
||||||
g_ExecBiosHack = false;
|
g_ExecBiosHack = false;
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,7 @@ extern bool eeEventTestIsActive;
|
||||||
extern u32 s_iLastCOP0Cycle;
|
extern u32 s_iLastCOP0Cycle;
|
||||||
extern u32 s_iLastPERFCycle[2];
|
extern u32 s_iLastPERFCycle[2];
|
||||||
|
|
||||||
bool intEventTest();
|
void intEventTest();
|
||||||
void intSetBranch();
|
void intSetBranch();
|
||||||
|
|
||||||
// This is a special form of the interpreter's doBranch that is run from various
|
// This is a special form of the interpreter's doBranch that is run from various
|
||||||
|
@ -243,8 +243,7 @@ struct R5900cpu
|
||||||
void (*Allocate)(); // throws exceptions on failure.
|
void (*Allocate)(); // throws exceptions on failure.
|
||||||
void (*Reset)();
|
void (*Reset)();
|
||||||
void (*Step)();
|
void (*Step)();
|
||||||
void (*Execute)(); /* executes up to a break */
|
void (*Execute)();
|
||||||
void (*ExecuteBlock)();
|
|
||||||
void (*Clear)(u32 Addr, u32 Size);
|
void (*Clear)(u32 Addr, u32 Size);
|
||||||
void (*Shutdown)(); // deallocates memory reserved by Allocate
|
void (*Shutdown)(); // deallocates memory reserved by Allocate
|
||||||
};
|
};
|
||||||
|
@ -267,7 +266,7 @@ extern void cpuSetNextBranchDelta( s32 delta );
|
||||||
extern int cpuTestCycle( u32 startCycle, s32 delta );
|
extern int cpuTestCycle( u32 startCycle, s32 delta );
|
||||||
extern void cpuSetBranch();
|
extern void cpuSetBranch();
|
||||||
|
|
||||||
extern bool _cpuBranchTest_Shared(); // for internal use by the Dynarecs and Ints inside R5900:
|
extern void _cpuBranchTest_Shared(); // for internal use by the Dynarecs and Ints inside R5900:
|
||||||
|
|
||||||
extern void cpuTestINTCInts();
|
extern void cpuTestINTCInts();
|
||||||
extern void cpuTestDMACInts();
|
extern void cpuTestDMACInts();
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "IniInterface.h"
|
#include "IniInterface.h"
|
||||||
|
#include "Plugins.h"
|
||||||
|
|
||||||
#include <wx/stdpaths.h>
|
#include <wx/stdpaths.h>
|
||||||
|
|
||||||
|
@ -266,7 +267,7 @@ namespace FilenameDefs
|
||||||
wxFileName( L"Mcd002.ps2" )
|
wxFileName( L"Mcd002.ps2" )
|
||||||
};
|
};
|
||||||
|
|
||||||
if( IsDevBuild && ((uint)slot) < 2 )
|
if( IsDevBuild && ((uint)slot) >= 2 )
|
||||||
throw Exception::IndexBoundsFault( L"FilenameDefs::Memcard", slot, 2 );
|
throw Exception::IndexBoundsFault( L"FilenameDefs::Memcard", slot, 2 );
|
||||||
|
|
||||||
return retval[slot];
|
return retval[slot];
|
||||||
|
@ -373,6 +374,10 @@ AppConfig::AppConfig() :
|
||||||
, EmuOptions()
|
, EmuOptions()
|
||||||
, m_IsLoaded( false )
|
, m_IsLoaded( false )
|
||||||
{
|
{
|
||||||
|
Mcd[0].Enabled = true;
|
||||||
|
Mcd[1].Enabled = true;
|
||||||
|
Mcd[0].Filename = FilenameDefs::Memcard(0);
|
||||||
|
Mcd[1].Filename = FilenameDefs::Memcard(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -395,6 +400,17 @@ void AppConfig::LoadSaveUserMode( IniInterface& ini, const wxString& cwdhash )
|
||||||
ini.Flush();
|
ini.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void AppConfig::LoadSaveMemcards( IniInterface& ini )
|
||||||
|
{
|
||||||
|
IniScopedGroup path( ini, L"MemoryCards" );
|
||||||
|
|
||||||
|
ini.Entry( L"Slot1Enable", Mcd[0].Enabled, true );
|
||||||
|
ini.Entry( L"Slot2Enable", Mcd[1].Enabled, true );
|
||||||
|
ini.Entry( L"Slot1Filename", Mcd[0].Filename, FilenameDefs::Memcard(0) );
|
||||||
|
ini.Entry( L"Slot2Filename", Mcd[1].Filename, FilenameDefs::Memcard(1) );
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void AppConfig::LoadSave( IniInterface& ini )
|
void AppConfig::LoadSave( IniInterface& ini )
|
||||||
{
|
{
|
||||||
|
@ -584,22 +600,9 @@ void AppConfig::FilenameOptions::LoadSave( IniInterface& ini )
|
||||||
IniScopedGroup path( ini, L"Filenames" );
|
IniScopedGroup path( ini, L"Filenames" );
|
||||||
|
|
||||||
static const wxFileName pc( L"Please Configure" );
|
static const wxFileName pc( L"Please Configure" );
|
||||||
static const wxString g_PluginNames[] =
|
|
||||||
{
|
|
||||||
L"CDVD",
|
|
||||||
L"GS",
|
|
||||||
L"PAD1",
|
|
||||||
L"PAD2",
|
|
||||||
L"SPU2",
|
|
||||||
L"USB",
|
|
||||||
L"FW",
|
|
||||||
L"DEV9"
|
|
||||||
};
|
|
||||||
|
|
||||||
for( int i=0; i<PluginId_Count; ++i )
|
for( int i=0; i<PluginId_Count; ++i )
|
||||||
{
|
ini.Entry( tbl_PluginInfo[i].GetShortname(), Plugins[i], pc );
|
||||||
ini.Entry( g_PluginNames[i], Plugins[i], pc );
|
|
||||||
}
|
|
||||||
|
|
||||||
ini.Entry( L"BIOS", Bios, pc );
|
ini.Entry( L"BIOS", Bios, pc );
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void LoadSave( IniInterface& ini );
|
void LoadSave( IniInterface& ini );
|
||||||
|
void LoadSaveMemcards( IniInterface& ini );
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxFileConfig; // forward declare.
|
class wxFileConfig; // forward declare.
|
||||||
|
|
|
@ -451,6 +451,7 @@ namespace Panels
|
||||||
void Apply( AppConfig& conf );
|
void Apply( AppConfig& conf );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void OnConfigure_Clicked( wxCommandEvent& evt );
|
||||||
virtual void OnProgress( wxCommandEvent& evt );
|
virtual void OnProgress( wxCommandEvent& evt );
|
||||||
virtual void OnEnumComplete( wxCommandEvent& evt );
|
virtual void OnEnumComplete( wxCommandEvent& evt );
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ END_DECLARE_EVENT_TYPES()
|
||||||
DEFINE_EVENT_TYPE(wxEVT_EnumeratedNext)
|
DEFINE_EVENT_TYPE(wxEVT_EnumeratedNext)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_EnumerationFinished);
|
DEFINE_EVENT_TYPE(wxEVT_EnumerationFinished);
|
||||||
|
|
||||||
typedef s32 (CALLBACK* PluginTestFnptr)();
|
typedef s32 (CALLBACK* PluginTestFnptr)();
|
||||||
|
typedef void (CALLBACK* PluginConfigureFnptr)();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -154,6 +155,9 @@ void Panels::PluginSelectorPanel::StatusPanel::Reset()
|
||||||
m_label.SetLabel( wxEmptyString );
|
m_label.SetLabel( wxEmptyString );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Id for all Configure buttons (any non-negative arbitrary integer will do)
|
||||||
|
static const int ButtonId_Configure = 51;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
Panels::PluginSelectorPanel::ComboBoxPanel::ComboBoxPanel( PluginSelectorPanel* parent ) :
|
Panels::PluginSelectorPanel::ComboBoxPanel::ComboBoxPanel( PluginSelectorPanel* parent ) :
|
||||||
wxPanelWithHelpers( parent )
|
wxPanelWithHelpers( parent )
|
||||||
|
@ -170,14 +174,16 @@ Panels::PluginSelectorPanel::ComboBoxPanel::ComboBoxPanel( PluginSelectorPanel*
|
||||||
for( int i=0; i<NumPluginTypes; ++i )
|
for( int i=0; i<NumPluginTypes; ++i )
|
||||||
{
|
{
|
||||||
s_plugin.Add(
|
s_plugin.Add(
|
||||||
new wxStaticText( this, wxID_ANY, wxString::FromAscii( tbl_PluginInfo[i].shortname ) ),
|
new wxStaticText( this, wxID_ANY, tbl_PluginInfo[i].GetShortname() ),
|
||||||
wxSizerFlags().Border( wxTOP | wxLEFT, 2 )
|
wxSizerFlags().Border( wxTOP | wxLEFT, 2 )
|
||||||
);
|
);
|
||||||
s_plugin.Add(
|
s_plugin.Add(
|
||||||
m_combobox[i] = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY ),
|
m_combobox[i] = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY ),
|
||||||
wxSizerFlags().Expand()
|
wxSizerFlags().Expand()
|
||||||
);
|
);
|
||||||
s_plugin.Add( new wxButton( this, wxID_ANY, L"Configure..." ) );
|
wxButton* bleh = new wxButton( this, ButtonId_Configure, L"Configure..." );
|
||||||
|
bleh->SetClientData( (void*)(int)tbl_PluginInfo[i].id );
|
||||||
|
s_plugin.Add( bleh );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_FolderPicker.SetStaticDesc( _("Click the Browse button to select a different folder for PCSX2 plugins.") );
|
m_FolderPicker.SetStaticDesc( _("Click the Browse button to select a different folder for PCSX2 plugins.") );
|
||||||
|
@ -225,6 +231,7 @@ Panels::PluginSelectorPanel::PluginSelectorPanel( wxWindow& parent, int idealWid
|
||||||
|
|
||||||
Connect( wxEVT_EnumeratedNext, wxCommandEventHandler( PluginSelectorPanel::OnProgress ) );
|
Connect( wxEVT_EnumeratedNext, wxCommandEventHandler( PluginSelectorPanel::OnProgress ) );
|
||||||
Connect( wxEVT_EnumerationFinished, wxCommandEventHandler( PluginSelectorPanel::OnEnumComplete ) );
|
Connect( wxEVT_EnumerationFinished, wxCommandEventHandler( PluginSelectorPanel::OnEnumComplete ) );
|
||||||
|
Connect( ButtonId_Configure, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PluginSelectorPanel::OnConfigure_Clicked ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
Panels::PluginSelectorPanel::~PluginSelectorPanel()
|
Panels::PluginSelectorPanel::~PluginSelectorPanel()
|
||||||
|
@ -239,7 +246,7 @@ void Panels::PluginSelectorPanel::Apply( AppConfig& conf )
|
||||||
int sel = m_ComponentBoxes.Get(i).GetSelection();
|
int sel = m_ComponentBoxes.Get(i).GetSelection();
|
||||||
if( sel == wxNOT_FOUND )
|
if( sel == wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
wxString plugname( wxString::FromAscii( tbl_PluginInfo[i].shortname ) );
|
wxString plugname( tbl_PluginInfo[i].GetShortname() );
|
||||||
|
|
||||||
throw Exception::CannotApplySettings( this,
|
throw Exception::CannotApplySettings( this,
|
||||||
// English Log
|
// English Log
|
||||||
|
@ -307,6 +314,17 @@ bool Panels::PluginSelectorPanel::ValidateEnumerationStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
void Panels::PluginSelectorPanel::OnConfigure_Clicked( wxCommandEvent& evt )
|
||||||
|
{
|
||||||
|
PluginsEnum_t pid = (PluginsEnum_t)(int)evt.GetClientData();
|
||||||
|
|
||||||
|
int sel = m_ComponentBoxes.Get(pid).GetSelection();
|
||||||
|
if( sel == wxNOT_FOUND ) return;
|
||||||
|
wxDynamicLibrary dynlib( (*m_FileList)[(int)m_ComponentBoxes.Get(pid).GetClientData(sel)] );
|
||||||
|
if( PluginConfigureFnptr configfunc = (PluginConfigureFnptr)dynlib.GetSymbol( tbl_PluginInfo[pid].GetShortname() + L"configure" ) )
|
||||||
|
configfunc();
|
||||||
|
}
|
||||||
|
|
||||||
void Panels::PluginSelectorPanel::OnEnumComplete( wxCommandEvent& evt )
|
void Panels::PluginSelectorPanel::OnEnumComplete( wxCommandEvent& evt )
|
||||||
{
|
{
|
||||||
safe_delete( m_EnumeratorThread );
|
safe_delete( m_EnumeratorThread );
|
||||||
|
|
|
@ -150,6 +150,8 @@ bool Pcsx2App::OnInit()
|
||||||
g_Conf = new AppConfig();
|
g_Conf = new AppConfig();
|
||||||
g_EmuThread = new CoreEmuThread();
|
g_EmuThread = new CoreEmuThread();
|
||||||
|
|
||||||
|
delete wxMessageOutput::Set( new wxMessageOutputDebug() );
|
||||||
|
|
||||||
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
||||||
|
|
||||||
// User/Admin Mode Dual Setup:
|
// User/Admin Mode Dual Setup:
|
||||||
|
|
|
@ -27,18 +27,23 @@
|
||||||
#include "R3000A.h"
|
#include "R3000A.h"
|
||||||
#include "VUmicro.h"
|
#include "VUmicro.h"
|
||||||
|
|
||||||
sptr CoreEmuThread::ExecuteTask()
|
static __threadlocal CoreEmuThread* tls_coreThread = NULL;
|
||||||
{
|
|
||||||
while( !m_Done && (m_ExecMode != ExecMode_Running) )
|
|
||||||
{
|
|
||||||
m_ResumeEvent.Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CoreEmuThread& CoreEmuThread::Get()
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( tls_coreThread != NULL, L"This function must be called from the context of a running CoreEmuThread." );
|
||||||
|
return *tls_coreThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreEmuThread::CpuInitializeMess()
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
OpenPlugins();
|
||||||
cpuReset();
|
cpuReset();
|
||||||
SysClearExecutionCache();
|
SysClearExecutionCache();
|
||||||
OpenPlugins();
|
|
||||||
|
GSsetGameCRC( ElfCRC, 0 );
|
||||||
|
|
||||||
if( StateRecovery::HasState() )
|
if( StateRecovery::HasState() )
|
||||||
{
|
{
|
||||||
|
@ -69,9 +74,25 @@ sptr CoreEmuThread::ExecuteTask()
|
||||||
{
|
{
|
||||||
Msgbox::Alert( ex.DisplayMessage() );
|
Msgbox::Alert( ex.DisplayMessage() );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr CoreEmuThread::ExecuteTask()
|
||||||
|
{
|
||||||
|
tls_coreThread = this;
|
||||||
|
|
||||||
|
while( !m_Done && (m_ExecMode != ExecMode_Running) )
|
||||||
|
{
|
||||||
|
m_ResumeEvent.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
CpuInitializeMess();
|
||||||
|
|
||||||
StateCheck();
|
StateCheck();
|
||||||
|
|
||||||
|
PCSX2_MEM_PROTECT_BEGIN();
|
||||||
|
Cpu->Execute();
|
||||||
|
PCSX2_MEM_PROTECT_END();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,10 @@ protected:
|
||||||
|
|
||||||
MutexLock m_lock_elf_file;
|
MutexLock m_lock_elf_file;
|
||||||
MutexLock m_lock_ExecMode;
|
MutexLock m_lock_ExecMode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CoreEmuThread& Get();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CoreEmuThread() :
|
CoreEmuThread() :
|
||||||
m_ExecMode( ExecMode_Idle )
|
m_ExecMode( ExecMode_Idle )
|
||||||
|
@ -80,7 +83,9 @@ public:
|
||||||
void Resume();
|
void Resume();
|
||||||
void ApplySettings( const Pcsx2Config& src );
|
void ApplySettings( const Pcsx2Config& src );
|
||||||
|
|
||||||
protected:
|
|
||||||
sptr ExecuteTask();
|
|
||||||
void StateCheck();
|
void StateCheck();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void CpuInitializeMess();
|
||||||
|
sptr ExecuteTask();
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,7 +108,7 @@ static u32 dumplog = 0;
|
||||||
#define dumplog 0
|
#define dumplog 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void iBranchTest(u32 newpc = 0xffffffff, bool noDispatch=false);
|
static void iBranchTest(u32 newpc = 0xffffffff);
|
||||||
static void ClearRecLUT(BASEBLOCK* base, int count);
|
static void ClearRecLUT(BASEBLOCK* base, int count);
|
||||||
static u32 eeScaleBlockCycles();
|
static u32 eeScaleBlockCycles();
|
||||||
|
|
||||||
|
@ -538,7 +538,9 @@ static void recShutdown( void )
|
||||||
void recStep( void ) {
|
void recStep( void ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline bool recEventTest()
|
|
||||||
|
|
||||||
|
static void recEventTest()
|
||||||
{
|
{
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
// dont' remove this check unless doing an official release
|
// dont' remove this check unless doing an official release
|
||||||
|
@ -550,13 +552,12 @@ static __forceinline bool recEventTest()
|
||||||
assert( !g_globalXMMSaved && !g_globalMMXSaved);
|
assert( !g_globalXMMSaved && !g_globalMMXSaved);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Perform counters, ints, and IOP updates:
|
// Perform counters, interrupts, and IOP updates:
|
||||||
bool retval = _cpuBranchTest_Shared();
|
_cpuBranchTest_Shared();
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
assert( !g_globalXMMSaved && !g_globalMMXSaved);
|
assert( !g_globalXMMSaved && !g_globalMMXSaved);
|
||||||
#endif
|
#endif
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
@ -568,7 +569,7 @@ u32 g_EEDispatchTemp;
|
||||||
|
|
||||||
// The address for all cleared blocks. It recompiles the current pc and then
|
// The address for all cleared blocks. It recompiles the current pc and then
|
||||||
// dispatches to the recompiled block address.
|
// dispatches to the recompiled block address.
|
||||||
static __declspec(naked) void JITCompile()
|
static __naked void JITCompile()
|
||||||
{
|
{
|
||||||
__asm {
|
__asm {
|
||||||
mov esi, dword ptr [cpuRegs.pc]
|
mov esi, dword ptr [cpuRegs.pc]
|
||||||
|
@ -582,7 +583,7 @@ static __declspec(naked) void JITCompile()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static __declspec(naked) void JITCompileInBlock()
|
static __naked void JITCompileInBlock()
|
||||||
{
|
{
|
||||||
__asm {
|
__asm {
|
||||||
jmp JITCompile
|
jmp JITCompile
|
||||||
|
@ -601,34 +602,23 @@ static void __naked DispatcherReg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [TODO] : Replace these functions with x86Emitter-generated code and we can compound this
|
||||||
|
// function and DispatcherReg() into a fast fall-through case (removes the DispatcerReg jump
|
||||||
|
// in this function, since execution will just fall right into the DispatcherReg implementation).
|
||||||
|
//
|
||||||
|
static void __naked DispatcherEvent()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
call recEventTest;
|
||||||
|
jmp DispatcherReg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void recExecute()
|
void recExecute()
|
||||||
{
|
{
|
||||||
// Optimization note : Compared pushad against manually pushing the regs one-by-one.
|
// Optimization note : Compared pushad against manually pushing the regs one-by-one.
|
||||||
// Manually pushing is faster, especially on Core2's and such. :)
|
// Manually pushing is faster, especially on Core2's and such. :)
|
||||||
do
|
|
||||||
{
|
|
||||||
g_EEFreezeRegs = true;
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push ebx
|
|
||||||
push esi
|
|
||||||
push edi
|
|
||||||
push ebp
|
|
||||||
|
|
||||||
call DispatcherReg
|
|
||||||
|
|
||||||
pop ebp
|
|
||||||
pop edi
|
|
||||||
pop esi
|
|
||||||
pop ebx
|
|
||||||
}
|
|
||||||
g_EEFreezeRegs = false;
|
|
||||||
}
|
|
||||||
while( !recEventTest() );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void recExecuteBlock()
|
|
||||||
{
|
|
||||||
g_EEFreezeRegs = true;
|
g_EEFreezeRegs = true;
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
|
@ -638,14 +628,13 @@ static void recExecuteBlock()
|
||||||
push ebp
|
push ebp
|
||||||
|
|
||||||
call DispatcherReg
|
call DispatcherReg
|
||||||
|
|
||||||
pop ebp
|
pop ebp
|
||||||
pop edi
|
pop edi
|
||||||
pop esi
|
pop esi
|
||||||
pop ebx
|
pop ebx
|
||||||
}
|
}
|
||||||
g_EEFreezeRegs = false;
|
g_EEFreezeRegs = false;
|
||||||
recEventTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // _MSC_VER
|
#else // _MSC_VER
|
||||||
|
@ -654,31 +643,6 @@ __forceinline void recExecute()
|
||||||
{
|
{
|
||||||
// Optimization note : Compared pushad against manually pushing the regs one-by-one.
|
// Optimization note : Compared pushad against manually pushing the regs one-by-one.
|
||||||
// Manually pushing is faster, especially on Core2's and such. :)
|
// Manually pushing is faster, especially on Core2's and such. :)
|
||||||
do {
|
|
||||||
g_EEFreezeRegs = true;
|
|
||||||
__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"
|
|
||||||
);
|
|
||||||
g_EEFreezeRegs = false;
|
|
||||||
}
|
|
||||||
while( !recEventTest() );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void recExecuteBlock()
|
|
||||||
{
|
|
||||||
g_EEFreezeRegs = true;
|
g_EEFreezeRegs = true;
|
||||||
__asm__
|
__asm__
|
||||||
(
|
(
|
||||||
|
@ -689,7 +653,7 @@ static void recExecuteBlock()
|
||||||
"push ebp\n"
|
"push ebp\n"
|
||||||
|
|
||||||
"call DispatcherReg\n"
|
"call DispatcherReg\n"
|
||||||
|
|
||||||
"pop ebp\n"
|
"pop ebp\n"
|
||||||
"pop edi\n"
|
"pop edi\n"
|
||||||
"pop esi\n"
|
"pop esi\n"
|
||||||
|
@ -697,8 +661,8 @@ static void recExecuteBlock()
|
||||||
".att_syntax\n"
|
".att_syntax\n"
|
||||||
);
|
);
|
||||||
g_EEFreezeRegs = false;
|
g_EEFreezeRegs = false;
|
||||||
recEventTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace R5900 {
|
namespace R5900 {
|
||||||
|
@ -1038,10 +1002,10 @@ static u32 eeScaleBlockCycles()
|
||||||
// jump is assumed to be static, in which case the block will be "hardlinked" after
|
// jump is assumed to be static, in which case the block will be "hardlinked" after
|
||||||
// the first time it's dispatched.
|
// the first time it's dispatched.
|
||||||
//
|
//
|
||||||
// noDispatch - When set true, the jump to Dispatcher. Used by the recs
|
// noDispatch - When set true, then jump to Dispatcher. Used by the recs
|
||||||
// for blocks which perform exception checks without branching (it's enabled by
|
// for blocks which perform exception checks without branching (it's enabled by
|
||||||
// setting "branch = 2";
|
// setting "branch = 2";
|
||||||
static void iBranchTest(u32 newpc, bool noDispatch)
|
static void iBranchTest(u32 newpc)
|
||||||
{
|
{
|
||||||
if( g_ExecBiosHack ) CheckForBIOSEnd();
|
if( g_ExecBiosHack ) CheckForBIOSEnd();
|
||||||
|
|
||||||
|
@ -1050,13 +1014,46 @@ static void iBranchTest(u32 newpc, bool noDispatch)
|
||||||
// cpuRegs.cycle += blockcycles;
|
// cpuRegs.cycle += blockcycles;
|
||||||
// if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); }
|
// if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); }
|
||||||
|
|
||||||
if (EmuConfig.Speedhacks.BIFC0 && s_nBlockFF) {
|
if (EmuConfig.Speedhacks.BIFC0 && s_nBlockFF)
|
||||||
|
{
|
||||||
xMOV(eax, ptr32[&g_nextBranchCycle]);
|
xMOV(eax, ptr32[&g_nextBranchCycle]);
|
||||||
xADD(ptr32[&cpuRegs.cycle], eeScaleBlockCycles());
|
xADD(ptr32[&cpuRegs.cycle], eeScaleBlockCycles());
|
||||||
xCMP(eax, ptr32[&cpuRegs.cycle]);
|
xCMP(eax, ptr32[&cpuRegs.cycle]);
|
||||||
xCMOVL(eax, ptr32[&cpuRegs.cycle]);
|
xCMOVL(eax, ptr32[&cpuRegs.cycle]);
|
||||||
xMOV(ptr32[&cpuRegs.cycle], eax);
|
xMOV(ptr32[&cpuRegs.cycle], eax);
|
||||||
} else {
|
|
||||||
|
xJMP( DispatcherEvent );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Optimization -- we need to load cpuRegs.pc on static block links, but doing it inside
|
||||||
|
// the if() block below (it would be paired with recBlocks.Link) breaks the sub/jcc
|
||||||
|
// pairing that modern CPUs optimize (applies to all P4+ and AMD X2+ CPUs). So let's do
|
||||||
|
// it up here instead. :D
|
||||||
|
|
||||||
|
if( newpc != 0xffffffff )
|
||||||
|
xMOV( ptr32[&cpuRegs.pc], newpc );
|
||||||
|
|
||||||
|
xMOV(eax, &cpuRegs.cycle);
|
||||||
|
xADD(eax, eeScaleBlockCycles());
|
||||||
|
xMOV(&cpuRegs.cycle, eax); // update cycles
|
||||||
|
xSUB(eax, &g_nextBranchCycle);
|
||||||
|
|
||||||
|
if (newpc == 0xffffffff)
|
||||||
|
{
|
||||||
|
xJNS( DispatcherEvent );
|
||||||
|
xJMP( DispatcherReg );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recBlocks.Link( HWADDR(newpc), xJcc32( Jcc_Signed ) );
|
||||||
|
xJMP( DispatcherEvent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
{
|
||||||
xMOV(eax, &cpuRegs.cycle);
|
xMOV(eax, &cpuRegs.cycle);
|
||||||
xADD(eax, eeScaleBlockCycles());
|
xADD(eax, eeScaleBlockCycles());
|
||||||
xMOV(&cpuRegs.cycle, eax); // update cycles
|
xMOV(&cpuRegs.cycle, eax); // update cycles
|
||||||
|
@ -1072,7 +1069,10 @@ static void iBranchTest(u32 newpc, bool noDispatch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xRET();
|
xCALL( recEventTest );
|
||||||
|
xJMP( DispatcherReg );
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkcodefn()
|
static void checkcodefn()
|
||||||
|
@ -1622,7 +1622,7 @@ StartRecomp:
|
||||||
// for actual branching instructions.
|
// for actual branching instructions.
|
||||||
|
|
||||||
iFlushCall(FLUSH_EVERYTHING);
|
iFlushCall(FLUSH_EVERYTHING);
|
||||||
iBranchTest(0xffffffff, true);
|
iBranchTest();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1671,7 +1671,6 @@ R5900cpu recCpu = {
|
||||||
recResetEE,
|
recResetEE,
|
||||||
recStep,
|
recStep,
|
||||||
recExecute,
|
recExecute,
|
||||||
recExecuteBlock,
|
|
||||||
recClear,
|
recClear,
|
||||||
recShutdown
|
recShutdown
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue