1
// Copyright 2013 Dolphin Emulator Project
2
// Licensed under GPLv2
3
// Refer to the license.txt file included.
6
#include "VideoCommon.h"
7
#include "VideoConfig.h"
12
#include "ChunkFile.h"
13
#include "CommandProcessor.h"
14
#include "PixelEngine.h"
15
#include "CoreTiming.h"
16
#include "ConfigManager.h"
17
#include "HW/ProcessorInterface.h"
18
#include "HW/GPFifo.h"
19
#include "HW/Memmap.h"
21
#include "HW/SystemTimers.h"
24
namespace CommandProcessor
27
int et_UpdateInterrupts;
29
// TODO(ector): Warn on bbox read/write
33
UCPStatusReg m_CPStatusReg;
34
UCPCtrlReg m_CPCtrlReg;
35
UCPClearReg m_CPClearReg;
43
static bool bProcessFifoToLoWatermark = false;
44
static bool bProcessFifoAllDistance = false;
46
volatile bool isPossibleWaitingSetDrawDone = false;
47
volatile bool isHiWatermarkActive = false;
48
volatile bool isLoWatermarkActive = false;
49
volatile bool interruptSet= false;
50
volatile bool interruptWaiting= false;
51
volatile bool interruptTokenWaiting = false;
52
volatile bool interruptFinishWaiting = false;
54
volatile u32 VITicks = CommandProcessor::m_cpClockOrigin;
58
return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread;
61
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
63
UpdateInterrupts(userdata);
66
void DoState(PointerWrap &p)
68
p.DoPOD(m_CPStatusReg);
70
p.DoPOD(m_CPClearReg);
78
p.Do(bProcessFifoToLoWatermark);
79
p.Do(bProcessFifoAllDistance);
80
p.Do(isHiWatermarkActive);
81
p.Do(isLoWatermarkActive);
82
p.Do(isPossibleWaitingSetDrawDone);
84
p.Do(interruptWaiting);
85
p.Do(interruptTokenWaiting);
86
p.Do(interruptFinishWaiting);
89
inline void WriteLow (volatile u32& _reg, u16 lowbits) {Common::AtomicStore(_reg,(_reg & 0xFFFF0000) | lowbits);}
90
inline void WriteHigh(volatile u32& _reg, u16 highbits) {Common::AtomicStore(_reg,(_reg & 0x0000FFFF) | ((u32)highbits << 16));}
92
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
93
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
97
m_CPStatusReg.Hex = 0;
98
m_CPStatusReg.CommandIdle = 1;
99
m_CPStatusReg.ReadIdle = 1;
103
m_CPClearReg.Hex = 0;
112
memset(&fifo,0,sizeof(fifo));
115
fifo.bFF_Breakpoint = 0;
116
fifo.bFF_HiWatermark = 0;
117
fifo.bFF_HiWatermarkInt = 0;
118
fifo.bFF_LoWatermark = 0;
119
fifo.bFF_LoWatermarkInt = 0;
121
interruptSet = false;
122
interruptWaiting = false;
123
interruptFinishWaiting = false;
124
interruptTokenWaiting = false;
126
bProcessFifoToLoWatermark = false;
127
bProcessFifoAllDistance = false;
128
isPossibleWaitingSetDrawDone = false;
129
isHiWatermarkActive = false;
130
isLoWatermarkActive = false;
132
et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper);
135
void Read16(u16& _rReturnValue, const u32 _Address)
137
INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
138
switch (_Address & 0xFFF)
140
case STATUS_REGISTER:
141
SetCpStatusRegister();
142
_rReturnValue = m_CPStatusReg.Hex;
144
case CTRL_REGISTER: _rReturnValue = m_CPCtrlReg.Hex; return;
146
_rReturnValue = m_CPClearReg.Hex;
147
PanicAlert("CommandProcessor:: CPU reads from CLEAR_REGISTER!");
148
ERROR_LOG(COMMANDPROCESSOR, "(r) clear: 0x%04x", _rReturnValue);
150
case FIFO_TOKEN_REGISTER: _rReturnValue = m_tokenReg; return;
151
case FIFO_BOUNDING_BOX_LEFT: _rReturnValue = m_bboxleft; return;
152
case FIFO_BOUNDING_BOX_RIGHT: _rReturnValue = m_bboxright; return;
153
case FIFO_BOUNDING_BOX_TOP: _rReturnValue = m_bboxtop; return;
154
case FIFO_BOUNDING_BOX_BOTTOM: _rReturnValue = m_bboxbottom; return;
156
case FIFO_BASE_LO: _rReturnValue = ReadLow (fifo.CPBase); return;
157
case FIFO_BASE_HI: _rReturnValue = ReadHigh(fifo.CPBase); return;
158
case FIFO_END_LO: _rReturnValue = ReadLow (fifo.CPEnd); return;
159
case FIFO_END_HI: _rReturnValue = ReadHigh(fifo.CPEnd); return;
160
case FIFO_HI_WATERMARK_LO: _rReturnValue = ReadLow (fifo.CPHiWatermark); return;
161
case FIFO_HI_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPHiWatermark); return;
162
case FIFO_LO_WATERMARK_LO: _rReturnValue = ReadLow (fifo.CPLoWatermark); return;
163
case FIFO_LO_WATERMARK_HI: _rReturnValue = ReadHigh(fifo.CPLoWatermark); return;
165
case FIFO_RW_DISTANCE_LO:
168
if(fifo.CPWritePointer >= fifo.SafeCPReadPointer)
169
_rReturnValue = ReadLow (fifo.CPWritePointer - fifo.SafeCPReadPointer);
171
_rReturnValue = ReadLow (fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
175
_rReturnValue = ReadLow (fifo.CPReadWriteDistance);
177
DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_RW_DISTANCE_LO : %04x", _rReturnValue);
179
case FIFO_RW_DISTANCE_HI:
182
if(fifo.CPWritePointer >= fifo.SafeCPReadPointer)
183
_rReturnValue = ReadHigh (fifo.CPWritePointer - fifo.SafeCPReadPointer);
185
_rReturnValue = ReadHigh (fifo.CPEnd - fifo.SafeCPReadPointer + fifo.CPWritePointer - fifo.CPBase + 32);
189
_rReturnValue = ReadHigh(fifo.CPReadWriteDistance);
191
DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_RW_DISTANCE_HI : %04x", _rReturnValue);
193
case FIFO_WRITE_POINTER_LO:
194
_rReturnValue = ReadLow (fifo.CPWritePointer);
195
DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_WRITE_POINTER_LO : %04x", _rReturnValue);
197
case FIFO_WRITE_POINTER_HI:
198
_rReturnValue = ReadHigh(fifo.CPWritePointer);
199
DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_WRITE_POINTER_HI : %04x", _rReturnValue);
201
case FIFO_READ_POINTER_LO:
203
_rReturnValue = ReadLow (fifo.SafeCPReadPointer);
205
_rReturnValue = ReadLow (fifo.CPReadPointer);
206
DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_READ_POINTER_LO : %04x", _rReturnValue);
208
case FIFO_READ_POINTER_HI:
210
_rReturnValue = ReadHigh (fifo.SafeCPReadPointer);
212
_rReturnValue = ReadHigh (fifo.CPReadPointer);
213
DEBUG_LOG(COMMANDPROCESSOR, "Read FIFO_READ_POINTER_HI : %04x", _rReturnValue);
216
case FIFO_BP_LO: _rReturnValue = ReadLow (fifo.CPBreakpoint); return;
217
case FIFO_BP_HI: _rReturnValue = ReadHigh(fifo.CPBreakpoint); return;
220
_rReturnValue = 0; // TODO: Figure out the true value
221
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_RASBUSY_L: %04x", _rReturnValue);
224
_rReturnValue = 0; // TODO: Figure out the true value
225
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_RASBUSY_H: %04x", _rReturnValue);
229
_rReturnValue = 0; // TODO: Figure out the true value
230
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_CLKS_L: %04x", _rReturnValue);
233
_rReturnValue = 0; // TODO: Figure out the true value
234
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_CLKS_H: %04x", _rReturnValue);
238
_rReturnValue = 0; // TODO: Figure out the true value
239
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_IN_L: %04x", _rReturnValue);
242
_rReturnValue = 0; // TODO: Figure out the true value
243
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_IN_H: %04x", _rReturnValue);
247
_rReturnValue = 0; // TODO: Figure out the true value
248
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_OUT_L: %04x", _rReturnValue);
251
_rReturnValue = 0; // TODO: Figure out the true value
252
DEBUG_LOG(COMMANDPROCESSOR, "Read from XF_WAIT_OUT_H: %04x", _rReturnValue);
255
case VCACHE_METRIC_CHECK_L:
256
_rReturnValue = 0; // TODO: Figure out the true value
257
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_CHECK_L: %04x", _rReturnValue);
259
case VCACHE_METRIC_CHECK_H:
260
_rReturnValue = 0; // TODO: Figure out the true value
261
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_CHECK_H: %04x", _rReturnValue);
264
case VCACHE_METRIC_MISS_L:
265
_rReturnValue = 0; // TODO: Figure out the true value
266
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_MISS_L: %04x", _rReturnValue);
268
case VCACHE_METRIC_MISS_H:
269
_rReturnValue = 0; // TODO: Figure out the true value
270
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_MISS_H: %04x", _rReturnValue);
273
case VCACHE_METRIC_STALL_L:
274
_rReturnValue = 0; // TODO: Figure out the true value
275
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_STALL_L: %04x", _rReturnValue);
277
case VCACHE_METRIC_STALL_H:
278
_rReturnValue = 0; // TODO: Figure out the true value
279
DEBUG_LOG(COMMANDPROCESSOR, "Read from VCACHE_METRIC_STALL_H: %04x", _rReturnValue);
282
case CLKS_PER_VTX_OUT:
283
_rReturnValue = 4; //Number of clocks per vertex.. TODO: Calculate properly
284
DEBUG_LOG(COMMANDPROCESSOR, "Read from CLKS_PER_VTX_OUT: %04x", _rReturnValue);
288
WARN_LOG(COMMANDPROCESSOR, "(r16) unknown CP reg @ %08x", _Address);
295
void Write16(const u16 _Value, const u32 _Address)
297
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
299
switch (_Address & 0xFFF)
301
case STATUS_REGISTER:
303
// This should be Read-Only
304
ERROR_LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value);
305
PanicAlert("CommandProcessor:: CPU writes to STATUS_REGISTER!");
311
UCPCtrlReg tmpCtrl(_Value);
312
m_CPCtrlReg.Hex = tmpCtrl.Hex;
313
INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value);
314
SetCpControlRegister();
320
UCPClearReg tmpCtrl(_Value);
321
m_CPClearReg.Hex = tmpCtrl.Hex;
322
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to CLEAR_REGISTER : %04x", _Value);
323
SetCpClearRegister();
328
// Seems to select which set of perf registers should be exposed.
329
DEBUG_LOG(COMMANDPROCESSOR, "Write to PERF_SELECT: %04x", _Value);
333
case FIFO_TOKEN_REGISTER:
335
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_TOKEN_REGISTER : %04x", _Value);
338
WriteLow ((u32 &)fifo.CPBase, _Value & 0xFFE0);
339
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_BASE_LO : %04x", _Value);
342
WriteHigh((u32 &)fifo.CPBase, _Value);
343
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_BASE_HI : %04x", _Value);
347
WriteLow ((u32 &)fifo.CPEnd, _Value & 0xFFE0);
348
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_END_LO : %04x", _Value);
351
WriteHigh((u32 &)fifo.CPEnd, _Value);
352
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_END_HI : %04x", _Value);
355
case FIFO_WRITE_POINTER_LO:
356
WriteLow ((u32 &)fifo.CPWritePointer, _Value & 0xFFE0);
357
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_WRITE_POINTER_LO : %04x", _Value);
359
case FIFO_WRITE_POINTER_HI:
360
WriteHigh((u32 &)fifo.CPWritePointer, _Value);
361
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_WRITE_POINTER_HI : %04x", _Value);
364
case FIFO_READ_POINTER_LO:
365
WriteLow ((u32 &)fifo.CPReadPointer, _Value & 0xFFE0);
366
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_READ_POINTER_LO : %04x", _Value);
368
case FIFO_READ_POINTER_HI:
369
WriteHigh((u32 &)fifo.CPReadPointer, _Value);
370
fifo.SafeCPReadPointer = fifo.CPReadPointer;
371
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_READ_POINTER_HI : %04x", _Value);
374
case FIFO_HI_WATERMARK_LO:
375
WriteLow ((u32 &)fifo.CPHiWatermark, _Value);
376
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_HI_WATERMARK_LO : %04x", _Value);
378
case FIFO_HI_WATERMARK_HI:
379
WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
380
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_HI_WATERMARK_HI : %04x", _Value);
383
case FIFO_LO_WATERMARK_LO:
384
WriteLow ((u32 &)fifo.CPLoWatermark, _Value);
385
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_LO_WATERMARK_LO : %04x", _Value);
387
case FIFO_LO_WATERMARK_HI:
388
WriteHigh((u32 &)fifo.CPLoWatermark, _Value);
389
DEBUG_LOG(COMMANDPROCESSOR,"\t Write to FIFO_LO_WATERMARK_HI : %04x", _Value);
393
WriteLow ((u32 &)fifo.CPBreakpoint, _Value & 0xFFE0);
394
DEBUG_LOG(COMMANDPROCESSOR,"Write to FIFO_BP_LO : %04x", _Value);
397
WriteHigh((u32 &)fifo.CPBreakpoint, _Value);
398
DEBUG_LOG(COMMANDPROCESSOR,"Write to FIFO_BP_HI : %04x", _Value);
401
case FIFO_RW_DISTANCE_HI:
402
WriteHigh((u32 &)fifo.CPReadWriteDistance, _Value);
403
if (fifo.CPReadWriteDistance == 0)
405
GPFifo::ResetGatherPipe();
412
IncrementCheckContextId();
413
DEBUG_LOG(COMMANDPROCESSOR,"Try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
415
case FIFO_RW_DISTANCE_LO:
416
WriteLow((u32 &)fifo.CPReadWriteDistance, _Value & 0xFFE0);
417
DEBUG_LOG(COMMANDPROCESSOR,"Try to write to FIFO_RW_DISTANCE_LO : %04x", _Value);
421
WARN_LOG(COMMANDPROCESSOR, "(w16) unknown CP reg write %04x @ %08x", _Value, _Address);
428
void Read32(u32& _rReturnValue, const u32 _Address)
431
_dbg_assert_msg_(COMMANDPROCESSOR, 0, "Read32 from CommandProccessor at 0x%08x", _Address);
434
void Write32(const u32 _Data, const u32 _Address)
436
_dbg_assert_msg_(COMMANDPROCESSOR, 0, "Write32 at CommandProccessor at 0x%08x", _Address);
439
void STACKALIGN GatherPipeBursted()
442
// if we aren't linked, we don't care about gather pipe data
443
if (!m_CPCtrlReg.GPLinkEnable)
451
// In multibuffer mode is not allowed write in the same FIFO attached to the GPU.
452
// Fix Pokemon XD in DC mode.
453
if((ProcessorInterface::Fifo_CPUEnd == fifo.CPEnd) && (ProcessorInterface::Fifo_CPUBase == fifo.CPBase)
454
&& fifo.CPReadWriteDistance > 0)
456
ProcessFifoAllDistance();
465
// update the fifo pointer
466
if (fifo.CPWritePointer >= fifo.CPEnd)
467
fifo.CPWritePointer = fifo.CPBase;
469
fifo.CPWritePointer += GATHER_PIPE_SIZE;
471
Common::AtomicAdd(fifo.CPReadWriteDistance, GATHER_PIPE_SIZE);
476
_assert_msg_(COMMANDPROCESSOR, fifo.CPReadWriteDistance <= fifo.CPEnd - fifo.CPBase,
477
"FIFO is overflowed by GatherPipe !\nCPU thread is too fast!");
479
// check if we are in sync
480
_assert_msg_(COMMANDPROCESSOR, fifo.CPWritePointer == ProcessorInterface::Fifo_CPUWritePointer, "FIFOs linked but out of sync");
481
_assert_msg_(COMMANDPROCESSOR, fifo.CPBase == ProcessorInterface::Fifo_CPUBase, "FIFOs linked but out of sync");
482
_assert_msg_(COMMANDPROCESSOR, fifo.CPEnd == ProcessorInterface::Fifo_CPUEnd, "FIFOs linked but out of sync");
485
void UpdateInterrupts(u64 userdata)
490
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
491
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
495
interruptSet = false;
496
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
497
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
499
interruptWaiting = false;
502
void UpdateInterruptsFromVideoBackend(u64 userdata)
504
CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata);
507
// This is called by the ProcessorInterface when PI_FIFO_RESET is written to.
513
void SetCpStatus(bool isCPUThread)
515
// overflow & underflow check
516
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
517
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
522
if (fifo.bFF_BPEnable)
524
if (fifo.CPBreakpoint == fifo.CPReadPointer)
526
if (!fifo.bFF_Breakpoint)
528
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
529
fifo.bFF_Breakpoint = true;
530
IncrementCheckContextId();
535
if (fifo.bFF_Breakpoint)
536
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
537
fifo.bFF_Breakpoint = false;
542
if (fifo.bFF_Breakpoint)
543
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
544
fifo.bFF_Breakpoint = false;
548
bool bpInt = fifo.bFF_Breakpoint && fifo.bFF_BPInt;
549
bool ovfInt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt;
550
bool undfInt = fifo.bFF_LoWatermark && fifo.bFF_LoWatermarkInt;
552
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
554
isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
555
isLoWatermarkActive = undfInt && m_CPCtrlReg.GPReadEnable;
557
if (interrupt != interruptSet && !interruptWaiting)
559
u64 userdata = interrupt?1:0;
562
if (!interrupt || bpInt || undfInt || ovfInt)
567
interruptWaiting = true;
568
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
573
interruptSet = interrupt;
574
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
575
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt);
581
CommandProcessor::UpdateInterrupts(userdata);
586
void ProcessFifoToLoWatermark()
590
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
591
fifo.CPReadWriteDistance > fifo.CPLoWatermark && !AtBreakpoint())
594
bProcessFifoToLoWatermark = false;
597
void ProcessFifoAllDistance()
601
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
602
fifo.CPReadWriteDistance && !AtBreakpoint())
605
bProcessFifoAllDistance = false;
608
void ProcessFifoEvents()
610
if (IsOnThread() && (interruptWaiting || interruptFinishWaiting || interruptTokenWaiting))
611
CoreTiming::ProcessFifoWaitEvents();
619
void SetCpStatusRegister()
621
// Here always there is one fifo attached to the GPU
622
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
623
m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || (fifo.CPReadPointer == fifo.CPWritePointer);
624
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || !fifo.bFF_GPReadEnable;
625
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
626
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
628
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
629
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
630
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
631
, m_CPStatusReg.ReadIdle ? "ON" : "OFF"
632
, m_CPStatusReg.CommandIdle ? "ON" : "OFF"
633
, m_CPStatusReg.OverflowHiWatermark ? "ON" : "OFF"
634
, m_CPStatusReg.UnderflowLoWatermark ? "ON" : "OFF"
638
void SetCpControlRegister()
640
// If the new fifo is being attached, force an exception check
641
// This fixes the hang while booting Eternal Darkness
642
if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable)
644
CoreTiming::ForceExceptionCheck(0);
647
fifo.bFF_BPInt = m_CPCtrlReg.BPInt;
648
fifo.bFF_BPEnable = m_CPCtrlReg.BPEnable;
649
fifo.bFF_HiWatermarkInt = m_CPCtrlReg.FifoOverflowIntEnable;
650
fifo.bFF_LoWatermarkInt = m_CPCtrlReg.FifoUnderflowIntEnable;
651
fifo.bFF_GPLinkEnable = m_CPCtrlReg.GPLinkEnable;
653
if(m_CPCtrlReg.GPReadEnable && m_CPCtrlReg.GPLinkEnable)
655
ProcessorInterface::Fifo_CPUWritePointer = fifo.CPWritePointer;
656
ProcessorInterface::Fifo_CPUBase = fifo.CPBase;
657
ProcessorInterface::Fifo_CPUEnd = fifo.CPEnd;
660
if(fifo.bFF_GPReadEnable && !m_CPCtrlReg.GPReadEnable)
662
fifo.bFF_GPReadEnable = m_CPCtrlReg.GPReadEnable;
663
while(fifo.isGpuReadingData) Common::YieldCPU();
667
fifo.bFF_GPReadEnable = m_CPCtrlReg.GPReadEnable;
670
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | BP %s | Int %s | OvF %s | UndF %s | LINK %s"
671
, fifo.bFF_GPReadEnable ? "ON" : "OFF"
672
, fifo.bFF_BPEnable ? "ON" : "OFF"
673
, fifo.bFF_BPInt ? "ON" : "OFF"
674
, m_CPCtrlReg.FifoOverflowIntEnable ? "ON" : "OFF"
675
, m_CPCtrlReg.FifoUnderflowIntEnable ? "ON" : "OFF"
676
, m_CPCtrlReg.GPLinkEnable ? "ON" : "OFF"
681
// NOTE: The implementation of this function should be correct, but we intentionally aren't using it at the moment.
682
// We don't emulate proper GP timing anyway at the moment, so this code would just slow down emulation.
683
void SetCpClearRegister()
687
// if (!m_CPClearReg.ClearFifoUnderflow && m_CPClearReg.ClearFifoOverflow)
688
// bProcessFifoToLoWatermark = true;
694
while (VITicks > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread())
697
if (fifo.isGpuReadingData)
698
Common::AtomicAdd(VITicks, SystemTimers::GetTicksPerSecond() / 10000);
700
} // end of namespace CommandProcessor