* add a new IToolForm update mechanism which has extensible update points (so a tool can both pre- and post- update)

* make trace logging "core-pushes" model, to a sink installed by the frontend. This sink can go straight to the disk without wasting memory if that's what the Trace Logger tool has selected; or the Trace Logger will buffer it if it needs to.  Formerly, we had a "core-pushes-to-buffer" and "client-pulls-once-per-frame" which necessarily caused huge buffers no matter what was going on.
This commit is contained in:
zeromus 2016-08-13 15:31:04 -05:00
parent 8721d0ef83
commit a7d2b8d7f7
45 changed files with 228 additions and 89 deletions

View File

@ -1,11 +1,35 @@
namespace BizHawk.Client.EmuHawk
{
public enum ToolFormUpdateType
{
//reserved
Legacy, LegacyFast,
//reserved concept: we can run other events through here (should probably rename then)
Reset,
/// <summary>
/// Called before a frame emulates
/// </summary>
PreFrame,
/// <summary>
/// Called after a frame emulates
/// </summary>
PostFrame
}
public interface IToolForm
{
/// <summary>
/// Will be called by the client anytime an Update needs to occur, such as after an emulated frame, a loadstate, or a related dialog has made a relevant change
/// </summary>
void UpdateValues();
void UpdateValues();
/// <summary>
/// A new extensible update method
/// </summary>
void NewUpdate(ToolFormUpdateType type);
/// <summary>
/// Will be called by the client when performance is critical,
@ -32,6 +56,7 @@
/// Indicates whether the tool should be updated before a frame loop or after.
/// In general, tools that draw graphics from the core should update before the loop,
/// Information tools such as those that display core ram values should be after.
/// AWESOME! no separate preupdate and postupdate hooks. seriously?
/// </summary>
bool UpdateBefore { get; }

View File

@ -129,6 +129,8 @@ namespace BizHawk.Client.EmuHawk
Close();
}
public void NewUpdate(ToolFormUpdateType type) { }
private TreeNode CreateCoreTree(CoreInfo ci)
{
var ret = new TreeNode

View File

@ -21,6 +21,8 @@ namespace BizHawk.Client.EmuHawk
{
}
public void NewUpdate(ToolFormUpdateType type) { }
public void FastUpdate()
{
}

View File

@ -40,6 +40,8 @@ namespace BizHawk.Client.EmuHawk
#region IToolForm Implementation
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
// TODO: per frame stuff goes here

View File

@ -371,6 +371,8 @@ namespace BizHawk.Client.EmuHawk
public bool UpdateBefore { get { return true; } }
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
Update(fast: false);

View File

@ -63,7 +63,9 @@ namespace BizHawk.Client.EmuHawk
InitializeComponent();
tsbViewStyle.SelectedIndex = 0;
}
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{

View File

@ -58,6 +58,8 @@ namespace BizHawk.Client.EmuHawk
public bool UpdateBefore { get { return false; } }
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
// Do nothing

View File

@ -86,6 +86,8 @@ namespace BizHawk.Client.EmuHawk.tools.Debugger
ParentDebugger.DisableCancelSeekBtn();
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (Enabled)

View File

@ -134,6 +134,8 @@ namespace BizHawk.Client.EmuHawk
#endregion
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
// Nothing to do

View File

@ -33,6 +33,8 @@ namespace BizHawk.Client.EmuHawk
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (this.Enabled)

View File

@ -533,6 +533,8 @@ namespace BizHawk.Client.EmuHawk
/// </summary>
int cbscanline_emu = -4; // force refresh
public void NewUpdate(ToolFormUpdateType type) { }
/// <summary>
/// put me in ToolsBefore
/// </summary>

View File

@ -33,6 +33,8 @@ namespace BizHawk.Client.EmuHawk
Close();
}
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{

View File

@ -693,6 +693,8 @@ namespace BizHawk.Client.EmuHawk
UpdateValues();
}
public void NewUpdate(ToolFormUpdateType type) { }
/// <summary>belongs in ToolsBefore</summary>
public void UpdateValues()
{

View File

@ -154,7 +154,9 @@ namespace BizHawk.Client.EmuHawk
public void Restart()
{
}
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{

View File

@ -85,6 +85,8 @@ namespace BizHawk.Client.EmuHawk
}
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (Emulator.SystemId != "GEN")

View File

@ -119,6 +119,7 @@ namespace BizHawk.Client.EmuHawk
bmpViewTiles.Refresh();
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{

View File

@ -146,6 +146,8 @@ namespace BizHawk.Client.EmuHawk
return true;
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
AddressesLabel.Text = GenerateMemoryViewString(true);

View File

@ -41,7 +41,9 @@ namespace BizHawk.Client.EmuHawk
#endregion
#region IToolForm implementation
#region IToolForm implementation
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{

View File

@ -94,6 +94,8 @@ namespace BizHawk.Client.EmuHawk
get { return SelectedItems.Where(x => !x.IsSeparator); }
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
// Do nothing

View File

@ -13,6 +13,8 @@ namespace BizHawk.Client.EmuHawk
InitializeComponent();
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (GlobalWin.Tools.LuaConsole.LuaImp.RegisteredFunctions.Any())

View File

@ -80,6 +80,8 @@ namespace BizHawk.Client.EmuHawk
MacroInputTool_Load(null, null);
}
public void NewUpdate(ToolFormUpdateType type) { }
// These do absolutely nothing.
public void UpdateValues()
{

View File

@ -57,6 +57,8 @@ namespace BizHawk.Client.EmuHawk
#region IToolForm
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{

View File

@ -100,6 +100,8 @@ namespace BizHawk.Client.EmuHawk
UpdateValues();
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
UseCurrentRomButton.Enabled = Global.Emulator != null // For the designer

View File

@ -25,6 +25,8 @@ namespace BizHawk.Client.EmuHawk
#region IToolForm
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
}

View File

@ -55,6 +55,8 @@ namespace BizHawk.Client.EmuHawk
}
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (Emulator.SystemId != "NES")

View File

@ -33,6 +33,8 @@ namespace BizHawk.Client.EmuHawk
{
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
}

View File

@ -47,6 +47,8 @@ namespace BizHawk.Client.EmuHawk
Generate(true);
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
_ppu.InstallCallback1(() => Generate(), scanline);

View File

@ -63,6 +63,7 @@ namespace BizHawk.Client.EmuHawk
public bool AskSaveChanges() { return true; }
public bool UpdateBefore { get { return true; } }
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
_ppu.InstallCallback2(() => Generate(), scanline);

View File

@ -94,6 +94,8 @@ namespace BizHawk.Client.EmuHawk
// Nothing to do
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
Generate();

View File

@ -42,6 +42,8 @@ namespace BizHawk.Client.EmuHawk
base.OnShown(e);
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
foreach (var entry in PSGEntries)

View File

@ -32,6 +32,8 @@ namespace BizHawk.Client.EmuHawk
#region IToolForm
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
DrawBacks();

View File

@ -139,6 +139,8 @@ namespace BizHawk.Client.EmuHawk
bmpViewPalette.Refresh();
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
unsafe

View File

@ -63,6 +63,8 @@ namespace BizHawk.Client.EmuHawk
// Do nothing
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
// Do nothing

View File

@ -133,6 +133,8 @@ namespace BizHawk.Client.EmuHawk
else return string.Format("@{0} ({1}K)", address.ToHexString(4), address / 1024);
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
SyncCore();

View File

@ -22,6 +22,8 @@ namespace BizHawk.Client.EmuHawk
public bool UpdateBefore { get { return false; } }
public void NewUpdate(ToolFormUpdateType type) { }
private int lastRefresh = 0;
public void UpdateValues()
{

View File

@ -41,6 +41,8 @@ namespace BizHawk.Client.EmuHawk
public bool AskSaveChanges() { return true; }
public bool UpdateBefore { get { return false; } }
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
// Do nothing

View File

@ -33,6 +33,8 @@ namespace BizHawk.Client.EmuHawk
);
}
public void NewUpdate(ToolFormUpdateType type) { }
public bool AskSaveChanges() { return true; }
public bool UpdateBefore { get { return false; } }
public void UpdateValues() { }

View File

@ -405,6 +405,8 @@ namespace BizHawk.Client.EmuHawk
tool.UpdateValues();
}
}
foreach (var tool in _tools)
tool.NewUpdate(ToolFormUpdateType.PreFrame);
}
public void UpdateAfter()
@ -418,6 +420,9 @@ namespace BizHawk.Client.EmuHawk
tool.UpdateValues();
}
}
foreach (var tool in _tools)
tool.NewUpdate(ToolFormUpdateType.PostFrame);
}
/// <summary>

View File

@ -33,9 +33,10 @@ namespace BizHawk.Client.EmuHawk
set { this.Registers.Width = value; }
}
private readonly List<TraceInfo> _instructions = new List<TraceInfo>();
private List<TraceInfo> _instructions = new List<TraceInfo>();
private FileInfo _logFile;
private StreamWriter _streamWriter;
public TraceLogger()
{
@ -61,7 +62,7 @@ namespace BizHawk.Client.EmuHawk
private void SaveConfigSettings()
{
Tracer.Enabled = LoggingEnabled.Checked;
//Tracer.Enabled = LoggingEnabled.Checked;
}
private void TraceView_QueryItemText(int index, int column, out string text)
@ -77,7 +78,6 @@ namespace BizHawk.Client.EmuHawk
case 1:
text = _instructions[index].RegisterInfo;
break;
}
}
}
@ -86,35 +86,79 @@ namespace BizHawk.Client.EmuHawk
{
ClearList();
OpenLogFile.Enabled = false;
Tracer.Enabled = LoggingEnabled.Checked = false;
//Tracer.Enabled = LoggingEnabled.Checked = false;
SetTracerBoxTitle();
}
public void UpdateValues()
class CallbackSink : ITraceSink
{
_instructions.AddRange(Tracer.TakeContents());
if (ToWindowRadio.Checked)
public void Put(TraceInfo info)
{
TraceView.BlazingFast = !GlobalWin.MainForm.EmulatorPaused;
LogToWindow();
putter(info);
}
else
public Action<TraceInfo> putter;
}
public void UpdateValues() { }
public void NewUpdate(ToolFormUpdateType type)
{
if (type == ToolFormUpdateType.PostFrame)
{
DumpToDisk(_logFile);
_instructions.Clear();
if (ToWindowRadio.Checked)
TraceView.VirtualListSize = _instructions.Count;
else
{
_streamWriter.Close();
_streamWriter = null;
}
}
if (type == ToolFormUpdateType.PreFrame)
{
if (LoggingEnabled.Checked)
{
//connect tracer to sink for next frame
if (ToWindowRadio.Checked)
{
//update listview with most recentr results
TraceView.BlazingFast = !GlobalWin.MainForm.EmulatorPaused;
Tracer.Sink = new CallbackSink()
{
putter = (info) =>
{
if (_instructions.Count >= MaxLines) { }
else _instructions.Add(info);
}
};
_instructions.Clear();
}
else
{
_streamWriter = new StreamWriter(_logFile.FullName, append: true);
Tracer.Sink = new CallbackSink {
putter = (info) =>
{
//no padding supported. core should be doing this anyway.
_streamWriter.WriteLine("{0} {1}", info.Disassembly, info.RegisterInfo);
}
};
}
}
else Tracer.Sink = null;
}
}
public void FastUpdate()
{
_instructions.AddRange(Tracer.TakeContents());
}
public void Restart()
{
ClearList();
Tracer.Enabled = LoggingEnabled.Checked = false;
//Tracer.Enabled = LoggingEnabled.Checked = false;
SetTracerBoxTitle();
}
@ -290,7 +334,7 @@ namespace BizHawk.Client.EmuHawk
private void LoggingEnabled_CheckedChanged(object sender, EventArgs e)
{
Tracer.Enabled = LoggingEnabled.Checked;
//Tracer.Enabled = LoggingEnabled.Checked;
SetTracerBoxTitle();
if (LoggingEnabled.Checked && _logFile != null)

View File

@ -168,6 +168,8 @@ namespace BizHawk.Client.EmuHawk
CreatePads();
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (!IsHandleCreated || IsDisposed)

View File

@ -261,6 +261,8 @@ namespace BizHawk.Client.EmuHawk
SetTotal();
}
public void NewUpdate(ToolFormUpdateType type) { }
/// <summary>
/// This should only be called when the values of the list need an update such as after a poke or emulation occured
/// </summary>

View File

@ -229,6 +229,8 @@ namespace BizHawk.Client.EmuHawk
}
}
public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues()
{
if (_paused)

View File

@ -36,51 +36,35 @@ namespace BizHawk.Emulation.Common
protected readonly List<TraceInfo> Buffer = new List<TraceInfo>();
private bool _enabled;
public abstract void TraceFromCallback();
public bool Enabled
{
get
{
return _enabled;
}
set
{
_enabled = value;
DebuggableCore.MemoryCallbacks.Remove(TraceFromCallback);
if (_enabled)
{
DebuggableCore.MemoryCallbacks.Add(new TracingMemoryCallback(TraceFromCallback));
}
}
public abstract void TraceFromCallback();
public ITraceSink _sink;
public bool Enabled { get { return Sink != null; } }
public void Put(TraceInfo info) { Sink.Put(info); }
public ITraceSink Sink
{
get
{
return _sink;
}
set
{
_sink = value;
DebuggableCore.MemoryCallbacks.Remove(TraceFromCallback);
if (_sink != null)
{
DebuggableCore.MemoryCallbacks.Add(new TracingMemoryCallback(TraceFromCallback));
}
}
}
public string Header { get; set; }
public IEnumerable<TraceInfo> Contents
{
get { return Buffer; }
}
public IEnumerable<TraceInfo> TakeContents()
{
var contents = Buffer.ToList();
Buffer.Clear();
return contents;
}
public void Put(TraceInfo content)
{
if (Enabled)
{
Buffer.Add(content);
}
}
public class TracingMemoryCallback : IMemoryCallback
{
public TracingMemoryCallback(Action callback)

View File

@ -1,39 +1,23 @@
using System.Collections.Generic;
using System.Linq;
//garbage
namespace BizHawk.Emulation.Common
{
public class TraceBuffer : ITraceable
{
private readonly List<TraceInfo> Buffer = new List<TraceInfo>();
public TraceBuffer()
{
Header = "Instructions";
}
public IEnumerable<TraceInfo> TakeContents()
{
var contents = Buffer.ToList();
Buffer.Clear();
return contents;
}
public IEnumerable<TraceInfo> Contents
{
get { return Buffer; }
}
public void Put(TraceInfo content)
{
if (Enabled)
{
Buffer.Add(content);
}
}
public bool Enabled { get; set; }
public string Header { get; set; }
public ITraceSink Sink { get; set; }
public bool Enabled { get { return Sink != null; } }
public void Put(TraceInfo info) { Sink.Put(info); }
}
}

View File

@ -2,13 +2,18 @@
namespace BizHawk.Emulation.Common
{
public interface ITraceSink
{
void Put(TraceInfo info);
}
/// <summary>
/// This service allows the core to dump a cpu trace to the client
/// If available the Trace Logger tool will be available on the client
/// </summary>
public interface ITraceable : IEmulatorService
{
bool Enabled { get; set; }
//bool Enabled { get; set; }
/// <summary>
/// The header that would be used by a trace logger
@ -18,14 +23,30 @@ namespace BizHawk.Emulation.Common
/// <summary>
/// The current log of cpu instructions
/// </summary>
IEnumerable<TraceInfo> Contents { get; }
//IEnumerable<TraceInfo> Contents { get; }
/// <summary>
/// Takes the current log of cpu instructions, when doing so, it will clear the contents from the buffer
/// </summary>
IEnumerable<TraceInfo> TakeContents();
//IEnumerable<TraceInfo> TakeContents();
void Put(TraceInfo content);
//void Put(TraceInfo content);
//that's right, we can only have one sink.
//a sink can route to two other sinks if it has to, though
ITraceSink Sink { get; set; }
/// <summary>
/// This is defined as equivalent to Sink != null
/// It's put here because it's such a common operation to check whether it's enabled, and it's not nice to write Sink != null all over
/// </summary>
bool Enabled { get; }
/// <summary>
/// This is defined as equivalent to Sink.Put
/// TBD: could it be defined as equivalent to if(Enabled) Sink.Put()? Probably not, that's just a small amount of wasted work
/// </summary>
void Put(TraceInfo info);
}
public class TraceInfo