diff --git a/src/BizHawk.Client.Common/tools/Cheat.cs b/src/BizHawk.Client.Common/tools/Cheat.cs index 1840449e18..227c0b5626 100644 --- a/src/BizHawk.Client.Common/tools/Cheat.cs +++ b/src/BizHawk.Client.Common/tools/Cheat.cs @@ -91,35 +91,20 @@ namespace BizHawk.Client.Common public string AddressStr => _watch.AddressString; - public string ValueStr => - _watch.Size switch - { - WatchSize.Byte => ((ByteWatch) _watch).FormatValue((byte)_val), - WatchSize.Word => ((WordWatch) _watch).FormatValue((ushort)_val), - WatchSize.DWord => ((DWordWatch) _watch).FormatValue((uint)_val), - WatchSize.Separator => "", - _ => string.Empty, - }; + public string ValueStr + => _watch.Size is WatchSize.Byte or WatchSize.Word or WatchSize.DWord + ? _watch.IsValid + ? Watch.FormatValue(unchecked((uint) _val), _watch.Size, _watch.Type) + : "-" + : string.Empty; public string CompareStr - { - get - { - if (_compare.HasValue) - { - return _watch.Size switch - { - 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.Separator => "", - _ => string.Empty, - }; - } - - return ""; - } - } + => _compare.Value is int compareValue + && _watch.Size is WatchSize.Byte or WatchSize.Word or WatchSize.DWord + ? _watch.IsValid + ? Watch.FormatValue(unchecked((uint) compareValue), _watch.Size, _watch.Type) + : "-" + : string.Empty; public CompareType ComparisonType { get; } diff --git a/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs b/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs index 3fb72c3faf..d2480d7c45 100644 --- a/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/ByteWatch.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using System.Globalization; + using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -56,16 +56,7 @@ namespace BizHawk.Client.Common { try { - byte val = Type switch - { - WatchDisplayType.Unsigned => byte.Parse(value), - WatchDisplayType.Signed => (byte)sbyte.Parse(value), - WatchDisplayType.Hex => byte.Parse(value, NumberStyles.HexNumber), - WatchDisplayType.Binary => Convert.ToByte(value, 2), - _ => 0, - }; - - PokeByte(val); + PokeByte(unchecked((byte) Watch.ParseValue(value, Size, Type))); return true; } catch @@ -104,17 +95,7 @@ namespace BizHawk.Client.Common // TODO: Implements IFormattable public string FormatValue(byte val) - { - return Type switch - { - _ when !IsValid => "-", - WatchDisplayType.Unsigned => val.ToString(), - WatchDisplayType.Signed => ((sbyte) val).ToString(), - WatchDisplayType.Hex => $"{val:X2}", - WatchDisplayType.Binary => Convert.ToString(val, 2).PadLeft(8, '0').Insert(4, " "), - _ => val.ToString(), - }; - } + => IsValid ? Watch.FormatValue(val, Size, Type) : "-"; public override string Diff => $"{_value - _previous:+#;-#;0}"; diff --git a/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs b/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs index 9d9ab5e781..9096a72911 100644 --- a/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; -using System.Globalization; -using BizHawk.Common.NumberExtensions; + using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -58,19 +57,7 @@ namespace BizHawk.Client.Common { try { - uint val = Type switch - { - WatchDisplayType.Unsigned => uint.Parse(value), - WatchDisplayType.Signed => (uint)int.Parse(value), - WatchDisplayType.Hex => uint.Parse(value, NumberStyles.HexNumber), - WatchDisplayType.FixedPoint_20_12 => (uint)(double.Parse(value, NumberFormatInfo.InvariantInfo) * 4096.0), - WatchDisplayType.FixedPoint_16_16 => (uint)(double.Parse(value, NumberFormatInfo.InvariantInfo) * 65536.0), - WatchDisplayType.Float => NumberExtensions.ReinterpretAsUInt32(float.Parse(value, NumberFormatInfo.InvariantInfo)), - WatchDisplayType.Binary => Convert.ToUInt32(value, 2), - _ => 0, - }; - - PokeDWord(val); + PokeDWord(Watch.ParseValue(value, Size, Type)); return true; } catch @@ -109,36 +96,7 @@ namespace BizHawk.Client.Common // TODO: Implements IFormattable public string FormatValue(uint val) - { - string FormatFloat() - { - var _float = NumberExtensions.ReinterpretAsF32(val); - return _float.ToString(NumberFormatInfo.InvariantInfo); - } - - string FormatBinary() - { - var str = Convert.ToString(val, 2).PadLeft(32, '0'); - for (var i = 28; i > 0; i -= 4) - { - str = str.Insert(i, " "); - } - return str; - } - - return Type switch - { - _ when !IsValid => "-", - WatchDisplayType.Unsigned => val.ToString(), - WatchDisplayType.Signed => ((int)val).ToString(), - WatchDisplayType.Hex => $"{val:X8}", - WatchDisplayType.FixedPoint_20_12 => ((int)val / 4096.0).ToString("0.######", NumberFormatInfo.InvariantInfo), - WatchDisplayType.FixedPoint_16_16 => ((int)val / 65536.0).ToString("0.######", NumberFormatInfo.InvariantInfo), - WatchDisplayType.Float => FormatFloat(), - WatchDisplayType.Binary => FormatBinary(), - _ => val.ToString(), - }; - } + => IsValid ? Watch.FormatValue(val, Size, Type) : "-"; public override string Diff => $"{_value - (long)_previous:+#;-#;0}"; diff --git a/src/BizHawk.Client.Common/tools/Watch/Watch.cs b/src/BizHawk.Client.Common/tools/Watch/Watch.cs index 1405123cfd..c9a2c79990 100644 --- a/src/BizHawk.Client.Common/tools/Watch/Watch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/Watch.cs @@ -19,6 +19,78 @@ namespace BizHawk.Client.Common IEquatable, IComparable { + private const string ERR_MSG_INVALID_WIDTH = "can only parse numeric strings for 1-, 2-, or 4-octet watches"; + + public static string FormatValue(uint value, WatchSize width, WatchDisplayType dispType) + => width switch + { + WatchSize.Byte => dispType switch + { + WatchDisplayType.Signed => unchecked((sbyte) value).ToString(), + WatchDisplayType.Unsigned => value.ToString(), + WatchDisplayType.Hex => $"{value:X2}", + WatchDisplayType.Binary => Convert.ToString(unchecked((byte) value), toBase: 2).PadLeft(8, '0').Insert(4, " "), + _ => value.ToString(), //TODO throw instead? + }, + WatchSize.Word => dispType switch + { + WatchDisplayType.Signed => unchecked((short) value).ToString(), + WatchDisplayType.Unsigned => value.ToString(), + WatchDisplayType.Hex => $"{value:X4}", + WatchDisplayType.Binary => Convert.ToString(unchecked((ushort) value), toBase: 2).PadLeft(16, '0') + .Insert(8, " ").Insert(4, " ").Insert(14, " "), + WatchDisplayType.FixedPoint_12_4 => $"{unchecked((short) value) / 16.0:F4}", + _ => value.ToString(), //TODO throw instead? + }, + WatchSize.DWord => dispType switch + { + WatchDisplayType.Signed => unchecked((int) value).ToString(), + WatchDisplayType.Unsigned => value.ToString(), + WatchDisplayType.Hex => $"{value:X8}", + WatchDisplayType.Binary => Convert.ToString(value, toBase: 2).PadLeft(32, '0') + .Insert(28, " ").Insert(24, " ").Insert(20, " ").Insert(16, " ").Insert(12, " ").Insert(8, " ").Insert(4, " "), + WatchDisplayType.FixedPoint_20_12 => $"{unchecked((int) value) / 4096.0:0.######}", + WatchDisplayType.FixedPoint_16_16 => $"{unchecked((int) value) / 65536.0:0.######}", + WatchDisplayType.Float => NumberExtensions.ReinterpretAsF32(value).ToString(NumberFormatInfo.InvariantInfo), + _ => value.ToString(), //TODO throw instead? + }, + _ => throw new ArgumentOutOfRangeException(paramName: nameof(width), width, message: ERR_MSG_INVALID_WIDTH), + }; + + public static uint ParseValue(string value, WatchSize width, WatchDisplayType dispType) + => width switch + { + WatchSize.Byte => dispType switch + { + WatchDisplayType.Signed => unchecked((byte) sbyte.Parse(value)), + WatchDisplayType.Unsigned => byte.Parse(value), + WatchDisplayType.Hex => byte.Parse(value, NumberStyles.HexNumber), + WatchDisplayType.Binary => Convert.ToByte(value, fromBase: 2), + _ => 0, //TODO throw instead? + }, + WatchSize.Word => dispType switch + { + WatchDisplayType.Signed => unchecked((ushort) short.Parse(value)), + WatchDisplayType.Unsigned => ushort.Parse(value), + WatchDisplayType.Hex => ushort.Parse(value, NumberStyles.HexNumber), + WatchDisplayType.Binary => Convert.ToUInt16(value, fromBase: 2), + WatchDisplayType.FixedPoint_12_4 => unchecked((ushort) (16.0 * double.Parse(value, NumberFormatInfo.InvariantInfo))), + _ => 0, //TODO throw instead? + }, + WatchSize.DWord => dispType switch + { + WatchDisplayType.Signed => unchecked((uint) int.Parse(value)), + WatchDisplayType.Unsigned => uint.Parse(value), + WatchDisplayType.Hex => uint.Parse(value, NumberStyles.HexNumber), + WatchDisplayType.Binary => Convert.ToUInt32(value, fromBase: 2), + WatchDisplayType.FixedPoint_20_12 => unchecked((uint) (4096.0 * double.Parse(value, NumberFormatInfo.InvariantInfo))), + WatchDisplayType.FixedPoint_16_16 => unchecked((uint) (65536.0 * double.Parse(value, NumberFormatInfo.InvariantInfo))), + WatchDisplayType.Float => NumberExtensions.ReinterpretAsUInt32(float.Parse(value, NumberFormatInfo.InvariantInfo)), + _ => 0, //TODO throw instead? + }, + _ => throw new ArgumentOutOfRangeException(paramName: nameof(width), width, message: ERR_MSG_INVALID_WIDTH), + }; + private MemoryDomain _domain; private WatchDisplayType _type; diff --git a/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs b/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs index aa47d9f889..15f8fb446a 100644 --- a/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/WordWatch.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using System.Globalization; + using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -54,17 +54,7 @@ namespace BizHawk.Client.Common { try { - ushort val = Type switch - { - WatchDisplayType.Unsigned => ushort.Parse(value), - WatchDisplayType.Signed => (ushort)short.Parse(value), - WatchDisplayType.Hex => ushort.Parse(value, NumberStyles.HexNumber), - WatchDisplayType.Binary => Convert.ToUInt16(value, 2), - WatchDisplayType.FixedPoint_12_4 => (ushort)(double.Parse(value, NumberFormatInfo.InvariantInfo) * 16.0), - _ => 0, - }; - - PokeWord(val); + PokeWord(unchecked((ushort) Watch.ParseValue(value, Size, Type))); return true; } catch @@ -104,22 +94,7 @@ namespace BizHawk.Client.Common // TODO: Implements IFormattable public string FormatValue(ushort val) - { - return Type switch - { - _ when !IsValid => "-", - WatchDisplayType.Unsigned => val.ToString(), - WatchDisplayType.Signed => ((short) val).ToString(), WatchDisplayType.Hex => $"{val:X4}", - WatchDisplayType.FixedPoint_12_4 => ((short)val / 16.0).ToString("F4", NumberFormatInfo.InvariantInfo), - WatchDisplayType.Binary => Convert - .ToString(val, 2) - .PadLeft(16, '0') - .Insert(8, " ") - .Insert(4, " ") - .Insert(14, " "), - _ => val.ToString(), - }; - } + => IsValid ? Watch.FormatValue(val, Size, Type) : "-"; public override string Diff => $"{_value - _previous:+#;-#;0}";