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