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:
donkopunchstania 2009-11-11 03:14:38 +00:00
parent c2a4e33313
commit 52da977c73
10 changed files with 245 additions and 159 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,8 +36,6 @@ Config::Config()
bHwRasterizer = false; bHwRasterizer = false;
nFrameSkip = 0;
drawStart = 0; drawStart = 0;
drawEnd = 100000; drawEnd = 100000;
} }

View File

@ -42,8 +42,6 @@ struct Config
bool bHwRasterizer; bool bHwRasterizer;
u32 nFrameSkip;
u32 drawStart; u32 drawStart;
u32 drawEnd; u32 drawEnd;

View File

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

View File

@ -22,6 +22,4 @@
extern SVideoInitialize g_VideoInitialize; extern SVideoInitialize g_VideoInitialize;
extern bool g_SkipFrame;
#endif #endif