Refactor MemoryCallbackSystem. Now that the API is much simpler, the underlying code can be as well.

This commit is contained in:
adelikat 2014-12-07 19:27:21 +00:00
parent 1c179da80c
commit be8563469c
1 changed files with 40 additions and 110 deletions

View File

@ -7,169 +7,94 @@ namespace BizHawk.Emulation.Common
{
public class MemoryCallbackSystem : IMemoryCallbackSystem
{
private readonly List<Action> _reads = new List<Action>();
private readonly List<uint?> _readAddrs = new List<uint?>();
private readonly List<Action> _writes = new List<Action>();
private readonly List<uint?> _writeAddrs = new List<uint?>();
private readonly List<Action> _executes = new List<Action>();
private readonly List<uint> _execAddrs = new List<uint>();
private readonly List<IMemoryCallback> Callbacks = new List<IMemoryCallback>();
public void Add(IMemoryCallback callback)
{
switch (callback.Type)
{
case MemoryCallbackType.Read:
AddRead(callback.Callback, callback.Address);
break;
case MemoryCallbackType.Write:
AddWrite(callback.Callback, callback.Address);
break;
case MemoryCallbackType.Execute:
if (!callback.Address.HasValue)
{
throw new InvalidOperationException("When assigning an execute callback, an address must be specified");
}
else
{
AddExecute(callback.Callback, callback.Address.Value);
}
var hadAny = Callbacks.Any();
break;
}
}
Callbacks.Add(callback);
private void AddRead(Action function, uint? addr)
{
var hadAny = _reads.Any() || _writes.Any() || _executes.Any();
_reads.Add(function);
_readAddrs.Add(addr);
var hasAny = _reads.Any() || _writes.Any() || _executes.Any();
Changes(hadAny, hasAny);
}
private void AddWrite(Action function, uint? addr)
{
var hadAny = _reads.Any() || _writes.Any() || _executes.Any();
_writes.Add(function);
_writeAddrs.Add(addr);
var hasAny = _reads.Any() || _writes.Any() || _executes.Any();
Changes(hadAny, hasAny);
}
private void AddExecute(Action function, uint addr)
{
var hadAny = _reads.Any() || _writes.Any() || _executes.Any();
_executes.Add(function);
_execAddrs.Add(addr);
var hasAny = _reads.Any() || _writes.Any() || _executes.Any();
var hasAny = Callbacks.Any();
Changes(hadAny, hasAny);
}
public void CallReads(uint addr)
{
for (int i = 0; i < _reads.Count; i++)
foreach (var read in Callbacks.Where(callback => callback.Type == MemoryCallbackType.Read))
{
if (!_readAddrs[i].HasValue || _readAddrs[i].Value == addr)
if (!read.Address.HasValue || read.Address == addr)
{
_reads[i]();
read.Callback();
}
}
}
public void CallWrites(uint addr)
{
for (int i = 0; i < _writes.Count; i++)
foreach (var read in Callbacks.Where(callback => callback.Type == MemoryCallbackType.Write))
{
if (!_writeAddrs[i].HasValue || _writeAddrs[i] == addr)
if (!read.Address.HasValue || read.Address == addr)
{
_writes[i]();
read.Callback();
}
}
}
public void CallExecutes(uint addr)
{
for (int i = 0; i < _executes.Count; i++)
foreach (var read in Callbacks.Where(callback => callback.Type == MemoryCallbackType.Execute))
{
if (_execAddrs[i] == addr)
if (!read.Address.HasValue || read.Address == addr)
{
_executes[i]();
read.Callback();
}
}
}
public bool HasReads { get { return _reads.Any(); } }
public bool HasWrites { get { return _writes.Any(); } }
public bool HasExecutes { get { return _executes.Any(); } }
public bool HasReads
{
get { return Callbacks.Any(callback => callback.Type == MemoryCallbackType.Read); }
}
public bool HasWrites
{
get { return Callbacks.Any(callback => callback.Type == MemoryCallbackType.Write); }
}
public bool HasExecutes
{
get { return Callbacks.Any(callback => callback.Type == MemoryCallbackType.Execute); }
}
public void Remove(Action action)
{
var hadAny = _reads.Any() || _writes.Any() || _executes.Any();
var hadAny = Callbacks.Any();
for (int i = 0; i < _reads.Count; i++)
{
if (_reads[i] == action)
{
_reads.Remove(_reads[i]);
_readAddrs.Remove(_readAddrs[i]);
}
}
var actions = Callbacks.Where(c => c.Callback == action);
Callbacks.RemoveAll(c => actions.Contains(c));
for (int i = 0; i < _writes.Count; i++)
{
if (_writes[i] == action)
{
_writes.Remove(_writes[i]);
_writeAddrs.Remove(_writeAddrs[i]);
}
}
for (int i = 0; i < _executes.Count; i++)
{
if (_executes[i] == action)
{
_executes.Remove(_executes[i]);
_execAddrs.Remove(_execAddrs[i]);
}
}
var hasAny = _reads.Any() || _writes.Any() || _executes.Any();
var hasAny = Callbacks.Any();
Changes(hadAny, hasAny);
}
public void RemoveAll(IEnumerable<Action> actions)
{
var hadAny = _reads.Any() || _writes.Any() || _executes.Any();
var hadAny = Callbacks.Any();
foreach (var action in actions)
{
Remove(action);
}
var hasAny = _reads.Any() || _writes.Any() || _executes.Any();
var hasAny = Callbacks.Any();
Changes(hadAny, hasAny);
}
public void Clear()
{
var hadAny = _reads.Any() || _writes.Any() || _executes.Any();
_reads.Clear();
_readAddrs.Clear();
_writes.Clear();
_writes.Clear();
_executes.Clear();
_execAddrs.Clear();
var hadAny = Callbacks.Any();
Callbacks.Clear();
Changes(hadAny, false);
}
@ -192,6 +117,11 @@ namespace BizHawk.Emulation.Common
{
public MemoryCallback(MemoryCallbackType type, string name, Action callback, uint? address)
{
if (type == MemoryCallbackType.Execute && !address.HasValue)
{
throw new InvalidOperationException("When assigning an execute callback, an address must be specified");
}
Type = type;
Name = name;
Callback = callback;