Refactor ITraceable to work on TraceInfo objects that separate Disassembly and Register information. Make Tracelogger two columns.

This commit is contained in:
adelikat 2016-02-21 17:34:14 -05:00
parent 01dc05375d
commit f5e679fa0d
21 changed files with 340 additions and 183 deletions

View File

@ -31,7 +31,7 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TraceLogger)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TraceLogger));
this.TracerBox = new System.Windows.Forms.GroupBox(); this.TracerBox = new System.Windows.Forms.GroupBox();
this.TraceView = new BizHawk.Client.EmuHawk.VirtualListView(); this.TraceView = new BizHawk.Client.EmuHawk.VirtualListView();
this.Script = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.Disasm = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.menuStrip1 = new MenuStripEx(); this.menuStrip1 = new MenuStripEx();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.FileSubMenu = new System.Windows.Forms.ToolStripMenuItem(); this.FileSubMenu = new System.Windows.Forms.ToolStripMenuItem();
@ -50,6 +50,7 @@
this.ToWindowRadio = new System.Windows.Forms.RadioButton(); this.ToWindowRadio = new System.Windows.Forms.RadioButton();
this.ClearButton = new System.Windows.Forms.Button(); this.ClearButton = new System.Windows.Forms.Button();
this.LoggingEnabled = new System.Windows.Forms.CheckBox(); this.LoggingEnabled = new System.Windows.Forms.CheckBox();
this.Registers = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.TracerBox.SuspendLayout(); this.TracerBox.SuspendLayout();
this.menuStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout();
this.groupBox2.SuspendLayout(); this.groupBox2.SuspendLayout();
@ -76,7 +77,8 @@
this.TraceView.BlazingFast = false; this.TraceView.BlazingFast = false;
this.TraceView.CheckBoxes = true; this.TraceView.CheckBoxes = true;
this.TraceView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.TraceView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.Script}); this.Disasm,
this.Registers});
this.TraceView.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.TraceView.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.TraceView.FullRowSelect = true; this.TraceView.FullRowSelect = true;
this.TraceView.GridLines = true; this.TraceView.GridLines = true;
@ -93,10 +95,10 @@
this.TraceView.UseCustomBackground = true; this.TraceView.UseCustomBackground = true;
this.TraceView.View = System.Windows.Forms.View.Details; this.TraceView.View = System.Windows.Forms.View.Details;
// //
// Script // Disasm
// //
this.Script.Text = "Instructions"; this.Disasm.Text = "Disasm";
this.Script.Width = 599; this.Disasm.Width = 239;
// //
// menuStrip1 // menuStrip1
// //
@ -124,27 +126,27 @@
this.toolStripSeparator1, this.toolStripSeparator1,
this.ExitMenuItem}); this.ExitMenuItem});
this.FileSubMenu.Name = "FileSubMenu"; this.FileSubMenu.Name = "FileSubMenu";
this.FileSubMenu.Size = new System.Drawing.Size(35, 20); this.FileSubMenu.Size = new System.Drawing.Size(37, 20);
this.FileSubMenu.Text = "&File"; this.FileSubMenu.Text = "&File";
// //
// SaveLogMenuItem // SaveLogMenuItem
// //
this.SaveLogMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; this.SaveLogMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs;
this.SaveLogMenuItem.Name = "SaveLogMenuItem"; this.SaveLogMenuItem.Name = "SaveLogMenuItem";
this.SaveLogMenuItem.Size = new System.Drawing.Size(132, 22); this.SaveLogMenuItem.Size = new System.Drawing.Size(134, 22);
this.SaveLogMenuItem.Text = "&Save Log"; this.SaveLogMenuItem.Text = "&Save Log";
this.SaveLogMenuItem.Click += new System.EventHandler(this.SaveLogMenuItem_Click); this.SaveLogMenuItem.Click += new System.EventHandler(this.SaveLogMenuItem_Click);
// //
// toolStripSeparator1 // toolStripSeparator1
// //
this.toolStripSeparator1.Name = "toolStripSeparator1"; this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(129, 6); this.toolStripSeparator1.Size = new System.Drawing.Size(131, 6);
// //
// ExitMenuItem // ExitMenuItem
// //
this.ExitMenuItem.Name = "ExitMenuItem"; this.ExitMenuItem.Name = "ExitMenuItem";
this.ExitMenuItem.ShortcutKeyDisplayString = "Alt+F4"; this.ExitMenuItem.ShortcutKeyDisplayString = "Alt+F4";
this.ExitMenuItem.Size = new System.Drawing.Size(132, 22); this.ExitMenuItem.Size = new System.Drawing.Size(134, 22);
this.ExitMenuItem.Text = "E&xit"; this.ExitMenuItem.Text = "E&xit";
this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click);
// //
@ -154,7 +156,7 @@
this.CopyMenuItem, this.CopyMenuItem,
this.SelectAllMenuItem}); this.SelectAllMenuItem});
this.EditSubMenu.Name = "EditSubMenu"; this.EditSubMenu.Name = "EditSubMenu";
this.EditSubMenu.Size = new System.Drawing.Size(37, 20); this.EditSubMenu.Size = new System.Drawing.Size(39, 20);
this.EditSubMenu.Text = "Edit"; this.EditSubMenu.Text = "Edit";
// //
// CopyMenuItem // CopyMenuItem
@ -162,7 +164,7 @@
this.CopyMenuItem.Name = "CopyMenuItem"; this.CopyMenuItem.Name = "CopyMenuItem";
this.CopyMenuItem.ShortcutKeyDisplayString = ""; this.CopyMenuItem.ShortcutKeyDisplayString = "";
this.CopyMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); this.CopyMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
this.CopyMenuItem.Size = new System.Drawing.Size(156, 22); this.CopyMenuItem.Size = new System.Drawing.Size(164, 22);
this.CopyMenuItem.Text = "&Copy"; this.CopyMenuItem.Text = "&Copy";
this.CopyMenuItem.Click += new System.EventHandler(this.CopyMenuItem_Click); this.CopyMenuItem.Click += new System.EventHandler(this.CopyMenuItem_Click);
// //
@ -171,7 +173,7 @@
this.SelectAllMenuItem.Name = "SelectAllMenuItem"; this.SelectAllMenuItem.Name = "SelectAllMenuItem";
this.SelectAllMenuItem.ShortcutKeyDisplayString = ""; this.SelectAllMenuItem.ShortcutKeyDisplayString = "";
this.SelectAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A))); this.SelectAllMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
this.SelectAllMenuItem.Size = new System.Drawing.Size(156, 22); this.SelectAllMenuItem.Size = new System.Drawing.Size(164, 22);
this.SelectAllMenuItem.Text = "Select &All"; this.SelectAllMenuItem.Text = "Select &All";
this.SelectAllMenuItem.Click += new System.EventHandler(this.SelectAllMenuItem_Click); this.SelectAllMenuItem.Click += new System.EventHandler(this.SelectAllMenuItem_Click);
// //
@ -180,13 +182,13 @@
this.OptionsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.OptionsSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.MaxLinesMenuItem}); this.MaxLinesMenuItem});
this.OptionsSubMenu.Name = "OptionsSubMenu"; this.OptionsSubMenu.Name = "OptionsSubMenu";
this.OptionsSubMenu.Size = new System.Drawing.Size(58, 20); this.OptionsSubMenu.Size = new System.Drawing.Size(61, 20);
this.OptionsSubMenu.Text = "&Settings"; this.OptionsSubMenu.Text = "&Settings";
// //
// MaxLinesMenuItem // MaxLinesMenuItem
// //
this.MaxLinesMenuItem.Name = "MaxLinesMenuItem"; this.MaxLinesMenuItem.Name = "MaxLinesMenuItem";
this.MaxLinesMenuItem.Size = new System.Drawing.Size(152, 22); this.MaxLinesMenuItem.Size = new System.Drawing.Size(154, 22);
this.MaxLinesMenuItem.Text = "&Set Max Lines..."; this.MaxLinesMenuItem.Text = "&Set Max Lines...";
this.MaxLinesMenuItem.Click += new System.EventHandler(this.MaxLinesMenuItem_Click); this.MaxLinesMenuItem.Click += new System.EventHandler(this.MaxLinesMenuItem_Click);
// //
@ -277,6 +279,11 @@
this.LoggingEnabled.UseVisualStyleBackColor = true; this.LoggingEnabled.UseVisualStyleBackColor = true;
this.LoggingEnabled.CheckedChanged += new System.EventHandler(this.LoggingEnabled_CheckedChanged); this.LoggingEnabled.CheckedChanged += new System.EventHandler(this.LoggingEnabled_CheckedChanged);
// //
// Registers
//
this.Registers.Text = "Registers";
this.Registers.Width = 357;
//
// TraceLogger // TraceLogger
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -317,7 +324,7 @@
private System.Windows.Forms.Button ClearButton; private System.Windows.Forms.Button ClearButton;
private System.Windows.Forms.ToolStripMenuItem OptionsSubMenu; private System.Windows.Forms.ToolStripMenuItem OptionsSubMenu;
private VirtualListView TraceView; private VirtualListView TraceView;
public System.Windows.Forms.ColumnHeader Script; public System.Windows.Forms.ColumnHeader Disasm;
private System.Windows.Forms.ToolStripMenuItem MaxLinesMenuItem; private System.Windows.Forms.ToolStripMenuItem MaxLinesMenuItem;
private System.Windows.Forms.RadioButton ToFileRadio; private System.Windows.Forms.RadioButton ToFileRadio;
private System.Windows.Forms.RadioButton ToWindowRadio; private System.Windows.Forms.RadioButton ToWindowRadio;
@ -326,5 +333,6 @@
private System.Windows.Forms.ToolStripMenuItem EditSubMenu; private System.Windows.Forms.ToolStripMenuItem EditSubMenu;
private System.Windows.Forms.ToolStripMenuItem CopyMenuItem; private System.Windows.Forms.ToolStripMenuItem CopyMenuItem;
private System.Windows.Forms.ToolStripMenuItem SelectAllMenuItem; private System.Windows.Forms.ToolStripMenuItem SelectAllMenuItem;
private System.Windows.Forms.ColumnHeader Registers;
} }
} }

View File

@ -1,17 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Client.Common; using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.WinFormExtensions; using BizHawk.Client.EmuHawk.WinFormExtensions;
namespace BizHawk.Client.EmuHawk namespace BizHawk.Client.EmuHawk
{ {
public partial class TraceLogger : Form, IToolFormAutoConfig public partial class TraceLogger : Form, IToolFormAutoConfig
@ -22,7 +19,7 @@ namespace BizHawk.Client.EmuHawk
[ConfigPersist] [ConfigPersist]
private int MaxLines { get; set; } private int MaxLines { get; set; }
private readonly List<string> _instructions = new List<string>(); private readonly List<TraceInfo> _instructions = new List<TraceInfo>();
private FileInfo _logFile; private FileInfo _logFile;
@ -55,7 +52,20 @@ namespace BizHawk.Client.EmuHawk
private void TraceView_QueryItemText(int index, int column, out string text) private void TraceView_QueryItemText(int index, int column, out string text)
{ {
text = index < _instructions.Count ? _instructions[index] : string.Empty; text = string.Empty;
if (index < _instructions.Count)
{
switch (column)
{
case 0:
text = _instructions[index].Disassembly;
break;
case 1:
text = _instructions[index].RegisterInfo;
break;
}
}
} }
private void TraceLogger_Load(object sender, EventArgs e) private void TraceLogger_Load(object sender, EventArgs e)
@ -80,11 +90,10 @@ namespace BizHawk.Client.EmuHawk
public void FastUpdate() public void FastUpdate()
{ {
// never skip instructions when tracelogging! // TODO: get instructions, but don't draw on screen
UpdateValues(); UpdateValues();
} }
public void Restart() public void Restart()
{ {
ClearList(); ClearList();
@ -99,21 +108,47 @@ namespace BizHawk.Client.EmuHawk
SetTracerBoxTitle(); SetTracerBoxTitle();
} }
// TODO: LogToFile and DumpListTODisk have a lot of repeated code
private void LogToFile() private void LogToFile()
{ {
using (var sw = new StreamWriter(_logFile.FullName, true)) var todo = Tracer.TakeContents();
if (todo.Any())
{ {
sw.Write(Tracer.TakeContents()); using (var sw = new StreamWriter(_logFile.FullName, true))
{
int pad = todo.Max(i => i.Disassembly.Length) + 4;
foreach (var instruction in todo)
{
sw.WriteLine(instruction.Disassembly.PadRight(pad)
+ instruction.RegisterInfo
);
}
sw.Write(Tracer.TakeContents());
}
}
}
private void DumpListToDisk(FileSystemInfo file)
{
using (var sw = new StreamWriter(file.FullName))
{
int pad = _instructions.Max(i => i.Disassembly.Length) + 4;
foreach (var instruction in _instructions)
{
sw.WriteLine(instruction.Disassembly.PadRight(pad)
+ instruction.RegisterInfo
);
}
} }
} }
private void LogToWindow() private void LogToWindow()
{ {
var instructions = Tracer.TakeContents().Split('\n'); _instructions.AddRange(Tracer.TakeContents());
if (!string.IsNullOrWhiteSpace(instructions[0]))
{
_instructions.AddRange(instructions);
}
if (_instructions.Count >= MaxLines) if (_instructions.Count >= MaxLines)
{ {
@ -190,19 +225,6 @@ namespace BizHawk.Client.EmuHawk
} }
} }
private void DumpListToDisk(FileSystemInfo file)
{
using (var sw = new StreamWriter(file.FullName))
{
foreach (var instruction in _instructions)
{
sw.WriteLine(instruction
.Replace("\r", string.Empty)
.Replace("\n", string.Empty));
}
}
}
#region Events #region Events
#region Menu Items #region Menu Items
@ -231,10 +253,10 @@ namespace BizHawk.Client.EmuHawk
var blob = new StringBuilder(); var blob = new StringBuilder();
foreach (int index in indices) foreach (int index in indices)
{ {
if (blob.Length != 0) blob.AppendLine(); int pad = _instructions.Max(m => m.Disassembly.Length) + 4;
blob.Append(_instructions[index] blob.Append(_instructions[index].Disassembly.PadRight(pad))
.Replace("\r", string.Empty) .Append(_instructions[index].RegisterInfo)
.Replace("\n", string.Empty) ); .AppendLine();
} }
Clipboard.SetDataObject(blob.ToString()); Clipboard.SetDataObject(blob.ToString());
} }

View File

@ -1,34 +1,34 @@
using System.Text; using System.Collections.Generic;
using System.Linq;
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
public class TraceBuffer : ITraceable public class TraceBuffer : ITraceable
{ {
private readonly StringBuilder buffer; private readonly List<TraceInfo> Buffer = new List<TraceInfo>();
public TraceBuffer() public TraceBuffer()
{ {
buffer = new StringBuilder();
Header = "Instructions"; Header = "Instructions";
} }
public string TakeContents() public IEnumerable<TraceInfo> TakeContents()
{ {
string s = buffer.ToString(); var contents = Buffer.ToList();
buffer.Clear(); Buffer.Clear();
return s; return contents;
} }
public string Contents public IEnumerable<TraceInfo> Contents
{ {
get { return buffer.ToString(); } get { return Buffer; }
} }
public void Put(string content) public void Put(TraceInfo content)
{ {
if (Enabled) if (Enabled)
{ {
buffer.AppendLine(content); Buffer.Add(content);
} }
} }

View File

@ -1,4 +1,6 @@
namespace BizHawk.Emulation.Common using System.Collections.Generic;
namespace BizHawk.Emulation.Common
{ {
/// <summary> /// <summary>
/// Allows the cpu to dump trace info to a trace stream /// Allows the cpu to dump trace info to a trace stream
@ -17,16 +19,19 @@
/// <summary> /// <summary>
/// The current log of cpu instructions /// The current log of cpu instructions
/// </summary> /// </summary>
string Contents { get; } IEnumerable<TraceInfo> Contents { get; }
/// <summary> /// <summary>
/// Takes the current log of cpu instructions, when doing so, it will clear the contents from the buffer /// Takes the current log of cpu instructions, when doing so, it will clear the contents from the buffer
/// </summary> /// </summary>
string TakeContents(); IEnumerable<TraceInfo> TakeContents();
/// <summary> void Put(TraceInfo content);
/// Adds contents to the log of cpu instructions }
/// </summary>
void Put(string content); public class TraceInfo
{
public string Disassembly { get; set; }
public string RegisterInfo { get; set; }
} }
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using BizHawk.Emulation.Common;
// Do not modify this file directly! This is GENERATED code. // Do not modify this file directly! This is GENERATED code.
// Please open the CpuCoreGenerator solution and make your modifications there. // Please open the CpuCoreGenerator solution and make your modifications there.
@ -8,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Components.H6280
public partial class HuC6280 public partial class HuC6280
{ {
public bool Debug; public bool Debug;
public Action<string> Logger; public Action<TraceInfo> Logger;
public void Execute(int cycles) public void Execute(int cycles)
{ {

View File

@ -262,21 +262,35 @@ namespace BizHawk.Emulation.Cores.Components.H6280
return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8)); return (ushort)(ReadMemory(address) | (ReadMemory(highAddress) << 8));
} }
public string State() public TraceInfo State()
{ {
int notused; int notused;
string a = string.Format("{3:X2}:{0:X4} {1:X2} {2} ", PC, ReadMemory(PC), Disassemble(PC, out notused), MPR[PC>>13]).PadRight(41);
string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); return new TraceInfo
string val = a + b + " "; {
if (FlagN) val = val + "N"; Disassembly = string.Format(
if (FlagV) val = val + "V"; "{3:X2}:{0:X4} {1:X2} {2} ",
if (FlagT) val = val + "T"; PC,
if (FlagB) val = val + "B"; ReadMemory(PC),
if (FlagD) val = val + "D"; Disassemble(PC, out notused), MPR[PC >> 13]),
if (FlagI) val = val + "I"; RegisterInfo = string.Format(
if (FlagZ) val = val + "Z"; "A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5} {6}{7}{8}{9}{10}{11}{12}{13}",
if (FlagC) val = val + "C"; A,
return val; X,
Y,
P,
S,
TotalExecutedCycles,
FlagN ? "N" : "",
FlagV ? "V" : "",
FlagT ? "T" : "",
FlagB ? "B" : "",
FlagD ? "D" : "",
FlagI ? "I" : "",
FlagZ ? "Z" : "",
FlagC ? "C" : ""
)
};
} }
private static readonly byte[] TableNZ = private static readonly byte[] TableNZ =

View File

@ -3,6 +3,7 @@
using System; using System;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Common.NumberExtensions; using BizHawk.Common.NumberExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Components.M6502 namespace BizHawk.Emulation.Cores.Components.M6502
{ {
@ -551,7 +552,7 @@ namespace BizHawk.Emulation.Cores.Components.M6502
bool booltemp; bool booltemp;
int tempint; int tempint;
int lo, hi; int lo, hi;
public Action<string> TraceCallback; public Action<TraceInfo> TraceCallback;
void Fetch1() void Fetch1()
{ {
@ -563,7 +564,14 @@ namespace BizHawk.Emulation.Cores.Components.M6502
if (NMI) if (NMI)
{ {
if (TraceCallback != null) if (TraceCallback != null)
TraceCallback("====NMI===="); {
TraceCallback(new TraceInfo
{
Disassembly = "====NMI====",
RegisterInfo = ""
});
}
ea = NMIVector; ea = NMIVector;
opcode = VOP_NMI; opcode = VOP_NMI;
NMI = false; NMI = false;
@ -574,7 +582,13 @@ namespace BizHawk.Emulation.Cores.Components.M6502
else if (IRQ && !my_iflag) else if (IRQ && !my_iflag)
{ {
if (TraceCallback != null) if (TraceCallback != null)
TraceCallback("====IRQ===="); {
TraceCallback(new TraceInfo
{
Disassembly = "====IRQ====",
RegisterInfo = ""
});
}
ea = IRQVector; ea = IRQVector;
opcode = VOP_IRQ; opcode = VOP_IRQ;
mi = 0; mi = 0;

View File

@ -2,6 +2,7 @@
using System.IO; using System.IO;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Components.M6502 namespace BizHawk.Emulation.Cores.Components.M6502
{ {
@ -40,27 +41,40 @@ namespace BizHawk.Emulation.Cores.Components.M6502
FlagI = true; FlagI = true;
} }
public string State(bool disassemble = true) public TraceInfo State(bool disassemble = true)
{ {
int notused; int notused;
string a = string.Format("{0:X4} {1:X2} {2} ", PC, PeekMemory(PC), disassemble ? Disassemble(PC, out notused) : "---").PadRight(30);
string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); return new TraceInfo
string val = a + b + " "; {
if (FlagN) val = val + "N"; Disassembly = string.Format(
if (FlagV) val = val + "V"; "{0:X4} {1:X2} {2} ",
if (FlagT) val = val + "T"; PC,
if (FlagB) val = val + "B"; PeekMemory(PC),
if (FlagD) val = val + "D"; disassemble ? Disassemble(PC, out notused) : "---"),
if (FlagI) val = val + "I"; RegisterInfo = string.Format(
if (FlagZ) val = val + "Z"; "A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5} {6}{7}{8}{9}{10}{11}{12}{13}",
if (FlagC) val = val + "C"; A,
if (!RDY) val = val + "R"; X,
return val; Y,
P,
S,
TotalExecutedCycles,
FlagN ? "N" : "",
FlagV ? "V" : "",
FlagT ? "T" : "",
FlagB ? "B" : "",
FlagD ? "D" : "",
FlagI ? "I" : "",
FlagZ ? "Z" : "",
FlagC ? "C" : "",
!RDY ? "R" : "")
};
} }
public bool AtStart { get { return opcode == VOP_Fetch1 || Microcode[opcode][mi] >= Uop.End; } } public bool AtStart { get { return opcode == VOP_Fetch1 || Microcode[opcode][mi] >= Uop.End; } }
public string TraceState() public TraceInfo TraceState()
{ {
// only disassemble when we're at the beginning of an opcode // only disassemble when we're at the beginning of an opcode
return State(AtStart); return State(AtStart);

View File

@ -1,3 +1,4 @@
using BizHawk.Emulation.Common;
using System; using System;
namespace BizHawk.Emulation.Cores.Components.Z80 namespace BizHawk.Emulation.Cores.Components.Z80
@ -14,7 +15,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80
public int PendingCycles { get { return pendingCycles; } set { pendingCycles = value; } } public int PendingCycles { get { return pendingCycles; } set { pendingCycles = value; } }
public bool Debug; public bool Debug;
public Action<string> Logger; public Action<TraceInfo> Logger;
/// <summary> /// <summary>
/// Runs the CPU for a particular number of clock cycles. /// Runs the CPU for a particular number of clock cycles.
@ -11949,22 +11950,37 @@ namespace BizHawk.Emulation.Cores.Components.Z80
// TODO, not super thrilled with the existing Z80 disassembler, lets see if we can find something decent to replace it with // TODO, not super thrilled with the existing Z80 disassembler, lets see if we can find something decent to replace it with
Disassembler Disassembler = new Disassembler(); Disassembler Disassembler = new Disassembler();
public string State() public TraceInfo State()
{ {
ushort tempPC = RegPC.Word; ushort tempPC = RegPC.Word;
string a = string.Format("{0:X4} {1:X2} {2} ", RegPC.Word, FetchMemoryWrapper(RegPC.Word), Disassembler.Disassemble(() => ReadMemoryWrapper(tempPC++)).PadRight(41));
string b = string.Format("AF:{0:X4} BC:{1:X4} DE:{2:X4} HL:{3:X4} IX:{4:X4} IY:{5:X4} SP:{6:X4} Cy:{7}", RegAF.Word, RegBC.Word, RegDE.Word, RegHL.Word, RegIX.Word, RegIY.Word, RegSP.Word, TotalExecutedCycles);
string val = a + b + " ";
if (RegFlagC) val = val + "C"; return new TraceInfo
if (RegFlagN) val = val + "N"; {
if (RegFlagP) val = val + "P"; Disassembly = string.Format(
if (RegFlag3) val = val + "3"; "{0:X4} {1:X2} {2}",
if (RegFlagH) val = val + "H"; RegPC.Word,
if (RegFlag5) val = val + "5"; FetchMemoryWrapper(RegPC.Word),
if (RegFlagZ) val = val + "Z"; Disassembler.Disassemble(() => ReadMemoryWrapper(tempPC++))),
if (RegFlagS) val = val + "S"; RegisterInfo = string.Format(
return val; "AF:{0:X4} BC:{1:X4} DE:{2:X4} HL:{3:X4} IX:{4:X4} IY:{5:X4} SP:{6:X4} Cy:{7} {8}{9}{10}{11}{12}{13}{14}{15}",
RegAF.Word,
RegBC.Word,
RegDE.Word,
RegHL.Word,
RegIX.Word,
RegIY.Word,
RegSP.Word,
TotalExecutedCycles,
RegFlagC ? "C" : "",
RegFlagN ? "N" : "",
RegFlagP ? "P" : "",
RegFlag3 ? "3" : "",
RegFlagH ? "H" : "",
RegFlag5 ? "5" : "",
RegFlagZ ? "Z" : "",
RegFlagS ? "S" : ""
)
};
} }
} }
} }

View File

@ -123,7 +123,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
private void StepInto() private void StepInto()
{ {
if (Tracer.Enabled) if (Tracer.Enabled)
_machine.Cpu.TraceCallback = (s) => Tracer.Put(s); _machine.Cpu.TraceCallback = (s) => TracerWrapper(s);
else else
_machine.Cpu.TraceCallback = null; _machine.Cpu.TraceCallback = null;

View File

@ -140,12 +140,25 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
private bool _nextPressed = false; private bool _nextPressed = false;
private bool _prevPressed = false; private bool _prevPressed = false;
private void TracerWrapper(string[] content)
{
Tracer.Put(new TraceInfo
{
Disassembly = content[0],
RegisterInfo = content[1]
});
}
private void FrameAdv(bool render, bool rendersound) private void FrameAdv(bool render, bool rendersound)
{ {
if (Tracer.Enabled) if (Tracer.Enabled)
_machine.Cpu.TraceCallback = (s) => Tracer.Put(s); {
_machine.Cpu.TraceCallback = (s) => TracerWrapper(s);
}
else else
{
_machine.Cpu.TraceCallback = null; _machine.Cpu.TraceCallback = null;
}
if (Controller["Next Disk"] && !_nextPressed) if (Controller["Next Disk"] && !_nextPressed)
{ {

View File

@ -235,10 +235,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
#endregion #endregion
void Trace(string msg) // Tracer refactor TODO - rehook up meteor, if it is worth it
{ //void Trace(string msg)
Tracer.Put(msg); //{
} // Tracer.Put(msg);
//}
private void Init() private void Init()
{ {
@ -247,7 +248,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
messagecallback = PrintMessage; messagecallback = PrintMessage;
inputcallback = GetInput; inputcallback = GetInput;
tracecallback = Trace; // don't set this callback now, only set if enabled
// Tracer refactor TODO - rehook up meteor, if it is worth it
//tracecallback = Trace; // don't set this callback now, only set if enabled
LibMeteor.libmeteor_setmessagecallback(messagecallback); LibMeteor.libmeteor_setmessagecallback(messagecallback);
LibMeteor.libmeteor_setkeycallback(inputcallback); LibMeteor.libmeteor_setkeycallback(inputcallback);

View File

@ -10,6 +10,7 @@ using BizHawk.Emulation.Common;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.ComponentModel; using System.ComponentModel;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Cores.Components.ARM;
namespace BizHawk.Emulation.Cores.Nintendo.GBA namespace BizHawk.Emulation.Cores.Nintendo.GBA
{ {
@ -159,13 +160,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } } public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } }
string Trace(uint addr, uint opcode) TraceInfo Trace(uint addr, uint opcode)
{ {
return return new TraceInfo
string.Format("{0:x8} {1} {2}", {
opcode, Disassembly = string.Format("{0:X8} {1}", opcode, Darm.DisassembleStuff(addr, opcode)),
(Emulation.Cores.Components.ARM.Darm.DisassembleStuff(addr, opcode) ?? "").PadRight(30), RegisterInfo = regs.TraceString()
regs.TraceString()); };
} }
void InitCallbacks() void InitCallbacks()

View File

@ -1,8 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components.Z80GB;
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{ {
@ -17,24 +16,30 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
System.Runtime.InteropServices.Marshal.Copy(_s, s, 0, 14); System.Runtime.InteropServices.Marshal.Copy(_s, s, 0, 14);
ushort unused; ushort unused;
Tracer.Put(string.Format( Tracer.Put(new TraceInfo
"{13} SP:{2:x2} A:{3:x2} B:{4:x2} C:{5:x2} D:{6:x2} E:{7:x2} F:{8:x2} H:{9:x2} L:{10:x2} LY:{14:x2} {11} Cy:{0}", {
s[0], Disassembly =
s[1] & 0xffff, NewDisassembler
s[2] & 0xffff, .Disassemble((ushort)s[1], (addr) => LibGambatte.gambatte_cpuread(GambatteState, addr), out unused)
s[3] & 0xff, .PadRight(30),
s[4] & 0xff, RegisterInfo =
s[5] & 0xff, string.Format(
s[6] & 0xff, "SP:{2:x2} A:{3:x2} B:{4:x2} C:{5:x2} D:{6:x2} E:{7:x2} F:{8:x2} H:{9:x2} L:{10:x2} LY:{14:x2} {11} Cy:{0}",
s[7] & 0xff, s[0],
s[8] & 0xff, s[1] & 0xffff,
s[9] & 0xff, s[2] & 0xffff,
s[10] & 0xff, s[3] & 0xff,
s[11] != 0 ? "skip" : "", s[4] & 0xff,
s[12] & 0xff, s[5] & 0xff,
Common.Components.Z80GB.NewDisassembler.Disassemble((ushort)s[1], (addr) => LibGambatte.gambatte_cpuread(GambatteState, addr), out unused).PadRight(30), s[6] & 0xff,
s[13] & 0xff s[7] & 0xff,
)); s[8] & 0xff,
s[9] & 0xff,
s[10] & 0xff,
s[11] != 0 ? "skip" : "",
s[12] & 0xff
)
});
} }
} }
} }

View File

@ -27,16 +27,17 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
int notused = 0; int notused = 0;
string opcodeStr = MOS6502X.Disassemble(pc, out notused, (address) => _memoryDomains.SystemBus.PeekByte(address)); string opcodeStr = MOS6502X.Disassemble(pc, out notused, (address) => _memoryDomains.SystemBus.PeekByte(address));
Tracer.Put(string.Format( Tracer.Put(new TraceInfo
"{0:X4}: {1} SP:{2:X2} A:{3:X2} P:{4:X2} X:{5:X2} Y:{6:X2} ", {
pc, Disassembly = string.Format("{0:X4} {1}", pc, opcodeStr).PadRight(26),
opcodeStr.PadRight(26), RegisterInfo = string.Format(
sp, "SP:{0:X2} A:{1:X2} P:{2:X2} X:{3:X2} Y:{4:X2}",
a, sp,
p, a,
x, p,
y)); x,
y)
});
} }
private const string TraceHeader = "PC: OP SP_A_P_X_Y "; private const string TraceHeader = "PC: OP SP_A_P_X_Y ";

View File

@ -393,7 +393,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
void snes_trace(string msg) void snes_trace(string msg)
{ {
Tracer.Put(msg); // TODO: get them out of the core split up and remove this hackery
string splitStr = "[";
if (!msg.Contains('['))
{
splitStr = "A:";
}
var split = msg.Split(new[] {splitStr }, StringSplitOptions.None);
Tracer.Put(new TraceInfo
{
Disassembly = split[0],
RegisterInfo = splitStr + split[1]
});
} }
public SnesColors.ColorType CurrPalette { get; private set; } public SnesColors.ColorType CurrPalette { get; private set; }

View File

@ -224,7 +224,11 @@ namespace BizHawk.Emulation.Cores.PCEngine
RomData = rom; RomData = rom;
RomLength = RomData.Length; RomLength = RomData.Length;
// user request: current value of the SF2MapperLatch on the tracelogger // user request: current value of the SF2MapperLatch on the tracelogger
Cpu.Logger = (s) => Tracer.Put(string.Format("{0:X1}:{1}", SF2MapperLatch, s)); Cpu.Logger = (s) => Tracer.Put(new TraceInfo
{
Disassembly = string.Format("{0:X1}:{1}", SF2MapperLatch, s),
RegisterInfo = ""
});
} }
else else
{ {

View File

@ -1,5 +1,7 @@
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using BizHawk.Emulation.Common.IEmulatorExtensions; using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Common.NumberExtensions; using BizHawk.Common.NumberExtensions;
@ -29,7 +31,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
throw new InvalidOperationException("GetCpuFlagsAndRegisters is required"); throw new InvalidOperationException("GetCpuFlagsAndRegisters is required");
} }
Buffer = new StringBuilder();
Header = "Instructions"; Header = "Instructions";
DebuggableCore = debuggableCore; DebuggableCore = debuggableCore;
@ -42,7 +43,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
private readonly IMemoryDomains MemoryDomains; private readonly IMemoryDomains MemoryDomains;
private readonly IDisassemblable Disassembler; private readonly IDisassemblable Disassembler;
private readonly IDebuggable DebuggableCore; private readonly IDebuggable DebuggableCore;
private readonly StringBuilder Buffer;
private readonly List<TraceInfo> Buffer = new List<TraceInfo>();
private bool _enabled; private bool _enabled;
@ -55,20 +57,28 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
// feos: we shouldn't append up to 64, but movem.l prints all the regs affected // feos: we shouldn't append up to 64, but movem.l prints all the regs affected
// so use 32 and deal with registers shifting every now and then // so use 32 and deal with registers shifting every now and then
Buffer.Append(string.Format("{0:X6}: {1,-32}", pc, disasm));
var traceInfo = new TraceInfo
{
Disassembly = string.Format("{0:X6}: {1,-32}", pc, disasm)
};
var sb = new StringBuilder();
foreach (var r in regs) foreach (var r in regs)
{ {
if (r.Key.StartsWith("M68K")) if (r.Key.StartsWith("M68K"))
{ {
Buffer.Append( sb.Append(
string.Format("{0}:{1} ", string.Format("{0}:{1} ",
r.Key.Replace("M68K", string.Empty).Trim(), r.Key.Replace("M68K", string.Empty).Trim(),
r.Value.Value.ToHexString(r.Value.BitSize / 4))); r.Value.Value.ToHexString(r.Value.BitSize / 4)));
} }
} }
Buffer.AppendLine(); traceInfo.RegisterInfo = sb.ToString();
Buffer.Add(traceInfo);
} }
public bool Enabled public bool Enabled
@ -92,23 +102,23 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
public string Header { get; set; } public string Header { get; set; }
public string Contents public IEnumerable<TraceInfo> Contents
{ {
get { return Buffer.ToString(); } get { return Buffer; }
} }
public string TakeContents() public IEnumerable<TraceInfo> TakeContents()
{ {
string s = Buffer.ToString(); var contents = Buffer.ToList();
Buffer.Clear(); Buffer.Clear();
return s; return contents;
} }
public void Put(string content) public void Put(TraceInfo content)
{ {
if (_enabled) if (Enabled)
{ {
Buffer.AppendLine(content); Buffer.Add(content);
} }
} }

View File

@ -1325,7 +1325,12 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
public void ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis) public void ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis)
{ {
Tracer.Put(dis); // Tracer refactor TODO: fix this
Tracer.Put(new TraceInfo
{
Disassembly = dis,
RegisterInfo = "TODO"
});
} }
private readonly MemoryCallbackSystem _memoryCallbacks = new MemoryCallbackSystem(); private readonly MemoryCallbackSystem _memoryCallbacks = new MemoryCallbackSystem();

View File

@ -177,20 +177,28 @@ namespace Jellyfish.Virtu
RA, RX, RY, RP, RS, RPC, EA, CC); RA, RX, RY, RP, RS, RPC, EA, CC);
} }
public string TraceState() public string[] TraceState()
{ {
string a = string.Format("{0:X4} {1:X2} {2} ", RPC, _memory.Read(RPC), ReadOpcode(RPC)).PadRight(30); string[] parts = new string[2];
string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", RA, RX, RY, RP, RS, Cycles); parts[0] = string.Format("{0:X4} {1:X2} {2} ", RPC, _memory.Read(RPC), ReadOpcode(RPC));
string state = a + b + " "; parts[1] = string.Format(
if (FlagN) state = state + "N"; "A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}",
if (FlagV) state = state + "V"; RA,
if (FlagT) state = state + "T"; RX,
if (FlagB) state = state + "B"; RY,
if (FlagD) state = state + "D"; RP,
if (FlagI) state = state + "I"; RS,
if (FlagZ) state = state + "Z"; Cycles,
if (FlagC) state = state + "C"; FlagN ? "N" : "",
return state; FlagV ? "V" : "",
FlagT ? "T" : "",
FlagB ? "B" : "",
FlagD ? "D" : "",
FlagI ? "I" : "",
FlagZ ? "Z" : "",
FlagC ? "C" : "");
return parts;
} }
private string ReadOpcode(int pc) private string ReadOpcode(int pc)
@ -3448,7 +3456,7 @@ namespace Jellyfish.Virtu
private Action[] _executeOpCode; private Action[] _executeOpCode;
[JsonIgnore] [JsonIgnore]
public Action<string> TraceCallback; public Action<string[]> TraceCallback;
/// <summary>Carry Flag</summary> /// <summary>Carry Flag</summary>
[JsonIgnore] [JsonIgnore]

Binary file not shown.