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
{
private readonly MGBAHawk _mgba;
private LibmGBA.ExecCallback _executeCallback;
private readonly Dictionary<uint, IMemoryCallback> _execPcs = new Dictionary<uint, IMemoryCallback> { [0] = null };
public MGBAMemoryCallbackSystem(MGBAHawk mgba)
{
@ -18,7 +20,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
private readonly List<CallbackContainer> _callbacks = new List<CallbackContainer>();
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);
}

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/=Vrom/@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/=Widescreen/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Winform/@EntryIndexedValue">True</s:Boolean>