2015-08-09 14:47:27 -04:00
|
|
|
|
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;
|
2016-12-11 14:25:29 -05:00
|
|
|
|
using Mesen.GUI.Controls;
|
2015-08-09 14:47:27 -04:00
|
|
|
|
|
|
|
|
|
namespace Mesen.GUI.Debugger.Controls
|
|
|
|
|
{
|
2016-12-11 14:25:29 -05:00
|
|
|
|
public partial class ctrlCallstack : BaseControl
|
2015-08-09 14:47:27 -04:00
|
|
|
|
{
|
2016-11-26 14:15:50 -05:00
|
|
|
|
private class StackInfo
|
|
|
|
|
{
|
|
|
|
|
public string SubName;
|
|
|
|
|
public bool IsMapped;
|
|
|
|
|
public int CurrentRelativeAddr;
|
|
|
|
|
public int CurrentAbsoluteAddr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-09 14:47:27 -04:00
|
|
|
|
public event EventHandler FunctionSelected;
|
|
|
|
|
|
|
|
|
|
private Int32[] _absoluteCallstack;
|
|
|
|
|
private Int32[] _relativeCallstack;
|
|
|
|
|
private Int32 _programCounter;
|
|
|
|
|
|
|
|
|
|
public ctrlCallstack()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateCallstack()
|
2016-11-26 14:15:50 -05:00
|
|
|
|
{
|
|
|
|
|
List<StackInfo> stack = GetStackInfo();
|
|
|
|
|
this.UpdateList(stack);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<StackInfo> GetStackInfo()
|
2015-08-09 14:47:27 -04:00
|
|
|
|
{
|
2017-03-04 21:50:19 -05:00
|
|
|
|
int nmiHandler = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFA) | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFB) << 8);
|
|
|
|
|
int irqHandler = InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFE) | (InteropEmu.DebugGetMemoryValue(DebugMemoryType.CpuMemory, 0xFFFF) << 8);
|
2016-11-22 00:14:49 -05:00
|
|
|
|
|
2015-08-09 14:47:27 -04:00
|
|
|
|
InteropEmu.DebugGetCallstack(out _absoluteCallstack, out _relativeCallstack);
|
|
|
|
|
DebugState state = new DebugState();
|
|
|
|
|
InteropEmu.DebugGetState(ref state);
|
|
|
|
|
_programCounter = state.CPU.DebugPC;
|
|
|
|
|
|
2016-11-26 14:15:50 -05:00
|
|
|
|
int relDestinationAddr = -1, absDestinationAddr = -1;
|
|
|
|
|
|
|
|
|
|
List<StackInfo> stack = new List<StackInfo>();
|
2015-08-09 14:47:27 -04:00
|
|
|
|
for(int i = 0, len = _relativeCallstack.Length; i < len; i+=2) {
|
|
|
|
|
if(_relativeCallstack[i] == -2) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-06-05 10:53:41 -04:00
|
|
|
|
|
2016-11-26 14:15:50 -05:00
|
|
|
|
int relSubEntryAddr = i == 0 ? -1 : _relativeCallstack[i-1] & 0xFFFF;
|
|
|
|
|
int absSubEntryAddr = i == 0 ? -1 : _absoluteCallstack[i-1];
|
|
|
|
|
|
|
|
|
|
stack.Add(new StackInfo() {
|
|
|
|
|
SubName = this.GetFunctionName(relSubEntryAddr, absSubEntryAddr, nmiHandler, irqHandler),
|
|
|
|
|
IsMapped = (_relativeCallstack[i] & 0x10000) != 0x10000,
|
|
|
|
|
CurrentRelativeAddr = _relativeCallstack[i] & 0xFFFF,
|
|
|
|
|
CurrentAbsoluteAddr = _absoluteCallstack[i]
|
|
|
|
|
});
|
2016-11-22 00:14:49 -05:00
|
|
|
|
|
|
|
|
|
relDestinationAddr = _relativeCallstack[i+1] & 0xFFFF;
|
|
|
|
|
absDestinationAddr = _absoluteCallstack[i+1];
|
2016-11-26 14:15:50 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Add current location
|
|
|
|
|
stack.Add(new StackInfo() {
|
|
|
|
|
SubName = this.GetFunctionName(relDestinationAddr, absDestinationAddr, nmiHandler, irqHandler),
|
|
|
|
|
IsMapped = true,
|
|
|
|
|
CurrentRelativeAddr = _programCounter,
|
|
|
|
|
CurrentAbsoluteAddr = InteropEmu.DebugGetAbsoluteAddress((UInt32)_programCounter)
|
|
|
|
|
});
|
2016-11-22 00:14:49 -05:00
|
|
|
|
|
2016-11-26 14:15:50 -05:00
|
|
|
|
return stack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateList(List<StackInfo> stack)
|
|
|
|
|
{
|
|
|
|
|
if(this.lstCallstack.Items.Count != stack.Count) {
|
|
|
|
|
this.lstCallstack.Items.Clear();
|
|
|
|
|
for(int i = 0, len = stack.Count; i < len; i++) {
|
|
|
|
|
this.lstCallstack.Items.Add("").SubItems.AddRange(new string[] { "", "" });
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-22 00:14:49 -05:00
|
|
|
|
|
2016-11-26 14:15:50 -05:00
|
|
|
|
for(int i = 0, len = stack.Count; i < len; i++) {
|
|
|
|
|
StackInfo stackInfo = stack[i];
|
|
|
|
|
ListViewItem item = this.lstCallstack.Items[len - i - 1];
|
|
|
|
|
|
|
|
|
|
item.Text = stackInfo.SubName;
|
|
|
|
|
item.SubItems[1].Text = "@ $" + stackInfo.CurrentRelativeAddr.ToString("X4");
|
|
|
|
|
item.SubItems[2].Text = "[$" + stackInfo.CurrentAbsoluteAddr.ToString("X4") + "]";
|
|
|
|
|
|
|
|
|
|
if(!stackInfo.IsMapped && item.ForeColor != Color.Gray) {
|
2015-08-09 14:47:27 -04:00
|
|
|
|
item.ForeColor = Color.Gray;
|
|
|
|
|
item.Font = new Font(item.Font, FontStyle.Italic);
|
2016-11-26 14:15:50 -05:00
|
|
|
|
} else if(stackInfo.IsMapped && item.ForeColor != Color.Black) {
|
|
|
|
|
item.ForeColor = Color.Black;
|
|
|
|
|
item.Font = new Font(item.Font, FontStyle.Regular);
|
2015-08-09 14:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-26 14:15:50 -05:00
|
|
|
|
}
|
2016-11-22 00:14:49 -05:00
|
|
|
|
|
2016-11-26 14:15:50 -05:00
|
|
|
|
private void UpdateList()
|
|
|
|
|
{
|
2016-11-22 00:14:49 -05:00
|
|
|
|
|
2015-08-09 14:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-22 00:14:49 -05:00
|
|
|
|
private string GetFunctionName(int relSubEntryAddr, int absSubEntryAddr, int nmiHandler, int irqHandler)
|
|
|
|
|
{
|
|
|
|
|
if(relSubEntryAddr < 0) {
|
|
|
|
|
return "[bottom of stack]";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string funcName;
|
2016-11-22 22:38:14 -05:00
|
|
|
|
CodeLabel label = LabelManager.GetLabel((UInt32)absSubEntryAddr, AddressType.PrgRom);
|
2016-11-22 00:14:49 -05:00
|
|
|
|
if(label != null) {
|
|
|
|
|
funcName = label.Label + (relSubEntryAddr >= 0 ? (" ($" + relSubEntryAddr.ToString("X4") + ")") : "");
|
|
|
|
|
} else {
|
|
|
|
|
funcName = (relSubEntryAddr >= 0 ? ("$" + relSubEntryAddr.ToString("X4")) : "n/a");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(relSubEntryAddr == nmiHandler) {
|
|
|
|
|
funcName = "[nmi] " + funcName;
|
|
|
|
|
} else if(relSubEntryAddr == irqHandler) {
|
|
|
|
|
funcName = "[irq] " + funcName;
|
|
|
|
|
}
|
|
|
|
|
return funcName;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-09 14:47:27 -04:00
|
|
|
|
private void lstCallstack_DoubleClick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if(this.lstCallstack.SelectedIndices.Count > 0) {
|
|
|
|
|
if(this.lstCallstack.SelectedIndices[0] == 0) {
|
|
|
|
|
this.FunctionSelected(_programCounter, null);
|
|
|
|
|
} else {
|
|
|
|
|
Int32 address = _relativeCallstack[(this.lstCallstack.Items.Count - 1 - this.lstCallstack.SelectedIndices[0]) * 2];
|
2016-11-22 00:14:49 -05:00
|
|
|
|
if((address & 0x10000) == 0) {
|
|
|
|
|
this.FunctionSelected?.Invoke(address & 0xFFFF, null);
|
2015-08-09 14:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|