From 2e4c75aca3c51bd42041f59599197e2fae6d0f31 Mon Sep 17 00:00:00 2001 From: Eskuero Date: Sun, 5 Jun 2016 19:49:20 +0100 Subject: [PATCH 1/4] Fix third gen balls on second gen starters with HA Second generation starters are legal with third generation introduced balls because you can catch their second stage on Pokemon Colosseum, but since back then Hidden Abilities didn't exist they're restricted to normal balls only. Other balls are checked already but this ones weren't flagged as illegal. --- Legality/Checks.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Legality/Checks.cs b/Legality/Checks.cs index 3b924e242..577bf5bd2 100644 --- a/Legality/Checks.cs +++ b/Legality/Checks.cs @@ -553,6 +553,8 @@ private LegalityCheck verifyBall() { if (Legal.Ban_Gen3Ball.Contains(pk6.Species)) return new LegalityCheck(Severity.Invalid, "Unobtainable capture for Gen4 Ball."); + if (pk6.AbilityNumber == 4 && 152 <= pk6.Species && pk6.Species <= 160) + return new LegalityCheck(Severity.Invalid, "Ball not possible for species with hidden ability."); return new LegalityCheck(Severity.Valid, "Obtainable capture for Gen4 Ball."); } From a0fb281ced636425e0095b70da8fc377a3be07d4 Mon Sep 17 00:00:00 2001 From: chenzw95 Date: Fri, 10 Jun 2016 15:43:39 +0800 Subject: [PATCH 2/4] Move WC6 OT memory checks from verifyHistory to verifyOTMemory --- Legality/Checks.cs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Legality/Checks.cs b/Legality/Checks.cs index 577bf5bd2..4aa70f9c9 100644 --- a/Legality/Checks.cs +++ b/Legality/Checks.cs @@ -576,14 +576,6 @@ private LegalityCheck verifyHistory() return new LegalityCheck(Severity.Invalid, "Event OT Affection should be zero."); if (pk6.CurrentHandler != 1) return new LegalityCheck(Severity.Invalid, "Current handler should not be Event OT."); - if (pk6.OT_Memory != MatchedWC6.OT_Memory) - return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_Memory == 0 ? "should not have an OT Memory" : "OT Memory should be index " + MatchedWC6.OT_Memory) + "."); - if (pk6.OT_Intensity != MatchedWC6.OT_Intensity) - return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_Intensity == 0 ? "should not have an OT Memory Intensity value" : "OT Memory Intensity should be index " + MatchedWC6.OT_Intensity) + "."); - if (pk6.OT_TextVar != MatchedWC6.OT_TextVar) - return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_TextVar == 0 ? "should not have an OT Memory TextVar value" : "OT Memory TextVar should be index " + MatchedWC6.OT_TextVar) + "."); - if (pk6.OT_Feeling != MatchedWC6.OT_Feeling) - return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_Feeling == 0 ? "should not have an OT Memory Feeling value" : "OT Memory Feeling should be index " + MatchedWC6.OT_Feeling) + "."); } if (!pk6.WasEvent && !(pk6.WasLink && (EncounterMatch as EncounterLink)?.OT == false) && (pk6.HT_Name.Length == 0 || pk6.Geo1_Country == 0)) // Is not Traded { @@ -691,10 +683,15 @@ private LegalityCheck verifyOTMemory() } if (EncounterType == typeof(WC6)) { - if (pk6.OT_Memory != 0) - return new LegalityCheck(Severity.Invalid, "Event Pokémon should not have an OT memory."); - - return new LegalityCheck(Severity.Valid, "OT Memory (Event) is valid."); + WC6 MatchedWC6 = EncounterMatch as WC6; + if (pk6.OT_Memory != MatchedWC6.OT_Memory) + return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_Memory == 0 ? "should not have an OT Memory" : "OT Memory should be index " + MatchedWC6.OT_Memory) + "."); + if (pk6.OT_Intensity != MatchedWC6.OT_Intensity) + return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_Intensity == 0 ? "should not have an OT Memory Intensity value" : "OT Memory Intensity should be index " + MatchedWC6.OT_Intensity) + "."); + if (pk6.OT_TextVar != MatchedWC6.OT_TextVar) + return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_TextVar == 0 ? "should not have an OT Memory TextVar value" : "OT Memory TextVar should be index " + MatchedWC6.OT_TextVar) + "."); + if (pk6.OT_Feeling != MatchedWC6.OT_Feeling) + return new LegalityCheck(Severity.Invalid, "Event " + (MatchedWC6.OT_Feeling == 0 ? "should not have an OT Memory Feeling value" : "OT Memory Feeling should be index " + MatchedWC6.OT_Feeling) + "."); } switch (pk6.OT_Memory) { From 52ff97191ab707016802a30f1f0d1cb40c7769d4 Mon Sep 17 00:00:00 2001 From: chenzw95 Date: Fri, 10 Jun 2016 15:44:25 +0800 Subject: [PATCH 3/4] Clarify History vs Memory check in legality output --- Legality/Checks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Legality/Checks.cs b/Legality/Checks.cs index 4aa70f9c9..31443de14 100644 --- a/Legality/Checks.cs +++ b/Legality/Checks.cs @@ -565,7 +565,7 @@ private LegalityCheck verifyBall() private LegalityCheck verifyHistory() { if (!Encounter.Valid) - return new LegalityCheck(Severity.Valid, "Skipped Memory check due to other check being invalid."); + return new LegalityCheck(Severity.Valid, "Skipped History check due to other check being invalid."); WC6 MatchedWC6 = EncounterMatch as WC6; if (MatchedWC6?.OT.Length > 0) // Has Event OT -- null propagation yields false if MatchedWC6=null From 1bf70d99a39be371142f22c9b1d70d838f7eedc3 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 14 Jun 2016 15:31:33 -0700 Subject: [PATCH 4/4] Preliminary Gen V Checksum Support --- Misc/SAV5.cs | 1080 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1074 insertions(+), 6 deletions(-) diff --git a/Misc/SAV5.cs b/Misc/SAV5.cs index 7f29c58f2..ca94e4705 100644 --- a/Misc/SAV5.cs +++ b/Misc/SAV5.cs @@ -3,20 +3,27 @@ namespace PKHeX { + public class BlockInfo5 + { + public int Offset; + public int Length; + public int ChecksumOffset; + public int ChecksumMirror; + } public class SAV5 : PKM { internal const int SIZERAW = 0x80000; // 512KB - internal const int SIZE1 = 0x24000; // B/W - internal const int SIZE2 = 0x26000; // B2/W2 + internal const int SIZE_BW = 0x24000; // B/W + internal const int SIZE_B2W2 = 0x26000; // B2/W2 internal static int getIsG5SAV(byte[] data) { - ushort chk1 = BitConverter.ToUInt16(data, SIZE1 - 0x100 + 0x8C + 0xE); - ushort actual1 = ccitt16(data.Skip(SIZE1 - 0x100).Take(0x8C).ToArray()); + ushort chk1 = BitConverter.ToUInt16(data, SIZE_BW - 0x100 + 0x8C + 0xE); + ushort actual1 = ccitt16(data.Skip(SIZE_BW - 0x100).Take(0x8C).ToArray()); if (chk1 == actual1) return 0; - ushort chk2 = BitConverter.ToUInt16(data, SIZE2 - 0x100 + 0x94 + 0xE); - ushort actual2 = ccitt16(data.Skip(SIZE2 - 0x100).Take(0x94).ToArray()); + ushort chk2 = BitConverter.ToUInt16(data, SIZE_B2W2 - 0x100 + 0x94 + 0xE); + ushort actual2 = ccitt16(data.Skip(SIZE_B2W2 - 0x100).Take(0x94).ToArray()); if (chk2 == actual2) return 1; return -1; @@ -29,6 +36,9 @@ internal static int getIsG5SAV(byte[] data) public readonly bool Exportable; public readonly byte[] BAK; public string FileName, FilePath; + + private BlockInfo5[] Blocks; + public SAV5(byte[] data = null) { Data = (byte[])(data ?? new byte[SIZERAW]).Clone(); @@ -40,8 +50,1039 @@ public SAV5(byte[] data = null) if (version < 0) // Invalidate Data Data = null; + B2W2 = version == 1; + BW = version == 0; + // Different Offsets for different games. BattleBox = version == 1 ? 0x20A00 : 0x20900; + + #region Block Tables + if (BW) + { + Blocks = new[] + { + new BlockInfo5 + { + Offset = 0x00000, + Length = 0x3E0, + ChecksumOffset = 0x003E2, + ChecksumMirror = 0x23F00 /* Box Names */ + }, + new BlockInfo5 + { + Offset = 0x00400, + Length = 0xFF0, + ChecksumOffset = 0x013F2, + ChecksumMirror = 0x23F02 /* Box 1 */ + }, + new BlockInfo5 + { + Offset = 0x01400, + Length = 0xFF0, + ChecksumOffset = 0x023F2, + ChecksumMirror = 0x23F04 /* Box 2 */ + }, + new BlockInfo5 + { + Offset = 0x02400, + Length = 0xFF0, + ChecksumOffset = 0x033F2, + ChecksumMirror = 0x23F06 /* Box 3 */ + }, + new BlockInfo5 + { + Offset = 0x03400, + Length = 0xFF0, + ChecksumOffset = 0x043F2, + ChecksumMirror = 0x23F08 /* Box 4 */ + }, + new BlockInfo5 + { + Offset = 0x04400, + Length = 0xFF0, + ChecksumOffset = 0x053F2, + ChecksumMirror = 0x23F0A /* Box 5 */ + }, + new BlockInfo5 + { + Offset = 0x05400, + Length = 0xFF0, + ChecksumOffset = 0x063F2, + ChecksumMirror = 0x23F0C /* Box 6 */ + }, + new BlockInfo5 + { + Offset = 0x06400, + Length = 0xFF0, + ChecksumOffset = 0x073F2, + ChecksumMirror = 0x23F0E /* Box 7 */ + }, + new BlockInfo5 + { + Offset = 0x07400, + Length = 0xFF0, + ChecksumOffset = 0x083F2, + ChecksumMirror = 0x23F10 /* Box 8 */ + }, + new BlockInfo5 + { + Offset = 0x08400, + Length = 0xFF0, + ChecksumOffset = 0x093F2, + ChecksumMirror = 0x23F12 /* Box 9 */ + }, + new BlockInfo5 + { + Offset = 0x09400, + Length = 0xFF0, + ChecksumOffset = 0x0A3F2, + ChecksumMirror = 0x23F14 /* Box 10 */ + }, + new BlockInfo5 + { + Offset = 0x0A400, + Length = 0xFF0, + ChecksumOffset = 0x0B3F2, + ChecksumMirror = 0x23F16 /* Box 11 */ + }, + new BlockInfo5 + { + Offset = 0x0B400, + Length = 0xFF0, + ChecksumOffset = 0x0C3F2, + ChecksumMirror = 0x23F18 /* Box 12 */ + }, + new BlockInfo5 + { + Offset = 0x0C400, + Length = 0xFF0, + ChecksumOffset = 0x0D3F2, + ChecksumMirror = 0x23F1A /* Box 13 */ + }, + new BlockInfo5 + { + Offset = 0x0D400, + Length = 0xFF0, + ChecksumOffset = 0x0E3F2, + ChecksumMirror = 0x23F1C /* Box 14 */ + }, + new BlockInfo5 + { + Offset = 0x0E400, + Length = 0xFF0, + ChecksumOffset = 0x0F3F2, + ChecksumMirror = 0x23F1E /* Box 15 */ + }, + new BlockInfo5 + { + Offset = 0x0F400, + Length = 0xFF0, + ChecksumOffset = 0x103F2, + ChecksumMirror = 0x23F20 /* Box 16 */ + }, + new BlockInfo5 + { + Offset = 0x10400, + Length = 0xFF0, + ChecksumOffset = 0x113F2, + ChecksumMirror = 0x23F22 /* Box 17 */ + }, + new BlockInfo5 + { + Offset = 0x11400, + Length = 0xFF0, + ChecksumOffset = 0x123F2, + ChecksumMirror = 0x23F24 /* Box 18 */ + }, + new BlockInfo5 + { + Offset = 0x12400, + Length = 0xFF0, + ChecksumOffset = 0x133F2, + ChecksumMirror = 0x23F26 /* Box 19 */ + }, + new BlockInfo5 + { + Offset = 0x13400, + Length = 0xFF0, + ChecksumOffset = 0x143F2, + ChecksumMirror = 0x23F28 /* Box 20 */ + }, + new BlockInfo5 + { + Offset = 0x14400, + Length = 0xFF0, + ChecksumOffset = 0x153F2, + ChecksumMirror = 0x23F2A /* Box 21 */ + }, + new BlockInfo5 + { + Offset = 0x15400, + Length = 0xFF0, + ChecksumOffset = 0x163F2, + ChecksumMirror = 0x23F2C /* Box 22 */ + }, + new BlockInfo5 + { + Offset = 0x16400, + Length = 0xFF0, + ChecksumOffset = 0x173F2, + ChecksumMirror = 0x23F2E /* Box 23 */ + }, + new BlockInfo5 + { + Offset = 0x17400, + Length = 0xFF0, + ChecksumOffset = 0x183F2, + ChecksumMirror = 0x23F30 /* Box 24 */ + }, + new BlockInfo5 + { + Offset = 0x18400, + Length = 0x9C0, + ChecksumOffset = 0x18DC2, + ChecksumMirror = 0x23F32 /* Inventory */ + }, + new BlockInfo5 + { + Offset = 0x18E00, + Length = 0x534, + ChecksumOffset = 0x19336, + ChecksumMirror = 0x23F34 /* Party Pokemon */ + }, + new BlockInfo5 + { + Offset = 0x19400, + Length = 0x68, + ChecksumOffset = 0x19469, + ChecksumMirror = 0x23F36 /* Trainer Data */ + }, + new BlockInfo5 + { + Offset = 0x19500, + Length = 0x9C, + ChecksumOffset = 0x1959E, + ChecksumMirror = 0x23F38 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x19600, + Length = 0x1338, + ChecksumOffset = 0x1A93A, + ChecksumMirror = 0x23F3A /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1AA00, + Length = 0x7C4, + ChecksumOffset = 0x1B1C6, + ChecksumMirror = 0x23F3C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1B200, + Length = 0xD54, + ChecksumOffset = 0x1BF56, + ChecksumMirror = 0x23F3E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1C000, + Length = 0x2C, + ChecksumOffset = 0x1C02E, + ChecksumMirror = 0x23F40 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1C100, + Length = 0x658, + ChecksumOffset = 0x1C75A, + ChecksumMirror = 0x23F42 /* ??? Gym badge data */ + }, + new BlockInfo5 + { + Offset = 0x1C800, + Length = 0xA94, + ChecksumOffset = 0x1D296, + ChecksumMirror = 0x23F44 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1D300, + Length = 0x1AC, + ChecksumOffset = 0x1D4AE, + ChecksumMirror = 0x23F46 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1D500, + Length = 0x3EC, + ChecksumOffset = 0x1D8EE, + ChecksumMirror = 0x23F48 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1D900, + Length = 0x5C, + ChecksumOffset = 0x1D95E, + ChecksumMirror = 0x23F4A /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1DA00, + Length = 0x1E0, + ChecksumOffset = 0x1DBE2, + ChecksumMirror = 0x23F4C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1DC00, + Length = 0xA8, + ChecksumOffset = 0x1DCAA, + ChecksumMirror = 0x23F4E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1DD00, + Length = 0x460, + ChecksumOffset = 0x1E162, + ChecksumMirror = 0x23F50 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1E200, + Length = 0x1400, + ChecksumOffset = 0x1F602, + ChecksumMirror = 0x23F52 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1F700, + Length = 0x2A4, + ChecksumOffset = 0x1F9A6, + ChecksumMirror = 0x23F54 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1FA00, + Length = 0x2DC, + ChecksumOffset = 0x1FCDE, + ChecksumMirror = 0x23F56 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1FD00, + Length = 0x34C, + ChecksumOffset = 0x2004E, + ChecksumMirror = 0x23F58 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20100, + Length = 0x3EC, + ChecksumOffset = 0x204EE, + ChecksumMirror = 0x23F5A /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20500, + Length = 0xF8, + ChecksumOffset = 0x205FA, + ChecksumMirror = 0x23F5C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20600, + Length = 0x2FC, + ChecksumOffset = 0x208FE, + ChecksumMirror = 0x23F5E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20900, + Length = 0x94, + ChecksumOffset = 0x20996, + ChecksumMirror = 0x23F60 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20A00, + Length = 0x35C, + ChecksumOffset = 0x20D5E, + ChecksumMirror = 0x23F62 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20E00, + Length = 0x1CC, + ChecksumOffset = 0x20FCE, + ChecksumMirror = 0x23F64 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21000, + Length = 0x168, + ChecksumOffset = 0x2116A, + ChecksumMirror = 0x23F66 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21200, + Length = 0xEC, + ChecksumOffset = 0x212EE, + ChecksumMirror = 0x23F68 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21300, + Length = 0x1B0, + ChecksumOffset = 0x214B2, + ChecksumMirror = 0x23F6A /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21500, + Length = 0x1C, + ChecksumOffset = 0x2151E, + ChecksumMirror = 0x23F6C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21600, + Length = 0x4D4, + ChecksumOffset = 0x21AD6, + ChecksumMirror = 0x23F6E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21B00, + Length = 0x34, + ChecksumOffset = 0x21B36, + ChecksumMirror = 0x23F70 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21C00, + Length = 0x3C, + ChecksumOffset = 0x21C3E, + ChecksumMirror = 0x23F72 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21D00, + Length = 0x1AC, + ChecksumOffset = 0x21EAE, + ChecksumMirror = 0x23F74 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21F00, + Length = 0xB90, + ChecksumOffset = 0x22A92, + ChecksumMirror = 0x23F76 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x22B00, + Length = 0x9C, + ChecksumOffset = 0x22B9E, + ChecksumMirror = 0x23F78 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x22C00, + Length = 0x850, + ChecksumOffset = 0x23452, + ChecksumMirror = 0x23F7A /* Entralink Forest pokémon data */ + }, + new BlockInfo5 + { + Offset = 0x23500, + Length = 0x28, + ChecksumOffset = 0x2352A, + ChecksumMirror = 0x23F7C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23600, + Length = 0x284, + ChecksumOffset = 0x23886, + ChecksumMirror = 0x23F7E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23900, + Length = 0x10, + ChecksumOffset = 0x23912, + ChecksumMirror = 0x23F80 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23A00, + Length = 0x5C, + ChecksumOffset = 0x23A5E, + ChecksumMirror = 0x23F82 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23B00, + Length = 0x16C, + ChecksumOffset = 0x23C6E, + ChecksumMirror = 0x23F84 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23D00, + Length = 0x40, + ChecksumOffset = 0x23D42, + ChecksumMirror = 0x23F86 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23E00, + Length = 0xFC, + ChecksumOffset = 0x23EFE, + ChecksumMirror = 0x23F88 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23F00, + Length = 0x8C, + ChecksumOffset = 0x23F9A, + ChecksumMirror = 0x23F9A /* Checksums */ + } + }; + } + else if (B2W2) + { + Blocks = new[] + { + new BlockInfo5 + { + Offset = 0x00000, + Length = 0x3e0, + ChecksumOffset = 0x003E2, + ChecksumMirror = 0x25F00 /* Box Names */ + }, + new BlockInfo5 + { + Offset = 0x00400, + Length = 0xff0, + ChecksumOffset = 0x013F2, + ChecksumMirror = 0x25F02 /* Box 1 */ + }, + new BlockInfo5 + { + Offset = 0x01400, + Length = 0xff0, + ChecksumOffset = 0x023F2, + ChecksumMirror = 0x25F04 /* Box 2 */ + }, + new BlockInfo5 + { + Offset = 0x02400, + Length = 0xff0, + ChecksumOffset = 0x033F2, + ChecksumMirror = 0x25F06 /* Box 3 */ + }, + new BlockInfo5 + { + Offset = 0x03400, + Length = 0xff0, + ChecksumOffset = 0x043F2, + ChecksumMirror = 0x25F08 /* Box 4 */ + }, + new BlockInfo5 + { + Offset = 0x04400, + Length = 0xff0, + ChecksumOffset = 0x053F2, + ChecksumMirror = 0x25F0A /* Box 5 */ + }, + new BlockInfo5 + { + Offset = 0x05400, + Length = 0xff0, + ChecksumOffset = 0x063F2, + ChecksumMirror = 0x25F0C /* Box 6 */ + }, + new BlockInfo5 + { + Offset = 0x06400, + Length = 0xff0, + ChecksumOffset = 0x073F2, + ChecksumMirror = 0x25F0E /* Box 7 */ + }, + new BlockInfo5 + { + Offset = 0x07400, + Length = 0xff0, + ChecksumOffset = 0x083F2, + ChecksumMirror = 0x25F10 /* Box 8 */ + }, + new BlockInfo5 + { + Offset = 0x08400, + Length = 0xff0, + ChecksumOffset = 0x093F2, + ChecksumMirror = 0x25F12 /* Box 9 */ + }, + new BlockInfo5 + { + Offset = 0x09400, + Length = 0xff0, + ChecksumOffset = 0x0A3F2, + ChecksumMirror = 0x25F14 /* Box 10 */ + }, + new BlockInfo5 + { + Offset = 0x0A400, + Length = 0xff0, + ChecksumOffset = 0x0B3F2, + ChecksumMirror = 0x25F16 /* Box 11 */ + }, + new BlockInfo5 + { + Offset = 0x0B400, + Length = 0xff0, + ChecksumOffset = 0x0C3F2, + ChecksumMirror = 0x25F18 /* Box 12 */ + }, + new BlockInfo5 + { + Offset = 0x0C400, + Length = 0xff0, + ChecksumOffset = 0x0D3F2, + ChecksumMirror = 0x25F1A /* Box 13 */ + }, + new BlockInfo5 + { + Offset = 0x0D400, + Length = 0xff0, + ChecksumOffset = 0x0E3F2, + ChecksumMirror = 0x25F1C /* Box 14 */ + }, + new BlockInfo5 + { + Offset = 0x0E400, + Length = 0xff0, + ChecksumOffset = 0x0F3F2, + ChecksumMirror = 0x25F1E /* Box 15 */ + }, + new BlockInfo5 + { + Offset = 0x0F400, + Length = 0xff0, + ChecksumOffset = 0x103F2, + ChecksumMirror = 0x25F20 /* Box 16 */ + }, + new BlockInfo5 + { + Offset = 0x10400, + Length = 0xff0, + ChecksumOffset = 0x113F2, + ChecksumMirror = 0x25F22 /* Box 17 */ + }, + new BlockInfo5 + { + Offset = 0x11400, + Length = 0xff0, + ChecksumOffset = 0x123F2, + ChecksumMirror = 0x25F24 /* Box 18 */ + }, + new BlockInfo5 + { + Offset = 0x12400, + Length = 0xff0, + ChecksumOffset = 0x133F2, + ChecksumMirror = 0x25F26 /* Box 19 */ + }, + new BlockInfo5 + { + Offset = 0x13400, + Length = 0xff0, + ChecksumOffset = 0x143F2, + ChecksumMirror = 0x25F28 /* Box 20 */ + }, + new BlockInfo5 + { + Offset = 0x14400, + Length = 0xff0, + ChecksumOffset = 0x153F2, + ChecksumMirror = 0x25F2A /* Box 21 */ + }, + new BlockInfo5 + { + Offset = 0x15400, + Length = 0xff0, + ChecksumOffset = 0x163F2, + ChecksumMirror = 0x25F2C /* Box 22 */ + }, + new BlockInfo5 + { + Offset = 0x16400, + Length = 0xff0, + ChecksumOffset = 0x173F2, + ChecksumMirror = 0x25F2E /* Box 23 */ + }, + new BlockInfo5 + { + Offset = 0x17400, + Length = 0xff0, + ChecksumOffset = 0x183F2, + ChecksumMirror = 0x25F30 /* Box 24 */ + }, + new BlockInfo5 + { + Offset = 0x18400, + Length = 0x9ec, + ChecksumOffset = 0x18DEE, + ChecksumMirror = 0x25F32 /* Inventory */ + }, + new BlockInfo5 + { + Offset = 0x18E00, + Length = 0x534, + ChecksumOffset = 0x19336, + ChecksumMirror = 0x25F34 /* Party Pokemon */ + }, + new BlockInfo5 + { + Offset = 0x19400, + Length = 0xb0, + ChecksumOffset = 0x194B2, + ChecksumMirror = 0x25F36 /* Trainer Data */ + }, + new BlockInfo5 + { + Offset = 0x19500, + Length = 0xa8, + ChecksumOffset = 0x195AA, + ChecksumMirror = 0x25F38 /* Trainer Position */ + }, + new BlockInfo5 + { + Offset = 0x19600, + Length = 0x1338, + ChecksumOffset = 0x1A93A, + ChecksumMirror = 0x25F3A /* Unity Tower and survey stuff */ + }, + new BlockInfo5 + { + Offset = 0x1AA00, + Length = 0x7c4, + ChecksumOffset = 0x1B1C6, + ChecksumMirror = 0x25F3C /* Pal Pad Player Data (30d) */ + }, + new BlockInfo5 + { + Offset = 0x1B200, + Length = 0xd54, + ChecksumOffset = 0x1BF56, + ChecksumMirror = 0x25F3E /* Pal Pad Friend Data */ + }, + new BlockInfo5 + { + Offset = 0x1C000, + Length = 0x94, + ChecksumOffset = 0x1C096, + ChecksumMirror = 0x25F40 /* C-Gear */ + }, + new BlockInfo5 + { + Offset = 0x1C100, + Length = 0x658, + ChecksumOffset = 0x1C75A, + ChecksumMirror = 0x25F42 /* Card Signature Block & ???? */ + }, + new BlockInfo5 + { + Offset = 0x1C800, + Length = 0xa94, + ChecksumOffset = 0x1D296, + ChecksumMirror = 0x25F44 /* Mystery Gift */ + }, + new BlockInfo5 + { + Offset = 0x1D300, + Length = 0x1ac, + ChecksumOffset = 0x1D4AE, + ChecksumMirror = 0x25F46 /* Dream World Stuff (Catalog) */ + }, + new BlockInfo5 + { + Offset = 0x1D500, + Length = 0x3ec, + ChecksumOffset = 0x1D8EE, + ChecksumMirror = 0x25F48 /* Chatter */ + }, + new BlockInfo5 + { + Offset = 0x1D900, + Length = 0x5c, + ChecksumOffset = 0x1D95E, + ChecksumMirror = 0x25F4A /* Adventure data */ + }, + new BlockInfo5 + { + Offset = 0x1DA00, + Length = 0x1e0, + ChecksumOffset = 0x1DBE2, + ChecksumMirror = 0x25F4C /* Trainer Card Records */ + }, + new BlockInfo5 + { + Offset = 0x1DC00, + Length = 0xa8, + ChecksumOffset = 0x1DCAA, + ChecksumMirror = 0x25F4E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1DD00, + Length = 0x460, + ChecksumOffset = 0x1E162, + ChecksumMirror = 0x25F50 /* (40d) */ + }, + new BlockInfo5 + { + Offset = 0x1E200, + Length = 0x1400, + ChecksumOffset = 0x1F602, + ChecksumMirror = 0x25F52 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1F700, + Length = 0x2a4, + ChecksumOffset = 0x1F9A6, + ChecksumMirror = 0x25F54 /* Contains flags and references for downloaded data (Musical) */ + }, + new BlockInfo5 + { + Offset = 0x1FA00, + Length = 0xe0, + ChecksumOffset = 0x1FAE2, + ChecksumMirror = 0x25F56 /* Fused Reshiram/Zekrom Storage */ + }, + new BlockInfo5 + { + Offset = 0x1FB00, + Length = 0x34c, + ChecksumOffset = 0x1FE4E, + ChecksumMirror = 0x25F58 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x1FF00, + Length = 0x4e0, + ChecksumOffset = 0x203E2, + ChecksumMirror = 0x25F5A /* Const Data Block and Event Flag Block (0x35E is the split) */ + }, + new BlockInfo5 + { + Offset = 0x20400, + Length = 0xf8, + ChecksumOffset = 0x204FA, + ChecksumMirror = 0x25F5C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20500, + Length = 0x2fc, + ChecksumOffset = 0x207FE, + ChecksumMirror = 0x25F5E /* Tournament Block */ + }, + new BlockInfo5 + { + Offset = 0x20800, + Length = 0x94, + ChecksumOffset = 0x20896, + ChecksumMirror = 0x25F60 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x20900, + Length = 0x35c, + ChecksumOffset = 0x20C5E, + ChecksumMirror = 0x25F62 /* Battle Box Block */ + }, + new BlockInfo5 + { + Offset = 0x20D00, + Length = 0x1d4, + ChecksumOffset = 0x20ED6, + ChecksumMirror = 0x25F64 /* Daycare Block (50d) */ + }, + new BlockInfo5 + { + Offset = 0x20F00, + Length = 0x1e0, + ChecksumOffset = 0x201E2, + ChecksumMirror = 0x25F66 /* Strength Boulder Status Block */ + }, + new BlockInfo5 + { + Offset = 0x21100, + Length = 0xf0, + ChecksumOffset = 0x211F2, + ChecksumMirror = 0x25F68 /* Badge Flags, Money, Trainer Sayings */ + }, + new BlockInfo5 + { + Offset = 0x21200, + Length = 0x1b4, + ChecksumOffset = 0x213B6, + ChecksumMirror = 0x25F6A /* Entralink (Level & Powers etc) */ + }, + new BlockInfo5 + { + Offset = 0x21400, + Length = 0x4dc, + ChecksumOffset = 0x218DE, + ChecksumMirror = 0x25F6C /* Pokedex */ + }, + new BlockInfo5 + { + Offset = 0x21900, + Length = 0x34, + ChecksumOffset = 0x21936, + ChecksumMirror = 0x25F6E + /* Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type */ + }, + new BlockInfo5 + { + Offset = 0x21A00, + Length = 0x3c, + ChecksumOffset = 0x21A3E, + ChecksumMirror = 0x25F70 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21B00, + Length = 0x1ac, + ChecksumOffset = 0x21CAE, + ChecksumMirror = 0x25F72 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x21D00, + Length = 0xb90, + ChecksumOffset = 0x22892, + ChecksumMirror = 0x25F74 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x22900, + Length = 0xac, + ChecksumOffset = 0x229AE, + ChecksumMirror = 0x25F76 /* Online Records */ + }, + new BlockInfo5 + { + Offset = 0x22A00, + Length = 0x850, + ChecksumOffset = 0x23252, + ChecksumMirror = 0x25F78 /* Area NPC data - encrypted (60d) */ + }, + new BlockInfo5 + { + Offset = 0x23300, + Length = 0x284, + ChecksumOffset = 0x23586, + ChecksumMirror = 0x25F7A /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23600, + Length = 0x10, + ChecksumOffset = 0x23612, + ChecksumMirror = 0x25F7C /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23700, + Length = 0xa8, + ChecksumOffset = 0x237AA, + ChecksumMirror = 0x25F7E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23800, + Length = 0x16c, + ChecksumOffset = 0x2396E, + ChecksumMirror = 0x25F80 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23A00, + Length = 0x80, + ChecksumOffset = 0x23A82, + ChecksumMirror = 0x25F82 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x23B00, + Length = 0xfc, + ChecksumOffset = 0x23BFE, + ChecksumMirror = 0x25F84 /* Hollow/Rival Block */ + }, + new BlockInfo5 + { + Offset = 0x23C00, + Length = 0x16a8, + ChecksumOffset = 0x252AA, + ChecksumMirror = 0x25F86 /* Join Avenue Block */ + }, + new BlockInfo5 + { + Offset = 0x25300, + Length = 0x498, + ChecksumOffset = 0x2579A, + ChecksumMirror = 0x25F88 /* Medal data */ + }, + new BlockInfo5 + { + Offset = 0x25800, + Length = 0x60, + ChecksumOffset = 0x25862, + ChecksumMirror = 0x25F8A /* Key-related data */ + }, + new BlockInfo5 + { + Offset = 0x25900, + Length = 0xfc, + ChecksumOffset = 0x259FE, + ChecksumMirror = 0x25F8C /* (70d) */ + }, + new BlockInfo5 + { + Offset = 0x25A00, + Length = 0x3e4, + ChecksumOffset = 0x25DE6, + ChecksumMirror = 0x25F8E /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x25E00, + Length = 0xf0, + ChecksumOffset = 0x25EF2, + ChecksumMirror = 0x25F90 /* ??? */ + }, + new BlockInfo5 + { + Offset = 0x25F00, + Length = 0x94, + ChecksumOffset = 0x25FA2, + ChecksumMirror = 0x25FA2 /* Checksum Block (73d) */ + } + }; + } + else + { + Blocks = new BlockInfo5[] {}; + } + #endregion } private const int Box = 0x400; @@ -51,6 +1092,33 @@ public SAV5(byte[] data = null) private const int Wondercard = 0x1C800; private const int wcSeed = 0x1D290; + private bool BW; + private bool B2W2; + + private void setChecksums() + { + // Check for invalid block lengths + if (Blocks.Length < 3) // arbitrary... + { + Console.WriteLine("Not enough blocks ({0}), aborting setChecksums", Blocks.Length); + return; + } + // Apply checksums + for (int i = 0; i < Blocks.Length; i++) + { + byte[] array = Data.Skip(Blocks[i].Offset).Take(Blocks[i].Length).ToArray(); + ushort chk = ccitt16(array); + BitConverter.GetBytes(chk).CopyTo(Data, Blocks[i].ChecksumOffset); + BitConverter.GetBytes(chk).CopyTo(Data, Blocks[i].ChecksumMirror); + } + } + + public byte[] Write() + { + setChecksums(); + return Data; + } + public int PartyCount { get { return Data[Party]; }