Fixes to the software plugin command processor. Made it easy to use the command processor in place of the one in video common. Use frame skip setting from the application in the software plugin instead of the internal frame skipping config setting. The WGP does not loop if the write pointer is set beyond the end of the fifo.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4527 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
c2a4e33313
commit
52da977c73
|
@ -80,14 +80,10 @@ void STACKALIGN CheckGatherPipe()
|
||||||
memcpy(m_gatherPipe, m_gatherPipe + GATHER_PIPE_SIZE, m_gatherPipeCount);
|
memcpy(m_gatherPipe, m_gatherPipe + GATHER_PIPE_SIZE, m_gatherPipeCount);
|
||||||
|
|
||||||
// increase the CPUWritePointer
|
// increase the CPUWritePointer
|
||||||
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
|
if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd)
|
||||||
|
|
||||||
if (ProcessorInterface::Fifo_CPUWritePointer > ProcessorInterface::Fifo_CPUEnd)
|
|
||||||
_assert_msg_(DYNA_REC, 0, "Fifo_CPUWritePointer out of bounds: %08x (end = %08x)",
|
|
||||||
ProcessorInterface::Fifo_CPUWritePointer, ProcessorInterface::Fifo_CPUEnd);
|
|
||||||
|
|
||||||
if (ProcessorInterface::Fifo_CPUWritePointer >= ProcessorInterface::Fifo_CPUEnd)
|
|
||||||
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
|
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
|
||||||
|
else
|
||||||
|
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
|
||||||
|
|
||||||
// TODO store video plugin pointer
|
// TODO store video plugin pointer
|
||||||
CPluginManager::GetInstance().GetVideo()->Video_GatherPipeBursted();
|
CPluginManager::GetInstance().GetVideo()->Video_GatherPipeBursted();
|
||||||
|
|
|
@ -17,16 +17,33 @@
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "pluginspecs_video.h"
|
#include "pluginspecs_video.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
#include "Atomic.h"
|
||||||
|
|
||||||
#include "CommandProcessor.h"
|
#include "CommandProcessor.h"
|
||||||
#include "OpcodeDecoder.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "ChunkFile.h"
|
#include "ChunkFile.h"
|
||||||
#include "MathUtil.h"
|
#include "MathUtil.h"
|
||||||
|
|
||||||
|
volatile bool g_bSkipCurrentFrame;
|
||||||
|
bool fifoStateRun;
|
||||||
|
|
||||||
u8* g_pVideoData; // data reader uses this as the read pointer
|
// set to 0 if using in video common
|
||||||
|
#define SW_PLUGIN 1
|
||||||
|
|
||||||
|
#if (SW_PLUGIN)
|
||||||
|
|
||||||
|
#include "OpcodeDecoder.h"
|
||||||
|
#include "main.h"
|
||||||
|
u8* g_pVideoData;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "VideoConfig.h"
|
||||||
|
#include "OpcodeDecoding.h"
|
||||||
|
#include "VideoCommon.h"
|
||||||
|
extern u8* g_pVideoData;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace CommandProcessor
|
namespace CommandProcessor
|
||||||
{
|
{
|
||||||
|
@ -40,17 +57,18 @@ enum
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
// variables
|
// variables
|
||||||
|
|
||||||
const int commandBufferSize = 4 * 1024;
|
const int commandBufferSize = 1024 * 1024;
|
||||||
const int commandBufferCopySize = 32;
|
const int maxCommandBufferWrite = commandBufferSize - GATHER_PIPE_SIZE;
|
||||||
const int maxCommandBufferWrite = commandBufferSize - commandBufferCopySize;
|
|
||||||
u8 commandBuffer[commandBufferSize];
|
u8 commandBuffer[commandBufferSize];
|
||||||
u32 readPos;
|
u32 readPos;
|
||||||
u32 writePos;
|
u32 writePos;
|
||||||
bool interruptSet;
|
|
||||||
int et_UpdateInterrupts;
|
int et_UpdateInterrupts;
|
||||||
|
volatile bool interruptSet;
|
||||||
|
volatile bool interruptWaiting;
|
||||||
|
|
||||||
CPReg cpreg; // shared between gfx and emulator thread
|
CPReg cpreg; // shared between gfx and emulator thread
|
||||||
|
|
||||||
|
Common::CriticalSection criticalSection;
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +85,12 @@ inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
|
||||||
|
|
||||||
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
UpdateInterrupts();
|
UpdateInterrupts(userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool AtBreakpoint()
|
||||||
|
{
|
||||||
|
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
|
@ -93,8 +116,10 @@ void Init()
|
||||||
writePos = 0;
|
writePos = 0;
|
||||||
|
|
||||||
interruptSet = false;
|
interruptSet = false;
|
||||||
|
interruptWaiting = false;
|
||||||
|
|
||||||
g_pVideoData = 0;
|
g_pVideoData = 0;
|
||||||
|
g_bSkipCurrentFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
|
@ -112,7 +137,7 @@ void RunGpu()
|
||||||
// run the opcode decoder
|
// run the opcode decoder
|
||||||
do {
|
do {
|
||||||
RunBuffer();
|
RunBuffer();
|
||||||
} while (cpreg.ctrl.GPReadEnable && !cpreg.status.Breakpoint && cpreg.rwdistance >= commandBufferCopySize);
|
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
||||||
|
|
||||||
LoadSSEState();
|
LoadSSEState();
|
||||||
}
|
}
|
||||||
|
@ -120,9 +145,10 @@ void RunGpu()
|
||||||
|
|
||||||
void Read16(u16& _rReturnValue, const u32 _Address)
|
void Read16(u16& _rReturnValue, const u32 _Address)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
|
|
||||||
|
|
||||||
u32 regAddr = (_Address & 0xFFF) >> 1;
|
u32 regAddr = (_Address & 0xFFF) >> 1;
|
||||||
|
|
||||||
|
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
|
||||||
|
|
||||||
if (regAddr < 0x20)
|
if (regAddr < 0x20)
|
||||||
_rReturnValue = ((u16*)&cpreg)[regAddr];
|
_rReturnValue = ((u16*)&cpreg)[regAddr];
|
||||||
else
|
else
|
||||||
|
@ -137,16 +163,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
{
|
{
|
||||||
case STATUS_REGISTER:
|
case STATUS_REGISTER:
|
||||||
{
|
{
|
||||||
UCPStatusReg tmpStatus(_Value);
|
ERROR_LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value);
|
||||||
|
|
||||||
if (cpreg.status.Breakpoint != tmpStatus.Breakpoint)
|
|
||||||
INFO_LOG(COMMANDPROCESSOR,"Set breakpoint status by writing to STATUS_REGISTER");
|
|
||||||
|
|
||||||
cpreg.status.Hex = _Value;
|
|
||||||
|
|
||||||
INFO_LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value);
|
|
||||||
|
|
||||||
UpdateInterrupts();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -154,13 +171,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
{
|
{
|
||||||
cpreg.ctrl.Hex = _Value;
|
cpreg.ctrl.Hex = _Value;
|
||||||
|
|
||||||
// clear breakpoint if BPEnable and CPIntEnable are 0
|
|
||||||
if (!cpreg.ctrl.BPEnable) {
|
|
||||||
if (!cpreg.ctrl.BreakPointIntEnable) {
|
|
||||||
cpreg.status.Breakpoint = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || BPIntEnable %s | OvF %s | UndF %s"
|
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || BPIntEnable %s | OvF %s | UndF %s"
|
||||||
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
|
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
|
||||||
|
@ -170,9 +180,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
|
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
|
||||||
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
|
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
|
||||||
);
|
);
|
||||||
|
|
||||||
UpdateInterrupts();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -186,8 +193,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
cpreg.status.UnderflowLoWatermark = 0;
|
cpreg.status.UnderflowLoWatermark = 0;
|
||||||
|
|
||||||
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
|
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
|
||||||
|
|
||||||
UpdateInterrupts();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -198,7 +203,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_BASE_LO:
|
case FIFO_BASE_LO:
|
||||||
WriteLow ((u32 &)cpreg.fifobase, _Value);
|
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO. FIFO base is : %08x", cpreg.fifobase);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO. FIFO base is : %08x", cpreg.fifobase);
|
||||||
break;
|
break;
|
||||||
case FIFO_BASE_HI:
|
case FIFO_BASE_HI:
|
||||||
|
@ -206,7 +211,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI. FIFO base is : %08x", cpreg.fifobase);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI. FIFO base is : %08x", cpreg.fifobase);
|
||||||
break;
|
break;
|
||||||
case FIFO_END_LO:
|
case FIFO_END_LO:
|
||||||
WriteLow ((u32 &)cpreg.fifoend, _Value);
|
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO. FIFO end is : %08x", cpreg.fifoend);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO. FIFO end is : %08x", cpreg.fifoend);
|
||||||
break;
|
break;
|
||||||
case FIFO_END_HI:
|
case FIFO_END_HI:
|
||||||
|
@ -215,7 +220,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_WRITE_POINTER_LO:
|
case FIFO_WRITE_POINTER_LO:
|
||||||
WriteLow ((u32 &)cpreg.writeptr, _Value);
|
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO. write ptr is : %08x", cpreg.writeptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO. write ptr is : %08x", cpreg.writeptr);
|
||||||
break;
|
break;
|
||||||
case FIFO_WRITE_POINTER_HI:
|
case FIFO_WRITE_POINTER_HI:
|
||||||
|
@ -223,7 +228,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI. write ptr is : %08x", cpreg.writeptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI. write ptr is : %08x", cpreg.writeptr);
|
||||||
break;
|
break;
|
||||||
case FIFO_READ_POINTER_LO:
|
case FIFO_READ_POINTER_LO:
|
||||||
WriteLow ((u32 &)cpreg.readptr, _Value);
|
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO. read ptr is : %08x", cpreg.readptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO. read ptr is : %08x", cpreg.readptr);
|
||||||
break;
|
break;
|
||||||
case FIFO_READ_POINTER_HI:
|
case FIFO_READ_POINTER_HI:
|
||||||
|
@ -249,7 +254,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_BP_LO:
|
case FIFO_BP_LO:
|
||||||
WriteLow ((u32 &)cpreg.breakpt, _Value);
|
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpt is : %08x", cpreg.breakpt);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpt is : %08x", cpreg.breakpt);
|
||||||
break;
|
break;
|
||||||
case FIFO_BP_HI:
|
case FIFO_BP_HI:
|
||||||
|
@ -257,12 +262,8 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpt is : %08x", cpreg.breakpt);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpt is : %08x", cpreg.breakpt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Super monkey try to overwrite CPReadWriteDistance by an old saved RWD value. Which is lame for us.
|
|
||||||
// hack: We have to force CPU to think fifo is alway empty and on idle.
|
|
||||||
// When we fall here CPReadWriteDistance should be always null and the game should always want to overwrite it by 0.
|
|
||||||
// So, we can skip it.
|
|
||||||
case FIFO_RW_DISTANCE_LO:
|
case FIFO_RW_DISTANCE_LO:
|
||||||
WriteLow ((u32 &)cpreg.rwdistance, _Value);
|
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_LO. rwdistance is : %08x", cpreg.rwdistance);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_LO. rwdistance is : %08x", cpreg.rwdistance);
|
||||||
break;
|
break;
|
||||||
case FIFO_RW_DISTANCE_HI:
|
case FIFO_RW_DISTANCE_HI:
|
||||||
|
@ -289,105 +290,106 @@ void STACKALIGN GatherPipeBursted()
|
||||||
{
|
{
|
||||||
if (cpreg.ctrl.GPLinkEnable)
|
if (cpreg.ctrl.GPLinkEnable)
|
||||||
{
|
{
|
||||||
cpreg.writeptr += GATHER_PIPE_SIZE;
|
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
|
||||||
if (cpreg.writeptr >= (cpreg.fifoend & 0xFFFFFFE0))
|
|
||||||
cpreg.writeptr = cpreg.fifobase;
|
|
||||||
|
|
||||||
// the read/write pointers will be managed in RunGpu which will read the current fifo and
|
if (cpreg.writeptr == cpreg.fifoend)
|
||||||
// send as much data as is available and the plugin can take
|
cpreg.writeptr = cpreg.fifobase;
|
||||||
// this will have the cost of copying data to the plugin fifo buffer in the main thread
|
else
|
||||||
|
cpreg.writeptr += GATHER_PIPE_SIZE;
|
||||||
|
|
||||||
|
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunGpu();
|
RunGpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterrupts()
|
void UpdateInterrupts(u64 userdata)
|
||||||
{
|
{
|
||||||
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
if (userdata)
|
||||||
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
|
||||||
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
|
|
||||||
|
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "\tUpdate Interrupts");
|
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "\tBreakPointIntEnable %s | BP %s | OvF %s | UndF %s"
|
|
||||||
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
|
|
||||||
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
|
|
||||||
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
|
|
||||||
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
|
|
||||||
);
|
|
||||||
|
|
||||||
interruptSet = bpInt || ovfInt || undfInt;
|
|
||||||
|
|
||||||
if (interruptSet)
|
|
||||||
{
|
{
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"Interrupt set");
|
interruptSet = true;
|
||||||
|
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, true);
|
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
interruptSet = false;
|
||||||
|
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
||||||
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, false);
|
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, false);
|
||||||
}
|
}
|
||||||
|
interruptWaiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterruptsFromVideoPlugin()
|
void UpdateInterruptsFromVideoPlugin(u64 userdata)
|
||||||
{
|
{
|
||||||
g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, 0);
|
g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadFifo()
|
void ReadFifo()
|
||||||
{
|
{
|
||||||
cpreg.status.ReadIdle = 0;
|
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < maxCommandBufferWrite;
|
||||||
|
bool atBreakpoint = AtBreakpoint();
|
||||||
// update rwdistance
|
|
||||||
u32 writePtr = cpreg.writeptr;
|
|
||||||
if (cpreg.readptr <= writePtr)
|
|
||||||
cpreg.rwdistance = writePtr - cpreg.readptr;
|
|
||||||
else
|
|
||||||
cpreg.rwdistance = ((cpreg.fifoend & 0xFFFFFFE0) - cpreg.fifobase) - (cpreg.readptr - writePtr);
|
|
||||||
|
|
||||||
// overflow check
|
|
||||||
cpreg.status.OverflowHiWatermark = cpreg.rwdistance < cpreg.hiwatermark?0:1;
|
|
||||||
|
|
||||||
|
if (canRead && !atBreakpoint)
|
||||||
|
{
|
||||||
// read from fifo
|
// read from fifo
|
||||||
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(cpreg.readptr);
|
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(cpreg.readptr);
|
||||||
|
int bytesRead = 0;
|
||||||
|
|
||||||
u32 readptr = cpreg.readptr;
|
do
|
||||||
u32 distance = cpreg.rwdistance;
|
{
|
||||||
|
// copy to buffer
|
||||||
|
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
|
||||||
|
writePos += GATHER_PIPE_SIZE;
|
||||||
|
bytesRead += GATHER_PIPE_SIZE;
|
||||||
|
|
||||||
while (distance >= commandBufferCopySize && !cpreg.status.Breakpoint && writePos < maxCommandBufferWrite)
|
if (cpreg.readptr == cpreg.fifoend)
|
||||||
{
|
{
|
||||||
// check for breakpoint
|
cpreg.readptr = cpreg.fifobase;
|
||||||
// todo - check if this is precise enough
|
ptr = g_VideoInitialize.pGetMemoryPointer(cpreg.readptr);
|
||||||
if (cpreg.ctrl.BPEnable && (cpreg.breakpt & 0xFFFFFFE0) == (readptr & 0xFFFFFFE0))
|
|
||||||
{
|
|
||||||
cpreg.status.Breakpoint = 1;
|
|
||||||
DEBUG_LOG(VIDEO,"Hit breakpoint at %x", readptr);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// copy to buffer
|
cpreg.readptr += GATHER_PIPE_SIZE;
|
||||||
memcpy(&commandBuffer[writePos], ptr, commandBufferCopySize);
|
ptr += GATHER_PIPE_SIZE;
|
||||||
writePos += commandBufferCopySize;
|
|
||||||
ptr += commandBufferCopySize;
|
|
||||||
readptr += commandBufferCopySize;
|
|
||||||
distance -= commandBufferCopySize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readptr >= (cpreg.fifoend & 0xFFFFFFE0))
|
canRead = cpreg.readptr != cpreg.writeptr && writePos < maxCommandBufferWrite;
|
||||||
{
|
atBreakpoint = AtBreakpoint();
|
||||||
readptr = cpreg.fifobase;
|
} while (canRead && !atBreakpoint);
|
||||||
ptr = g_VideoInitialize.pGetMemoryPointer(readptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lock read pointer until rw distance is updated?
|
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
|
||||||
cpreg.readptr = readptr;
|
}
|
||||||
cpreg.rwdistance = distance;
|
}
|
||||||
|
|
||||||
|
void SetStatus()
|
||||||
|
{
|
||||||
|
// overflow check
|
||||||
|
if (cpreg.rwdistance > cpreg.hiwatermark)
|
||||||
|
cpreg.status.OverflowHiWatermark = 1;
|
||||||
|
|
||||||
// underflow check
|
// underflow check
|
||||||
cpreg.status.UnderflowLoWatermark = cpreg.rwdistance > cpreg.lowatermark?0:1;
|
if (cpreg.rwdistance < cpreg.lowatermark)
|
||||||
|
cpreg.status.UnderflowLoWatermark = 1;
|
||||||
|
|
||||||
cpreg.status.ReadIdle = 1;
|
// breakpoint
|
||||||
|
if (cpreg.ctrl.BPEnable)
|
||||||
|
{
|
||||||
|
if (cpreg.breakpt == cpreg.readptr)
|
||||||
|
{
|
||||||
|
if (!cpreg.status.Breakpoint)
|
||||||
|
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
|
||||||
|
cpreg.status.Breakpoint = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cpreg.status.Breakpoint)
|
||||||
|
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
|
||||||
|
cpreg.status.Breakpoint = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
|
||||||
|
|
||||||
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
||||||
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
||||||
|
@ -395,10 +397,16 @@ void ReadFifo()
|
||||||
|
|
||||||
bool interrupt = bpInt || ovfInt || undfInt;
|
bool interrupt = bpInt || ovfInt || undfInt;
|
||||||
|
|
||||||
if (interrupt != interruptSet)
|
if (interrupt != interruptSet && !interruptWaiting)
|
||||||
{
|
{
|
||||||
interruptSet = interrupt;
|
u64 userdata = interrupt?1:0;
|
||||||
UpdateInterruptsFromVideoPlugin();
|
if (g_VideoInitialize.bOnThread)
|
||||||
|
{
|
||||||
|
interruptWaiting = true;
|
||||||
|
CommandProcessor::UpdateInterruptsFromVideoPlugin(userdata);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CommandProcessor::UpdateInterrupts(userdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,11 +417,15 @@ bool RunBuffer()
|
||||||
if (cpreg.ctrl.GPReadEnable)
|
if (cpreg.ctrl.GPReadEnable)
|
||||||
ReadFifo();
|
ReadFifo();
|
||||||
|
|
||||||
|
SetStatus();
|
||||||
|
|
||||||
|
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
||||||
|
|
||||||
g_pVideoData = &commandBuffer[readPos];
|
g_pVideoData = &commandBuffer[readPos];
|
||||||
|
|
||||||
u32 availableBytes = writePos - readPos;
|
u32 availableBytes = writePos - readPos;
|
||||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
|
||||||
|
|
||||||
|
#if (SW_PLUGIN)
|
||||||
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
||||||
{
|
{
|
||||||
cpreg.status.CommandIdle = 0;
|
cpreg.status.CommandIdle = 0;
|
||||||
|
@ -425,11 +437,18 @@ bool RunBuffer()
|
||||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
_dbg_assert_(VIDEO, writePos >= readPos);
|
||||||
availableBytes = writePos - readPos;
|
availableBytes = writePos - readPos;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
cpreg.status.CommandIdle = 0;
|
||||||
|
OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||||
|
|
||||||
|
// if data was read by the opcode decoder then the video data pointer changed
|
||||||
|
readPos = g_pVideoData - &commandBuffer[0];
|
||||||
|
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
||||||
|
availableBytes = writePos - readPos;
|
||||||
|
#endif
|
||||||
|
|
||||||
cpreg.status.CommandIdle = 1;
|
cpreg.status.CommandIdle = 1;
|
||||||
|
|
||||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
|
||||||
|
|
||||||
bool ranDecoder = false;
|
bool ranDecoder = false;
|
||||||
|
|
||||||
// move data remaing in command buffer
|
// move data remaing in command buffer
|
||||||
|
@ -446,3 +465,66 @@ bool RunBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace CommandProcessor
|
} // end of namespace CommandProcessor
|
||||||
|
|
||||||
|
|
||||||
|
// fifo functions
|
||||||
|
#if (SW_PLUGIN)
|
||||||
|
|
||||||
|
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||||
|
{
|
||||||
|
fifoStateRun = true;
|
||||||
|
|
||||||
|
while (fifoStateRun)
|
||||||
|
{
|
||||||
|
g_VideoInitialize.pPeekMessages();
|
||||||
|
if (!CommandProcessor::RunBuffer()) {
|
||||||
|
Common::YieldCPU();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||||
|
{
|
||||||
|
fifoStateRun = true;
|
||||||
|
|
||||||
|
while (fifoStateRun)
|
||||||
|
{
|
||||||
|
g_VideoInitialize.pPeekMessages();
|
||||||
|
if (g_ActiveConfig.bEFBAccessEnable)
|
||||||
|
VideoFifo_CheckEFBAccess();
|
||||||
|
VideoFifo_CheckSwapRequest();
|
||||||
|
|
||||||
|
if (!CommandProcessor::RunBuffer()) {
|
||||||
|
Common::YieldCPU();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Fifo_ExitLoop()
|
||||||
|
{
|
||||||
|
fifoStateRun = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fifo_SetRendering(bool enabled)
|
||||||
|
{
|
||||||
|
g_bSkipCurrentFrame = !enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for compatibility with video common
|
||||||
|
void Fifo_Init() {}
|
||||||
|
void Fifo_Shutdown() {}
|
||||||
|
void Fifo_DoState(PointerWrap &p) {}
|
||||||
|
|
||||||
|
u8* FAKE_GetFifoStartPtr()
|
||||||
|
{
|
||||||
|
return CommandProcessor::commandBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* FAKE_GetFifoEndPtr()
|
||||||
|
{
|
||||||
|
return &CommandProcessor::commandBuffer[CommandProcessor::writePos];
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,22 @@
|
||||||
#include "pluginspecs_video.h"
|
#include "pluginspecs_video.h"
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
|
extern volatile bool g_bSkipCurrentFrame;
|
||||||
|
|
||||||
|
// for compatibility with video common
|
||||||
|
void Fifo_Init();
|
||||||
|
void Fifo_Shutdown();
|
||||||
|
void Fifo_DoState(PointerWrap &p);
|
||||||
|
|
||||||
|
void Fifo_EnterLoop(const SVideoInitialize &video_initialize);
|
||||||
|
void Fifo_ExitLoop();
|
||||||
|
void Fifo_SetRendering(bool bEnabled);
|
||||||
|
|
||||||
|
// Implemented by the Video Plugin
|
||||||
|
void VideoFifo_CheckSwapRequest();
|
||||||
|
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||||
|
void VideoFifo_CheckEFBAccess();
|
||||||
|
|
||||||
namespace CommandProcessor
|
namespace CommandProcessor
|
||||||
{
|
{
|
||||||
// internal hardware addresses
|
// internal hardware addresses
|
||||||
|
@ -76,11 +92,11 @@ namespace CommandProcessor
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned GPReadEnable : 1;
|
unsigned GPReadEnable : 1;
|
||||||
unsigned BreakPointIntEnable : 1;
|
unsigned BPEnable : 1;
|
||||||
unsigned FifoOverflowIntEnable : 1;
|
unsigned FifoOverflowIntEnable : 1;
|
||||||
unsigned FifoUnderflowIntEnable : 1;
|
unsigned FifoUnderflowIntEnable : 1;
|
||||||
unsigned GPLinkEnable : 1;
|
unsigned GPLinkEnable : 1;
|
||||||
unsigned BPEnable : 1;
|
unsigned BreakPointIntEnable : 1;
|
||||||
unsigned : 10;
|
unsigned : 10;
|
||||||
};
|
};
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
|
@ -134,6 +150,7 @@ namespace CommandProcessor
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
|
||||||
bool RunBuffer();
|
bool RunBuffer();
|
||||||
|
void RunGpu();
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
void Read16(u16& _rReturnValue, const u32 _Address);
|
void Read16(u16& _rReturnValue, const u32 _Address);
|
||||||
|
@ -143,8 +160,8 @@ namespace CommandProcessor
|
||||||
|
|
||||||
// for CGPFIFO
|
// for CGPFIFO
|
||||||
void GatherPipeBursted();
|
void GatherPipeBursted();
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts(u64 userdata);
|
||||||
void UpdateInterruptsFromVideoPlugin();
|
void UpdateInterruptsFromVideoPlugin(u64 userdata);
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace CommandProcessor
|
} // end of namespace CommandProcessor
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "HwRasterizer.h"
|
#include "HwRasterizer.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
#include "CommandProcessor.h"
|
||||||
#include "../../../Core/VideoCommon/Src/ImageWrite.h"
|
#include "../../../Core/VideoCommon/Src/ImageWrite.h"
|
||||||
|
|
||||||
namespace DebugUtil
|
namespace DebugUtil
|
||||||
|
@ -162,7 +163,7 @@ void DrawObjectBuffer(s16 x, s16 y, u8 *color, int buffer, const char *name)
|
||||||
|
|
||||||
void OnObjectBegin()
|
void OnObjectBegin()
|
||||||
{
|
{
|
||||||
if (!g_SkipFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (g_Config.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
if (g_Config.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
||||||
DumpActiveTextures();
|
DumpActiveTextures();
|
||||||
|
@ -174,7 +175,7 @@ void OnObjectBegin()
|
||||||
|
|
||||||
void OnObjectEnd()
|
void OnObjectEnd()
|
||||||
{
|
{
|
||||||
if (!g_SkipFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (g_Config.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
if (g_Config.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
|
||||||
DumpEfb(StringFromFormat("%s/object%i.tga", FULL_FRAMES_DIR, stats.thisFrame.numDrawnObjects).c_str());
|
DumpEfb(StringFromFormat("%s/object%i.tga", FULL_FRAMES_DIR, stats.thisFrame.numDrawnObjects).c_str());
|
||||||
|
@ -199,7 +200,7 @@ void OnObjectEnd()
|
||||||
|
|
||||||
void OnFrameEnd()
|
void OnFrameEnd()
|
||||||
{
|
{
|
||||||
if (!g_SkipFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (g_Config.bDumpFrames)
|
if (g_Config.bDumpFrames)
|
||||||
{
|
{
|
||||||
|
@ -207,9 +208,6 @@ void OnFrameEnd()
|
||||||
DumpDepth(StringFromFormat("%s/frame%i_depth.tga", FULL_FRAMES_DIR, stats.frameCount).c_str());
|
DumpDepth(StringFromFormat("%s/frame%i_depth.tga", FULL_FRAMES_DIR, stats.frameCount).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_SkipFrame = skipFrames > 0;
|
|
||||||
skipFrames = g_SkipFrame?(skipFrames-1):g_Config.nFrameSkip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -25,6 +25,7 @@
|
||||||
#include "VideoConfig.h"
|
#include "VideoConfig.h"
|
||||||
#include "DebugUtil.h"
|
#include "DebugUtil.h"
|
||||||
#include "HwRasterizer.h"
|
#include "HwRasterizer.h"
|
||||||
|
#include "CommandProcessor.h"
|
||||||
|
|
||||||
|
|
||||||
namespace EfbCopy
|
namespace EfbCopy
|
||||||
|
@ -73,7 +74,7 @@ namespace EfbCopy
|
||||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||||
DebugUtil::OnFrameEnd();
|
DebugUtil::OnFrameEnd();
|
||||||
|
|
||||||
if (!g_SkipFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||||
{
|
{
|
||||||
|
@ -95,5 +96,13 @@ namespace EfbCopy
|
||||||
ClearEfb();
|
ClearEfb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||||
|
{
|
||||||
|
// no frame rendered but tell that a frame has finished for frame skip counter
|
||||||
|
g_VideoInitialize.pCopiedToXFB(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "DebugUtil.h"
|
#include "DebugUtil.h"
|
||||||
|
#include "CommandProcessor.h"
|
||||||
|
|
||||||
typedef void (*DecodingFunction)(u32);
|
typedef void (*DecodingFunction)(u32);
|
||||||
DecodingFunction currentFunction = NULL;
|
DecodingFunction currentFunction = NULL;
|
||||||
|
@ -47,7 +48,7 @@ void DecodePrimitiveStream(u32 iBufferSize)
|
||||||
{
|
{
|
||||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||||
|
|
||||||
if(g_SkipFrame)
|
if(g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,8 +36,6 @@ Config::Config()
|
||||||
|
|
||||||
bHwRasterizer = false;
|
bHwRasterizer = false;
|
||||||
|
|
||||||
nFrameSkip = 0;
|
|
||||||
|
|
||||||
drawStart = 0;
|
drawStart = 0;
|
||||||
drawEnd = 100000;
|
drawEnd = 100000;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,6 @@ struct Config
|
||||||
|
|
||||||
bool bHwRasterizer;
|
bool bHwRasterizer;
|
||||||
|
|
||||||
u32 nFrameSkip;
|
|
||||||
|
|
||||||
u32 drawStart;
|
u32 drawStart;
|
||||||
u32 drawEnd;
|
u32 drawEnd;
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,7 @@
|
||||||
|
|
||||||
|
|
||||||
PLUGIN_GLOBALS* globals = NULL;
|
PLUGIN_GLOBALS* globals = NULL;
|
||||||
static volatile bool fifoStateRun = false;
|
|
||||||
SVideoInitialize g_VideoInitialize;
|
SVideoInitialize g_VideoInitialize;
|
||||||
bool g_SkipFrame;
|
|
||||||
|
|
||||||
|
|
||||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||||
|
@ -76,8 +74,6 @@ void Initialize(void *init)
|
||||||
SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
|
SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
|
||||||
g_VideoInitialize = *_pVideoInitialize;
|
g_VideoInitialize = *_pVideoInitialize;
|
||||||
|
|
||||||
g_SkipFrame = false;
|
|
||||||
|
|
||||||
g_Config.Load();
|
g_Config.Load();
|
||||||
|
|
||||||
InitBPMemory();
|
InitBPMemory();
|
||||||
|
@ -158,20 +154,12 @@ void Video_Screenshot(const char *_szFilename)
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
void Video_EnterLoop()
|
void Video_EnterLoop()
|
||||||
{
|
{
|
||||||
fifoStateRun = true;
|
Fifo_EnterLoop(g_VideoInitialize);
|
||||||
|
|
||||||
while (fifoStateRun)
|
|
||||||
{
|
|
||||||
g_VideoInitialize.pPeekMessages();
|
|
||||||
if (!CommandProcessor::RunBuffer()) {
|
|
||||||
Common::SleepCurrentThread(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video_ExitLoop()
|
void Video_ExitLoop()
|
||||||
{
|
{
|
||||||
fifoStateRun = false;
|
Fifo_ExitLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||||
|
@ -180,6 +168,7 @@ void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||||
|
|
||||||
void Video_SetRendering(bool bEnabled)
|
void Video_SetRendering(bool bEnabled)
|
||||||
{
|
{
|
||||||
|
Fifo_SetRendering(bEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
|
void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
|
||||||
|
|
|
@ -22,6 +22,4 @@
|
||||||
|
|
||||||
extern SVideoInitialize g_VideoInitialize;
|
extern SVideoInitialize g_VideoInitialize;
|
||||||
|
|
||||||
extern bool g_SkipFrame;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue