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;