public SAV3XD(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G3XD] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); Exportable = !Data.SequenceEqual(new byte[Data.Length]); if (SaveUtil.getIsG3XDSAV(Data) != GameVersion.XD) { return; } OriginalData = (byte[])Data.Clone(); // 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_CXD; LegalDisc = Legal.Pouch_Disc_XD; Personal = PersonalTable.RS; HeldItems = Legal.HeldItems_XD; if (!Exportable) { resetBoxes(); } // 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++; } } }