diff --git a/tools/PsfPlayer/Source/Debuggable.h b/tools/PsfPlayer/Source/Debuggable.h index fafb9a3a..ef6bc20b 100644 --- a/tools/PsfPlayer/Source/Debuggable.h +++ b/tools/PsfPlayer/Source/Debuggable.h @@ -2,16 +2,22 @@ #define _DEBUGGABLE_H_ #include "MIPS.h" +#include "MIPSModule.h" +#include #include class CDebuggable { public: + typedef std::list ModuleList; + typedef std::tr1::function GetCpuFuncType; typedef std::tr1::function StepFuncType; + typedef std::tr1::function GetModulesFuncType; GetCpuFuncType GetCpu; StepFuncType Step; + GetModulesFuncType GetModules; }; #endif diff --git a/tools/PsfPlayer/Source/FunctionsView.cpp b/tools/PsfPlayer/Source/FunctionsView.cpp index eea6d3d2..f77b7858 100644 --- a/tools/PsfPlayer/Source/FunctionsView.cpp +++ b/tools/PsfPlayer/Source/FunctionsView.cpp @@ -1,28 +1,28 @@ #include -#include #include "FunctionsView.h" #include "layout/HorizontalLayout.h" +#include "layout/LayoutStretch.h" #include "win32/LayoutWindow.h" #include "win32/InputBox.h" #include "string_cast.h" #include "lexical_cast_ex.h" -#include "layout/LayoutStretch.h" -#include "layout/LayoutEngine.h" #include "PtrMacro.h" #define CLSNAME _T("FunctionsView") +#define DEFAULT_GROUPID (1) +#define DEFAULT_GROUPNAME _T("Global") + using namespace Framework; using namespace std; -using namespace boost; +using namespace std::tr1; -CFunctionsView::CFunctionsView(HWND hParent, CMIPS* pCtx) +CFunctionsView::CFunctionsView(HWND hParent) : +m_pCtx(NULL), +m_pELF(NULL) { RECT rc; - m_pCtx = pCtx; - m_pELF = NULL; - if(!DoesWindowClassExist(CLSNAME)) { WNDCLASSEX wc; @@ -38,7 +38,11 @@ CFunctionsView::CFunctionsView(HWND hParent, CMIPS* pCtx) SetRect(&rc, 0, 0, 320, 240); - Create(NULL, CLSNAME, _T("Functions"), WS_CLIPCHILDREN | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX, &rc, hParent, NULL); + unsigned long windowStyle = WS_CLIPCHILDREN | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX; +#ifndef FUNCTIONSVIEW_STANDALONE + windowStyle |= WS_CHILD; +#endif + Create(NULL, CLSNAME, _T("Functions"), windowStyle, &rc, hParent, NULL); SetClassPtr(); SetRect(&rc, 0, 0, 0, 0); @@ -53,24 +57,22 @@ CFunctionsView::CFunctionsView(HWND hParent, CMIPS* pCtx) m_pDelete = new Win32::CButton(_T("Delete"), m_hWnd, &rc); m_pImport = new Win32::CButton(_T("Load ELF symbols"), m_hWnd, &rc); - FlatLayoutPtr pSubLayout0 = CHorizontalLayout::Create(); - pSubLayout0->InsertObject(CLayoutStretch::Create()); - pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pNew)); - pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pRename)); - pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pDelete)); - pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pImport)); + FlatLayoutPtr pSubLayout0 = CHorizontalLayout::Create(); + pSubLayout0->InsertObject(CLayoutStretch::Create()); + pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pNew)); + pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pRename)); + pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pDelete)); + pSubLayout0->InsertObject(Win32::CLayoutWindow::CreateButtonBehavior(100, 23, m_pImport)); - m_pLayout = CVerticalLayout::Create(); - m_pLayout->InsertObject(Win32::CLayoutWindow::CreateCustomBehavior(1, 1, 1, 1, m_pList)); - m_pLayout->InsertObject(pSubLayout0); - - m_pCtx->m_Functions.m_OnTagListChanged.connect(bind(&CFunctionsView::Refresh, this)); + m_pLayout = CVerticalLayout::Create(); + m_pLayout->InsertObject(Win32::CLayoutWindow::CreateCustomBehavior(1, 1, 1, 1, m_pList)); + m_pLayout->InsertObject(pSubLayout0); SetSize(469, 612); - SetELF(NULL); + SetELF(NULL); - RefreshLayout(); + RefreshLayout(); } CFunctionsView::~CFunctionsView() @@ -93,8 +95,7 @@ long CFunctionsView::OnNotify(WPARAM wParam, NMHDR* pH) { if(pH->hwndFrom == m_pList->m_hWnd) { - NMLISTVIEW* pN; - pN = (NMLISTVIEW*)pH; + NMLISTVIEW* pN = reinterpret_cast(pH); switch(pN->hdr.code) { case NM_DBLCLK: @@ -183,11 +184,29 @@ void CFunctionsView::RefreshLayout() void CFunctionsView::RefreshList() { - unsigned int nCount; - uint32 nAddress; - + m_pList->SetRedraw(false); m_pList->DeleteAllItems(); + if(m_pCtx == NULL) return; + if(m_moduleListProvider) + { + m_modules = m_moduleListProvider(); + } + else + { + m_modules.clear(); + } + bool groupingEnabled = m_modules.size() != 0; + + if(groupingEnabled) + { + InitializeModuleGrouper(); + } + else + { + m_pList->EnableGroupView(false); + } + for(CMIPSTags::TagIterator itTag(m_pCtx->m_Functions.GetTagsBegin()); itTag != m_pCtx->m_Functions.GetTagsEnd(); itTag++) { @@ -199,16 +218,49 @@ void CFunctionsView::RefreshList() it.pszText = const_cast(sTag.c_str()); it.lParam = itTag->first; it.mask = LVIF_PARAM | LVIF_TEXT; + if(groupingEnabled) + { + it.iGroupId = GetFunctionGroupId(itTag->first); + it.mask |= LVIF_GROUPID; + } m_pList->InsertItem(&it); } - nCount = m_pList->GetItemCount(); + unsigned int nCount = m_pList->GetItemCount(); for(unsigned int i = 0; i < nCount; i++) { - nAddress = m_pList->GetItemData(i); + uint32 nAddress = m_pList->GetItemData(i); m_pList->SetItemText(i, 1, (_T("0x") + lexical_cast_hex(nAddress, 8)).c_str()); } + + m_pList->SetRedraw(true); +} + +void CFunctionsView::InitializeModuleGrouper() +{ + m_pList->RemoveAllGroups(); + m_pList->EnableGroupView(true); + m_pList->InsertGroup(DEFAULT_GROUPNAME, DEFAULT_GROUPID); + for(ModuleList::const_iterator moduleIterator(m_modules.begin()); + m_modules.end() != moduleIterator; moduleIterator++) + { + const MIPSMODULE& module(*moduleIterator); + m_pList->InsertGroup( + string_cast(module.name.c_str()).c_str(), + module.begin); + } +} + +uint32 CFunctionsView::GetFunctionGroupId(uint32 address) +{ + for(ModuleList::const_iterator moduleIterator(m_modules.begin()); + m_modules.end() != moduleIterator; moduleIterator++) + { + const MIPSMODULE& module(*moduleIterator); + if(address >= module.begin && address < module.end) return module.begin; + } + return DEFAULT_GROUPID; } void CFunctionsView::SetELF(CELF* pELF) @@ -224,6 +276,21 @@ void CFunctionsView::SetELF(CELF* pELF) } } +void CFunctionsView::SetContext(CMIPS* context, const ModuleListProvider& moduleListProvider) +{ + if(m_functionTagsChangeConnection.connected()) + { + m_functionTagsChangeConnection.disconnect(); + } + + m_pCtx = context; + m_moduleListProvider = moduleListProvider; + + m_functionTagsChangeConnection = m_pCtx->m_Functions.m_OnTagListChanged.connect( + bind(&CFunctionsView::RefreshList, this)); + RefreshList(); +} + void CFunctionsView::OnListDblClick() { int nItem; @@ -236,42 +303,32 @@ void CFunctionsView::OnListDblClick() void CFunctionsView::OnNewClick() { - Win32::CInputBox* pInput; - bool bQuit; + if(m_pCtx == NULL) return; + TCHAR sNameX[256]; - const TCHAR* sValue; uint32 nAddress; - pInput = new Win32::CInputBox(_T("New Function"), _T("New Function Name:"), _T("")); - sValue = pInput->GetValue(m_hWnd); + { + Win32::CInputBox inputBox(_T("New Function"), _T("New Function Name:"), _T("")); + const TCHAR* sValue = inputBox.GetValue(m_hWnd); + if(sValue == NULL) return; + _tcsncpy(sNameX, sValue, 255); + } - bQuit = (sValue == NULL); - if(sValue != NULL) - { - _tcsncpy(sNameX, sValue, 255); - } - - delete pInput; - - if(bQuit) return; - - pInput = new Win32::CInputBox(_T("New Function"), _T("New Function Address:"), _T("00000000")); - sValue = pInput->GetValue(m_hWnd); - - bQuit = (sValue == NULL); - if(sValue != NULL) - { - _stscanf(sValue, _T("%x"), &nAddress); - if((nAddress & 0x3) != 0x0) - { - MessageBox(m_hWnd, _T("Invalid address."), NULL, 16); - bQuit = true; - } - } - - delete pInput; - - if(bQuit) return; + { + Win32::CInputBox inputBox(_T("New Function"), _T("New Function Address:"), _T("00000000")); + const TCHAR* sValue = inputBox.GetValue(m_hWnd); + if(sValue == NULL) return; + if(sValue != NULL) + { + _stscanf(sValue, _T("%x"), &nAddress); + if((nAddress & 0x3) != 0x0) + { + MessageBox(m_hWnd, _T("Invalid address."), NULL, 16); + return; + } + } + } m_pCtx->m_Functions.InsertTag(nAddress, string_cast(sNameX).c_str()); @@ -281,16 +338,13 @@ void CFunctionsView::OnNewClick() void CFunctionsView::OnRenameClick() { - int nItem; - uint32 nAddress; - const char* sName; - const TCHAR* sNewNameX; + if(m_pCtx == NULL) return; - nItem = m_pList->GetSelection(); + int nItem = m_pList->GetSelection(); if(nItem == -1) return; - nAddress = m_pList->GetItemData(nItem); - sName = m_pCtx->m_Functions.Find(nAddress); + uint32 nAddress = m_pList->GetItemData(nItem); + const char* sName = m_pCtx->m_Functions.Find(nAddress); if(sName == NULL) { @@ -299,7 +353,7 @@ void CFunctionsView::OnRenameClick() } Win32::CInputBox RenameInput(_T("Rename Function"), _T("New Function Name:"), string_cast(sName).c_str()); - sNewNameX = RenameInput.GetValue(m_hWnd); + const TCHAR* sNewNameX = RenameInput.GetValue(m_hWnd); if(sNewNameX == NULL) return; @@ -311,23 +365,19 @@ void CFunctionsView::OnRenameClick() void CFunctionsView::OnImportClick() { - unsigned int i, nCount; - ELFSYMBOL* pSym; - ELFSECTIONHEADER* pSymTab; - const char* pStrTab; - + if(m_pCtx == NULL) return; if(m_pELF == NULL) return; - pSymTab = m_pELF->FindSection(".symtab"); + ELFSECTIONHEADER* pSymTab = m_pELF->FindSection(".symtab"); if(pSymTab == NULL) return; - pStrTab = (const char*)m_pELF->GetSectionData(pSymTab->nIndex); + const char* pStrTab = (const char*)m_pELF->GetSectionData(pSymTab->nIndex); if(pStrTab == NULL) return; - pSym = (ELFSYMBOL*)m_pELF->FindSectionData(".symtab"); - nCount = pSymTab->nSize / sizeof(ELFSYMBOL); + ELFSYMBOL* pSym = (ELFSYMBOL*)m_pELF->FindSectionData(".symtab"); + unsigned int nCount = pSymTab->nSize / sizeof(ELFSYMBOL); - for(i = 0; i < nCount; i++) + for(unsigned int i = 0; i < nCount; i++) { if((pSym[i].nInfo & 0x0F) != 0x02) continue; m_pCtx->m_Functions.InsertTag(pSym[i].nValue, (char*)pStrTab + pSym[i].nName); @@ -342,17 +392,16 @@ void CFunctionsView::OnImportClick() void CFunctionsView::OnDeleteClick() { - int nItem; - uint32 nAddress; + if(m_pCtx == NULL) return; - nItem = m_pList->GetSelection(); + int nItem = m_pList->GetSelection(); if(nItem == -1) return; if(MessageBox(m_hWnd, _T("Delete this function?"), NULL, MB_ICONQUESTION | MB_YESNO) != IDYES) { return; } - nAddress = m_pList->GetItemData(nItem); + uint32 nAddress = m_pList->GetItemData(nItem); m_pCtx->m_Functions.InsertTag(nAddress, NULL); RefreshList(); diff --git a/tools/PsfPlayer/Source/FunctionsView.h b/tools/PsfPlayer/Source/FunctionsView.h index 99c9e9cb..5d4623b5 100644 --- a/tools/PsfPlayer/Source/FunctionsView.h +++ b/tools/PsfPlayer/Source/FunctionsView.h @@ -2,19 +2,34 @@ #define _FUNCTIONSVIEW_H_ #include +#include #include "win32/MDIChild.h" #include "win32/ListView.h" #include "win32/Button.h" #include "layout/VerticalLayout.h" #include "MIPS.h" +#include "MIPSModule.h" #include "ELF.h" -class CFunctionsView : public Framework::Win32::CWindow, public boost::signals::trackable +class CFunctionsView : +#ifdef FUNCTIONSVIEW_STANDALONE + public Framework::Win32::CWindow, +#else + public Framework::Win32::CMDIChild, +#endif + public boost::signals::trackable { public: - CFunctionsView(HWND, CMIPS*); - ~CFunctionsView(); + typedef std::list ModuleList; + typedef std::tr1::function ModuleListProvider; + + + CFunctionsView(HWND); + virtual ~CFunctionsView(); + + void SetContext(CMIPS*, const ModuleListProvider&); void SetELF(CELF*); + void Refresh(); boost::signal m_OnFunctionDblClick; @@ -31,6 +46,8 @@ private: void ResizeListColumns(); void RefreshLayout(); void RefreshList(); + void InitializeModuleGrouper(); + uint32 GetFunctionGroupId(uint32); void OnListDblClick(); void OnNewClick(); @@ -44,9 +61,14 @@ private: Framework::Win32::CButton* m_pDelete; Framework::Win32::CButton* m_pImport; - Framework::FlatLayoutPtr m_pLayout; - CMIPS* m_pCtx; + Framework::FlatLayoutPtr m_pLayout; + + boost::signals::connection m_functionTagsChangeConnection; + + CMIPS* m_pCtx; CELF* m_pELF; + ModuleList m_modules; + ModuleListProvider m_moduleListProvider; }; #endif diff --git a/tools/PsfPlayer/Source/MiniDebugger.cpp b/tools/PsfPlayer/Source/MiniDebugger.cpp index e1d7ba29..572f740b 100644 --- a/tools/PsfPlayer/Source/MiniDebugger.cpp +++ b/tools/PsfPlayer/Source/MiniDebugger.cpp @@ -56,8 +56,9 @@ m_memoryView(NULL) m_registerView = new CRegViewGeneral(m_subSplitter->m_hWnd, Win32::CRect(0, 0, 1, 1), m_virtualMachine, &m_debuggable.GetCpu()); m_registerView->Show(SW_SHOW); - m_functionsView = new CFunctionsView(NULL, &m_debuggable.GetCpu()); + m_functionsView = new CFunctionsView(NULL); m_functionsView->m_OnFunctionDblClick.connect(bind(&CMiniDebugger::OnFunctionDblClick, this, _1)); + m_functionsView->SetContext(&m_debuggable.GetCpu(), m_debuggable.GetModules); m_functionsView->Refresh(); m_subSplitter->SetChild(0, *m_disAsmView); diff --git a/tools/PsfPlayer/Source/PsfBios.cpp b/tools/PsfPlayer/Source/PsfBios.cpp index 4c00e3e6..63dc6fad 100644 --- a/tools/PsfPlayer/Source/PsfBios.cpp +++ b/tools/PsfPlayer/Source/PsfBios.cpp @@ -48,6 +48,11 @@ void CPsfBios::CountTicks(uint32 ticks) m_bios.CountTicks(ticks); } +MipsModuleList CPsfBios::GetModuleList() +{ + return m_bios.GetModuleList(); +} + #ifdef DEBUGGER_INCLUDED void CPsfBios::LoadDebugTags(Framework::Xml::CNode* root) diff --git a/tools/PsfPlayer/Source/PsfBios.h b/tools/PsfPlayer/Source/PsfBios.h index 8e27a045..769f62ce 100644 --- a/tools/PsfPlayer/Source/PsfBios.h +++ b/tools/PsfPlayer/Source/PsfBios.h @@ -19,6 +19,7 @@ namespace PS2 #ifdef DEBUGGER_INCLUDED void LoadDebugTags(Framework::Xml::CNode*); void SaveDebugTags(Framework::Xml::CNode*); + MipsModuleList GetModuleList(); #endif void AppendArchive(const CPsfBase&); diff --git a/tools/PsfPlayer/Source/PsfVm.cpp b/tools/PsfPlayer/Source/PsfVm.cpp index 32bcc91e..a08c8ab5 100644 --- a/tools/PsfPlayer/Source/PsfVm.cpp +++ b/tools/PsfPlayer/Source/PsfVm.cpp @@ -123,22 +123,12 @@ void CPsfVm::LoadDebugTags(const char* packageName) try { string packagePath = MakeTagPackagePath(packageName); - Xml::CNode* document = Xml::CParser::ParseDocument(&CStdStream(packagePath.c_str(), "rb")); - { - Xml::CNode* subNode = document->Select((TAGS_SECTION_TAGS + string("/") + TAGS_SECTION_FUNCTIONS).c_str()); - if(subNode) - { - m_cpu.m_Functions.Unserialize(subNode); - } - } - { - Xml::CNode* subNode = document->Select((TAGS_SECTION_TAGS + string("/") + TAGS_SECTION_COMMENTS).c_str()); - if(subNode) - { - m_cpu.m_Comments.Unserialize(subNode); - } - } - m_bios->LoadDebugTags(document); + boost::scoped_ptr document(Xml::CParser::ParseDocument(&CStdStream(packagePath.c_str(), "rb"))); + Xml::CNode* tagsSection = document->Select(TAGS_SECTION_TAGS); + if(tagsSection == NULL) return; + m_cpu.m_Functions.Unserialize(tagsSection, TAGS_SECTION_FUNCTIONS); + m_cpu.m_Comments.Unserialize(tagsSection, TAGS_SECTION_COMMENTS); + m_bios->LoadDebugTags(document.get()); } catch(...) { @@ -149,20 +139,11 @@ void CPsfVm::LoadDebugTags(const char* packageName) void CPsfVm::SaveDebugTags(const char* packageName) { string packagePath = MakeTagPackagePath(packageName); - Xml::CNode* document = new Xml::CNode(TAGS_SECTION_TAGS, true); - { - Xml::CNode* subNode = new Xml::CNode(TAGS_SECTION_FUNCTIONS, true); - m_cpu.m_Functions.Serialize(subNode); - document->InsertNode(subNode); - } - { - Xml::CNode* subNode = new Xml::CNode(TAGS_SECTION_COMMENTS, true); - m_cpu.m_Comments.Serialize(subNode); - document->InsertNode(subNode); - } - m_bios->SaveDebugTags(document); - Xml::CWriter::WriteDocument(&CStdStream(packagePath.c_str(), "wb"), document); - delete document; + boost::scoped_ptr document(new Xml::CNode(TAGS_SECTION_TAGS, true)); + m_cpu.m_Functions.Serialize(document.get(), TAGS_SECTION_FUNCTIONS); + m_cpu.m_Comments.Serialize(document.get(), TAGS_SECTION_COMMENTS); + m_bios->SaveDebugTags(document.get()); + Xml::CWriter::WriteDocument(&CStdStream(packagePath.c_str(), "wb"), document.get()); } #endif @@ -265,6 +246,7 @@ CDebuggable CPsfVm::GetDebugInfo() CDebuggable debug; debug.Step = bind(&CPsfVm::Step, this); debug.GetCpu = bind(&CPsfVm::GetCpu, this); + debug.GetModules = bind(&Iop::CBiosBase::GetModuleList, m_bios); return debug; } diff --git a/tools/PsfPlayer/Source/PsfVm.h b/tools/PsfPlayer/Source/PsfVm.h index cb759ccf..d2e2e65e 100644 --- a/tools/PsfPlayer/Source/PsfVm.h +++ b/tools/PsfPlayer/Source/PsfVm.h @@ -74,6 +74,7 @@ private: HW_REG_END = 0x1F9FFFFF }; + MipsModuleList GetIopModules(); unsigned int ExecuteCpu(bool); void ThreadProc(); diff --git a/tools/PsfPlayer/Source/PsxBios.cpp b/tools/PsfPlayer/Source/PsxBios.cpp index ef31b080..7e2de959 100644 --- a/tools/PsfPlayer/Source/PsxBios.cpp +++ b/tools/PsfPlayer/Source/PsxBios.cpp @@ -122,6 +122,11 @@ void CPsxBios::SaveDebugTags(Framework::Xml::CNode* root) } +MipsModuleList CPsxBios::GetModuleList() +{ + return MipsModuleList(); +} + #endif void CPsxBios::CountTicks(uint32 ticks) diff --git a/tools/PsfPlayer/Source/PsxBios.h b/tools/PsfPlayer/Source/PsxBios.h index 1ae68b67..3d882e76 100644 --- a/tools/PsfPlayer/Source/PsxBios.h +++ b/tools/PsfPlayer/Source/PsxBios.h @@ -20,6 +20,7 @@ public: #ifdef DEBUGGER_INCLUDED void LoadDebugTags(Framework::Xml::CNode*); void SaveDebugTags(Framework::Xml::CNode*); + MipsModuleList GetModuleList(); #endif private: diff --git a/tools/PsfPlayer/Tester.vcproj b/tools/PsfPlayer/Tester.vcproj index 45f3fa34..61613ce8 100644 --- a/tools/PsfPlayer/Tester.vcproj +++ b/tools/PsfPlayer/Tester.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""C:\Program Files\OpenAL 1.1 SDK\include";C:\Projects\Rawr\Source;C:\Projects\zlib;C:\Components\boost_1_35_0\boost\tr1\tr1;C:\Components\boost_1_35_0;C:\Projects\Framework\include;C:\Projects\Rawr\tools\PsfPlayer2\Source" - PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_MSVC;_PSX;DEBUGGER_INCLUDED" + PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_MSVC;_PSX;DEBUGGER_INCLUDED;FUNCTIONSVIEW_STANDALONE" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -73,6 +73,7 @@ /> + + @@ -800,6 +806,14 @@ RelativePath="..\..\Source\iop\Iop_Timrman.h" > + + + + diff --git a/tools/PsfPlayer/manifest.xml b/tools/PsfPlayer/manifest.xml new file mode 100644 index 00000000..3deaeb62 --- /dev/null +++ b/tools/PsfPlayer/manifest.xml @@ -0,0 +1,10 @@ + + + + PsfPlayer + + + + + +