Skip to content

Commit

Permalink
FifoAnalyzer: Unify DecodeOp/DecodeCommand
Browse files Browse the repository at this point in the history
We actually discovered a bug while combining the two functions with
FifoRecordAnalzyer's vertex array loading code. If per-vertex
postion or texture matrices were enabled and vertex arrays in use
then the wrong data would be used to calculate the minimum/maxmium
indices, which would result in either too much or too little vertex
data being included in the dff.

So this commit also increments the dff version number, so we can
identify old broken dffs later.
  • Loading branch information
phire committed Nov 23, 2015
1 parent 1656b27 commit 0367c31
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 212 deletions.
132 changes: 124 additions & 8 deletions Source/Core/Core/FifoPlayer/FifoAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/FifoPlayer/FifoAnalyzer.h"
#include "Core/FifoPlayer/FifoPlaybackAnalyzer.h"
#include "Core/FifoPlayer/FifoRecordAnalyzer.h"
#include "VideoCommon/OpcodeDecoding.h"
#include "VideoCommon/VertexLoader.h"
#include "VideoCommon/VertexLoader_Normal.h"
#include "VideoCommon/VertexLoader_Position.h"
Expand All @@ -16,6 +19,10 @@
namespace FifoAnalyzer
{

bool s_DrawingObject;
BPMemory s_BpMem;
FifoAnalyzer::CPMemory s_CpMem;

void Init()
{
VertexLoader_Normal::Init();
Expand All @@ -42,6 +49,123 @@ u32 ReadFifo32(u8*& data)
return value;
}

u32 AnalyzeCommand(u8* data, DecodeMode mode)
{
u8* dataStart = data;

int cmd = ReadFifo8(data);

switch (cmd)
{
case GX_NOP:
case 0x44:
case GX_CMD_INVL_VC:
break;

case GX_LOAD_CP_REG:
{
s_DrawingObject = false;

u32 cmd2 = ReadFifo8(data);
u32 value = ReadFifo32(data);
LoadCPReg(cmd2, value, s_CpMem);
break;
}

case GX_LOAD_XF_REG:
{
s_DrawingObject = false;

u32 cmd2 = ReadFifo32(data);
u8 streamSize = ((cmd2 >> 16) & 15) + 1;

data += streamSize * 4;
break;
}

case GX_LOAD_INDX_A:
case GX_LOAD_INDX_B:
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
{
s_DrawingObject = false;

int array = 0xc + (cmd - GX_LOAD_INDX_A) / 8;
u32 value = ReadFifo32(data);

if (mode == DECODE_RECORD)
FifoRecordAnalyzer::ProcessLoadIndexedXf(value, array);
break;
}

case GX_CMD_CALL_DL:
// The recorder should have expanded display lists into the fifo stream and skipped the call to start them
// That is done to make it easier to track where memory is updated
_assert_(false);
data += 8;
break;

case GX_LOAD_BP_REG:
{
s_DrawingObject = false;
u32 cmd2 = ReadFifo32(data);

if (mode == DECODE_PLAYBACK)
{
BPCmd bp = DecodeBPCmd(cmd2, s_BpMem);

LoadBPReg(bp, s_BpMem);

if (bp.address == BPMEM_TRIGGER_EFB_COPY)
{
FifoPlaybackAnalyzer::StoreEfbCopyRegion();
}
}
break;
}

default:
if (cmd & 0x80)
{
s_DrawingObject = true;

int sizes[21];
FifoAnalyzer::CalculateVertexElementSizes(sizes, cmd & GX_VAT_MASK, s_CpMem);

// Determine offset of each element that might be a vertex array
// The first 9 elements are never vertex arrays so we just accumulate their sizes.
int offsets[12];
int offset = std::accumulate(&sizes[0], &sizes[9], 0u);
for (int i = 0; i < 12; ++i)
{
offsets[i] = offset;
offset += sizes[i + 9];
}

int vertexSize = offset;
int numVertices = ReadFifo16(data);

if (mode == DECODE_RECORD && numVertices > 0)
{
for (int i = 0; i < 12; ++i)
{
FifoRecordAnalyzer::WriteVertexArray(i, data + offsets[i], vertexSize, numVertices);
}
}

data += numVertices * vertexSize;
}
else
{
PanicAlert("FifoPlayer: Unknown Opcode (0x%x).\n", cmd);
return 0;
}
break;
}

return (u32)(data - dataStart);
}

void InitBPMemory(BPMemory* bpMem)
{
memset(bpMem, 0, sizeof(BPMemory));
Expand Down Expand Up @@ -109,14 +233,6 @@ void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem)
}
}

u32 CalculateVertexSize(int vatIndex, const CPMemory& cpMem)
{
int sizes[21];
CalculateVertexElementSizes(sizes, vatIndex, cpMem);

return std::accumulate(std::begin(sizes), std::end(sizes), 0U);
}

void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory& cpMem)
{
const TVtxDesc &vtxDesc = cpMem.vtxDesc;
Expand Down
13 changes: 12 additions & 1 deletion Source/Core/Core/FifoPlayer/FifoAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ namespace FifoAnalyzer
u16 ReadFifo16(u8*& data);
u32 ReadFifo32(u8*& data);

enum DecodeMode
{
DECODE_RECORD,
DECODE_PLAYBACK,
};

u32 AnalyzeCommand(u8* data, DecodeMode mode);

// TODO- move to video common
void InitBPMemory(BPMemory* bpMem);
BPCmd DecodeBPCmd(u32 value, const BPMemory &bpMem);
Expand All @@ -32,6 +40,9 @@ namespace FifoAnalyzer

void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem);

u32 CalculateVertexSize(int vatIndex, const CPMemory& cpMem);
void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory& cpMem);

extern bool s_DrawingObject;
extern BPMemory s_BpMem;
extern FifoAnalyzer::CPMemory s_CpMem;
}
2 changes: 1 addition & 1 deletion Source/Core/Core/FifoPlayer/FifoFileStruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace FifoFileStruct
enum
{
FILE_ID = 0x0d01f1f0,
VERSION_NUMBER = 2,
VERSION_NUMBER = 3,
MIN_LOADER_VERSION = 1,
};

Expand Down
97 changes: 2 additions & 95 deletions Source/Core/Core/FifoPlayer/FifoPlaybackAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,8 @@ struct MemoryRange
};

static std::vector<MemoryRange> s_WrittenMemory;
static BPMemory s_BpMem;
static FifoAnalyzer::CPMemory s_CpMem;
static bool s_DrawingObject;

static void AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo& frameInfo);
static u32 DecodeCommand(u8* data);
static void StoreEfbCopyRegion();
static void StoreWrittenRegion(u32 address, u32 size);

void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file, std::vector<AnalyzedFrameInfo>& frameInfo)
Expand Down Expand Up @@ -84,7 +79,7 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file, std::vector<Analyze

bool wasDrawing = s_DrawingObject;

u32 cmdSize = DecodeCommand(&frame.fifoData[cmdStart]);
u32 cmdSize = FifoAnalyzer::AnalyzeCommand(&frame.fifoData[cmdStart], DECODE_PLAYBACK);

#if LOG_FIFO_CMDS
CmdData cmdData;
Expand Down Expand Up @@ -162,95 +157,7 @@ static void AddMemoryUpdate(MemoryUpdate memUpdate, AnalyzedFrameInfo& frameInfo
frameInfo.memoryUpdates.push_back(memUpdate);
}

static u32 DecodeCommand(u8* data)
{
u8* dataStart = data;

int cmd = ReadFifo8(data);

switch (cmd)
{
case GX_NOP:
case 0x44:
case GX_CMD_INVL_VC:
break;

case GX_LOAD_CP_REG:
{
s_DrawingObject = false;

u32 cmd2 = ReadFifo8(data);
u32 value = ReadFifo32(data);
FifoAnalyzer::LoadCPReg(cmd2, value, s_CpMem);
}
break;

case GX_LOAD_XF_REG:
{
s_DrawingObject = false;

u32 cmd2 = ReadFifo32(data);
u8 streamSize = ((cmd2 >> 16) & 15) + 1;

data += streamSize * 4;
}
break;

case GX_LOAD_INDX_A:
case GX_LOAD_INDX_B:
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
s_DrawingObject = false;
data += 4;
break;

case GX_CMD_CALL_DL:
// The recorder should have expanded display lists into the fifo stream and skipped the call to start them
// That is done to make it easier to track where memory is updated
_assert_(false);
data += 8;
break;

case GX_LOAD_BP_REG:
{
s_DrawingObject = false;

u32 cmd2 = ReadFifo32(data);
BPCmd bp = FifoAnalyzer::DecodeBPCmd(cmd2, s_BpMem);

FifoAnalyzer::LoadBPReg(bp, s_BpMem);

if (bp.address == BPMEM_TRIGGER_EFB_COPY)
{
StoreEfbCopyRegion();
}
}
break;

default:
if (cmd & 0x80)
{
s_DrawingObject = true;

u32 vtxAttrGroup = cmd & GX_VAT_MASK;
int vertexSize = FifoAnalyzer::CalculateVertexSize(vtxAttrGroup, s_CpMem);

u16 streamSize = ReadFifo16(data);

data += streamSize * vertexSize;
}
else
{
PanicAlert("FifoPlayer: Unknown Opcode (0x%x).\nAborting frame analysis.\n", cmd);
return 0;
}
break;
}

return (u32)(data - dataStart);
}

static void StoreEfbCopyRegion()
void FifoPlaybackAnalyzer::StoreEfbCopyRegion()
{
UPE_Copy peCopy = s_BpMem.triggerEFBCopy;

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/FifoPlayer/FifoPlaybackAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ struct AnalyzedFrameInfo
namespace FifoPlaybackAnalyzer
{
void AnalyzeFrames(FifoDataFile* file, std::vector<AnalyzedFrameInfo>& frameInfo);

void StoreEfbCopyRegion();
};

0 comments on commit 0367c31

Please sign in to comment.