Deduplicate some logic

No need to length check in the SwishCrypto hash check, as the methods pre-check length as well.
Extract checksum footer check for Gen5 saves
This commit is contained in:
Kurt
2022-03-05 17:14:25 -08:00
parent 1f07685921
commit 8fdd96209c
3 changed files with 16 additions and 26 deletions

View File

@@ -203,6 +203,10 @@ public static SCBlock ReadFromOffset(ReadOnlySpan<byte> data, ref int offset)
}
}
/// <summary>
/// Merges the properties from <see cref="other"/> into this object.
/// </summary>
/// <param name="other">Block to copy all values from.</param>
public void CopyFrom(SCBlock other)
{
if (Type.IsBoolean())

View File

@@ -82,24 +82,6 @@ private static byte[] ComputeHash(byte[] data)
/// <returns>True if hash matches</returns>
public static bool GetIsHashValid(byte[] data)
{
if (!SaveUtil.SizesSWSH.Contains(data.Length))
return false;
var hash = ComputeHash(data);
var span = data.AsSpan()[^hash.Length..];
return span.SequenceEqual(hash);
}
/// <summary>
/// Checks if the file is a rough example of a save file.
/// </summary>
/// <param name="data">Encrypted save data</param>
/// <returns>True if hash matches</returns>
public static bool GetIsHashValidLA(byte[] data)
{
if (data.Length is not (SaveUtil.SIZE_G8LA or SaveUtil.SIZE_G8LA_1))
return false;
var hash = ComputeHash(data);
var span = data.AsSpan()[^hash.Length..];
return span.SequenceEqual(hash);

View File

@@ -428,16 +428,20 @@ private static GameVersion GetIsG5SAV(ReadOnlySpan<byte> data)
if (data.Length != SIZE_G5RAW)
return Invalid;
// check the checksum block validity; nobody would normally modify this region
ushort chk1 = ReadUInt16LittleEndian(data[(SIZE_G5BW - 0x100 + 0x8C + 0xE)..]);
ushort actual1 = Checksums.CRC16_CCITT(data.Slice(SIZE_G5BW - 0x100, 0x8C));
if (chk1 == actual1)
// check the checksum footer block validity; nobody would normally modify this region
if (IsValidFooter(data, SIZE_G5BW, 0x8C))
return BW;
ushort chk2 = ReadUInt16LittleEndian(data[(SIZE_G5B2W2 - 0x100 + 0x94 + 0xE)..]);
ushort actual2 = Checksums.CRC16_CCITT(data.Slice(SIZE_G5B2W2 - 0x100, 0x94));
if (chk2 == actual2)
if (IsValidFooter(data, SIZE_G5B2W2, 0x94))
return B2W2;
return Invalid;
static bool IsValidFooter(ReadOnlySpan<byte> data, int mainSize, int infoLength)
{
var footer = data.Slice(mainSize - 0x100, infoLength + 0x10);
ushort stored = ReadUInt16LittleEndian(footer[^2..]);
ushort actual = Checksums.CRC16_CCITT(footer[..infoLength]);
return stored == actual;
}
}
/// <summary>Checks to see if the data belongs to a Gen6 save</summary>
@@ -514,7 +518,7 @@ private static GameVersion GetIsG8SAV_LA(byte[] data)
if (data.Length is not (SIZE_G8LA or SIZE_G8LA_1))
return Invalid;
return SwishCrypto.GetIsHashValidLA(data) ? PLA : Invalid;
return SwishCrypto.GetIsHashValid(data) ? PLA : Invalid;
}
private static bool GetIsBank7(ReadOnlySpan<byte> data) => data.Length == SIZE_G7BANK && data[0] != 0;