mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-28 16:49:58 -06:00
Refactor OpcodeDecoding and FIFO analyzer to use callbacks
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
#include "Core/FifoPlayer/FifoPlayer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
@ -12,7 +13,6 @@
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/FifoPlayer/FifoAnalyzer.h"
|
||||
#include "Core/FifoPlayer/FifoDataFile.h"
|
||||
#include "Core/HW/CPU.h"
|
||||
#include "Core/HW/GPFifo.h"
|
||||
@ -31,6 +31,121 @@
|
||||
// TODO: Move texMem somewhere else so this isn't an issue.
|
||||
#include "VideoCommon/TextureDecoder.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class FifoPlaybackAnalyzer : public OpcodeDecoder::Callback
|
||||
{
|
||||
public:
|
||||
static void AnalyzeFrames(FifoDataFile* file, std::vector<AnalyzedFrameInfo>& frame_info);
|
||||
|
||||
explicit FifoPlaybackAnalyzer(const u32* cpmem) : m_cpmem(cpmem) {}
|
||||
|
||||
OPCODE_CALLBACK(void OnXF(u16 address, u8 count, const u8* data)) {}
|
||||
OPCODE_CALLBACK(void OnCP(u8 command, u32 value)) { GetCPState().LoadCPReg(command, value); }
|
||||
OPCODE_CALLBACK(void OnBP(u8 command, u32 value)) {}
|
||||
OPCODE_CALLBACK(void OnIndexedLoad(CPArray array, u32 index, u16 address, u8 size)) {}
|
||||
OPCODE_CALLBACK(void OnPrimitiveCommand(OpcodeDecoder::Primitive primitive, u8 vat,
|
||||
u32 vertex_size, u16 num_vertices,
|
||||
const u8* vertex_data));
|
||||
OPCODE_CALLBACK(void OnDisplayList(u32 address, u32 size)) {}
|
||||
OPCODE_CALLBACK(void OnNop(u32 count));
|
||||
OPCODE_CALLBACK(void OnUnknown(u8 opcode, const u8* data)) {}
|
||||
|
||||
OPCODE_CALLBACK(void OnCommand(const u8* data, u32 size));
|
||||
|
||||
OPCODE_CALLBACK(CPState& GetCPState()) { return m_cpmem; }
|
||||
|
||||
bool m_start_of_primitives = false;
|
||||
bool m_end_of_primitives = false;
|
||||
// Internal state, copied to above in OnCommand
|
||||
bool m_was_primitive = false;
|
||||
bool m_is_primitive = false;
|
||||
bool m_is_nop = false;
|
||||
CPState m_cpmem;
|
||||
};
|
||||
|
||||
void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile* file,
|
||||
std::vector<AnalyzedFrameInfo>& frame_info)
|
||||
{
|
||||
FifoPlaybackAnalyzer analyzer(file->GetCPMem());
|
||||
frame_info.clear();
|
||||
frame_info.resize(file->GetFrameCount());
|
||||
|
||||
for (u32 frame_no = 0; frame_no < file->GetFrameCount(); frame_no++)
|
||||
{
|
||||
const FifoFrameInfo& frame = file->GetFrame(frame_no);
|
||||
AnalyzedFrameInfo& analyzed = frame_info[frame_no];
|
||||
|
||||
u32 offset = 0;
|
||||
|
||||
u32 part_start = 0;
|
||||
CPState cpmem;
|
||||
|
||||
while (offset < frame.fifoData.size())
|
||||
{
|
||||
const u32 cmd_size = OpcodeDecoder::RunCommand(&frame.fifoData[offset],
|
||||
u32(frame.fifoData.size()) - offset, analyzer);
|
||||
|
||||
if (analyzer.m_start_of_primitives)
|
||||
{
|
||||
// Start of primitive data for an object
|
||||
analyzed.AddPart(FramePartType::Commands, part_start, offset, analyzer.m_cpmem);
|
||||
part_start = offset;
|
||||
// Copy cpmem now, because end_of_primitives isn't triggered until the first opcode after
|
||||
// primitive data, and the first opcode might update cpmem
|
||||
std::memcpy(&cpmem, &analyzer.m_cpmem, sizeof(CPState));
|
||||
}
|
||||
if (analyzer.m_end_of_primitives)
|
||||
{
|
||||
// End of primitive data for an object, and thus end of the object
|
||||
analyzed.AddPart(FramePartType::PrimitiveData, part_start, offset, cpmem);
|
||||
part_start = offset;
|
||||
}
|
||||
|
||||
offset += cmd_size;
|
||||
}
|
||||
|
||||
if (part_start != offset)
|
||||
{
|
||||
// Remaining data, usually without any primitives
|
||||
analyzed.AddPart(FramePartType::Commands, part_start, offset, analyzer.m_cpmem);
|
||||
}
|
||||
|
||||
ASSERT(offset == frame.fifoData.size());
|
||||
}
|
||||
}
|
||||
|
||||
void FifoPlaybackAnalyzer::OnPrimitiveCommand(OpcodeDecoder::Primitive primitive, u8 vat,
|
||||
u32 vertex_size, u16 num_vertices,
|
||||
const u8* vertex_data)
|
||||
{
|
||||
m_is_primitive = true;
|
||||
}
|
||||
|
||||
void FifoPlaybackAnalyzer::OnNop(u32 count)
|
||||
{
|
||||
m_is_nop = true;
|
||||
}
|
||||
|
||||
void FifoPlaybackAnalyzer::OnCommand(const u8* data, u32 size)
|
||||
{
|
||||
m_start_of_primitives = false;
|
||||
m_end_of_primitives = false;
|
||||
|
||||
if (!m_is_nop)
|
||||
{
|
||||
if (m_is_primitive && !m_was_primitive)
|
||||
m_start_of_primitives = true;
|
||||
else if (m_was_primitive && !m_is_primitive)
|
||||
m_end_of_primitives = true;
|
||||
|
||||
m_was_primitive = m_is_primitive;
|
||||
}
|
||||
m_is_primitive = false;
|
||||
m_is_nop = false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool IsPlayingBackFifologWithBrokenEFBCopies = false;
|
||||
|
||||
FifoPlayer::FifoPlayer() : m_Loop{SConfig::GetInstance().bLoopFifoReplay}
|
||||
|
Reference in New Issue
Block a user