From 3eda4a90a63074562a852fa0967d15f33c165891 Mon Sep 17 00:00:00 2001 From: goyuken Date: Fri, 2 Nov 2012 19:44:31 +0000 Subject: [PATCH] gbhawk: tracelogger --- .../Consoles/Nintendo/Gameboy/Gambatte.cs | 31 ++++++++++++++++++ .../Consoles/Nintendo/Gameboy/LibGambatte.cs | 15 +++++++++ .../output/dll/libgambatte.dll | Bin 177152 -> 177664 bytes libgambatte/include/gambatte.h | 1 + libgambatte/src/cinterface.cpp | 6 ++++ libgambatte/src/cinterface.h | 2 ++ libgambatte/src/cpu.cpp | 25 ++++++++++++-- libgambatte/src/cpu.h | 6 ++++ libgambatte/src/gambatte.cpp | 4 +++ 9 files changed, 88 insertions(+), 2 deletions(-) diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs index 18d7edf42c..5f03aee564 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -139,6 +139,11 @@ namespace BizHawk.Emulation.Consoles.GB LibGambatte.gambatte_reset(GambatteState); RefreshMemoryCallbacks(); + if (CoreInputComm.Tracer.Enabled) + tracecb = MakeTrace; + else + tracecb = null; + LibGambatte.gambatte_settracecallback(GambatteState, tracecb); LibGambatte.gambatte_runfor(GambatteState, VideoBuffer, 160, soundbuff, ref nsamp); @@ -410,6 +415,7 @@ namespace BizHawk.Emulation.Consoles.GB VsyncDen = 4389, RomStatusAnnotation = null, //"Bizwhackin it up", RomStatusDetails = null, //"LEVAR BURTON", + CpuTraceAvailable = true }; public CoreOutputComm CoreOutputComm @@ -417,6 +423,31 @@ namespace BizHawk.Emulation.Consoles.GB get { return GbOutputComm; } } + LibGambatte.TraceCallback tracecb; + + void MakeTrace(IntPtr _s) + { + int[] s = new int[13]; + System.Runtime.InteropServices.Marshal.Copy(_s, s, 0, 13); + + CoreInputComm.Tracer.Put(string.Format( + "{1:x4} {12:x2} SP:{2:x2} A:{3:x2} B:{4:x2} C:{5:x2} D:{6:x2} E:{7:x2} F:{8:x2} H:{9:x2} L:{10:x2} {11} Cy:{0}", + s[0], + s[1] & 0xffff, + s[2] & 0xffff, + s[3] & 0xff, + s[4] & 0xff, + s[5] & 0xff, + s[6] & 0xff, + s[7] & 0xff, + s[8] & 0xff, + s[9] & 0xff, + s[10] & 0xff, + s[11] != 0 ? "skip" : "", + s[12] & 0xff + )); + } + #region MemoryDomains class MemoryRefresher diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs index 948998da5b..0edce548ee 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs @@ -152,6 +152,21 @@ namespace BizHawk.Emulation.Consoles.GB [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void gambatte_setwritecallback(IntPtr core, MemoryCallback callback); + /// + /// type of the cpu trace callback + /// + /// cpu state + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void TraceCallback(IntPtr state); + + /// + /// set a callback to occur immediately BEFORE each opcode is executed + /// + /// opaque state pointer + /// null to clear + [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void gambatte_settracecallback(IntPtr core, TraceCallback callback); + /// /// Sets the directory used for storing save data. The default is the same directory as the ROM Image file. /// diff --git a/BizHawk.MultiClient/output/dll/libgambatte.dll b/BizHawk.MultiClient/output/dll/libgambatte.dll index a7a81490b3e5436e1ecb46af08d0a8e416c880c0..94c1c8beae95b4ca26485373e17d8f639549fc1a 100644 GIT binary patch delta 30210 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 diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index ccc1dd2f8f..a0729dbea9 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -85,6 +85,7 @@ public: void setReadCallback(void (*callback)(unsigned)); void setWriteCallback(void (*callback)(unsigned)); + void setTraceCallback(void (*callback)(void *)); /** Sets the directory used for storing save data. The default is the same directory as the ROM Image file. */ void setSaveDir(const std::string &sdir); diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp index f85e0d589f..26735cf718 100644 --- a/libgambatte/src/cinterface.cpp +++ b/libgambatte/src/cinterface.cpp @@ -77,6 +77,12 @@ __declspec(dllexport) void gambatte_setwritecallback(void *core, void (*callback g->setWriteCallback(callback); } +__declspec(dllexport) void gambatte_settracecallback(void *core, void (*callback)(void *)) +{ + GB *g = (GB *) core; + g->setTraceCallback(callback); +} + __declspec(dllexport) void gambatte_setsavedir(void *core, const char *sdir) { GB *g = (GB *) core; diff --git a/libgambatte/src/cinterface.h b/libgambatte/src/cinterface.h index 30278421ab..01b0c383d7 100644 --- a/libgambatte/src/cinterface.h +++ b/libgambatte/src/cinterface.h @@ -22,6 +22,8 @@ extern "C" __declspec(dllexport) void gambatte_setwritecallback(void *core, void (*callback)(unsigned)); + __declspec(dllexport) void gambatte_settracecallback(void *core, void (*callback)(void *)); + __declspec(dllexport) void gambatte_setsavedir(void *core, const char *sdir); __declspec(dllexport) int gambatte_iscgb(void *core); diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp index d36d1d818f..181232769e 100644 --- a/libgambatte/src/cpu.cpp +++ b/libgambatte/src/cpu.cpp @@ -38,7 +38,8 @@ CPU::CPU() E(0xD8), H(0x01), L(0x4D), - skip(false) + skip(false), + tracecallback(0) { } @@ -520,7 +521,27 @@ void CPU::process(const unsigned long cycles) { } else while (cycleCounter < memory.nextEventTime()) { unsigned char opcode; - PC_READ(opcode); + if (tracecallback) { + int result[13]; + result[0] = cycleCounter; + result[1] = PC; + result[2] = SP; + result[3] = A; + result[4] = B; + result[5] = C; + result[6] = D; + result[7] = E; + result[8] = F(); + result[9] = H; + result[10] = L; + result[11] = skip; + PC_READ(opcode); + result[12] = opcode; + tracecallback((void *)result); + } + else { + PC_READ(opcode); + } if (skip) { PC = (PC - 1) & 0xFFFF; diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index e56dafd9d1..640f518460 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -39,6 +39,8 @@ class CPU { void process(unsigned long cycles); + void (*tracecallback)(void *); + public: CPU(); @@ -72,6 +74,10 @@ public: void setWriteCallback(void (*callback)(unsigned)) { memory.setWriteCallback(callback); } + + void setTraceCallback(void (*callback)(void *)) { + tracecallback = callback; + } void setSaveDir(const std::string &sdir) { memory.setSaveDir(sdir); diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index 52b64a32c6..acb5a29b8c 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -103,6 +103,10 @@ void GB::setWriteCallback(void (*callback)(unsigned)) { p_->cpu.setWriteCallback(callback); } +void GB::setTraceCallback(void (*callback)(void *)) { + p_->cpu.setTraceCallback(callback); +} + void GB::setSaveDir(const std::string &sdir) { p_->cpu.setSaveDir(sdir); }