Comments on Watch derived class; started on watchlist

+ Moved WatchList.cs to specific directory (just a matter of ordering)
+ Mark some properties and methods in watchlist as obsolete
+ Create Comparer class that are used for sorting (Only domain and
address atm, other a still stored with linq). Unlike OrderBy in LINQ, it
doesn't create a new list for sorting (so it saves memory), furthermore,
it runs faster.
Finally, change to type of Watch.Address from nullable lon to regular
long (the rare times watch.Address.Value was used, there wasn't any
check of null and so, program would have crashed -
InvalidOperationException -)
This commit is contained in:
Hathor86 2015-12-01 22:16:28 +01:00
parent ef563a77e0
commit 32271899c3
14 changed files with 850 additions and 393 deletions

View File

@ -239,7 +239,9 @@
<Compile Include="tools\RamSearchEngine.cs" />
<Compile Include="tools\Watch\SeparatorWatch.cs" />
<Compile Include="tools\Watch\Watch.cs" />
<Compile Include="tools\Watch\WatchList.cs" />
<Compile Include="tools\Watch\WatchList\WatchDomainComparer.cs" />
<Compile Include="tools\Watch\WatchList\WatchAddressComparer.cs" />
<Compile Include="tools\Watch\WatchList\WatchList.cs" />
<Compile Include="tools\Watch\WatchSize.cs" />
<Compile Include="tools\Watch\WordWatch.cs" />
<Compile Include="XmlGame.cs" />

View File

@ -248,12 +248,12 @@ namespace BizHawk.Client.Common
case WatchSize.Separator:
return false;
case WatchSize.Byte:
return (_watch.Address ?? 0) == addr;
return _watch.Address == addr;
case WatchSize.Word:
return (addr == (_watch.Address ?? 0)) || (addr == (_watch.Address ?? 0) + 1);
return (addr == _watch.Address) || (addr == (_watch.Address) + 1);
case WatchSize.DWord:
return (addr == (_watch.Address ?? 0)) || (addr == (_watch.Address ?? 0) + 1) ||
(addr == (_watch.Address ?? 0) + 2) || (addr == (_watch.Address ?? 0) + 3);
return (addr == (_watch.Address)) || (addr == (_watch.Address) + 1) ||
(addr == (_watch.Address) + 2) || (addr == (_watch.Address) + 3);
}
}
@ -271,22 +271,22 @@ namespace BizHawk.Client.Common
case WatchSize.Byte:
return (byte?)_val;
case WatchSize.Word:
if (addr == (_watch.Address ?? 0))
if (addr == (_watch.Address))
{
return (byte)(_val >> 8);
}
return (byte)(_val & 0xFF);
case WatchSize.DWord:
if (addr == (_watch.Address ?? 0))
if (addr == (_watch.Address))
{
return (byte)((_val >> 24) & 0xFF);
}
else if (addr == (_watch.Address ?? 0) + 1)
else if (addr == (_watch.Address) + 1)
{
return (byte)((_val >> 16) & 0xFF);
}
else if (addr == ((_watch.Address ?? 0)) + 2)
else if (addr == ((_watch.Address)) + 2)
{
return (byte)((_val >> 8) & 0xFF);
}

View File

@ -346,7 +346,7 @@ namespace BizHawk.Client.Common
_history.AddState(_watchList);
}
var addresses = watches.Select(x => x.Address ?? 0);
var addresses = watches.Select(x => x.Address);
var removeList = _watchList.Where(x => !addresses.Contains(x.Address)).ToList();
}

View File

@ -80,136 +80,6 @@ namespace BizHawk.Client.Common
_previous = GetByte();
}
/// <summary>
/// Update the Watch (read it from <see cref="MemoryDomain"/>
/// </summary>
public override void Update()
{
switch (Global.Config.RamWatchDefinePrevious)
{
case PreviousType.Original:
return;
case PreviousType.LastChange:
var temp = _value;
_value = GetByte();
if (_value != temp)
{
_previous = _value;
_changecount++;
}
break;
case PreviousType.LastFrame:
_previous = _value;
_value = GetByte();
if (_value != Previous)
{
_changecount++;
}
break;
}
}
#endregion
//TODO: Implements IFormattable
public string FormatValue(byte val)
{
switch (Type)
{
default:
case DisplayType.Unsigned:
return val.ToString();
case DisplayType.Signed:
return ((sbyte)val).ToString();
case DisplayType.Hex:
return val.ToHexString(2);
case DisplayType.Binary:
return Convert.ToString(val, 2).PadLeft(8, '0').Insert(4, " ");
}
}
#endregion
/*public override string ToString()
{
return Notes + ": " + ValueString;
}*/
#region Properties
#region Implements
/// <summary>
/// Get a string representation of difference
/// between current value and the previous one
/// </summary>
public override string Diff
{
get
{
string diff = string.Empty;
byte diffVal = Convert.ToByte(_value - _previous);
if (diffVal > 0)
{
diff = "+";
}
else if (diffVal < 0)
{
diff = "-";
}
return string.Format("{0}{1}", diff, FormatValue(diffVal));
}
}
/// <summary>
/// Get the maximum possible value
/// </summary>
public override uint MaxValue
{
get
{
return byte.MaxValue;
}
}
/// <summary>
/// Get the current value
/// </summary>
public override int Value
{
get
{
return GetByte();
}
}
/// <summary>
/// Gets the current value
/// but with stuff I don't understand
/// </summary>
/// <remarks>zero 15-nov-2015 - bypass LIAR LOGIC, see fdc9ea2aa922876d20ba897fb76909bf75fa6c92 https://github.com/TASVideos/BizHawk/issues/326 </remarks>
public override int ValueNoFreeze
{
get
{
return GetByte(true);
}
}
/// <summary>
/// Get a string representation of the current value
/// </summary>
public override string ValueString
{
get
{
return FormatValue(_value);
}
}
/// <summary>
/// Try to sets the value into the <see cref="MemoryDomain"/>
/// at the current <see cref="Watch"/> address
@ -290,6 +160,131 @@ namespace BizHawk.Client.Common
}
}
/// <summary>
/// Update the Watch (read it from <see cref="MemoryDomain"/>
/// </summary>
public override void Update()
{
switch (Global.Config.RamWatchDefinePrevious)
{
case PreviousType.Original:
return;
case PreviousType.LastChange:
var temp = _value;
_value = GetByte();
if (_value != temp)
{
_previous = _value;
_changecount++;
}
break;
case PreviousType.LastFrame:
_previous = _value;
_value = GetByte();
if (_value != Previous)
{
_changecount++;
}
break;
}
}
#endregion Implements
//TODO: Implements IFormattable
public string FormatValue(byte val)
{
switch (Type)
{
default:
case DisplayType.Unsigned:
return val.ToString();
case DisplayType.Signed:
return ((sbyte)val).ToString();
case DisplayType.Hex:
return val.ToHexString(2);
case DisplayType.Binary:
return Convert.ToString(val, 2).PadLeft(8, '0').Insert(4, " ");
}
}
#endregion
#region Properties
#region Implements
/// <summary>
/// Get a string representation of difference
/// between current value and the previous one
/// </summary>
public override string Diff
{
get
{
string diff = string.Empty;
byte diffVal = Convert.ToByte(_value - _previous);
if (diffVal > 0)
{
diff = "+";
}
else if (diffVal < 0)
{
diff = "-";
}
return string.Format("{0}{1}", diff, FormatValue(diffVal));
}
}
/// <summary>
/// Get the maximum possible value
/// </summary>
public override uint MaxValue
{
get
{
return byte.MaxValue;
}
}
/// <summary>
/// Get the current value
/// </summary>
public override int Value
{
get
{
return GetByte();
}
}
/// <summary>
/// Gets the current value
/// but with stuff I don't understand
/// </summary>
/// <remarks>zero 15-nov-2015 - bypass LIAR LOGIC, see fdc9ea2aa922876d20ba897fb76909bf75fa6c92 https://github.com/TASVideos/BizHawk/issues/326 </remarks>
public override int ValueNoFreeze
{
get
{
return GetByte(true);
}
}
/// <summary>
/// Get a string representation of the current value
/// </summary>
public override string ValueString
{
get
{
return FormatValue(_value);
}
}
/// <summary>
/// Get the previous value
/// </summary>
@ -314,6 +309,6 @@ namespace BizHawk.Client.Common
#endregion Implements
#endregion
#endregion
}
}

View File

@ -9,6 +9,9 @@ using System.Text;
namespace BizHawk.Client.Common
{
/// <summary>
/// This class holds a double word (32 bits) <see cref="Watch"/>
/// </summary>
public sealed class DWordWatch : Watch
{
#region Fields
@ -20,6 +23,18 @@ namespace BizHawk.Client.Common
#region cTor(s)
/// <summary>
/// Inialize a new instance of <see cref="DWordWatch"/>
/// </summary>
/// <param name="domain"><see cref="MemoryDomain"/> where you want to track</param>
/// <param name="address">The address you want to track</param>
/// <param name="type">How you you want to display the value See <see cref="DisplayType"/></param>
/// <param name="bigEndian">Specify the endianess. true for big endian</param>
/// <param name="note">A custom note about the <see cref="Watch"/></param>
/// <param name="value">Current value</param>
/// <param name="previous">Previous value</param>
/// <param name="changeCount">How many times value has changed</param>
/// <exception cref="ArgumentException">Occurs when a <see cref="DisplayType"/> is incompatible with <see cref="WatchSize.DWord"/></exception>
internal DWordWatch(MemoryDomain domain, long address, DisplayType type, bool bigEndian, string note, uint value, uint previous, int changeCount)
: base(domain, address, WatchSize.DWord, type, bigEndian, note)
{
@ -28,15 +43,13 @@ namespace BizHawk.Client.Common
this._changecount = changeCount;
}
internal DWordWatch(MemoryDomain domain, long address, DisplayType type, bool bigEndian, string note)
:this(domain, address, type, bigEndian, note, 0, 0, 0)
{
_previous = GetDWord();
_value = GetDWord();
}
#endregion
#region Methods
/// <summary>
/// Enumerate wich <see cref="DisplayType"/> are valid for a <see cref="DWordWatch"/>
/// </summary>
public static IEnumerable<DisplayType> ValidTypes
{
get
@ -51,80 +64,31 @@ namespace BizHawk.Client.Common
}
}
#region Implements
/// <summary>
/// Get a list a <see cref="DisplayType"/> that can be used for this <see cref="DWordWatch"/>
/// </summary>
/// <returns>An enumartion that contains all valid <see cref="DisplayType"/></returns>
public override IEnumerable<DisplayType> AvailableTypes()
{
yield return DisplayType.Unsigned;
yield return DisplayType.Signed;
yield return DisplayType.Hex;
yield return DisplayType.Binary;
yield return DisplayType.FixedPoint_20_12;
yield return DisplayType.FixedPoint_16_16;
yield return DisplayType.Float;
}
public override int Value
{
get { return (int)GetDWord(); }
}
public override int ValueNoFreeze
{
get { return (int)GetDWord(true); }
}
public override int Previous
{
get { return (int)_previous; }
}
public override string PreviousStr
{
get { return FormatValue(_previous); }
return ValidTypes;
}
/// <summary>
/// Reset the previous value; set it to the current one
/// </summary>
public override void ResetPrevious()
{
_previous = GetWord();
}
public override uint MaxValue
{
get { return uint.MaxValue; }
}
public override string ValueString
{
get { return FormatValue(GetDWord()); }
}
/*public override string ToString()
{
return Notes + ": " + ValueString;
}*/
public string FormatValue(uint val)
{
switch (Type)
{
default:
case DisplayType.Unsigned:
return val.ToString();
case DisplayType.Signed:
return ((int)val).ToString();
case DisplayType.Hex:
return val.ToHexString(8);
case DisplayType.FixedPoint_20_12:
return string.Format("{0:0.######}", val / 4096.0);
case DisplayType.FixedPoint_16_16:
return string.Format("{0:0.######}", val / 65536.0);
case DisplayType.Float:
var bytes = BitConverter.GetBytes(val);
var _float = BitConverter.ToSingle(bytes, 0);
//return string.Format("{0:0.######}", _float);
return _float.ToString(); // adelikat: decided that we like sci notation instead of spooky rounding
}
}
/// <summary>
/// Try to sets the value into the <see cref="MemoryDomain"/>
/// at the current <see cref="Watch"/> address
/// </summary>
/// <param name="value">Value to set</param>
/// <returns>True if value successfully sets; othewise, false</returns>
public override bool Poke(string value)
{
try
@ -221,11 +185,9 @@ namespace BizHawk.Client.Common
}
}
public override string Diff
{
get { return FormatValue(_previous - _value); }
}
/// <summary>
/// Update the Watch (read it from <see cref="MemoryDomain"/>
/// </summary>
public override void Update()
{
switch (Global.Config.RamWatchDefinePrevious)
@ -253,5 +215,120 @@ namespace BizHawk.Client.Common
break;
}
}
#endregion Implements
//TODO: Implements IFormattable
public string FormatValue(uint val)
{
switch (Type)
{
default:
case DisplayType.Unsigned:
return val.ToString();
case DisplayType.Signed:
return ((int)val).ToString();
case DisplayType.Hex:
return val.ToHexString(8);
case DisplayType.FixedPoint_20_12:
return string.Format("{0:0.######}", val / 4096.0);
case DisplayType.FixedPoint_16_16:
return string.Format("{0:0.######}", val / 65536.0);
case DisplayType.Float:
var bytes = BitConverter.GetBytes(val);
var _float = BitConverter.ToSingle(bytes, 0);
//return string.Format("{0:0.######}", _float);
return _float.ToString(); // adelikat: decided that we like sci notation instead of spooky rounding
}
}
#endregion
#region Properties
#region Implements
/// <summary>
/// Get a string representation of difference
/// between current value and the previous one
/// </summary>
public override string Diff
{
get
{
return FormatValue(_previous - _value);
}
}
/// <summary>
/// Get the maximum possible value
/// </summary>
public override uint MaxValue
{
get
{
return uint.MaxValue;
}
}
/// <summary>
/// Get the current value
/// </summary>
public override int Value
{
get
{
return (int)GetDWord();
}
}
/// <summary>
/// Gets the current value
/// but with stuff I don't understand
/// </summary>
public override int ValueNoFreeze
{
get
{
return (int)GetDWord(true);
}
}
/// <summary>
/// Get a string representation of the current value
/// </summary>
public override string ValueString
{
get
{
return FormatValue(GetDWord());
}
}
/// <summary>
/// Get the previous value
/// </summary>
public override int Previous
{
get
{
return (int)_previous;
}
}
/// <summary>
/// Get a string representation of the previous value
/// </summary>
public override string PreviousStr
{
get
{
return FormatValue(_previous);
}
}
#endregion Implements
#endregion
}
}

View File

@ -3,69 +3,117 @@ using System.Collections.Generic;
namespace BizHawk.Client.Common
{
/// <summary>
/// This class holds a separator for RamWatch
/// Use the static property Instance to get it
/// </summary>
public sealed class SeparatorWatch : Watch
{
/// <summary>
/// Initialize a new separator instance
/// </summary>
internal SeparatorWatch()
:base(null, 0, WatchSize.Separator, DisplayType.Separator, true, string.Empty)
{ }
/// <summary>
/// Gets the separator instance
/// </summary>
public static SeparatorWatch Instance
{
get { return new SeparatorWatch(); }
}
/// <summary>
/// Get the appropriate DisplayType
/// </summary>
/// <returns>DisplayType.Separator nothing else</returns>
public override IEnumerable<DisplayType> AvailableTypes()
{
yield return DisplayType.Separator;
}
#region Stuff to ignore
/// <summary>
/// Ignore that stuff
/// </summary>
public override int Value
{
get { return 0; }
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override int ValueNoFreeze
{
get { return 0; }
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override int Previous
{
get { return 0; }
}
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override string ValueString
{
get { return string.Empty; }
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override string PreviousStr
{
get { return string.Empty; }
}
public override string ToString()
{
return "----";
}
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override bool Poke(string value)
{
return false;
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override void ResetPrevious()
{
return;
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override string Diff { get { return string.Empty; } }
/// <summary>
/// Ignore that stuff
/// </summary>
public override uint MaxValue
{
get { return 0; }
}
/// <summary>
/// Ignore that stuff
/// </summary>
public override void Update() { return; }
public override IEnumerable<DisplayType> AvailableTypes()
{
yield return DisplayType.Separator;
}
#endregion
}
}

View File

@ -327,8 +327,8 @@ namespace BizHawk.Client.Common
#endregion Abstracts
#region Protected
#region Protected
protected byte GetByte(bool bypassFreeze = false)
{
if (!bypassFreeze && Global.CheatList.IsActive(_domain, _address))
@ -429,10 +429,16 @@ namespace BizHawk.Client.Common
/// <returns>True if both object are equals; otherwise, false</returns>
public bool Equals(Watch other)
{
return !object.ReferenceEquals(other, null) &&
this._domain == other._domain &&
this._address == other._address &&
this._size == other._size;
if (object.ReferenceEquals(other, null))
{
return false;
}
else
{
return this._domain == other._domain &&
this._address == other._address &&
this._size == other._size;
}
}
#endregion IEquatable<Watch>
@ -478,7 +484,7 @@ namespace BizHawk.Client.Common
{
return 1;
}
else if (_address.Equals(other._address))
else if (_address.Equals(other._address))
{
return ((int)_size).CompareTo((int)other._size);
}
@ -518,7 +524,7 @@ namespace BizHawk.Client.Common
/// <returns>int that can serves as a unique representation of current Watch</returns>
public override int GetHashCode()
{
return this.Domain.GetHashCode() + (int)(this.Address ?? 0);
return this.Domain.GetHashCode() + (int)(this.Address);
}
/// <summary>
@ -539,7 +545,7 @@ namespace BizHawk.Client.Common
public override string ToString()
{
return string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}"
, (Address ?? 0).ToHexString((Domain.Size - 1).NumHexDigits())
, Address.ToHexString((Domain.Size - 1).NumHexDigits())
, SizeAsChar
, TypeAsChar
, Convert.ToInt32(BigEndian)
@ -605,7 +611,7 @@ namespace BizHawk.Client.Common
/// <summary>
/// Gets the address in the <see cref="MemoryDomain"/>
/// </summary>
public long? Address
public long Address
{
get
{
@ -699,9 +705,16 @@ namespace BizHawk.Client.Common
{
return _domain;
}
set
internal set
{
_domain = value;
if (_domain.Name == value.Name)
{
_domain = value;
}
else
{
throw new InvalidOperationException("You cannot set diffrent domain to a watch on the fly");
}
}
}
@ -719,7 +732,7 @@ namespace BizHawk.Client.Common
}
else
{
return null;
return string.Empty;
}
}
}

View File

@ -0,0 +1,94 @@
using System.Collections.Generic;
namespace BizHawk.Client.Common
{
/// <summary>
/// This class hold a collection <see cref="Watch"/>
/// Different memory domain can be mixed
/// </summary>
public sealed partial class WatchList
{
/// <summary>
/// Netsed private class that define how to compare two <see cref="Watch"/>
/// based on their address
/// </summary>
private struct WatchAddressComparer
: IEqualityComparer<Watch>,
IComparer<Watch>
{
/// <summary>
/// Compare two <see cref="Watch"/> between them
/// and determine wich one comes first.
/// If they are equals, comapraison will done one the domain and next on size
/// </summary>
/// <param name="x">First <see cref="Watch"/></param>
/// <returns>True if <see cref="Watch"/> are equal; otherwise, false</returns>
/// <returns></returns>
public int Compare(Watch x, Watch y)
{
if (Equals(x, y))
{
return 0;
}
else if (x.Address.Equals(y.Address))
{
if (x.Domain.Name.Equals(y.Domain.Name))
{
return x.Size.CompareTo(y.Size);
}
else
{
return x.Domain.Name.CompareTo(y.Domain.Name);
}
}
else
{
return x.Address.CompareTo(y.Address);
}
}
/// <summary>
/// Determine if two <see cref="Watch"/> are equals
/// </summary>
/// <param name="x">First <see cref="Watch"/></param>
/// <param name="y">Second <see cref="Watch"/></param>
/// <returns>True if <see cref="Watch"/> are equal; otherwise, false</returns>
public bool Equals(Watch x, Watch y)
{
if (object.ReferenceEquals(x, null))
{
if (object.ReferenceEquals(y, null))
{
return true;
}
else
{
return false;
}
}
else if (object.ReferenceEquals(y, null))
{
return false;
}
else if (object.ReferenceEquals(x, y))
{
return true;
}
else
{
return x.Address.Equals(y.Address);
}
}
/// <summary>
/// Get the hash value of specified <see cref="Watch"/>
/// </summary>
/// <param name="obj">Watch to get hash</param>
/// <returns>int that can serves as a unique representation of current Watch</returns>
public int GetHashCode(Watch obj)
{
return obj.GetHashCode();
}
}
}
}

View File

@ -0,0 +1,94 @@
using System.Collections.Generic;
namespace BizHawk.Client.Common
{
/// <summary>
/// This class hold a collection <see cref="Watch"/>
/// Different memory domain can be mixed
/// </summary>
public sealed partial class WatchList
{
/// <summary>
/// Netsed private class that define how to compare two <see cref="Watch"/>
/// based on their domain
/// </summary>
private struct WatchDomainComparer
: IEqualityComparer<Watch>,
IComparer<Watch>
{
/// <summary>
/// Compare two <see cref="Watch"/> between them
/// and determine wich one comes first.
/// If they are equals, comapraison will done one the address and next on size
/// </summary>
/// <param name="x">First <see cref="Watch"/></param>
/// <returns>True if <see cref="Watch"/> are equal; otherwise, false</returns>
/// <returns></returns>
public int Compare(Watch x, Watch y)
{
if(Equals(x, y))
{
return 0;
}
else if(x.Domain.Name.Equals(y.Domain.Name))
{
if (x.Address.Equals(y.Address))
{
return x.Size.CompareTo(y.Size);
}
else
{
return x.Address.CompareTo(y.Address);
}
}
else
{
return x.Domain.Name.CompareTo(y.Domain.Name);
}
}
/// <summary>
/// Determine if two <see cref="Watch"/> are equals
/// </summary>
/// <param name="x">First <see cref="Watch"/></param>
/// <param name="y">Second <see cref="Watch"/></param>
/// <returns>True if <see cref="Watch"/> are equal; otherwise, false</returns>
public bool Equals(Watch x, Watch y)
{
if(object.ReferenceEquals(x, null))
{
if(object.ReferenceEquals(y, null))
{
return true;
}
else
{
return false;
}
}
else if(object.ReferenceEquals(y, null))
{
return false;
}
else if(object.ReferenceEquals(x,y))
{
return true;
}
else
{
return x.Domain.Name.Equals(y.Domain.Name);
}
}
/// <summary>
/// Get the hash value of specified <see cref="Watch"/>
/// </summary>
/// <param name="obj">Watch to get hash</param>
/// <returns>int that can serves as a unique representation of current Watch</returns>
public int GetHashCode(Watch obj)
{
return obj.GetHashCode();
}
}
}
}

View File

@ -1,23 +1,27 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BizHawk.Common.NumberExtensions;
using BizHawk.Common.StringExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
public class WatchList : IList<Watch>
/// <summary>
/// This class hold a collection <see cref="Watch"/>
/// Different memory domain can be mixed
/// </summary>
public sealed partial class WatchList
: IList<Watch>
{
private IMemoryDomains _memoryDomains;
private List<Watch> _watchList = new List<Watch>();
private MemoryDomain _domain;
private string _currentFilename = string.Empty;
private string _systemid;
#region Fields
public const string ADDRESS = "AddressColumn";
public const string VALUE = "ValueColumn";
@ -27,14 +31,62 @@ namespace BizHawk.Client.Common
public const string DOMAIN = "DomainColumn";
public const string NOTES = "NotesColumn";
private static readonly WatchDomainComparer domainComparer = new WatchDomainComparer();
private static readonly WatchAddressComparer addressComparer = new WatchAddressComparer();
private static IMemoryDomains _memoryDomains;
private List<Watch> _watchList = new List<Watch>(0);
private MemoryDomain _domain;
private string _currentFilename = string.Empty;
private string _systemid;
#endregion
#region cTor(s)
/// <summary>
/// Initialize a new instance of <see cref="WatchList"/> that will
/// contains a set of <see cref="Watch"/>
/// </summary>
/// <param name="core">All available memomry domains</param>
/// <param name="domain">Domain you want to watch</param>
/// <param name="systemid">System identifier (NES, SNES, ...)</param>
[Obsolete("Use the constructor with two parameters instead")]
public WatchList(IMemoryDomains core, MemoryDomain domain, string systemid)
{
_memoryDomains = core;
if (_memoryDomains == null)
{
_memoryDomains = core;
}
_domain = domain;
_systemid = systemid;
}
public void RefreshDomans(IMemoryDomains core, MemoryDomain domain)
/// <summary>
/// Initialize a new instance of <see cref="WatchList"/> that will
/// contains a set of <see cref="Watch"/>
/// </summary>
/// <param name="core">All available memomry domains</param>
/// <param name="domain">Domain you want to watch</param>
/// <param name="systemid">System identifier (NES, SNES, ...)</param>
public WatchList(IMemoryDomains core, string systemid)
{
if (_memoryDomains == null)
{
_memoryDomains = core;
}
//TODO: Remove this after tests
_domain = core.MainMemory;
_systemid = systemid;
}
#endregion
#region Methods
[Obsolete("Use the method with single parameter instead")]
public void RefreshDomains(IMemoryDomains core, MemoryDomain domain)
{
_memoryDomains = core;
_domain = domain;
@ -47,8 +99,21 @@ namespace BizHawk.Client.Common
}
});
}
public enum WatchPrevDef { LastSearch, Original, LastFrame, LastChange }
public void RefreshDomains(IMemoryDomains core)
{
_memoryDomains = core;
Parallel.ForEach<Watch>(_watchList, watch =>
{
watch.Domain = core[watch.Domain.Name];
watch.ResetPrevious();
watch.Update();
watch.ClearChangeCount();
}
);
}
#endregion
public string AddressFormatStr // TODO: this is probably compensating for not using the ToHex string extension
{
@ -65,19 +130,30 @@ namespace BizHawk.Client.Common
public int Count
{
get { return _watchList.Count; }
get
{
return _watchList.Count;
}
}
public int WatchCount
{
get { return _watchList.Count(w => !w.IsSeparator); }
get
{
return _watchList.Count<Watch>(watch => !watch.IsSeparator);
}
}
[Obsolete("Use count property instead")]
public int ItemCount
{
get { return _watchList.Count; }
get
{
return Count;
}
}
[Obsolete("Use domain from individual watch instead")]
public MemoryDomain Domain
{
get { return _domain; }
@ -117,23 +193,12 @@ namespace BizHawk.Client.Common
case ADDRESS:
if (reverse)
{
_watchList = _watchList
.OrderByDescending(x => x.Address)
.ThenBy(x => x.Domain.Name)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ThenBy(x => x.BigEndian)
.ToList();
_watchList.Sort(addressComparer);
_watchList.Reverse();
}
else
{
_watchList = _watchList
.OrderBy(x => x.Address)
.ThenBy(x => x.Domain.Name)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ThenBy(x => x.BigEndian)
.ToList();
_watchList.Sort();
}
break;
@ -165,7 +230,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderByDescending(x => x.PreviousStr)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -174,7 +239,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderBy(x => x.PreviousStr)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -186,7 +251,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderByDescending(x => x.Diff)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -195,7 +260,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderBy(x => x.Diff)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -207,7 +272,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderByDescending(x => x.ChangeCount)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -216,7 +281,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderBy(x => x.ChangeCount)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -226,23 +291,12 @@ namespace BizHawk.Client.Common
case DOMAIN:
if (reverse)
{
_watchList = _watchList
.OrderByDescending(x => x.Domain)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ThenBy(x => x.BigEndian)
.ToList();
_watchList.Sort(domainComparer);
_watchList.Reverse();
}
else
{
_watchList = _watchList
.OrderBy(x => x.Domain)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ThenBy(x => x.BigEndian)
.ToList();
_watchList.Sort(domainComparer);
}
break;
@ -251,7 +305,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderByDescending(x => x.Notes)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -260,7 +314,7 @@ namespace BizHawk.Client.Common
{
_watchList = _watchList
.OrderBy(x => x.Notes)
.ThenBy(x => x.Address ?? 0)
.ThenBy(x => x.Address)
.ThenBy(x => x.Size)
.ThenBy(x => x.Type)
.ToList();
@ -279,11 +333,11 @@ namespace BizHawk.Client.Common
public void UpdateValues()
{
foreach (var watch in _watchList)
Parallel.ForEach<Watch>(_watchList, watch =>
{
watch.Update();
}
}
});
}
public void Add(Watch watch)
{
@ -412,7 +466,7 @@ namespace BizHawk.Client.Common
CurrentFileName = file.FullName;
return Save();
}
return false;
}
@ -476,7 +530,7 @@ namespace BizHawk.Client.Common
{
isOldBizHawkWatch = true; // This supports the legacy .wch format from 1.0.5 and earlier
}
else
else
{
continue; // If not 4, something is wrong with this line, ignore it
}
@ -532,9 +586,9 @@ namespace BizHawk.Client.Common
memDomain,
addr,
size,
type,
type,
bigEndian,
notes));
notes));
_domain = _memoryDomains[domain];
}

View File

@ -1,13 +1,17 @@
using BizHawk.Common.NumberExtensions;
using BizHawk.Common.StringExtensions;
using BizHawk.Emulation.Common;
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using BizHawk.Common.NumberExtensions;
using BizHawk.Common.StringExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Client.Common
{
/// <summary>
/// This class holds a word (16 bits) <see cref="Watch"/>
/// </summary>
public sealed class WordWatch : Watch
{
#region Fields
@ -19,6 +23,18 @@ namespace BizHawk.Client.Common
#region cTor(s)
/// <summary>
/// Inialize a new instance of <see cref="WordWatch"/>
/// </summary>
/// <param name="domain"><see cref="MemoryDomain"/> where you want to track</param>
/// <param name="address">The address you want to track</param>
/// <param name="type">How you you want to display the value See <see cref="DisplayType"/></param>
/// <param name="bigEndian">Specify the endianess. true for big endian</param>
/// <param name="note">A custom note about the <see cref="Watch"/></param>
/// <param name="value">Current value</param>
/// <param name="previous">Previous value</param>
/// <param name="changeCount">How many times value has changed</param>
/// <exception cref="ArgumentException">Occurs when a <see cref="DisplayType"/> is incompatible with <see cref="WatchSize.Word"/></exception>
internal WordWatch(MemoryDomain domain, long address, DisplayType type, bool bigEndian, string note, ushort value, ushort previous, int changeCount)
: base(domain, address, WatchSize.Word, type, bigEndian, note)
{
@ -27,15 +43,13 @@ namespace BizHawk.Client.Common
this._changecount = changeCount;
}
internal WordWatch(MemoryDomain domain, long address, DisplayType type, bool bigEndian, string note)
:this(domain, address, type, bigEndian, note, 0, 0, 0)
{
_previous = GetWord();
_value = GetWord();
}
#endregion
#region Methods
/// <summary>
/// Enumerate wich <see cref="DisplayType"/> are valid for a <see cref="WordWatch"/>
/// </summary>
public static IEnumerable<DisplayType> ValidTypes
{
get
@ -48,73 +62,31 @@ namespace BizHawk.Client.Common
}
}
#region Implements
/// <summary>
/// Get a list a <see cref="DisplayType"/> that can be used for this <see cref="WordWatch"/>
/// </summary>
/// <returns>An enumartion that contains all valid <see cref="DisplayType"/></returns>
public override IEnumerable<DisplayType> AvailableTypes()
{
yield return DisplayType.Unsigned;
yield return DisplayType.Signed;
yield return DisplayType.Hex;
yield return DisplayType.Binary;
yield return DisplayType.FixedPoint_12_4;
}
public override uint MaxValue
{
get { return ushort.MaxValue; }
}
public override int Value
{
get { return GetWord(); }
}
public override int ValueNoFreeze
{
get { return GetWord(true); }
}
public override int Previous
{
get { return _previous; }
}
public override string PreviousStr
{
get { return FormatValue(_previous); }
return ValidTypes;
}
/// <summary>
/// Reset the previous value; set it to the current one
/// </summary>
public override void ResetPrevious()
{
_previous = GetWord();
}
public override string ValueString
{
get { return FormatValue(GetWord()); }
}
/*public override string ToString()
{
return Notes + ": " + ValueString;
}*/
public string FormatValue(ushort val)
{
switch (Type)
{
default:
case DisplayType.Unsigned:
return val.ToString();
case DisplayType.Signed:
return ((short)val).ToString();
case DisplayType.Hex:
return val.ToHexString(4);
case DisplayType.FixedPoint_12_4:
return string.Format("{0:F4}", val / 16.0);
case DisplayType.Binary:
return Convert.ToString(val, 2).PadLeft(16, '0').Insert(8, " ").Insert(4, " ").Insert(14, " ");
}
}
/// <summary>
/// Try to sets the value into the <see cref="MemoryDomain"/>
/// at the current <see cref="Watch"/> address
/// </summary>
/// <param name="value">Value to set</param>
/// <returns>True if value successfully sets; othewise, false</returns>
public override bool Poke(string value)
{
try
@ -199,11 +171,9 @@ namespace BizHawk.Client.Common
}
}
public override string Diff
{
get { return FormatValue((ushort)(_previous - _value)); }
}
/// <summary>
/// Update the Watch (read it from <see cref="MemoryDomain"/>
/// </summary>
public override void Update()
{
switch (Global.Config.RamWatchDefinePrevious)
@ -232,5 +202,115 @@ namespace BizHawk.Client.Common
break;
}
}
#endregion Implements
//TODO: Implements IFormattable
public string FormatValue(ushort val)
{
switch (Type)
{
default:
case DisplayType.Unsigned:
return val.ToString();
case DisplayType.Signed:
return ((short)val).ToString();
case DisplayType.Hex:
return val.ToHexString(4);
case DisplayType.FixedPoint_12_4:
return string.Format("{0:F4}", val / 16.0);
case DisplayType.Binary:
return Convert.ToString(val, 2).PadLeft(16, '0').Insert(8, " ").Insert(4, " ").Insert(14, " ");
}
}
#endregion
#region Properties
#region Implements
/// <summary>
/// Get a string representation of difference
/// between current value and the previous one
/// </summary>
public override string Diff
{
get
{
return FormatValue((ushort)(_previous - _value));
}
}
/// <summary>
/// Get the maximum possible value
/// </summary>
public override uint MaxValue
{
get
{
return ushort.MaxValue;
}
}
/// <summary>
/// Gets the current value
/// </summary>
public override int Value
{
get
{
return GetWord();
}
}
/// <summary>
/// Gets the current value
/// but with stuff I don't understand
/// </summary>
public override int ValueNoFreeze
{
get
{
return GetWord(true);
}
}
/// <summary>
/// Get a string representation of the current value
/// </summary>
public override string ValueString
{
get
{
return FormatValue(GetWord());
}
}
/// <summary>
/// Get the previous value
/// </summary>
public override int Previous
{
get
{
return _previous;
}
}
/// <summary>
/// Get a string representation of the previous value
/// </summary>
public override string PreviousStr
{
get
{
return FormatValue(_previous);
}
}
#endregion Implements
#endregion
}
}

View File

@ -172,10 +172,10 @@ namespace BizHawk.Client.EmuHawk
{
var nextColor = Color.White;
var isCheat = Global.CheatList.IsActive(_settings.Domain, _searches[index].Address ?? 0);
var isWeeded = Settings.PreviewMode && !_forcePreviewClear && _searches.Preview(_searches[index].Address ?? 0);
var isCheat = Global.CheatList.IsActive(_settings.Domain, _searches[index].Address);
var isWeeded = Settings.PreviewMode && !_forcePreviewClear && _searches.Preview(_searches[index].Address);
if (_searches[index].Address.Value >= _searches[index].Domain.Size)
if (_searches[index].Address >= _searches[index].Domain.Size)
{
nextColor = Color.PeachPuff;
}
@ -852,7 +852,7 @@ namespace BizHawk.Client.EmuHawk
watches.Load(file.FullName, append);
var watchList = watches.Where(x => !x.IsSeparator);
var addresses = watchList.Select(x => x.Address ?? 0).ToList();
var addresses = watchList.Select(x => x.Address).ToList();
if (truncate)
{
@ -1319,7 +1319,7 @@ namespace BizHawk.Client.EmuHawk
private void FreezeAddressMenuItem_Click(object sender, EventArgs e)
{
var allCheats = SelectedWatches.All(x => Global.CheatList.IsActive(x.Domain, x.Address ?? 0));
var allCheats = SelectedWatches.All(x => Global.CheatList.IsActive(x.Domain, x.Address));
if (allCheats)
{
SelectedWatches.UnfreezeAll();
@ -1463,7 +1463,7 @@ namespace BizHawk.Client.EmuHawk
var allCheats = true;
foreach (var index in SelectedIndices)
{
if (!Global.CheatList.IsActive(_settings.Domain, _searches[index].Address ?? 0))
if (!Global.CheatList.IsActive(_settings.Domain, _searches[index].Address))
{
allCheats = false;
}
@ -1490,7 +1490,7 @@ namespace BizHawk.Client.EmuHawk
{
if (SelectedWatches.Any())
{
ToolHelpers.ViewInHexEditor(_searches.Domain, SelectedWatches.Select(x => x.Address ?? 0), SelectedSize);
ToolHelpers.ViewInHexEditor(_searches.Domain, SelectedWatches.Select(x => x.Address), SelectedSize);
}
}

View File

@ -219,7 +219,7 @@ namespace BizHawk.Client.EmuHawk
if (_watches != null && !string.IsNullOrWhiteSpace(_watches.CurrentFileName))
{
_watches.RefreshDomans(_memoryDomains, _memoryDomains.MainMemory);
_watches.RefreshDomains(_memoryDomains, _memoryDomains.MainMemory);
_watches.Reload();
SetPlatformAndMemoryDomainLabel();
UpdateStatusBar();
@ -251,7 +251,7 @@ namespace BizHawk.Client.EmuHawk
{
for (var i = 0; i < _watches.Count; i++)
{
var frozen = !_watches[i].IsSeparator && Global.CheatList.IsActive(_watches[i].Domain, _watches[i].Address ?? 0);
var frozen = !_watches[i].IsSeparator && Global.CheatList.IsActive(_watches[i].Domain, _watches[i].Address);
GlobalWin.OSD.AddGUIText(
_watches[i].ToString(),
Global.Config.DispRamWatchx,
@ -286,7 +286,7 @@ namespace BizHawk.Client.EmuHawk
return true;
}
if (Global.CheatList.IsActive(_watches.Domain, watch.Address ?? 0))
if (Global.CheatList.IsActive(_watches.Domain, watch.Address))
{
return true;
}
@ -321,7 +321,7 @@ namespace BizHawk.Client.EmuHawk
{
for (var i = 0; i < _watches.Count; i++)
{
var frozen = !_watches[i].IsSeparator && Global.CheatList.IsActive(_watches[i].Domain, _watches[i].Address ?? 0);
var frozen = !_watches[i].IsSeparator && Global.CheatList.IsActive(_watches[i].Domain, _watches[i].Address);
GlobalWin.OSD.AddGUIText(
_watches[i].ToString(),
Global.Config.DispRamWatchx,
@ -585,7 +585,7 @@ namespace BizHawk.Client.EmuHawk
}
}
ErrorIconButton.Visible = _watches.Where(watch => !watch.IsSeparator).Any(watch => (watch.Address ?? 0) >= watch.Domain.Size);
ErrorIconButton.Visible = _watches.Where(watch => !watch.IsSeparator).Any(watch => (watch.Address) >= watch.Domain.Size);
MessageLabel.Text = message;
}
@ -608,11 +608,11 @@ namespace BizHawk.Client.EmuHawk
{
color = BackColor;
}
else if (_watches[index].Address.Value >= _watches[index].Domain.Size)
else if (_watches[index].Address >= _watches[index].Domain.Size)
{
color = Color.PeachPuff;
}
else if (Global.CheatList.IsActive(_watches.Domain, _watches[index].Address ?? 0))
else if (Global.CheatList.IsActive(_watches.Domain, _watches[index].Address))
{
color = Color.LightCyan;
}
@ -813,7 +813,7 @@ namespace BizHawk.Client.EmuHawk
private void FreezeAddressMenuItem_Click(object sender, EventArgs e)
{
var allCheats = SelectedWatches.All(x => Global.CheatList.IsActive(x.Domain, x.Address ?? 0));
var allCheats = SelectedWatches.All(x => Global.CheatList.IsActive(x.Domain, x.Address));
if (allCheats)
{
SelectedWatches.UnfreezeAll();
@ -1074,7 +1074,7 @@ namespace BizHawk.Client.EmuHawk
SelectedIndices.Any() &&
SelectedWatches.All(w => w.Domain.CanPoke());
var allCheats = _watches.All(x => Global.CheatList.IsActive(x.Domain, x.Address ?? 0));
var allCheats = _watches.All(x => Global.CheatList.IsActive(x.Domain, x.Address));
if (allCheats)
{
@ -1108,11 +1108,11 @@ namespace BizHawk.Client.EmuHawk
if (selected.Select(x => x.Domain).Distinct().Count() > 1)
{
ToolHelpers.ViewInHexEditor(selected[0].Domain, new List<long> { selected.First().Address ?? 0 }, selected.First().Size);
ToolHelpers.ViewInHexEditor(selected[0].Domain, new List<long> { selected.First().Address }, selected.First().Size);
}
else
{
ToolHelpers.ViewInHexEditor(selected.First().Domain, selected.Select(x => x.Address ?? 0), selected.First().Size);
ToolHelpers.ViewInHexEditor(selected.First().Domain, selected.Select(x => x.Address ), selected.First().Size);
}
}
}
@ -1127,7 +1127,7 @@ namespace BizHawk.Client.EmuHawk
foreach (var watch in selected)
{
debugger.AddBreakpoint((uint)watch.Address.Value, MemoryCallbackType.Read);
debugger.AddBreakpoint((uint)watch.Address, MemoryCallbackType.Read);
}
}
}
@ -1142,7 +1142,7 @@ namespace BizHawk.Client.EmuHawk
foreach (var watch in selected)
{
debugger.AddBreakpoint((uint)watch.Address.Value, MemoryCallbackType.Write);
debugger.AddBreakpoint((uint)watch.Address, MemoryCallbackType.Write);
}
}
}
@ -1194,7 +1194,7 @@ namespace BizHawk.Client.EmuHawk
private void ErrorIconButton_Click(object sender, EventArgs e)
{
var items = _watches
.Where(watch => (watch.Address ?? 0) >= watch.Domain.Size)
.Where(watch => (watch.Address) >= watch.Domain.Size)
.ToList();
foreach (var item in items)

View File

@ -96,7 +96,7 @@ namespace BizHawk.Client.EmuHawk
else
{
NotesBox.Text = _watchList[0].Notes;
AddressBox.SetFromLong(_watchList[0].Address ?? 0);
AddressBox.SetFromLong(_watchList[0].Address);
}
SetBigEndianCheckBox();
@ -267,7 +267,7 @@ namespace BizHawk.Client.EmuHawk
{
_watchList.Add(Watch.GenerateWatch(
watch.Domain,
watch.Address ?? 0,
watch.Address,
watch.Size,
watch.Type,
watch.BigEndian,
@ -308,7 +308,7 @@ namespace BizHawk.Client.EmuHawk
_watchList[i] = Watch.GenerateWatch(
_watchList[i].Domain,
_watchList.Count == 1 ? AddressBox.ToRawInt() ?? 0 : _watchList[i].Address ?? 0,
_watchList.Count == 1 ? AddressBox.ToRawInt() ?? 0 : _watchList[i].Address,
size,
_watchList[i].Type,
_watchList[i].BigEndian,