2017-04-15 19:53:02 +00:00
using System ;
using System.Collections.Generic ;
2019-12-15 18:12:52 +00:00
using System.Linq ;
2017-04-15 19:53:02 +00:00
using BizHawk.Emulation.Common.IEmulatorExtensions ;
namespace BizHawk.Emulation.Common
2016-12-14 15:11:07 +00:00
{
/// <summary>
2017-04-27 13:24:21 +00:00
/// An implementation of <seealso cref="ITraceable"/> that is implementation using only methods
/// from <seealso cref="IDebuggable"/>, <seealso cref="IMemoryDomains"/>, and <seealso cref="IDisassemblable"/>
2016-12-14 15:11:07 +00:00
/// 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"/>
2017-04-14 17:28:23 +00:00
/// <seealso cref="IDisassemblable"/>
2017-04-15 19:53:02 +00:00
public abstract class CallbackBasedTraceBuffer : ITraceable
{
2019-12-28 20:52:34 +00:00
/// <exception cref="InvalidOperationException"><paramref name="debuggableCore"/> does not provide memory callback support or does not implement <see cref="IDebuggable.GetCpuFlagsAndRegisters"/></exception>
2017-04-27 13:24:21 +00:00
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-08-13 20:31:04 +00:00
2016-12-14 20:30:43 +00:00
private ITraceSink _sink ;
2016-08-13 20:31:04 +00:00
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 ) ;
}
2016-08-13 20:31:04 +00:00
public ITraceSink Sink
{
2017-04-27 13:24:21 +00:00
private get
2016-08-13 20:31:04 +00:00
{
return _sink ;
}
2017-04-24 12:41:55 +00:00
2016-08-13 20:31:04 +00:00
set
{
_sink = value ;
DebuggableCore . MemoryCallbacks . Remove ( TraceFromCallback ) ;
if ( _sink ! = null )
{
2019-12-15 18:12:52 +00:00
var scope = DebuggableCore . MemoryCallbacks . AvailableScopes . First ( ) ; // This will be an issue when cores use this trace buffer and utilize multiple scopes
DebuggableCore . MemoryCallbacks . Add ( new TracingMemoryCallback ( TraceFromCallback , scope ) ) ;
2016-08-13 20:31:04 +00:00
}
}
2017-04-15 19:53:02 +00:00
}
2017-04-27 13:24:21 +00:00
public string Header { get ; protected set ; }
2017-04-15 19:53:02 +00:00
public class TracingMemoryCallback : IMemoryCallback
{
2019-12-15 18:12:52 +00:00
public TracingMemoryCallback ( MemoryCallbackDelegate callback , string scope )
2017-04-15 19:53:02 +00:00
{
Callback = callback ;
2019-12-15 18:12:52 +00:00
Scope = scope ;
2017-04-15 19:53:02 +00:00
}
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 ;
2017-08-02 03:05:17 +00:00
2019-12-15 18:12:52 +00:00
public string Scope { get ; }
2017-04-15 19:53:02 +00:00
}
}
}