- I've implemented cache of interrupt states for PEFINISH and PETOKEN
- I've implemented calling to ProcessFifoEvents when is there is a pending event in the main queue from CP, PE & GP - I've implemented FifoIntReset(TRUE, TRUE) in write Clear Register. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6572 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
3d3411f3a0
commit
5fd9951649
|
@ -330,6 +330,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||||
VideoInitialize.pRegisterEvent = CoreTiming::RegisterEvent;
|
VideoInitialize.pRegisterEvent = CoreTiming::RegisterEvent;
|
||||||
VideoInitialize.pScheduleEvent_Threadsafe = CoreTiming::ScheduleEvent_Threadsafe;
|
VideoInitialize.pScheduleEvent_Threadsafe = CoreTiming::ScheduleEvent_Threadsafe;
|
||||||
VideoInitialize.pRemoveEvent = CoreTiming::RemoveAllEvents;
|
VideoInitialize.pRemoveEvent = CoreTiming::RemoveAllEvents;
|
||||||
|
VideoInitialize.pProcessFifoEvents = CoreTiming::ProcessFifoWaitEvents;
|
||||||
// This is first the m_Panel handle, then it is updated to have the new window handle
|
// This is first the m_Panel handle, then it is updated to have the new window handle
|
||||||
VideoInitialize.pWindowHandle = _CoreParameter.hMainWindow;
|
VideoInitialize.pWindowHandle = _CoreParameter.hMainWindow;
|
||||||
VideoInitialize.pLog = Callback_VideoLog;
|
VideoInitialize.pLog = Callback_VideoLog;
|
||||||
|
|
|
@ -111,11 +111,13 @@ static u32 fake_GPWatchdogLastToken = 0;
|
||||||
static Common::EventEx s_fifoIdleEvent;
|
static Common::EventEx s_fifoIdleEvent;
|
||||||
static Common::CriticalSection sFifoCritical;
|
static Common::CriticalSection sFifoCritical;
|
||||||
static bool bProcessFifoToLoWatemark = false;
|
static bool bProcessFifoToLoWatemark = false;
|
||||||
|
static bool bProcessFifoAllDistance = false;
|
||||||
|
|
||||||
volatile bool isFifoBusy = false; //This state is changed when the FIFO is processing data.
|
volatile bool isFifoBusy = false; //This state is changed when the FIFO is processing data.
|
||||||
volatile bool interruptSet= false;
|
volatile bool interruptSet= false;
|
||||||
volatile bool interruptWaiting= false;
|
volatile bool interruptWaiting= false;
|
||||||
|
volatile bool interruptTokenWaiting = false;
|
||||||
|
volatile bool interruptFinishWaiting = false;
|
||||||
|
|
||||||
void FifoCriticalEnter()
|
void FifoCriticalEnter()
|
||||||
{
|
{
|
||||||
|
@ -177,6 +179,8 @@ void Init()
|
||||||
|
|
||||||
interruptSet = false;
|
interruptSet = false;
|
||||||
interruptWaiting = false;
|
interruptWaiting = false;
|
||||||
|
interruptFinishWaiting = false;
|
||||||
|
interruptTokenWaiting = false;
|
||||||
|
|
||||||
s_fifoIdleEvent.Init();
|
s_fifoIdleEvent.Init();
|
||||||
|
|
||||||
|
@ -192,6 +196,7 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
||||||
{
|
{
|
||||||
|
|
||||||
INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
|
INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
|
||||||
|
ProcessFifoEvents();
|
||||||
switch (_Address & 0xFFF)
|
switch (_Address & 0xFFF)
|
||||||
{
|
{
|
||||||
case STATUS_REGISTER:
|
case STATUS_REGISTER:
|
||||||
|
@ -459,6 +464,9 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
if (bProcessFifoToLoWatemark)
|
if (bProcessFifoToLoWatemark)
|
||||||
ProcessFifoToLoWatemark();
|
ProcessFifoToLoWatemark();
|
||||||
|
|
||||||
|
if (bProcessFifoAllDistance)
|
||||||
|
ProcessFifoAllDistance();
|
||||||
|
|
||||||
INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value);
|
INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | BP %s | Int %s | OvF %s | UndF %s | LINK %s"
|
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | BP %s | Int %s | OvF %s | UndF %s | LINK %s"
|
||||||
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
|
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
|
||||||
|
@ -479,6 +487,9 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
{
|
{
|
||||||
if (!tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow)
|
if (!tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow)
|
||||||
bProcessFifoToLoWatemark = true;
|
bProcessFifoToLoWatemark = true;
|
||||||
|
|
||||||
|
if (tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow)
|
||||||
|
bProcessFifoAllDistance = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -590,8 +601,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
|
|
||||||
if (!g_VideoInitialize.bOnThread)
|
if (!g_VideoInitialize.bOnThread)
|
||||||
CatchUpGPU();
|
CatchUpGPU();
|
||||||
|
ProcessFifoEvents();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read32(u32& _rReturnValue, const u32 _Address)
|
void Read32(u32& _rReturnValue, const u32 _Address)
|
||||||
|
@ -626,7 +636,7 @@ void WaitForFrameFinish()
|
||||||
|
|
||||||
void STACKALIGN GatherPipeBursted()
|
void STACKALIGN GatherPipeBursted()
|
||||||
{
|
{
|
||||||
|
ProcessFifoEvents();
|
||||||
// if we aren't linked, we don't care about gather pipe data
|
// if we aren't linked, we don't care about gather pipe data
|
||||||
if (!m_CPCtrlReg.GPLinkEnable)
|
if (!m_CPCtrlReg.GPLinkEnable)
|
||||||
{
|
{
|
||||||
|
@ -862,6 +872,13 @@ void ProcessFifoAllDistance()
|
||||||
fifo.CPReadWriteDistance && !AtBreakpoint())
|
fifo.CPReadWriteDistance && !AtBreakpoint())
|
||||||
Common::YieldCPU();
|
Common::YieldCPU();
|
||||||
}
|
}
|
||||||
|
bProcessFifoAllDistance = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessFifoEvents()
|
||||||
|
{
|
||||||
|
if (g_VideoInitialize.bOnThread || interruptWaiting || interruptFinishWaiting || interruptTokenWaiting)
|
||||||
|
g_VideoInitialize.pProcessFifoEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator
|
||||||
extern volatile bool isFifoBusy; //This one is used for sync gfx thread and emulator thread.
|
extern volatile bool isFifoBusy; //This one is used for sync gfx thread and emulator thread.
|
||||||
extern volatile bool interruptSet;
|
extern volatile bool interruptSet;
|
||||||
extern volatile bool interruptWaiting;
|
extern volatile bool interruptWaiting;
|
||||||
|
extern volatile bool interruptTokenWaiting;
|
||||||
|
extern volatile bool interruptFinishWaiting;
|
||||||
|
|
||||||
// internal hardware addresses
|
// internal hardware addresses
|
||||||
enum
|
enum
|
||||||
|
@ -170,6 +172,7 @@ void FifoCriticalLeave();
|
||||||
void SetOverflowStatusFromGatherPipe();
|
void SetOverflowStatusFromGatherPipe();
|
||||||
void ProcessFifoToLoWatemark();
|
void ProcessFifoToLoWatemark();
|
||||||
void ProcessFifoAllDistance();
|
void ProcessFifoAllDistance();
|
||||||
|
void ProcessFifoEvents();
|
||||||
void AbortFrame();
|
void AbortFrame();
|
||||||
} // namespace CommandProcessor
|
} // namespace CommandProcessor
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,9 @@ static bool g_bSignalFinishInterrupt;
|
||||||
static int et_SetTokenOnMainThread;
|
static int et_SetTokenOnMainThread;
|
||||||
static int et_SetFinishOnMainThread;
|
static int et_SetFinishOnMainThread;
|
||||||
|
|
||||||
|
volatile bool interruptSetToken = false;
|
||||||
|
volatile bool interruptSetFinish = false;
|
||||||
|
|
||||||
u16 bbox[4];
|
u16 bbox[4];
|
||||||
bool bbox_active;
|
bool bbox_active;
|
||||||
|
|
||||||
|
@ -139,7 +142,8 @@ void DoState(PointerWrap &p)
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
|
void UpdateTokenInterrupt(bool active);
|
||||||
|
void UpdateFinishInterrupt(bool active);
|
||||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate);
|
void SetToken_OnMainThread(u64 userdata, int cyclesLate);
|
||||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
||||||
|
|
||||||
|
@ -161,7 +165,7 @@ void Init()
|
||||||
void Read16(u16& _uReturnValue, const u32 _iAddress)
|
void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(PIXELENGINE, "(r16) 0x%08x", _iAddress);
|
DEBUG_LOG(PIXELENGINE, "(r16) 0x%08x", _iAddress);
|
||||||
|
CommandProcessor::ProcessFifoEvents();
|
||||||
switch (_iAddress & 0xFFF)
|
switch (_iAddress & 0xFFF)
|
||||||
{
|
{
|
||||||
// CPU Direct Access EFB Raster State Config
|
// CPU Direct Access EFB Raster State Config
|
||||||
|
@ -226,6 +230,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||||
_uReturnValue = 1;
|
_uReturnValue = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write16(const u16 _iValue, const u32 _iAddress)
|
void Write16(const u16 _iValue, const u32 _iAddress)
|
||||||
|
@ -282,6 +287,8 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
||||||
WARN_LOG(PIXELENGINE, "(w16) unknown %04x @ %08x", _iValue, _iAddress);
|
WARN_LOG(PIXELENGINE, "(w16) unknown %04x @ %08x", _iValue, _iAddress);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandProcessor::ProcessFifoEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write32(const u32 _iValue, const u32 _iAddress)
|
void Write32(const u32 _iValue, const u32 _iAddress)
|
||||||
|
@ -291,22 +298,35 @@ void Write32(const u32 _iValue, const u32 _iAddress)
|
||||||
|
|
||||||
bool AllowIdleSkipping()
|
bool AllowIdleSkipping()
|
||||||
{
|
{
|
||||||
return !g_VideoInitialize.bOnThread|| (!m_Control.PETokenEnable && !m_Control.PEFinishEnable);
|
return !g_VideoInitialize.bOnThread || (!m_Control.PETokenEnable && !m_Control.PEFinishEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterrupts()
|
void UpdateInterrupts()
|
||||||
{
|
{
|
||||||
// check if there is a token-interrupt
|
// check if there is a token-interrupt
|
||||||
if (g_bSignalTokenInterrupt & m_Control.PETokenEnable)
|
UpdateTokenInterrupt((g_bSignalTokenInterrupt & m_Control.PETokenEnable));
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
|
||||||
else
|
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
|
||||||
|
|
||||||
// check if there is a finish-interrupt
|
// check if there is a finish-interrupt
|
||||||
if (g_bSignalFinishInterrupt & m_Control.PEFinishEnable)
|
UpdateFinishInterrupt((g_bSignalFinishInterrupt & m_Control.PEFinishEnable));
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, true);
|
}
|
||||||
else
|
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false);
|
void UpdateTokenInterrupt(bool active)
|
||||||
|
{
|
||||||
|
if(interruptSetToken != active)
|
||||||
|
{
|
||||||
|
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, active);
|
||||||
|
interruptSetToken = active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateFinishInterrupt(bool active)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(interruptSetFinish != active)
|
||||||
|
{
|
||||||
|
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, active);
|
||||||
|
interruptSetFinish = active;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
|
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
|
||||||
|
@ -322,6 +342,7 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
//_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
|
//_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
|
||||||
INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
|
INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
|
CommandProcessor::interruptTokenWaiting = false;
|
||||||
//}
|
//}
|
||||||
//else
|
//else
|
||||||
// LOGV(PIXELENGINE, 1, "VIDEO Plugin wrote token: %i", CommandProcessor::fifo.PEToken);
|
// LOGV(PIXELENGINE, 1, "VIDEO Plugin wrote token: %i", CommandProcessor::fifo.PEToken);
|
||||||
|
@ -331,6 +352,7 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
g_bSignalFinishInterrupt = 1;
|
g_bSignalFinishInterrupt = 1;
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
|
CommandProcessor::interruptFinishWaiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetToken
|
// SetToken
|
||||||
|
@ -342,6 +364,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
{
|
{
|
||||||
// This seems smelly...
|
// This seems smelly...
|
||||||
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack since PEToken seems to be a frame-finish too
|
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack since PEToken seems to be a frame-finish too
|
||||||
|
CommandProcessor::interruptTokenWaiting = true;
|
||||||
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
||||||
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||||
}
|
}
|
||||||
|
@ -361,6 +384,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
void SetFinish()
|
void SetFinish()
|
||||||
{
|
{
|
||||||
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack
|
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack
|
||||||
|
CommandProcessor::interruptFinishWaiting = true;
|
||||||
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
g_VideoInitialize.pScheduleEvent_Threadsafe(
|
||||||
0, et_SetFinishOnMainThread, 0);
|
0, et_SetFinishOnMainThread, 0);
|
||||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||||
|
@ -373,25 +397,27 @@ void ResetSetFinish()
|
||||||
//remove event from the queque
|
//remove event from the queque
|
||||||
if (g_bSignalFinishInterrupt)
|
if (g_bSignalFinishInterrupt)
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false);
|
UpdateFinishInterrupt(false);
|
||||||
g_bSignalFinishInterrupt = false;
|
g_bSignalFinishInterrupt = false;
|
||||||
|
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pRemoveEvent(et_SetFinishOnMainThread);
|
g_VideoInitialize.pRemoveEvent(et_SetFinishOnMainThread);
|
||||||
}
|
}
|
||||||
|
CommandProcessor::interruptFinishWaiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetSetToken()
|
void ResetSetToken()
|
||||||
{
|
{
|
||||||
if (g_bSignalTokenInterrupt)
|
if (g_bSignalTokenInterrupt)
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
UpdateTokenInterrupt(false);
|
||||||
g_bSignalTokenInterrupt = false;
|
g_bSignalTokenInterrupt = false;
|
||||||
|
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pRemoveEvent(et_SetTokenOnMainThread);
|
g_VideoInitialize.pRemoveEvent(et_SetTokenOnMainThread);
|
||||||
}
|
}
|
||||||
|
CommandProcessor::interruptTokenWaiting = false;
|
||||||
}
|
}
|
||||||
} // end of namespace PixelEngine
|
} // end of namespace PixelEngine
|
||||||
|
|
|
@ -15,6 +15,7 @@ typedef void (*TSetInterrupt)(u32 _causemask, bool _bSet);
|
||||||
typedef int (*TRegisterEvent)(const char *name, TimedCallback callback);
|
typedef int (*TRegisterEvent)(const char *name, TimedCallback callback);
|
||||||
typedef void (*TScheduleEvent_Threadsafe)(int cyclesIntoFuture, int event_type, u64 userdata);
|
typedef void (*TScheduleEvent_Threadsafe)(int cyclesIntoFuture, int event_type, u64 userdata);
|
||||||
typedef void (*TRemoveEvent)(int event_type);
|
typedef void (*TRemoveEvent)(int event_type);
|
||||||
|
typedef void (*TProcessFifoEvents)(void);
|
||||||
typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress);
|
typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress);
|
||||||
typedef void (*TVideoLog)(const char* _pMessage, int _bBreak);
|
typedef void (*TVideoLog)(const char* _pMessage, int _bBreak);
|
||||||
typedef void (*TSysMessage)(const char *fmt, ...);
|
typedef void (*TSysMessage)(const char *fmt, ...);
|
||||||
|
@ -82,6 +83,7 @@ typedef struct
|
||||||
TRegisterEvent pRegisterEvent;
|
TRegisterEvent pRegisterEvent;
|
||||||
TScheduleEvent_Threadsafe pScheduleEvent_Threadsafe;
|
TScheduleEvent_Threadsafe pScheduleEvent_Threadsafe;
|
||||||
TRemoveEvent pRemoveEvent;
|
TRemoveEvent pRemoveEvent;
|
||||||
|
TProcessFifoEvents pProcessFifoEvents;
|
||||||
TGetMemoryPointer pGetMemoryPointer;
|
TGetMemoryPointer pGetMemoryPointer;
|
||||||
TVideoLog pLog;
|
TVideoLog pLog;
|
||||||
TSysMessage pSysMessage;
|
TSysMessage pSysMessage;
|
||||||
|
@ -197,5 +199,6 @@ EXPORT bool CALL Video_IsFifoBusy(void);
|
||||||
|
|
||||||
EXPORT void CALL Video_AbortFrame(void);
|
EXPORT void CALL Video_AbortFrame(void);
|
||||||
|
|
||||||
|
|
||||||
#include "ExportEpilog.h"
|
#include "ExportEpilog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue