diff --git a/src/BizHawk.Common/checksums/CRC32.cs b/src/BizHawk.Common/checksums/CRC32.cs index afe8b65d94..14756a8e2f 100644 --- a/src/BizHawk.Common/checksums/CRC32.cs +++ b/src/BizHawk.Common/checksums/CRC32.cs @@ -17,10 +17,32 @@ namespace BizHawk.Common private static readonly uint[] COMBINER_INIT_STATE; + private static readonly uint[]? CRC32Table; + static CRC32() { // for Add (CRC32 computation): - _calcCRC = Marshal.GetDelegateForFunctionPointer(LibBizHash.BizCalcCrcFunc()); + if (RuntimeInformation.ProcessArchitecture == Architecture.X64) + { + _calcCRC = Marshal.GetDelegateForFunctionPointer(LibBizHash.BizCalcCrcFunc()); + } + else + { + CRC32Table = new uint[256]; + for (var i = 0U; i < 256U; i++) + { + var crc = i; + for (var j = 0; j < 8; j++) + { + var xor = (crc & 1U) == 1U; + crc >>= 1; + if (xor) crc ^= POLYNOMIAL_CONST; + } + CRC32Table[i] = crc; + } + + _calcCRC = CrcFuncAnyCpu; + } // for Incorporate: var combinerState = (COMBINER_INIT_STATE = new uint[64]).AsSpan(); @@ -43,6 +65,16 @@ namespace BizHawk.Common return crc32.Result; } + public static unsafe uint CrcFuncAnyCpu(uint current, IntPtr buffer, int len) + { + for (var i = 0; i < len; i++) + { + current = CRC32Table[(current ^ ((byte*)buffer)[i]) & 0xFF] ^ (current >> 8); + } + + return current; + } + private static void gf2_matrix_square(Span square, ReadOnlySpan mat) { if (mat.Length != square.Length) throw new ArgumentException(message: "must be same length as " + nameof(square), paramName: nameof(mat)); @@ -76,7 +108,7 @@ namespace BizHawk.Common public unsafe void Add(ReadOnlySpan data) { - fixed (byte* d = &data.GetPinnableReference()) + fixed (byte* d = data) { _current = _calcCRC(_current, (IntPtr) d, data.Length); } diff --git a/src/BizHawk.Common/checksums/SHA1Checksum.cs b/src/BizHawk.Common/checksums/SHA1Checksum.cs index 471bc5f67f..00920f3549 100644 --- a/src/BizHawk.Common/checksums/SHA1Checksum.cs +++ b/src/BizHawk.Common/checksums/SHA1Checksum.cs @@ -64,14 +64,16 @@ namespace BizHawk.Common } } + private static readonly bool UseUnmanagedImpl = RuntimeInformation.ProcessArchitecture == Architecture.X64 && LibBizHash.BizSupportsShaInstructions(); + public static byte[] Compute(byte[] data) - => LibBizHash.BizSupportsShaInstructions() + => UseUnmanagedImpl ? UnmanagedImpl(data) : SHA1Impl.ComputeHash(data); public static byte[] ComputeConcat(byte[] dataA, byte[] dataB) { - if (LibBizHash.BizSupportsShaInstructions()) return UnmanagedImpl(dataA.ConcatArray(dataB)); + if (UseUnmanagedImpl) return UnmanagedImpl(dataA.ConcatArray(dataB)); using var impl = IncrementalHash.CreateHash(HashAlgorithmName.SHA1); impl.AppendData(dataA); impl.AppendData(dataB);