FifoPlayer: Add an "Analyzer" tab which allows browsing through all rendered objects per frame and through all register setting commands per object
This commit is contained in:
parent
96d56cd8ef
commit
700123c55b
|
@ -95,6 +95,7 @@ bool FifoPlayer::Play()
|
|||
WriteAllMemoryUpdates();
|
||||
|
||||
WriteFrame(m_File->GetFrame(m_CurrentFrame), m_FrameInfo[m_CurrentFrame]);
|
||||
|
||||
++m_CurrentFrame;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
u32 GetFrameObjectCount();
|
||||
u32 GetCurrentFrameNum() { return m_CurrentFrame; }
|
||||
|
||||
const AnalyzedFrameInfo& GetAnalyzedFrameInfo(u32 frame) { return m_FrameInfo[frame]; }
|
||||
|
||||
// Frame range
|
||||
u32 GetFrameRangeStart() { return m_FrameRangeStart; }
|
||||
void SetFrameRangeStart(u32 start);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Thread.h"
|
||||
#include "FifoPlayer/FifoPlayer.h"
|
||||
#include "FifoPlayer/FifoRecorder.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include <wx/spinctrl.h>
|
||||
|
||||
DECLARE_EVENT_TYPE(RECORDING_FINISHED_EVENT, -1)
|
||||
|
@ -65,6 +66,10 @@ FifoPlayerDlg::~FifoPlayerDlg()
|
|||
m_FramesToRecordCtrl->Disconnect(wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(FifoPlayerDlg::OnNumFramesToRecord), NULL, this);
|
||||
m_Close->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnCloseClick), NULL, this);
|
||||
|
||||
m_framesList->Disconnect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnFrameListSelectionChanged), NULL, this);
|
||||
m_objectsList->Disconnect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnObjectListSelectionChanged), NULL, this);
|
||||
m_objectCmdList->Disconnect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnObjectCmdListSelectionChanged), NULL, this);
|
||||
|
||||
FifoPlayer::GetInstance().SetFrameWrittenCallback(NULL);
|
||||
|
||||
sMutex.lock();
|
||||
|
@ -80,6 +85,8 @@ void FifoPlayerDlg::CreateGUIControls()
|
|||
sMain = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_Notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
|
||||
|
||||
{
|
||||
m_PlayPage = new wxPanel(m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
wxBoxSizer* sPlayPage;
|
||||
sPlayPage = new wxBoxSizer(wxVERTICAL);
|
||||
|
@ -151,6 +158,9 @@ void FifoPlayerDlg::CreateGUIControls()
|
|||
m_PlayPage->Layout();
|
||||
sPlayPage->Fit(m_PlayPage);
|
||||
m_Notebook->AddPage(m_PlayPage, _("Play"), true);
|
||||
}
|
||||
|
||||
{
|
||||
m_RecordPage = new wxPanel(m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
wxBoxSizer* sRecordPage;
|
||||
sRecordPage = new wxBoxSizer(wxVERTICAL);
|
||||
|
@ -199,6 +209,36 @@ void FifoPlayerDlg::CreateGUIControls()
|
|||
m_RecordPage->Layout();
|
||||
sRecordPage->Fit(m_RecordPage);
|
||||
m_Notebook->AddPage(m_RecordPage, _("Record"), false);
|
||||
}
|
||||
|
||||
// Analyze page
|
||||
{
|
||||
m_AnalyzePage = new wxPanel(m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
wxBoxSizer* sAnalyzePage;
|
||||
sAnalyzePage = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticBoxSizer* sTestSizer;
|
||||
sTestSizer = new wxStaticBoxSizer(new wxStaticBox(m_AnalyzePage, wxID_ANY, _("Frame info")), wxHORIZONTAL);
|
||||
|
||||
m_framesList = new wxListBox(m_AnalyzePage, wxID_ANY);
|
||||
m_framesList->SetMinSize(wxSize(100, 250));
|
||||
sTestSizer->Add(m_framesList, 0, wxALL, 5);
|
||||
|
||||
m_objectsList = new wxListBox(m_AnalyzePage, wxID_ANY);
|
||||
m_objectsList->SetMinSize(wxSize(110, 250));
|
||||
sTestSizer->Add(m_objectsList, 0, wxALL, 5);
|
||||
|
||||
m_objectCmdList = new wxListBox(m_AnalyzePage, wxID_ANY);
|
||||
m_objectCmdList->SetMinSize(wxSize(175, 250));
|
||||
sTestSizer->Add(m_objectCmdList, 0, wxALL, 5);
|
||||
|
||||
sAnalyzePage->Add(sTestSizer, 0, wxEXPAND, 5);
|
||||
|
||||
m_AnalyzePage->SetSizer(sAnalyzePage);
|
||||
m_AnalyzePage->Layout();
|
||||
sAnalyzePage->Fit(m_AnalyzePage);
|
||||
m_Notebook->AddPage(m_AnalyzePage, _("Analyze"), false);
|
||||
}
|
||||
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
|
@ -231,7 +271,11 @@ void FifoPlayerDlg::CreateGUIControls()
|
|||
m_RecordStop->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnRecordStop), NULL, this);
|
||||
m_Save->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnSaveFile), NULL, this);
|
||||
m_FramesToRecordCtrl->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(FifoPlayerDlg::OnNumFramesToRecord), NULL, this);
|
||||
m_Close->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnCloseClick), NULL, this);
|
||||
Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnCloseClick), NULL, this);
|
||||
|
||||
m_framesList->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnFrameListSelectionChanged), NULL, this);
|
||||
m_objectsList->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnObjectListSelectionChanged), NULL, this);
|
||||
m_objectCmdList->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnObjectCmdListSelectionChanged), NULL, this);
|
||||
|
||||
Connect(RECORDING_FINISHED_EVENT, wxCommandEventHandler(FifoPlayerDlg::OnRecordingFinished), NULL, this);
|
||||
Connect(FRAME_WRITTEN_EVENT, wxCommandEventHandler(FifoPlayerDlg::OnFrameWritten), NULL, this);
|
||||
|
@ -243,6 +287,7 @@ void FifoPlayerDlg::OnPaint(wxPaintEvent& event)
|
|||
{
|
||||
UpdatePlayGui();
|
||||
UpdateRecorderGui();
|
||||
UpdateAnalyzerGui();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
@ -250,6 +295,7 @@ void FifoPlayerDlg::OnPaint(wxPaintEvent& event)
|
|||
void FifoPlayerDlg::OnFrameFrom(wxSpinEvent& event)
|
||||
{
|
||||
FifoPlayer &player = FifoPlayer::GetInstance();
|
||||
|
||||
player.SetFrameRangeStart(event.GetPosition());
|
||||
|
||||
m_FrameFromCtrl->SetValue(player.GetFrameRangeStart());
|
||||
|
@ -326,6 +372,141 @@ void FifoPlayerDlg::OnNumFramesToRecord(wxSpinEvent& event)
|
|||
m_FramesToRecord = -1;
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::OnFrameListSelectionChanged(wxCommandEvent& event)
|
||||
{
|
||||
FifoPlayer& player = FifoPlayer::GetInstance();
|
||||
|
||||
m_objectsList->Clear();
|
||||
if (event.GetInt() != -1)
|
||||
{
|
||||
int num_objects = player.GetAnalyzedFrameInfo(event.GetInt()).objectStarts.size();
|
||||
for (int i = 0; i < num_objects; ++i)
|
||||
m_objectsList->Append(wxString::Format(wxT("Object %i"), i));
|
||||
}
|
||||
|
||||
// Call OnObjectListSelectionChanged
|
||||
m_objectsList->SetSelection(-1);
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::OnObjectListSelectionChanged (wxCommandEvent& event)
|
||||
{
|
||||
FifoPlayer& player = FifoPlayer::GetInstance();
|
||||
|
||||
int frame_idx = m_framesList->GetSelection();
|
||||
int object_idx = event.GetInt();
|
||||
|
||||
m_objectCmdList->Clear();
|
||||
if (frame_idx != -1 && object_idx != -1)
|
||||
{
|
||||
const AnalyzedFrameInfo& frame = player.GetAnalyzedFrameInfo(frame_idx);
|
||||
const FifoFrameInfo& fifo_frame = player.GetFile()->GetFrame(frame_idx);
|
||||
const u8* objectdata_start = &fifo_frame.fifoData[frame.objectStarts[object_idx]];
|
||||
const u8* objectdata_end = &fifo_frame.fifoData[frame.objectEnds[object_idx]];
|
||||
u8* objectdata = (u8*)objectdata_start;
|
||||
const int obj_offset = objectdata_start - &fifo_frame.fifoData[frame.objectStarts[0]];
|
||||
|
||||
int cmd = *objectdata++;
|
||||
int stream_size = Common::swap16(objectdata);
|
||||
objectdata += 2;
|
||||
int vertex_size = (objectdata_end - objectdata) / stream_size;
|
||||
wxString newLabel = wxString::Format(wxT("%08X: %02X %04X "), obj_offset, cmd, stream_size);
|
||||
if ((objectdata_end - objectdata) % stream_size) newLabel += _("NOTE: Stream size doesn't match actual data length\n");
|
||||
while (objectdata < objectdata_end)
|
||||
{
|
||||
// Group bytes by vertex
|
||||
newLabel += wxString::Format(wxT("%02X"), *objectdata++);
|
||||
if (((objectdata - (objectdata_start+3)) % vertex_size) == 0) newLabel += wxT(" ");
|
||||
}
|
||||
m_objectCmdList->Append(newLabel);
|
||||
|
||||
|
||||
// Between objectdata_end and next_objdata_start, there are register setting commands
|
||||
if (object_idx + 1 < frame.objectStarts.size())
|
||||
{
|
||||
const u8* next_objdata_start = &fifo_frame.fifoData[frame.objectStarts[object_idx+1]];
|
||||
while (objectdata < next_objdata_start)
|
||||
{
|
||||
int cmd = *objectdata++;
|
||||
switch (cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
newLabel = _("NOP");
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
newLabel = _("0x44");
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:
|
||||
newLabel = _("GX_CMD_INVL_VC");
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
{
|
||||
u32 cmd2 = *objectdata++;
|
||||
u32 value = Common::swap32(objectdata);
|
||||
objectdata += 4;
|
||||
|
||||
newLabel = wxString::Format(wxT("CP %02X %08X"), cmd2, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 cmd2 = Common::swap32(objectdata);
|
||||
objectdata += 4;
|
||||
u8 streamSize = ((cmd2 >> 16) & 15) + 1;
|
||||
|
||||
newLabel = wxString::Format(wxT("XF %08X(%02X) ..."), cmd2, streamSize);
|
||||
|
||||
objectdata += streamSize * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
objectdata += 4;
|
||||
newLabel = wxString::Format(wxT("LOAD INDX %s"), (cmd == GX_LOAD_INDX_A) ? "A" :
|
||||
(cmd == GX_LOAD_INDX_B) ? "B" :
|
||||
(cmd == GX_LOAD_INDX_C) ? "C" : "D");
|
||||
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);
|
||||
objectdata += 8;
|
||||
newLabel = wxString::Format(wxT("CALL DL"));
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG:
|
||||
{
|
||||
u32 cmd2 = Common::swap32(objectdata);
|
||||
objectdata += 4;
|
||||
newLabel = wxString::Format(wxT("BP %02X %06X"), cmd2 >> 24, cmd2 & 0xFFFFFF);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
newLabel = _("Unexpected 0x80 call? Aborting...");
|
||||
objectdata = (u8*)next_objdata_start;
|
||||
break;
|
||||
}
|
||||
m_objectCmdList->Append(newLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Call OnObjectCmdListSelectionChanged
|
||||
m_objectCmdList->SetSelection(-1);
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::OnObjectCmdListSelectionChanged (wxCommandEvent& event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::OnCloseClick(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
Hide();
|
||||
|
@ -375,6 +556,23 @@ void FifoPlayerDlg::UpdateRecorderGui()
|
|||
m_Save->Enable(GetSaveButtonEnabled());
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::UpdateAnalyzerGui()
|
||||
{
|
||||
FifoPlayer &player = FifoPlayer::GetInstance();
|
||||
FifoDataFile* file = player.GetFile();
|
||||
|
||||
int num_frames = (file) ? player.GetFile()->GetFrameCount() : 0;
|
||||
if (m_framesList->GetCount() != num_frames)
|
||||
{
|
||||
m_framesList->Clear();
|
||||
for (int i = 0; i < num_frames; ++i)
|
||||
{
|
||||
m_framesList->Append(wxString::Format(wxT("Frame %i"), i));
|
||||
}
|
||||
m_framesList->SetSelection(-1);
|
||||
}
|
||||
}
|
||||
|
||||
wxString FifoPlayerDlg::CreateFileFrameCountLabel() const
|
||||
{
|
||||
FifoDataFile *file = FifoPlayer::GetInstance().GetFile();
|
||||
|
|
|
@ -47,8 +47,13 @@ private:
|
|||
void OnRecordingFinished(wxCommandEvent& event);
|
||||
void OnFrameWritten(wxCommandEvent& event);
|
||||
|
||||
void OnFrameListSelectionChanged(wxCommandEvent& event);
|
||||
void OnObjectListSelectionChanged(wxCommandEvent& event);
|
||||
void OnObjectCmdListSelectionChanged(wxCommandEvent& event);
|
||||
|
||||
void UpdatePlayGui();
|
||||
void UpdateRecorderGui();
|
||||
void UpdateAnalyzerGui();
|
||||
|
||||
wxString CreateFileFrameCountLabel() const;
|
||||
wxString CreateCurrentFrameLabel() const;
|
||||
|
@ -89,6 +94,12 @@ private:
|
|||
wxButton* m_Save;
|
||||
wxStaticText* m_FramesToRecordLabel;
|
||||
wxSpinCtrl* m_FramesToRecordCtrl;
|
||||
|
||||
wxPanel* m_AnalyzePage;
|
||||
wxListBox* m_framesList;
|
||||
wxListBox* m_objectsList;
|
||||
wxListBox* m_objectCmdList;
|
||||
|
||||
wxButton* m_Close;
|
||||
|
||||
s32 m_FramesToRecord;
|
||||
|
|
Loading…
Reference in New Issue