diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs index 5d8dae2e..270f98e0 100644 --- a/SabreTools.Library/DatFiles/DatFile.cs +++ b/SabreTools.Library/DatFiles/DatFile.cs @@ -1902,16 +1902,7 @@ namespace SabreTools.Library.DatFiles Rom rom = item as Rom; // If we have the case where there is SHA-1 and nothing else, we don't fill in any other part of the data - if (rom.Size == null - && string.IsNullOrWhiteSpace(rom.CRC) - && string.IsNullOrWhiteSpace(rom.MD5) -#if NET_FRAMEWORK - && string.IsNullOrWhiteSpace(rom.RIPEMD160) -#endif - && !string.IsNullOrWhiteSpace(rom.SHA1) - && string.IsNullOrWhiteSpace(rom.SHA256) - && string.IsNullOrWhiteSpace(rom.SHA384) - && string.IsNullOrWhiteSpace(rom.SHA512)) + if (rom.Size == null && !rom.HasHashes()) { // No-op, just catch it so it doesn't go further Globals.Logger.Verbose($"{Header.FileName}: Entry with only SHA-1 found - '{rom.Name}'"); @@ -1919,15 +1910,7 @@ namespace SabreTools.Library.DatFiles // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info else if ((rom.Size == 0 || rom.Size == null) - && ((rom.CRC == Constants.CRCZero || string.IsNullOrWhiteSpace(rom.CRC)) - || rom.MD5 == Constants.MD5Zero -#if NET_FRAMEWORK - || rom.RIPEMD160 == Constants.RIPEMD160Zero -#endif - || rom.SHA1 == Constants.SHA1Zero - || rom.SHA256 == Constants.SHA256Zero - || rom.SHA384 == Constants.SHA384Zero - || rom.SHA512 == Constants.SHA512Zero)) + && (string.IsNullOrWhiteSpace(rom.CRC) || rom.HasZeroHash())) { // TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually rom.Size = Constants.SizeZero; @@ -1940,6 +1923,7 @@ namespace SabreTools.Library.DatFiles rom.SHA256 = null; // Constants.SHA256Zero; rom.SHA384 = null; // Constants.SHA384Zero; rom.SHA512 = null; // Constants.SHA512Zero; + rom.SpamSum = null; // Constants.SpamSumZero; } // If the file has no size and it's not the above case, skip and log @@ -1951,17 +1935,8 @@ namespace SabreTools.Library.DatFiles // If the file has a size but aboslutely no hashes, skip and log else if (rom.ItemStatus != ItemStatus.Nodump - && rom.Size != null - && rom.Size > 0 - && string.IsNullOrWhiteSpace(rom.CRC) - && string.IsNullOrWhiteSpace(rom.MD5) -#if NET_FRAMEWORK - && string.IsNullOrWhiteSpace(rom.RIPEMD160) -#endif - && string.IsNullOrWhiteSpace(rom.SHA1) - && string.IsNullOrWhiteSpace(rom.SHA256) - && string.IsNullOrWhiteSpace(rom.SHA384) - && string.IsNullOrWhiteSpace(rom.SHA512)) + && rom.Size != null && rom.Size > 0 + && !rom.HasHashes()) { Globals.Logger.Verbose($"{Header.FileName}: Incomplete entry for '{rom.Name}' will be output as nodump"); rom.ItemStatus = ItemStatus.Nodump; @@ -3746,6 +3721,7 @@ namespace SabreTools.Library.DatFiles rom.SHA256 = rom.SHA256 == "null" ? Constants.SHA256Zero : null; rom.SHA384 = rom.SHA384 == "null" ? Constants.SHA384Zero : null; rom.SHA512 = rom.SHA512 == "null" ? Constants.SHA512Zero : null; + rom.SpamSum = rom.SpamSum == "null" ? Constants.SpamSumZero : null; } return rom; diff --git a/SabreTools.Library/DatItems/DatItem.cs b/SabreTools.Library/DatItems/DatItem.cs index a6d89e97..50508050 100644 --- a/SabreTools.Library/DatItems/DatItem.cs +++ b/SabreTools.Library/DatItems/DatItem.cs @@ -818,7 +818,7 @@ namespace SabreTools.Library.DatItems break; case Field.DatItem_SpamSum: - key = null; + key = Constants.SpamSumZero; break; } diff --git a/SabreTools.Library/DatItems/Rom.cs b/SabreTools.Library/DatItems/Rom.cs index 83d5e2fe..cd4a6696 100644 --- a/SabreTools.Library/DatItems/Rom.cs +++ b/SabreTools.Library/DatItems/Rom.cs @@ -685,6 +685,42 @@ namespace SabreTools.Library.DatItems return "_1"; } + /// + /// Returns if the Rom contains any hashes + /// + /// True if any hash exists, false otherwise + public bool HasHashes() + { + return !_crc.IsNullOrEmpty() + || !_md5.IsNullOrEmpty() +#if NET_FRAMEWORK + || !_ripemd160.IsNullOrEmpty() +#endif + || !_sha1.IsNullOrEmpty() + || !_sha256.IsNullOrEmpty() + || !_sha384.IsNullOrEmpty() + || !_sha512.IsNullOrEmpty() + || !_spamsum.IsNullOrEmpty(); + } + + /// + /// Returns if all of the hashes are set to their 0-byte values + /// + /// True if any hash matches the 0-byte value, false otherwise + public bool HasZeroHash() + { + return (_crc != null && _crc.SequenceEqual(Constants.CRCZeroBytes)) + || (_md5 != null && _md5.SequenceEqual(Constants.MD5ZeroBytes)) +#if NET_FRAMEWORK + || (_ripemd160 != null && _ripemd160.SequenceEqual(Constants.RIPEMD160ZeroBytes)) +#endif + || (_sha1 != null && _sha1.SequenceEqual(Constants.SHA1ZeroBytes)) + || (_sha256 != null && _sha256.SequenceEqual(Constants.SHA256ZeroBytes)) + || (_sha384 != null && _sha384.SequenceEqual(Constants.SHA384ZeroBytes)) + || (_sha512 != null && _sha512.SequenceEqual(Constants.SHA512ZeroBytes)) + || (_spamsum != null && _spamsum.SequenceEqual(Constants.SpamSumZeroBytes)); + } + /// /// Returns if there are no, non-empty hashes in common with another Rom /// @@ -704,24 +740,6 @@ namespace SabreTools.Library.DatItems || !(_spamsum.IsNullOrEmpty() ^ other._spamsum.IsNullOrEmpty()); } - /// - /// Returns if the Rom contains any hashes - /// - /// True if any hash exists, false otherwise - private bool HasHashes() - { - return !_crc.IsNullOrEmpty() - || !_md5.IsNullOrEmpty() -#if NET_FRAMEWORK - || !_ripemd160.IsNullOrEmpty() -#endif - || !_sha1.IsNullOrEmpty() - || !_sha256.IsNullOrEmpty() - || !_sha384.IsNullOrEmpty() - || !_sha512.IsNullOrEmpty() - || !_spamsum.IsNullOrEmpty(); - } - /// /// Returns if any hashes are common with another Rom /// diff --git a/SabreTools.Library/Data/Constants.cs b/SabreTools.Library/Data/Constants.cs index 4201fe0e..6b07eb2e 100644 --- a/SabreTools.Library/Data/Constants.cs +++ b/SabreTools.Library/Data/Constants.cs @@ -79,6 +79,8 @@ namespace SabreTools.Library.Data 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }; + public const string SpamSumZero = "QXX"; + public static readonly byte[] SpamSumZeroBytes = { 0x51, 0x58, 0x58 }; #endregion diff --git a/SabreTools.Library/External/Aaru/SpamSumContext.cs b/SabreTools.Library/External/Aaru/SpamSumContext.cs index 5df4671e..cd4eb26a 100644 --- a/SabreTools.Library/External/Aaru/SpamSumContext.cs +++ b/SabreTools.Library/External/Aaru/SpamSumContext.cs @@ -109,7 +109,12 @@ namespace Aaru.Checksums /// /// Returns a byte array of the hash value. - public byte[] Final() => throw new NotImplementedException("SpamSum does not have a binary representation."); + public byte[] Final() + { + FuzzyDigest(out byte[] result); + + return CToArray(result); + } /// /// Returns a base64 representation of the hash value. @@ -485,6 +490,25 @@ namespace Aaru.Checksums return Encoding.ASCII.GetString(cString, 0, count); } + // Converts an ASCII null-terminated string to .NET string + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static byte[] CToArray(byte[] cString) + { + int count = 0; + + // ReSharper disable once LoopCanBeConvertedToQuery + // LINQ is six times slower + foreach (byte c in cString) + { + if (c == 0) + break; + + count++; + } + + return new ReadOnlySpan(cString, 0, count).ToArray(); + } + public void Dispose() { // TODO: No-op to dispose for now