summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/CommandProcessor.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2014-02-16 19:30:10 +0100
committerPierre Bourdon <delroth@gmail.com>2014-02-16 19:30:10 +0100
commit2a7a94387ca0e096f698c0468307bfe6b1d365d7 (patch)
treec27d33a1b27de83d378708f9c966c1a1b8d16af5 /Source/Core/VideoCommon/CommandProcessor.cpp
parent1e94853301b15fcce23db311f480b64d12ac4d41 (diff)
parent96a66ada2e11420aeaf90df37100d67796c0bdf5 (diff)
Merge pull request #69 from delroth/mmio-interface
Redesign of the MMIO access interface
Diffstat (limited to 'Source/Core/VideoCommon/CommandProcessor.cpp')
-rw-r--r--Source/Core/VideoCommon/CommandProcessor.cpp456
1 files changed, 159 insertions, 297 deletions
diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp
index b52be51865..ca70a43703 100644
--- a/Source/Core/VideoCommon/CommandProcessor.cpp
+++ b/Source/Core/VideoCommon/CommandProcessor.cpp
@@ -19,6 +19,7 @@
#include "HW/Memmap.h"
#include "HW/SystemTimers.h"
#include "Core.h"
+#include "HW/MMIO.h"
namespace CommandProcessor
{
@@ -33,10 +34,10 @@ UCPStatusReg m_CPStatusReg;
UCPCtrlReg m_CPCtrlReg;
UCPClearReg m_CPClearReg;
-int m_bboxleft;
-int m_bboxtop;
-int m_bboxright;
-int m_bboxbottom;
+u16 m_bboxleft;
+u16 m_bboxtop;
+u16 m_bboxright;
+u16 m_bboxbottom;
u16 m_tokenReg;
static bool bProcessFifoToLoWatermark = false;
@@ -131,307 +132,168 @@ void Init()
et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper);
}
-void Read16(u16& _rReturnValue, const u32 _Address)
+void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
- INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
- switch (_Address & 0xFFF)
+ struct {
+ u32 addr;
+ u16* ptr;
+ bool readonly;
+ bool writes_align_to_32_bytes;
+ } directly_mapped_vars[] = {
+ { FIFO_TOKEN_REGISTER, &m_tokenReg },
+
+ // Bounding box registers are read only.
+ { FIFO_BOUNDING_BOX_LEFT, &m_bboxleft, true },
+ { FIFO_BOUNDING_BOX_RIGHT, &m_bboxright, true },
+ { FIFO_BOUNDING_BOX_TOP, &m_bboxtop, true },
+ { FIFO_BOUNDING_BOX_BOTTOM, &m_bboxbottom, true },
+
+ // Some FIFO addresses need to be aligned on 32 bytes on write - only
+ // the high part can be written directly without a mask.
+ { FIFO_BASE_LO, MMIO::Utils::LowPart(&fifo.CPBase), false, true },
+ { FIFO_BASE_HI, MMIO::Utils::HighPart(&fifo.CPBase) },
+ { FIFO_END_LO, MMIO::Utils::LowPart(&fifo.CPEnd), false, true },
+ { FIFO_END_HI, MMIO::Utils::HighPart(&fifo.CPEnd) },
+ { FIFO_HI_WATERMARK_LO, MMIO::Utils::LowPart(&fifo.CPHiWatermark) },
+ { FIFO_HI_WATERMARK_HI, MMIO::Utils::HighPart(&fifo.CPHiWatermark) },
+ { FIFO_LO_WATERMARK_LO, MMIO::Utils::LowPart(&fifo.CPLoWatermark) },
+ { FIFO_LO_WATERMARK_HI, MMIO::Utils::HighPart(&fifo.CPLoWatermark) },
+ // FIFO_RW_DISTANCE has some complex read code different for
+ // single/dual core.
+ { FIFO_WRITE_POINTER_LO, MMIO::Utils::LowPart(&fifo.CPWritePointer), false, true },
+ { FIFO_WRITE_POINTER_HI, MMIO::Utils::HighPart(&fifo.CPWritePointer) },
+ // FIFO_READ_POINTER has different code for single/dual core.
+ { FIFO_BP_LO, MMIO::Utils::LowPart(&fifo.CPBreakpoint), false, true },
+ { FIFO_BP_HI, MMIO::Utils::HighPart(&fifo.CPBreakpoint) },
+ };
+ for (auto& mapped_var : directly_mapped_vars)
{
- case STATUS_REGISTER:
- SetCpStatusRegister();
- _rReturnValue = m_CPStatusReg.Hex;
- return;
- case CTRL_REGISTER: _rReturnValue = m_CPCtrlReg.Hex; return;
- case CLEAR_REGISTER:
- _rReturnValue = m_CPClearReg.Hex;
- PanicAlert("CommandProcessor:: CPU reads from CLEAR_REGISTER!");
- ERROR_LOG(COMMANDPROCESSOR, "(r) clear: 0x%04x", _rReturnValue);
- return;
- case FIFO_TOKEN_REGISTER: _rReturnValue = m_tokenReg; return;
- case FIFO_BOUNDING_BOX_LEFT: _rReturnValue = m_bboxleft; return;
- case FIFO_BOUNDING_BOX_RIGHT: _rReturnValue = m_bboxright; return;
- case FIFO_BOUNDING_BOX_TOP: _rReturnValue = m_bboxtop; return;
- case FIFO_BOUNDING_BOX_BOTTOM: _rReturnValue = m_bboxbottom; return;
-
- case FIFO_BASE_LO: _rReturnValue = ReadLow (fifo.CPBase); return;
- case FIFO_BASE_HI: _rReturnValue = ReadHigh(fifo.CPBase); return;
- case FIFO_END_LO: _rReturnValue = ReadLow (fifo.CPEnd); return;
- case FIFO_END_HI: _rReturnValue = ReadHigh(fifo.CPEnd); return;
- case FIFO_HI_WATERMARK_LO: _rReturnValue = ReadLow (fifo.CPHiWatermark); return;
- case FIFO_HI_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPHiWatermark); return;
- case FIFO_LO_WATERMARK_LO: _rReturnValue = ReadLow (fifo.CPLoWatermark); return;
- case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
-
- case FIFO_RW_DISTANCE_LO:
- 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:
- 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:
- _rReturnValue = ReadLow (fifo.CPWritePointer);
- DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue);
- return;
- case FIFO_WRITE_POINTER_HI:
- _rReturnValue = ReadHigh(fifo.CPWritePointer);
- DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue);
- return;
- case FIFO_READ_POINTER_LO:
- if (IsOnThread())
- _rReturnValue = ReadLow (fifo.SafeCPReadPointer);
- else
- _rReturnValue = ReadLow (fifo.CPReadPointer);
- DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_READ_POINTER_LO : %04x", _rReturnValue);
- return;
- case FIFO_READ_POINTER_HI:
- if (IsOnThread())
- _rReturnValue = ReadHigh (fifo.SafeCPReadPointer);
- else
- _rReturnValue = ReadHigh (fifo.CPReadPointer);
- DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_READ_POINTER_HI : %04x", _rReturnValue);
- return;
-
- case FIFO_BP_LO: _rReturnValue = ReadLow (fifo.CPBreakpoint); return;
- case FIFO_BP_HI: _rReturnValue = ReadHigh(fifo.CPBreakpoint); return;
-
- case XF_RASBUSY_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_RASBUSY_L: %04x", _rReturnValue);
- return;
- case XF_RASBUSY_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_RASBUSY_H: %04x", _rReturnValue);
- return;
-
- case XF_CLKS_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_CLKS_L: %04x", _rReturnValue);
- return;
- case XF_CLKS_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_CLKS_H: %04x", _rReturnValue);
- return;
-
- case XF_WAIT_IN_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_IN_L: %04x", _rReturnValue);
- return;
- case XF_WAIT_IN_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_IN_H: %04x", _rReturnValue);
- return;
-
- case XF_WAIT_OUT_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_OUT_L: %04x", _rReturnValue);
- return;
- case XF_WAIT_OUT_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_OUT_H: %04x", _rReturnValue);
- return;
-
- case VCACHE_METRIC_CHECK_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_CHECK_L: %04x", _rReturnValue);
- return;
- case VCACHE_METRIC_CHECK_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_CHECK_H: %04x", _rReturnValue);
- return;
-
- case VCACHE_METRIC_MISS_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_MISS_L: %04x", _rReturnValue);
- return;
- case VCACHE_METRIC_MISS_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_MISS_H: %04x", _rReturnValue);
- return;
-
- case VCACHE_METRIC_STALL_L:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_STALL_L: %04x", _rReturnValue);
- return;
- case VCACHE_METRIC_STALL_H:
- _rReturnValue = 0; // TODO: Figure out the true value
- DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_STALL_H: %04x", _rReturnValue);
- return;
-
- case CLKS_PER_VTX_OUT:
- _rReturnValue = 4; //Number of clocks per vertex.. TODO: Calculate properly
- DEBUG_LOG(COMMANDPROCESSOR, "Read from CLKS_PER_VTX_OUT: %04x", _rReturnValue);
- return;
- default:
- _rReturnValue = 0;
- WARN_LOG(COMMANDPROCESSOR, "(r16) unknown CP reg @ %08x", _Address);
- return;
+ u16 wmask = mapped_var.writes_align_to_32_bytes ? 0xFFE0 : 0xFFFF;
+ mmio->Register(base | mapped_var.addr,
+ MMIO::DirectRead<u16>(mapped_var.ptr),
+ mapped_var.readonly
+ ? MMIO::InvalidWrite<u16>()
+ : MMIO::DirectWrite<u16>(mapped_var.ptr, wmask)
+ );
}
- return;
-}
-
-void Write16(const u16 _Value, const u32 _Address)
-{
- INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
-
- switch (_Address & 0xFFF)
+ // Timing and metrics MMIOs are stubbed with fixed values.
+ struct {
+ u32 addr;
+ u16 value;
+ } metrics_mmios[] = {
+ { XF_RASBUSY_L, 0 },
+ { XF_RASBUSY_H, 0 },
+ { XF_CLKS_L, 0 },
+ { XF_CLKS_H, 0 },
+ { XF_WAIT_IN_L, 0 },
+ { XF_WAIT_IN_H, 0 },
+ { XF_WAIT_OUT_L, 0 },
+ { XF_WAIT_OUT_H, 0 },
+ { VCACHE_METRIC_CHECK_L, 0 },
+ { VCACHE_METRIC_CHECK_H, 0 },
+ { VCACHE_METRIC_MISS_L, 0 },
+ { VCACHE_METRIC_MISS_H, 0 },
+ { VCACHE_METRIC_STALL_L, 0 },
+ { VCACHE_METRIC_STALL_H, 0 },
+ { CLKS_PER_VTX_OUT, 4 },
+ };
+ for (auto& metrics_mmio : metrics_mmios)
{
- case STATUS_REGISTER:
- {
- // This should be Read-Only
- ERROR_LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value);
- PanicAlert("CommandProcessor:: CPU writes to STATUS_REGISTER!");
- }
- break;
+ mmio->Register(base | metrics_mmio.addr,
+ MMIO::Constant<u16>(metrics_mmio.value),
+ MMIO::InvalidWrite<u16>()
+ );
+ }
- case CTRL_REGISTER:
- {
- UCPCtrlReg tmpCtrl(_Value);
- m_CPCtrlReg.Hex = tmpCtrl.Hex;
- INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value);
+ mmio->Register(base | STATUS_REGISTER,
+ MMIO::ComplexRead<u16>([](u32) {
+ SetCpStatusRegister();
+ return m_CPStatusReg.Hex;
+ }),
+ MMIO::InvalidWrite<u16>()
+ );
+
+ mmio->Register(base | CTRL_REGISTER,
+ MMIO::DirectRead<u16>(&m_CPCtrlReg.Hex),
+ MMIO::ComplexWrite<u16>([](u32, u16 val) {
+ UCPCtrlReg tmp(val);
+ m_CPCtrlReg.Hex = tmp.Hex;
SetCpControlRegister();
- }
- break;
-
- case CLEAR_REGISTER:
- {
- UCPClearReg tmpCtrl(_Value);
- m_CPClearReg.Hex = tmpCtrl.Hex;
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to CLEAR_REGISTER : %04x", _Value);
+ if (!IsOnThread())
+ RunGpu();
+ })
+ );
+
+ mmio->Register(base | CLEAR_REGISTER,
+ MMIO::DirectRead<u16>(&m_CPClearReg.Hex),
+ MMIO::ComplexWrite<u16>([](u32, u16 val) {
+ UCPClearReg tmp(val);
+ m_CPClearReg.Hex = tmp.Hex;
SetCpClearRegister();
- }
- break;
-
- case PERF_SELECT:
- // Seems to select which set of perf registers should be exposed.
- DEBUG_LOG(COMMANDPROCESSOR, "Write to PERF_SELECT: %04x", _Value);
- break;
-
- // Fifo Registers
- case FIFO_TOKEN_REGISTER:
- m_tokenReg = _Value;
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_TOKEN_REGISTER : %04x", _Value);
- break;
- case FIFO_BASE_LO:
- WriteLow ((u32 &)fifo.CPBase, _Value & 0xFFE0);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_BASE_LO : %04x", _Value);
- break;
- case FIFO_BASE_HI:
- WriteHigh((u32 &)fifo.CPBase, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_BASE_HI : %04x", _Value);
- break;
-
- case FIFO_END_LO:
- WriteLow ((u32 &)fifo.CPEnd, _Value & 0xFFE0);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_END_LO : %04x", _Value);
- break;
- case FIFO_END_HI:
- WriteHigh((u32 &)fifo.CPEnd, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_END_HI : %04x", _Value);
- break;
-
- case FIFO_WRITE_POINTER_LO:
- WriteLow ((u32 &)fifo.CPWritePointer, _Value & 0xFFE0);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_WRITE_POINTER_LO : %04x", _Value);
- break;
- case FIFO_WRITE_POINTER_HI:
- WriteHigh((u32 &)fifo.CPWritePointer, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_WRITE_POINTER_HI : %04x", _Value);
- break;
-
- case FIFO_READ_POINTER_LO:
- WriteLow ((u32 &)fifo.CPReadPointer, _Value & 0xFFE0);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_READ_POINTER_LO : %04x", _Value);
- 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;
-
- case FIFO_HI_WATERMARK_LO:
- WriteLow ((u32 &)fifo.CPHiWatermark, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_HI_WATERMARK_LO : %04x", _Value);
- break;
- case FIFO_HI_WATERMARK_HI:
- WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_HI_WATERMARK_HI : %04x", _Value);
- break;
-
- case FIFO_LO_WATERMARK_LO:
- WriteLow ((u32 &)fifo.CPLoWatermark, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_LO_WATERMARK_LO : %04x", _Value);
- break;
- case FIFO_LO_WATERMARK_HI:
- WriteHigh((u32 &)fifo.CPLoWatermark, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_LO_WATERMARK_HI : %04x", _Value);
- break;
-
- case FIFO_BP_LO:
- WriteLow ((u32 &)fifo.CPBreakpoint, _Value & 0xFFE0);
- DEBUG_LOG(COMMANDPROCESSOR,"Write to FIFO_BP_LO : %04x", _Value);
- break;
- case FIFO_BP_HI:
- WriteHigh((u32 &)fifo.CPBreakpoint, _Value);
- DEBUG_LOG(COMMANDPROCESSOR,"Write to FIFO_BP_HI : %04x", _Value);
- break;
-
- case FIFO_RW_DISTANCE_HI:
- WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value);
- if (fifo.CPReadWriteDistance == 0)
- {
- GPFifo::ResetGatherPipe();
- ResetVideoBuffer();
- }
- else
- {
- ResetVideoBuffer();
- }
- 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;
-
- default:
- WARN_LOG(COMMANDPROCESSOR, "(w16) unknown CP reg write %04x @ %08x", _Value, _Address);
- }
-
- if (!IsOnThread())
- RunGpu();
-}
-
-void Read32(u32& _rReturnValue, const u32 _Address)
-{
- _rReturnValue = 0;
- _dbg_assert_msg_(COMMANDPROCESSOR, 0, "Read32 from CommandProccessor at 0x%08x", _Address);
-}
-
-void Write32(const u32 _Data, const u32 _Address)
-{
- _dbg_assert_msg_(COMMANDPROCESSOR, 0, "Write32 at CommandProccessor at 0x%08x", _Address);
+ if (!IsOnThread())
+ RunGpu();
+ })
+ );
+
+ mmio->Register(base | PERF_SELECT,
+ MMIO::InvalidRead<u16>(),
+ MMIO::Nop<u16>()
+ );
+
+ // Some MMIOs have different handlers for single core vs. dual core mode.
+ mmio->Register(base | FIFO_RW_DISTANCE_LO,
+ IsOnThread()
+ ? MMIO::ComplexRead<u16>([](u32) {
+ if (fifo.CPWritePointer >= fifo.SafeCPReadPointer)
+ return ReadLow(fifo.CPWritePointer - fifo.SafeCPReadPointer);
+ else
+ return ReadLow(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
+ })
+ : MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance)),
+ MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadWriteDistance), 0xFFE0)
+ );
+ mmio->Register(base | FIFO_RW_DISTANCE_HI,
+ IsOnThread()
+ ? MMIO::ComplexRead<u16>([](u32) {
+ if (fifo.CPWritePointer >= fifo.SafeCPReadPointer)
+ return ReadHigh(fifo.CPWritePointer - fifo.SafeCPReadPointer);
+ else
+ return ReadHigh(fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
+ })
+ : MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&fifo.CPReadWriteDistance)),
+ MMIO::ComplexWrite<u16>([](u32, u16 val) {
+ WriteHigh(fifo.CPReadWriteDistance, val);
+ if (fifo.CPReadWriteDistance == 0)
+ {
+ GPFifo::ResetGatherPipe();
+ ResetVideoBuffer();
+ }
+ else
+ {
+ ResetVideoBuffer();
+ }
+ if (!IsOnThread())
+ RunGpu();
+ })
+ );
+ mmio->Register(base | FIFO_READ_POINTER_LO,
+ IsOnThread()
+ ? MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.SafeCPReadPointer))
+ : MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer)),
+ MMIO::DirectWrite<u16>(MMIO::Utils::LowPart(&fifo.CPReadPointer), 0xFFE0)
+ );
+ mmio->Register(base | FIFO_READ_POINTER_HI,
+ IsOnThread()
+ ? MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&fifo.SafeCPReadPointer))
+ : MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&fifo.CPReadPointer)),
+ IsOnThread()
+ ? MMIO::ComplexWrite<u16>([](u32, u16 val) {
+ WriteHigh(fifo.CPReadPointer, val);
+ fifo.SafeCPReadPointer = fifo.CPReadPointer;
+ })
+ : MMIO::DirectWrite<u16>(MMIO::Utils::HighPart(&fifo.CPReadPointer))
+ );
}
void STACKALIGN GatherPipeBursted()