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 public class MemoryCallbackSystem : IMemoryCallbackSystem
{ {
private readonly List<Action> _reads = new List<Action>(); private readonly List<IMemoryCallback> Callbacks = new List<IMemoryCallback>();
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>();
public void Add(IMemoryCallback callback) public void Add(IMemoryCallback callback)
{ {
switch (callback.Type) var hadAny = Callbacks.Any();
{
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);
}
break; Callbacks.Add(callback);
}
}
private void AddRead(Action function, uint? addr) var hasAny = Callbacks.Any();
{
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();
Changes(hadAny, hasAny); Changes(hadAny, hasAny);
} }
public void CallReads(uint addr) 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) 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) 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 HasReads
public bool HasWrites { get { return _writes.Any(); } } {
public bool HasExecutes { get { return _executes.Any(); } } 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) 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++) var actions = Callbacks.Where(c => c.Callback == action);
{ Callbacks.RemoveAll(c => actions.Contains(c));
if (_reads[i] == action)
{
_reads.Remove(_reads[i]);
_readAddrs.Remove(_readAddrs[i]);
}
}
for (int i = 0; i < _writes.Count; i++) var hasAny = Callbacks.Any();
{
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();
Changes(hadAny, hasAny); Changes(hadAny, hasAny);
} }
public void RemoveAll(IEnumerable<Action> actions) public void RemoveAll(IEnumerable<Action> actions)
{ {
var hadAny = _reads.Any() || _writes.Any() || _executes.Any(); var hadAny = Callbacks.Any();
foreach (var action in actions) foreach (var action in actions)
{ {
Remove(action); Remove(action);
} }
var hasAny = _reads.Any() || _writes.Any() || _executes.Any(); var hasAny = Callbacks.Any();
Changes(hadAny, hasAny); Changes(hadAny, hasAny);
} }
public void Clear() public void Clear()
{ {
var hadAny = _reads.Any() || _writes.Any() || _executes.Any(); var hadAny = Callbacks.Any();
Callbacks.Clear();
_reads.Clear();
_readAddrs.Clear();
_writes.Clear();
_writes.Clear();
_executes.Clear();
_execAddrs.Clear();
Changes(hadAny, false); Changes(hadAny, false);
} }
@ -192,6 +117,11 @@ namespace BizHawk.Emulation.Common
{ {
public MemoryCallback(MemoryCallbackType type, string name, Action callback, uint? address) 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; Type = type;
Name = name; Name = name;
Callback = callback; Callback = callback;