diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs index abcc6566d9..d9794a467f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/Octoshock.cs @@ -324,6 +324,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX OctoshockDll.shock_Create(out psx, SystemRegion, pFirmware); SetMemoryDomains(); + InitMemCallbacks(); //set a default framebuffer based on the first frame of emulation, to cut down on flickering or whatever //this is probably quixotic, but we have to pick something @@ -790,6 +791,39 @@ namespace BizHawk.Emulation.Cores.Sony.PSX #region Debugging + OctoshockDll.ShockCallback_Mem mem_cb; + + void ShockMemCallback(uint address, OctoshockDll.eShockMemCb type, uint size, uint value) + { + switch (type) + { + case OctoshockDll.eShockMemCb.Read: + MemoryCallbacks.CallReads(address); + break; + case OctoshockDll.eShockMemCb.Write: + MemoryCallbacks.CallWrites(address); + break; + case OctoshockDll.eShockMemCb.Execute: + MemoryCallbacks.CallExecutes(address); + break; + } + } + + void InitMemCallbacks() + { + mem_cb = new OctoshockDll.ShockCallback_Mem(ShockMemCallback); + _memoryCallbacks.ActiveChanged += RefreshMemCallbacks; + } + + void RefreshMemCallbacks() + { + OctoshockDll.eShockMemCb mask = OctoshockDll.eShockMemCb.None; + if (MemoryCallbacks.HasReads) mask |= OctoshockDll.eShockMemCb.Read; + if (MemoryCallbacks.HasWrites) mask |= OctoshockDll.eShockMemCb.Write; + if (MemoryCallbacks.HasExecutes) mask |= OctoshockDll.eShockMemCb.Execute; + OctoshockDll.shock_SetMemCb(psx, mem_cb, mask); + } + unsafe void SetMemoryDomains() { var mmd = new List(); @@ -1284,13 +1318,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX public ITraceable Tracer { get { return tracer; } } - public int ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis) + public void ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis) { Tracer.Put(dis); - return OctoshockDll.SHOCK_OK; } - public IMemoryCallbackSystem MemoryCallbacks { get { throw new NotImplementedException(); } } + private readonly MemoryCallbackSystem _memoryCallbacks = new MemoryCallbackSystem(); + public IMemoryCallbackSystem MemoryCallbacks { get { return _memoryCallbacks; } } public bool CanStep(StepType type) { return false; } diff --git a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs index ddecc7141a..955d5f382d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sony/PSX/OctoshockDll.cs @@ -96,6 +96,15 @@ namespace BizHawk.Emulation.Cores.Sony.PSX BobOffset } + [Flags] + public enum eShockMemCb : int + { + None = 0, + Read = 1, + Write = 2, + Execute = 4 + } + public const int SHOCK_OK = 0; public const int SHOCK_FALSE = 0; public const int SHOCK_TRUE = 1; @@ -172,8 +181,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX public TextStateFPtrs ff; }; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate int ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis); + public delegate void ShockCallback_Trace(IntPtr opaque, uint PC, uint inst, string dis); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int ShockDisc_ReadTOC(IntPtr opaque, ShockTOC* read_target, ShockTOCTrack* tracks101); @@ -181,6 +191,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int ShockDisc_ReadLBA(IntPtr opaque, int lba, void* dst); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ShockCallback_Mem(uint address, eShockMemCb type, uint size, uint value); + [DllImport(dd, CallingConvention = cc)] public static extern int shock_Util_DisassembleMIPS(uint PC, uint instr, IntPtr outbuf, int buflen); @@ -193,8 +206,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSX [DllImport(dd, CallingConvention = cc)] public static extern int shock_AnalyzeDisc(IntPtr disc, out ShockDiscInfo info); - - [DllImport(dd, CallingConvention = cc)] public static extern int shock_Create(out IntPtr psx, eRegion region, void* firmware512k); @@ -271,7 +282,10 @@ namespace BizHawk.Emulation.Cores.Sony.PSX public static extern int shock_SetRegister_CPU(IntPtr psx, int index, uint value); [DllImport(dd, CallingConvention = cc)] - public static extern int shock_SetTraceCallback(IntPtr psx, IntPtr opaque, ShockTraceCallback callback); + public static extern int shock_SetTraceCallback(IntPtr psx, IntPtr opaque, ShockCallback_Trace callback); + + [DllImport(dd, CallingConvention = cc)] + public static extern int shock_SetMemCb(IntPtr psx, ShockCallback_Mem cb, eShockMemCb cbMask); [DllImport(dd, CallingConvention = cc)] public static extern int shock_SetLEC(IntPtr psx, bool enable); diff --git a/output/dll/octoshock.dll b/output/dll/octoshock.dll index 1dadf2281d..e2f63ab329 100644 Binary files a/output/dll/octoshock.dll and b/output/dll/octoshock.dll differ diff --git a/psx/octoshock/psx/cpu.cpp b/psx/octoshock/psx/cpu.cpp index 4be2a6699e..a62047975b 100644 --- a/psx/octoshock/psx/cpu.cpp +++ b/psx/octoshock/psx/cpu.cpp @@ -29,6 +29,8 @@ //not very organized, is it void* g_ShockTraceCallbackOpaque = NULL; ShockCallback_Trace g_ShockTraceCallback = NULL; +ShockCallback_Mem g_ShockMemCallback; +eShockMemCb g_ShockMemCbType; /* TODO Make sure load delays are correct. @@ -252,6 +254,9 @@ INLINE T PS_CPU::ReadMemory(pscpu_timestamp_t ×tamp, uint32 address, bool D ReadAbsorb[ReadAbsorbWhich] = 0; ReadAbsorbWhich = 0; + if (g_ShockMemCallback && (g_ShockMemCbType & eShockMemCb_Read)) + g_ShockMemCallback(address, eShockMemCb_Read, DS24 ? 24 : 32, 0); + address &= addr_mask[address >> 29]; if(address >= 0x1F800000 && address <= 0x1F8003FF) @@ -296,6 +301,9 @@ INLINE T PS_CPU::ReadMemory(pscpu_timestamp_t ×tamp, uint32 address, bool D template INLINE void PS_CPU::WriteMemory(pscpu_timestamp_t ×tamp, uint32 address, uint32 value, bool DS24) { + if (g_ShockMemCallback && (g_ShockMemCbType & eShockMemCb_Write)) + g_ShockMemCallback(address, eShockMemCb_Write, DS24 ? 24 : 32, value); + if(MDFN_LIKELY(!(CP0.SR & 0x10000))) { address &= addr_mask[address >> 29]; diff --git a/psx/octoshock/psx/psx.cpp b/psx/octoshock/psx/psx.cpp index e57a3afe10..ab41268a99 100644 --- a/psx/octoshock/psx/psx.cpp +++ b/psx/octoshock/psx/psx.cpp @@ -2700,6 +2700,8 @@ EW_EXPORT s32 shock_SetRenderOptions(void* pxs, ShockRenderOptions* opts) extern void* g_ShockTraceCallbackOpaque; extern ShockCallback_Trace g_ShockTraceCallback; +extern ShockCallback_Mem g_ShockMemCallback; +extern eShockMemCb g_ShockMemCbType; //Sets the callback to be used for CPU tracing EW_EXPORT s32 shock_SetTraceCallback(void* psx, void* opaque, ShockCallback_Trace callback) @@ -2710,6 +2712,14 @@ EW_EXPORT s32 shock_SetTraceCallback(void* psx, void* opaque, ShockCallback_Trac return SHOCK_OK; } +//Sets the callback to be used for memory hook events +EW_EXPORT s32 shock_SetMemCb(void* psx, ShockCallback_Mem callback, eShockMemCb cbMask) +{ + g_ShockMemCallback = callback; + g_ShockMemCbType = cbMask; + return SHOCK_OK; +} + //Sets whether LEC is enabled (sector level error correction). Defaults to FALSE (disabled) EW_EXPORT s32 shock_SetLEC(void* psx, bool enabled) { diff --git a/psx/octoshock/psx/psx.h b/psx/octoshock/psx/psx.h index 44b297e4f7..1804885245 100644 --- a/psx/octoshock/psx/psx.h +++ b/psx/octoshock/psx/psx.h @@ -192,6 +192,13 @@ enum eShockMemcardTransaction eShockMemcardTransaction_CheckDirty = 4, //checks whether the memcard is dirty }; +enum eShockMemCb +{ + eShockMemCb_None = 0, + eShockMemCb_Read = 1, + eShockMemCb_Write = 2, + eShockMemCb_Execute = 4 +}; #define MDFN_MSC_RESET 0 #define MDFN_MSC_POWER 1 @@ -237,7 +244,12 @@ typedef s32 (*ShockDisc_ReadTOC)(void* opaque, ShockTOC *read_target, ShockTOCTr typedef s32 (*ShockDisc_ReadLBA)(void* opaque, s32 lba, void* dst); //The callback to be issued for traces -typedef s32 (*ShockCallback_Trace)(void* opaque, u32 PC, u32 inst, const char* msg); +typedef void (*ShockCallback_Trace)(void* opaque, u32 PC, u32 inst, const char* msg); + +//the callback to be issued for memory hook events +//note: only one callback can be set. the type is sent to mask that one callback, not indicate which event type the callback is fore. +//there isnt one callback per type. +typedef void (*ShockCallback_Mem)(u32 address, eShockMemCb type, u32 size, u32 value); class ShockDiscRef {