From e5c569f818f449c00d4b3ef1336b2574528d5d69 Mon Sep 17 00:00:00 2001 From: goyuken Date: Mon, 11 Nov 2013 18:05:29 +0000 Subject: [PATCH] support register reading on GB core. untested as i can't compile at the moment. flags are exported as part of register "F", as is usual for z80. --- .../Consoles/Nintendo/Gameboy/Gambatte.cs | 15 ++++++++++++++- .../Consoles/Nintendo/Gameboy/LibGambatte.cs | 13 +++++++++++++ libgambatte/include/gambatte.h | 2 ++ libgambatte/src/cinterface.cpp | 6 ++++++ libgambatte/src/cinterface.h | 2 ++ libgambatte/src/cpu.cpp | 14 ++++++++++++++ libgambatte/src/cpu.h | 2 ++ libgambatte/src/gambatte.cpp | 4 ++++ output/dll/libgambatte.dll | Bin 177152 -> 177152 bytes 9 files changed, 57 insertions(+), 1 deletion(-) diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs index a0c43173c6..35affbfbf4 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -126,7 +126,20 @@ namespace BizHawk.Emulation.Consoles.GB public List> GetCpuFlagsAndRegisters() { - throw new NotImplementedException(); + List> ret = new List>(); + int[] data = new int[10]; + LibGambatte.gambatte_getregs(GambatteState, data); + ret.Add(new KeyValuePair("PC", data[(int)LibGambatte.RegIndicies.PC] & 0xffff)); + ret.Add(new KeyValuePair("SP", data[(int)LibGambatte.RegIndicies.SP] & 0xffff)); + ret.Add(new KeyValuePair("A", data[(int)LibGambatte.RegIndicies.A] & 0xff)); + ret.Add(new KeyValuePair("B", data[(int)LibGambatte.RegIndicies.B] & 0xff)); + ret.Add(new KeyValuePair("C", data[(int)LibGambatte.RegIndicies.C] & 0xff)); + ret.Add(new KeyValuePair("D", data[(int)LibGambatte.RegIndicies.D] & 0xff)); + ret.Add(new KeyValuePair("E", data[(int)LibGambatte.RegIndicies.E] & 0xff)); + ret.Add(new KeyValuePair("F", data[(int)LibGambatte.RegIndicies.F] & 0xff)); + ret.Add(new KeyValuePair("H", data[(int)LibGambatte.RegIndicies.H] & 0xff)); + ret.Add(new KeyValuePair("L", data[(int)LibGambatte.RegIndicies.L] & 0xff)); + return ret; } /// diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs index 4e28fcce6d..03a2ed20bb 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/LibGambatte.cs @@ -402,5 +402,18 @@ namespace BizHawk.Emulation.Consoles.GB /// todo [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int gambatte_linkstatus(IntPtr core, int which); + + /// + /// get reg and flag values + /// + /// opaque state pointer + /// length of at least 10, please + [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void gambatte_getregs(IntPtr core, int[] dest); + + public enum RegIndicies : int + { + PC, SP, A, B, C, D, E, F, H, L + } } } diff --git a/libgambatte/include/gambatte.h b/libgambatte/include/gambatte.h index f425485825..bd1f533fe7 100644 --- a/libgambatte/include/gambatte.h +++ b/libgambatte/include/gambatte.h @@ -162,6 +162,8 @@ public: int LinkStatus(int which); + void GetRegs(int *dest); + private: struct Priv; Priv *const p_; diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp index 306d047851..cbe7c855d8 100644 --- a/libgambatte/src/cinterface.cpp +++ b/libgambatte/src/cinterface.cpp @@ -246,3 +246,9 @@ __declspec(dllexport) int gambatte_linkstatus(void *core, int which) GB *g = (GB *) core; return g->LinkStatus(which); } + +__declspec(dllexport) void gambatte_getregs(void *core, int *dest) +{ + GB *g = (GB *) core; + g->GetRegs(dest); +} diff --git a/libgambatte/src/cinterface.h b/libgambatte/src/cinterface.h index 3487f39f57..8a81d658e5 100644 --- a/libgambatte/src/cinterface.h +++ b/libgambatte/src/cinterface.h @@ -67,6 +67,8 @@ extern "C" __declspec(dllexport) int gambatte_linkstatus(void *core, int which); + __declspec(dllexport) void gambatte_getregs(void *core, int *dest); + } diff --git a/libgambatte/src/cpu.cpp b/libgambatte/src/cpu.cpp index 181232769e..1755228700 100644 --- a/libgambatte/src/cpu.cpp +++ b/libgambatte/src/cpu.cpp @@ -2833,4 +2833,18 @@ void CPU::process(const unsigned long cycles) { cycleCounter_ = cycleCounter; } +void CPU::GetRegs(int *dest) +{ + dest[0] = PC_; + dest[1] = SP; + dest[2] = A_; + dest[3] = B; + dest[4] = C; + dest[5] = D; + dest[6] = E; + dest[7] = F(); + dest[8] = H; + dest[9] = L; +} + } diff --git a/libgambatte/src/cpu.h b/libgambatte/src/cpu.h index 45979cd96e..2bd7ca2e2e 100644 --- a/libgambatte/src/cpu.h +++ b/libgambatte/src/cpu.h @@ -127,6 +127,8 @@ public: void ExternalWrite(unsigned short addr, unsigned char val) { memory.write(addr, val, cycleCounter_); } int LinkStatus(int which) { return memory.LinkStatus(which); } + + void GetRegs(int *dest); }; } diff --git a/libgambatte/src/gambatte.cpp b/libgambatte/src/gambatte.cpp index 02460fc07f..bca5e65140 100644 --- a/libgambatte/src/gambatte.cpp +++ b/libgambatte/src/gambatte.cpp @@ -268,4 +268,8 @@ int GB::LinkStatus(int which) { return p_->cpu.LinkStatus(which); } +void GB::GetRegs(int *dest) { + p_->cpu.GetRegs(dest); +} + } diff --git a/output/dll/libgambatte.dll b/output/dll/libgambatte.dll index ba0d506a7fff4c20f688cdd33071b8672fe13453..0e03875488e899e3d073047933553e09787fa3af 100644 GIT binary patch delta 16123 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ν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 Y+FWK|XaCCnEjFS<_TtD*Tt(Rb0J>q57ytkO delta 16069 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