From cfcd3ce8223a9accfea2d191516e422023a0a3b0 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 2 Apr 2009 12:50:47 +0000 Subject: [PATCH] beginning dsp lle debugger, buttons dont work yet so dont spazz out. (Thanks a lot to whoever wrote min32 gui :) ) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2828 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_DSP_LLE-testing/Src/DSPTables.cpp | 20 +- .../Src/Debugger/DSPRegisterView.cpp | 94 ++++ .../Src/Debugger/DSPRegisterView.h | 56 +++ .../Src/Debugger/Debugger.cpp | 406 ++++++++++++++++-- .../Src/Debugger/Debugger.h | 168 ++++++-- .../Plugin_DSP_LLE-testing/Src/main.cpp | 45 +- 6 files changed, 692 insertions(+), 97 deletions(-) create mode 100644 Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.cpp create mode 100644 Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.h diff --git a/Source/Plugins/Plugin_DSP_LLE-testing/Src/DSPTables.cpp b/Source/Plugins/Plugin_DSP_LLE-testing/Src/DSPTables.cpp index 3c92ba5782..d621b1a035 100644 --- a/Source/Plugins/Plugin_DSP_LLE-testing/Src/DSPTables.cpp +++ b/Source/Plugins/Plugin_DSP_LLE-testing/Src/DSPTables.cpp @@ -102,7 +102,7 @@ DSPOPCTemplate opcodes[] = {"CMPI", 0x0280, 0xfeff, nop, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64 {"ILRR", 0x0210, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, - {"ILRRD", 0x0214, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, + {"ILRRD", 0x0214, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, {"ILRRI", 0x0218, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},}, // load and store value pointed by indexing reg and increment; LRR/SRR variants @@ -201,11 +201,11 @@ DSPOPCTemplate opcodes[] = {"MSUBC", 0xec00, 0xfcff, DSPInterpreter::msubc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},}, // FIXME: nakee guessing (check masks and params!) - {"SHIFTI?", 0x1400, 0xfec0, DSPInterpreter::shifti, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, + {"SHIFTI?", 0x1400, 0xfec0, DSPInterpreter::shifti, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, - {"JMPA?", 0x1700, 0xff1f, DSPInterpreter::jmpa, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, + {"JMPA?", 0x1700, 0xff1f, DSPInterpreter::jmpa, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},}, - {"TSTA?", 0xa100, 0xe7ff, DSPInterpreter::tsta, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, + {"TSTA?", 0xa100, 0xe7ff, DSPInterpreter::tsta, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},}, // assemble CW {"CW", 0x0000, 0xffff, nop, nop, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},}, @@ -246,9 +246,12 @@ const u32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate); dspInstFunc opTable[OPTABLE_SIZE]; -void InitInstructionTable() { - for(u32 i = 0; i < OPTABLE_SIZE; i++) { - for(u32 j = 0; j < opcodes_size; j++) { +void InitInstructionTable() +{ + for(u32 i = 0; i < OPTABLE_SIZE; i++) + { + for(u32 j = 0; j < opcodes_size; j++) + { if((opcodes[j].opcode_mask & i) == opcodes[j].opcode_mask) opTable[i] = opcodes[j].interpFunc; else @@ -257,6 +260,7 @@ void InitInstructionTable() { } } -void ComputeInstruction(const UDSPInstruction& inst) { +void ComputeInstruction(const UDSPInstruction& inst) +{ opTable[inst.hex](inst); } diff --git a/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.cpp b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.cpp new file mode 100644 index 0000000000..d89e6e0f57 --- /dev/null +++ b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Debugger.h" +#include "DSPRegisterView.h" + + +wxString CRegTable::GetValue(int row, int col) +{ + if (row < 36) // 32 "normal" regs + { + switch (col) + { + case 0: return wxString::FromAscii(gd_dis_get_reg_name(row)); + case 1: return wxString::Format(wxT("0x%04x"), g_dsp.r[row]); + default: return wxString::FromAscii(""); + } + } + return wxString::FromAscii(""); +} + +void CRegTable::SetValue(int, int, const wxString &) +{ +} + +void CRegTable::UpdateCachedRegs() +{ + if (m_CachedCounter == g_dsp.step_counter) + { + return; + } + + m_CachedCounter = g_dsp.step_counter; + + for (int i = 0; i < 36; ++i) + { + m_CachedRegHasChanged[i] = (m_CachedRegs[i] != g_dsp.r[i]); + m_CachedRegs[i] = g_dsp.r[i]; + } +} + +wxGridCellAttr *CRegTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind) +{ + wxGridCellAttr *attr = new wxGridCellAttr(); + + attr->SetBackgroundColour(wxColour(wxT("#FFFFFF"))); + + switch (col) + { + case 1: + attr->SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER); + break; + default: + attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER); + break; + } + + if (col == 1) + attr->SetTextColour(m_CachedRegHasChanged[row] ? wxColor(wxT("#FF0000")) : wxColor(wxT("#000000"))); + + attr->IncRef(); + return attr; +} + +DSPRegisterView::DSPRegisterView(wxWindow *parent, wxWindowID id) +: wxGrid(parent, id) +{ + SetTable(new CRegTable(), true); + SetRowLabelSize(0); + SetColLabelSize(0); + DisableDragRowSize(); + + AutoSizeColumns(); +} + +void DSPRegisterView::Update() +{ + ForceRefresh(); + ((CRegTable *)GetTable())->UpdateCachedRegs(); +} diff --git a/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.h b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.h new file mode 100644 index 0000000000..f369302035 --- /dev/null +++ b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/DSPRegisterView.h @@ -0,0 +1,56 @@ +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef __DSPREGISTERVIEW_h__ +#define __DSPREGISTERVIEW_h__ + +#include + + +class CRegTable : public wxGridTableBase +{ +private: + u64 m_CachedCounter; + u16 m_CachedRegs[32]; + bool m_CachedRegHasChanged[32]; + + DECLARE_NO_COPY_CLASS(CRegTable); + +public: + CRegTable() + { + memset(m_CachedRegs, 0, sizeof(m_CachedRegs)); + memset(m_CachedRegHasChanged, 0, sizeof(m_CachedRegHasChanged)); + } + + int GetNumberCols(void) {return 2;} + int GetNumberRows(void) {return 36;} + bool IsEmptyCell(int row, int col) {return false;} + wxString GetValue(int row, int col); + void SetValue(int row, int col, const wxString &); + wxGridCellAttr *GetAttr(int, int, wxGridCellAttr::wxAttrKind); + void UpdateCachedRegs(); +}; + +class DSPRegisterView : public wxGrid +{ +public: + DSPRegisterView(wxWindow* parent, wxWindowID id); + void Update(); +}; + +#endif //__DSPREGISTERVIEW_h__ diff --git a/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.cpp b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.cpp index c870d60f94..2b628b11a2 100644 --- a/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.cpp +++ b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2003-2008 Dolphin Project. +// Copyright (C) 2003-2009 Dolphin Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -21,53 +21,389 @@ #include #include "Debugger.h" +#include "DSPRegisterView.h" // Event table and class -BEGIN_EVENT_TABLE(CDebugger,wxDialog) - EVT_CLOSE(CDebugger::OnClose) // on close event +BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame) + EVT_CLOSE(DSPDebuggerLLE::OnClose) + EVT_SIZE(DSPDebuggerLLE::OnChangeSize) - //EVT_RIGHT_DOWN(CDebugger::ScrollBlocks) - //EVT_LEFT_DOWN(CDebugger::ScrollBlocks) - //EVT_MOUSE_EVENTS(CDebugger::ScrollBlocks) - //EVT_MOTION(CDebugger::ScrollBlocks) - //EVT_SCROLL(CDebugger::ScrollBlocks) - //EVT_SCROLLWIN(CDebugger::ScrollBlocks) + //EVT_RIGHT_DOWN(DSPDebuggerLLE::ScrollBlocks) + //EVT_LEFT_DOWN(DSPDebuggerLLE::ScrollBlocks) + //EVT_MOUSE_EVENTS(DSPDebuggerLLE::ScrollBlocks) + //EVT_MOTION(DSPDebuggerLLE::ScrollBlocks) + //EVT_SCROLL(DSPDebuggerLLE::ScrollBlocks) + //EVT_SCROLLWIN(DSPDebuggerLLE::ScrollBlocks) END_EVENT_TABLE() -CDebugger::CDebugger(wxWindow *parent, wxWindowID id, const wxString &title, - const wxPoint &position, const wxSize& size, long style) - : wxDialog(parent, id, title, position, size, style) +DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title, + const wxPoint &position, const wxSize& size, long style) + : wxFrame(parent, id, title, position, size, style) + , m_CachedStepCounter(-1) + , m_CachedCR(-1) + , m_State(RUN) + , m_CachedUCodeCRC(-1) { CreateGUIControls(); } -CDebugger::~CDebugger() +DSPDebuggerLLE::~DSPDebuggerLLE() { -} - -void CDebugger::OnClose(wxCloseEvent& /*event*/) -{ - EndModal(0); } -void CDebugger::DoHide() +void DSPDebuggerLLE::CreateGUIControls() { - Hide(); -} - -void CDebugger::DoShow() -{ - Show(); - //DoShowConsole(); // The console goes with the wx window -} - -void CDebugger::CreateGUIControls() -{ - SetTitle(wxT("Sound Debugging")); - // Basic settings - SetIcon(wxNullIcon); - SetSize(8, 8, 200, 100); // These will become the minimin sizes allowed by resizing - Center(); + SetSize(700, 500); + this->SetSizeHints(700, 500); + this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + m_Toolbar = CreateToolBar(wxTB_NODIVIDER|wxTB_NOICONS|wxTB_HORZ_TEXT|wxTB_DOCKABLE, ID_TOOLBAR); + m_Toolbar->AddTool(ID_RUNTOOL, wxT("Run"), wxNullBitmap, wxEmptyString, wxITEM_NORMAL); + m_Toolbar->AddTool(ID_PAUSETOOL, wxT("Pause"), wxNullBitmap, wxEmptyString, wxITEM_NORMAL); + m_Toolbar->AddTool(ID_STEPTOOL, wxT("Step"), wxNullBitmap, wxT("Step Code "), wxITEM_NORMAL); + m_Toolbar->AddTool(ID_RESETTOPCTOOL, wxT("Show Pc"), wxNullBitmap, wxT("Reset To PC counter"), wxITEM_NORMAL); + m_Toolbar->AddTool(ID_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL); + m_Toolbar->AddTool(ID_DUMPCODETOOL, wxT("Dump"), wxNullBitmap, wxT("Dump Code to File"), wxITEM_NORMAL); + m_Toolbar->AddSeparator(); + m_Toolbar->AddCheckTool(ID_CHECK_ASSERTINT, wxT("AssertInt"), wxNullBitmap, wxNullBitmap, wxEmptyString); + m_Toolbar->AddCheckTool(ID_CHECK_HALT, wxT("Halt"), wxNullBitmap, wxNullBitmap, wxEmptyString); + m_Toolbar->AddCheckTool(ID_CHECK_INIT, wxT("Init"), wxNullBitmap, wxNullBitmap, wxEmptyString); + m_Toolbar->Realize(); + + wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL); + + m_Disasm = new wxListCtrl(this, ID_DISASM, wxDefaultPosition, wxDefaultSize, wxLC_REPORT); + sMain->Add(m_Disasm, 4, wxALL|wxEXPAND, 5); + + wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL); + sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 5); + + m_Regs = new DSPRegisterView(this, ID_DSP_REGS); + sMain->Add(m_Regs, 1, wxEXPAND|wxALL, 5); + + this->SetSizer(sMain); + this->Layout(); + + // Add the disasm columns + m_Disasm->InsertColumn(COLUMN_BP, wxT("BP"), wxLIST_FORMAT_LEFT, 25); + m_Disasm->InsertColumn(COLUMN_FUNCTION, wxT("Function"), wxLIST_FORMAT_LEFT, 160); + m_Disasm->InsertColumn(COLUMN_ADDRESS, wxT("Address"), wxLIST_FORMAT_LEFT, 55); + m_Disasm->InsertColumn(COLUMN_MNEMONIC, wxT("Mnemonic"), wxLIST_FORMAT_LEFT, 55); + m_Disasm->InsertColumn(COLUMN_OPCODE, wxT("Opcode"), wxLIST_FORMAT_LEFT, 60); + m_Disasm->InsertColumn(COLUMN_EXT, wxT("Ext"), wxLIST_FORMAT_LEFT, 40); + m_Disasm->InsertColumn(COLUMN_PARAM, wxT("Param"), wxLIST_FORMAT_LEFT, 500); +} + +void DSPDebuggerLLE::OnClose(wxCloseEvent& event) +{ + event.Skip(); +} + +void DSPDebuggerLLE::OnChangeSize(wxSizeEvent& event) +{ + Refresh(); + event.Skip(); +} + +void DSPDebuggerLLE::Refresh() +{ + UpdateSymbolMap(); + UpdateDisAsmListView(); + UpdateRegisterFlags(); +} + +void DSPDebuggerLLE::RebuildDisAsmListView() +{ + m_Disasm->Freeze(); + m_Disasm->DeleteAllItems(); + + char Buffer[256]; + gd_globals_t gdg; + + if (g_dsp.pc & 0x8000) + gdg.binbuf = g_dsp.irom; + else + gdg.binbuf = g_dsp.iram; + + gdg.buffer = Buffer; + gdg.buffer_size = 256; + gdg.ext_separator = (char)0xff; + + gdg.show_pc = false; + gdg.show_hex = false; + gdg.print_tabs = true; + gdg.decode_names = true; + gdg.decode_registers = true; + + for (gdg.pc = 0; gdg.pc < DSP_IROM_SIZE;) + { + u16 CurrentPC = gdg.pc; + + if (g_dsp.pc & 0x8000) + CurrentPC |= 0x8000; + + char Temp[256]; + sprintf_s(Temp, 256, "0x%04x", CurrentPC); + + char Temp2[256]; + sprintf_s(Temp2, 256, "0x%04x", dsp_imem_read(CurrentPC)); + + char* pOpcode = gd_dis_opcode(&gdg); + const char* pParameter = NULL; + const char* pExtension = NULL; + + size_t WholeString = strlen(pOpcode); + + for (size_t i = 0; i < WholeString; i++) + { + if (pOpcode[i] == (char)0xff) + { + pOpcode[i] = 0x00; + pExtension = &pOpcode[i + 1]; + } + + if (pOpcode[i] == 0x09) + { + pOpcode[i] = 0x00; + pParameter = &pOpcode[i + 1]; + } + } + + + const char* pFunctionName = NULL; + + if (m_SymbolMap.find(CurrentPC) != m_SymbolMap.end()) + { + pFunctionName = m_SymbolMap[CurrentPC].Name.c_str(); + } + + int Item = m_Disasm->InsertItem(gdg.pc, wxEmptyString); + m_Disasm->SetItem(Item, COLUMN_BP, wxEmptyString); + m_Disasm->SetItem(Item, COLUMN_FUNCTION, pFunctionName); + m_Disasm->SetItem(Item, COLUMN_ADDRESS, Temp); + m_Disasm->SetItem(Item, COLUMN_MNEMONIC, Temp2); + m_Disasm->SetItem(Item, COLUMN_OPCODE, pOpcode); + m_Disasm->SetItem(Item, COLUMN_EXT, pExtension); + + if (!_stricmp(pOpcode, "CALL")) + { + u32 FunctionAddress = -1; + sscanf(pParameter, "0x%04x", &FunctionAddress); + + if (m_SymbolMap.find(FunctionAddress) != m_SymbolMap.end()) + { + pParameter = m_SymbolMap[FunctionAddress].Name.c_str(); + } + } + + m_Disasm->SetItem(Item, COLUMN_PARAM, pParameter); + + m_Disasm->SetItemData(Item, CurrentPC); + } + +// m_Disasm->SortItems(CompareFunc, this); // TODO verify + + m_Disasm->Thaw(); +} + +void DSPDebuggerLLE::UpdateDisAsmListView() +{ + if (g_dsp.dram == NULL) + return; + + // check if we have to rebuild the list view + if (m_Disasm->GetItemCount() == 0) + { + RebuildDisAsmListView(); + } + else + { + u16 FirstPC = static_cast(m_Disasm->GetItemData(0)); // TODO verify + + if ((FirstPC & 0x8000) != (g_dsp.pc & 0x8000)) + { + RebuildDisAsmListView(); + } + } + + if (m_CachedStepCounter == g_dsp.step_counter) + return; + + // show PC + for (int i = 0; i < m_Disasm->GetItemCount(); i++) + { + if (m_Disasm->GetItemData(i) == g_dsp.pc) + { + m_Disasm->EnsureVisible(i - 5); + m_Disasm->EnsureVisible(i + 14); + m_Disasm->SetItemState(i, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED); + break; + } + } + + m_CachedStepCounter = g_dsp.step_counter; + +// RebuildDisAsmListView(); // TODO do we need this? + + m_Regs->Update(); +} + +void DSPDebuggerLLE::UpdateSymbolMap() +{ + if (g_dsp.dram == NULL) + { + return; + } + + if (m_CachedUCodeCRC != g_dsp.iram_crc) + { + // load symbol map (if there is one) + m_CachedUCodeCRC = g_dsp.iram_crc; + char FileName[256]; + sprintf(FileName, "%sDSP_%08x.map", FULL_MAPS_DIR, m_CachedUCodeCRC); + LoadSymbolMap(FileName); + + // rebuild the disasm +// RebuildDisAsmListView(); // TODO do we need this? + } +} + +void DSPDebuggerLLE::UpdateRegisterFlags() +{ + if (m_CachedCR == g_dsp.cr) + return; + + m_Toolbar->ToggleTool(ID_CHECK_ASSERTINT, g_dsp.cr & 0x02 ? true : false); + m_Toolbar->ToggleTool(ID_CHECK_HALT, g_dsp.cr & 0x04 ? true : false); + m_Toolbar->ToggleTool(ID_CHECK_INIT, g_dsp.cr & 0x800 ? true : false); + + m_CachedCR = g_dsp.cr; +} + +bool DSPDebuggerLLE::CanDoStep() +{ + // update the symbols all the time because they're script cmds like bps + UpdateSymbolMap(); + + switch (m_State) + { + case RUN_START: + m_State = RUN; + return true; + + case RUN: + + if (IsBreakPoint(g_dsp.pc)) + { + Refresh(); + m_State = PAUSE; + return false; + } + + return true; + + case PAUSE: + Refresh(); + return false; + + case STEP: + Refresh(); + m_State = PAUSE; + return true; + } + + return false; +} + +void DSPDebuggerLLE::DebugBreak() +{ + m_State = PAUSE; +} + +bool DSPDebuggerLLE::IsBreakPoint(u16 _Address) +{ + return(std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address) != m_BreakPoints.end()); +} + +void DSPDebuggerLLE::ToggleBreakPoint(u16 _Address) +{ + if (IsBreakPoint(_Address)) + RemoveBreakPoint(_Address); + else + AddBreakPoint(_Address); +} + +void DSPDebuggerLLE::RemoveBreakPoint(u16 _Address) +{ + CBreakPointList::iterator itr = std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address); + + if (itr != m_BreakPoints.end()) + m_BreakPoints.erase(itr); +} + +void DSPDebuggerLLE::AddBreakPoint(u16 _Address) +{ + CBreakPointList::iterator itr = std::find(m_BreakPoints.begin(), m_BreakPoints.end(), _Address); + + if (itr == m_BreakPoints.end()) + m_BreakPoints.push_back(_Address); +} + +void DSPDebuggerLLE::ClearBreakPoints() +{ + m_BreakPoints.clear(); +} + +bool DSPDebuggerLLE::LoadSymbolMap(const char* _pFileName) +{ + m_SymbolMap.clear(); + + FILE* pFile = fopen(_pFileName, "r"); + + if (!pFile) + return false; + + char Name[1024]; + u32 AddressStart, AddressEnd; + + while (!feof(pFile)) + { + char line[512]; + fgets(line, 511, pFile); + + if (strlen(line) < 2) + continue; + + // check for comment + if (line[0] == '.') + continue; + + // clear all breakpoints + if (line[0] == 'C') + { + ClearBreakPoints(); + continue; + } + + // add breakpoint + if (line[0] == 'B') + { + sscanf(line, "B %04x", &AddressStart); + AddBreakPoint(static_cast(AddressStart)); + continue; + } + + // default add new symbol + sscanf(line, "%04x %04x %s", &AddressStart, &AddressEnd, Name); + + if (m_SymbolMap.find(AddressStart) == m_SymbolMap.end()) + m_SymbolMap.insert(std::pair(AddressStart, SSymbol(AddressStart, AddressEnd, Name))); + else + m_SymbolMap[AddressStart] = SSymbol(AddressStart, AddressEnd, Name); + } + + fclose(pFile); + + return true; } diff --git a/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.h b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.h index d7079e47bc..8eb1c49bf8 100644 --- a/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.h +++ b/Source/Plugins/Plugin_DSP_LLE-testing/Src/Debugger/Debugger.h @@ -1,63 +1,155 @@ -#pragma once +// Copyright (C) 2003-2009 Dolphin Project. -#ifndef __CDebugger_h__ -#define __CDebugger_h__ +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _DSP_DEBUGGER_LLE_H +#define _DSP_DEBUGGER_LLE_H // general things #include #include +#include +#include +#include -#ifndef WX_PRECOMP #include -#include -#else -#include -#endif - +#include #include #include #include -#include -#include // for the timestamps - #include -#include -#include #include -#include +#include -//#include "../Globals.h" +#include "../disassemble.h" +#include "../gdsp_interpreter.h" +#include "../gdsp_memory.h" -//class CPBView; -//class IniFile; +class DSPRegisterView; -// Window settings -#undef CDebugger_STYLE -#define CDebugger_STYLE wxDEFAULT_FRAME_STYLE | wxCLIP_CHILDREN | wxNO_FULL_REPAINT_ON_RESIZE - -class CDebugger : public wxDialog +class DSPDebuggerLLE : public wxFrame { +public: + DSPDebuggerLLE(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString &title = wxT("DSP LLE Debugger"), + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE); + + virtual ~DSPDebuggerLLE(); + + bool CanDoStep(); + void DebugBreak(); + private: DECLARE_EVENT_TABLE(); -public: - CDebugger(wxWindow *parent, wxWindowID id = 1, const wxString &title = _("Sound Debugger"), - const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = CDebugger_STYLE); - - virtual ~CDebugger(); - - void DoHide(); - void DoShow(); -private: - // WARNING: Make sure these are not also elsewhere enum { - // = 2000, + // Toolbar + ID_TOOLBAR = 1000, + ID_RUNTOOL, + ID_PAUSETOOL, + ID_STEPTOOL, + ID_RESETTOPCTOOL, + ID_JUMPTOTOOL, + ID_CHECK_ASSERTINT, + ID_CHECK_HALT, + ID_CHECK_INIT, + ID_DUMPCODETOOL, + + // Disasm view + ID_DISASM, + + // Register View + ID_DSP_REGS, }; - void OnClose(wxCloseEvent& event); - void CreateGUIControls(); + // Disasm listctrl columns + enum + { + COLUMN_BP, + COLUMN_FUNCTION, + COLUMN_ADDRESS, + COLUMN_MNEMONIC, + COLUMN_OPCODE, + COLUMN_EXT, + COLUMN_PARAM, + }; + + enum EState + { + PAUSE, + STEP, + RUN, + RUN_START // ignores breakpoints and switches after one step to RUN + }; + EState m_State; + + u64 m_CachedStepCounter; + u16 m_CachedCR; + u32 m_CachedUCodeCRC; + + // Break point handling + typedef std::listCBreakPointList; + CBreakPointList m_BreakPoints; + + bool IsBreakPoint(u16 _Address); + void ToggleBreakPoint(u16 _Address); + void RemoveBreakPoint(u16 _Address); + void AddBreakPoint(u16 _Address); + void ClearBreakPoints(); + + // Symbols + struct SSymbol + { + u32 AddressStart; + u32 AddressEnd; + std::string Name; + + SSymbol(u32 _AddressStart = 0, u32 _AddressEnd = 0, char* _Name = NULL) + : AddressStart(_AddressStart) + , AddressEnd(_AddressEnd) + , Name(_Name) + { + } + }; + typedef std::mapCSymbolMap; + CSymbolMap m_SymbolMap; + + bool LoadSymbolMap(const char* _pFileName); + + // GUI updaters + void UpdateDisAsmListView(); + void UpdateRegisterFlags(); + void UpdateSymbolMap(); + + void RebuildDisAsmListView(); + + // GUI items + wxToolBar* m_Toolbar; + wxListCtrl* m_Disasm; + DSPRegisterView* m_Regs; + + void OnClose(wxCloseEvent& event); + void OnChangeSize(wxSizeEvent& event); + + void CreateGUIControls(); + void Refresh(); }; -#endif +#endif //_DSP_DEBUGGER_LLE_H diff --git a/Source/Plugins/Plugin_DSP_LLE-testing/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE-testing/Src/main.cpp index ad661732fa..2ef038d844 100644 --- a/Source/Plugins/Plugin_DSP_LLE-testing/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE-testing/Src/main.cpp @@ -36,8 +36,8 @@ #if defined(HAVE_WX) && HAVE_WX #include "DSPConfigDlgLLE.h" -#include "Debugger/Debugger.h" // For the CDebugger class -CDebugger* m_frame = NULL; +#include "Debugger/Debugger.h" // For the DSPDebuggerLLE class +DSPDebuggerLLE* m_DebuggerFrame = NULL; #endif PLUGIN_GLOBALS* globals = NULL; @@ -168,19 +168,8 @@ void DoState(unsigned char **ptr, int mode) void DllDebugger(HWND _hParent, bool Show) { #if defined(HAVE_WX) && HAVE_WX - if (m_frame && Show) // if we have created it, let us show it again - { - m_frame->DoShow(); - } - else if (!m_frame && Show) - { - m_frame = new CDebugger(NULL); - m_frame->Show(); - } - else if (m_frame && !Show) - { - m_frame->DoHide(); - } + DSPDebuggerLLE *debugger = new DSPDebuggerLLE(NULL); + debugger->Show(); #endif } @@ -202,11 +191,29 @@ THREAD_RETURN dsp_thread(void* lpParameter) // Debug thread THREAD_RETURN dsp_thread_debug(void* lpParameter) { +#if defined(HAVE_WX) && HAVE_WX + while (bIsRunning) + { +// Logging(); // logging + + if (m_DebuggerFrame->CanDoStep()) + { + gdsp_runx(1); + } + else + { + Sleep(100); + } + } +#endif return NULL; } void DSP_DebugBreak() { +#if defined(HAVE_WX) && HAVE_WX + m_DebuggerFrame->DebugBreak(); +#endif } @@ -348,7 +355,13 @@ void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail) void DSP_Update(int cycles) { - soundStream->Update(); + soundStream->Update(); + +#if defined(HAVE_WX) && HAVE_WX + // TODO fix? dunno how we should handle debug thread or whatever +// if (m_DebuggerFrame->CanDoStep()) +// gdsp_runx(100); // cycles +#endif } void DSP_SendAIBuffer(unsigned int address, int sample_rate)