diff --git a/Saves/SAV6.cs b/Saves/SAV6.cs index 65a472183..da76600a5 100644 --- a/Saves/SAV6.cs +++ b/Saves/SAV6.cs @@ -102,8 +102,39 @@ protected override void setChecksums() BitConverter.GetBytes(SaveUtil.ccitt16(array)).CopyTo(Data, BlockInfoOffset + 6 + i * 8); } } - public override bool ChecksumsValid => SaveUtil.verifyG6SAV(Data); - public override string ChecksumInfo => SaveUtil.verifyG6CHK(Data); + public override bool ChecksumsValid + { + get + { + for (int i = 0; i < Blocks.Length; i++) + { + byte[] array = Data.Skip(Blocks[i].Offset).Take(Blocks[i].Length).ToArray(); + if (SaveUtil.ccitt16(array) != BitConverter.ToUInt16(Data, BlockInfoOffset + 6 + i * 8)) + return false; + } + return true; + } + } + public override string ChecksumInfo + { + get + { + int invalid = 0; + string rv = ""; + for (int i = 0; i < Blocks.Length; i++) + { + byte[] array = Data.Skip(Blocks[i].Offset).Take(Blocks[i].Length).ToArray(); + if (SaveUtil.ccitt16(array) == BitConverter.ToUInt16(Data, BlockInfoOffset + 6 + i * 8)) + continue; + + invalid++; + rv += $"Invalid: {i.ToString("X2")} @ Region {Blocks[i].Offset.ToString("X5") + Environment.NewLine}"; + } + // Return Outputs + rv += $"SAV: {Blocks.Length - invalid}/{Blocks.Length + Environment.NewLine}"; + return rv; + } + } public ulong Secure1 { get { return BitConverter.ToUInt64(Data, BlockInfoOffset - 0x14); } diff --git a/Saves/SaveUtil.cs b/Saves/SaveUtil.cs index 12d8f07af..34a84e58f 100644 --- a/Saves/SaveUtil.cs +++ b/Saves/SaveUtil.cs @@ -212,134 +212,6 @@ public static ushort ccitt16(byte[] data) } return crc; } - /// Simple check to see if the save is valid. - /// Input binary file - /// True/False - public static bool verifyG6SAV(byte[] savefile) - { - // Dynamic handling of checksums regardless of save size. - - int verificationOffset = savefile.Length - 0x200 + 0x10; - if (BitConverter.ToUInt32(savefile, verificationOffset) != BEEF) - verificationOffset -= 0x200; // No savegames have more than 0x3D blocks, maybe in the future? - - int count = (savefile.Length - verificationOffset - 0x8) / 8; - verificationOffset += 4; - int[] Lengths = new int[count]; - ushort[] BlockIDs = new ushort[count]; - ushort[] Checksums = new ushort[count]; - int[] Start = new int[count]; - int CurrentPosition = 0; - for (int i = 0; i < count; i++) - { - Start[i] = CurrentPosition; - Lengths[i] = BitConverter.ToInt32(savefile, verificationOffset + 0 + 8 * i); - BlockIDs[i] = BitConverter.ToUInt16(savefile, verificationOffset + 4 + 8 * i); - Checksums[i] = BitConverter.ToUInt16(savefile, verificationOffset + 6 + 8 * i); - - CurrentPosition += Lengths[i] % 0x200 == 0 ? Lengths[i] : 0x200 - Lengths[i] % 0x200 + Lengths[i]; - - if ((BlockIDs[i] != 0) || i == 0) continue; - count = i; - break; - } - // Verify checksums - for (int i = 0; i < count; i++) - { - ushort chk = ccitt16(savefile.Skip(Start[i]).Take(Lengths[i]).ToArray()); - ushort old = BitConverter.ToUInt16(savefile, verificationOffset + 6 + i * 8); - - if (chk != old) - return false; - } - return true; - } - /// Verbose check to see if the save is valid. - /// Input binary file - /// String containing invalid blocks. - public static string verifyG6CHK(byte[] savefile) - { - string rv = ""; - int invalid = 0; - // Dynamic handling of checksums regardless of save size. - - int verificationOffset = savefile.Length - 0x200 + 0x10; - if (BitConverter.ToUInt32(savefile, verificationOffset) != BEEF) - verificationOffset -= 0x200; // No savegames have more than 0x3D blocks, maybe in the future? - - int count = (savefile.Length - verificationOffset - 0x8) / 8; - verificationOffset += 4; - int[] Lengths = new int[count]; - ushort[] BlockIDs = new ushort[count]; - ushort[] Checksums = new ushort[count]; - int[] Start = new int[count]; - int CurrentPosition = 0; - for (int i = 0; i < count; i++) - { - Start[i] = CurrentPosition; - Lengths[i] = BitConverter.ToInt32(savefile, verificationOffset + 0 + 8 * i); - BlockIDs[i] = BitConverter.ToUInt16(savefile, verificationOffset + 4 + 8 * i); - Checksums[i] = BitConverter.ToUInt16(savefile, verificationOffset + 6 + 8 * i); - - CurrentPosition += Lengths[i] % 0x200 == 0 ? Lengths[i] : 0x200 - Lengths[i] % 0x200 + Lengths[i]; - - if (BlockIDs[i] != 0 || i == 0) continue; - count = i; - break; - } - // Apply checksums - for (int i = 0; i < count; i++) - { - ushort chk = ccitt16(savefile.Skip(Start[i]).Take(Lengths[i]).ToArray()); - ushort old = BitConverter.ToUInt16(savefile, verificationOffset + 6 + i * 8); - - if (chk == old) continue; - - invalid++; - rv += $"Invalid: {i.ToString("X2")} @ Region {Start[i].ToString("X5") + Environment.NewLine}"; - } - // Return Outputs - rv += $"SAV: {count - invalid}/{count + Environment.NewLine}"; - return rv; - } - /// Fix checksums in the input save file. - /// Input binary file - /// Fixed save file. - public static void writeG6CHK(byte[] savefile) - { - // Dynamic handling of checksums regardless of save size. - - int verificationOffset = savefile.Length - 0x200 + 0x10; - if (BitConverter.ToUInt32(savefile, verificationOffset) != BEEF) - verificationOffset -= 0x200; // No savegames have more than 0x3D blocks, maybe in the future? - - int count = (savefile.Length - verificationOffset - 0x8) / 8; - verificationOffset += 4; - int[] Lengths = new int[count]; - ushort[] BlockIDs = new ushort[count]; - ushort[] Checksums = new ushort[count]; - int[] Start = new int[count]; - int CurrentPosition = 0; - for (int i = 0; i < count; i++) - { - Start[i] = CurrentPosition; - Lengths[i] = BitConverter.ToInt32(savefile, verificationOffset + 0 + 8 * i); - BlockIDs[i] = BitConverter.ToUInt16(savefile, verificationOffset + 4 + 8 * i); - Checksums[i] = BitConverter.ToUInt16(savefile, verificationOffset + 6 + 8 * i); - - CurrentPosition += Lengths[i] % 0x200 == 0 ? Lengths[i] : 0x200 - Lengths[i] % 0x200 + Lengths[i]; - - if (BlockIDs[i] != 0 || i == 0) continue; - count = i; - break; - } - // Apply checksums - for (int i = 0; i < count; i++) - { - byte[] array = savefile.Skip(Start[i]).Take(Lengths[i]).ToArray(); - BitConverter.GetBytes(ccitt16(array)).CopyTo(savefile, verificationOffset + 6 + i * 8); - } - } /// Calculates the 32bit checksum over an input byte array. Used in GBA save files. /// Input byte array /// Checksum