BizHawk/BizHawk.Client.Common/tools/RamSearchEngine.cs

1039 lines
26 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
2013-10-27 07:54:00 +00:00
using BizHawk.Common;
using BizHawk.Emulation.Common;
2013-10-27 07:54:00 +00:00
namespace BizHawk.Client.Common
{
public class RamSearchEngine
{
2013-09-21 14:09:37 +00:00
public enum ComparisonOperator { Equal, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, NotEqual, DifferentBy };
public enum Compare { Previous, SpecificValue, SpecificAddress, Changes, Difference }
private int? _differentBy;
private Compare _compareTo = Compare.Previous;
private long? _compareValue;
private ComparisonOperator _operator = ComparisonOperator.Equal;
2013-09-21 14:09:37 +00:00
private List<IMiniWatch> _watchList = new List<IMiniWatch>();
private readonly Settings _settings = new Settings();
private readonly UndoHistory<IMiniWatch> _history = new UndoHistory<IMiniWatch>(true);
private bool _keepHistory = true;
2013-09-16 01:24:06 +00:00
public RamSearchEngine(Settings settings)
{
_settings.Mode = settings.Mode;
_settings.Domain = settings.Domain;
_settings.Size = settings.Size;
_settings.CheckMisAligned = settings.CheckMisAligned;
_settings.Type = settings.Type;
_settings.BigEndian = settings.BigEndian;
_settings.PreviousType = settings.PreviousType;
}
public RamSearchEngine(Settings settings, Compare compareTo, long? compareValue, int? differentBy)
: this(settings)
{
_compareTo = compareTo;
_differentBy = differentBy;
_compareValue = compareValue;
}
#region API
2013-09-14 23:30:23 +00:00
public void Start()
{
_history.Clear();
var domain = _settings.Domain;
_watchList = new List<IMiniWatch>(domain.Size);
2013-09-19 23:45:29 +00:00
switch (_settings.Size)
2013-09-14 23:30:23 +00:00
{
2013-09-19 23:45:29 +00:00
default:
case Watch.WatchSize.Byte:
if (_settings.Mode == Settings.SearchMode.Detailed)
2013-09-19 23:45:29 +00:00
{
for (int i = 0; i < _settings.Domain.Size; i++)
{
_watchList.Add(new MiniByteWatchDetailed(domain, i));
}
}
else
{
for (int i = 0; i < _settings.Domain.Size; i++)
{
_watchList.Add(new MiniByteWatch(domain, i));
}
2013-09-19 23:45:29 +00:00
}
break;
case Watch.WatchSize.Word:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
for (int i = 0; i < _settings.Domain.Size; i += (_settings.CheckMisAligned ? 1 : 2))
{
_watchList.Add(new MiniWordWatchDetailed(domain, i, _settings.BigEndian));
}
}
else
2013-09-19 23:45:29 +00:00
{
for (int i = 0; i < _settings.Domain.Size; i += (_settings.CheckMisAligned ? 1 : 2))
{
_watchList.Add(new MiniWordWatch(domain, i, _settings.BigEndian));
}
2013-09-19 23:45:29 +00:00
}
break;
case Watch.WatchSize.DWord:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
for (int i = 0; i < _settings.Domain.Size; i += (_settings.CheckMisAligned ? 1 : 4))
{
_watchList.Add(new MiniDWordWatchDetailed(domain, i, _settings.BigEndian));
}
}
else
2013-09-19 23:45:29 +00:00
{
for (int i = 0; i < _settings.Domain.Size; i += (_settings.CheckMisAligned ? 1 : 4))
{
_watchList.Add(new MiniDWordWatch(domain, i, _settings.BigEndian));
}
2013-09-19 23:45:29 +00:00
}
break;
2013-09-14 23:30:23 +00:00
}
if (_keepHistory)
{
_history.AddState(_watchList);
}
2013-09-14 23:30:23 +00:00
}
/// <summary>
/// Exposes the current watch state based on index
/// </summary>
public Watch this[int index]
{
get
{
if (_settings.Mode == Settings.SearchMode.Detailed)
{
return Watch.GenerateWatch(
_settings.Domain,
_watchList[index].Address,
_settings.Size,
_settings.Type,
_settings.BigEndian,
_watchList[index].Previous,
(_watchList[index] as IMiniWatchDetails).ChangeCount
);
}
else
{
return Watch.GenerateWatch(
_settings.Domain,
_watchList[index].Address,
_settings.Size,
_settings.Type,
_settings.BigEndian,
_watchList[index].Previous,
0
);
}
}
}
public int DoSearch()
{
int before = _watchList.Count;
switch (_compareTo)
{
default:
case Compare.Previous:
_watchList = ComparePrevious(_watchList).ToList();
break;
case Compare.SpecificValue:
_watchList = CompareSpecificValue(_watchList).ToList();
break;
case Compare.SpecificAddress:
_watchList = CompareSpecificAddress(_watchList).ToList();
break;
case Compare.Changes:
_watchList = CompareChanges(_watchList).ToList();
break;
case Compare.Difference:
_watchList = CompareDifference(_watchList).ToList();
2013-09-22 17:00:05 +00:00
break;
}
if (_settings.PreviousType == Watch.PreviousType.LastSearch)
{
SetPrevousToCurrent();
}
if (_keepHistory)
{
_history.AddState(_watchList);
}
return before - _watchList.Count;
}
public bool Preview(int address)
{
var listOfOne = new List<IMiniWatch>
{
_watchList.BinarySearch(x => x.Address, address)
};
switch (_compareTo)
{
default:
case Compare.Previous:
return !ComparePrevious(listOfOne).Any();
case Compare.SpecificValue:
return !CompareSpecificValue(listOfOne).Any();
case Compare.SpecificAddress:
return !CompareSpecificAddress(listOfOne).Any();
case Compare.Changes:
return !CompareChanges(listOfOne).Any();
case Compare.Difference:
return !CompareDifference(listOfOne).Any();
}
}
public int Count
{
2013-09-21 14:09:37 +00:00
get { return _watchList.Count; }
}
public Settings.SearchMode Mode { get { return _settings.Mode; } }
public MemoryDomain Domain
{
get { return _settings.Domain; }
}
public Compare CompareTo
{
get { return _compareTo; }
2013-09-29 18:52:11 +00:00
set
{
if (CanDoCompareType(value))
{
_compareTo = value;
}
else
{
throw new InvalidOperationException();
}
}
}
public long? CompareValue
{
get { return _compareValue; }
set { _compareValue = value; }
}
public ComparisonOperator Operator
{
get { return _operator; }
set { _operator = value; }
}
public int? DifferentBy
{
get { return _differentBy; }
set { _differentBy = value; }
}
2013-09-14 23:30:23 +00:00
public void Update()
{
if (_settings.Mode == Settings.SearchMode.Detailed)
{
2013-09-21 14:09:37 +00:00
foreach (IMiniWatchDetails watch in _watchList)
{
watch.Update(_settings.PreviousType, _settings.Domain, _settings.BigEndian);
}
}
else
{
2013-09-22 17:00:05 +00:00
return;
}
2013-09-14 23:30:23 +00:00
}
2013-09-19 23:45:29 +00:00
public void SetType(Watch.DisplayType type)
{
if (Watch.AvailableTypes(_settings.Size).Contains(type))
{
_settings.Type = type;
}
else
{
throw new InvalidOperationException();
}
}
public void SetEndian(bool bigendian)
{
_settings.BigEndian = bigendian;
}
public void SetPreviousType(Watch.PreviousType type)
{
if (type == Watch.PreviousType.LastChange)
{
throw new InvalidOperationException();
}
if (_settings.Mode == Settings.SearchMode.Fast)
{
if (type == Watch.PreviousType.LastFrame)
{
throw new InvalidOperationException();
}
}
2013-09-21 14:09:37 +00:00
_settings.PreviousType = type;
}
public void SetPrevousToCurrent()
{
_watchList.ForEach(x => x.SetPreviousToCurrent(_settings.Domain, _settings.BigEndian));
}
public void ClearChangeCounts()
{
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach (IMiniWatchDetails watch in _watchList.Cast<IMiniWatchDetails>())
{
watch.ClearChangeCount();
}
}
}
public void RemoveRange(List<int> addresses)
{
_watchList = _watchList.Where(x => !addresses.Contains(x.Address)).ToList();
}
public void AddRange(List<int> addresses, bool append)
{
if (!append)
{
_watchList.Clear();
}
switch(_settings.Size)
{
default:
case Watch.WatchSize.Byte:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach(var addr in addresses) { _watchList.Add(new MiniByteWatchDetailed(_settings.Domain, addr)); }
}
else
{
foreach(var addr in addresses) { _watchList.Add(new MiniByteWatch(_settings.Domain, addr)); }
}
break;
case Watch.WatchSize.Word:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach (var addr in addresses) { _watchList.Add(new MiniWordWatchDetailed(_settings.Domain, addr, _settings.BigEndian)); }
}
else
{
foreach (var addr in addresses) { _watchList.Add(new MiniWordWatch(_settings.Domain, addr, _settings.BigEndian)); }
}
break;
case Watch.WatchSize.DWord:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
foreach (var addr in addresses) { _watchList.Add(new MiniDWordWatchDetailed(_settings.Domain, addr, _settings.BigEndian)); }
}
else
{
foreach (var addr in addresses) { _watchList.Add(new MiniDWordWatch(_settings.Domain, addr, _settings.BigEndian)); }
}
break;
}
}
public void Sort(string column, bool reverse)
{
switch(column)
{
2013-10-27 07:54:00 +00:00
case WatchList.ADDRESS:
if (reverse)
{
_watchList = _watchList.OrderByDescending(x => x.Address).ToList();
}
else
{
_watchList = _watchList.OrderBy(x => x.Address).ToList();
}
break;
2013-10-27 07:54:00 +00:00
case WatchList.VALUE:
if (reverse)
{
_watchList = _watchList.OrderByDescending(x => GetValue(x.Address)).ToList();
}
else
{
_watchList = _watchList.OrderBy(x => GetValue(x.Address)).ToList();
}
break;
2013-10-27 07:54:00 +00:00
case WatchList.PREV:
if (reverse)
{
_watchList = _watchList.OrderByDescending(x => x.Previous).ToList();
}
else
{
_watchList = _watchList.OrderBy(x => x.Previous).ToList();
}
break;
2013-10-27 07:54:00 +00:00
case WatchList.CHANGES:
if (_settings.Mode == Settings.SearchMode.Detailed)
{
if (reverse)
{
_watchList = _watchList
.Cast<IMiniWatchDetails>()
.OrderByDescending(x => x.ChangeCount)
.Cast<IMiniWatch>().ToList();
}
else
{
_watchList = _watchList
.Cast<IMiniWatchDetails>()
.OrderBy(x => x.ChangeCount)
.Cast<IMiniWatch>().ToList();
}
}
break;
2013-10-27 07:54:00 +00:00
case WatchList.DIFF:
if (reverse)
{
_watchList = _watchList.OrderByDescending(x => (GetValue(x.Address) - x.Previous)).ToList();
}
else
{
_watchList = _watchList.OrderBy(x => (GetValue(x.Address) - x.Previous)).ToList();
}
break;
}
}
#endregion
#region Undo API
public bool UndoEnabled
{
get { return _keepHistory; }
set { _keepHistory = value; }
}
public bool CanUndo
{
get { return _keepHistory && _history.CanUndo; }
}
public bool CanRedo
{
get { return _keepHistory && _history.CanRedo; }
}
public void ClearHistory()
{
_history.Clear();
}
public void Undo()
{
if (_keepHistory)
{
2013-10-27 07:54:00 +00:00
_watchList = _history.Undo().ToList();
}
}
public void Redo()
{
if (_keepHistory)
{
2013-10-27 07:54:00 +00:00
_watchList = _history.Redo().ToList();
}
}
2013-09-14 23:30:23 +00:00
#endregion
#region Comparisons
private IEnumerable<IMiniWatch> ComparePrevious(IEnumerable<IMiniWatch> watchList)
2013-09-14 23:30:23 +00:00
{
switch (_operator)
2013-09-21 14:09:37 +00:00
{
default:
2013-09-21 14:09:37 +00:00
case ComparisonOperator.Equal:
return watchList.Where(x => GetValue(x.Address) == x.Previous);
case ComparisonOperator.NotEqual:
return watchList.Where(x => GetValue(x.Address) != x.Previous);
case ComparisonOperator.GreaterThan:
return watchList.Where(x => GetValue(x.Address) > x.Previous);
case ComparisonOperator.GreaterThanEqual:
return watchList.Where(x => GetValue(x.Address) >= x.Previous);
case ComparisonOperator.LessThan:
return watchList.Where(x => GetValue(x.Address) < x.Previous);
case ComparisonOperator.LessThanEqual:
return watchList.Where(x => GetValue(x.Address) <= x.Previous);
case ComparisonOperator.DifferentBy:
if (_differentBy.HasValue)
{
return watchList.Where(x => (GetValue(x.Address) + _differentBy.Value == x.Previous) || (GetValue(x.Address) - _differentBy.Value == x.Previous));
}
else
{
throw new InvalidOperationException();
}
2013-09-21 14:09:37 +00:00
}
2013-09-14 23:30:23 +00:00
}
private IEnumerable<IMiniWatch> CompareSpecificValue(IEnumerable<IMiniWatch> watchList)
2013-09-14 23:30:23 +00:00
{
if (_compareValue.HasValue)
{
switch (_operator)
{
default:
case ComparisonOperator.Equal:
return watchList.Where(x => GetValue(x.Address) == _compareValue.Value);
case ComparisonOperator.NotEqual:
return watchList.Where(x => GetValue(x.Address) != _compareValue.Value);
case ComparisonOperator.GreaterThan:
return watchList.Where(x => GetValue(x.Address) > _compareValue.Value);
case ComparisonOperator.GreaterThanEqual:
return watchList.Where(x => GetValue(x.Address) >= _compareValue.Value);
case ComparisonOperator.LessThan:
return watchList.Where(x => GetValue(x.Address) < _compareValue.Value);
case ComparisonOperator.LessThanEqual:
return watchList.Where(x => GetValue(x.Address) <= _compareValue.Value);
case ComparisonOperator.DifferentBy:
if (_differentBy.HasValue)
{
return watchList.Where(x => (GetValue(x.Address) + _differentBy.Value == _compareValue.Value) || (GetValue(x.Address) - _differentBy.Value == _compareValue.Value));
}
else
{
throw new InvalidOperationException();
}
}
}
else
{
throw new InvalidOperationException();
}
2013-09-14 23:30:23 +00:00
}
private IEnumerable<IMiniWatch> CompareSpecificAddress(IEnumerable<IMiniWatch> watchList)
2013-09-14 23:30:23 +00:00
{
if (_compareValue.HasValue)
{
switch (_operator)
{
default:
case ComparisonOperator.Equal:
return watchList.Where(x => x.Address == _compareValue.Value);
case ComparisonOperator.NotEqual:
return watchList.Where(x => x.Address != _compareValue.Value);
case ComparisonOperator.GreaterThan:
return watchList.Where(x => x.Address > _compareValue.Value);
case ComparisonOperator.GreaterThanEqual:
return watchList.Where(x => x.Address >= _compareValue.Value);
case ComparisonOperator.LessThan:
return watchList.Where(x => x.Address < _compareValue.Value);
case ComparisonOperator.LessThanEqual:
return watchList.Where(x => x.Address <= _compareValue.Value);
case ComparisonOperator.DifferentBy:
if (_differentBy.HasValue)
{
return watchList.Where(x => (x.Address + _differentBy.Value == _compareValue.Value) || (x.Address - _differentBy.Value == _compareValue.Value));
}
else
{
throw new InvalidOperationException();
}
}
}
else
{
throw new InvalidOperationException();
}
2013-09-14 23:30:23 +00:00
}
private IEnumerable<IMiniWatch> CompareChanges(IEnumerable<IMiniWatch> watchList)
2013-09-14 23:30:23 +00:00
{
if (_settings.Mode == Settings.SearchMode.Detailed && _compareValue.HasValue)
{
switch (_operator)
{
default:
case ComparisonOperator.Equal:
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => x.ChangeCount == _compareValue.Value)
.Cast<IMiniWatch>();
case ComparisonOperator.NotEqual:
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => x.ChangeCount != _compareValue.Value)
.Cast<IMiniWatch>();
case ComparisonOperator.GreaterThan:
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => x.ChangeCount > _compareValue.Value)
.Cast<IMiniWatch>();
case ComparisonOperator.GreaterThanEqual:
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => x.ChangeCount >= _compareValue.Value)
.Cast<IMiniWatch>();
case ComparisonOperator.LessThan:
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => x.ChangeCount < _compareValue.Value)
.Cast<IMiniWatch>();
case ComparisonOperator.LessThanEqual:
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => x.ChangeCount <= _compareValue.Value)
.Cast<IMiniWatch>();
case ComparisonOperator.DifferentBy:
if (_differentBy.HasValue)
{
return watchList
.Cast<IMiniWatchDetails>()
.Where(x => (x.ChangeCount + _differentBy.Value == _compareValue.Value) || (x.ChangeCount - _differentBy.Value == _compareValue.Value))
.Cast<IMiniWatch>();
}
else
{
throw new InvalidOperationException();
}
}
}
else
{
throw new InvalidCastException();
}
2013-09-14 23:30:23 +00:00
}
private IEnumerable<IMiniWatch> CompareDifference(IEnumerable<IMiniWatch> watchList)
2013-09-14 23:30:23 +00:00
{
if (_compareValue.HasValue)
{
switch (_operator)
{
default:
case ComparisonOperator.Equal:
return watchList.Where(x => (GetValue(x.Address) - x.Previous) == _compareValue.Value);
case ComparisonOperator.NotEqual:
return watchList.Where(x => (GetValue(x.Address) - x.Previous) != _compareValue.Value);
case ComparisonOperator.GreaterThan:
return watchList.Where(x => (GetValue(x.Address) - x.Previous) > _compareValue.Value);
case ComparisonOperator.GreaterThanEqual:
return watchList.Where(x => (GetValue(x.Address) - x.Previous) >= _compareValue.Value);
case ComparisonOperator.LessThan:
return watchList.Where(x => (GetValue(x.Address) - x.Previous) < _compareValue.Value);
case ComparisonOperator.LessThanEqual:
return watchList.Where(x => (GetValue(x.Address) - x.Previous) <= _compareValue.Value);
case ComparisonOperator.DifferentBy:
if (_differentBy.HasValue)
{
return watchList.Where(x => (GetValue(x.Address) - x.Previous + _differentBy.Value == _compareValue) || (GetValue(x.Address) - x.Previous - _differentBy.Value == x.Previous));
}
else
{
throw new InvalidOperationException();
}
}
}
else
{
throw new InvalidCastException();
}
2013-09-14 23:30:23 +00:00
}
#endregion
#region Private parts
2013-09-21 14:09:37 +00:00
private long GetValue(int addr)
2013-09-21 14:09:37 +00:00
{
switch (_settings.Size)
{
default:
case Watch.WatchSize.Byte:
2013-09-28 00:10:06 +00:00
var theByte = _settings.Domain.PeekByte(addr);
if (_settings.Type == Watch.DisplayType.Signed)
{
return (sbyte)theByte;
}
else
{
return theByte;
}
2013-09-21 14:09:37 +00:00
case Watch.WatchSize.Word:
var theWord = _settings.Domain.PeekWord(addr, _settings.BigEndian);
if (_settings.Type == Watch.DisplayType.Signed)
{
return (short)theWord;
}
else
{
return theWord;
}
2013-09-21 14:09:37 +00:00
case Watch.WatchSize.DWord:
var theDWord = _settings.Domain.PeekDWord(addr, _settings.BigEndian);
if (_settings.Type == Watch.DisplayType.Signed)
{
return (int)theDWord;
}
else
{
return theDWord;
}
2013-09-21 14:09:37 +00:00
}
}
2013-09-29 18:52:11 +00:00
private bool CanDoCompareType(Compare compareType)
{
switch (_settings.Mode)
{
default:
case Settings.SearchMode.Detailed:
return true;
case Settings.SearchMode.Fast:
return compareType != Compare.Changes;
2013-09-29 18:52:11 +00:00
}
}
#endregion
2013-09-16 01:24:06 +00:00
#region Classes
public interface IMiniWatch
2013-09-19 23:45:29 +00:00
{
int Address { get; }
int Previous { get; }
void SetPreviousToCurrent(MemoryDomain domain, bool bigendian);
}
private interface IMiniWatchDetails
{
int ChangeCount { get; }
void ClearChangeCount();
void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian);
2013-09-19 23:45:29 +00:00
}
private class MiniByteWatch : IMiniWatch
2013-09-19 23:45:29 +00:00
{
public int Address { get; private set; }
private byte _previous;
2013-09-19 23:45:29 +00:00
public MiniByteWatch(MemoryDomain domain, int addr)
{
Address = addr;
_previous = domain.PeekByte(Address);
2013-09-19 23:45:29 +00:00
}
public int Previous
2013-09-19 23:45:29 +00:00
{
get { return _previous; }
2013-09-19 23:45:29 +00:00
}
public void SetPreviousToCurrent(MemoryDomain domain, bool bigendian)
{
_previous = domain.PeekByte(Address);
}
2013-09-19 23:45:29 +00:00
}
private class MiniWordWatch : IMiniWatch
2013-09-19 23:45:29 +00:00
{
public int Address { get; private set; }
private ushort _previous;
2013-09-19 23:45:29 +00:00
public MiniWordWatch(MemoryDomain domain, int addr, bool bigEndian)
{
Address = addr;
_previous = domain.PeekWord(Address, bigEndian);
2013-09-19 23:45:29 +00:00
}
public int Previous
2013-09-19 23:45:29 +00:00
{
get { return _previous; }
2013-09-19 23:45:29 +00:00
}
public void SetPreviousToCurrent(MemoryDomain domain, bool bigendian)
{
_previous = domain.PeekWord(Address, bigendian);
}
2013-09-19 23:45:29 +00:00
}
public class MiniDWordWatch : IMiniWatch
2013-09-19 23:45:29 +00:00
{
public int Address { get; private set; }
private uint _previous;
2013-09-19 23:45:29 +00:00
public MiniDWordWatch(MemoryDomain domain, int addr, bool bigEndian)
{
Address = addr;
_previous = domain.PeekDWord(Address, bigEndian);
}
public int Previous
{
2013-09-21 14:09:37 +00:00
get { return (int)_previous; }
}
public void SetPreviousToCurrent(MemoryDomain domain, bool bigendian)
{
_previous = domain.PeekDWord(Address, bigendian);
}
}
private sealed class MiniByteWatchDetailed : IMiniWatch, IMiniWatchDetails
{
public int Address { get; private set; }
private byte _previous;
int _changecount;
public MiniByteWatchDetailed(MemoryDomain domain, int addr)
{
Address = addr;
SetPreviousToCurrent(domain, false);
}
public void SetPreviousToCurrent(MemoryDomain domain, bool bigendian)
{
_previous = domain.PeekByte(Address);
}
public int Previous
{
get { return _previous; }
}
public int ChangeCount
{
get { return _changecount; }
}
public void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian)
{
2013-09-21 14:09:37 +00:00
byte value = domain.PeekByte(Address);
if (value != Previous)
{
_changecount++;
}
2013-09-21 14:09:37 +00:00
switch (type)
{
case Watch.PreviousType.Original:
case Watch.PreviousType.LastSearch:
break;
case Watch.PreviousType.LastFrame:
_previous = value;
break;
}
}
public void ClearChangeCount()
{
_changecount = 0;
}
}
private sealed class MiniWordWatchDetailed : IMiniWatch, IMiniWatchDetails
{
public int Address { get; private set; }
private ushort _previous;
int _changecount;
public MiniWordWatchDetailed(MemoryDomain domain, int addr, bool bigEndian)
{
Address = addr;
SetPreviousToCurrent(domain, bigEndian);
}
public void SetPreviousToCurrent(MemoryDomain domain, bool bigendian)
{
_previous = domain.PeekWord(Address, bigendian);
}
public int Previous
{
get { return _previous; }
}
public int ChangeCount
{
get { return _changecount; }
}
public void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian)
{
ushort value = domain.PeekWord(Address, bigendian);
if (value != Previous)
{
_changecount++;
}
2013-09-21 14:09:37 +00:00
switch (type)
{
case Watch.PreviousType.Original:
case Watch.PreviousType.LastSearch:
2013-09-21 14:09:37 +00:00
break;
case Watch.PreviousType.LastFrame:
_previous = value;
break;
2013-09-21 14:09:37 +00:00
}
}
public void ClearChangeCount()
{
_changecount = 0;
}
}
public sealed class MiniDWordWatchDetailed : IMiniWatch, IMiniWatchDetails
{
public int Address { get; private set; }
private uint _previous;
int _changecount;
public MiniDWordWatchDetailed(MemoryDomain domain, int addr, bool bigEndian)
{
Address = addr;
SetPreviousToCurrent(domain, bigEndian);
}
public void SetPreviousToCurrent(MemoryDomain domain, bool bigendian)
{
_previous = domain.PeekDWord(Address, bigendian);
2013-09-19 23:45:29 +00:00
}
public int Previous
{
get { return (int)_previous; }
}
public int ChangeCount
{
get { return _changecount; }
}
public void Update(Watch.PreviousType type, MemoryDomain domain, bool bigendian)
2013-09-19 23:45:29 +00:00
{
uint value = domain.PeekDWord(Address, bigendian);
if (value != Previous)
{
_changecount++;
}
2013-09-21 14:09:37 +00:00
switch (type)
{
case Watch.PreviousType.Original:
case Watch.PreviousType.LastSearch:
2013-09-21 14:09:37 +00:00
break;
case Watch.PreviousType.LastFrame:
_previous = value;
break;
2013-09-21 14:09:37 +00:00
}
2013-09-19 23:45:29 +00:00
}
public void ClearChangeCount()
{
_changecount = 0;
}
2013-09-19 23:45:29 +00:00
}
2013-09-16 01:24:06 +00:00
public class Settings
{
/*Require restart*/
public enum SearchMode { Fast, Detailed }
2013-09-21 14:09:37 +00:00
public SearchMode Mode;
public MemoryDomain Domain;
public Watch.WatchSize Size;
public bool CheckMisAligned;
2013-09-16 01:24:06 +00:00
/*Can be changed mid-search*/
public Watch.DisplayType Type;
public bool BigEndian;
public Watch.PreviousType PreviousType;
public Settings()
{
switch (Global.Emulator.SystemId)
{
case "N64":
Mode = SearchMode.Fast;
Size = Watch.WatchSize.DWord;
Type = Watch.DisplayType.Unsigned;
BigEndian = true;
break;
case "GBA":
Mode = SearchMode.Detailed;
Size = Watch.WatchSize.DWord;
Type = Watch.DisplayType.Unsigned;
BigEndian = false;
break;
case "GEN":
Mode = SearchMode.Detailed;
Size = Watch.WatchSize.Word;
Type = Watch.DisplayType.Unsigned;
BigEndian = true;
break;
case "SNES":
Mode = SearchMode.Detailed;
Size = Watch.WatchSize.Byte;
Type = Watch.DisplayType.Unsigned;
BigEndian = false;
break;
case "SAT":
Mode = SearchMode.Fast;
Size = Watch.WatchSize.DWord;
Type = Watch.DisplayType.Unsigned;
BigEndian = true;
break;
default:
case "NES":
case "A26":
case "A78":
case "TI83":
case "SMS":
case "GG":
case "SG":
case "Coleco":
case "C64":
Mode = SearchMode.Detailed;
Size = Watch.WatchSize.Byte;
Type = Watch.DisplayType.Unsigned;
BigEndian = false;
break;
}
Domain = Global.Emulator.MemoryDomains.MainMemory;
CheckMisAligned = false;
PreviousType = Watch.PreviousType.LastSearch;
}
2013-09-16 01:24:06 +00:00
}
2013-09-16 01:24:06 +00:00
#endregion
}
}