Allow negative values to be entered in ram watch for fixed-point watches (#3181)
* structurize NumericStringExtensions better, allow negative fixedpoint numbers * Tune MaxLength values to make more sense * Use Invariant culture to prevent ","<->"." issue in decimal recognition for some locales * Cleanup more watch stuff - simplify Poke functions by removing redundant text checking - make fixed-point constants const - remove OnKeyPress overload; let the user type whatever and check it later, similarly in OnTextChanged - more invariant NumberFormatInfo use for ","<->"." issues, also do a basic fixup on OnKeyDown - cleanup ToRawInt and SetFromRawInt, there are likely still issues remaining but I have no idea whether they realistically affect anything with the way those functions are used - remove now unused functions in NumericStringExtensions
This commit is contained in:
parent
64ac7253f6
commit
6db532fb84
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using BizHawk.Common.StringExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
|
@ -76,54 +74,14 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
try
|
||||
{
|
||||
byte val = 0;
|
||||
switch (Type)
|
||||
byte val = Type switch
|
||||
{
|
||||
case WatchDisplayType.Unsigned:
|
||||
if (value.IsUnsigned())
|
||||
{
|
||||
val = (byte)int.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Signed:
|
||||
if (value.IsSigned())
|
||||
{
|
||||
val = (byte)(sbyte)int.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Hex:
|
||||
if (value.IsHex())
|
||||
{
|
||||
val = (byte)int.Parse(value, NumberStyles.HexNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Binary:
|
||||
if (value.IsBinary())
|
||||
{
|
||||
val = (byte)Convert.ToInt32(value, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using BizHawk.Common.StringExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
|
@ -79,77 +77,16 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
try
|
||||
{
|
||||
uint val = 0;
|
||||
switch (Type)
|
||||
uint val = Type switch
|
||||
{
|
||||
case WatchDisplayType.Unsigned:
|
||||
if (value.IsUnsigned())
|
||||
{
|
||||
val = (uint)int.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Signed:
|
||||
if (value.IsSigned())
|
||||
{
|
||||
val = (uint)int.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Hex:
|
||||
if (value.IsHex())
|
||||
{
|
||||
val = (uint)int.Parse(value, NumberStyles.HexNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
if (value.IsFixedPoint())
|
||||
{
|
||||
val = (uint)(int)(double.Parse(value) * 4096.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
if (value.IsFixedPoint())
|
||||
{
|
||||
val = (uint)(int)(double.Parse(value) * 65536.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
if (value.IsFloat())
|
||||
{
|
||||
var bytes = BitConverter.GetBytes(float.Parse(value));
|
||||
val = BitConverter.ToUInt32(bytes, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
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 => BitConverter.ToUInt32(BitConverter.GetBytes(float.Parse(value, NumberFormatInfo.InvariantInfo)), 0),
|
||||
_ => 0
|
||||
};
|
||||
|
||||
PokeDWord(val);
|
||||
return true;
|
||||
|
@ -198,7 +135,7 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
var bytes = BitConverter.GetBytes(val);
|
||||
var _float = BitConverter.ToSingle(bytes, 0);
|
||||
return _float.ToString();
|
||||
return _float.ToString(NumberFormatInfo.InvariantInfo);
|
||||
}
|
||||
|
||||
string FormatBinary()
|
||||
|
@ -217,8 +154,8 @@ namespace BizHawk.Client.Common
|
|||
WatchDisplayType.Unsigned => val.ToString(),
|
||||
WatchDisplayType.Signed => ((int)val).ToString(),
|
||||
WatchDisplayType.Hex => $"{val:X8}",
|
||||
WatchDisplayType.FixedPoint_20_12 => $"{(int)val / 4096.0:0.######}",
|
||||
WatchDisplayType.FixedPoint_16_16 => $"{(int)val / 65536.0:0.######}",
|
||||
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()
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using BizHawk.Common.StringExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
|
@ -74,65 +72,15 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
try
|
||||
{
|
||||
ushort val = 0;
|
||||
switch (Type)
|
||||
ushort val = Type switch
|
||||
{
|
||||
case WatchDisplayType.Unsigned:
|
||||
if (value.IsUnsigned())
|
||||
{
|
||||
val = (ushort)int.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Signed:
|
||||
if (value.IsSigned())
|
||||
{
|
||||
val = (ushort)(short)int.Parse(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Hex:
|
||||
if (value.IsHex())
|
||||
{
|
||||
val = (ushort)int.Parse(value, NumberStyles.HexNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Binary:
|
||||
if (value.IsBinary())
|
||||
{
|
||||
val = (ushort)Convert.ToInt32(value, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
if (value.IsFixedPoint())
|
||||
{
|
||||
val = (ushort)(double.Parse(value) * 16.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
|
@ -183,7 +131,7 @@ namespace BizHawk.Client.Common
|
|||
_ when !IsValid => "-",
|
||||
WatchDisplayType.Unsigned => val.ToString(),
|
||||
WatchDisplayType.Signed => ((short) val).ToString(), WatchDisplayType.Hex => $"{val:X4}",
|
||||
WatchDisplayType.FixedPoint_12_4 => $"{val / 16.0:F4}",
|
||||
WatchDisplayType.FixedPoint_12_4 => ((short)val / 16.0).ToString("F4", NumberFormatInfo.InvariantInfo),
|
||||
WatchDisplayType.Binary => Convert
|
||||
.ToString(val, 2)
|
||||
.PadLeft(16, '0')
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using BizHawk.Common.StringExtensions;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
|
@ -27,7 +25,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
set
|
||||
{
|
||||
var changed = _size != value;
|
||||
|
||||
|
||||
_size = value;
|
||||
if (changed)
|
||||
{
|
||||
|
@ -87,17 +85,20 @@ namespace BizHawk.Client.EmuHawk
|
|||
_ => sbyte.MinValue
|
||||
};
|
||||
|
||||
private double Max12_4 => MaxUnsignedInt / 16.0;
|
||||
private const double Max12_4 = short.MaxValue / 16.0;
|
||||
private const double Min12_4 = short.MinValue / 16.0;
|
||||
|
||||
private double Max20_12 => MaxUnsignedInt / 4096.0;
|
||||
private const double Max20_12 = int.MaxValue / 4096.0;
|
||||
private const double Min20_12 = int.MinValue / 4096.0;
|
||||
|
||||
private double Max16_16 => MaxUnsignedInt / 65536.0;
|
||||
private const double Max16_16 = int.MaxValue / 65536.0;
|
||||
private const double Min16_16 = int.MinValue / 65536.0;
|
||||
|
||||
private static double _12_4_Unit => 1 / 16.0;
|
||||
private const double _12_4_Unit = 1 / 16.0;
|
||||
|
||||
private static double _20_12_Unit => 1 / 4096.0;
|
||||
private const double _20_12_Unit = 1 / 4096.0;
|
||||
|
||||
private static double _16_16_Unit => 1 / 65536.0;
|
||||
private const double _16_16_Unit = 1 / 65536.0;
|
||||
|
||||
public override void ResetText()
|
||||
{
|
||||
|
@ -173,88 +174,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
};
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
MaxLength = 9;
|
||||
MaxLength = 10;
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
MaxLength = 21;
|
||||
MaxLength = 40;
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
MaxLength = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnKeyPress(KeyPressEventArgs e)
|
||||
{
|
||||
if (e.KeyChar == '\b' || e.KeyChar == 22 || e.KeyChar == 1 || e.KeyChar == 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.KeyChar == '.')
|
||||
{
|
||||
if (Text.Contains(".") && !SelectedText.Contains("."))
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (e.KeyChar == '-')
|
||||
{
|
||||
if (Text.Contains("-") && !SelectedText.Contains("-"))
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
default:
|
||||
case WatchDisplayType.Binary:
|
||||
if (!e.KeyChar.IsBinary())
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
if (!e.KeyChar.IsFixedPoint())
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
if (!e.KeyChar.IsFloat())
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Hex:
|
||||
if (!e.KeyChar.IsHex())
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Signed:
|
||||
if (!e.KeyChar.IsSigned())
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Unsigned:
|
||||
if (!e.KeyChar.IsUnsigned())
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
MaxLength = 24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -321,47 +248,47 @@ namespace BizHawk.Client.EmuHawk
|
|||
Text = hexVal.ToHexString(MaxLength);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
var f12val = double.Parse(text);
|
||||
var f12val = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (f12val > Max12_4 - _12_4_Unit)
|
||||
{
|
||||
f12val = 0;
|
||||
f12val = Min12_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
f12val += _12_4_Unit;
|
||||
}
|
||||
|
||||
Text = f12val.ToString();
|
||||
Text = f12val.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
var f24val = double.Parse(text);
|
||||
if (f24val >= Max20_12 - _20_12_Unit)
|
||||
var f20val = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (f20val > Max20_12 - _20_12_Unit)
|
||||
{
|
||||
f24val = 0;
|
||||
f20val = Min20_12;
|
||||
}
|
||||
else
|
||||
{
|
||||
f24val += _20_12_Unit;
|
||||
f20val += _20_12_Unit;
|
||||
}
|
||||
|
||||
Text = f24val.ToString();
|
||||
Text = f20val.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
var f16val = double.Parse(text);
|
||||
if (f16val >= Max16_16 - _16_16_Unit)
|
||||
var f16val = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (f16val > Max16_16 - _16_16_Unit)
|
||||
{
|
||||
f16val = 0;
|
||||
f16val = Min16_16;
|
||||
}
|
||||
else
|
||||
{
|
||||
f16val += _16_16_Unit;
|
||||
}
|
||||
|
||||
Text = f16val.ToString();
|
||||
Text = f16val.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
var dVal = double.Parse(text);
|
||||
if (dVal > double.MaxValue - 1)
|
||||
var dVal = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (dVal > float.MaxValue - 1)
|
||||
{
|
||||
dVal = 0;
|
||||
}
|
||||
|
@ -370,7 +297,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
dVal++;
|
||||
}
|
||||
|
||||
Text = dVal.ToString();
|
||||
Text = dVal.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -437,8 +364,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
Text = hexVal.ToHexString(MaxLength);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
var f12val = double.Parse(text);
|
||||
if (f12val < 0 + _12_4_Unit)
|
||||
var f12val = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (f12val < Min12_4 + _12_4_Unit)
|
||||
{
|
||||
f12val = Max12_4;
|
||||
}
|
||||
|
@ -447,24 +374,24 @@ namespace BizHawk.Client.EmuHawk
|
|||
f12val -= _12_4_Unit;
|
||||
}
|
||||
|
||||
Text = f12val.ToString();
|
||||
Text = f12val.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
var f24val = double.Parse(text);
|
||||
if (f24val < 0 + _20_12_Unit)
|
||||
var f20val = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (f20val < Min20_12 + _20_12_Unit)
|
||||
{
|
||||
f24val = Max20_12;
|
||||
f20val = Max20_12;
|
||||
}
|
||||
else
|
||||
{
|
||||
f24val -= _20_12_Unit;
|
||||
f20val -= _20_12_Unit;
|
||||
}
|
||||
|
||||
Text = f24val.ToString();
|
||||
Text = f20val.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
var f16val = double.Parse(text);
|
||||
if (f16val < 0 + _16_16_Unit)
|
||||
var f16val = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (f16val < Min16_16 + _16_16_Unit)
|
||||
{
|
||||
f16val = Max16_16;
|
||||
}
|
||||
|
@ -473,11 +400,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
f16val -= _16_16_Unit;
|
||||
}
|
||||
|
||||
Text = f16val.ToString();
|
||||
Text = f16val.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
var dval = double.Parse(text);
|
||||
if (dval > double.MaxValue - 1)
|
||||
var dval = double.Parse(text, NumberFormatInfo.InvariantInfo);
|
||||
if (dval < float.MinValue + 1)
|
||||
{
|
||||
dval = 0;
|
||||
}
|
||||
|
@ -486,7 +413,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
dval--;
|
||||
}
|
||||
|
||||
Text = dval.ToString();
|
||||
Text = dval.ToString(NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -505,113 +432,32 @@ namespace BizHawk.Client.EmuHawk
|
|||
return;
|
||||
}
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
case WatchDisplayType.Signed:
|
||||
Text = Text.OnlySigned();
|
||||
break;
|
||||
case WatchDisplayType.Unsigned:
|
||||
Text = Text.OnlyUnsigned();
|
||||
break;
|
||||
case WatchDisplayType.Binary:
|
||||
Text = Text.OnlyBinary();
|
||||
break;
|
||||
case WatchDisplayType.Hex:
|
||||
Text = Text.OnlyHex();
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
Text = Text.OnlyFixedPoint();
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
Text = Text.OnlyFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
base.OnTextChanged(e);
|
||||
}
|
||||
|
||||
public int? ToRawInt()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Text))
|
||||
try
|
||||
{
|
||||
if (Nullable)
|
||||
return _type switch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return 0;
|
||||
WatchDisplayType.Signed => int.Parse(Text),
|
||||
WatchDisplayType.Unsigned => (int)uint.Parse(Text),
|
||||
WatchDisplayType.Binary => Convert.ToInt32(Text, 2),
|
||||
WatchDisplayType.Hex => int.Parse(Text, NumberStyles.HexNumber),
|
||||
WatchDisplayType.FixedPoint_12_4 => (int)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 16.0),
|
||||
WatchDisplayType.FixedPoint_20_12 => (int)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 4096.0),
|
||||
WatchDisplayType.FixedPoint_16_16 => (int)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 65536.0),
|
||||
WatchDisplayType.Float => BitConverter.ToInt32(BitConverter.GetBytes(float.Parse(Text, NumberFormatInfo.InvariantInfo)), 0),
|
||||
_ => int.Parse(Text)
|
||||
};
|
||||
}
|
||||
|
||||
switch (_type)
|
||||
catch
|
||||
{
|
||||
case WatchDisplayType.Signed:
|
||||
if (Text.IsSigned())
|
||||
{
|
||||
return Text == "-" ? 0 : int.Parse(Text);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Unsigned:
|
||||
if (Text.IsUnsigned())
|
||||
{
|
||||
return (int)uint.Parse(Text);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Binary:
|
||||
if (Text.IsBinary())
|
||||
{
|
||||
return Convert.ToInt32(Text, 2);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Hex:
|
||||
if (Text.IsHex())
|
||||
{
|
||||
return int.Parse(Text, NumberStyles.HexNumber);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
if (Text.IsFixedPoint())
|
||||
{
|
||||
return (int)(double.Parse(Text) * 16.0);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
if (Text.IsFixedPoint())
|
||||
{
|
||||
return (int)(double.Parse(Text) * 4096.0);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
if (Text.IsFixedPoint())
|
||||
{
|
||||
return (int)(double.Parse(Text) * 65536.0);
|
||||
}
|
||||
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
if (Text.IsFloat())
|
||||
{
|
||||
if (Text == "-" || Text == ".")
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float val = float.Parse(Text);
|
||||
var bytes = BitConverter.GetBytes(val);
|
||||
return BitConverter.ToInt32(bytes, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
// ignored
|
||||
}
|
||||
|
||||
return 0;
|
||||
return Nullable ? null : 0;
|
||||
}
|
||||
|
||||
public void SetFromRawInt(int? val)
|
||||
|
@ -637,18 +483,18 @@ namespace BizHawk.Client.EmuHawk
|
|||
Text = val.Value.ToHexString(MaxLength);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_12_4:
|
||||
Text = $"{val.Value / 16.0:F5}";
|
||||
Text = (val.Value / 16.0).ToString("F5", NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_20_12:
|
||||
Text = $"{val.Value / 4096.0:F5}";
|
||||
Text = (val.Value / 4096.0).ToString("F5", NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.FixedPoint_16_16:
|
||||
Text = $"{val.Value / 65536.0:F5}";
|
||||
Text = (val.Value / 65536.0).ToString("F5", NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
case WatchDisplayType.Float:
|
||||
var bytes = BitConverter.GetBytes(val.Value);
|
||||
float _float = BitConverter.ToSingle(bytes, 0);
|
||||
Text = $"{_float:F6}";
|
||||
Text = _float.ToString("F6", NumberFormatInfo.InvariantInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Common.StringExtensions
|
||||
{
|
||||
|
@ -13,26 +12,6 @@ namespace BizHawk.Common.StringExtensions
|
|||
/// <remarks><paramref name="str"/> should exclude the prefix <c>0b</c></remarks>
|
||||
public static bool IsBinary(this string? str) => !string.IsNullOrWhiteSpace(str) && str.All(IsBinary);
|
||||
|
||||
/// <returns><see langword="true"/> iff <paramref name="c"/> is <c>'.'</c> or a digit</returns>
|
||||
/// <remarks>Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be <c>IsUnsignedDecimal</c>.</remarks>
|
||||
public static bool IsFixedPoint(this char c) => IsUnsigned(c) || c == '.';
|
||||
|
||||
/// <returns>
|
||||
/// <see langword="true"/> iff <paramref name="str"/> is not <see langword="null"/>,<br/>
|
||||
/// all chars of <paramref name="str"/> are <c>'.'</c> or a digit, and<br/>
|
||||
/// <paramref name="str"/> contains at most <c>1</c> decimal separator <c>'.'</c>
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <paramref name="str"/> should exclude the suffix <c>M</c>.<br/>
|
||||
/// This method returning <see langword="true"/> for some <paramref name="str"/> does not imply that <see cref="float.TryParse(string,out float)">float.TryParse</see> will also return <see langword="true"/>.<br/>
|
||||
/// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be <c>IsUnsignedDecimal</c>.
|
||||
/// </remarks>
|
||||
public static bool IsFixedPoint(this string? str) => !string.IsNullOrWhiteSpace(str) && str.Count(c => c == '.') <= 1 && str.All(IsFixedPoint);
|
||||
|
||||
/// <returns><see langword="true"/> iff <paramref name="c"/> is <c>'-'</c>, <c>'.'</c>, or a digit</returns>
|
||||
/// <remarks>Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be <c>IsSignedDecimal</c>.</remarks>
|
||||
public static bool IsFloat(this char c) => c.IsFixedPoint() || c == '-';
|
||||
|
||||
/// <returns><see langword="true"/> iff <paramref name="c"/> is a hex digit (<c>[0-9A-Fa-f]</c>)</returns>
|
||||
public static bool IsHex(this char c) => IsUnsigned(c) || 'A' <= char.ToUpperInvariant(c) && char.ToUpperInvariant(c) <= 'F';
|
||||
|
||||
|
@ -46,128 +25,13 @@ namespace BizHawk.Common.StringExtensions
|
|||
/// <returns><see langword="true"/> iff <paramref name="c"/> is a digit</returns>
|
||||
public static bool IsUnsigned(this char c) => char.IsDigit(c);
|
||||
|
||||
/// <returns><see langword="true"/> iff <paramref name="str"/> is not <see langword="null"/> and all chars of <paramref name="str"/> are digits</returns>
|
||||
public static bool IsUnsigned(this string? str) => !string.IsNullOrWhiteSpace(str) && str.All(IsUnsigned);
|
||||
|
||||
/// <returns>
|
||||
/// A copy of <paramref name="raw"/> with characters removed so that the whole thing passes <see cref="IsBinary(string?)">IsBinary</see>.<br/>
|
||||
/// That is, all chars of the copy will be either <c>'0'</c> or <c>'1'</c>.
|
||||
/// </returns>
|
||||
public static string OnlyBinary(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsBinary));
|
||||
|
||||
/// <returns>
|
||||
/// A copy of <paramref name="raw"/> with characters removed so that the whole thing passes <see cref="IsHex(string?)">IsHex</see>.<br/>
|
||||
/// That is, all chars of the copy will be hex digits (<c>[0-9A-F]</c>).
|
||||
/// </returns>
|
||||
public static string OnlyHex(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsHex)).ToUpperInvariant();
|
||||
|
||||
/// <returns>
|
||||
/// A copy of <paramref name="raw"/> with characters removed so that the whole thing passes <see cref="IsUnsigned(string?)">IsUnsigned</see>.<br/>
|
||||
/// That is, all chars of the copy will be digits.
|
||||
/// </returns>
|
||||
public static string OnlyUnsigned(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsUnsigned));
|
||||
|
||||
#pragma warning disable CS8602
|
||||
|
||||
/// <returns>
|
||||
/// <see langword="true"/> iff <paramref name="str"/> is not <see langword="null"/>,<br/>
|
||||
/// the first char of <paramref name="str"/> is <c>'-'</c>, <c>'.'</c>, or a digit,<br/>
|
||||
/// all subsequent chars of <paramref name="str"/> are <c>'.'</c> or a digit, and<br/>
|
||||
/// <paramref name="str"/> contains at most <c>1</c> decimal separator <c>'.'</c>
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <paramref name="str"/> should exclude the suffix <c>f</c>.<br/>
|
||||
/// This method returning <see langword="true"/> for some <paramref name="str"/> does not imply that <see cref="float.TryParse(string,out float)">float.TryParse</see> will also return <see langword="true"/>.<br/>
|
||||
/// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be <c>IsSignedDecimal</c>.
|
||||
/// </remarks>
|
||||
public static bool IsFloat(this string? str) => !string.IsNullOrWhiteSpace(str) && str.Count(c => c == '.') <= 1 && str[0].IsFloat() && str.Substring(1).All(IsFixedPoint);
|
||||
|
||||
/// <returns>
|
||||
/// <see langword="true"/> iff <paramref name="str"/> is not <see langword="null"/>,
|
||||
/// the first char of <paramref name="str"/> is <c>'-'</c> or a digit, and
|
||||
/// all subsequent chars of <paramref name="str"/> are digits
|
||||
/// </returns>
|
||||
public static bool IsSigned(this string? str) => !string.IsNullOrWhiteSpace(str) && str[0].IsSigned() && str.Substring(1).All(IsUnsigned);
|
||||
|
||||
/// <returns>
|
||||
/// A copy of <paramref name="raw"/> with characters removed so that the whole thing passes <see cref="IsFixedPoint(string?)">IsFixedPoint</see>.<br/>
|
||||
/// That is, the all chars of the copy will be <c>'.'</c> or a digit and the copy will contain at most <c>1</c> decimal separator <c>'.'</c>.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The returned value may not be parseable by <see cref="float.TryParse(string,out float)">float.TryParse</see>.<br/>
|
||||
/// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be <c>IsUnsignedDecimal</c>.
|
||||
/// </remarks>
|
||||
public static string OnlyFixedPoint(this string? raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw)) return string.Empty;
|
||||
var output = new StringBuilder();
|
||||
var usedDot = false;
|
||||
foreach (var chr in raw)
|
||||
{
|
||||
if (chr == '.')
|
||||
{
|
||||
if (usedDot) continue;
|
||||
output.Append(chr);
|
||||
usedDot = true;
|
||||
}
|
||||
else if (chr.IsUnsigned()) output.Append(chr);
|
||||
}
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A copy of <paramref name="raw"/> with characters removed so that the whole thing passes <see cref="IsFloat(string?)">IsFloat</see>.<br/>
|
||||
/// That is, the first char of the copy will be <c>'-'</c>, <c>'.'</c>, or a digit,<br/>
|
||||
/// all subsequent chars of the copy will be <c>'.'</c> or a digit, and<br/>
|
||||
/// the copy will contain at most <c>1</c> decimal separator <c>'.'</c>.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// If <paramref name="raw"/> contains a serialized negative decimal, it must be at the start (<paramref name="raw"/><c>[0] == '-'</c>) or the sign will be dropped.<br/>
|
||||
/// The returned value may not be parseable by <see cref="float.TryParse(string,out float)">float.TryParse</see>.<br/>
|
||||
/// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be <c>IsSignedDecimal</c>.
|
||||
/// </remarks>
|
||||
public static string OnlyFloat(this string? raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw)) return string.Empty;
|
||||
|
||||
var output = new StringBuilder();
|
||||
var usedDot = false;
|
||||
|
||||
var first = raw[0];
|
||||
if (first.IsFloat())
|
||||
{
|
||||
output.Append(first);
|
||||
if (first == '.') usedDot = true;
|
||||
}
|
||||
|
||||
for (int i = 1, l = raw.Length; i < l; i++)
|
||||
{
|
||||
var chr = raw[i];
|
||||
if (chr == '.')
|
||||
{
|
||||
if (usedDot) continue;
|
||||
output.Append(chr);
|
||||
usedDot = true;
|
||||
}
|
||||
else if (chr.IsUnsigned()) output.Append(chr);
|
||||
}
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// A copy of <paramref name="raw"/> with characters removed so that the whole thing passes <see cref="IsSigned(string?)">IsSigned</see>.<br/>
|
||||
/// That is, the first char of the copy will be <c>'-'</c> or a digit, and all subsequent chars of the copy will be digits.
|
||||
/// </returns>
|
||||
/// <remarks>If <paramref name="raw"/> contains a serialized negative integer, it must be at the start (<paramref name="raw"/><c>[0] == '-'</c>) or the sign will be dropped.</remarks>
|
||||
public static string OnlySigned(this string? raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw)) return string.Empty;
|
||||
return raw[0].IsSigned()
|
||||
? raw[0] + string.Concat(raw.Skip(1).Where(IsUnsigned))
|
||||
: string.Concat(raw.Skip(1).Where(IsUnsigned));
|
||||
}
|
||||
|
||||
#pragma warning restore CS8602
|
||||
/// <returns><see langword="true"/> iff <paramref name="str"/> is not <see langword="null"/> and all chars of <paramref name="str"/> are digits</returns>
|
||||
public static bool IsUnsigned(this string? str) => !string.IsNullOrWhiteSpace(str) && str.All(IsUnsigned);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue