Merge pull request #9540 from Pokechu22/better-fifo-analyzer-part-2
Fifo analyzer quality of life improvements
This commit is contained in:
28 files changed
+918
-816
No files matched your search
@@ -258,37 +258,37 @@ u32 AnalyzeCommand(const u8* data, DecodeMode mode)
|
||||
|
||||
void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem)
|
||||
{
|
||||
switch (subCmd & 0xF0)
|
||||
switch (subCmd & CP_COMMAND_MASK)
|
||||
{
|
||||
case 0x50:
|
||||
case VCD_LO:
|
||||
cpMem.vtxDesc.low.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
case VCD_HI:
|
||||
cpMem.vtxDesc.high.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
ASSERT((subCmd & 0x0F) < 8);
|
||||
cpMem.vtxAttr[subCmd & 7].g0.Hex = value;
|
||||
case CP_VAT_REG_A:
|
||||
ASSERT(subCmd - CP_VAT_REG_A < CP_NUM_VAT_REG);
|
||||
cpMem.vtxAttr[subCmd & CP_VAT_MASK].g0.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
ASSERT((subCmd & 0x0F) < 8);
|
||||
cpMem.vtxAttr[subCmd & 7].g1.Hex = value;
|
||||
case CP_VAT_REG_B:
|
||||
ASSERT(subCmd - CP_VAT_REG_B < CP_NUM_VAT_REG);
|
||||
cpMem.vtxAttr[subCmd & CP_VAT_MASK].g1.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
ASSERT((subCmd & 0x0F) < 8);
|
||||
cpMem.vtxAttr[subCmd & 7].g2.Hex = value;
|
||||
case CP_VAT_REG_C:
|
||||
ASSERT(subCmd - CP_VAT_REG_C < CP_NUM_VAT_REG);
|
||||
cpMem.vtxAttr[subCmd & CP_VAT_MASK].g2.Hex = value;
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
cpMem.arrayBases[subCmd & 0xF] = value;
|
||||
case ARRAY_BASE:
|
||||
cpMem.arrayBases[subCmd & CP_ARRAY_MASK] = value;
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
cpMem.arrayStrides[subCmd & 0xF] = value & 0xFF;
|
||||
case ARRAY_STRIDE:
|
||||
cpMem.arrayStrides[subCmd & CP_ARRAY_MASK] = value & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ u32 AnalyzeCommand(const u8* data, DecodeMode mode);
|
||||
struct CPMemory
|
||||
{
|
||||
TVtxDesc vtxDesc;
|
||||
std::array<VAT, 8> vtxAttr;
|
||||
std::array<u32, 16> arrayBases;
|
||||
std::array<u32, 16> arrayStrides;
|
||||
std::array<VAT, CP_NUM_VAT_REG> vtxAttr;
|
||||
std::array<u32, CP_NUM_ARRAYS> arrayBases;
|
||||
std::array<u32, CP_NUM_ARRAYS> arrayStrides;
|
||||
};
|
||||
|
||||
void LoadCPReg(u32 subCmd, u32 value, CPMemory& cpMem);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/FifoPlayer/FifoAnalyzer.h"
|
||||
#include "Core/FifoPlayer/FifoDataFile.h"
|
||||
@@ -25,14 +26,14 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file,
|
||||
std::vector<AnalyzedFrameInfo>& frameInfo)
|
||||
{
|
||||
u32* cpMem = file->GetCPMem();
|
||||
FifoAnalyzer::LoadCPReg(0x50, cpMem[0x50], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(0x60, cpMem[0x60], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(VCD_LO, cpMem[VCD_LO], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(VCD_HI, cpMem[VCD_HI], s_CpMem);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
for (u32 i = 0; i < CP_NUM_VAT_REG; ++i)
|
||||
{
|
||||
FifoAnalyzer::LoadCPReg(0x70 + i, cpMem[0x70 + i], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(0x80 + i, cpMem[0x80 + i], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(0x90 + i, cpMem[0x90 + i], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(CP_VAT_REG_A + i, cpMem[CP_VAT_REG_A + i], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(CP_VAT_REG_B + i, cpMem[CP_VAT_REG_B + i], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(CP_VAT_REG_C + i, cpMem[CP_VAT_REG_C + i], s_CpMem);
|
||||
}
|
||||
|
||||
frameInfo.clear();
|
||||
@@ -80,6 +81,7 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file,
|
||||
{
|
||||
// Clean up frame analysis
|
||||
analyzed.objectStarts.clear();
|
||||
analyzed.objectCPStates.clear();
|
||||
analyzed.objectEnds.clear();
|
||||
|
||||
return;
|
||||
@@ -88,9 +90,14 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file,
|
||||
if (wasDrawing != s_DrawingObject)
|
||||
{
|
||||
if (s_DrawingObject)
|
||||
{
|
||||
analyzed.objectStarts.push_back(cmdStart);
|
||||
analyzed.objectCPStates.push_back(s_CpMem);
|
||||
}
|
||||
else
|
||||
{
|
||||
analyzed.objectEnds.push_back(cmdStart);
|
||||
}
|
||||
}
|
||||
|
||||
cmdStart += cmdSize;
|
||||
@@ -98,5 +105,8 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file,
|
||||
|
||||
if (analyzed.objectEnds.size() < analyzed.objectStarts.size())
|
||||
analyzed.objectEnds.push_back(cmdStart);
|
||||
|
||||
ASSERT(analyzed.objectStarts.size() == analyzed.objectCPStates.size());
|
||||
ASSERT(analyzed.objectStarts.size() == analyzed.objectEnds.size());
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Core/FifoPlayer/FifoAnalyzer.h"
|
||||
#include "Core/FifoPlayer/FifoDataFile.h"
|
||||
|
||||
struct AnalyzedFrameInfo
|
||||
{
|
||||
// Start of the primitives for the object (after previous update commands)
|
||||
std::vector<u32> objectStarts;
|
||||
std::vector<FifoAnalyzer::CPMemory> objectCPStates;
|
||||
// End of the primitives for the object
|
||||
std::vector<u32> objectEnds;
|
||||
std::vector<MemoryUpdate> memoryUpdates;
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ bool FifoPlayer::Open(const std::string& filename)
|
||||
{
|
||||
FifoPlaybackAnalyzer::AnalyzeFrames(m_File.get(), m_FrameInfo);
|
||||
|
||||
m_FrameRangeEnd = m_File->GetFrameCount();
|
||||
m_FrameRangeEnd = m_File->GetFrameCount() - 1;
|
||||
}
|
||||
|
||||
if (m_FileLoadedCb)
|
||||
@@ -131,13 +131,10 @@ private:
|
||||
|
||||
CPU::State FifoPlayer::AdvanceFrame()
|
||||
{
|
||||
if (m_CurrentFrame >= m_FrameRangeEnd)
|
||||
if (m_CurrentFrame > m_FrameRangeEnd)
|
||||
{
|
||||
if (!m_Loop)
|
||||
return CPU::State::PowerDown;
|
||||
// If there are zero frames in the range then sleep instead of busy spinning
|
||||
if (m_FrameRangeStart >= m_FrameRangeEnd)
|
||||
return CPU::State::Stepping;
|
||||
|
||||
// When looping, reload the contents of all the BP/CP/CF registers.
|
||||
// This ensures that each time the first frame is played back, the state of the
|
||||
@@ -189,23 +186,40 @@ bool FifoPlayer::IsRunningWithFakeVideoInterfaceUpdates() const
|
||||
return m_File->ShouldGenerateFakeVIUpdates();
|
||||
}
|
||||
|
||||
u32 FifoPlayer::GetFrameObjectCount() const
|
||||
u32 FifoPlayer::GetMaxObjectCount() const
|
||||
{
|
||||
if (m_CurrentFrame < m_FrameInfo.size())
|
||||
u32 result = 0;
|
||||
for (auto& frame : m_FrameInfo)
|
||||
{
|
||||
return (u32)(m_FrameInfo[m_CurrentFrame].objectStarts.size());
|
||||
const u32 count = static_cast<u32>(frame.objectStarts.size());
|
||||
if (count > result)
|
||||
result = count;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 FifoPlayer::GetFrameObjectCount(u32 frame) const
|
||||
{
|
||||
if (frame < m_FrameInfo.size())
|
||||
{
|
||||
return static_cast<u32>(m_FrameInfo[frame].objectStarts.size());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 FifoPlayer::GetCurrentFrameObjectCount() const
|
||||
{
|
||||
return GetFrameObjectCount(m_CurrentFrame);
|
||||
}
|
||||
|
||||
void FifoPlayer::SetFrameRangeStart(u32 start)
|
||||
{
|
||||
if (m_File)
|
||||
{
|
||||
u32 frameCount = m_File->GetFrameCount();
|
||||
if (start > frameCount)
|
||||
start = frameCount;
|
||||
const u32 lastFrame = m_File->GetFrameCount() - 1;
|
||||
if (start > lastFrame)
|
||||
start = lastFrame;
|
||||
|
||||
m_FrameRangeStart = start;
|
||||
if (m_FrameRangeEnd < start)
|
||||
@@ -220,9 +234,9 @@ void FifoPlayer::SetFrameRangeEnd(u32 end)
|
||||
{
|
||||
if (m_File)
|
||||
{
|
||||
u32 frameCount = m_File->GetFrameCount();
|
||||
if (end > frameCount)
|
||||
end = frameCount;
|
||||
const u32 lastFrame = m_File->GetFrameCount() - 1;
|
||||
if (end > lastFrame)
|
||||
end = lastFrame;
|
||||
|
||||
m_FrameRangeEnd = end;
|
||||
if (m_FrameRangeStart > end)
|
||||
@@ -375,6 +389,8 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end)
|
||||
{
|
||||
while (IsHighWatermarkSet())
|
||||
{
|
||||
if (CPU::GetState() != CPU::State::Running)
|
||||
break;
|
||||
CoreTiming::Idle();
|
||||
CoreTiming::Advance();
|
||||
}
|
||||
|
||||
@@ -74,7 +74,9 @@ public:
|
||||
bool IsPlaying() const;
|
||||
|
||||
FifoDataFile* GetFile() const { return m_File.get(); }
|
||||
u32 GetFrameObjectCount() const;
|
||||
u32 GetMaxObjectCount() const;
|
||||
u32 GetFrameObjectCount(u32 frame) const;
|
||||
u32 GetCurrentFrameObjectCount() const;
|
||||
u32 GetCurrentFrameNum() const { return m_CurrentFrame; }
|
||||
const AnalyzedFrameInfo& GetAnalyzedFrameInfo(u32 frame) const { return m_FrameInfo[frame]; }
|
||||
// Frame range
|
||||
|
||||
@@ -17,16 +17,16 @@ void FifoRecordAnalyzer::Initialize(const u32* cpMem)
|
||||
{
|
||||
s_DrawingObject = false;
|
||||
|
||||
FifoAnalyzer::LoadCPReg(0x50, *(cpMem + 0x50), s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(0x60, *(cpMem + 0x60), s_CpMem);
|
||||
for (int i = 0; i < 8; ++i)
|
||||
FifoAnalyzer::LoadCPReg(0x70 + i, *(cpMem + 0x70 + i), s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(VCD_LO, cpMem[VCD_LO], s_CpMem);
|
||||
FifoAnalyzer::LoadCPReg(VCD_HI, cpMem[VCD_HI], s_CpMem);
|
||||
for (u32 i = 0; i < CP_NUM_VAT_REG; ++i)
|
||||
FifoAnalyzer::LoadCPReg(CP_VAT_REG_A + i, cpMem[CP_VAT_REG_A + i], s_CpMem);
|
||||
|
||||
const u32* const bases_start = cpMem + 0xA0;
|
||||
const u32* const bases_start = cpMem + ARRAY_BASE;
|
||||
const u32* const bases_end = bases_start + s_CpMem.arrayBases.size();
|
||||
std::copy(bases_start, bases_end, s_CpMem.arrayBases.begin());
|
||||
|
||||
const u32* const strides_start = cpMem + 0xB0;
|
||||
const u32* const strides_start = cpMem + ARRAY_STRIDE;
|
||||
const u32* const strides_end = strides_start + s_CpMem.arrayStrides.size();
|
||||
std::copy(strides_start, strides_end, s_CpMem.arrayStrides.begin());
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user