summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/Src/CommandProcessor.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2012-03-22 15:21:52 +0100
committerPierre Bourdon <delroth@gmail.com>2012-03-22 15:21:52 +0100
commit0ffc12bbfd6ac44b3030ec30f400a58e951087b7 (patch)
tree53a6fac9ec79bcd71fe2046d8fb579478da12fd2 /Source/Core/VideoCommon/Src/CommandProcessor.cpp
parent006923e871e496a7c6c0fe9ba76da4ee939ce14e (diff)
parentd95e31af3f779bfa3141047e8b6275e1fd2e4bbb (diff)
Merge branch 'master' into zcomploc-support
Conflicts: Source/Core/VideoCommon/Src/PixelShaderGen.cpp
Diffstat (limited to 'Source/Core/VideoCommon/Src/CommandProcessor.cpp')
-rw-r--r--Source/Core/VideoCommon/Src/CommandProcessor.cpp134
1 files changed, 74 insertions, 60 deletions
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
index ad05a9797e..a4dddf537f 100644
--- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp
+++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
@@ -56,11 +56,12 @@ static bool bProcessFifoToLoWatermark = false;
static bool bProcessFifoAllDistance = false;
volatile bool isPossibleWaitingSetDrawDone = false;
+volatile bool isHiWatermarkActive = false;
volatile bool interruptSet= false;
volatile bool interruptWaiting= false;
volatile bool interruptTokenWaiting = false;
volatile bool interruptFinishWaiting = false;
-volatile bool OnOverflow = false;
+volatile bool waitingForPEInterruptDisable = false;
bool IsOnThread()
{
@@ -86,13 +87,12 @@ void DoState(PointerWrap &p)
p.Do(bProcessFifoToLoWatermark);
p.Do(bProcessFifoAllDistance);
-
+ p.Do(isHiWatermarkActive);
p.Do(isPossibleWaitingSetDrawDone);
p.Do(interruptSet);
p.Do(interruptWaiting);
p.Do(interruptTokenWaiting);
p.Do(interruptFinishWaiting);
- p.Do(OnOverflow);
}
inline void WriteLow (volatile u32& _reg, u16 lowbits) {Common::AtomicStore(_reg,(_reg & 0xFFFF0000) | lowbits);}
@@ -109,6 +109,8 @@ void Init()
m_CPCtrlReg.Hex = 0;
+ m_CPClearReg.Hex = 0;
+
m_bboxleft = 0;
m_bboxtop = 0;
m_bboxright = 640;
@@ -130,14 +132,17 @@ void Init()
interruptFinishWaiting = false;
interruptTokenWaiting = false;
+ bProcessFifoToLoWatermark = false;
+ bProcessFifoAllDistance = false;
+ isPossibleWaitingSetDrawDone = false;
+ isHiWatermarkActive = false;
+
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
}
void Read16(u16& _rReturnValue, const u32 _Address)
{
-
INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
- ProcessFifoEvents();
switch (_Address & 0xFFF)
{
case STATUS_REGISTER:
@@ -166,11 +171,23 @@ void Read16(u16& _rReturnValue, const u32 _Address)
case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
case FIFO_RW_DISTANCE_LO:
- _rReturnValue = ReadLow (fifo.CPReadWriteDistance);
+ if (IsOnThread())
+ if(fifo.CPWritePointer >= fifo.SafeCPReadPointer)
+ _rReturnValue = ReadLow (fifo.CPWritePointer - fifo.SafeCPReadPointer);
+ else
+ _rReturnValue = ReadLow (fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
+ else
+ _rReturnValue = ReadLow (fifo.CPReadWriteDistance);
DEBUG_LOG(COMMANDPROCESSOR, "read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
return;
case FIFO_RW_DISTANCE_HI:
- _rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
+ if (IsOnThread())
+ if(fifo.CPWritePointer >= fifo.SafeCPReadPointer)
+ _rReturnValue = ReadHigh (fifo.CPWritePointer - fifo.SafeCPReadPointer);
+ else
+ _rReturnValue = ReadHigh (fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
+ else
+ _rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
DEBUG_LOG(COMMANDPROCESSOR, "read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
return;
case FIFO_WRITE_POINTER_LO:
@@ -304,6 +321,7 @@ void Write16(const u16 _Value, const u32 _Address)
UCPClearReg tmpCtrl(_Value);
m_CPClearReg.Hex = tmpCtrl.Hex;
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x", _Value);
+ SetCpClearRegister();
}
break;
@@ -350,6 +368,7 @@ void Write16(const u16 _Value, const u32 _Address)
break;
case FIFO_READ_POINTER_HI:
WriteHigh((u32 &)fifo.CPReadPointer, _Value);
+ fifo.SafeCPReadPointer = fifo.CPReadPointer;
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI : %04x", _Value);
break;
@@ -382,10 +401,6 @@ void Write16(const u16 _Value, const u32 _Address)
case FIFO_RW_DISTANCE_HI:
WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
- break;
- case FIFO_RW_DISTANCE_LO:
- WriteLow((u32 &)fifo.CPReadWriteDistance, _Value & 0xFFE0);
if (fifo.CPReadWriteDistance == 0)
{
GPFifo::ResetGatherPipe();
@@ -395,6 +410,10 @@ void Write16(const u16 _Value, const u32 _Address)
ResetVideoBuffer();
}
IncrementCheckContextId();
+ DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
+ break;
+ case FIFO_RW_DISTANCE_LO:
+ WriteLow((u32 &)fifo.CPReadWriteDistance, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_LO : %04x", _Value);
break;
@@ -404,7 +423,6 @@ void Write16(const u16 _Value, const u32 _Address)
if (!IsOnThread())
RunGpu();
- ProcessFifoEvents();
}
void Read32(u32& _rReturnValue, const u32 _Address)
@@ -426,6 +444,19 @@ void STACKALIGN GatherPipeBursted()
{
if (!IsOnThread())
RunGpu();
+ else
+ {
+ // In multibuffer mode is not allowed write in the same fifo attached to the GPU.
+ // Fix Pokemon XD in DC mode.
+ if((ProcessorInterface::Fifo_CPUEnd == fifo.CPEnd) && (ProcessorInterface::Fifo_CPUBase == fifo.CPBase)
+ && fifo.CPReadWriteDistance > 0)
+ {
+ waitingForPEInterruptDisable = true;
+ ProcessFifoAllDistance();
+ waitingForPEInterruptDisable = false;
+ }
+
+ }
return;
}
@@ -441,26 +472,7 @@ void STACKALIGN GatherPipeBursted()
Common::AtomicAdd(fifo.CPReadWriteDistance, GATHER_PIPE_SIZE);
if (!IsOnThread())
- {
RunGpu();
- }
- else
- {
- if(fifo.CPReadWriteDistance == fifo.CPEnd - fifo.CPBase - 32)
- {
- if(!OnOverflow)
- NOTICE_LOG(COMMANDPROCESSOR,"FIFO is almost in overflown, BreakPoint: %i", fifo.bFF_Breakpoint);
- OnOverflow = true;
- while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
- fifo.CPReadWriteDistance > fifo.CPEnd - fifo.CPBase - 64)
- Common::YieldCPU();
- }
- else
- {
- OnOverflow = false;
- }
- }
-
_assert_msg_(COMMANDPROCESSOR, fifo.CPReadWriteDistance <= fifo.CPEnd - fifo.CPBase,
"FIFO is overflown by GatherPipe !\nCPU thread is too fast!");
@@ -501,17 +513,15 @@ void AbortFrame()
void SetOverflowStatusFromGatherPipe()
{
- if (!fifo.bFF_HiWatermarkInt) return;
-
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
- fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
-
- bool interrupt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt &&
- m_CPCtrlReg.GPLinkEnable && m_CPCtrlReg.GPReadEnable;
+ isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable;
- if (interrupt != interruptSet && interrupt)
- CommandProcessor::UpdateInterrupts(true);
-
+ if (isHiWatermarkActive)
+ {
+ interruptSet = true;
+ INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
+ ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
+ }
}
void SetCpStatus()
@@ -519,14 +529,12 @@ void SetCpStatus()
// overflow & underflow check
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
-
- // breakpoint
+ // breakpoint
if (fifo.bFF_BPEnable)
{
if (fifo.CPBreakpoint == fifo.CPReadPointer)
- {
-
+ {
if (!fifo.bFF_Breakpoint)
{
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
@@ -554,13 +562,18 @@ void SetCpStatus()
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
+ isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
+
if (interrupt != interruptSet && !interruptWaiting)
{
u64 userdata = interrupt?1:0;
if (IsOnThread())
{
- interruptWaiting = true;
- CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
+ if(!interrupt || bpInt || undfInt)
+ {
+ interruptWaiting = true;
+ CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
+ }
}
else
CommandProcessor::UpdateInterrupts(userdata);
@@ -583,7 +596,7 @@ void ProcessFifoAllDistance()
if (IsOnThread())
{
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
- fifo.CPReadWriteDistance && !AtBreakpoint())
+ fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
Common::YieldCPU();
}
bProcessFifoAllDistance = false;
@@ -603,13 +616,16 @@ void Shutdown()
void SetCpStatusRegister()
{
// Here always there is one fifo attached to the GPU
-
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
- m_CPStatusReg.ReadIdle = (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint);
+ m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ;
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance;
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
+ // HACK to compensate for slow response to PE interrupts in Time Splitters: Future Perfect
+ if (IsOnThread())
+ PixelEngine::ResumeWaitingForPEInterrupt();
+
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
@@ -622,14 +638,14 @@ void SetCpStatusRegister()
void SetCpControlRegister()
{
-
// If the new fifo is being attached We make sure there wont be SetFinish event pending.
// This protection fix eternal darkness booting, because the second SetFinish event when it is booting
// seems invalid or has a bug and hang the game.
if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable)
{
- PixelEngine::ResetSetFinish();
+ ProcessFifoEvents();
+ PixelEngine::ResetSetFinish();
}
fifo.bFF_BPInt = m_CPCtrlReg.BPInt;
@@ -644,9 +660,6 @@ void SetCpControlRegister()
ProcessorInterface::Fifo_CPUBase = fifo.CPBase;
ProcessorInterface::Fifo_CPUEnd = fifo.CPEnd;
}
- // If overflown happens process the fifo to LoWatemark
- if (bProcessFifoToLoWatermark)
- ProcessFifoToLoWatermark();
if(fifo.bFF_GPReadEnable && !m_CPCtrlReg.GPReadEnable)
{
@@ -658,7 +671,6 @@ void SetCpControlRegister()
fifo.bFF_GPReadEnable = m_CPCtrlReg.GPReadEnable;
}
-
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | BP %s | Int %s | OvF %s | UndF %s | LINK %s"
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
, fifo.bFF_BPEnable ? "ON" : "OFF"
@@ -670,13 +682,15 @@ void SetCpControlRegister()
}
+// NOTE: The implementation of this function should be correct, but we intentionally aren't using it at the moment.
+// We don't emulate proper GP timing anyway at the moment, so this code would just slow down emulation.
void SetCpClearRegister()
{
- if (IsOnThread())
- {
- if (!m_CPClearReg.ClearFifoUnderflow && m_CPClearReg.ClearFifoOverflow)
- bProcessFifoToLoWatermark = true;
- }
+// if (IsOnThread())
+// {
+// if (!m_CPClearReg.ClearFifoUnderflow && m_CPClearReg.ClearFifoOverflow)
+// bProcessFifoToLoWatermark = true;
+// }
}
} // end of namespace CommandProcessor