Refactor RamSearch to increase speed and improve functionality (#3954)
- merges `IMiniWatchDetailed` and `IMiniWatch` into one - allow switching search modes without restarting the search - general speed improvements due to less peeks when e.g. auto-search is toggled - removes `PreviousType.LastSearch` due to its questionable use case
This commit is contained in:
parent
866fb86b60
commit
1a9e5e52f1
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
|
@ -7,43 +6,22 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
internal static class Extensions
|
||||
{
|
||||
public static float ToFloat(this long val)
|
||||
{
|
||||
var bytes = BitConverter.GetBytes((int)val);
|
||||
return BitConverter.ToSingle(bytes, 0);
|
||||
}
|
||||
|
||||
public static IEnumerable<IMiniWatch> ToBytes(this IEnumerable<long> addresses, SearchEngineSettings settings)
|
||||
=> settings.IsDetailed()
|
||||
? addresses.ToDetailedBytes(settings.Domain)
|
||||
: addresses.ToBytes(settings.Domain);
|
||||
=> addresses.ToDetailedBytes(settings.Domain);
|
||||
|
||||
public static IEnumerable<IMiniWatch> ToWords(this IEnumerable<long> addresses, SearchEngineSettings settings)
|
||||
=> settings.IsDetailed()
|
||||
? addresses.ToDetailedWords(settings.Domain, settings.BigEndian)
|
||||
: addresses.ToWords(settings.Domain, settings.BigEndian);
|
||||
=> addresses.ToDetailedWords(settings.Domain, settings.BigEndian);
|
||||
|
||||
public static IEnumerable<IMiniWatch> ToDWords(this IEnumerable<long> addresses, SearchEngineSettings settings)
|
||||
=> settings.IsDetailed()
|
||||
? addresses.ToDetailedDWords(settings.Domain, settings.BigEndian)
|
||||
: addresses.ToDWords(settings.Domain, settings.BigEndian);
|
||||
|
||||
private static IEnumerable<IMiniWatch> ToBytes(this IEnumerable<long> addresses, MemoryDomain domain)
|
||||
=> addresses.Select(a => new MiniByteWatch(domain, a));
|
||||
=> addresses.ToDetailedDWords(settings.Domain, settings.BigEndian);
|
||||
|
||||
private static IEnumerable<IMiniWatch> ToDetailedBytes(this IEnumerable<long> addresses, MemoryDomain domain)
|
||||
=> addresses.Select(a => new MiniByteWatchDetailed(domain, a));
|
||||
|
||||
private static IEnumerable<IMiniWatch> ToWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
|
||||
=> addresses.Select(a => new MiniWordWatch(domain, a, bigEndian));
|
||||
=> addresses.Select(a => new MiniByteWatch(domain, a));
|
||||
|
||||
private static IEnumerable<IMiniWatch> ToDetailedWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
|
||||
=> addresses.Select(a => new MiniWordWatchDetailed(domain, a, bigEndian));
|
||||
|
||||
private static IEnumerable<IMiniWatch> ToDWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
|
||||
=> addresses.Select(a => new MiniDWordWatch(domain, a, bigEndian));
|
||||
=> addresses.Select(a => new MiniWordWatch(domain, a, bigEndian));
|
||||
|
||||
private static IEnumerable<IMiniWatch> ToDetailedDWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
|
||||
=> addresses.Select(a => new MiniDWordWatchDetailed(domain, a, bigEndian));
|
||||
=> addresses.Select(a => new MiniDWordWatch(domain, a, bigEndian));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,130 +4,172 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
/// <summary>
|
||||
/// Represents a Ram address for watching in the <see cref="RamSearchEngine" />
|
||||
/// With the minimal details necessary for searching
|
||||
/// </summary>
|
||||
internal interface IMiniWatch
|
||||
{
|
||||
long Address { get; }
|
||||
long Previous { get; } // do not store sign extended variables in here.
|
||||
void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian);
|
||||
long Current { get; }
|
||||
int ChangeCount { get; }
|
||||
void ClearChangeCount();
|
||||
void SetPreviousToCurrent();
|
||||
bool IsValid(MemoryDomain domain);
|
||||
void Update(PreviousType type, MemoryDomain domain, bool bigEndian);
|
||||
}
|
||||
|
||||
internal sealed class MiniByteWatch : IMiniWatch
|
||||
{
|
||||
public long Address { get; }
|
||||
|
||||
private byte _previous;
|
||||
private byte _current;
|
||||
|
||||
public MiniByteWatch(MemoryDomain domain, long addr)
|
||||
{
|
||||
Address = addr;
|
||||
_previous = GetByte(Address, domain);
|
||||
_previous = _current = GetByte(domain);
|
||||
}
|
||||
|
||||
public void SetPreviousToCurrent()
|
||||
{
|
||||
_previous = _current;
|
||||
}
|
||||
|
||||
public long Previous => _previous;
|
||||
public long Current => _current;
|
||||
|
||||
public bool IsValid(MemoryDomain domain)
|
||||
{
|
||||
return IsValid(Address, domain);
|
||||
}
|
||||
public int ChangeCount { get; private set; }
|
||||
|
||||
public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
|
||||
public void Update(PreviousType type, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
_previous = GetByte(Address, domain);
|
||||
}
|
||||
var newValue = GetByte(domain);
|
||||
|
||||
public static bool IsValid(long address, MemoryDomain domain)
|
||||
{
|
||||
return address < domain.Size;
|
||||
}
|
||||
|
||||
public static byte GetByte(long address, MemoryDomain domain)
|
||||
{
|
||||
if (!IsValid(address, domain))
|
||||
if (newValue != _current)
|
||||
{
|
||||
return 0;
|
||||
ChangeCount++;
|
||||
if (type == PreviousType.LastChange)
|
||||
{
|
||||
_previous = _current;
|
||||
}
|
||||
}
|
||||
|
||||
return domain.PeekByte(address);
|
||||
if (type == PreviousType.LastFrame)
|
||||
_previous = _current;
|
||||
|
||||
_current = newValue;
|
||||
}
|
||||
|
||||
public void ClearChangeCount() => ChangeCount = 0;
|
||||
|
||||
public bool IsValid(MemoryDomain domain) => Address < domain.Size;
|
||||
|
||||
public byte GetByte(MemoryDomain domain)
|
||||
{
|
||||
return IsValid(domain) ? domain.PeekByte(Address) : (byte)0;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MiniWordWatch : IMiniWatch
|
||||
{
|
||||
public long Address { get; }
|
||||
|
||||
private ushort _previous;
|
||||
private ushort _current;
|
||||
|
||||
public MiniWordWatch(MemoryDomain domain, long addr, bool bigEndian)
|
||||
{
|
||||
Address = addr;
|
||||
_previous = GetUshort(Address, domain, bigEndian);
|
||||
_previous = _current = GetUshort(domain, bigEndian);
|
||||
}
|
||||
|
||||
public void SetPreviousToCurrent()
|
||||
{
|
||||
_previous = _current;
|
||||
}
|
||||
|
||||
public long Previous => _previous;
|
||||
public long Current => _current;
|
||||
|
||||
public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
_previous = GetUshort(Address, domain, bigEndian);
|
||||
}
|
||||
public int ChangeCount { get; private set; }
|
||||
|
||||
public bool IsValid(MemoryDomain domain)
|
||||
public void Update(PreviousType type, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
return IsValid(Address, domain);
|
||||
}
|
||||
var newValue = GetUshort(domain, bigEndian);
|
||||
|
||||
public static bool IsValid(long address, MemoryDomain domain)
|
||||
{
|
||||
return address < (domain.Size - 1);
|
||||
}
|
||||
|
||||
public static ushort GetUshort(long address, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
if (!IsValid(address, domain))
|
||||
if (newValue != _current)
|
||||
{
|
||||
return 0;
|
||||
ChangeCount++;
|
||||
if (type == PreviousType.LastChange)
|
||||
{
|
||||
_previous = _current;
|
||||
}
|
||||
}
|
||||
|
||||
return domain.PeekUshort(address, bigEndian);
|
||||
if (type == PreviousType.LastFrame)
|
||||
_previous = _current;
|
||||
|
||||
_current = newValue;
|
||||
}
|
||||
|
||||
public void ClearChangeCount() => ChangeCount = 0;
|
||||
|
||||
public bool IsValid(MemoryDomain domain) => Address < domain.Size - 1;
|
||||
|
||||
private ushort GetUshort(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
return IsValid(domain) ? domain.PeekUshort(Address, bigEndian) : (ushort)0;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MiniDWordWatch : IMiniWatch
|
||||
{
|
||||
public long Address { get; }
|
||||
|
||||
private uint _previous;
|
||||
private uint _current;
|
||||
|
||||
public MiniDWordWatch(MemoryDomain domain, long addr, bool bigEndian)
|
||||
{
|
||||
Address = addr;
|
||||
_previous = GetUint(Address, domain, bigEndian);
|
||||
_previous = _current = GetUint(domain, bigEndian);
|
||||
}
|
||||
|
||||
public void SetPreviousToCurrent()
|
||||
{
|
||||
_previous = _current;
|
||||
}
|
||||
|
||||
public long Previous => _previous;
|
||||
public long Current => _current;
|
||||
|
||||
public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
_previous = GetUint(Address, domain, bigEndian);
|
||||
}
|
||||
public int ChangeCount { get; private set; }
|
||||
|
||||
public bool IsValid(MemoryDomain domain)
|
||||
public void Update(PreviousType type, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
return IsValid(Address, domain);
|
||||
}
|
||||
var newValue = GetUint(domain, bigEndian);
|
||||
|
||||
public static bool IsValid(long address, MemoryDomain domain)
|
||||
{
|
||||
return address < (domain.Size - 3);
|
||||
}
|
||||
|
||||
public static uint GetUint(long address, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
if (!IsValid(address, domain))
|
||||
if (newValue != _current)
|
||||
{
|
||||
return 0;
|
||||
ChangeCount++;
|
||||
if (type == PreviousType.LastChange)
|
||||
{
|
||||
_previous = _current;
|
||||
}
|
||||
}
|
||||
|
||||
return domain.PeekUint(address, bigEndian);
|
||||
if (type == PreviousType.LastFrame)
|
||||
_previous = _current;
|
||||
|
||||
_current = newValue;
|
||||
}
|
||||
|
||||
public void ClearChangeCount() => ChangeCount = 0;
|
||||
|
||||
public bool IsValid(MemoryDomain domain) => Address < domain.Size - 3;
|
||||
|
||||
private uint GetUint(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
return IsValid(domain) ? domain.PeekUint(Address, bigEndian) : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common.RamSearchEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMiniWatch" /> but with added details
|
||||
/// to do change tracking. These types add more information but at a cost of
|
||||
/// having to poll the ram address on every update
|
||||
/// </summary>
|
||||
internal interface IMiniWatchDetails : IMiniWatch
|
||||
{
|
||||
int ChangeCount { get; }
|
||||
|
||||
void ClearChangeCount();
|
||||
void Update(PreviousType type, MemoryDomain domain, bool bigEndian);
|
||||
}
|
||||
|
||||
internal sealed class MiniByteWatchDetailed : IMiniWatchDetails
|
||||
{
|
||||
public long Address { get; }
|
||||
|
||||
private byte _previous;
|
||||
private byte _prevFrame;
|
||||
|
||||
public MiniByteWatchDetailed(MemoryDomain domain, long addr)
|
||||
{
|
||||
Address = addr;
|
||||
SetPreviousToCurrent(domain, false);
|
||||
}
|
||||
|
||||
public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
_previous = _prevFrame = MiniByteWatch.GetByte(Address, domain);
|
||||
}
|
||||
|
||||
public long Previous => _previous;
|
||||
|
||||
public int ChangeCount { get; private set; }
|
||||
|
||||
public void Update(PreviousType type, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
var value = MiniByteWatch.GetByte(Address, domain);
|
||||
|
||||
if (value != _prevFrame)
|
||||
{
|
||||
ChangeCount++;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PreviousType.Original:
|
||||
case PreviousType.LastSearch:
|
||||
break;
|
||||
case PreviousType.LastFrame:
|
||||
_previous = _prevFrame;
|
||||
break;
|
||||
case PreviousType.LastChange:
|
||||
if (_prevFrame != value)
|
||||
{
|
||||
_previous = _prevFrame;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_prevFrame = value;
|
||||
}
|
||||
|
||||
public void ClearChangeCount() => ChangeCount = 0;
|
||||
|
||||
public bool IsValid(MemoryDomain domain) => MiniByteWatch.IsValid(Address, domain);
|
||||
}
|
||||
|
||||
internal sealed class MiniWordWatchDetailed : IMiniWatchDetails
|
||||
{
|
||||
public long Address { get; }
|
||||
|
||||
private ushort _previous;
|
||||
private ushort _prevFrame;
|
||||
|
||||
public MiniWordWatchDetailed(MemoryDomain domain, long addr, bool bigEndian)
|
||||
{
|
||||
Address = addr;
|
||||
SetPreviousToCurrent(domain, bigEndian);
|
||||
}
|
||||
|
||||
public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
_previous = _prevFrame = MiniWordWatch.GetUshort(Address, domain, bigEndian);
|
||||
}
|
||||
|
||||
public long Previous => _previous;
|
||||
|
||||
public int ChangeCount { get; private set; }
|
||||
|
||||
public void Update(PreviousType type, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
var value = MiniWordWatch.GetUshort(Address, domain, bigEndian);
|
||||
if (value != Previous)
|
||||
{
|
||||
ChangeCount++;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PreviousType.Original:
|
||||
case PreviousType.LastSearch:
|
||||
break;
|
||||
case PreviousType.LastFrame:
|
||||
_previous = _prevFrame;
|
||||
break;
|
||||
case PreviousType.LastChange:
|
||||
if (_prevFrame != value)
|
||||
{
|
||||
_previous = _prevFrame;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_prevFrame = value;
|
||||
}
|
||||
|
||||
public void ClearChangeCount() => ChangeCount = 0;
|
||||
|
||||
public bool IsValid(MemoryDomain domain) => MiniWordWatch.IsValid(Address, domain);
|
||||
}
|
||||
|
||||
internal sealed class MiniDWordWatchDetailed : IMiniWatchDetails
|
||||
{
|
||||
public long Address { get; }
|
||||
|
||||
private uint _previous;
|
||||
private uint _prevFrame;
|
||||
|
||||
public MiniDWordWatchDetailed(MemoryDomain domain, long addr, bool bigEndian)
|
||||
{
|
||||
Address = addr;
|
||||
SetPreviousToCurrent(domain, bigEndian);
|
||||
}
|
||||
|
||||
public void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
_previous = _prevFrame = MiniDWordWatch.GetUint(Address, domain, bigEndian);
|
||||
}
|
||||
|
||||
public long Previous => (int)_previous;
|
||||
|
||||
public int ChangeCount { get; private set; }
|
||||
|
||||
public void Update(PreviousType type, MemoryDomain domain, bool bigEndian)
|
||||
{
|
||||
var value = MiniDWordWatch.GetUint(Address, domain, bigEndian);
|
||||
if (value != Previous)
|
||||
{
|
||||
ChangeCount++;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PreviousType.Original:
|
||||
case PreviousType.LastSearch:
|
||||
break;
|
||||
case PreviousType.LastFrame:
|
||||
_previous = _prevFrame;
|
||||
break;
|
||||
case PreviousType.LastChange:
|
||||
if (_prevFrame != value)
|
||||
{
|
||||
_previous = _prevFrame;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_prevFrame = value;
|
||||
}
|
||||
|
||||
public void ClearChangeCount() => ChangeCount = 0;
|
||||
|
||||
public bool IsValid(MemoryDomain domain) => MiniDWordWatch.IsValid(Address, domain);
|
||||
}
|
||||
}
|
|
@ -21,10 +21,9 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
|
||||
private Compare _compareTo = Compare.Previous;
|
||||
|
||||
private IMiniWatch[] _watchList = Array.Empty<IMiniWatch>();
|
||||
private IMiniWatch[] _watchList = [ ];
|
||||
private readonly SearchEngineSettings _settings;
|
||||
private readonly UndoHistory<IEnumerable<IMiniWatch>> _history = new UndoHistory<IEnumerable<IMiniWatch>>(true, new List<IMiniWatch>()); //TODO use IList instead of IEnumerable and stop calling `.ToArray()` (i.e. cloning) on reads and writes?
|
||||
private bool _isSorted = true; // Tracks whether or not the array is sorted by address, if it is, binary search can be used for finding watches
|
||||
private readonly UndoHistory<IEnumerable<IMiniWatch>> _history = new(true, [ ]); //TODO use IList instead of IEnumerable and stop calling `.ToArray()` (i.e. cloning) on reads and writes?
|
||||
|
||||
public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains)
|
||||
{
|
||||
|
@ -65,46 +64,13 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
default:
|
||||
case WatchSize.Byte:
|
||||
if (_settings.IsDetailed())
|
||||
{
|
||||
for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniByteWatchDetailed(domain, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniByteWatch(domain, i);
|
||||
}
|
||||
for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniByteWatch(domain, i);
|
||||
break;
|
||||
case WatchSize.Word:
|
||||
if (_settings.IsDetailed())
|
||||
{
|
||||
for (var i = 0; i < _watchList.Length; i++)
|
||||
{
|
||||
_watchList[i] = new MiniWordWatchDetailed(domain, i * stepSize, _settings.BigEndian);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < _watchList.Length; i++)
|
||||
{
|
||||
_watchList[i] = new MiniWordWatch(domain, i * stepSize, _settings.BigEndian);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniWordWatch(domain, i * stepSize, _settings.BigEndian);
|
||||
break;
|
||||
case WatchSize.DWord:
|
||||
if (_settings.IsDetailed())
|
||||
{
|
||||
for (var i = 0; i < _watchList.Length; i++)
|
||||
{
|
||||
_watchList[i] = new MiniDWordWatchDetailed(domain, i * stepSize, _settings.BigEndian);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < _watchList.Length; i++)
|
||||
{
|
||||
_watchList[i] = new MiniDWordWatch(domain, i * stepSize, _settings.BigEndian);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < _watchList.Length; i++) _watchList[i] = new MiniDWordWatch(domain, i * stepSize, _settings.BigEndian);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -122,12 +88,14 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
"",
|
||||
0,
|
||||
_watchList[index].Previous,
|
||||
_settings.IsDetailed() ? ((IMiniWatchDetails)_watchList[index]).ChangeCount : 0);
|
||||
_settings.IsDetailed() ? _watchList[index].ChangeCount : 0);
|
||||
|
||||
public int DoSearch()
|
||||
public int DoSearch(bool updatePrevious)
|
||||
{
|
||||
int before = _watchList.Length;
|
||||
|
||||
Update(updatePrevious);
|
||||
|
||||
using (Domain.EnterExit())
|
||||
{
|
||||
_watchList = _compareTo switch
|
||||
|
@ -139,11 +107,6 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
Compare.Difference => CompareDifference(_watchList).ToArray(),
|
||||
_ => ComparePrevious(_watchList).ToArray()
|
||||
};
|
||||
|
||||
if (_settings.PreviousType == PreviousType.LastSearch)
|
||||
{
|
||||
SetPreviousToCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
if (UndoEnabled)
|
||||
|
@ -154,11 +117,11 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
return before - _watchList.Length;
|
||||
}
|
||||
|
||||
public bool Preview(long address)
|
||||
public bool Preview(int index)
|
||||
{
|
||||
var listOfOne = Enumerable.Repeat(_isSorted
|
||||
? _watchList.BinarySearch(w => w.Address, address)
|
||||
: _watchList.FirstOrDefault(w => w.Address == address), 1);
|
||||
var addressWatch = _watchList[index];
|
||||
addressWatch.Update(PreviousType.Original, _settings.Domain, _settings.BigEndian);
|
||||
IMiniWatch[] listOfOne = [ addressWatch ];
|
||||
|
||||
return _compareTo switch
|
||||
{
|
||||
|
@ -204,13 +167,12 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
/// </remarks>
|
||||
public int? DifferentBy { get; set; }
|
||||
|
||||
public void Update()
|
||||
public void Update(bool updatePrevious)
|
||||
{
|
||||
if (!_settings.IsDetailed()) return;
|
||||
using var @lock = _settings.Domain.EnterExit();
|
||||
foreach (IMiniWatchDetails watch in _watchList)
|
||||
foreach (var watch in _watchList)
|
||||
{
|
||||
watch.Update(_settings.PreviousType, _settings.Domain, _settings.BigEndian);
|
||||
watch.Update(updatePrevious ? _settings.PreviousType : PreviousType.Original, _settings.Domain, _settings.BigEndian);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,26 +180,18 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
|
||||
public void SetEndian(bool bigEndian) => _settings.BigEndian = bigEndian;
|
||||
|
||||
/// <exception cref="InvalidOperationException"><see cref="Mode"/> is <see cref="SearchMode.Fast"/> and <paramref name="type"/> is <see cref="PreviousType.LastFrame"/></exception>
|
||||
public void SetPreviousType(PreviousType type)
|
||||
{
|
||||
if (_settings.IsFastMode() && type == PreviousType.LastFrame)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
public void SetPreviousType(PreviousType type) => _settings.PreviousType = type;
|
||||
|
||||
_settings.PreviousType = type;
|
||||
}
|
||||
public void SetMode(SearchMode mode) => _settings.Mode = mode;
|
||||
|
||||
public void SetPreviousToCurrent()
|
||||
{
|
||||
Array.ForEach(_watchList, w => w.SetPreviousToCurrent(_settings.Domain, _settings.BigEndian));
|
||||
Array.ForEach(_watchList, static w => w.SetPreviousToCurrent());
|
||||
}
|
||||
|
||||
public void ClearChangeCounts()
|
||||
{
|
||||
if (!_settings.IsDetailed()) return;
|
||||
foreach (var watch in _watchList.Cast<IMiniWatchDetails>())
|
||||
foreach (var watch in _watchList)
|
||||
{
|
||||
watch.ClearChangeCount();
|
||||
}
|
||||
|
@ -285,33 +239,26 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
};
|
||||
|
||||
_watchList = (append ? _watchList.Concat(list) : list).ToArray();
|
||||
_isSorted = false; //TODO can this be smarter, such as by inserting instead of appending?
|
||||
}
|
||||
|
||||
public void Sort(string column, bool reverse)
|
||||
{
|
||||
_isSorted = column == WatchList.Address && !reverse;
|
||||
switch (column)
|
||||
{
|
||||
case WatchList.Address:
|
||||
_watchList = _watchList.OrderBy(w => w.Address, reverse).ToArray();
|
||||
break;
|
||||
case WatchList.Value:
|
||||
_watchList = _watchList.OrderBy(w => GetValue(w.Address), reverse).ToArray();
|
||||
_watchList = _watchList.OrderBy(w => w.Current, reverse).ToArray();
|
||||
break;
|
||||
case WatchList.Prev:
|
||||
_watchList = _watchList.OrderBy(w => w.Previous, reverse).ToArray();
|
||||
break;
|
||||
case WatchList.ChangesCol:
|
||||
if (!_settings.IsDetailed()) break;
|
||||
_watchList = _watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.OrderBy(w => w.ChangeCount, reverse)
|
||||
.Cast<IMiniWatch>()
|
||||
.ToArray();
|
||||
_watchList = _watchList.OrderBy(w => w.ChangeCount, reverse).ToArray();
|
||||
break;
|
||||
case WatchList.Diff:
|
||||
_watchList = _watchList.OrderBy(w => GetValue(w.Address) - w.Previous, reverse).ToArray();
|
||||
_watchList = _watchList.OrderBy(w => w.Current - w.Previous, reverse).ToArray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -360,52 +307,52 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) == SignExtendAsNeeded(w.Previous));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) == SignExtendAsNeeded(w.Previous));
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) != SignExtendAsNeeded(w.Previous));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) != SignExtendAsNeeded(w.Previous));
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) > SignExtendAsNeeded(w.Previous));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) > SignExtendAsNeeded(w.Previous));
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) >= SignExtendAsNeeded(w.Previous));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) >= SignExtendAsNeeded(w.Previous));
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) < SignExtendAsNeeded(w.Previous));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) < SignExtendAsNeeded(w.Previous));
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) <= SignExtendAsNeeded(w.Previous));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) <= SignExtendAsNeeded(w.Previous));
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
return watchList.Where(w =>
|
||||
differentBy == Math.Abs(SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous)));
|
||||
differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous)));
|
||||
}
|
||||
}
|
||||
switch (Operator)
|
||||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(w.Previous)));
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current).HawkFloatEquality(ReinterpretAsF32(w.Previous)));
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList.Where(w => !ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(ReinterpretAsF32(w.Previous)));
|
||||
return watchList.Where(w => !ReinterpretAsF32(w.Current).HawkFloatEquality(ReinterpretAsF32(w.Previous)));
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) > ReinterpretAsF32(w.Previous));
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current) > ReinterpretAsF32(w.Previous));
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList.Where(w =>
|
||||
{
|
||||
var val = ReinterpretAsF32(GetValue(w.Address));
|
||||
var val = ReinterpretAsF32(w.Current);
|
||||
var prev = ReinterpretAsF32(w.Previous);
|
||||
return val > prev || val.HawkFloatEquality(prev);
|
||||
});
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) < ReinterpretAsF32(w.Previous));
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current) < ReinterpretAsF32(w.Previous));
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList.Where(w =>
|
||||
{
|
||||
var val = ReinterpretAsF32(GetValue(w.Address));
|
||||
var val = ReinterpretAsF32(w.Current);
|
||||
var prev = ReinterpretAsF32(w.Previous);
|
||||
return val < prev || val.HawkFloatEquality(prev);
|
||||
});
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
var differentByF = ReinterpretAsF32(differentBy);
|
||||
return watchList.Where(w => Math.Abs(ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous))
|
||||
return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous))
|
||||
.HawkFloatEquality(differentByF));
|
||||
}
|
||||
}
|
||||
|
@ -419,21 +366,21 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) == SignExtendAsNeeded(compareValue));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) == SignExtendAsNeeded(compareValue));
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) != SignExtendAsNeeded(compareValue));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) != SignExtendAsNeeded(compareValue));
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) > SignExtendAsNeeded(compareValue));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) > SignExtendAsNeeded(compareValue));
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) >= SignExtendAsNeeded(compareValue));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) >= SignExtendAsNeeded(compareValue));
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) < SignExtendAsNeeded(compareValue));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) < SignExtendAsNeeded(compareValue));
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) <= SignExtendAsNeeded(compareValue));
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) <= SignExtendAsNeeded(compareValue));
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
return watchList.Where(w =>
|
||||
differentBy == Math.Abs(SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(compareValue)));
|
||||
differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(compareValue)));
|
||||
}
|
||||
}
|
||||
var compareValueF = ReinterpretAsF32(compareValue);
|
||||
|
@ -441,29 +388,29 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(compareValueF));
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current).HawkFloatEquality(compareValueF));
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList.Where(w => !ReinterpretAsF32(GetValue(w.Address)).HawkFloatEquality(compareValueF));
|
||||
return watchList.Where(w => !ReinterpretAsF32(w.Current).HawkFloatEquality(compareValueF));
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) > compareValueF);
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current) > compareValueF);
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList.Where(w =>
|
||||
{
|
||||
var val = ReinterpretAsF32(GetValue(w.Address));
|
||||
var val = ReinterpretAsF32(w.Current);
|
||||
return val > compareValueF || val.HawkFloatEquality(compareValueF);
|
||||
});
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) < compareValueF);
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current) < compareValueF);
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList.Where(w =>
|
||||
{
|
||||
var val = ReinterpretAsF32(GetValue(w.Address));
|
||||
var val = ReinterpretAsF32(w.Current);
|
||||
return val < compareValueF || val.HawkFloatEquality(compareValueF);
|
||||
});
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
var differentByF = ReinterpretAsF32(differentBy);
|
||||
return watchList.Where(w => Math.Abs(ReinterpretAsF32(GetValue(w.Address)) - compareValueF)
|
||||
return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - compareValueF)
|
||||
.HawkFloatEquality(differentByF));
|
||||
}
|
||||
}
|
||||
|
@ -494,40 +441,25 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
|
||||
private IEnumerable<IMiniWatch> CompareChanges(IEnumerable<IMiniWatch> watchList)
|
||||
{
|
||||
if (!_settings.IsDetailed()) throw new InvalidCastException(); //TODO matches previous behaviour; was this intended to skip processing? --yoshi
|
||||
if (CompareValue is not long compareValue) throw new InvalidCastException(); //TODO typo for IOE?
|
||||
if (CompareValue is not long compareValue) throw new InvalidOperationException();
|
||||
switch (Operator)
|
||||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => w.ChangeCount == compareValue);
|
||||
return watchList.Where(w => w.ChangeCount == compareValue);
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => w.ChangeCount != compareValue);
|
||||
return watchList.Where(w => w.ChangeCount != compareValue);
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => w.ChangeCount > compareValue);
|
||||
return watchList.Where(w => w.ChangeCount > compareValue);
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => w.ChangeCount >= compareValue);
|
||||
return watchList.Where(w => w.ChangeCount >= compareValue);
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => w.ChangeCount < compareValue);
|
||||
return watchList.Where(w => w.ChangeCount < compareValue);
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => w.ChangeCount <= compareValue);
|
||||
return watchList.Where(w => w.ChangeCount <= compareValue);
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
return watchList
|
||||
.Cast<IMiniWatchDetails>()
|
||||
.Where(w => Math.Abs(w.ChangeCount - compareValue) == differentBy);
|
||||
return watchList.Where(w => Math.Abs(w.ChangeCount - compareValue) == differentBy);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,21 +472,21 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) == compareValue);
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) == compareValue);
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) != compareValue);
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) != compareValue);
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) > compareValue);
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) > compareValue);
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) >= compareValue);
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) >= compareValue);
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) < compareValue);
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) < compareValue);
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList.Where(w => SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) <= compareValue);
|
||||
return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) <= compareValue);
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
return watchList.Where(w =>
|
||||
differentBy == Math.Abs(SignExtendAsNeeded(GetValue(w.Address)) - SignExtendAsNeeded(w.Previous) - compareValue));
|
||||
differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) - compareValue));
|
||||
}
|
||||
}
|
||||
var compareValueF = ReinterpretAsF32(compareValue);
|
||||
|
@ -562,29 +494,29 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
default:
|
||||
case ComparisonOperator.Equal:
|
||||
return watchList.Where(w => (ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF));
|
||||
return watchList.Where(w => (ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF));
|
||||
case ComparisonOperator.NotEqual:
|
||||
return watchList.Where(w => !(ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF));
|
||||
return watchList.Where(w => !(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous)).HawkFloatEquality(compareValueF));
|
||||
case ComparisonOperator.GreaterThan:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) > compareValueF);
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) > compareValueF);
|
||||
case ComparisonOperator.GreaterThanEqual:
|
||||
return watchList.Where(w =>
|
||||
{
|
||||
var diff = ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous);
|
||||
var diff = ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous);
|
||||
return diff > compareValueF || diff.HawkFloatEquality(compareValueF);
|
||||
});
|
||||
case ComparisonOperator.LessThan:
|
||||
return watchList.Where(w => ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) < compareValueF);
|
||||
return watchList.Where(w => ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) < compareValueF);
|
||||
case ComparisonOperator.LessThanEqual:
|
||||
return watchList.Where(w =>
|
||||
{
|
||||
var diff = ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous);
|
||||
var diff = ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous);
|
||||
return diff < compareValueF || diff.HawkFloatEquality(compareValueF);
|
||||
});
|
||||
case ComparisonOperator.DifferentBy:
|
||||
if (DifferentBy is not int differentBy) throw new InvalidOperationException();
|
||||
var differentByF = ReinterpretAsF32(differentBy);
|
||||
return watchList.Where(w => Math.Abs(ReinterpretAsF32(GetValue(w.Address)) - ReinterpretAsF32(w.Previous) - compareValueF)
|
||||
return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) - compareValueF)
|
||||
.HawkFloatEquality(differentByF));
|
||||
}
|
||||
}
|
||||
|
@ -605,24 +537,12 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
};
|
||||
}
|
||||
|
||||
private long GetValue(long addr)
|
||||
{
|
||||
// do not return sign extended variables from here.
|
||||
return _settings.Size switch
|
||||
{
|
||||
WatchSize.Byte => MiniByteWatch.GetByte(addr, Domain),
|
||||
WatchSize.Word => MiniWordWatch.GetUshort(addr, Domain, _settings.BigEndian),
|
||||
WatchSize.DWord => MiniDWordWatch.GetUint(addr, Domain, _settings.BigEndian),
|
||||
_ => MiniByteWatch.GetByte(addr, Domain)
|
||||
};
|
||||
}
|
||||
|
||||
private bool CanDoCompareType(Compare compareType)
|
||||
{
|
||||
return _settings.Mode switch
|
||||
{
|
||||
SearchMode.Detailed => true,
|
||||
SearchMode.Fast => (compareType != Compare.Changes),
|
||||
SearchMode.Fast => compareType != Compare.Changes,
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,28 +8,25 @@ namespace BizHawk.Client.Common.RamSearchEngine
|
|||
{
|
||||
BigEndian = memoryDomains.MainMemory.EndianType == MemoryDomain.Endian.Big;
|
||||
Size = (WatchSize)memoryDomains.MainMemory.WordSize;
|
||||
Type = WatchDisplayType.Unsigned;
|
||||
Mode = memoryDomains.MainMemory.Size > 1024 * 1024
|
||||
? SearchMode.Fast
|
||||
: SearchMode.Detailed;
|
||||
|
||||
Domain = memoryDomains.MainMemory;
|
||||
CheckMisAligned = false;
|
||||
PreviousType = PreviousType.LastSearch;
|
||||
UseUndoHistory = useUndoHistory;
|
||||
}
|
||||
|
||||
/*Require restart*/
|
||||
public SearchMode Mode { get; set; }
|
||||
public MemoryDomain Domain { get; set; }
|
||||
public WatchSize Size { get; set; }
|
||||
public bool CheckMisAligned { get; set; }
|
||||
|
||||
/*Can be changed mid-search*/
|
||||
public WatchDisplayType Type { get; set; }
|
||||
public WatchDisplayType Type { get; set; } = WatchDisplayType.Unsigned;
|
||||
public bool BigEndian { get; set; }
|
||||
public PreviousType PreviousType { get; set; }
|
||||
public PreviousType PreviousType { get; set; } = PreviousType.LastFrame;
|
||||
public bool UseUndoHistory { get; set; }
|
||||
public SearchMode Mode { get; set; }
|
||||
}
|
||||
|
||||
public static class SearchEngineSettingsExtensions
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
{
|
||||
public enum PreviousType
|
||||
{
|
||||
Original = 0,
|
||||
LastSearch = 1,
|
||||
LastFrame = 2,
|
||||
LastChange = 3
|
||||
Original,
|
||||
LastFrame,
|
||||
LastChange,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
this.DisplayTypeSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.toolStripSeparator1 = new BizHawk.WinForms.Controls.ToolStripSeparatorEx();
|
||||
this.DefinePreviousValueSubMenu = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.Previous_LastSearchMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.PreviousFrameMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.Previous_OriginalMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
this.Previous_LastChangeMenuItem = new BizHawk.WinForms.Controls.ToolStripMenuItemEx();
|
||||
|
@ -397,18 +396,12 @@ namespace BizHawk.Client.EmuHawk
|
|||
// DefinePreviousValueSubMenu
|
||||
//
|
||||
this.DefinePreviousValueSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.Previous_LastSearchMenuItem,
|
||||
this.PreviousFrameMenuItem,
|
||||
this.Previous_OriginalMenuItem,
|
||||
this.Previous_LastChangeMenuItem});
|
||||
this.DefinePreviousValueSubMenu.Text = "Define Previous Value";
|
||||
this.DefinePreviousValueSubMenu.DropDownOpened += new System.EventHandler(this.DefinePreviousValueSubMenu_DropDownOpened);
|
||||
//
|
||||
// Previous_LastSearchMenuItem
|
||||
//
|
||||
this.Previous_LastSearchMenuItem.Text = "Last &Search";
|
||||
this.Previous_LastSearchMenuItem.Click += new System.EventHandler(this.Previous_LastSearchMenuItem_Click);
|
||||
//
|
||||
// PreviousFrameMenuItem
|
||||
//
|
||||
this.PreviousFrameMenuItem.Text = "&Previous Frame";
|
||||
|
@ -1132,7 +1125,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
private BizHawk.WinForms.Controls.ToolStripSeparatorEx toolStripSeparator8;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx DefinePreviousValueSubMenu;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx PreviousFrameMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx Previous_LastSearchMenuItem;
|
||||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx Previous_OriginalMenuItem;
|
||||
private System.Windows.Forms.GroupBox CompareToBox;
|
||||
private System.Windows.Forms.RadioButton DifferenceRadio;
|
||||
|
@ -1185,4 +1177,4 @@ namespace BizHawk.Client.EmuHawk
|
|||
private BizHawk.WinForms.Controls.ToolStripMenuItemEx AutoSearchAccountForLagMenuItem;
|
||||
private ToolStripMenuItemEx SelectAllMenuItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
var nextColor = Color.White;
|
||||
var search = _searches[index];
|
||||
var isCheat = MainForm.CheatList.IsActive(_settings.Domain, search.Address);
|
||||
var isWeeded = Settings.PreviewMode && !_forcePreviewClear && _searches.Preview(search.Address);
|
||||
var isWeeded = Settings.PreviewMode && !_forcePreviewClear && _searches.Preview(index);
|
||||
|
||||
if (!search.IsValid)
|
||||
{
|
||||
|
@ -271,8 +271,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
if (_searches.Count > 0)
|
||||
{
|
||||
_searches.Update();
|
||||
|
||||
if (_autoSearch)
|
||||
{
|
||||
if (InputPollableCore != null && Settings.AutoSearchTakeLagFramesIntoAccount && InputPollableCore.IsLagFrame)
|
||||
|
@ -281,21 +279,24 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
DoSearch();
|
||||
DoSearch(true);
|
||||
}
|
||||
}
|
||||
else if (_settings.IsDetailed())
|
||||
{
|
||||
_searches.Update(true);
|
||||
}
|
||||
|
||||
_forcePreviewClear = false;
|
||||
WatchListView.RowCount = _searches.Count;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this seems to be missing some logic from FrameUpdate that probably should exist here
|
||||
private void MinimalUpdate()
|
||||
{
|
||||
if (_searches.Count > 0)
|
||||
{
|
||||
_searches.Update();
|
||||
|
||||
if (_autoSearch)
|
||||
{
|
||||
DoSearch();
|
||||
|
@ -522,14 +523,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
}
|
||||
|
||||
public void DoSearch()
|
||||
public void DoSearch(bool updatePrevious = false)
|
||||
{
|
||||
_searches.CompareValue = CompareToValue;
|
||||
_searches.DifferentBy = DifferentByValue;
|
||||
_searches.Operator = Operator;
|
||||
_searches.CompareTo = Compare;
|
||||
|
||||
var removed = _searches.DoSearch();
|
||||
var removed = _searches.DoSearch(updatePrevious);
|
||||
UpdateList();
|
||||
SetRemovedMessage(removed);
|
||||
ToggleSearchDependentToolBarItems();
|
||||
|
@ -588,7 +589,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
&& _settings.IsDetailed())
|
||||
{
|
||||
_settings.Mode = SearchMode.Fast;
|
||||
SetReboot(true);
|
||||
MessageLabel.Text = "Large domain, switching to fast mode";
|
||||
}
|
||||
}
|
||||
|
@ -754,6 +754,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
private void SetToDetailedMode()
|
||||
{
|
||||
_settings.Mode = SearchMode.Detailed;
|
||||
_searches.SetMode(SearchMode.Detailed);
|
||||
NumberOfChangesRadio.Enabled = true;
|
||||
NumberOfChangesBox.Enabled = true;
|
||||
DifferenceRadio.Enabled = true;
|
||||
|
@ -764,7 +765,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
ChangesMenuItem.Checked = true;
|
||||
|
||||
ColumnToggleCallback();
|
||||
SetReboot(true);
|
||||
}
|
||||
|
||||
private ToolStripMenuItem ChangesMenuItem
|
||||
|
@ -783,11 +783,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
private void SetToFastMode()
|
||||
{
|
||||
_settings.Mode = SearchMode.Fast;
|
||||
|
||||
if (_settings.PreviousType == PreviousType.LastFrame || _settings.PreviousType == PreviousType.LastChange)
|
||||
{
|
||||
SetPreviousType(PreviousType.LastSearch);
|
||||
}
|
||||
_searches.SetMode(SearchMode.Fast);
|
||||
|
||||
NumberOfChangesRadio.Enabled = false;
|
||||
NumberOfChangesBox.Enabled = false;
|
||||
|
@ -803,7 +799,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
ChangesMenuItem.Checked = false;
|
||||
|
||||
ColumnToggleCallback();
|
||||
SetReboot(true);
|
||||
}
|
||||
|
||||
private void RemoveAddresses()
|
||||
|
@ -1085,7 +1080,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
private void DefinePreviousValueSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
Previous_LastSearchMenuItem.Checked = false;
|
||||
PreviousFrameMenuItem.Checked = false;
|
||||
Previous_OriginalMenuItem.Checked = false;
|
||||
Previous_LastChangeMenuItem.Checked = false;
|
||||
|
@ -1093,9 +1087,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
switch (_settings.PreviousType)
|
||||
{
|
||||
default:
|
||||
case PreviousType.LastSearch:
|
||||
Previous_LastSearchMenuItem.Checked = true;
|
||||
break;
|
||||
case PreviousType.LastFrame:
|
||||
PreviousFrameMenuItem.Checked = true;
|
||||
break;
|
||||
|
@ -1106,9 +1097,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
Previous_LastChangeMenuItem.Checked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
PreviousFrameMenuItem.Enabled = _settings.IsDetailed();
|
||||
Previous_LastChangeMenuItem.Enabled = _settings.IsDetailed();
|
||||
}
|
||||
|
||||
private void DetailedMenuItem_Click(object sender, EventArgs e)
|
||||
|
@ -1147,11 +1135,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
SetPreviousType(PreviousType.LastFrame);
|
||||
}
|
||||
|
||||
private void Previous_LastSearchMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetPreviousType(PreviousType.LastSearch);
|
||||
}
|
||||
|
||||
private void Previous_OriginalMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetPreviousType(PreviousType.Original);
|
||||
|
@ -1170,8 +1153,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
private void SearchSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
ClearChangeCountsMenuItem.Enabled = _settings.IsDetailed();
|
||||
|
||||
RemoveMenuItem.Enabled =
|
||||
AddToRamWatchMenuItem.Enabled =
|
||||
WatchListView.AnyRowsSelected;
|
||||
|
|
Loading…
Reference in New Issue