From 1bf70d99a39be371142f22c9b1d70d838f7eedc3 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 14 Jun 2016 15:31:33 -0700 Subject: [PATCH] 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]; }