forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			287 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2009 Dolphin Emulator Project
 | 
						|
// Licensed under GPLv2+
 | 
						|
// Refer to the license.txt file included.
 | 
						|
 | 
						|
#include <cstdio>
 | 
						|
#include <wx/artprov.h>
 | 
						|
#include <wx/listbox.h>
 | 
						|
#include <wx/panel.h>
 | 
						|
#include <wx/sizer.h>
 | 
						|
#include <wx/textctrl.h>
 | 
						|
#include <wx/thread.h>
 | 
						|
#include <wx/aui/auibar.h>
 | 
						|
#include <wx/aui/auibook.h>
 | 
						|
#include <wx/aui/framemanager.h>
 | 
						|
 | 
						|
#include "Common/CommonTypes.h"
 | 
						|
#include "Common/StringUtil.h"
 | 
						|
#include "Common/SymbolDB.h"
 | 
						|
#include "Core/Host.h"
 | 
						|
#include "Core/DSP/DSPCore.h"
 | 
						|
#include "Core/HW/DSPLLE/DSPDebugInterface.h"
 | 
						|
#include "Core/HW/DSPLLE/DSPSymbols.h"
 | 
						|
#include "DolphinWX/WxUtils.h"
 | 
						|
#include "DolphinWX/Debugger/CodeView.h"
 | 
						|
#include "DolphinWX/Debugger/DSPDebugWindow.h"
 | 
						|
#include "DolphinWX/Debugger/DSPRegisterView.h"
 | 
						|
#include "DolphinWX/Debugger/MemoryView.h"
 | 
						|
 | 
						|
static DSPDebuggerLLE* m_DebuggerFrame = nullptr;
 | 
						|
 | 
						|
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow* parent, wxWindowID id)
 | 
						|
	: wxPanel(parent, id, wxDefaultPosition, wxDefaultSize,
 | 
						|
			wxTAB_TRAVERSAL, _("DSP LLE Debugger"))
 | 
						|
	, m_CachedStepCounter(-1)
 | 
						|
{
 | 
						|
	Bind(wxEVT_CLOSE_WINDOW, &DSPDebuggerLLE::OnClose, this);
 | 
						|
	Bind(wxEVT_MENU, &DSPDebuggerLLE::OnChangeState, this, ID_RUNTOOL, ID_SHOWPCTOOL);
 | 
						|
 | 
						|
	m_DebuggerFrame = this;
 | 
						|
 | 
						|
	// notify wxAUI which frame to use
 | 
						|
	m_mgr.SetManagedWindow(this);
 | 
						|
	m_mgr.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE);
 | 
						|
 | 
						|
	m_Toolbar = new wxAuiToolBar(this, ID_TOOLBAR,
 | 
						|
		wxDefaultPosition, wxDefaultSize, wxAUI_TB_HORZ_TEXT);
 | 
						|
	m_Toolbar->AddTool(ID_RUNTOOL, _("Pause"),
 | 
						|
		wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, wxSize(10,10)));
 | 
						|
	m_Toolbar->AddTool(ID_STEPTOOL, _("Step"),
 | 
						|
		wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_OTHER, wxSize(10,10)));
 | 
						|
	m_Toolbar->AddTool(ID_SHOWPCTOOL, _("Show PC"),
 | 
						|
		wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_OTHER, wxSize(10,10)));
 | 
						|
	m_Toolbar->AddSeparator();
 | 
						|
 | 
						|
	m_addr_txtctrl = new wxTextCtrl(m_Toolbar, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
 | 
						|
	m_addr_txtctrl->Bind(wxEVT_TEXT_ENTER, &DSPDebuggerLLE::OnAddrBoxChange, this);
 | 
						|
 | 
						|
	m_Toolbar->AddControl(m_addr_txtctrl);
 | 
						|
	m_Toolbar->Realize();
 | 
						|
 | 
						|
	m_SymbolList = new wxListBox(this, wxID_ANY, wxDefaultPosition,
 | 
						|
		wxSize(140, 100), 0, nullptr, wxLB_SORT);
 | 
						|
	m_SymbolList->Bind(wxEVT_LISTBOX, &DSPDebuggerLLE::OnSymbolListChange, this);
 | 
						|
 | 
						|
	m_MainNotebook = new wxAuiNotebook(this, wxID_ANY,
 | 
						|
		wxDefaultPosition, wxDefaultSize,
 | 
						|
		wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE);
 | 
						|
 | 
						|
	wxPanel *code_panel = new wxPanel(m_MainNotebook, wxID_ANY);
 | 
						|
	wxBoxSizer *code_sizer = new wxBoxSizer(wxVERTICAL);
 | 
						|
	m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, code_panel);
 | 
						|
	m_CodeView->SetPlain();
 | 
						|
	code_sizer->Add(m_CodeView, 1, wxALL | wxEXPAND);
 | 
						|
	code_panel->SetSizer(code_sizer);
 | 
						|
	m_MainNotebook->AddPage(code_panel, _("Disassembly"), true);
 | 
						|
 | 
						|
	wxPanel *mem_panel = new wxPanel(m_MainNotebook, wxID_ANY);
 | 
						|
	wxBoxSizer *mem_sizer = new wxBoxSizer(wxVERTICAL);
 | 
						|
	// TODO insert memViewer class
 | 
						|
	m_MemView = new CMemoryView(&debug_interface, mem_panel);
 | 
						|
	mem_sizer->Add(m_MemView, 1, wxALL | wxEXPAND);
 | 
						|
	mem_panel->SetSizer(mem_sizer);
 | 
						|
	m_MainNotebook->AddPage(mem_panel, _("Memory"));
 | 
						|
 | 
						|
	m_Regs = new DSPRegisterView(this);
 | 
						|
 | 
						|
	// add the panes to the manager
 | 
						|
	m_mgr.AddPane(m_Toolbar, wxAuiPaneInfo().
 | 
						|
		ToolbarPane().Top().
 | 
						|
		LeftDockable(false).RightDockable(false));
 | 
						|
 | 
						|
	m_mgr.AddPane(m_SymbolList, wxAuiPaneInfo().
 | 
						|
		Left().CloseButton(false).
 | 
						|
		Caption(_("Symbols")).Dockable(true));
 | 
						|
 | 
						|
	m_mgr.AddPane(m_MainNotebook, wxAuiPaneInfo().
 | 
						|
		Name("m_MainNotebook").Center().
 | 
						|
		CloseButton(false).MaximizeButton(true));
 | 
						|
 | 
						|
	m_mgr.AddPane(m_Regs, wxAuiPaneInfo().Right().
 | 
						|
		CloseButton(false).Caption(_("Registers")).
 | 
						|
		Dockable(true));
 | 
						|
 | 
						|
	UpdateState();
 | 
						|
 | 
						|
	m_mgr.Update();
 | 
						|
}
 | 
						|
 | 
						|
DSPDebuggerLLE::~DSPDebuggerLLE()
 | 
						|
{
 | 
						|
	m_mgr.UnInit();
 | 
						|
	m_DebuggerFrame = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
 | 
						|
{
 | 
						|
	event.Skip();
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
 | 
						|
{
 | 
						|
	if (DSPCore_GetState() == DSPCORE_STOP)
 | 
						|
		return;
 | 
						|
 | 
						|
	switch (event.GetId())
 | 
						|
	{
 | 
						|
		case ID_RUNTOOL:
 | 
						|
			if (DSPCore_GetState() == DSPCORE_RUNNING)
 | 
						|
				DSPCore_SetState(DSPCORE_STEPPING);
 | 
						|
			else
 | 
						|
				DSPCore_SetState(DSPCORE_RUNNING);
 | 
						|
			break;
 | 
						|
 | 
						|
		case ID_STEPTOOL:
 | 
						|
			if (DSPCore_GetState() == DSPCORE_STEPPING)
 | 
						|
			{
 | 
						|
				DSPCore_Step();
 | 
						|
				Update();
 | 
						|
			}
 | 
						|
			break;
 | 
						|
 | 
						|
		case ID_SHOWPCTOOL:
 | 
						|
			FocusOnPC();
 | 
						|
			break;
 | 
						|
	}
 | 
						|
 | 
						|
	UpdateState();
 | 
						|
	m_mgr.Update();
 | 
						|
}
 | 
						|
 | 
						|
void Host_RefreshDSPDebuggerWindow()
 | 
						|
{
 | 
						|
	if (m_DebuggerFrame)
 | 
						|
		m_DebuggerFrame->Update();
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::Update()
 | 
						|
{
 | 
						|
#if defined __WXGTK__
 | 
						|
	if (!wxIsMainThread())
 | 
						|
		wxMutexGuiEnter();
 | 
						|
#endif
 | 
						|
	UpdateSymbolMap();
 | 
						|
	UpdateDisAsmListView();
 | 
						|
	UpdateRegisterFlags();
 | 
						|
	UpdateState();
 | 
						|
#if defined __WXGTK__
 | 
						|
	if (!wxIsMainThread())
 | 
						|
		wxMutexGuiLeave();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::FocusOnPC()
 | 
						|
{
 | 
						|
	JumpToAddress(g_dsp.pc);
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::UpdateState()
 | 
						|
{
 | 
						|
	if (DSPCore_GetState() == DSPCORE_RUNNING)
 | 
						|
	{
 | 
						|
		m_Toolbar->SetToolLabel(ID_RUNTOOL, _("Pause"));
 | 
						|
		m_Toolbar->SetToolBitmap(ID_RUNTOOL,
 | 
						|
			wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, wxSize(10,10)));
 | 
						|
		m_Toolbar->EnableTool(ID_STEPTOOL, false);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		m_Toolbar->SetToolLabel(ID_RUNTOOL, _("Run"));
 | 
						|
		m_Toolbar->SetToolBitmap(ID_RUNTOOL,
 | 
						|
			wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_OTHER, wxSize(10,10)));
 | 
						|
		m_Toolbar->EnableTool(ID_STEPTOOL, true);
 | 
						|
	}
 | 
						|
	m_Toolbar->Realize();
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::UpdateDisAsmListView()
 | 
						|
{
 | 
						|
	if (m_CachedStepCounter == g_dsp.step_counter)
 | 
						|
		return;
 | 
						|
 | 
						|
	// show PC
 | 
						|
	FocusOnPC();
 | 
						|
	m_CachedStepCounter = g_dsp.step_counter;
 | 
						|
	m_Regs->Update();
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::UpdateSymbolMap()
 | 
						|
{
 | 
						|
	if (g_dsp.dram == nullptr)
 | 
						|
		return;
 | 
						|
 | 
						|
	m_SymbolList->Freeze(); // HyperIris: wx style fast filling
 | 
						|
	m_SymbolList->Clear();
 | 
						|
	for (const auto& symbol : DSPSymbols::g_dsp_symbol_db.Symbols())
 | 
						|
	{
 | 
						|
		int idx = m_SymbolList->Append(StrToWxStr(symbol.second.name));
 | 
						|
		m_SymbolList->SetClientData(idx, (void*)&symbol.second);
 | 
						|
	}
 | 
						|
	m_SymbolList->Thaw();
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event)
 | 
						|
{
 | 
						|
	int index = m_SymbolList->GetSelection();
 | 
						|
	if (index >= 0)
 | 
						|
	{
 | 
						|
		Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index));
 | 
						|
		if (pSymbol != nullptr)
 | 
						|
		{
 | 
						|
			if (pSymbol->type == Symbol::SYMBOL_FUNCTION)
 | 
						|
			{
 | 
						|
				JumpToAddress(pSymbol->address);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::UpdateRegisterFlags()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
 | 
						|
{
 | 
						|
	wxString txt = m_addr_txtctrl->GetValue();
 | 
						|
 | 
						|
	auto text = StripSpaces(WxStrToStr(txt));
 | 
						|
	if (text.size())
 | 
						|
	{
 | 
						|
		u32 addr;
 | 
						|
		sscanf(text.c_str(), "%04x", &addr);
 | 
						|
		if (JumpToAddress(addr))
 | 
						|
			m_addr_txtctrl->SetBackgroundColour(*wxWHITE);
 | 
						|
		else
 | 
						|
			m_addr_txtctrl->SetBackgroundColour(*wxRED);
 | 
						|
	}
 | 
						|
	event.Skip();
 | 
						|
}
 | 
						|
 | 
						|
bool DSPDebuggerLLE::JumpToAddress(u16 addr)
 | 
						|
{
 | 
						|
	int page = m_MainNotebook->GetSelection();
 | 
						|
	if (page == 0)
 | 
						|
	{
 | 
						|
		// Center on valid instruction in IRAM/IROM
 | 
						|
		int new_line = DSPSymbols::Addr2Line(addr);
 | 
						|
		if (new_line >= 0)
 | 
						|
		{
 | 
						|
			m_CodeView->Center(new_line);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else if (page == 1)
 | 
						|
	{
 | 
						|
		// Center on any location in any valid ROM/RAM
 | 
						|
		int seg = addr >> 12;
 | 
						|
		if (seg == 0 || seg == 1 ||
 | 
						|
			seg == 8 || seg == 0xf)
 | 
						|
		{
 | 
						|
			m_MemView->Center(addr);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 |