diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs index 7850fe0566..291780a441 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs @@ -140,6 +140,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA [DllImport(dllname, CallingConvention = cc)] public static extern IntPtr GetRegisters(IntPtr g); + [UnmanagedFunctionPointer(cc)] + public delegate void AddressCallback(uint addr); + + [DllImport(dllname, CallingConvention = cc)] + public static extern void SetPadCallback(IntPtr g, StandardCallback cb); + [DllImport(dllname, CallingConvention = cc)] + public static extern void SetFetchCallback(IntPtr g, AddressCallback cb); + [DllImport(dllname, CallingConvention = cc)] + public static extern void SetReadCallback(IntPtr g, AddressCallback cb); + [DllImport(dllname, CallingConvention = cc)] + public static extern void SetWriteCallback(IntPtr g, AddressCallback cb); + + [StructLayout(LayoutKind.Sequential)] public class MemoryAreas { diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs index 947bfea4ae..5b1f5fd6cd 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs @@ -76,6 +76,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA savebuff2 = new byte[savebuff.Length + 13]; InitMemoryDomains(); InitRegisters(); + InitCallbacks(); // todo: hook me up as a setting SetupColors(); @@ -94,6 +95,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA if (Controller["Power"]) LibVBANext.Reset(Core); + SyncCallbacks(); + IsLagFrame = LibVBANext.FrameAdvance(Core, GetButtons(), videobuff, soundbuff, out numsamp, videopalette); if (IsLagFrame) @@ -259,6 +262,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA #region Debugging + LibVBANext.StandardCallback padcb; + LibVBANext.AddressCallback fetchcb; + LibVBANext.AddressCallback readcb; + LibVBANext.AddressCallback writecb; + + void InitCallbacks() + { + padcb = new LibVBANext.StandardCallback(() => CoreComm.InputCallback.Call()); + fetchcb = new LibVBANext.AddressCallback((addr) => CoreComm.MemoryCallbackSystem.CallExecute(addr)); + readcb = new LibVBANext.AddressCallback((addr) => CoreComm.MemoryCallbackSystem.CallRead(addr)); + writecb = new LibVBANext.AddressCallback((addr) => CoreComm.MemoryCallbackSystem.CallWrite(addr)); + } + + void SyncCallbacks() + { + LibVBANext.SetPadCallback(Core, CoreComm.InputCallback.Any() ? padcb : null); + LibVBANext.SetFetchCallback(Core, CoreComm.MemoryCallbackSystem.HasExecutes ? fetchcb : null); + LibVBANext.SetReadCallback(Core, CoreComm.MemoryCallbackSystem.HasReads ? readcb : null); + LibVBANext.SetWriteCallback(Core, CoreComm.MemoryCallbackSystem.HasWrites ? writecb : null); + } + LibVBANext.StandardCallback scanlinecb; GBAGPUMemoryAreas IGBAGPUViewable.GetMemoryAreas() diff --git a/output/dll/libvbanext.dll b/output/dll/libvbanext.dll index 2fabdcb1e6..22be59b15f 100644 Binary files a/output/dll/libvbanext.dll and b/output/dll/libvbanext.dll differ diff --git a/vbanext/instance.cpp b/vbanext/instance.cpp index ebd854dbe1..6d6d962c81 100644 --- a/vbanext/instance.cpp +++ b/vbanext/instance.cpp @@ -2922,6 +2922,9 @@ int timer3ClockReload ; INLINE u32 CPUReadMemory(u32 address) { + if (readCallback) + readCallback(address); + u32 value; switch(address >> 24) { @@ -2947,7 +2950,11 @@ INLINE u32 CPUReadMemory(u32 address) case 0x04: /* I/O registers */ if (address == 0x4000130) + { + if (padCallback) + padCallback(); lagged = false; + } if((address < 0x4000400) && ioReadable[address & 0x3fc]) { if(ioReadable[(address & 0x3fc) + 2]) @@ -3010,8 +3017,10 @@ unreadable: INLINE u32 CPUReadHalfWord(u32 address) { - u32 value; + if (readCallback) + readCallback(address); + u32 value; switch(address >> 24) { case 0: @@ -3033,7 +3042,11 @@ INLINE u32 CPUReadHalfWord(u32 address) break; case 4: if (address == 0x4000130) + { + if (padCallback) + padCallback(); lagged = false; + } if((address < 0x4000400) && ioReadable[address & 0x3fe]) { @@ -3115,6 +3128,9 @@ INLINE u16 CPUReadHalfWordSigned(u32 address) INLINE u8 CPUReadByte(u32 address) { + if (readCallback) + readCallback(address); + switch(address >> 24) { case 0: @@ -3132,7 +3148,11 @@ INLINE u8 CPUReadByte(u32 address) return internalRAM[address & 0x7fff]; case 4: if (address == 0x4000130 || address == 0x4000131) + { + if (padCallback) + padCallback(); lagged = false; + } if((address < 0x4000400) && ioReadable[address & 0x3ff]) return ioMem[address & 0x3ff]; @@ -3185,6 +3205,9 @@ unreadable: INLINE void CPUWriteMemory(u32 address, u32 value) { + if (writeCallback) + writeCallback(address); + switch(address >> 24) { case 0x02: @@ -3230,6 +3253,9 @@ INLINE void CPUWriteMemory(u32 address, u32 value) INLINE void CPUWriteHalfWord(u32 address, u16 value) { + if (writeCallback) + writeCallback(address); + switch(address >> 24) { case 2: @@ -3276,6 +3302,9 @@ INLINE void CPUWriteHalfWord(u32 address, u16 value) INLINE void CPUWriteByte(u32 address, u8 b) { + if (writeCallback) + writeCallback(address); + switch(address >> 24) { case 2: @@ -5576,6 +5605,8 @@ int armExecute (void) int oldArmNextPC = bus.armNextPC; bus.armNextPC = bus.reg[15].I; + if (fetchCallback) + fetchCallback(bus.armNextPC); bus.reg[15].I += 4; ARM_PREFETCH_NEXT; @@ -6469,7 +6500,9 @@ DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E) if (bus.busPrefetchCount == 0) bus.busPrefetch = bus.busPrefetchEnable; u32 address = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - bus.reg[regist].I = CPUReadMemoryQuick(address); + // why quick? + // bus.reg[regist].I = CPUReadMemoryQuick(address); + bus.reg[regist].I = CPUReadMemory(address); bus.busPrefetchCount=0; int dataticks_value = DATATICKS_ACCESS_32BIT(address); DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); @@ -6664,7 +6697,9 @@ DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E) if (bus.busPrefetchCount == 0) bus.busPrefetch = bus.busPrefetchEnable; u32 address = bus.reg[13].I + ((opcode&255)<<2); - bus.reg[regist].I = CPUReadMemoryQuick(address); + // why quick? + // bus.reg[regist].I = CPUReadMemoryQuick(address); + bus.reg[regist].I = CPUReadMemory(address); int dataticks_value = DATATICKS_ACCESS_32BIT(address); DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); @@ -7169,6 +7204,9 @@ int thumbExecute (void) u32 oldArmNextPC = bus.armNextPC; bus.armNextPC = bus.reg[15].I; + if (fetchCallback) + fetchCallback(bus.armNextPC); + bus.reg[15].I += 2; THUMB_PREFETCH_NEXT; @@ -12941,6 +12979,12 @@ bool lagged; void (*scanlineCallback)(); int scanlineCallbackLine; +void (*fetchCallback)(u32 addr); +void (*writeCallback)(u32 addr); +void (*readCallback)(u32 addr); + +void (*padCallback)(); + void systemDrawScreen (void) { // upconvert 555->888 (TODO: BETTER) @@ -13365,6 +13409,30 @@ templatebool SyncBatteryRam(NewState *ns) return &bus.reg[0].I; } + void SetPadCallback(void (*cb)()) + { + // before each read of the pad regs + padCallback = cb; + } + + void SetFetchCallback(void (*cb)(u32 addr)) + { + // before each opcode fetch + fetchCallback = cb; + } + + void SetReadCallback(void (*cb)(u32 addr)) + { + // before each read, not including opcodes, including pad regs + readCallback = cb; + } + + void SetWriteCallback(void (*cb)(u32 addr)) + { + // before each write + writeCallback = cb; + } + }; // class Gigazoid // zeroing mem operators: these are very important @@ -13516,4 +13584,10 @@ EXPORT u32 *GetRegisters(Gigazoid *g) return g->GetRegisters(); } +EXPORT void SetPadCallback(Gigazoid *g, void (*cb)()) { g->SetPadCallback(cb); } +EXPORT void SetFetchCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetFetchCallback(cb); } +EXPORT void SetReadCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetReadCallback(cb); } +EXPORT void SetWriteCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetWriteCallback(cb); } + + #include "optable.inc"