From b9fdaf5109e93275ff19206dcd660ac4e8707d89 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 4 Oct 2015 16:56:47 -0700 Subject: [PATCH] Add save->bool (valid) & documentation --- Misc/PKX.cs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/Misc/PKX.cs b/Misc/PKX.cs index 03cb46612..2afa12333 100644 --- a/Misc/PKX.cs +++ b/Misc/PKX.cs @@ -692,6 +692,9 @@ public SaveGame(string GameID) #endregion // SAV Manipulation + /// Calculates the CRC16-CCITT checksum. + /// Input byte array + /// Checksum internal static ushort ccitt16(byte[] data) { ushort crc = 0xFFFF; @@ -708,6 +711,51 @@ internal static ushort ccitt16(byte[] data) } return crc; } + /// Simple check to see if the save is valid. + /// Input binary file + /// True/False + internal static bool verifyG6SAV(byte[] savefile) + { + // Dynamic handling of checksums regardless of save size. + + int verificationOffset = savefile.Length - 0x200 + 0x10; + if (BitConverter.ToUInt32(savefile, verificationOffset) != 0x42454546) + 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. internal static string verifyG6CHK(byte[] savefile) { string rv = ""; @@ -753,6 +801,9 @@ internal static string verifyG6CHK(byte[] savefile) rv += String.Format("SAV: {0}/{1}", (count - invalid), count + Environment.NewLine); return rv; } + /// Fix checksums in the input save file. + /// Input binary file + /// Fixed save file. internal static void writeG6CHK(byte[] savefile) { // Dynamic handling of checksums regardless of save size. @@ -1246,11 +1297,9 @@ internal static string[] getFormList(int species, string[] t, string[] f, string return new[] {""}; } - /// - /// Calculate the Hidden Power Type of the entered IVs. - /// - /// HP/ATK/DEF/SPEED/SPA/SPD - /// + /// Calculate the Hidden Power Type of the entered IVs. + /// Order: HP,ATK,DEF,SPEED,SPA,SPD + /// Hidden Power Type internal static int getHPType(int[] ivs) { return (15 * ((ivs[0] & 1) + 2 * (ivs[1] & 1) + 4 * (ivs[2] & 1) + 8 * (ivs[3] & 1) + 16 * (ivs[4] & 1) + 32 * (ivs[5] & 1))) / 63;