mirror of https://github.com/PCSX2/pcsx2.git
Cleanup for VsyncInThread, lots of source code comments. (it's fun reading! ...maybe)
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2318 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
6b5e302f82
commit
acbe1ed547
|
@ -30,7 +30,6 @@
|
||||||
using namespace Threading;
|
using namespace Threading;
|
||||||
|
|
||||||
extern u8 psxhblankgate;
|
extern u8 psxhblankgate;
|
||||||
extern void ApplyPatch( int place = 1);
|
|
||||||
|
|
||||||
static const uint EECNT_FUTURE_TARGET = 0x10000000;
|
static const uint EECNT_FUTURE_TARGET = 0x10000000;
|
||||||
|
|
||||||
|
@ -293,7 +292,6 @@ void frameLimitReset()
|
||||||
// Framelimiter - Measures the delta time between calls and stalls until a
|
// Framelimiter - Measures the delta time between calls and stalls until a
|
||||||
// certain amount of time passes if such time hasn't passed yet.
|
// certain amount of time passes if such time hasn't passed yet.
|
||||||
// See the GS FrameSkip function for details on why this is here and not in the GS.
|
// See the GS FrameSkip function for details on why this is here and not in the GS.
|
||||||
extern int limitOn;
|
|
||||||
static __forceinline void frameLimit()
|
static __forceinline void frameLimit()
|
||||||
{
|
{
|
||||||
// 999 means the user would rather just have framelimiting turned off...
|
// 999 means the user would rather just have framelimiting turned off...
|
||||||
|
@ -325,8 +323,10 @@ static __forceinline void frameLimit()
|
||||||
if( sDeltaTime >= 0 ) return;
|
if( sDeltaTime >= 0 ) return;
|
||||||
|
|
||||||
// If we're way ahead then we can afford to sleep the thread a bit.
|
// If we're way ahead then we can afford to sleep the thread a bit.
|
||||||
// (note, sleep(1) thru sleep(2) tend to be the least accurate sleeps, and longer
|
// (note, on Windows sleep(1) thru sleep(2) tend to be the least accurate sleeps,
|
||||||
// sleeps tend to be pretty reliable, so that's why the convoluted if/else below)
|
// and longer sleeps tend to be pretty reliable, so that's why the convoluted if/
|
||||||
|
// else below. The same generally isn't true for Linux, but no harm either way
|
||||||
|
// really.)
|
||||||
|
|
||||||
s32 msec = (int)((sDeltaTime*-1000) / (s64)GetTickFrequency());
|
s32 msec = (int)((sDeltaTime*-1000) / (s64)GetTickFrequency());
|
||||||
if( msec > 4 ) Threading::Sleep( msec );
|
if( msec > 4 ) Threading::Sleep( msec );
|
||||||
|
@ -339,8 +339,18 @@ static __forceinline void frameLimit()
|
||||||
|
|
||||||
static __forceinline void VSyncStart(u32 sCycle)
|
static __forceinline void VSyncStart(u32 sCycle)
|
||||||
{
|
{
|
||||||
EECNT_LOG( "///////// EE COUNTER VSYNC START \\\\\\\\\\\\\\\\\\\\ (frame: %d)", iFrame );
|
Cpu->CheckExecutionState();
|
||||||
vSyncDebugStuff( iFrame ); // EE Profiling and Debug code
|
SysCoreThread::Get().VsyncInThread();
|
||||||
|
|
||||||
|
EECNT_LOG( "///////// EE COUNTER VSYNC START (frame: %6d) \\\\\\\\\\\\\\\\\\\\ ", iFrame );
|
||||||
|
|
||||||
|
// EE Profiling and Debug code.
|
||||||
|
// FIXME: should probably be moved to VsyncInThread, and handled
|
||||||
|
// by UI implementations. (ie, AppCoreThread in PCSX2-wx interface).
|
||||||
|
vSyncDebugStuff( iFrame );
|
||||||
|
|
||||||
|
if (CHECK_MICROVU0) vsyncVUrec(0);
|
||||||
|
if (CHECK_MICROVU1) vsyncVUrec(1);
|
||||||
|
|
||||||
if ((CSRw & 0x8))
|
if ((CSRw & 0x8))
|
||||||
{
|
{
|
||||||
|
@ -355,7 +365,6 @@ static __forceinline void VSyncStart(u32 sCycle)
|
||||||
psxVBlankStart();
|
psxVBlankStart();
|
||||||
|
|
||||||
if (gates) rcntStartGate(true, sCycle); // Counters Start Gate code
|
if (gates) rcntStartGate(true, sCycle); // Counters Start Gate code
|
||||||
if (EmuConfig.EnablePatches) ApplyPatch(); // fixme - Apply patches
|
|
||||||
|
|
||||||
// INTC - VB Blank Start Hack --
|
// INTC - VB Blank Start Hack --
|
||||||
// Hack fix! This corrects a freezeup in Granda 2 where it decides to spin
|
// Hack fix! This corrects a freezeup in Granda 2 where it decides to spin
|
||||||
|
@ -445,8 +454,6 @@ __forceinline void rcntUpdate_vSync()
|
||||||
|
|
||||||
if (vsyncCounter.Mode == MODE_VSYNC)
|
if (vsyncCounter.Mode == MODE_VSYNC)
|
||||||
{
|
{
|
||||||
Cpu->CheckExecutionState();
|
|
||||||
|
|
||||||
VSyncEnd(vsyncCounter.sCycle);
|
VSyncEnd(vsyncCounter.sCycle);
|
||||||
|
|
||||||
vsyncCounter.sCycle += vSyncInfo.Blank;
|
vsyncCounter.sCycle += vSyncInfo.Blank;
|
||||||
|
@ -464,9 +471,6 @@ __forceinline void rcntUpdate_vSync()
|
||||||
// Accumulate hsync rounding errors:
|
// Accumulate hsync rounding errors:
|
||||||
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
hsyncCounter.sCycle += vSyncInfo.hSyncError;
|
||||||
|
|
||||||
if (CHECK_MICROVU0) vsyncVUrec(0);
|
|
||||||
if (CHECK_MICROVU1) vsyncVUrec(1);
|
|
||||||
|
|
||||||
# ifdef VSYNC_DEBUG
|
# ifdef VSYNC_DEBUG
|
||||||
vblankinc++;
|
vblankinc++;
|
||||||
if( vblankinc > 1 )
|
if( vblankinc > 1 )
|
||||||
|
|
|
@ -390,7 +390,6 @@ static void intExecute()
|
||||||
|
|
||||||
static void intCheckExecutionState()
|
static void intCheckExecutionState()
|
||||||
{
|
{
|
||||||
SysCoreThread::Get().OnVsyncInThread();
|
|
||||||
SysCoreThread::Get().StateCheckInThread();
|
SysCoreThread::Get().StateCheckInThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,12 +406,15 @@ static void intClear(u32 Addr, u32 Size)
|
||||||
static void intShutdown() {
|
static void intShutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
R5900cpu intCpu = {
|
R5900cpu intCpu =
|
||||||
|
{
|
||||||
intAlloc,
|
intAlloc,
|
||||||
|
intShutdown,
|
||||||
|
|
||||||
intReset,
|
intReset,
|
||||||
intStep,
|
intStep,
|
||||||
intExecute,
|
intExecute,
|
||||||
|
|
||||||
intCheckExecutionState,
|
intCheckExecutionState,
|
||||||
intClear,
|
intClear,
|
||||||
intShutdown
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1147,6 +1147,11 @@ void PluginManager::Freeze( PluginsEnum_t pid, SaveStateBase& state )
|
||||||
|
|
||||||
bool PluginManager::KeyEvent( const keyEvent& evt )
|
bool PluginManager::KeyEvent( const keyEvent& evt )
|
||||||
{
|
{
|
||||||
|
// [TODO] : The plan here is to give plugins "first chance" handling of keys.
|
||||||
|
// Handling order will be fixed (GS, SPU2, PAD, etc), and the first plugin to
|
||||||
|
// pick up the key and return "true" (for handled) will cause the loop to break.
|
||||||
|
// The current version of PS2E doesn't support it yet, though.
|
||||||
|
|
||||||
const PluginInfo* pi = tbl_PluginInfo; do {
|
const PluginInfo* pi = tbl_PluginInfo; do {
|
||||||
if( pi->id != PluginId_PAD )
|
if( pi->id != PluginId_PAD )
|
||||||
m_info[pi->id].CommonBindings.KeyEvent( const_cast<keyEvent*>(&evt) );
|
m_info[pi->id].CommonBindings.KeyEvent( const_cast<keyEvent*>(&evt) );
|
||||||
|
|
|
@ -263,16 +263,102 @@ void __fastcall intDoBranch(u32 target);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// R5900 Public Interface / API
|
// R5900 Public Interface / API
|
||||||
|
//
|
||||||
|
// [TODO] : This is on the list to get converted to a proper C++ class. I'm putting it
|
||||||
|
// off until I get my new IOPint and IOPrec re-merged. --air
|
||||||
|
//
|
||||||
struct R5900cpu
|
struct R5900cpu
|
||||||
{
|
{
|
||||||
void (*Allocate)(); // throws exceptions on failure.
|
// Memory allocation function, for allocating virtual memory spaces needed by
|
||||||
|
// the emulator. (ints/recs are free to allocate additional memory while running
|
||||||
|
// code, however any virtual mapped memory should always be allocated as soon
|
||||||
|
// as possible, to claim the memory before some plugin does..)
|
||||||
|
//
|
||||||
|
// Thread Affinity:
|
||||||
|
// Can be called from any thread. Execute status must be suspended or stopped
|
||||||
|
// to prevent multi-thread race conditions.
|
||||||
|
//
|
||||||
|
// Notable Exception Throws:
|
||||||
|
// OutOfMemory - Not enough memory, or the memory areas required were already
|
||||||
|
// reserved.
|
||||||
|
//
|
||||||
|
void (*Allocate)();
|
||||||
|
|
||||||
|
// Deallocates ram allocated by Allocate and/or by runtime code execution.
|
||||||
|
//
|
||||||
|
// Thread Affinity:
|
||||||
|
// Can be called from any thread. Execute status must be suspended or stopped
|
||||||
|
// to prevent multi-thread race conditions.
|
||||||
|
//
|
||||||
|
// Exception Throws: None. This function is a destructor, and should not throw.
|
||||||
|
//
|
||||||
|
void (*Shutdown)();
|
||||||
|
|
||||||
|
// Initializes / Resets code execution states. Typically implementation is only
|
||||||
|
// needed for recompilers, as interpreters have no internal execution states and
|
||||||
|
// rely on the CPU/VM states almost entirely.
|
||||||
|
//
|
||||||
|
// Thread Affinity:
|
||||||
|
// Can be called from any thread. Execute status must be suspended or stopped
|
||||||
|
// to prevent multi-thread race conditions.
|
||||||
|
//
|
||||||
|
// Exception Throws: Emulator-defined. Common exception types to look for:
|
||||||
|
// OutOfMemory, Stream Exceptions
|
||||||
|
//
|
||||||
void (*Reset)();
|
void (*Reset)();
|
||||||
|
|
||||||
|
// Steps a single instruction. Meant to be used by debuggers. Is currently unused
|
||||||
|
// and unimplemented. Future note: recompiler "step" should *always* fall back
|
||||||
|
// on interpreters.
|
||||||
|
//
|
||||||
|
// Exception Throws: [TODO] (possible execution-related throws to be added)
|
||||||
|
//
|
||||||
void (*Step)();
|
void (*Step)();
|
||||||
|
|
||||||
|
// Executes code until a break is signaled. Execution can be paused or suspended
|
||||||
|
// via thread-style signals that are handled by CheckExecutionState callbacks.
|
||||||
|
// Execution Breakages are handled the same way, where-by a signal causes the Execute
|
||||||
|
// call to return at the nearest state check (typically handled internally using
|
||||||
|
// either C++ exceptions or setjmp/longjmp).
|
||||||
|
//
|
||||||
|
// Exception Throws: [TODO] (possible execution-related throws to be added)
|
||||||
|
//
|
||||||
void (*Execute)();
|
void (*Execute)();
|
||||||
|
|
||||||
|
// Checks for execution suspension or cancellation. In pthreads terms this provides
|
||||||
|
// a "cancellation point." Execution state checks are typically performed at Vsyncs
|
||||||
|
// by the generic VM event handlers in R5900.cpp/Counters.cpp (applies to both recs
|
||||||
|
// and ints).
|
||||||
|
//
|
||||||
|
// Implementation note: Because of the nuances of recompiled code execution, setjmp
|
||||||
|
// may be used in place of thread cancellation or C++ exceptions (non-SEH exceptions
|
||||||
|
// cannot unwind through the recompiled code stackframes).
|
||||||
|
//
|
||||||
|
// Thread Affinity:
|
||||||
|
// Must be called on the same thread as Execute only.
|
||||||
|
//
|
||||||
|
// Exception Throws:
|
||||||
|
// May throw threading/Pthreads cancellations if the compiler supports SEH.
|
||||||
|
// ThreadTimedOut - For canceling VM execution in response to MTGS deadlock. (if the
|
||||||
|
// core emulator does not support multithreaded GS then this will not be a throw
|
||||||
|
// exception).
|
||||||
|
//
|
||||||
void (*CheckExecutionState)();
|
void (*CheckExecutionState)();
|
||||||
|
|
||||||
|
// Manual recompiled code cache clear; typically useful to recompilers only. Size is
|
||||||
|
// in MIPS words (32 bits). Dev note: this callback is nearly obsolete, and might be
|
||||||
|
// better off replaced with some generic API callbacks from VTLB block protection.
|
||||||
|
// Also: the calls from COP0's TLB remap code should be replaced with full recompiler
|
||||||
|
// resets, since TLB remaps affect more than just the code they contain (code that
|
||||||
|
// may reference the remaped blocks via memory loads/stores, for example).
|
||||||
|
//
|
||||||
|
// Thread Affinity Rule:
|
||||||
|
// Can be called from any thread (namely for being called from debugging threads)
|
||||||
|
//
|
||||||
|
// Exception Throws: [TODO] Emulator defined? (probably shouldn't throw, probably
|
||||||
|
// doesn't matter if we're stripping it out soon. ;)
|
||||||
|
//
|
||||||
void (*Clear)(u32 Addr, u32 Size);
|
void (*Clear)(u32 Addr, u32 Size);
|
||||||
void (*Shutdown)(); // deallocates memory reserved by Allocate
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern R5900cpu *Cpu;
|
extern R5900cpu *Cpu;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
#include "Elfheader.h"
|
#include "Elfheader.h"
|
||||||
|
#include "Patch.h"
|
||||||
#include "PageFaultSource.h"
|
#include "PageFaultSource.h"
|
||||||
#include "SysThreads.h"
|
#include "SysThreads.h"
|
||||||
|
|
||||||
|
@ -279,10 +280,37 @@ void SysCoreThread::_reset_stuff_as_needed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysCoreThread::OnVsyncInThread()
|
// Called by the VsyncInThread() if a valid keyEvent is pending and is unhandled by other
|
||||||
|
// PS2 core plugins.
|
||||||
|
void SysCoreThread::DispatchKeyEventToUI( const keyEvent& evt )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called from the PS2 VM at the start of every vsync (either 59.94 or 50 hz by PS2
|
||||||
|
// clock scale, which does not correlate to the actual host machine vsync).
|
||||||
|
//
|
||||||
|
// Default tasks: Updates PADs and applies vsync patches. Derived classes can override this
|
||||||
|
// to change either PAD and/or Patching behaviors.
|
||||||
|
//
|
||||||
|
// [TODO]: Should probably also handle profiling and debugging updates, once those are
|
||||||
|
// re-implemented.
|
||||||
|
//
|
||||||
|
void SysCoreThread::VsyncInThread()
|
||||||
|
{
|
||||||
|
if( !pxAssert(g_plugins!=NULL) ) return;
|
||||||
|
const keyEvent* ev = PADkeyEvent();
|
||||||
|
if( ev != NULL && (ev->key != 0) )
|
||||||
|
{
|
||||||
|
// Give plugins first try to handle keys. If none of them handles the key, it will
|
||||||
|
// be passed to the main user interface.
|
||||||
|
|
||||||
|
if( !g_plugins->KeyEvent( *ev ) )
|
||||||
|
DispatchKeyEventToUI( *ev );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EmuConfig.EnablePatches) ApplyPatch();
|
||||||
|
}
|
||||||
|
|
||||||
void SysCoreThread::StateCheckInThread()
|
void SysCoreThread::StateCheckInThread()
|
||||||
{
|
{
|
||||||
GetMTGS().RethrowException();
|
GetMTGS().RethrowException();
|
||||||
|
@ -290,8 +318,6 @@ void SysCoreThread::StateCheckInThread()
|
||||||
if( !m_hasValidState )
|
if( !m_hasValidState )
|
||||||
throw Exception::RuntimeError( "Invalid emulation state detected; Virtual machine threads have been cancelled." );
|
throw Exception::RuntimeError( "Invalid emulation state detected; Virtual machine threads have been cancelled." );
|
||||||
|
|
||||||
//OnVsyncInThread();
|
|
||||||
|
|
||||||
_reset_stuff_as_needed();
|
_reset_stuff_as_needed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,8 @@ public:
|
||||||
|
|
||||||
bool HasPendingStateChangeRequest() const;
|
bool HasPendingStateChangeRequest() const;
|
||||||
virtual void StateCheckInThread();
|
virtual void StateCheckInThread();
|
||||||
virtual void OnVsyncInThread();
|
virtual void VsyncInThread();
|
||||||
|
virtual void DispatchKeyEventToUI( const keyEvent& evt );
|
||||||
|
|
||||||
virtual const wxString& GetElfOverride() const { return m_elf_override; }
|
virtual const wxString& GetElfOverride() const { return m_elf_override; }
|
||||||
virtual void SetElfOverride( const wxString& elf );
|
virtual void SetElfOverride( const wxString& elf );
|
||||||
|
|
|
@ -542,7 +542,8 @@ protected:
|
||||||
virtual void OnResumeInThread( bool IsSuspended );
|
virtual void OnResumeInThread( bool IsSuspended );
|
||||||
virtual void OnSuspendInThread();
|
virtual void OnSuspendInThread();
|
||||||
virtual void OnCleanupInThread();
|
virtual void OnCleanupInThread();
|
||||||
virtual void OnVsyncInThread();
|
//virtual void VsyncInThread();
|
||||||
|
virtual void DispatchKeyEventToUI( const keyEvent& ev );
|
||||||
virtual void ExecuteTaskInThread();
|
virtual void ExecuteTaskInThread();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -163,23 +163,15 @@ void AppCoreThread::OnCleanupInThread()
|
||||||
extern int TranslateGDKtoWXK( u32 keysym );
|
extern int TranslateGDKtoWXK( u32 keysym );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void AppCoreThread::OnVsyncInThread()
|
void AppCoreThread::DispatchKeyEventToUI( const keyEvent& ev )
|
||||||
{
|
{
|
||||||
_parent::OnVsyncInThread();
|
m_kevt.SetEventType( ( ev.evt == KEYPRESS ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP );
|
||||||
|
const bool isDown = (ev.evt == KEYPRESS);
|
||||||
if( !pxAssert(g_plugins!=NULL) ) return;
|
|
||||||
|
|
||||||
const keyEvent* ev = PADkeyEvent();
|
|
||||||
if( ev == NULL || (ev->key == 0) ) return;
|
|
||||||
|
|
||||||
g_plugins->KeyEvent( *ev );
|
|
||||||
m_kevt.SetEventType( ( ev->evt == KEYPRESS ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP );
|
|
||||||
const bool isDown = (ev->evt == KEYPRESS);
|
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
const int vkey = wxCharCodeMSWToWX( ev->key );
|
const int vkey = wxCharCodeMSWToWX( ev.key );
|
||||||
#elif defined( __WXGTK__ )
|
#elif defined( __WXGTK__ )
|
||||||
const int vkey = TranslateGDKtoWXK( ev->key );
|
const int vkey = TranslateGDKtoWXK( ev.key );
|
||||||
#else
|
#else
|
||||||
# error Unsupported Target Platform.
|
# error Unsupported Target Platform.
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -656,8 +656,6 @@ static jmp_buf m_SetJmp_StateCheck;
|
||||||
|
|
||||||
static void recCheckExecutionState()
|
static void recCheckExecutionState()
|
||||||
{
|
{
|
||||||
SysCoreThread::Get().OnVsyncInThread();
|
|
||||||
|
|
||||||
#if PCSX2_SEH
|
#if PCSX2_SEH
|
||||||
SysCoreThread::Get().StateCheckInThread();
|
SysCoreThread::Get().StateCheckInThread();
|
||||||
|
|
||||||
|
@ -1733,10 +1731,12 @@ StartRecomp:
|
||||||
R5900cpu recCpu =
|
R5900cpu recCpu =
|
||||||
{
|
{
|
||||||
recAlloc,
|
recAlloc,
|
||||||
|
recShutdown,
|
||||||
|
|
||||||
recResetEE,
|
recResetEE,
|
||||||
recStep,
|
recStep,
|
||||||
recExecute,
|
recExecute,
|
||||||
|
|
||||||
recCheckExecutionState,
|
recCheckExecutionState,
|
||||||
recClear,
|
recClear,
|
||||||
recShutdown
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue