2012-09-30 00:53:08 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
2013-11-29 00:35:05 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
2012-09-30 00:53:08 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
2014-12-05 00:05:40 +00:00
|
|
|
|
using BizHawk.Emulation.Common;
|
|
|
|
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
2013-10-25 00:57:23 +00:00
|
|
|
|
using BizHawk.Client.Common;
|
2014-07-27 15:22:30 +00:00
|
|
|
|
using BizHawk.Client.EmuHawk.WinFormExtensions;
|
2013-10-25 00:57:23 +00:00
|
|
|
|
|
2014-12-05 00:05:40 +00:00
|
|
|
|
|
2013-11-03 03:54:37 +00:00
|
|
|
|
namespace BizHawk.Client.EmuHawk
|
2012-09-30 00:53:08 +00:00
|
|
|
|
{
|
2014-12-22 19:01:21 +00:00
|
|
|
|
public partial class TraceLogger : Form, IToolFormAutoConfig
|
2012-09-30 00:53:08 +00:00
|
|
|
|
{
|
2014-12-15 03:19:23 +00:00
|
|
|
|
[RequiredService]
|
2014-12-23 01:58:12 +00:00
|
|
|
|
private ITraceable Tracer { get; set; }
|
2014-12-05 00:05:40 +00:00
|
|
|
|
|
2014-12-22 19:01:21 +00:00
|
|
|
|
[ConfigPersist]
|
|
|
|
|
private int MaxLines { get; set; }
|
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private readonly List<string> _instructions = new List<string>();
|
2014-01-30 15:28:05 +00:00
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private FileInfo _logFile;
|
2013-11-02 21:31:04 +00:00
|
|
|
|
|
2012-09-30 00:53:08 +00:00
|
|
|
|
public TraceLogger()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
2013-11-29 00:35:05 +00:00
|
|
|
|
|
2013-04-14 23:56:45 +00:00
|
|
|
|
TraceView.QueryItemText += TraceView_QueryItemText;
|
2012-09-30 00:53:08 +00:00
|
|
|
|
TraceView.VirtualMode = true;
|
2012-09-30 03:49:53 +00:00
|
|
|
|
|
2012-09-30 00:53:08 +00:00
|
|
|
|
Closing += (o, e) => SaveConfigSettings();
|
2014-12-22 19:01:21 +00:00
|
|
|
|
|
|
|
|
|
MaxLines = 10000;
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
public bool UpdateBefore
|
2012-09-30 00:53:08 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
get { return false; }
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-19 19:24:17 +00:00
|
|
|
|
public bool AskSaveChanges()
|
2013-11-29 00:35:05 +00:00
|
|
|
|
{
|
|
|
|
|
return true;
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private void SaveConfigSettings()
|
2012-09-30 00:53:08 +00:00
|
|
|
|
{
|
2014-12-05 00:05:40 +00:00
|
|
|
|
Tracer.Enabled = false;
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-09-30 03:09:41 +00:00
|
|
|
|
private void TraceView_QueryItemText(int index, int column, out string text)
|
2012-09-30 00:53:08 +00:00
|
|
|
|
{
|
2014-01-30 03:34:58 +00:00
|
|
|
|
text = index < _instructions.Count ? _instructions[index] : string.Empty;
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void TraceLogger_Load(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ClearList();
|
|
|
|
|
LoggingEnabled.Checked = true;
|
2014-12-05 00:05:40 +00:00
|
|
|
|
Tracer.Enabled = true;
|
2012-09-30 13:38:37 +00:00
|
|
|
|
SetTracerBoxTitle();
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateValues()
|
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
TraceView.BlazingFast = !GlobalWin.MainForm.EmulatorPaused;
|
|
|
|
|
if (ToWindowRadio.Checked)
|
|
|
|
|
{
|
|
|
|
|
LogToWindow();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LogToFile();
|
|
|
|
|
}
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-07-25 01:55:21 +00:00
|
|
|
|
public void FastUpdate()
|
|
|
|
|
{
|
2014-12-22 19:01:21 +00:00
|
|
|
|
// never skip instructions when tracelogging!
|
|
|
|
|
UpdateValues();
|
2014-07-25 01:55:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-09-30 00:53:08 +00:00
|
|
|
|
public void Restart()
|
|
|
|
|
{
|
2014-12-14 01:45:24 +00:00
|
|
|
|
ClearList();
|
2015-03-11 20:58:49 +00:00
|
|
|
|
LoggingEnabled.Checked = true;
|
|
|
|
|
Tracer.Enabled = true;
|
|
|
|
|
SetTracerBoxTitle();
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ClearList()
|
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
_instructions.Clear();
|
2012-09-30 04:28:06 +00:00
|
|
|
|
TraceView.ItemCount = 0;
|
2012-10-08 00:27:21 +00:00
|
|
|
|
SetTracerBoxTitle();
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-09-30 14:52:36 +00:00
|
|
|
|
private void LogToFile()
|
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
using (var sw = new StreamWriter(_logFile.FullName, true))
|
2012-09-30 14:52:36 +00:00
|
|
|
|
{
|
2014-12-05 00:05:40 +00:00
|
|
|
|
sw.Write(Tracer.TakeContents());
|
2012-09-30 14:52:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LogToWindow()
|
2012-09-30 00:53:08 +00:00
|
|
|
|
{
|
2014-12-05 00:05:40 +00:00
|
|
|
|
var instructions = Tracer.TakeContents().Split('\n');
|
2014-01-30 03:34:58 +00:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(instructions[0]))
|
2012-09-30 02:37:00 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
_instructions.AddRange(instructions);
|
2012-09-30 14:52:36 +00:00
|
|
|
|
}
|
2013-11-29 00:35:05 +00:00
|
|
|
|
|
2014-12-22 19:01:21 +00:00
|
|
|
|
if (_instructions.Count >= MaxLines)
|
2012-09-30 14:52:36 +00:00
|
|
|
|
{
|
2014-12-22 19:01:21 +00:00
|
|
|
|
_instructions.RemoveRange(0, _instructions.Count - MaxLines);
|
2012-09-30 02:37:00 +00:00
|
|
|
|
}
|
2012-09-30 14:52:36 +00:00
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
TraceView.ItemCount = _instructions.Count;
|
2012-09-30 13:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetTracerBoxTitle()
|
|
|
|
|
{
|
2014-12-05 00:05:40 +00:00
|
|
|
|
if (Tracer.Enabled)
|
2012-09-30 13:38:37 +00:00
|
|
|
|
{
|
2012-09-30 14:52:36 +00:00
|
|
|
|
if (ToFileRadio.Checked)
|
|
|
|
|
{
|
|
|
|
|
TracerBox.Text = "Trace log - logging to file...";
|
|
|
|
|
}
|
2013-11-29 00:35:05 +00:00
|
|
|
|
else if (_instructions.Any())
|
2012-09-30 13:38:37 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
TracerBox.Text = "Trace log - logging - " + _instructions.Count + " instructions";
|
2012-09-30 13:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TracerBox.Text = "Trace log - logging...";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
if (_instructions.Any())
|
2012-09-30 13:38:37 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
TracerBox.Text = "Trace log - " + _instructions.Count + " instructions";
|
2012-09-30 13:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
TracerBox.Text = "Trace log";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-09-30 14:52:36 +00:00
|
|
|
|
|
|
|
|
|
private void CloseFile()
|
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
// TODO: save the remaining instructions in CoreComm
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private FileInfo GetFileFromUser()
|
|
|
|
|
{
|
|
|
|
|
var sfd = new SaveFileDialog();
|
2013-11-29 00:35:05 +00:00
|
|
|
|
if (_logFile == null)
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
sfd.FileName = PathManager.FilesystemSafeName(Global.Game) + ".txt";
|
2013-12-13 05:20:50 +00:00
|
|
|
|
sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null);
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
2014-01-30 03:34:58 +00:00
|
|
|
|
else if (!string.IsNullOrWhiteSpace(_logFile.FullName))
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
|
|
|
|
sfd.FileName = PathManager.FilesystemSafeName(Global.Game);
|
2013-11-29 00:35:05 +00:00
|
|
|
|
sfd.InitialDirectory = Path.GetDirectoryName(_logFile.FullName);
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
sfd.FileName = Path.GetFileNameWithoutExtension(_logFile.FullName);
|
2013-12-13 05:20:50 +00:00
|
|
|
|
sfd.InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null);
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sfd.Filter = "Text Files (*.txt)|*.txt|Log Files (*.log)|*.log|All Files|*.*";
|
|
|
|
|
sfd.RestoreDirectory = true;
|
2013-11-28 22:39:00 +00:00
|
|
|
|
var result = sfd.ShowHawkDialog();
|
2013-11-29 00:35:05 +00:00
|
|
|
|
if (result == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
return new FileInfo(sfd.FileName);
|
|
|
|
|
}
|
|
|
|
|
else
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private void DumpListToDisk(FileSystemInfo file)
|
|
|
|
|
{
|
|
|
|
|
using (var sw = new StreamWriter(file.FullName))
|
|
|
|
|
{
|
|
|
|
|
foreach (var instruction in _instructions)
|
|
|
|
|
{
|
2014-05-20 18:38:25 +00:00
|
|
|
|
sw.WriteLine(instruction
|
|
|
|
|
.Replace("\r", string.Empty)
|
|
|
|
|
.Replace("\n", string.Empty));
|
2013-11-29 00:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Events
|
|
|
|
|
|
|
|
|
|
#region Menu Items
|
|
|
|
|
|
|
|
|
|
private void SaveLogMenuItem_Click(object sender, EventArgs e)
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
|
|
|
|
var file = GetFileFromUser();
|
|
|
|
|
if (file != null)
|
|
|
|
|
{
|
|
|
|
|
DumpListToDisk(file);
|
2013-11-03 16:07:58 +00:00
|
|
|
|
GlobalWin.OSD.AddMessage("Log dumped to " + file.FullName);
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private void ExitMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CopyMenuItem_Click(object sender, EventArgs e)
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
var indices = TraceView.SelectedIndices;
|
|
|
|
|
|
|
|
|
|
if (indices.Count > 0)
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
var blob = new StringBuilder();
|
|
|
|
|
foreach (int index in indices)
|
2012-09-30 18:37:59 +00:00
|
|
|
|
{
|
2015-02-08 15:32:56 +00:00
|
|
|
|
if (blob.Length != 0) blob.AppendLine();
|
|
|
|
|
blob.Append(_instructions[index]
|
2014-05-06 17:53:21 +00:00
|
|
|
|
.Replace("\r", string.Empty)
|
|
|
|
|
.Replace("\n", string.Empty) );
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
2013-11-29 00:35:05 +00:00
|
|
|
|
Clipboard.SetDataObject(blob.ToString());
|
2012-09-30 18:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-28 18:59:56 +00:00
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private void SelectAllMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < _instructions.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
TraceView.SelectItem(i, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MaxLinesMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2014-07-28 02:31:51 +00:00
|
|
|
|
var prompt = new InputPrompt
|
|
|
|
|
{
|
|
|
|
|
StartLocation = this.ChildPointToScreen(TraceView),
|
2014-07-28 02:40:30 +00:00
|
|
|
|
TextInputType = InputPrompt.InputType.Unsigned,
|
|
|
|
|
Message = "Max lines to display in the window",
|
2014-12-22 19:01:21 +00:00
|
|
|
|
InitialValue = MaxLines.ToString()
|
2014-07-28 02:31:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-07-15 23:43:17 +00:00
|
|
|
|
var result = prompt.ShowHawkDialog();
|
|
|
|
|
if (result == DialogResult.OK)
|
2013-11-29 00:35:05 +00:00
|
|
|
|
{
|
2014-07-28 02:40:30 +00:00
|
|
|
|
var max = int.Parse(prompt.PromptText);
|
2013-11-29 00:35:05 +00:00
|
|
|
|
if (max > 0)
|
|
|
|
|
{
|
2014-12-22 19:01:21 +00:00
|
|
|
|
MaxLines = max;
|
2013-11-29 00:35:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Dialog and ListView Events
|
|
|
|
|
|
|
|
|
|
private void LoggingEnabled_CheckedChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
2014-12-05 00:05:40 +00:00
|
|
|
|
Tracer.Enabled = LoggingEnabled.Checked;
|
2013-11-29 00:35:05 +00:00
|
|
|
|
SetTracerBoxTitle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ClearButton_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
ClearList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BrowseBox_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var file = GetFileFromUser();
|
|
|
|
|
if (file != null)
|
|
|
|
|
{
|
|
|
|
|
_logFile = file;
|
|
|
|
|
FileBox.Text = _logFile.FullName;
|
|
|
|
|
}
|
2012-11-28 18:59:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-29 00:35:05 +00:00
|
|
|
|
private void ToFileRadio_CheckedChanged(object sender, EventArgs e)
|
2012-11-28 18:59:56 +00:00
|
|
|
|
{
|
2013-11-29 00:35:05 +00:00
|
|
|
|
if (ToFileRadio.Checked)
|
|
|
|
|
{
|
|
|
|
|
FileBox.Visible = true;
|
|
|
|
|
BrowseBox.Visible = true;
|
|
|
|
|
var name = PathManager.FilesystemSafeName(Global.Game);
|
2013-12-13 05:20:50 +00:00
|
|
|
|
var filename = Path.Combine(PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null), name) + ".txt";
|
2013-11-29 00:35:05 +00:00
|
|
|
|
_logFile = new FileInfo(filename);
|
|
|
|
|
if (_logFile.Directory != null && !_logFile.Directory.Exists)
|
|
|
|
|
{
|
|
|
|
|
_logFile.Directory.Create();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_logFile.Exists)
|
|
|
|
|
{
|
|
|
|
|
_logFile.Delete();
|
|
|
|
|
}
|
2014-10-23 05:14:03 +00:00
|
|
|
|
|
|
|
|
|
using (_logFile.Create()) { }
|
2013-11-29 00:35:05 +00:00
|
|
|
|
|
|
|
|
|
FileBox.Text = _logFile.FullName;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CloseFile();
|
|
|
|
|
FileBox.Visible = false;
|
|
|
|
|
BrowseBox.Visible = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetTracerBoxTitle();
|
2012-11-28 18:59:56 +00:00
|
|
|
|
}
|
2013-11-29 00:35:05 +00:00
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#endregion
|
2012-09-30 00:53:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|