Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions src/BizHawk.Client.Common/tools/Cheat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@ public enum CompareType

private readonly Watch _watch;
private int? _compare;
private int _val;

private long _val;

private bool _enabled;

public Cheat(Watch watch, int value, int? compare = null, bool enabled = true, CompareType comparisonType = CompareType.None)
public Cheat(
Watch watch,
long value,
int? compare = null,
bool enabled = true,
CompareType comparisonType = CompareType.None)
{
_enabled = enabled;
_watch = watch;
Expand Down Expand Up @@ -67,7 +74,8 @@ public Cheat(Cheat cheat)

public long? Address => _watch.Address;

public int? Value => IsSeparator ? null : _val;
public long? Value
=> IsSeparator ? null : _val;

public bool? BigEndian => IsSeparator ? null : _watch.BigEndian;

Expand Down Expand Up @@ -97,6 +105,7 @@ public MemoryDomain Domain
WatchSize.Byte => ((ByteWatch) _watch).FormatValue((byte)_val),
WatchSize.Word => ((WordWatch) _watch).FormatValue((ushort)_val),
WatchSize.DWord => ((DWordWatch) _watch).FormatValue((uint)_val),
WatchSize.QWord => ((QWordWatch) _watch).FormatValue(unchecked((ulong) _val)),
WatchSize.Separator => "",
_ => string.Empty,
};
Expand All @@ -112,6 +121,7 @@ public string CompareStr
WatchSize.Byte => ((ByteWatch) _watch).FormatValue((byte)_compare.Value),
WatchSize.Word => ((WordWatch) _watch).FormatValue((ushort)_compare.Value),
WatchSize.DWord => ((DWordWatch) _watch).FormatValue((uint)_compare.Value),
WatchSize.QWord => ((QWordWatch) _watch).FormatValue(unchecked((ulong) _compare.Value)),
WatchSize.Separator => "",
_ => string.Empty,
};
Expand Down Expand Up @@ -178,6 +188,9 @@ public void Pulse()
case WatchSize.DWord:
_watch.Poke(((DWordWatch)_watch).FormatValue((uint)_val));
break;
case WatchSize.QWord:
_watch.Poke(((QWordWatch) _watch).FormatValue(unchecked((ulong) _val)));
break;
}
}

Expand Down Expand Up @@ -229,10 +242,12 @@ public bool Contains(long addr)
return addr == _watch.Address || addr == _watch.Address + 1;
case WatchSize.DWord:
return addr >= _watch.Address && addr <= _watch.Address + 3;
case WatchSize.QWord:
return _watch.Address <= addr && addr <= _watch.Address + (sizeof(ulong) - 1);
}
}

public void PokeValue(int val)
public void PokeValue(long val)
{
if (!IsSeparator)
{
Expand All @@ -245,7 +260,7 @@ public void Increment()
if (!IsSeparator)
{
_val++;
if (_val > _watch.MaxValue)
if (unchecked((ulong) _val) > _watch.MaxValue)
{
_val = 0;
}
Expand All @@ -260,10 +275,7 @@ public void Decrement()
if (!IsSeparator)
{
_val--;
if ((uint)_val > _watch.MaxValue)
{
_val = (int)_watch.MaxValue;
}
if (unchecked((ulong) _val) > _watch.MaxValue) _val = unchecked((long) _watch.MaxValue);

Pulse();
Changes();
Expand Down
11 changes: 11 additions & 0 deletions src/BizHawk.Client.Common/tools/RamSearchEngine/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public static IEnumerable<IMiniWatch> ToDWords(this IEnumerable<long> addresses,
? addresses.ToDetailedDWords(settings.Domain, settings.BigEndian)
: addresses.ToDWords(settings.Domain, settings.BigEndian);

public static IEnumerable<IMiniWatch> ToQWords(this IEnumerable<long> addresses, SearchEngineSettings settings)
=> settings.IsDetailed()
? addresses.ToDetailedQWords(settings.Domain, settings.BigEndian)
: addresses.ToQWords(settings.Domain, settings.BigEndian);

private static IEnumerable<IMiniWatch> ToBytes(this IEnumerable<long> addresses, MemoryDomain domain)
=> addresses.Select(a => new MiniByteWatch(domain, a));

Expand All @@ -38,5 +43,11 @@ private static IEnumerable<IMiniWatch> ToDWords(this IEnumerable<long> addresses

private static IEnumerable<IMiniWatch> ToDetailedDWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
=> addresses.Select(a => new MiniDWordWatchDetailed(domain, a, bigEndian));

private static IEnumerable<IMiniWatch> ToQWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
=> addresses.Select(a => new MiniQWordWatch(domain, a, bigEndian));

private static IEnumerable<IMiniWatch> ToDetailedQWords(this IEnumerable<long> addresses, MemoryDomain domain, bool bigEndian)
=> addresses.Select(a => new MiniQWordWatchDetailed(domain, a, bigEndian));
}
}
135 changes: 48 additions & 87 deletions src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,125 +9,86 @@ namespace BizHawk.Client.Common.RamSearchEngine
internal interface IMiniWatch
{
long Address { get; }
uint Previous { get; }

ulong Previous { get; }

ulong GetValue(MemoryDomain domain, bool bigEndian);

void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian);
bool IsValid(MemoryDomain domain);
}

internal class MiniByteWatch : IMiniWatch
internal abstract class MiniWatchBase : IMiniWatch
{
public long Address { get; }
private protected byte _previous;

public MiniByteWatch(MemoryDomain domain, long addr)
public ulong Previous { get; protected set; }

protected MiniWatchBase(long addr, ulong prevValue)
{
Address = addr;
_previous = GetByte(Address, domain);
Previous = prevValue;
}

public uint Previous => _previous;
public ulong GetValue(MemoryDomain domain, bool bigEndian)
=> IsValid(domain) ? GetValueInner(Address, domain, bigEndian: bigEndian) : default;

protected abstract ulong GetValueInner(long address, MemoryDomain domain, bool bigEndian);

public bool IsValid(MemoryDomain domain)
{
return IsValid(Address, domain);
}
=> IsValid(Address, domain);

protected abstract bool IsValid(long address, MemoryDomain domain);

public virtual void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
{
_previous = GetByte(Address, domain);
}
=> Previous = GetValueInner(Address, domain, bigEndian: bigEndian);
}

public static bool IsValid(long address, MemoryDomain domain)
{
return address < domain.Size;
}
internal class MiniByteWatch : MiniWatchBase
{
public MiniByteWatch(MemoryDomain domain, long addr)
: base(addr: addr, prevValue: domain.PeekByte(addr)) {}

public static byte GetByte(long address, MemoryDomain domain)
{
if (!IsValid(address, domain))
{
return 0;
}
protected override ulong GetValueInner(long address, MemoryDomain domain, bool bigEndian)
=> domain.PeekByte(address);

return domain.PeekByte(address);
}
protected override bool IsValid(long address, MemoryDomain domain)
=> 0L <= address && address < domain.Size;
}

internal class MiniWordWatch : IMiniWatch
internal class MiniWordWatch : MiniWatchBase
{
public long Address { get; }
private protected ushort _previous;

public MiniWordWatch(MemoryDomain domain, long addr, bool bigEndian)
{
Address = addr;
_previous = GetUshort(Address, domain, bigEndian);
}
: base(addr: addr, prevValue: domain.PeekUshort(addr, bigEndian: bigEndian)) {}

public uint Previous => _previous;
protected override ulong GetValueInner(long address, MemoryDomain domain, bool bigEndian)
=> domain.PeekUshort(address, bigEndian);

public virtual void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
{
_previous = GetUshort(Address, domain, bigEndian);
}

public bool IsValid(MemoryDomain domain)
{
return IsValid(Address, domain);
}

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))
{
return 0;
}

return domain.PeekUshort(address, bigEndian);
}
protected override bool IsValid(long address, MemoryDomain domain)
=> 0L <= address && address <= domain.Size - sizeof(ushort);
}

internal class MiniDWordWatch : IMiniWatch
internal class MiniDWordWatch : MiniWatchBase
{
public long Address { get; }
private protected uint _previous;

public MiniDWordWatch(MemoryDomain domain, long addr, bool bigEndian)
{
Address = addr;
_previous = GetUint(Address, domain, bigEndian);
}
: base(addr: addr, prevValue: domain.PeekUint(addr, bigEndian: bigEndian)) {}

public uint Previous => _previous;
protected override ulong GetValueInner(long address, MemoryDomain domain, bool bigEndian)
=> domain.PeekUint(address, bigEndian);

public virtual void SetPreviousToCurrent(MemoryDomain domain, bool bigEndian)
{
_previous = GetUint(Address, domain, bigEndian);
}

public bool IsValid(MemoryDomain domain)
{
return IsValid(Address, domain);
}
protected override bool IsValid(long address, MemoryDomain domain)
=> 0L <= address && address <= domain.Size - sizeof(uint);
}

public static bool IsValid(long address, MemoryDomain domain)
{
return address < (domain.Size - 3);
}
internal class MiniQWordWatch : MiniWatchBase
{
public MiniQWordWatch(MemoryDomain domain, long addr, bool bigEndian)
: base(addr: addr, prevValue: domain.PeekUint(addr, bigEndian: bigEndian)) {}

public static uint GetUint(long address, MemoryDomain domain, bool bigEndian)
{
if (!IsValid(address, domain))
{
return 0;
}
protected override ulong GetValueInner(long address, MemoryDomain domain, bool bigEndian)
=> domain.PeekUlong(address, bigEndian);

return domain.PeekUint(address, bigEndian);
}
protected override bool IsValid(long address, MemoryDomain domain)
=> 0L <= address && address <= domain.Size - sizeof(ulong);
}
}
Loading
Loading