BizHawk/BizHawk.Emulation.Common/Base Implementations/CallbackBasedTraceBuffer.cs

102 lines
2.8 KiB
C#
Raw Normal View History

2017-04-15 19:53:02 +00:00
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common.IEmulatorExtensions;
namespace BizHawk.Emulation.Common
{
/// <summary>
/// An implementation of <seealso cref="ITraceable"/> that is implementation using only methods
/// from <seealso cref="IDebuggable"/>, <seealso cref="IMemoryDomains"/>, and <seealso cref="IDisassemblable"/>
/// Useful for ported cores that have these hooks but no trace logging hook,
/// This allows for a traceable implementation without the need for additional API
/// Note that this technique will always be significantly slower than a direct implementation
/// </summary>
/// <seealso cref="ITraceable"/>
/// <seealso cref="IDebuggable"/>
/// <seealso cref="IMemoryDomains"/>
/// <seealso cref="IDisassemblable"/>
2017-04-15 19:53:02 +00:00
public abstract class CallbackBasedTraceBuffer : ITraceable
{
protected CallbackBasedTraceBuffer(IDebuggable debuggableCore, IMemoryDomains memoryDomains, IDisassemblable disassembler)
2017-04-15 19:53:02 +00:00
{
if (!debuggableCore.MemoryCallbacksAvailable())
{
throw new InvalidOperationException("Memory callbacks are required");
}
try
{
debuggableCore.GetCpuFlagsAndRegisters();
}
catch (NotImplementedException)
{
2019-03-28 03:17:14 +00:00
throw new InvalidOperationException($"{nameof(IDebuggable.GetCpuFlagsAndRegisters)} is required");
2017-04-15 19:53:02 +00:00
}
Header = "Instructions";
DebuggableCore = debuggableCore;
MemoryDomains = memoryDomains;
Disassembler = disassembler;
}
protected readonly IMemoryDomains MemoryDomains;
protected readonly IDisassemblable Disassembler;
protected readonly IDebuggable DebuggableCore;
protected readonly List<TraceInfo> Buffer = new List<TraceInfo>();
2019-06-06 09:04:47 +00:00
protected abstract void TraceFromCallback(uint addr, uint value, uint flags);
2016-12-14 20:30:43 +00:00
private ITraceSink _sink;
2017-04-15 19:53:02 +00:00
public bool Enabled => Sink != null;
2017-04-15 20:37:30 +00:00
public void Put(TraceInfo info)
2016-12-14 20:30:43 +00:00
{
Sink.Put(info);
}
public ITraceSink Sink
{
private get
{
return _sink;
}
2017-04-24 12:41:55 +00:00
set
{
_sink = value;
DebuggableCore.MemoryCallbacks.Remove(TraceFromCallback);
if (_sink != null)
{
DebuggableCore.MemoryCallbacks.Add(new TracingMemoryCallback(TraceFromCallback));
}
}
2017-04-15 19:53:02 +00:00
}
public string Header { get; protected set; }
2017-04-15 19:53:02 +00:00
public class TracingMemoryCallback : IMemoryCallback
{
2019-06-06 09:04:47 +00:00
public TracingMemoryCallback(MemoryCallbackDelegate callback)
2017-04-15 19:53:02 +00:00
{
Callback = callback;
}
public MemoryCallbackType Type => MemoryCallbackType.Execute;
2017-04-15 20:37:30 +00:00
public string Name => "Trace Logging";
2017-04-15 19:53:02 +00:00
2019-06-06 09:04:47 +00:00
public MemoryCallbackDelegate Callback { get; }
2017-04-15 19:53:02 +00:00
public uint? Address => null;
public uint? AddressMask => null;
public string Scope => ""; // This will be relevant if/when the trace logger can trace anything other than the system bus
2017-04-15 19:53:02 +00:00
}
}
}