parent
45a83322a7
commit
799afc6b0a
|
@ -2,72 +2,74 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Nintendo.N64.NativeApi;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.N64
|
||||
{
|
||||
public partial class N64
|
||||
partial class N64
|
||||
{
|
||||
private readonly ITraceable Tracer;
|
||||
public TraceBuffer Tracer { get; private set; }
|
||||
|
||||
public class m64pTraceBuffer : CallbackBasedTraceBuffer
|
||||
private mupen64plusApi.TraceCallback _tracecb;
|
||||
|
||||
public void MakeTrace()
|
||||
{
|
||||
public m64pTraceBuffer(IDebuggable debuggableCore, IMemoryDomains memoryDomains, IDisassemblable disassembler)
|
||||
: base(debuggableCore, memoryDomains, disassembler)
|
||||
var regs = GetCpuFlagsAndRegisters();
|
||||
uint pc = (uint)regs["PC"].Value;
|
||||
var length = 0;
|
||||
var disasm = Disassemble(MemoryDomains.SystemBus, pc, out length);
|
||||
|
||||
var traceInfo = new TraceInfo
|
||||
{
|
||||
Header = "r3400: PC, mnemonic, arguments, registers (GPRs, Load/Link Bit, MultHI, MultLO, Implementation/Revision, Control/Status)";
|
||||
}
|
||||
|
||||
public override void TraceFromCallback()
|
||||
{
|
||||
var regs = DebuggableCore.GetCpuFlagsAndRegisters();
|
||||
uint pc = (uint)regs["PC"].Value;
|
||||
var length = 0;
|
||||
var disasm = Disassembler.Disassemble(MemoryDomains.SystemBus, pc, out length);
|
||||
|
||||
var traceInfo = new TraceInfo
|
||||
{
|
||||
Disassembly = string.Format("{0:X}: {1}", pc, disasm.PadRight(32))
|
||||
};
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
for (int i = 1; i < 32; i++) // r0 is always zero
|
||||
{
|
||||
UInt64 val = (regs["REG" + i + "_hi"].Value << 32) | regs["REG" + i + "_lo"].Value;
|
||||
string name = GPRnames[i];
|
||||
sb.Append(string.Format("{0}:{1:X16} ", name, val));
|
||||
}
|
||||
|
||||
sb.Append(string.Format("LL:{0:X8} ", regs["LL"].Value));
|
||||
sb.Append(string.Format("LO:{0:X8}{1:X8} ", regs["LO_hi"].Value, regs["LO_lo"].Value));
|
||||
sb.Append(string.Format("HI:{0:X8}{1:X8} ", regs["HI_hi"].Value, regs["HI_lo"].Value));
|
||||
sb.Append(string.Format("FCR0:{0:X8} ", regs["FCR0"].Value));
|
||||
sb.Append(string.Format("FCR31:{0:X8} ", regs["FCR31"].Value));
|
||||
// drop co-processor regs for now
|
||||
|
||||
traceInfo.RegisterInfo = sb.ToString().Trim();
|
||||
|
||||
Put(traceInfo);
|
||||
}
|
||||
|
||||
private string[] GPRnames = new string[32]
|
||||
{
|
||||
"r0",
|
||||
"at",
|
||||
"v0", "v1",
|
||||
"a0", "a1", "a2", "a3",
|
||||
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9",
|
||||
"k0", "k1",
|
||||
"gp",
|
||||
"sp",
|
||||
"s8",
|
||||
"ra"
|
||||
Disassembly = string.Format("{0:X}: {1}", pc, disasm.PadRight(32))
|
||||
};
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
for (int i = 1; i < 32; i++) // r0 is always zero
|
||||
{
|
||||
UInt64 val = (regs["REG" + i + "_hi"].Value << 32) | regs["REG" + i + "_lo"].Value;
|
||||
string name = GPRnames[i];
|
||||
sb.Append(string.Format("{0}:{1:X16} ", name, val));
|
||||
}
|
||||
|
||||
sb.Append(string.Format("LL:{0:X8} ", regs["LL"].Value));
|
||||
sb.Append(string.Format("LO:{0:X8}{1:X8} ", regs["LO_hi"].Value, regs["LO_lo"].Value));
|
||||
sb.Append(string.Format("HI:{0:X8}{1:X8} ", regs["HI_hi"].Value, regs["HI_lo"].Value));
|
||||
sb.Append(string.Format("FCR0:{0:X8} ", regs["FCR0"].Value));
|
||||
sb.Append(string.Format("FCR31:{0:X8} ", regs["FCR31"].Value));
|
||||
// drop co-processor regs for now
|
||||
|
||||
traceInfo.RegisterInfo = sb.ToString().Trim();
|
||||
|
||||
Tracer.Put(traceInfo);
|
||||
}
|
||||
|
||||
private const string TraceHeader = "r3400: PC, mnemonic, arguments, registers (GPRs, Load/Link Bit, MultHI, MultLO, Implementation/Revision, Control/Status)";
|
||||
|
||||
private void ConnectTracer()
|
||||
{
|
||||
Tracer = new TraceBuffer { Header = TraceHeader };
|
||||
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
|
||||
_tracecb = new mupen64plusApi.TraceCallback(MakeTrace);
|
||||
}
|
||||
|
||||
private string[] GPRnames = new string[32]
|
||||
{
|
||||
"r0",
|
||||
"at",
|
||||
"v0", "v1",
|
||||
"a0", "a1", "a2", "a3",
|
||||
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9",
|
||||
"k0", "k1",
|
||||
"gp",
|
||||
"sp",
|
||||
"s8",
|
||||
"ra"
|
||||
};
|
||||
}
|
||||
}
|
|
@ -138,11 +138,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
|||
api.AttachPlugin(mupen64plusApi.m64p_plugin_type.M64PLUGIN_RSP, rsp);
|
||||
|
||||
InitMemoryDomains();
|
||||
ConnectTracer();
|
||||
RefreshMemoryCallbacks();
|
||||
|
||||
Tracer = new m64pTraceBuffer(this, MemoryDomains, this);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
|
||||
|
||||
api.AsyncExecuteEmulator();
|
||||
|
||||
// Hack: Saving a state on frame 0 has been shown to not be sync stable. Advance past that frame to avoid the problem.
|
||||
|
@ -215,9 +213,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
|||
public void FrameAdvance(bool render, bool rendersound)
|
||||
{
|
||||
IsVIFrame = false;
|
||||
|
||||
|
||||
RefreshMemoryCallbacks();
|
||||
|
||||
if (Tracer.Enabled)
|
||||
{
|
||||
api.setTraceCallback(_tracecb);
|
||||
}
|
||||
else
|
||||
{
|
||||
api.setTraceCallback(null);
|
||||
}
|
||||
|
||||
_audioProvider.RenderSound = rendersound;
|
||||
|
||||
if (Controller["Reset"])
|
||||
|
|
|
@ -377,6 +377,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
|||
public delegate void SetExecuteCallback(MemoryCallback callback);
|
||||
SetExecuteCallback m64pSetExecuteCallback;
|
||||
|
||||
/// <summary>
|
||||
/// Type of the trace callback
|
||||
/// </summary>
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void TraceCallback();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the trace callback
|
||||
/// </summary>
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void SetTraceCallback(TraceCallback callback);
|
||||
SetTraceCallback m64pSetTraceCallback;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the CPU registers
|
||||
/// </summary>
|
||||
|
@ -511,6 +524,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
|||
m64pSetReadCallback = (SetReadCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetReadCallback"), typeof(SetReadCallback));
|
||||
m64pSetWriteCallback = (SetWriteCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetWriteCallback"), typeof(SetWriteCallback));
|
||||
m64pSetExecuteCallback = (SetExecuteCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetExecuteCallback"), typeof(SetExecuteCallback));
|
||||
m64pSetTraceCallback = (SetTraceCallback)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "SetTraceCallback"), typeof(SetTraceCallback));
|
||||
|
||||
m64pGetRegisters = (GetRegisters)Marshal.GetDelegateForFunctionPointer(GetProcAddress(CoreDll, "GetRegisters"), typeof(GetRegisters));
|
||||
|
||||
|
@ -713,6 +727,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
|
|||
m64pSetExecuteCallback(callback);
|
||||
}
|
||||
|
||||
public void setTraceCallback(TraceCallback callback)
|
||||
{
|
||||
m64pSetTraceCallback(callback);
|
||||
}
|
||||
|
||||
public void getRegisters(byte[] dest)
|
||||
{
|
||||
m64pGetRegisters(dest);
|
||||
|
|
|
@ -136,6 +136,7 @@ static int firstFrameBufferSetting;
|
|||
void (*readCB)(unsigned int) = NULL;
|
||||
void (*writeCB)(unsigned int) = NULL;
|
||||
void (*executeCB)(unsigned int) = NULL;
|
||||
void (*traceCB)(void) = NULL;
|
||||
|
||||
// uncomment to output count of calls to write_rdram():
|
||||
//#define COUNT_WRITE_RDRAM_CALLS 1
|
||||
|
@ -4049,4 +4050,9 @@ EXPORT void CALL SetWriteCallback(void (*CB)(unsigned int))
|
|||
EXPORT void CALL SetExecuteCallback(void (*CB)(unsigned int))
|
||||
{
|
||||
executeCB = CB;
|
||||
}
|
||||
|
||||
EXPORT void CALL SetTraceCallback(void (*CB)(unsigned int))
|
||||
{
|
||||
traceCB = CB;
|
||||
}
|
|
@ -27,6 +27,7 @@
|
|||
#define READCB() if (readCB) readCB(address)
|
||||
#define WRITECB() if (writeCB) writeCB(address)
|
||||
#define EXECUTECB() if (executeCB) executeCB(PC->addr)
|
||||
#define TRACECB() if (traceCB) traceCB()
|
||||
|
||||
#define READCBADDR(addr) if (readCB) readCB(addr)
|
||||
#define WRITECBADDR(addr) if (writeCB) writeCB(addr)
|
||||
|
@ -56,6 +57,7 @@ extern unsigned short hword;
|
|||
extern unsigned long long dword, *rdword;
|
||||
|
||||
extern void (*executeCB)(unsigned int);
|
||||
extern void (*traceCB)(void);
|
||||
|
||||
extern void (*readmem[0x10000])(void);
|
||||
extern void (*readmemb[0x10000])(void);
|
||||
|
|
|
@ -420,6 +420,7 @@ void pure_interpreter(void)
|
|||
if (g_DebuggerActive) update_debugger(PC->addr);
|
||||
#endif
|
||||
EXECUTECB();
|
||||
TRACECB();
|
||||
PC->ops();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1069,6 +1069,7 @@ void r4300_execute(void (*startcb)(void))
|
|||
if (g_DebuggerActive) update_debugger(PC->addr);
|
||||
#endif
|
||||
EXECUTECB();
|
||||
TRACECB();
|
||||
PC->ops();
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue