Debugger: Improved watch window (now allows expressions like conditional breakpoints)

This commit is contained in:
Souryo 2016-01-10 13:23:19 -05:00
parent 7d0b9e8dd5
commit 9658597e9f
11 changed files with 224 additions and 96 deletions

View file

@ -153,7 +153,7 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
return true;
} else {
ExpressionEvaluator expEval;
if(expEval.Evaluate(condition, state, value)) {
if(expEval.Evaluate(condition, state, value) != 0) {
return true;
}
}
@ -163,6 +163,16 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
return false;
}
int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultType)
{
ExpressionEvaluator expEval;
DebugState state;
GetState(&state);
return expEval.Evaluate(expression, state, resultType);
}
void Debugger::UpdateCallstack(uint32_t addr)
{
if(_lastInstruction == 0x60 && !_callstackRelative.empty()) {

View file

@ -111,9 +111,11 @@ public:
bool IsCodeChanged();
string GenerateOutput();
string* GetCode();
uint8_t GetMemoryValue(uint32_t addr);
uint32_t GetRelativeAddress(uint32_t addr);
int32_t EvaluateExpression(string expression, EvalResultType &resultType);
static void ProcessRamOperation(MemoryOperationType type, uint16_t &addr, uint8_t value);
static void ProcessVramOperation(MemoryOperationType type, uint16_t addr, uint8_t value);

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include <climits>
#include "ExpressionEvaluator.h"
#include "Console.h"
#include "Debugger.h"
@ -51,7 +52,7 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str
do {
char c = std::tolower(expression[pos]);
if(c >= 'a' && c <= 'z') {
token += expression[pos];
token += c;
pos++;
} else {
break;
@ -91,22 +92,37 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos)
bool isOperator = false;
bool isNumber = false;
bool isHex = false;
bool isMemoryAddress = false;
bool validMemoryAddress = false;
size_t initialPos = pos;
for(size_t len = expression.size(); pos < len; pos++) {
char c = std::tolower(expression[pos]);
if(c == '$' && pos == initialPos) {
isHex = true;
if((c == '$' || c == '[') && pos == initialPos) {
if(c == '$') {
isHex = true;
} else if(c == '[') {
isMemoryAddress = true;
//Pretend the token starts after this
initialPos++;
}
} else if((c >= '0' && c <= '9') || (isHex && c >= 'a' && c <= 'f')) {
if(isNumber || output.empty()) {
output += c;
isNumber = true;
} else {
//Done reading number
//Just hit the start of a number, done reading current token
break;
}
} else if(isNumber) {
//First non-numeric character, done
if(c == ']') {
if(isMemoryAddress) {
validMemoryAddress = true;
}
pos++;
}
break;
} else if(c == '(' || c == ')' || c == '-' || c == '+' || c == '~') {
if(output.empty()) {
@ -118,10 +134,11 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos)
//Figure out if it's ! or !=
if(pos < len - 1) {
if(expression[pos + 1] == '=') {
pos++;
output += "!=";
pos+=2;
} else {
output += "!";
pos++;
}
}
break;
@ -155,6 +172,12 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos)
output = std::to_string(x);
}
if(isMemoryAddress && validMemoryAddress) {
uint32_t address = std::stoi(output) % 0xFFFF;
address += EvalValues::MemoryAddress;
output = std::to_string(address);
}
return output;
}
@ -209,12 +232,14 @@ void ExpressionEvaluator::ToRpn(string expression, vector<int> &outputQueue)
}
}
bool ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugState &state, int16_t memoryValue)
int32_t ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue)
{
int pos = 0;
int right = 0;
int left = 0;
int operandStack[1000];
resultType = EvalResultType::Numeric;
shared_ptr<Debugger> debugger = Console::GetInstance()->GetDebugger().lock();
for(size_t i = 0, len = outputQueue->size(); i < len; i++) {
int token = (*outputQueue)[i];
@ -233,12 +258,18 @@ bool ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugStat
case EvalValues::PpuScanline: token = state.PPU.Scanline; break;
case EvalValues::Value: token = memoryValue; break;
}
if(token >= EvalValues::MemoryAddress) {
uint16_t memoryAddress = token - EvalValues::MemoryAddress;
token = debugger->GetMemoryValue(memoryAddress);
}
} else if(token >= EvalOperators::Multiplication) {
right = operandStack[--pos];
if(pos > 0) {
left = operandStack[--pos];
}
resultType = EvalResultType::Numeric;
switch(token) {
case EvalOperators::Multiplication: token = left * right; break;
case EvalOperators::Division: token = left / right; break;
@ -247,17 +278,17 @@ bool ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugStat
case EvalOperators::Substration: token = left - right; break;
case EvalOperators::ShiftLeft: token = left << right; break;
case EvalOperators::ShiftRight: token = left >> right; break;
case EvalOperators::SmallerThan: token = left < right; break;
case EvalOperators::SmallerOrEqual: token = left <= right; break;
case EvalOperators::GreaterThan: token = left > right; break;
case EvalOperators::GreaterOrEqual: token = left >= right; break;
case EvalOperators::Equal: token = left == right; break;
case EvalOperators::NotEqual: token = left != right; break;
case EvalOperators::SmallerThan: token = left < right; resultType = EvalResultType::Boolean; break;
case EvalOperators::SmallerOrEqual: token = left <= right; resultType = EvalResultType::Boolean; break;
case EvalOperators::GreaterThan: token = left > right; resultType = EvalResultType::Boolean; break;
case EvalOperators::GreaterOrEqual: token = left >= right; resultType = EvalResultType::Boolean; break;
case EvalOperators::Equal: token = left == right; resultType = EvalResultType::Boolean; break;
case EvalOperators::NotEqual: token = left != right; resultType = EvalResultType::Boolean; break;
case EvalOperators::BinaryAnd: token = left & right; break;
case EvalOperators::BinaryXor: token = left | right; break;
case EvalOperators::BinaryOr: token = left ^ right; break;
case EvalOperators::LogicalAnd: token = left && right; break;
case EvalOperators::LogicalOr: token = left || right; break;
case EvalOperators::LogicalAnd: token = left && right; resultType = EvalResultType::Boolean; break;
case EvalOperators::LogicalOr: token = left || right; resultType = EvalResultType::Boolean; break;
//Unary operators
case EvalOperators::Plus: token = right; break;
@ -269,14 +300,14 @@ bool ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugStat
}
operandStack[pos++] = token;
}
return operandStack[0] != 0;
return operandStack[0];
}
ExpressionEvaluator::ExpressionEvaluator()
{
}
bool ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, int16_t memoryValue)
int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue)
{
vector<int> *outputQueue = nullptr;
@ -301,15 +332,22 @@ bool ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state,
outputQueue = &_outputCache[expression];
}
return EvaluateExpression(outputQueue, state, memoryValue);
return EvaluateExpression(outputQueue, state, resultType, memoryValue);
}
bool ExpressionEvaluator::Evaluate(string expression, DebugState &state, int16_t memoryValue)
int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, int16_t memoryValue)
{
EvalResultType resultType;
return Evaluate(expression, state, resultType, memoryValue);
}
int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue)
{
try {
return PrivateEvaluate(expression, state, memoryValue);
return PrivateEvaluate(expression, state, resultType, memoryValue);
} catch(std::exception) {
return false;
resultType = EvalResultType::Invalid;
return 0;
}
}
@ -317,7 +355,8 @@ bool ExpressionEvaluator::Validate(string expression)
{
try {
DebugState state;
PrivateEvaluate(expression, state, 0);
EvalResultType type;
PrivateEvaluate(expression, state, type, 0);
return true;
} catch(std::exception e) {
return false;

View file

@ -51,6 +51,15 @@ enum EvalValues
Nmi = 2000000107,
Irq = 2000000108,
Value = 2000000109,
MemoryAddress = 2000100000
};
enum EvalResultType
{
Numeric = 0,
Boolean = 1,
Invalid = 2
};
class StringHasher
@ -80,12 +89,13 @@ private:
bool CheckSpecialTokens(string expression, size_t &pos, string &output);
string GetNextToken(string expression, size_t &pos);
void ToRpn(string expression, vector<int> &outputQueue);
bool EvaluateExpression(vector<int> *outputQueue, DebugState &state, int16_t memoryValue);
bool PrivateEvaluate(string expression, DebugState &state, int16_t memoryValue);
int32_t EvaluateExpression(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue);
int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue);
public:
ExpressionEvaluator();
bool Evaluate(string expression, DebugState &state, int16_t memoryValue = 0);
int32_t Evaluate(string expression, DebugState &state, int16_t memoryValue = 0);
int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue = 0);
bool Validate(string expression);
};

View file

@ -11,13 +11,20 @@ namespace Mesen.GUI.Controls
{
class MyListView : ListView
{
private bool preventCheck = false;
private bool _preventCheck = false;
private int _editItemIndex = -1;
private string _originalText;
public bool IsEditing
{
get { return _editItemIndex >= 0; }
}
protected override void OnItemCheck(ItemCheckEventArgs e)
{
if(this.preventCheck) {
if(this._preventCheck) {
e.NewValue = e.CurrentValue;
this.preventCheck = false;
this._preventCheck = false;
} else
base.OnItemCheck(e);
}
@ -25,17 +32,64 @@ namespace Mesen.GUI.Controls
protected override void OnMouseDown(MouseEventArgs e)
{
if(e.Button == MouseButtons.Left && e.Clicks > 1) {
this.preventCheck = true;
this._preventCheck = true;
} else {
this.preventCheck = false;
this._preventCheck = false;
}
base.OnMouseDown(e);
}
protected override void OnBeforeLabelEdit(LabelEditEventArgs e)
{
_editItemIndex = e.Item;
base.OnBeforeLabelEdit(e);
}
protected override void OnAfterLabelEdit(LabelEditEventArgs e)
{
base.OnAfterLabelEdit(e);
_editItemIndex = -1;
}
protected override void OnKeyDown(KeyEventArgs e)
{
this.preventCheck = false;
if(!this.IsEditing && e.KeyData == Keys.Delete) {
if(this.SelectedItems.Count >= 1) {
var itemsToRemove = new List<ListViewItem>();
foreach(ListViewItem item in this.SelectedItems) {
itemsToRemove.Add(item);
}
foreach(ListViewItem item in itemsToRemove) {
this.Items.Remove(item);
}
}
}
this._preventCheck = false;
base.OnKeyDown(e);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(this.SelectedItems.Count > _editItemIndex && _editItemIndex >= 0) {
if(keyData == Keys.Escape) {
this.SelectedItems[_editItemIndex].Text = _originalText;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if(this.LabelEdit && _editItemIndex < 0 && this.SelectedItems.Count > 0) {
if(e.KeyChar >= 32 && e.KeyChar <= 127) {
_originalText = this.SelectedItems[0].Text;
this.SelectedItems[0].Text = e.KeyChar.ToString();
this.SelectedItems[0].BeginEdit();
SendKeys.Send("{RIGHT}");
}
}
base.OnKeyPress(e);
}
}
}

View file

@ -31,13 +31,13 @@
this.contextMenuBreakpoints = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuAddBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRemoveBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem();
this.lstBreakpoints = new Mesen.GUI.Controls.MyListView();
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colLastColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.mnuGoToLocation = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuBreakpoints.SuspendLayout();
this.SuspendLayout();
//
@ -54,6 +54,7 @@
// mnuAddBreakpoint
//
this.mnuAddBreakpoint.Name = "mnuAddBreakpoint";
this.mnuAddBreakpoint.ShortcutKeys = System.Windows.Forms.Keys.Insert;
this.mnuAddBreakpoint.Size = new System.Drawing.Size(152, 22);
this.mnuAddBreakpoint.Text = "Add...";
this.mnuAddBreakpoint.Click += new System.EventHandler(this.mnuAddBreakpoint_Click);
@ -66,6 +67,13 @@
this.mnuRemoveBreakpoint.Text = "Remove";
this.mnuRemoveBreakpoint.Click += new System.EventHandler(this.mnuRemoveBreakpoint_Click);
//
// mnuGoToLocation
//
this.mnuGoToLocation.Name = "mnuGoToLocation";
this.mnuGoToLocation.Size = new System.Drawing.Size(152, 22);
this.mnuGoToLocation.Text = "Go to location";
this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);
//
// lstBreakpoints
//
this.lstBreakpoints.CheckBoxes = true;
@ -114,13 +122,6 @@
//
this.colLastColumn.Text = "";
//
// mnuGoToLocation
//
this.mnuGoToLocation.Name = "mnuGoToLocation";
this.mnuGoToLocation.Size = new System.Drawing.Size(152, 22);
this.mnuGoToLocation.Text = "Go to location";
this.mnuGoToLocation.Click += new System.EventHandler(this.mnuGoToLocation_Click);
//
// ctrlBreakpoints
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

View file

@ -29,13 +29,13 @@
{
this.components = new System.ComponentModel.Container();
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("");
this.lstWatch = new System.Windows.Forms.ListView();
this.lstWatch = new Mesen.GUI.Controls.MyListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colLastColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.contextMenuWatch = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuRemoveWatch = new System.Windows.Forms.ToolStripMenuItem();
this.mnuHexDisplay = new System.Windows.Forms.ToolStripMenuItem();
this.colLastColumn = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.contextMenuWatch.SuspendLayout();
this.SuspendLayout();
//
@ -61,15 +61,22 @@
this.lstWatch.View = System.Windows.Forms.View.Details;
this.lstWatch.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.lstWatch_AfterLabelEdit);
this.lstWatch.SelectedIndexChanged += new System.EventHandler(this.lstWatch_SelectedIndexChanged);
this.lstWatch.Click += new System.EventHandler(this.lstWatch_Click);
this.lstWatch.DoubleClick += new System.EventHandler(this.lstWatch_DoubleClick);
//
// columnHeader1
//
this.columnHeader1.Text = "Address";
this.columnHeader1.Text = "Name";
this.columnHeader1.Width = 180;
//
// columnHeader2
//
this.columnHeader2.Text = "Value";
this.columnHeader2.Width = 100;
this.columnHeader2.Width = 110;
//
// colLastColumn
//
this.colLastColumn.Text = "";
//
// contextMenuWatch
//
@ -85,7 +92,6 @@
this.mnuRemoveWatch.ShortcutKeys = System.Windows.Forms.Keys.Delete;
this.mnuRemoveWatch.Size = new System.Drawing.Size(183, 22);
this.mnuRemoveWatch.Text = "Remove";
this.mnuRemoveWatch.Click += new System.EventHandler(this.mnuRemoveWatch_Click);
//
// mnuHexDisplay
//
@ -97,10 +103,6 @@
this.mnuHexDisplay.Text = "Hexadecimal Display";
this.mnuHexDisplay.Click += new System.EventHandler(this.mnuHexDisplay_Click);
//
// colLastColumn
//
this.colLastColumn.Text = "";
//
// ctrlWatch
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -115,7 +117,7 @@
#endregion
private System.Windows.Forms.ListView lstWatch;
private Mesen.GUI.Controls.MyListView lstWatch;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ContextMenuStrip contextMenuWatch;

View file

@ -49,7 +49,7 @@ namespace Mesen.GUI.Debugger
lstWatch.ColumnWidthChanged += lstWatch_ColumnWidthChanged;
}
public void UpdateWatch()
public void UpdateWatch(int currentSelection = -1)
{
lstWatch.SelectedIndices.Clear();
@ -70,20 +70,38 @@ namespace Mesen.GUI.Debugger
previousValue = item.SubItems[1].Text;
item.SubItems.RemoveAt(1);
}
item.SubItems[0].Text = item.SubItems[0].Text.ToUpper();
string newValue;
Byte memoryValue = InteropEmu.DebugGetMemoryValue((UInt32)item.Tag);
if(mnuHexDisplay.Checked) {
newValue = "$" + memoryValue.ToString("X");
} else {
newValue = memoryValue.ToString();
string newValue = "";
EvalResultType resultType;
Int32 result = InteropEmu.DebugEvaluateExpression(item.Text, out resultType);
switch(resultType) {
case EvalResultType.Numeric:
if(mnuHexDisplay.Checked) {
newValue = "$" + result.ToString("X");
} else {
newValue = result.ToString();
}
break;
case EvalResultType.Boolean:
newValue = result == 0 ? "false" : "true";
break;
case EvalResultType.Invalid:
newValue = "<invalid expression>";
break;
}
item.SubItems.Add(newValue);
item.SubItems[1].ForeColor = newValue != previousValue ? Color.Red : Color.Black;
}
}
AdjustColumnWidth();
if(currentSelection >= 0 && lstWatch.Items.Count > currentSelection) {
lstWatch.FocusedItem = lstWatch.Items[currentSelection];
lstWatch.Items[currentSelection].Selected = true;
}
}
public void AddWatch(UInt32 address)
@ -95,39 +113,7 @@ namespace Mesen.GUI.Debugger
private void lstWatch_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
e.CancelEdit = true;
if(e.Label != null) {
ListViewItem item = lstWatch.Items[e.Item];
item.Text = e.Label;
if(!string.IsNullOrWhiteSpace(item.Text)) {
if(!item.Text.StartsWith("$")) {
item.Text = "$" + item.Text;
}
UInt32 address;
if(UInt32.TryParse(item.Text.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier, null, out address)) {
lstWatch.Items[e.Item].Tag = address;
} else {
item.Text = string.Empty;
}
}
UpdateWatch();
}
}
private void mnuRemoveWatch_Click(object sender, EventArgs e)
{
if(lstWatch.SelectedItems.Count >= 1) {
var itemsToRemove = new List<ListViewItem>();
foreach(ListViewItem item in lstWatch.SelectedItems) {
itemsToRemove.Add(item);
}
foreach(ListViewItem item in itemsToRemove) {
lstWatch.Items.Remove(item);
}
UpdateWatch();
}
this.BeginInvoke((MethodInvoker)(() => { this.UpdateWatch(e.Item); }));
}
private void mnuHexDisplay_Click(object sender, EventArgs e)
@ -139,5 +125,19 @@ namespace Mesen.GUI.Debugger
{
mnuRemoveWatch.Enabled = lstWatch.SelectedItems.Count >= 1;
}
private void lstWatch_Click(object sender, EventArgs e)
{
if(lstWatch.SelectedItems.Count == 1 && string.IsNullOrWhiteSpace(lstWatch.SelectedItems[0].Text)) {
lstWatch.SelectedItems[0].BeginEdit();
}
}
private void lstWatch_DoubleClick(object sender, EventArgs e)
{
if(lstWatch.SelectedItems.Count == 1) {
lstWatch.SelectedItems[0].BeginEdit();
}
}
}
}

View file

@ -37,7 +37,7 @@ namespace Mesen.GUI.Debugger
AddBinding("Condition", txtCondition);
this.toolTip.SetToolTip(this.chkAbsolute, "Check to set an absolute address based on the exact address in PRG/CHR ROM (not CPU/PPU memory)");
this.toolTip.SetToolTip(this.picHelp, "Most expressions/operators are accepted (C++ syntax)." + Environment.NewLine + "Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine + Environment.NewLine + "A/X/Y/PS/SP: Value of registers" + Environment.NewLine +"Irq/Nmi: True if the Irq/Nmi flags are set" + Environment.NewLine + "Cycle/Scanline: Current cycle (0-340)/scanline(-1 to 240) of the PPU" + Environment.NewLine + "Value: Current value being read/written from/to memory" + Environment.NewLine + Environment.NewLine + "Examples:" + Environment.NewLine + "a == 10 || x == $23" + Environment.NewLine + "scanline == 10 && (cycle >= 55 && cycle <= 100)");
this.toolTip.SetToolTip(this.picHelp, "Most expressions/operators are accepted (C++ syntax)." + Environment.NewLine + "Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine + Environment.NewLine + "A/X/Y/PS/SP: Value of registers" + Environment.NewLine +"Irq/Nmi: True if the Irq/Nmi flags are set" + Environment.NewLine + "Cycle/Scanline: Current cycle (0-340)/scanline(-1 to 240) of the PPU" + Environment.NewLine + "Value: Current value being read/written from/to memory" + Environment.NewLine + "[<address>]: Value at address (CPU)" + Environment.NewLine + Environment.NewLine + "Examples:" + Environment.NewLine + "a == 10 || x == $23" + Environment.NewLine + "scanline == 10 && (cycle >= 55 && cycle <= 100)" + Environment.NewLine + "x == [$150] || y == [10]");
}
protected override bool ValidateInput()

View file

@ -35,7 +35,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void StartServer(UInt16 port);
[DllImport(DLLPath)] public static extern void StopServer();
[DllImport(DLLPath)] public static extern bool IsServerRunning();
[DllImport(DLLPath)] public static extern void Connect(string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string playerName, byte[] avatarData, UInt32 avatarSize);
[DllImport(DLLPath)] public static extern void Connect([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string host, UInt16 port, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string playerName, byte[] avatarData, UInt32 avatarSize);
[DllImport(DLLPath)] public static extern void Disconnect();
[DllImport(DLLPath)] public static extern bool IsConnected();
@ -64,7 +64,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern Int64 GetStateInfo(UInt32 stateIndex);
[DllImport(DLLPath)] public static extern void CheatAddCustom(UInt32 address, Byte value, Int32 compareValue, [MarshalAs(UnmanagedType.I1)]bool isRelativeAddress);
[DllImport(DLLPath)] public static extern void CheatAddGameGenie(string code);
[DllImport(DLLPath)] public static extern void CheatAddGameGenie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string code);
[DllImport(DLLPath)] public static extern void CheatAddProActionRocky(UInt32 code);
[DllImport(DLLPath)] public static extern void CheatClear();
@ -94,6 +94,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr);
[DllImport(DLLPath)] public static extern UInt32 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);
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool DebugLoadCdlFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string cdlFilepath);
@ -445,7 +446,14 @@ namespace Mesen.GUI
Write = 4,
ReadVram = 8,
WriteVram = 16
};
}
public enum EvalResultType
{
Numeric = 0,
Boolean = 1,
Invalid = 2
}
public enum NesModel
{

View file

@ -35,7 +35,7 @@ extern "C"
DllExport void __stdcall DebugStepCycles(uint32_t count) { GetDebugger()->StepCycles(count); }
DllExport void __stdcall DebugStepOver() { GetDebugger()->StepOver(); }
DllExport void __stdcall DebugStepOut() { GetDebugger()->StepOut(); }
DllExport int __stdcall DebugIsCodeChanged() { return GetDebugger()->IsCodeChanged(); }
DllExport uint32_t __stdcall DebugIsCodeChanged() { return GetDebugger()->IsCodeChanged(); }
DllExport const char* __stdcall DebugGetCode() { return GetDebugger()->GetCode()->c_str(); }
DllExport void __stdcall DebugSetNextStatement(uint16_t addr) { GetDebugger()->SetNextStatement(addr); }
@ -55,4 +55,6 @@ extern "C"
DllExport bool __stdcall DebugSaveCdlFile(char* cdlFilepath) { return GetDebugger()->SaveCdlFile(cdlFilepath); }
DllExport void __stdcall DebugGetCdlRatios(CdlRatios* cdlRatios) { *cdlRatios = GetDebugger()->GetCdlRatios(); }
DllExport void __stdcall DebugResetCdlLog() { GetDebugger()->ResetCdlLog(); }
DllExport int32_t __stdcall DebugEvaluateExpression(char* expression, EvalResultType *resultType) { return GetDebugger()->EvaluateExpression(expression, *resultType); }
};