- 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:
Marcos Vitali 2010-12-13 07:56:54 +00:00
parent 3d3411f3a0
commit 5fd9951649
5 changed files with 68 additions and 18 deletions

View File

@ -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;

View File

@ -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();
} }

View File

@ -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

View File

@ -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

View File

@ -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