mGBA - implement memory execute callbacks

This commit is contained in:
adelikat 2020-04-23 11:56:26 -05:00
parent 3abd526aa9
commit f6735a9f9b
2 changed files with 34 additions and 12 deletions

View File

@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
public class MGBAMemoryCallbackSystem : IMemoryCallbackSystem public class MGBAMemoryCallbackSystem : IMemoryCallbackSystem
{ {
private readonly MGBAHawk _mgba; private readonly MGBAHawk _mgba;
private LibmGBA.ExecCallback _executeCallback;
private readonly Dictionary<uint, IMemoryCallback> _execPcs = new Dictionary<uint, IMemoryCallback> { [0] = null };
public MGBAMemoryCallbackSystem(MGBAHawk mgba) public MGBAMemoryCallbackSystem(MGBAHawk mgba)
{ {
@ -18,7 +20,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
private readonly List<CallbackContainer> _callbacks = new List<CallbackContainer>(); private readonly List<CallbackContainer> _callbacks = new List<CallbackContainer>();
public string[] AvailableScopes { get; } = { "System Bus" }; 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 HasReads => _callbacks.Any(c => c.Callback.Type == MemoryCallbackType.Read);
public bool HasWrites => _callbacks.Any(c => c.Callback.Type == MemoryCallbackType.Write); 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); var container = new CallbackContainer(callback);
if (container.Callback.Type == MemoryCallbackType.Execute) if (container.Callback.Type == MemoryCallbackType.Execute)
{ {
// TODO _executeCallback = RunExecCallback;
} _execPcs[callback.Address.Value] = callback;
else LibmGBA.BizSetExecCallback(_executeCallback);
{ }
LibmGBA.BizSetMemCallback(container.CallDelegate); else
container.ID = LibmGBA.BizSetWatchpoint(_mgba.Core, callback.Address.Value, container.WatchPointType); {
LibmGBA.BizSetMemCallback(container.CallDelegate);
container.ID = LibmGBA.BizSetWatchpoint(_mgba.Core, callback.Address.Value, container.WatchPointType);
} }
_callbacks.Add(container); _callbacks.Add(container);
@ -69,7 +73,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
if (cbToRemove != null) 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); _callbacks.Remove(cbToRemove);
} }
@ -102,6 +115,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
{ {
// Not a thing in this implementation // 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 internal class CallbackContainer
@ -129,14 +150,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
case MemoryCallbackType.Write: case MemoryCallbackType.Write:
return LibmGBA.mWatchpointType.WATCHPOINT_WRITE; return LibmGBA.mWatchpointType.WATCHPOINT_WRITE;
case MemoryCallbackType.Execute: 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; 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); Callback.Callback?.Invoke(addr, newValue, 0);
} }

View File

@ -570,6 +570,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=vram/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=vram/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Vrom/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Vrom/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Vsync/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Vsync/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Watchpoint/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Waterbox/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Waterbox/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Widescreen/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Widescreen/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Winform/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Winform/@EntryIndexedValue">True</s:Boolean>