diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs index 6157927780..057a62455d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAMemoryCallbackSystem.cs @@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public class MGBAMemoryCallbackSystem : IMemoryCallbackSystem { private readonly MGBAHawk _mgba; + private LibmGBA.ExecCallback _executeCallback; + private readonly Dictionary _execPcs = new Dictionary { [0] = null }; public MGBAMemoryCallbackSystem(MGBAHawk mgba) { @@ -18,7 +20,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA private readonly List _callbacks = new List(); public string[] AvailableScopes { get; } = { "System Bus" }; - public bool ExecuteCallbacksAvailable => false; + public bool ExecuteCallbacksAvailable => true; public bool HasReads => _callbacks.Any(c => c.Callback.Type == MemoryCallbackType.Read); public bool HasWrites => _callbacks.Any(c => c.Callback.Type == MemoryCallbackType.Write); @@ -50,14 +52,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA var container = new CallbackContainer(callback); - if (container.Callback.Type == MemoryCallbackType.Execute) - { - // TODO - } - else - { - LibmGBA.BizSetMemCallback(container.CallDelegate); - container.ID = LibmGBA.BizSetWatchpoint(_mgba.Core, callback.Address.Value, container.WatchPointType); + if (container.Callback.Type == MemoryCallbackType.Execute) + { + _executeCallback = RunExecCallback; + _execPcs[callback.Address.Value] = callback; + LibmGBA.BizSetExecCallback(_executeCallback); + } + else + { + LibmGBA.BizSetMemCallback(container.CallDelegate); + container.ID = LibmGBA.BizSetWatchpoint(_mgba.Core, callback.Address.Value, container.WatchPointType); } _callbacks.Add(container); @@ -69,7 +73,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA if (cbToRemove != null) { - if (LibmGBA.BizClearWatchpoint(_mgba.Core, cbToRemove.ID)) + if (cbToRemove.Callback.Type == MemoryCallbackType.Execute) + { + _callbacks.Remove(cbToRemove); + if (_callbacks.All(cb => cb.Callback.Type != MemoryCallbackType.Execute)) + { + _executeCallback = null; + LibmGBA.BizSetExecCallback(null); + } + } + else if (LibmGBA.BizClearWatchpoint(_mgba.Core, cbToRemove.ID)) { _callbacks.Remove(cbToRemove); } @@ -102,6 +115,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA { // Not a thing in this implementation } + + private void RunExecCallback(uint pc) + { + if (_execPcs.TryGetValue(pc, out var callback)) + { + callback?.Callback?.Invoke(pc, 0, 0); + } + } } internal class CallbackContainer @@ -129,14 +150,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA case MemoryCallbackType.Write: return LibmGBA.mWatchpointType.WATCHPOINT_WRITE; case MemoryCallbackType.Execute: - throw new NotImplementedException("Executes not implemented yet"); + throw new NotImplementedException("Executes can not be used from watch points."); } } } public LibmGBA.MemCallback CallDelegate; - void Call(uint addr, LibmGBA.mWatchpointType type, uint oldValue, uint newValue) + private void Call(uint addr, LibmGBA.mWatchpointType type, uint oldValue, uint newValue) { Callback.Callback?.Invoke(addr, newValue, 0); } diff --git a/BizHawk.sln.DotSettings b/BizHawk.sln.DotSettings index 2f2f723973..41c1b010f7 100644 --- a/BizHawk.sln.DotSettings +++ b/BizHawk.sln.DotSettings @@ -570,6 +570,7 @@ True True True + True True True True