Debugger: Added function list (based on JSR calls)

This commit is contained in:
Souryo 2016-11-20 13:15:37 -05:00
parent ebd5fd318c
commit 1215b3e813
12 changed files with 449 additions and 28 deletions

View file

@ -136,6 +136,11 @@ bool CodeDataLogger::IsCode(uint32_t absoluteAddr)
return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::Code) == (uint8_t)CdlPrgFlags::Code;
}
bool CodeDataLogger::IsSubEntryPoint(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::SubEntryPoint) == (uint8_t)CdlPrgFlags::SubEntryPoint;
}
bool CodeDataLogger::IsData(uint32_t absoluteAddr)
{
return (_cdlData[absoluteAddr] & (uint8_t)CdlPrgFlags::Data) == (uint8_t)CdlPrgFlags::Data;

View file

@ -10,6 +10,7 @@ enum class CdlPrgFlags
IndirectCode = 0x10,
IndirectData = 0x20,
PcmData = 0x40,
SubEntryPoint = 0x80
};
enum class CdlChrFlags
@ -59,6 +60,7 @@ public:
CdlRatios GetRatios();
bool IsCode(uint32_t absoluteAddr);
bool IsSubEntryPoint(uint32_t absoluteAddr);
bool IsData(uint32_t absoluteAddr);
bool IsRead(uint32_t absoluteAddr);
bool IsDrawn(uint32_t absoluteAddr);

View file

@ -100,6 +100,13 @@ bool Debugger::LoadCdlFile(string cdlFilepath)
i = _disassembler->BuildCache(i, -1, 0xFFFF, false) - 1;
}
}
for(int i = 0, len = _mapper->GetPrgSize(); i < len; i++) {
if(_codeDataLogger->IsSubEntryPoint(i)) {
_functionEntryPoints.emplace(i);
}
}
return true;
}
return false;
@ -282,11 +289,15 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
}
if(type == MemoryOperationType::ExecOpCode) {
bool isSubEntryPoint = _lastInstruction == 0x20; //Previous instruction was a JSR
if(absoluteAddr >= 0) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::Code);
if(isSubEntryPoint) {
_codeDataLogger->SetFlag(absoluteAddr, CdlPrgFlags::SubEntryPoint);
_functionEntryPoints.emplace(absoluteAddr);
}
}
bool isSubEntryPoint = _lastInstruction == 0x20; //Previous instruction was a JSR
_disassembler->BuildCache(absoluteAddr, absoluteRamAddr, addr, isSubEntryPoint);
_lastInstruction = _memoryManager->DebugRead(addr);
@ -484,12 +495,12 @@ uint8_t Debugger::GetMemoryValue(uint32_t addr)
return _memoryManager->DebugRead(addr);
}
uint32_t Debugger::GetRelativeAddress(uint32_t addr)
int32_t Debugger::GetRelativeAddress(uint32_t addr)
{
return _mapper->FromAbsoluteAddress(addr);
}
uint32_t Debugger::GetAbsoluteAddress(uint32_t addr)
int32_t Debugger::GetAbsoluteAddress(uint32_t addr)
{
return _mapper->ToAbsoluteAddress(addr);
}
@ -551,6 +562,16 @@ void Debugger::GetCallstack(int32_t* callstackAbsolute, int32_t* callstackRelati
callstackRelative[_callstackRelative.size()] = -2;
}
void Debugger::GetFunctionEntryPoints(int32_t* entryPoints)
{
uint32_t i = 0;
for(auto itt = _functionEntryPoints.begin(); itt != _functionEntryPoints.end(); itt++) {
entryPoints[i] = *itt;
i++;
}
entryPoints[i] = -1;
}
shared_ptr<MemoryDumper> Debugger::GetMemoryDumper()
{
return _memoryDumper;

View file

@ -3,8 +3,10 @@
#include "stdafx.h"
#include <atomic>
#include <deque>
#include <unordered_set>
using std::atomic;
using std::deque;
using std::unordered_set;
#include "DebugState.h"
#include "Breakpoint.h"
@ -55,6 +57,8 @@ private:
deque<uint32_t> _callstackAbsolute;
deque<uint32_t> _callstackRelative;
unordered_set<uint32_t> _functionEntryPoints;
DebugState _debugState;
SimpleLock _breakLock;
@ -96,6 +100,7 @@ public:
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
void GetFunctionEntryPoints(int32_t* entryPoints);
void GetCallstack(int32_t* callstackAbsolute, int32_t* callstackRelative);
void GetState(DebugState *state);
@ -121,8 +126,8 @@ public:
string* GetCode();
uint8_t GetMemoryValue(uint32_t addr);
uint32_t GetRelativeAddress(uint32_t addr);
uint32_t GetAbsoluteAddress(uint32_t addr);
int32_t GetRelativeAddress(uint32_t addr);
int32_t GetAbsoluteAddress(uint32_t addr);
void StartTraceLogger(TraceLoggerOptions options);
void StopTraceLogger();

View file

@ -0,0 +1,89 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlFunctionList
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lstFunctions = new System.Windows.Forms.ListView();
this.colFunctionLabel = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colFunctionAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colMemoryAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.SuspendLayout();
//
// lstFunctions
//
this.lstFunctions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colFunctionLabel,
this.colFunctionAddress,
this.colMemoryAddress});
this.lstFunctions.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstFunctions.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lstFunctions.FullRowSelect = true;
this.lstFunctions.GridLines = true;
this.lstFunctions.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.lstFunctions.Location = new System.Drawing.Point(0, 0);
this.lstFunctions.MultiSelect = false;
this.lstFunctions.Name = "lstFunctions";
this.lstFunctions.Size = new System.Drawing.Size(275, 112);
this.lstFunctions.TabIndex = 2;
this.lstFunctions.UseCompatibleStateImageBehavior = false;
this.lstFunctions.View = System.Windows.Forms.View.Details;
this.lstFunctions.DoubleClick += new System.EventHandler(this.lstFunctions_DoubleClick);
//
// colFunctionLabel
//
this.colFunctionLabel.Text = "Label";
this.colFunctionLabel.Width = 136;
//
// colFunctionAddress
//
this.colFunctionAddress.Text = "Address";
this.colFunctionAddress.Width = 62;
//
// colMemoryAddress
//
this.colMemoryAddress.Text = "ROM Addr.";
this.colMemoryAddress.Width = 71;
//
// ctrlFunctionList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.lstFunctions);
this.Name = "ctrlFunctionList";
this.Size = new System.Drawing.Size(275, 112);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListView lstFunctions;
private System.Windows.Forms.ColumnHeader colFunctionLabel;
private System.Windows.Forms.ColumnHeader colFunctionAddress;
private System.Windows.Forms.ColumnHeader colMemoryAddress;
}
}

View file

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlFunctionList : UserControl
{
public event EventHandler OnFunctionSelected;
public ctrlFunctionList()
{
InitializeComponent();
}
private class FunctionComparer : IComparer
{
int IComparer.Compare(object x, object y)
{
ListViewItem a = x as ListViewItem;
ListViewItem b = y as ListViewItem;
string aText = string.IsNullOrWhiteSpace(a.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : a.Text;
string bText = string.IsNullOrWhiteSpace(b.Text) ? "ZZZZZZZZZZZZZZZZZZZZZZZ" : b.Text;
Int32 aRelative = (Int32)a.Tag == -1 ? Int32.MaxValue : (Int32)a.Tag;
Int32 bRelative = (Int32)b.Tag == -1 ? Int32.MaxValue : (Int32)b.Tag;
Int32 aAbsolute = (Int32)a.SubItems[1].Tag;
Int32 bAbsolute = (Int32)b.SubItems[1].Tag;
if(a.Text == b.Text) {
if(a.Tag == b.Tag) {
return aAbsolute > bAbsolute ? 1 : -1;
} else {
return aRelative > bRelative ? 1 : -1;
}
} else {
return string.Compare(aText, bText);
}
}
}
public void UpdateFunctionList()
{
Int32[] entryPoints = InteropEmu.DebugGetFunctionEntryPoints();
lstFunctions.BeginUpdate();
lstFunctions.ListViewItemSorter = null;
lstFunctions.Items.Clear();
for(int i = 0; entryPoints[i] >= 0; i++) {
ListViewItem item = lstFunctions.Items.Add("");
Int32 relativeAddress = InteropEmu.DebugGetRelativeAddress((UInt32)entryPoints[i]);
if(relativeAddress >= 0) {
item.SubItems.Add("$" + relativeAddress.ToString("X4"));
} else {
item.SubItems.Add("[n/a]");
item.ForeColor = Color.Gray;
item.Font = new Font(item.Font, FontStyle.Italic);
}
item.SubItems.Add("$" + entryPoints[i].ToString("X4"));
item.SubItems[1].Tag = entryPoints[i];
item.Tag = relativeAddress;
}
lstFunctions.ListViewItemSorter = new FunctionComparer();
lstFunctions.Sort();
lstFunctions.EndUpdate();
}
private void lstFunctions_DoubleClick(object sender, EventArgs e)
{
if(lstFunctions.SelectedItems.Count > 0) {
Int32 relativeAddress = (Int32)lstFunctions.SelectedItems[0].Tag;
if(relativeAddress >= 0) {
OnFunctionSelected?.Invoke(relativeAddress, e);
}
}
}
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -41,6 +41,10 @@
this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus();
this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.grpLabels = new System.Windows.Forms.GroupBox();
this.grpFunctions = new System.Windows.Forms.GroupBox();
this.ctrlFunctionList = new Mesen.GUI.Debugger.Controls.ctrlFunctionList();
this.tableLayoutPanel10 = new System.Windows.Forms.TableLayoutPanel();
this.grpWatch = new System.Windows.Forms.GroupBox();
this.picWatchHelp = new System.Windows.Forms.PictureBox();
@ -113,6 +117,8 @@
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.tlpTop.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.grpFunctions.SuspendLayout();
this.tableLayoutPanel10.SuspendLayout();
this.grpWatch.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
@ -168,25 +174,27 @@
//
this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10);
this.splitContainer.Panel2MinSize = 100;
this.splitContainer.Size = new System.Drawing.Size(984, 534);
this.splitContainer.Size = new System.Drawing.Size(1258, 534);
this.splitContainer.SplitterDistance = 387;
this.splitContainer.TabIndex = 1;
//
// tlpTop
//
this.tlpTop.ColumnCount = 3;
this.tlpTop.ColumnCount = 4;
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 0F));
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpTop.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 310F));
this.tlpTop.Controls.Add(this.ctrlDebuggerCode, 0, 0);
this.tlpTop.Controls.Add(this.ctrlConsoleStatus, 2, 0);
this.tlpTop.Controls.Add(this.ctrlDebuggerCodeSplit, 1, 0);
this.tlpTop.Controls.Add(this.tableLayoutPanel1, 3, 0);
this.tlpTop.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpTop.Location = new System.Drawing.Point(0, 0);
this.tlpTop.Name = "tlpTop";
this.tlpTop.RowCount = 1;
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpTop.Size = new System.Drawing.Size(984, 387);
this.tlpTop.Size = new System.Drawing.Size(1258, 387);
this.tlpTop.TabIndex = 2;
//
// ctrlDebuggerCode
@ -196,7 +204,7 @@
this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3);
this.ctrlDebuggerCode.Name = "ctrlDebuggerCode";
this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 381);
this.ctrlDebuggerCode.Size = new System.Drawing.Size(510, 381);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnWatchAdded);
this.ctrlDebuggerCode.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement);
@ -205,7 +213,7 @@
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0);
this.ctrlConsoleStatus.Location = new System.Drawing.Point(516, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362);
@ -215,7 +223,7 @@
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3);
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(519, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 381);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
@ -224,6 +232,52 @@
this.ctrlDebuggerCodeSplit.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement);
this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter);
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.grpLabels, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.grpFunctions, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(948, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(310, 387);
this.tableLayoutPanel1.TabIndex = 5;
//
// grpLabels
//
this.grpLabels.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpLabels.Location = new System.Drawing.Point(3, 196);
this.grpLabels.Name = "grpLabels";
this.grpLabels.Size = new System.Drawing.Size(304, 188);
this.grpLabels.TabIndex = 6;
this.grpLabels.TabStop = false;
this.grpLabels.Text = "Labels and Comments";
//
// grpFunctions
//
this.grpFunctions.Controls.Add(this.ctrlFunctionList);
this.grpFunctions.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpFunctions.Location = new System.Drawing.Point(3, 3);
this.grpFunctions.Name = "grpFunctions";
this.grpFunctions.Size = new System.Drawing.Size(304, 187);
this.grpFunctions.TabIndex = 5;
this.grpFunctions.TabStop = false;
this.grpFunctions.Text = "Functions";
//
// ctrlFunctionList
//
this.ctrlFunctionList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlFunctionList.Location = new System.Drawing.Point(3, 16);
this.ctrlFunctionList.Name = "ctrlFunctionList";
this.ctrlFunctionList.Size = new System.Drawing.Size(298, 168);
this.ctrlFunctionList.TabIndex = 0;
this.ctrlFunctionList.OnFunctionSelected += new System.EventHandler(this.ctrlFunctionList_OnFunctionSelected);
//
// tableLayoutPanel10
//
this.tableLayoutPanel10.ColumnCount = 3;
@ -240,7 +294,7 @@
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.Size = new System.Drawing.Size(984, 143);
this.tableLayoutPanel10.Size = new System.Drawing.Size(1258, 143);
this.tableLayoutPanel10.TabIndex = 0;
//
// grpWatch
@ -250,7 +304,7 @@
this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpWatch.Location = new System.Drawing.Point(3, 3);
this.grpWatch.Name = "grpWatch";
this.grpWatch.Size = new System.Drawing.Size(321, 137);
this.grpWatch.Size = new System.Drawing.Size(413, 137);
this.grpWatch.TabIndex = 2;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
@ -270,16 +324,16 @@
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(3, 16);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(315, 118);
this.ctrlWatch.Size = new System.Drawing.Size(407, 118);
this.ctrlWatch.TabIndex = 0;
//
// grpBreakpoints
//
this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints);
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(330, 3);
this.grpBreakpoints.Location = new System.Drawing.Point(422, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(322, 137);
this.grpBreakpoints.Size = new System.Drawing.Size(413, 137);
this.grpBreakpoints.TabIndex = 3;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
@ -289,7 +343,7 @@
this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16);
this.ctrlBreakpoints.Name = "ctrlBreakpoints";
this.ctrlBreakpoints.Size = new System.Drawing.Size(316, 118);
this.ctrlBreakpoints.Size = new System.Drawing.Size(407, 118);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointNavigation += new System.EventHandler(this.ctrlBreakpoints_BreakpointNavigation);
//
@ -297,9 +351,9 @@
//
this.grpCallstack.Controls.Add(this.ctrlCallstack);
this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCallstack.Location = new System.Drawing.Point(658, 3);
this.grpCallstack.Location = new System.Drawing.Point(841, 3);
this.grpCallstack.Name = "grpCallstack";
this.grpCallstack.Size = new System.Drawing.Size(323, 137);
this.grpCallstack.Size = new System.Drawing.Size(414, 137);
this.grpCallstack.TabIndex = 4;
this.grpCallstack.TabStop = false;
this.grpCallstack.Text = "Callstack";
@ -309,7 +363,7 @@
this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCallstack.Location = new System.Drawing.Point(3, 16);
this.ctrlCallstack.Name = "ctrlCallstack";
this.ctrlCallstack.Size = new System.Drawing.Size(317, 118);
this.ctrlCallstack.Size = new System.Drawing.Size(408, 118);
this.ctrlCallstack.TabIndex = 0;
this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected);
//
@ -323,7 +377,7 @@
this.toolsToolStripMenuItem});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.Size = new System.Drawing.Size(984, 24);
this.menuStrip.Size = new System.Drawing.Size(1258, 24);
this.menuStrip.TabIndex = 2;
this.menuStrip.Text = "menuStrip1";
//
@ -747,7 +801,7 @@
this.lblChrAnalysisResult});
this.statusStrip.Location = new System.Drawing.Point(0, 638);
this.statusStrip.Name = "statusStrip";
this.statusStrip.Size = new System.Drawing.Size(984, 24);
this.statusStrip.Size = new System.Drawing.Size(1258, 24);
this.statusStrip.TabIndex = 3;
this.statusStrip.Text = "statusStrip1";
//
@ -783,7 +837,7 @@
this.ctrlPpuMemoryMapping.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ctrlPpuMemoryMapping.Location = new System.Drawing.Point(0, 558);
this.ctrlPpuMemoryMapping.Name = "ctrlPpuMemoryMapping";
this.ctrlPpuMemoryMapping.Size = new System.Drawing.Size(984, 40);
this.ctrlPpuMemoryMapping.Size = new System.Drawing.Size(1258, 40);
this.ctrlPpuMemoryMapping.TabIndex = 5;
this.ctrlPpuMemoryMapping.Text = "ctrlMemoryMapping1";
this.ctrlPpuMemoryMapping.Visible = false;
@ -793,7 +847,7 @@
this.ctrlCpuMemoryMapping.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ctrlCpuMemoryMapping.Location = new System.Drawing.Point(0, 598);
this.ctrlCpuMemoryMapping.Name = "ctrlCpuMemoryMapping";
this.ctrlCpuMemoryMapping.Size = new System.Drawing.Size(984, 40);
this.ctrlCpuMemoryMapping.Size = new System.Drawing.Size(1258, 40);
this.ctrlCpuMemoryMapping.TabIndex = 4;
this.ctrlCpuMemoryMapping.Text = "ctrlMemoryMapping1";
this.ctrlCpuMemoryMapping.Visible = false;
@ -802,7 +856,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(984, 662);
this.ClientSize = new System.Drawing.Size(1258, 662);
this.Controls.Add(this.splitContainer);
this.Controls.Add(this.ctrlPpuMemoryMapping);
this.Controls.Add(this.ctrlCpuMemoryMapping);
@ -820,6 +874,8 @@
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
this.splitContainer.ResumeLayout(false);
this.tlpTop.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.grpFunctions.ResumeLayout(false);
this.tableLayoutPanel10.ResumeLayout(false);
this.grpWatch.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
@ -911,5 +967,9 @@
private System.Windows.Forms.ToolStripMenuItem mnuShowPpuMemoryMapping;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem6;
private System.Windows.Forms.ToolStripMenuItem mnuShowEffectiveAddresses;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.GroupBox grpLabels;
private System.Windows.Forms.GroupBox grpFunctions;
private Controls.ctrlFunctionList ctrlFunctionList;
}
}

View file

@ -131,6 +131,7 @@ namespace Mesen.GUI.Debugger
private void UpdateDebugger()
{
ctrlFunctionList.UpdateFunctionList();
UpdateDebuggerFlags();
if(InteropEmu.DebugIsCodeChanged()) {
@ -452,5 +453,10 @@ namespace Mesen.GUI.Debugger
ctrlCpuMemoryMapping.Invalidate();
ctrlPpuMemoryMapping.Invalidate();
}
private void ctrlFunctionList_OnFunctionSelected(object relativeAddress, EventArgs e)
{
_lastCodeWindow.ScrollToLineNumber((Int32)relativeAddress);
}
}
}

View file

@ -278,6 +278,12 @@
<Compile Include="Debugger\Controls\ctrlAddressList.Designer.cs">
<DependentUpon>ctrlAddressList.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlFunctionList.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlFunctionList.Designer.cs">
<DependentUpon>ctrlFunctionList.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlMemoryMapping.cs" />
<Compile Include="Debugger\Controls\ctrlPaletteViewer.cs">
<SubType>UserControl</SubType>
@ -576,6 +582,9 @@
<EmbeddedResource Include="Debugger\Controls\ctrlAddressList.resx">
<DependentUpon>ctrlAddressList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlFunctionList.resx">
<DependentUpon>ctrlFunctionList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlPaletteViewer.resx">
<DependentUpon>ctrlPaletteViewer.cs</DependentUpon>
</EmbeddedResource>

View file

@ -175,7 +175,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugIsCodeChanged();
[DllImport(DLLPath)] public static extern IntPtr DebugGetCode();
[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr);
[DllImport(DLLPath)] public static extern UInt32 DebugGetRelativeAddress(UInt32 addr);
[DllImport(DLLPath)] public static extern Int32 DebugGetRelativeAddress(UInt32 addr);
[DllImport(DLLPath)] public static extern void DebugSetNextStatement(UInt16 addr);
[DllImport(DLLPath)] public static extern Int32 DebugEvaluateExpression([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string expression, out EvalResultType resultType);
@ -305,6 +305,22 @@ namespace Mesen.GUI
}
}
[DllImport(DLLPath, EntryPoint = "DebugGetFunctionEntryPoints")]
private static extern void DebugGetFunctionEntryPointsWrapper(IntPtr callstackAbsolute);
public static Int32[] DebugGetFunctionEntryPoints()
{
Int32[] entryPoints = new Int32[32768];
GCHandle hEntryPoints = GCHandle.Alloc(entryPoints, GCHandleType.Pinned);
try {
InteropEmu.DebugGetFunctionEntryPointsWrapper(hEntryPoints.AddrOfPinnedObject());
} finally {
hEntryPoints.Free();
}
return entryPoints;
}
public static NsfHeader NsfGetHeader()
{
NsfHeader header = new NsfHeader();

View file

@ -51,9 +51,10 @@ extern "C"
DllExport void __stdcall DebugGetPalette(uint32_t *frameBuffer) { GetDebugger()->GetMemoryDumper()->GetPalette(frameBuffer); }
DllExport void __stdcall DebugGetCallstack(int32_t *callstackAbsolute, int32_t *callstackRelative) { GetDebugger()->GetCallstack(callstackAbsolute, callstackRelative); }
DllExport void __stdcall DebugGetFunctionEntryPoints(int32_t *entryPoints) { GetDebugger()->GetFunctionEntryPoints(entryPoints); }
DllExport uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return GetDebugger()->GetMemoryValue(addr); }
DllExport uint32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return GetDebugger()->GetRelativeAddress(addr); }
DllExport int32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return GetDebugger()->GetRelativeAddress(addr); }
DllExport bool __stdcall DebugLoadCdlFile(char* cdlFilepath) { return GetDebugger()->LoadCdlFile(cdlFilepath); }
DllExport bool __stdcall DebugSaveCdlFile(char* cdlFilepath) { return GetDebugger()->SaveCdlFile(cdlFilepath); }