private void InitializeData() { // Scan all 3 save slots for the highest counter for (int i = 0; i < SLOT_COUNT; i++) { int slotOffset = SLOT_START + (i * SLOT_SIZE); int SaveCounter = BigEndian.ToInt32(Data, slotOffset + 4); if (SaveCounter <= SaveCount) { continue; } SaveCount = SaveCounter; SaveIndex = i; } // Decrypt most recent save slot { byte[] slot = new byte[SLOT_SIZE]; int slotOffset = SLOT_START + (SaveIndex * SLOT_SIZE); Array.Copy(Data, slotOffset, slot, 0, slot.Length); byte[] digest = new byte[20]; Array.Copy(slot, SLOT_SIZE - 20, digest, 0, digest.Length); // Decrypt Slot Data = DecryptColosseum(slot, digest); } }
protected override void SetChecksums() { // Clear Header Checksum BitConverter.GetBytes(0).CopyTo(Data, 12); // Compute checksum of data byte[] checksum = sha1.ComputeHash(Data, 0, 0x1DFD8); // Set Checksum to end Array.Copy(checksum, 0, Data, Data.Length - 20, 20); // Header Integrity byte[] H = new byte[8]; Array.Copy(checksum, 0, H, 0, 8); byte[] D = new byte[8]; Array.Copy(Data, 0x18, D, 0, 8); // Decrypt Checksum for (int i = 0; i < 8; i++) { D[i] ^= (byte)~H[i]; } // Compute new header checksum int newHC = 0; for (int i = 0; i < 0x18; i += 4) { newHC -= BigEndian.ToInt32(Data, i); } newHC -= BigEndian.ToInt32(D, 0); newHC -= BigEndian.ToInt32(D, 4); // Set Header Checksum BigEndian.GetBytes(newHC).CopyTo(Data, 12); }
private void InitializeData(out StrategyMemo memo, out ShadowInfoTableXD info) { // Scan all 3 save slots for the highest counter for (int i = 0; i < SLOT_COUNT; i++) { int slotOffset = SLOT_START + (i * SLOT_SIZE); int SaveCounter = BigEndian.ToInt32(Data, slotOffset + 4); if (SaveCounter <= SaveCount) { continue; } SaveCount = SaveCounter; SaveIndex = i; } // Decrypt most recent save slot { byte[] slot = new byte[SLOT_SIZE]; int slotOffset = SLOT_START + (SaveIndex * SLOT_SIZE); Array.Copy(Data, slotOffset, slot, 0, slot.Length); ushort[] keys = new ushort[4]; for (int i = 0; i < keys.Length; i++) { keys[i] = BigEndian.ToUInt16(slot, 8 + (i * 2)); } // Decrypt Slot Data = GCSaveUtil.Decrypt(slot, 0x00010, 0x27FD8, keys); } // Get Offset Info ushort[] subLength = new ushort[16]; for (int i = 0; i < 16; i++) { subLength[i] = BigEndian.ToUInt16(Data, 0x20 + (2 * i)); subOffsets[i] = BigEndian.ToUInt16(Data, 0x40 + (4 * i)) | BigEndian.ToUInt16(Data, 0x40 + (4 * i) + 2) << 16; } // Offsets are displaced by the 0xA8 savedata region Trainer1 = subOffsets[1] + 0xA8; Party = Trainer1 + 0x30; Box = subOffsets[2] + 0xA8; DaycareOffset = subOffsets[4] + 0xA8; Memo = subOffsets[5] + 0xA8; Shadow = subOffsets[7] + 0xA8; // Purifier = subOffsets[14] + 0xA8; memo = new StrategyMemo(Data, Memo, xd: true); info = new ShadowInfoTableXD(Data.Slice(Shadow, subLength[7])); }
public SAV4Ranch(byte[] data) : base(data, typeof(PK4), 0) { Personal = PersonalTable.Pt; Version = Data.Length == SaveUtil.SIZE_G4RANCH_PLAT ? GameVersion.Pt : GameVersion.DP; HeldItems = Legal.HeldItems_Pt; OT = GetString(0x770, 0x12); // 0x18 starts the header table // Block 00, Offset = ??? // Block 01, Offset = Mii Data // Block 02, Offset = Mii Link Data // Block 03, Offset = Pokemon Data // Block 04, Offset = ?? // Unpack the binary a little: // size, count, Mii data[count] // size, count, Mii Link data[count] // size, count, Pokemon (PK4 + metadata)[count] // size, count, ??? /* ====Metadata==== * uint8_t poke_type;// 01 trainer, 04 hayley, 05 traded * uint8_t tradeable;// 02 is tradeable, normal 00 * uint16_t tid; * uint16_t sid; * uint32_t name1; * uint32_t name2; * uint32_t name3; * uint32_t name4; */ var pkCountOffset = BigEndian.ToInt32(Data, 0x34) + 4; SlotCount = BigEndian.ToInt32(Data, pkCountOffset); BoxCount = (int)Math.Ceiling((decimal)SlotCount / SlotsPerBox); Box = pkCountOffset + 4; FinalCountOffset = BigEndian.ToInt32(Data, 0x3C); FinalCount = BigEndian.ToInt32(Data, FinalCountOffset); }
public SAV3XD(byte[] data = null) { Data = data ?? new byte[SaveUtil.SIZE_G3XD]; BAK = (byte[])Data.Clone(); Exportable = !IsRangeEmpty(0, Data.Length); if (SaveUtil.GetIsG3XDSAV(Data) != GameVersion.XD) { return; } // Scan all 3 save slots for the highest counter for (int i = 0; i < SLOT_COUNT; i++) { int slotOffset = SLOT_START + (i * SLOT_SIZE); int SaveCounter = BigEndian.ToInt32(Data, slotOffset + 4); if (SaveCounter <= SaveCount) { continue; } SaveCount = SaveCounter; SaveIndex = i; } // Decrypt most recent save slot { byte[] slot = new byte[SLOT_SIZE]; int slotOffset = SLOT_START + (SaveIndex * SLOT_SIZE); Array.Copy(Data, slotOffset, slot, 0, slot.Length); ushort[] keys = new ushort[4]; for (int i = 0; i < keys.Length; i++) { keys[i] = BigEndian.ToUInt16(slot, 8 + (i * 2)); } // Decrypt Slot Data = SaveUtil.DecryptGC(slot, 0x00010, 0x27FD8, keys); } // Get Offset Info ushort[] subLength = new ushort[16]; for (int i = 0; i < 16; i++) { subLength[i] = BigEndian.ToUInt16(Data, 0x20 + (2 * i)); subOffsets[i] = BigEndian.ToUInt16(Data, 0x40 + (4 * i)) | BigEndian.ToUInt16(Data, 0x40 + (4 * i) + 2) << 16; } // Offsets are displaced by the 0xA8 savedata region Trainer1 = subOffsets[1] + 0xA8; Party = Trainer1 + 0x30; Box = subOffsets[2] + 0xA8; Daycare = subOffsets[4] + 0xA8; Memo = subOffsets[5] + 0xA8; Shadow = subOffsets[7] + 0xA8; // Purifier = subOffsets[14] + 0xA8; StrategyMemo = new StrategyMemo(Data, Memo, xd: true); ShadowInfo = new ShadowInfoTableXD(Data.Skip(Shadow).Take(subLength[7]).ToArray()); OFS_PouchHeldItem = Trainer1 + 0x4C8; OFS_PouchKeyItem = Trainer1 + 0x540; OFS_PouchBalls = Trainer1 + 0x5EC; OFS_PouchTMHM = Trainer1 + 0x62C; OFS_PouchBerry = Trainer1 + 0x72C; OFS_PouchCologne = Trainer1 + 0x7E4; OFS_PouchDisc = Trainer1 + 0x7F0; LegalItems = Legal.Pouch_Items_XD; LegalKeyItems = Legal.Pouch_Key_XD; LegalBalls = Legal.Pouch_Ball_RS; LegalTMHMs = Legal.Pouch_TM_RS; // not HMs LegalBerries = Legal.Pouch_Berries_RS; LegalCologne = Legal.Pouch_Cologne_XD; LegalDisc = Legal.Pouch_Disc_XD; Personal = PersonalTable.RS; HeldItems = Legal.HeldItems_XD; if (!Exportable) { ClearBoxes(); } // Since PartyCount is not stored in the save file, // Count up how many party slots are active. for (int i = 0; i < 6; i++) { if (GetPartySlot(GetPartyOffset(i)).Species != 0) { PartyCount++; } } }
public SAV3Colosseum(byte[] data = null) { Data = data ?? new byte[SaveUtil.SIZE_G3COLO]; BAK = (byte[])Data.Clone(); Exportable = !IsRangeEmpty(0, Data.Length); if (SaveUtil.GetIsG3COLOSAV(Data) != GameVersion.COLO) { return; } // Scan all 3 save slots for the highest counter for (int i = 0; i < SLOT_COUNT; i++) { int slotOffset = SLOT_START + (i * SLOT_SIZE); int SaveCounter = BigEndian.ToInt32(Data, slotOffset + 4); if (SaveCounter <= SaveCount) { continue; } SaveCount = SaveCounter; SaveIndex = i; } // Decrypt most recent save slot { byte[] slot = new byte[SLOT_SIZE]; int slotOffset = SLOT_START + (SaveIndex * SLOT_SIZE); Array.Copy(Data, slotOffset, slot, 0, slot.Length); byte[] digest = new byte[20]; Array.Copy(slot, SLOT_SIZE - 20, digest, 0, digest.Length); // Decrypt Slot Data = DecryptColosseum(slot, digest); } Trainer1 = 0x00078; Party = 0x000A8; OFS_PouchHeldItem = 0x007F8; OFS_PouchKeyItem = 0x00848; OFS_PouchBalls = 0x008F4; OFS_PouchTMHM = 0x00934; OFS_PouchBerry = 0x00A34; OFS_PouchCologne = 0x00AEC; // Cologne Box = 0x00B90; Daycare = 0x08170; Memo = 0x082B0; StrategyMemo = new StrategyMemo(Data, Memo, xd: false); LegalItems = Legal.Pouch_Items_COLO; LegalKeyItems = Legal.Pouch_Key_COLO; LegalBalls = Legal.Pouch_Ball_RS; LegalTMHMs = Legal.Pouch_TM_RS; // not HMs LegalBerries = Legal.Pouch_Berries_RS; LegalCologne = Legal.Pouch_Cologne_COLO; Personal = PersonalTable.RS; HeldItems = Legal.HeldItems_COLO; if (!Exportable) { ClearBoxes(); } // Since PartyCount is not stored in the save file, // Count up how many party slots are active. for (int i = 0; i < 6; i++) { if (GetPartySlot(GetPartyOffset(i)).Species != 0) { PartyCount++; } } }