diff --git a/Dist/git_hook_shim.sh b/Dist/git_hook_shim.sh index 6ad95f267d7..102fc9b662a 100755 --- a/Dist/git_hook_shim.sh +++ b/Dist/git_hook_shim.sh @@ -1,8 +1,12 @@ #!/bin/sh -set -e +kind="$(basename "$0")" pwsh="$(command -v pwsh)" if [ -z "$pwsh" ]; then pwsh="$(command -v dotnet) pwsh"; fi -if ! ("$pwsh" -v >/dev/null 2>/dev/null); then exit 0; fi -kind="$(basename "$0")" -"$pwsh" "./Dist/git_hooks/$kind.ps1" "$@" -if [ -e "./Dist/git_hooks/$kind.local.ps1" ]; then "$pwsh" "./Dist/git_hooks/$kind.local.ps1" "$@"; fi +if ! ("$pwsh" -v >/dev/null 2>/dev/null); then + printf "pwsh not found in PATH; skipping %s hook\n" "$kind" + exit 0 +fi +if [ -e "./Dist/git_hooks/$kind.ps1" ]; then + "$pwsh" "./Dist/git_hooks/$kind.ps1" "$@" || exit $? + if [ -e "./Dist/git_hooks/$kind.local.ps1" ]; then "$pwsh" "./Dist/git_hooks/$kind.local.ps1" "$@" || exit $?; fi +fi diff --git a/Dist/install_git_hooks.ps1 b/Dist/install_git_hooks.ps1 index 82ebc335b9c..370bc20171d 100755 --- a/Dist/install_git_hooks.ps1 +++ b/Dist/install_git_hooks.ps1 @@ -12,7 +12,7 @@ if (Test-Path $targetDir -PathType Container) { # is Git repo #TODO use symlinks on Linux } elseif ((Get-FileHash $target).Hash -ne $shimChecksum) { # files differ $head = Get-Content $target -TotalCount 3 - echo "[$PSCommandFilename] found existing Git hook $hook, please resolve conflict manually" + echo "[$PSCommandFilename] found existing Git hook $hook, please resolve conflict manually (ignore if checking out older commits)" exit 1 } # else no-op diff --git a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs index 5ce463ff57e..22e3ef1efaf 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs @@ -3,6 +3,7 @@ using System.Linq; using BizHawk.Common; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -287,7 +288,7 @@ public float ReadFloat(long addr, string domain = null) LogCallback($"Warning: Attempted read {addr} outside memory size of {d.Size}"); return default; } - return BitConverter.ToSingle(BitConverter.GetBytes(d.PeekUint(addr, _isBigEndian)), 0); + return NumberExtensions.ReinterpretAsF32(d.PeekUint(addr, _isBigEndian)); } public void WriteFloat(long addr, double value, string domain = null) @@ -303,7 +304,7 @@ public void WriteFloat(long addr, double value, string domain = null) LogCallback($"Warning: Attempted write {addr} outside memory size of {d.Size}"); return; } - d.PokeUint(addr, BitConverter.ToUInt32(BitConverter.GetBytes((float) value), 0), _isBigEndian); + d.PokeUint(addr, NumberExtensions.ReinterpretAsUInt32((float) value), _isBigEndian); } public int ReadS8(long addr, string domain = null) => (sbyte) ReadUnsigned(addr, 1, domain); diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs index 33a37a2c939..05162aa1572 100644 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs +++ b/src/BizHawk.Client.Common/tools/RamSearchEngine/IMiniWatch.cs @@ -8,8 +8,8 @@ namespace BizHawk.Client.Common.RamSearchEngine internal interface IMiniWatch { long Address { get; } - long Previous { get; } // do not store sign extended variables in here. - long Current { get; } + uint Previous { get; } + uint Current { get; } int ChangeCount { get; } void ClearChangeCount(); void SetPreviousToCurrent(); @@ -35,8 +35,8 @@ public void SetPreviousToCurrent() _previous = _current; } - public long Previous => _previous; - public long Current => _current; + public uint Previous => _previous; + public uint Current => _current; public int ChangeCount { get; private set; } @@ -87,8 +87,8 @@ public void SetPreviousToCurrent() _previous = _current; } - public long Previous => _previous; - public long Current => _current; + public uint Previous => _previous; + public uint Current => _current; public int ChangeCount { get; private set; } @@ -139,8 +139,8 @@ public void SetPreviousToCurrent() _previous = _current; } - public long Previous => _previous; - public long Current => _current; + public uint Previous => _previous; + public uint Current => _current; public int ChangeCount { get; private set; } diff --git a/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs b/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs index 5e4d0ebe806..6a762d877b5 100644 --- a/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs +++ b/src/BizHawk.Client.Common/tools/RamSearchEngine/RamSearchEngine.cs @@ -1,24 +1,17 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using BizHawk.Common; using BizHawk.Common.CollectionExtensions; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; +using static BizHawk.Common.NumberExtensions.NumberExtensions; -// ReSharper disable PossibleInvalidCastExceptionInForeachLoop namespace BizHawk.Client.Common.RamSearchEngine { public class RamSearchEngine { - /// TODO move to BizHawk.Common - private static float ReinterpretAsF32(long l) - { - return Unsafe.As(ref l); - } - private Compare _compareTo = Compare.Previous; private IMiniWatch[] _watchList = [ ]; @@ -39,7 +32,7 @@ public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomai }; } - public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains, Compare compareTo, long? compareValue, int? differentBy) + public RamSearchEngine(SearchEngineSettings settings, IMemoryDomains memoryDomains, Compare compareTo, uint? compareValue, uint? differentBy) : this(settings, memoryDomains) { _compareTo = compareTo; @@ -157,7 +150,7 @@ public Compare CompareTo } } - public long? CompareValue { get; set; } + public uint? CompareValue { get; set; } public ComparisonOperator Operator { get; set; } @@ -165,7 +158,7 @@ public Compare CompareTo /// zero 07-sep-2014 - this isn't ideal. but don't bother changing it (to a long, for instance) until it can support floats. maybe store it as a double here.
/// it already supported floats by way of reinterpret-cast, it just wasn't implemented correctly on this side --yoshi /// - public int? DifferentBy { get; set; } + public uint? DifferentBy { get; set; } public void Update(bool updatePrevious) { @@ -319,7 +312,7 @@ private IEnumerable ComparePrevious(IEnumerable watchLis case ComparisonOperator.LessThanEqual: return watchList.Where(w => SignExtendAsNeeded(w.Current) <= SignExtendAsNeeded(w.Previous)); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); return watchList.Where(w => differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous))); } @@ -350,7 +343,7 @@ private IEnumerable ComparePrevious(IEnumerable watchLis return val < prev || val.HawkFloatEquality(prev); }); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); var differentByF = ReinterpretAsF32(differentBy); return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous)) .HawkFloatEquality(differentByF)); @@ -359,7 +352,7 @@ private IEnumerable ComparePrevious(IEnumerable watchLis private IEnumerable CompareSpecificValue(IEnumerable watchList) { - if (CompareValue is not long compareValue) throw new InvalidOperationException(); + if (CompareValue is not uint compareValue) throw new InvalidOperationException(); if (_settings.Type is not WatchDisplayType.Float) { switch (Operator) @@ -378,7 +371,7 @@ private IEnumerable CompareSpecificValue(IEnumerable wat case ComparisonOperator.LessThanEqual: return watchList.Where(w => SignExtendAsNeeded(w.Current) <= SignExtendAsNeeded(compareValue)); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); return watchList.Where(w => differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(compareValue))); } @@ -408,7 +401,7 @@ private IEnumerable CompareSpecificValue(IEnumerable wat return val < compareValueF || val.HawkFloatEquality(compareValueF); }); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); var differentByF = ReinterpretAsF32(differentBy); return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - compareValueF) .HawkFloatEquality(differentByF)); @@ -417,7 +410,7 @@ private IEnumerable CompareSpecificValue(IEnumerable wat private IEnumerable CompareSpecificAddress(IEnumerable watchList) { - if (CompareValue is not long compareValue) throw new InvalidOperationException(); + if (CompareValue is not uint compareValue) throw new InvalidOperationException(); switch (Operator) { default: @@ -434,14 +427,14 @@ private IEnumerable CompareSpecificAddress(IEnumerable w case ComparisonOperator.LessThanEqual: return watchList.Where(w => w.Address <= compareValue); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); return watchList.Where(w => Math.Abs(w.Address - compareValue) == differentBy); } } private IEnumerable CompareChanges(IEnumerable watchList) { - if (CompareValue is not long compareValue) throw new InvalidOperationException(); + if (CompareValue is not uint compareValue) throw new InvalidOperationException(); switch (Operator) { default: @@ -458,14 +451,14 @@ private IEnumerable CompareChanges(IEnumerable watchList case ComparisonOperator.LessThanEqual: return watchList.Where(w => w.ChangeCount <= compareValue); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); return watchList.Where(w => Math.Abs(w.ChangeCount - compareValue) == differentBy); } } private IEnumerable CompareDifference(IEnumerable watchList) { - if (CompareValue is not long compareValue) throw new InvalidCastException(); //TODO typo for IOE? + if (CompareValue is not uint compareValue) throw new InvalidCastException(); //TODO typo for IOE? if (_settings.Type is not WatchDisplayType.Float) { switch (Operator) @@ -484,9 +477,9 @@ private IEnumerable CompareDifference(IEnumerable watchL case ComparisonOperator.LessThanEqual: return watchList.Where(w => SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) <= compareValue); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); return watchList.Where(w => - differentBy == Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous) - compareValue)); + differentBy == Math.Abs(Math.Abs(SignExtendAsNeeded(w.Current) - SignExtendAsNeeded(w.Previous)) - compareValue)); } } var compareValueF = ReinterpretAsF32(compareValue); @@ -514,7 +507,7 @@ private IEnumerable CompareDifference(IEnumerable watchL return diff < compareValueF || diff.HawkFloatEquality(compareValueF); }); case ComparisonOperator.DifferentBy: - if (DifferentBy is not int differentBy) throw new InvalidOperationException(); + if (DifferentBy is not uint differentBy) throw new InvalidOperationException(); var differentByF = ReinterpretAsF32(differentBy); return watchList.Where(w => Math.Abs(ReinterpretAsF32(w.Current) - ReinterpretAsF32(w.Previous) - compareValueF) .HawkFloatEquality(differentByF)); diff --git a/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs b/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs index 6c9645ba5e2..bc5f4df3a77 100644 --- a/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs +++ b/src/BizHawk.Client.Common/tools/Watch/DWordWatch.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.Common @@ -84,7 +85,7 @@ public override bool Poke(string 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), + WatchDisplayType.Float => NumberExtensions.ReinterpretAsUInt32(float.Parse(value, NumberFormatInfo.InvariantInfo)), _ => 0 }; @@ -133,8 +134,7 @@ public string FormatValue(uint val) { string FormatFloat() { - var bytes = BitConverter.GetBytes(val); - var _float = BitConverter.ToSingle(bytes, 0); + var _float = NumberExtensions.ReinterpretAsF32(val); return _float.ToString(NumberFormatInfo.InvariantInfo); } diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs b/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs index 7196a110b8f..f1c313c0b81 100644 --- a/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs +++ b/src/BizHawk.Client.EmuHawk/CustomControls/HexTextBox.cs @@ -11,8 +11,8 @@ namespace BizHawk.Client.EmuHawk public interface INumberBox { bool Nullable { get; } - int? ToRawInt(); - void SetFromRawInt(int? rawInt); + uint? ToRawUInt(); + void SetFromRawUInt(uint? rawUInt); } public class HexTextBox : ClipboardEventTextBox, INumberBox @@ -86,7 +86,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex() && !string.IsNullOrEmpty(_addressFormatStr)) { - var val = (uint)ToRawInt(); + var val = ToRawUInt(); if (val == GetMax()) { @@ -104,7 +104,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex() && !string.IsNullOrEmpty(_addressFormatStr)) { - var val = (uint)ToRawInt(); + var val = ToRawUInt(); if (val == 0) { val = (uint)GetMax(); // int to long todo @@ -147,7 +147,7 @@ protected override void OnPaste(PasteEventArgs e) base.OnPaste(e); } - public int? ToRawInt() + public uint? ToRawUInt() { if (string.IsNullOrWhiteSpace(Text)) { @@ -159,10 +159,10 @@ protected override void OnPaste(PasteEventArgs e) return 0; } - return int.Parse(Text, NumberStyles.HexNumber); + return uint.Parse(Text, NumberStyles.HexNumber); } - public void SetFromRawInt(int? val) + public void SetFromRawUInt(uint? val) { Text = val.HasValue ? string.Format(_addressFormatStr, val) : ""; } @@ -231,7 +231,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex()) { - var val = (uint)ToRawInt(); + var val = ToRawUInt().Value; if (val == uint.MaxValue) { val = 0; @@ -248,7 +248,7 @@ protected override void OnKeyDown(KeyEventArgs e) { if (Text.IsHex()) { - var val = (uint)ToRawInt(); + var val = ToRawUInt().Value; if (val == 0) { @@ -280,7 +280,7 @@ protected override void OnTextChanged(EventArgs e) base.OnTextChanged(e); } - public int? ToRawInt() + public uint? ToRawUInt() { if (string.IsNullOrWhiteSpace(Text) || !Text.IsHex()) { @@ -292,10 +292,10 @@ protected override void OnTextChanged(EventArgs e) return 0; } - return (int)uint.Parse(Text); + return uint.Parse(Text); } - public void SetFromRawInt(int? val) + public void SetFromRawUInt(uint? val) { Text = val?.ToString() ?? ""; } diff --git a/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs b/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs index 93440700ea7..df93e2ba480 100644 --- a/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs +++ b/src/BizHawk.Client.EmuHawk/movie/PlayMovie.cs @@ -594,7 +594,7 @@ private void Ok_Click(object sender, EventArgs e) if (StopOnFrameCheckbox.Checked) { if (LastFrameCheckbox.Checked) _mainForm.PauseOnFrame = _movieSession.Movie.InputLogLength; - else if (StopOnFrameTextBox.ToRawInt() is int i) _mainForm.PauseOnFrame = i; + else if (StopOnFrameTextBox.ToRawUInt() is uint i) _mainForm.PauseOnFrame = (int)i; } Close(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs b/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs index 8f1e470b1d3..19081fe1276 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs @@ -94,7 +94,7 @@ private void SetFormToCheat() CheckFormState(); if (!_cheat.Compare.HasValue) { - CompareBox.Text = ""; // Necessary hack until WatchValueBox.ToRawInt() becomes nullable + CompareBox.Text = ""; // Necessary hack until WatchValueBox.ToRawUInt() becomes nullable } _loading = false; @@ -133,7 +133,7 @@ private void SetFormToDefault() SetTypeSelected(WatchDisplayType.Hex); CheckFormState(); - CompareBox.Text = ""; // TODO: A needed hack until WatchValueBox.ToRawInt() becomes nullable + CompareBox.Text = ""; // TODO: A needed hack until WatchValueBox.ToRawUInt() becomes nullable _loading = false; } @@ -311,7 +311,7 @@ public void ClearForm() public Cheat GetCheat() { var domain = MemoryDomains[DomainDropDown.SelectedItem.ToString()]!; - var address = AddressBox.ToRawInt().Value; + var address = AddressBox.ToRawUInt().Value; if (address < domain.Size) { var watch = Watch.GenerateWatch( @@ -334,11 +334,11 @@ public Cheat GetCheat() _ => Cheat.CompareType.None }; - var compare = CompareBox.ToRawInt(); + var compare = CompareBox.ToRawUInt(); return new Cheat( watch, - value: ValueBox.ToRawInt().Value, - compare: compare, + value: (int)ValueBox.ToRawUInt().Value, + compare: (int?)compare, enabled: true, comparisonType); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs index eec013cd2a0..c07c02b039e 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/AddBreakpointDialog.cs @@ -101,13 +101,13 @@ public MemoryCallbackType BreakType public uint Address { - get => (uint)AddressBox.ToRawInt().Value & AddressMask; + get => AddressBox.ToRawUInt().Value & AddressMask; set => AddressBox.SetFromLong(value & AddressMask); } public uint AddressMask { - get => (uint)AddressMaskBox.ToRawInt().Value; + get => AddressMaskBox.ToRawUInt().Value; set => AddressMaskBox.SetFromLong(value); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs index 2b4b3fba8e3..172fc491b42 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Debugger/GenericDebugger.cs @@ -119,7 +119,7 @@ Control GenCPUPicker() var pc = PCRegister; SeekToBox.Nullable = false; SeekToBox.SetHexProperties((long)Math.Pow(2, pc.BitSize)); - SeekToBox.SetFromRawInt(0); + SeekToBox.SetFromRawUInt(0); } else { @@ -264,7 +264,7 @@ public void DisableCancelSeekBtn() private void SeekToBtn_Click(object sender, EventArgs e) { CancelSeekBtn.Enabled = true; - var pcVal = (uint)(SeekToBox.ToRawInt() ?? 0); + var pcVal = SeekToBox.ToRawUInt() ?? 0; var pcBitSize = PCRegister.BitSize; BreakPointControl1.RemoveCurrentSeek(); diff --git a/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs b/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs index 25127ef6d06..84f3b75e038 100644 --- a/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs +++ b/src/BizHawk.Client.EmuHawk/tools/TAStudio/FramesPrompt.cs @@ -18,7 +18,7 @@ public FramesPrompt(string headMessage, string bodyMessage) this.label1.Text = bodyMessage; } - public int Frames => NumFramesBox.ToRawInt() ?? 0; + public int Frames => (int)(NumFramesBox.ToRawUInt() ?? 0); private void FramesPrompt_Load(object sender, EventArgs e) { diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs index a5be0de254c..a017384500f 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs @@ -422,7 +422,7 @@ private void ToggleSearchDependentToolBarItems() WatchListView.AnyRowsSelected && _searches.Domain.Writable; } - private long? CompareToValue + private uint? CompareToValue { get { @@ -433,29 +433,29 @@ private long? CompareToValue if (SpecificValueRadio.Checked) { - return (long)SpecificValueBox.ToRawInt() & 0x00000000FFFFFFFF; + return SpecificValueBox.ToRawUInt(); } if (SpecificAddressRadio.Checked) { - return SpecificAddressBox.ToRawInt(); + return SpecificAddressBox.ToRawUInt(); } if (NumberOfChangesRadio.Checked) { - return NumberOfChangesBox.ToRawInt(); + return NumberOfChangesBox.ToRawUInt(); } if (DifferenceRadio.Checked) { - return DifferenceBox.ToRawInt(); + return DifferenceBox.ToRawUInt(); } return null; } } - private int? DifferentByValue => DifferentByRadio.Checked ? DifferentByBox.ToRawInt() : null; + private uint? DifferentByValue => DifferentByRadio.Checked ? DifferentByBox.ToRawUInt() : null; private ComparisonOperator Operator { @@ -738,7 +738,7 @@ private void SetCompareTo(Compare comp) WatchListView.Refresh(); } - private void SetCompareValue(int? value) + private void SetCompareValue(uint? value) { _searches.CompareValue = value; WatchListView.Refresh(); @@ -1446,7 +1446,7 @@ private void SpecificValueRadio_Click(object sender, EventArgs e) SpecificAddressBox.ResetText(); } - _searches.CompareValue = SpecificValueBox.ToRawInt(); + _searches.CompareValue = SpecificValueBox.ToRawUInt(); if (Focused) { @@ -1468,7 +1468,7 @@ private void SpecificAddressRadio_Click(object sender, EventArgs e) SpecificAddressBox.ResetText(); } - _searches.CompareValue = SpecificAddressBox.ToRawInt(); + _searches.CompareValue = SpecificAddressBox.ToRawUInt(); if (Focused) { @@ -1490,7 +1490,7 @@ private void NumberOfChangesRadio_Click(object sender, EventArgs e) NumberOfChangesBox.ResetText(); } - _searches.CompareValue = NumberOfChangesBox.ToRawInt(); + _searches.CompareValue = NumberOfChangesBox.ToRawUInt(); if (Focused) { @@ -1512,7 +1512,7 @@ private void DifferenceRadio_Click(object sender, EventArgs e) DifferenceBox.ResetText(); } - _searches.CompareValue = DifferenceBox.ToRawInt(); + _searches.CompareValue = DifferenceBox.ToRawUInt(); if (Focused) { @@ -1524,7 +1524,7 @@ private void DifferenceRadio_Click(object sender, EventArgs e) private void CompareToValue_TextChanged(object sender, EventArgs e) { - SetCompareValue(((INumberBox)sender).ToRawInt()); + SetCompareValue(((INumberBox)sender).ToRawUInt()); } private void EqualToRadio_Click(object sender, EventArgs e) @@ -1572,7 +1572,7 @@ private void DifferentByRadio_Click(object sender, EventArgs e) DifferentByBox.ResetText(); } - _searches.DifferentBy = DifferenceBox.ToRawInt(); + _searches.DifferentBy = DifferenceBox.ToRawUInt(); if (Focused) { @@ -1584,7 +1584,7 @@ private void DifferentByRadio_Click(object sender, EventArgs e) private void DifferentByBox_TextChanged(object sender, EventArgs e) { - _searches.DifferentBy = !string.IsNullOrWhiteSpace(DifferentByBox.Text) ? DifferentByBox.ToRawInt() : null; + _searches.DifferentBy = !string.IsNullOrWhiteSpace(DifferentByBox.Text) ? DifferentByBox.ToRawUInt() : null; WatchListView.Refresh(); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs index 7b20ab3490d..316485c51fd 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs @@ -276,7 +276,7 @@ private void DoEdit() Watches[i] = Watch.GenerateWatch( Watches[i].Domain, - Watches.Count == 1 ? AddressBox.ToRawInt() ?? 0 : Watches[i].Address, + Watches.Count == 1 ? AddressBox.ToRawUInt() ?? 0 : Watches[i].Address, size, _changedDisplayType ? displayType : Watches[i].Type, Watches[i].BigEndian, diff --git a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs index 79263daff92..0566345dd99 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Watch/WatchValueBox.cs @@ -56,10 +56,10 @@ public WatchDisplayType Type get => _type; set { - var val = ToRawInt(); + var val = ToRawUInt(); _type = value; SetMaxLength(); - SetFromRawInt(val); + SetFromRawUInt(val); } } @@ -197,7 +197,7 @@ protected override void OnKeyDown(KeyEventArgs e) { default: case WatchDisplayType.Signed: - int val = ToRawInt() ?? 0; + int val = (int)(ToRawUInt() ?? 0); if (val == MaxSignedInt) { val = MinSignedInt; @@ -210,7 +210,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = val.ToString(); break; case WatchDisplayType.Unsigned: - var uval = (uint)(ToRawInt() ?? 0); + var uval = ToRawUInt() ?? 0; if (uval == MaxUnsignedInt) { uval = 0; @@ -223,7 +223,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = uval.ToString(); break; case WatchDisplayType.Binary: - var bVal = (uint)(ToRawInt() ?? 0); + var bVal = ToRawUInt() ?? 0; if (bVal == MaxUnsignedInt) { bVal = 0; @@ -237,7 +237,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = Convert.ToString(bVal, 2).PadLeft(numBits, '0'); break; case WatchDisplayType.Hex: - var hexVal = (uint)(ToRawInt() ?? 0); + var hexVal = ToRawUInt() ?? 0; if (hexVal == MaxUnsignedInt) { hexVal = 0; @@ -309,7 +309,7 @@ protected override void OnKeyDown(KeyEventArgs e) { default: case WatchDisplayType.Signed: - int val = ToRawInt() ?? 0; + int val = (int)(ToRawUInt() ?? 0); if (val == MinSignedInt) { val = MaxSignedInt; @@ -322,7 +322,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = val.ToString(); break; case WatchDisplayType.Unsigned: - var uval = (uint)(ToRawInt() ?? 0); + var uval = ToRawUInt() ?? 0; if (uval == 0) { uval = MaxUnsignedInt; @@ -335,7 +335,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = uval.ToString(); break; case WatchDisplayType.Binary: - var bVal = (uint)(ToRawInt() ?? 0); + var bVal = ToRawUInt() ?? 0; if (bVal == 0) { bVal = MaxUnsignedInt; @@ -349,7 +349,7 @@ protected override void OnKeyDown(KeyEventArgs e) Text = Convert.ToString(bVal, 2).PadLeft(numBits, '0'); break; case WatchDisplayType.Hex: - var hexVal = (uint)(ToRawInt() ?? 0); + var hexVal = ToRawUInt() ?? 0; if (hexVal == 0) { hexVal = MaxUnsignedInt; @@ -445,21 +445,21 @@ protected override void OnPaste(PasteEventArgs e) base.OnPaste(e); } - public int? ToRawInt() + public uint? ToRawUInt() { try { return _type switch { - 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) + WatchDisplayType.Signed => (uint)int.Parse(Text), + WatchDisplayType.Unsigned => uint.Parse(Text), + WatchDisplayType.Binary => Convert.ToUInt32(Text, 2), + WatchDisplayType.Hex => uint.Parse(Text, NumberStyles.HexNumber), + WatchDisplayType.FixedPoint_12_4 => (uint)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 16.0), + WatchDisplayType.FixedPoint_20_12 => (uint)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 4096.0), + WatchDisplayType.FixedPoint_16_16 => (uint)(double.Parse(Text, NumberFormatInfo.InvariantInfo) * 65536.0), + WatchDisplayType.Float => NumberExtensions.ReinterpretAsUInt32(float.Parse(Text, NumberFormatInfo.InvariantInfo)), + _ => uint.Parse(Text) }; } catch @@ -470,7 +470,7 @@ protected override void OnPaste(PasteEventArgs e) return Nullable ? null : 0; } - public void SetFromRawInt(int? val) + public void SetFromRawUInt(uint? val) { if (val.HasValue) { @@ -481,11 +481,11 @@ public void SetFromRawInt(int? val) Text = val.Value.ToString(); break; case WatchDisplayType.Unsigned: - var uval = (uint)val.Value; + var uval = val.Value; Text = uval.ToString(); break; case WatchDisplayType.Binary: - var bVal = (uint)val.Value; + var bVal = val.Value; var numBits = ((int)ByteSize) * 8; Text = Convert.ToString(bVal, 2).PadLeft(numBits, '0'); break; @@ -502,8 +502,7 @@ public void SetFromRawInt(int? val) 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); + float _float = NumberExtensions.ReinterpretAsF32(val.Value); Text = _float.ToString("F6", NumberFormatInfo.InvariantInfo); break; } diff --git a/src/BizHawk.Common/Extensions/NumberExtensions.cs b/src/BizHawk.Common/Extensions/NumberExtensions.cs index 204e723489c..237d002bd48 100644 --- a/src/BizHawk.Common/Extensions/NumberExtensions.cs +++ b/src/BizHawk.Common/Extensions/NumberExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Runtime.CompilerServices; namespace BizHawk.Common.NumberExtensions { @@ -144,5 +145,11 @@ public static void RotateRightU8(ref byte b, int shift) /// don't use this in cores without picking a suitable ε public static bool HawkFloatEquality(this float f, float other, float ε = ReallySmallNumber) => Math.Abs(other - f) < ε; + + /// Reinterprets the byte representation of as a float + public static float ReinterpretAsF32(uint value) => Unsafe.As(ref value); + + /// Reinterprets the byte representation of as a uint + public static uint ReinterpretAsUInt32(float value) => Unsafe.As(ref value); } } diff --git a/src/BizHawk.Tests/Common/ConversionTests.cs b/src/BizHawk.Tests/Common/ConversionTests.cs index e4f17db3fbd..527b29bcfa2 100644 --- a/src/BizHawk.Tests/Common/ConversionTests.cs +++ b/src/BizHawk.Tests/Common/ConversionTests.cs @@ -1,41 +1,25 @@ -using System; -using System.Buffers.Binary; -using System.Runtime.CompilerServices; +using BizHawk.Common.NumberExtensions; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BizHawk.Tests.Common; -// test for RamSearchEngine.ReinterpretAsF32 [TestClass] public class ConversionTests { - private static float ReinterpretAsF32Unsafe(long l) + [TestMethod] + [DataRow(0U, 0)] + [DataRow(1U, 1.401298E-45F)] + [DataRow(1109917696U, 42)] + [DataRow(1123477881U, 123.456F)] + [DataRow(3212836864U, -1)] + public void TestReinterpretAsF32(uint input, float expected) { - return Unsafe.As(ref l); - } + float converted = NumberExtensions.ReinterpretAsF32(input); - private static readonly byte[] ScratchSpace = new byte[8]; + Assert.AreEqual(expected, converted); - private static float ReinterpretAsF32BitConverter(long l) - { - BinaryPrimitives.WriteInt64LittleEndian(ScratchSpace, l); - return BitConverter.ToSingle(ScratchSpace, startIndex: 0); - } - - [TestMethod] - [DoNotParallelize] // old implementation is not thread safe - [DataRow(0, 0)] - [DataRow(1, 1.401298E-45F)] - [DataRow(1109917696, 42)] - [DataRow(1123477881, 123.456F)] - [DataRow(3212836864, -1)] - [DataRow(0x7fffffffbf800000, -1)] - public void TestReinterpretAsF32(long input, float expected) - { - float f32BitConverter = ReinterpretAsF32BitConverter(input); - float f32Unsafe = ReinterpretAsF32Unsafe(input); + uint restoredInput = NumberExtensions.ReinterpretAsUInt32(converted); - Assert.AreEqual(expected, f32BitConverter); - Assert.AreEqual(expected, f32Unsafe); + Assert.AreEqual(input, restoredInput); } }