FifoPlayer: Add a search function for the analyzer tab.

Also some tiny fixes.
This commit is contained in:
NeoBrainX 2012-01-21 13:40:14 +01:00
parent ecb616f7ff
commit ad1a4d7ce3
3 changed files with 249 additions and 25 deletions

View File

@ -37,7 +37,7 @@ wxEvtHandler *volatile FifoPlayerDlg::m_EvtHandler = NULL;
FifoPlayerDlg::FifoPlayerDlg(wxWindow * const parent) :
wxDialog(parent, wxID_ANY, _("FIFO Player"), wxDefaultPosition, wxDefaultSize),
m_FramesToRecord(1)
m_search_result_idx(0), m_FramesToRecord(1)
{
CreateGUIControls();
@ -79,8 +79,6 @@ FifoPlayerDlg::~FifoPlayerDlg()
void FifoPlayerDlg::CreateGUIControls()
{
SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* sMain;
sMain = new wxBoxSizer(wxVERTICAL);
@ -153,7 +151,8 @@ void FifoPlayerDlg::CreateGUIControls()
sPlayOptions->Add(m_EarlyMemoryUpdates, 0, wxALL, 5);
sPlayPage->Add(sPlayOptions, 0, wxEXPAND, 5);
sPlayPage->AddStretchSpacer();
m_PlayPage->SetSizer(sPlayPage);
m_PlayPage->Layout();
sPlayPage->Fit(m_PlayPage);
@ -204,7 +203,8 @@ void FifoPlayerDlg::CreateGUIControls()
sRecordingOptions->Add(m_FramesToRecordCtrl, 0, wxALL, 5);
sRecordPage->Add(sRecordingOptions, 0, wxEXPAND, 5);
sRecordPage->AddStretchSpacer();
m_RecordPage->SetSizer(sRecordPage);
m_RecordPage->Layout();
sRecordPage->Fit(m_RecordPage);
@ -217,8 +217,8 @@ void FifoPlayerDlg::CreateGUIControls()
wxBoxSizer* sAnalyzePage;
sAnalyzePage = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer* sTestSizer;
sTestSizer = new wxStaticBoxSizer(new wxStaticBox(m_AnalyzePage, wxID_ANY, _("Frame info")), wxVERTICAL);
wxStaticBoxSizer* sFrameInfoSizer;
sFrameInfoSizer = new wxStaticBoxSizer(new wxStaticBox(m_AnalyzePage, wxID_ANY, _("Frame Info")), wxVERTICAL);
wxBoxSizer* sListsSizer = new wxBoxSizer(wxHORIZONTAL);
@ -234,13 +234,45 @@ void FifoPlayerDlg::CreateGUIControls()
m_objectCmdList->SetMinSize(wxSize(175, 250));
sListsSizer->Add(m_objectCmdList, 0, wxALL, 5);
sTestSizer->Add(sListsSizer, 0, wxALL, 5);
sFrameInfoSizer->Add(sListsSizer, 0, wxALL, 5);
m_objectCmdInfo = new wxStaticText(m_AnalyzePage, wxID_ANY, wxString());
sTestSizer->Add(m_objectCmdInfo, 0, wxALL, 5);
sFrameInfoSizer->Add(m_objectCmdInfo, 0, wxALL, 5);
sAnalyzePage->Add(sFrameInfoSizer, 0, wxEXPAND, 5);
wxStaticBoxSizer* sSearchSizer = new wxStaticBoxSizer(new wxStaticBox(m_AnalyzePage, wxID_ANY, _("Search current Object")), wxVERTICAL);
wxBoxSizer* sSearchField = new wxBoxSizer(wxHORIZONTAL);
sSearchField->Add(new wxStaticText(m_AnalyzePage, wxID_ANY, _("Search for hex Value:")), 0, wxALIGN_CENTER_VERTICAL, 5);
// TODO: ugh, wxValidator sucks - but we should use it anyway.
m_searchField = new wxTextCtrl(m_AnalyzePage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
m_numResultsText = new wxStaticText(m_AnalyzePage, wxID_ANY, wxEmptyString);
sSearchField->Add(m_searchField, 0, wxALL, 5);
sSearchField->Add(m_numResultsText, 0, wxALIGN_CENTER_VERTICAL, 5);
wxBoxSizer* sSearchButtons = new wxBoxSizer(wxHORIZONTAL);
m_beginSearch = new wxButton(m_AnalyzePage, wxID_ANY, _("Search"));
m_findNext = new wxButton(m_AnalyzePage, wxID_ANY, _("Find next"));
m_findPrevious = new wxButton(m_AnalyzePage, wxID_ANY, _("Find previous"));
m_beginSearch->Disable();
m_findNext->Disable();
m_findPrevious->Disable();
sSearchButtons->Add(m_beginSearch, 0, wxALL, 5);
sSearchButtons->Add(m_findNext, 0, wxALL, 5);
sSearchButtons->Add(m_findPrevious, 0, wxALL, 5);
sSearchSizer->Add(sSearchField, 0, wxEXPAND, 5);
sSearchSizer->Add(sSearchButtons, 0, wxEXPAND, 5);
sAnalyzePage->Add(sSearchSizer, 0, wxEXPAND, 5);
sAnalyzePage->AddStretchSpacer();
sAnalyzePage->Add(sTestSizer, 0, wxEXPAND, 5);
m_AnalyzePage->SetSizer(sAnalyzePage);
m_AnalyzePage->Layout();
sAnalyzePage->Fit(m_AnalyzePage);
@ -284,6 +316,13 @@ void FifoPlayerDlg::CreateGUIControls()
m_objectsList->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnObjectListSelectionChanged), NULL, this);
m_objectCmdList->Connect(wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(FifoPlayerDlg::OnObjectCmdListSelectionChanged), NULL, this);
m_beginSearch->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnBeginSearch), NULL, this);
m_findNext->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnFindNextClick), NULL, this);
m_findPrevious->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FifoPlayerDlg::OnFindPreviousClick), NULL, this);
m_searchField->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(FifoPlayerDlg::OnBeginSearch), NULL, this);
m_searchField->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FifoPlayerDlg::OnSearchFieldTextChanged), NULL, this);
Connect(RECORDING_FINISHED_EVENT, wxCommandEventHandler(FifoPlayerDlg::OnRecordingFinished), NULL, this);
Connect(FRAME_WRITTEN_EVENT, wxCommandEventHandler(FifoPlayerDlg::OnFrameWritten), NULL, this);
@ -379,6 +418,165 @@ void FifoPlayerDlg::OnNumFramesToRecord(wxSpinEvent& event)
m_FramesToRecord = -1;
}
void FifoPlayerDlg::OnBeginSearch(wxCommandEvent& event)
{
wxString str_search_val = m_searchField->GetValue();
if (m_framesList->GetSelection() == -1)
return;
// TODO: Limited to even str lengths...
if (str_search_val.Length() && str_search_val.Length() % 2)
{
m_numResultsText->SetLabel(_("Invalid search string (only even string lengths supported)"));
return;
}
unsigned int val_length = str_search_val.Length() / 2;
u8* search_val = new u8[val_length];
for (unsigned int i = 0; i < val_length; ++i)
{
wxString char_str = str_search_val.Mid(2*i, 2);
unsigned long val;
if (!char_str.ToULong(&val, 16))
{
m_numResultsText->SetLabel(_("Invalid search string (couldn't convert to number)"));
delete[] search_val;
return;
}
search_val[i] = (u8)val;
}
search_results.clear();
u8* start_ptr;
u8* end_ptr;
int frame_idx = m_framesList->GetSelection();
FifoPlayer& player = FifoPlayer::GetInstance();
const AnalyzedFrameInfo& frame = player.GetAnalyzedFrameInfo(frame_idx);
const FifoFrameInfo& fifo_frame = player.GetFile()->GetFrame(frame_idx);
// TODO: Support searching through the last object... How do we know were the cmd data ends?
// TODO: Support searching for bit patterns
int obj_idx = m_objectsList->GetSelection();
if (obj_idx == -1)
{
m_numResultsText->SetLabel(_("Invalid search parameters (no object selected)"));
return;
}
start_ptr = &fifo_frame.fifoData[frame.objectStarts[obj_idx]];
end_ptr = &fifo_frame.fifoData[frame.objectStarts[obj_idx+1]];
for (u8* ptr = start_ptr; ptr < end_ptr-val_length+1; ++ptr)
{
if (memcmp(ptr, search_val, val_length) == 0)
{
SearchResult result;
result.frame_idx = frame_idx;
int obj_idx = m_objectsList->GetSelection();
result.obj_idx = obj_idx;
result.cmd_idx = 0;
for (unsigned int cmd_idx = 1; cmd_idx < m_objectCmdOffsets.size(); ++cmd_idx)
{
if (ptr < start_ptr + m_objectCmdOffsets[cmd_idx])
{
result.cmd_idx = cmd_idx-1;
break;
}
}
search_results.push_back(result);
}
}
delete[] search_val;
ChangeSearchResult(0);
m_beginSearch->Disable();
m_findNext->Enable();
m_findPrevious->Enable();
m_numResultsText->SetLabel(wxString::Format(_("Found %d results for \'"), search_results.size()) + m_searchField->GetValue() + _("\'"));
}
void FifoPlayerDlg::OnSearchFieldTextChanged(wxCommandEvent& event)
{
m_beginSearch->Enable(m_searchField->GetLineLength(0) > 0);
m_findNext->Disable();
m_findPrevious->Disable();
}
void FifoPlayerDlg::OnFindNextClick(wxCommandEvent& event)
{
int cur_cmd_index = m_objectCmdList->GetSelection();
if (cur_cmd_index == -1)
{
ChangeSearchResult(0);
return;
}
for (std::vector<SearchResult>::iterator it = search_results.begin(); it != search_results.end(); ++it)
{
if (it->cmd_idx > cur_cmd_index)
{
ChangeSearchResult(it - search_results.begin());
return;
}
}
}
void FifoPlayerDlg::OnFindPreviousClick(wxCommandEvent& event)
{
int cur_cmd_index = m_objectCmdList->GetSelection();
if (cur_cmd_index == -1)
{
ChangeSearchResult(search_results.size() - 1);
return;
}
for (std::vector<SearchResult>::reverse_iterator it = search_results.rbegin(); it != search_results.rend(); ++it)
{
if (it->cmd_idx < cur_cmd_index)
{
ChangeSearchResult(search_results.size()-1 - (it - search_results.rbegin()));
return;
}
}
}
void FifoPlayerDlg::ChangeSearchResult(unsigned int result_idx)
{
if (search_results.size() > result_idx)
{
m_search_result_idx = result_idx;
int prev_frame = m_framesList->GetSelection();
int prev_obj = m_objectsList->GetSelection();
int prev_cmd = m_objectCmdList->GetSelection();
m_framesList->SetSelection(search_results[result_idx].frame_idx);
m_objectsList->SetSelection(search_results[result_idx].obj_idx);
m_objectCmdList->SetSelection(search_results[result_idx].cmd_idx);
wxCommandEvent ev(wxEVT_COMMAND_LISTBOX_SELECTED);
if (prev_frame != m_framesList->GetSelection())
{
ev.SetInt(m_framesList->GetSelection());
OnFrameListSelectionChanged(ev);
}
if (prev_obj != m_objectsList->GetSelection())
{
ev.SetInt(m_objectsList->GetSelection());
OnObjectListSelectionChanged(ev);
}
if (prev_cmd != m_objectCmdList->GetSelection())
{
ev.SetInt(m_objectCmdList->GetSelection());
OnObjectCmdListSelectionChanged(ev);
}
}
else if (search_results.size())
{
ChangeSearchResult(search_results.size() - 1);
}
}
void FifoPlayerDlg::OnFrameListSelectionChanged(wxCommandEvent& event)
{
FifoPlayer& player = FifoPlayer::GetInstance();
@ -391,8 +589,10 @@ void FifoPlayerDlg::OnFrameListSelectionChanged(wxCommandEvent& event)
m_objectsList->Append(wxString::Format(wxT("Object %i"), i));
}
// Call OnObjectListSelectionChanged
m_objectsList->SetSelection(-1);
// Update object list
wxCommandEvent ev = wxCommandEvent(wxEVT_COMMAND_LISTBOX_SELECTED);
ev.SetInt(-1);
OnObjectListSelectionChanged(ev);
}
void FifoPlayerDlg::OnObjectListSelectionChanged(wxCommandEvent& event)
@ -421,21 +621,20 @@ void FifoPlayerDlg::OnObjectListSelectionChanged(wxCommandEvent& event)
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 - TODO: Won't work..
newLabel += wxString::Format(wxT("%02X"), *objectdata++);
if (((objectdata - (objectdata_start+3)) % vertex_size) == 0) newLabel += wxT(" ");
}
m_objectCmdList->Append(newLabel);
m_objectCmdOffsets.push_back(0);
// Between objectdata_end and next_objdata_start, there are register setting commands
if (object_idx + 1 < frame.objectStarts.size())
if (object_idx + 1 < (int)frame.objectStarts.size())
{
const u8* next_objdata_start = &fifo_frame.fifoData[frame.objectStarts[object_idx+1]];
while (objectdata < next_objdata_start)
{
m_objectCmdOffsets.push_back(objectdata - objectdata_start);
int new_offset = objectdata - &fifo_frame.fifoData[frame.objectStarts[0]];
int cmd = *objectdata++;
switch (cmd)
{
@ -485,9 +684,9 @@ void FifoPlayerDlg::OnObjectListSelectionChanged(wxCommandEvent& event)
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");
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:
@ -511,12 +710,15 @@ void FifoPlayerDlg::OnObjectListSelectionChanged(wxCommandEvent& event)
objectdata = (u8*)next_objdata_start;
break;
}
newLabel = wxString::Format(_("%08X: "), new_offset) + newLabel;
m_objectCmdList->Append(newLabel);
}
}
}
// Call OnObjectCmdListSelectionChanged
m_objectCmdList->SetSelection(-1);
// Update command list
wxCommandEvent ev = wxCommandEvent(wxEVT_COMMAND_LISTBOX_SELECTED);
ev.SetInt(-1);
OnObjectCmdListSelectionChanged(ev);
}
void FifoPlayerDlg::OnObjectCmdListSelectionChanged(wxCommandEvent& event)
@ -526,7 +728,7 @@ void FifoPlayerDlg::OnObjectCmdListSelectionChanged(wxCommandEvent& event)
if (event.GetInt() == -1 || frame_idx == -1 || object_idx == -1)
{
m_objectCmdInfo->SetLabel(wxString());
m_objectCmdInfo->SetLabel(wxEmptyString);
return;
}
@ -616,14 +818,16 @@ void FifoPlayerDlg::UpdateAnalyzerGui()
FifoDataFile* file = player.GetFile();
int num_frames = (file) ? player.GetFile()->GetFrameCount() : 0;
if (m_framesList->GetCount() != num_frames)
if ((int)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);
wxCommandEvent ev = wxCommandEvent(wxEVT_COMMAND_LISTBOX_SELECTED);
ev.SetInt(-1);
OnFrameListSelectionChanged(ev);
}
}

View File

@ -45,6 +45,12 @@ private:
void OnNumFramesToRecord( wxSpinEvent& event );
void OnCloseClick( wxCommandEvent& event );
void OnBeginSearch(wxCommandEvent& event);
void OnFindNextClick(wxCommandEvent& event);
void OnFindPreviousClick(wxCommandEvent& event);
void OnSearchFieldTextChanged(wxCommandEvent& event);
void ChangeSearchResult(unsigned int result_idx);
void OnRecordingFinished(wxCommandEvent& event);
void OnFrameWritten(wxCommandEvent& event);
@ -103,6 +109,20 @@ private:
std::vector<u32> m_objectCmdOffsets;
wxStaticText* m_objectCmdInfo;
wxTextCtrl* m_searchField;
wxButton* m_beginSearch;
wxButton* m_findNext;
wxButton* m_findPrevious;
wxStaticText* m_numResultsText;
struct SearchResult {
int frame_idx;
int obj_idx;
int cmd_idx;
};
std::vector<SearchResult> search_results;
unsigned int m_search_result_idx;
wxButton* m_Close;
s32 m_FramesToRecord;

View File

@ -148,7 +148,7 @@ void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size
"Frame to field: 0x%01X\n"
"Copy to XFB: %s\n"
"Intensity format: %s\n"
"Automatic color conversion: %s\n",
"Automatic color conversion: %s",
(copy.clamp0 && copy.clamp1) ? "Top and Bottom" : (copy.clamp0) ? "Top only" : (copy.clamp1) ? "Bottom only" : "None",
no_yes[copy.yuv],
copy.tp_realFormat(),