// Checksums protected override void setChecksums() { for (int i = 0; i < 14; i++) { byte[] chunk = Data.Skip(ABO + i * 0x1000).Take(chunkLength[BlockOrder[i]]).ToArray(); ushort chk = SaveUtil.check32(chunk); BitConverter.GetBytes(chk).CopyTo(Data, ABO + i * 0x1000 + 0xFF6); } }
public override string getBoxName(int box) { int offset = getBoxOffset(BoxCount); if (Version == GameVersion.HGSS) { offset += 0x8; } return(PKX.array2strG4(Data.Skip(offset + box * 0x28).Take(0x28).ToArray())); }
public override string getDaycareRNGSeed(int loc) { if (loc != 0) return null; if (Daycare < 0) return null; var data = Data.Skip(Daycare + 0x1DC).Take(DaycareSeedSize / 2).Reverse().ToArray(); return BitConverter.ToString(data).Replace("-", ""); }
public override string getDaycareRNGSeed(int loc) { if (Version != GameVersion.B2W2) { return(null); } var data = Data.Skip(Daycare + 0x1CC).Take(DaycareSeedSize / 2).Reverse().ToArray(); return(BitConverter.ToString(data).Replace("-", "")); }
public WC6(byte[] data = null) { Data = (byte[])(data?.Clone() ?? new byte[Size]); if (Data.Length == SizeFull) { Data = Data.Skip(SizeFull - Size).ToArray(); DateTime now = DateTime.Now; Year = (uint)now.Year; Month = (uint)now.Month; Day = (uint)now.Day; } }
public override string getDaycareRNGSeed(int loc) { int ofs = loc == 0 ? Daycare : Daycare2; if (ofs <= 0) { return(null); } var data = Data.Skip(Daycare + 0x1E8).Take(DaycareSeedSize / 2).Reverse().ToArray(); return(BitConverter.ToString(data).Replace("-", "")); }
private WC7 getWC7(int index) { if (WondercardData < 0) { return(null); } if (index < 0 || index > GiftCountMax) { return(null); } return(new WC7(Data.Skip(WondercardData + index * WC7.Size).Take(WC7.Size).ToArray())); }
public override byte[] Write(bool DSV) { StrategyMemo.FinalData.CopyTo(Data, Memo); setChecksums(); // Get updated save slot data byte[] digest = Data.Skip(Data.Length - 20).Take(20).ToArray(); byte[] newSAV = EncryptColosseum(Data, digest); // Put save slot back in original save data byte[] newFile = (byte[])OriginalData.Clone(); Array.Copy(newSAV, 0, newFile, SLOT_START + SaveIndex * SLOT_SIZE, newSAV.Length); return(Header.Concat(newFile).ToArray()); }
protected override 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(); BitConverter.GetBytes(SaveUtil.ccitt16(array)).CopyTo(Data, BlockInfoOffset + 6 + i * 8); } }
protected override 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 foreach (BlockInfo b in Blocks) { byte[] array = Data.Skip(b.Offset).Take(b.Length).ToArray(); ushort chk = SaveUtil.ccitt16(array); BitConverter.GetBytes(chk).CopyTo(Data, b.ChecksumOffset); BitConverter.GetBytes(chk).CopyTo(Data, b.ChecksumMirror); } }
public SAV3RSBox(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G3BOX] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); Exportable = !Data.SequenceEqual(new byte[Data.Length]); if (SaveUtil.getIsG3BOXSAV(Data) != GameVersion.RSBOX) { return; } Blocks = new RSBOX_Block[2 * BLOCK_COUNT]; for (int i = 0; i < Blocks.Length; i++) { int offset = BLOCK_SIZE + i * BLOCK_SIZE; Blocks[i] = new RSBOX_Block(Data.Skip(offset).Take(BLOCK_SIZE).ToArray(), offset); } // Detect active save int[] SaveCounts = Blocks.Select(block => (int)block.SaveCount).ToArray(); SaveCount = SaveCounts.Max(); int ActiveSAV = Array.IndexOf(SaveCounts, SaveCount) / BLOCK_COUNT; Blocks = Blocks.Skip(ActiveSAV * BLOCK_COUNT).Take(BLOCK_COUNT).OrderBy(b => b.BlockNumber).ToArray(); // Set up PC data buffer beyond end of save file. Box = Data.Length; Array.Resize(ref Data, Data.Length + SIZE_RESERVED); // More than enough empty space. // Copy block to the allocated location foreach (RSBOX_Block b in Blocks) { Array.Copy(b.Data, 0xC, Data, Box + b.BlockNumber * (BLOCK_SIZE - 0x10), b.Data.Length - 0x10); } Personal = PersonalTable.RS; HeldItems = Legal.HeldItems_RS; if (!Exportable) { resetBoxes(); } }
public override string getBoxName(int box) { // Tweaked for the 1-30/31-60 box showing string lo = (30 * (box % 2) + 1).ToString("00"); string hi = (30 * (box % 2 + 1)).ToString("00"); string boxName = $"[{lo}-{hi}] "; box = box / 2; int offset = Box + 0x1EC38 + 9 * box; if (Data[offset] == 0 || Data[offset] == 0xFF) { boxName += $"BOX {box + 1}"; } boxName += PKX.getG3Str(Data.Skip(offset).Take(9).ToArray(), Japanese); return(boxName); }
public WC6(byte[] data = null) { Data = (byte[])(data?.Clone() ?? new byte[Size]); if (Data.Length == SizeFull) { if (Data[0x205] == 0) { Data = new byte[Data.Length]; // Invalidate } Data = Data.Skip(SizeFull - Size).ToArray(); DateTime now = DateTime.Now; Year = (uint)now.Year; Month = (uint)now.Month; Day = (uint)now.Day; } if (Year < 2000) { Data = new byte[Data.Length]; // Invalidate } }
// Writeback Validity public override string MiscSaveChecks() { string r = ""; byte[] FFFF = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < Data.Length / 0x200; i++) { if (!FFFF.SequenceEqual(Data.Skip(i * 0x200).Take(0x200))) continue; r = $"0x200 chunk @ 0x{(i*0x200).ToString("X5")} is FF'd." + Environment.NewLine + "Cyber will screw up (as of August 31st 2014)." + Environment.NewLine + Environment.NewLine; // Check to see if it is in the Pokedex if (i * 0x200 > PokeDex && i * 0x200 < PokeDex + 0x900) { r += "Problem lies in the Pokedex. "; if (i * 0x200 == PokeDex + 0x400) r += "Remove a language flag for a species < 585, ie Petilil"; } break; } return r; }
public SAV7(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G7SM] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); Exportable = !Data.SequenceEqual(new byte[Data.Length]); // Load Info getBlockInfo(); getSAVOffsets(); HeldItems = Legal.HeldItems_SM; Personal = PersonalTable.SM; if (!Exportable) { resetBoxes(); } var demo = new byte[0x4C4].SequenceEqual(Data.Skip(PCLayout).Take(0x4C4)); // up to Battle Box values if (demo || !Exportable) { PokeDex = -1; // Disabled LockedSlots = new int[0]; } else // Valid slot locking info present { int lockedCount = 0; for (int i = 0; i < LockedSlots.Length; i++) { short val = BitConverter.ToInt16(Data, BattleBoxFlags + i * 2); if (val >= 0) { LockedSlots[lockedCount++] = (BoxSlotCount * (val >> 8) + (val & 0xFF)) & 0xFFFF; } } Array.Resize(ref LockedSlots, lockedCount); } }
// Writeback Validity public override string MiscSaveChecks() { var r = new StringBuilder(); // MemeCrypto check if (RequiresMemeCrypto && !MemeCrypto.CanUseMemeCrypto()) { r.AppendLine("Platform does not support required cryptography providers."); r.AppendLine("Checksum will be broken until the file is saved using an OS without FIPS compliance enabled or a newer OS."); r.AppendLine(); } // FFFF checks byte[] FFFF = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); for (int i = 0; i < Data.Length / 0x200; i++) { if (!FFFF.SequenceEqual(Data.Skip(i * 0x200).Take(0x200))) { continue; } r.AppendLine($"0x200 chunk @ 0x{(i * 0x200).ToString("X5")} is FF'd."); r.AppendLine("Cyber will screw up (as of August 31st 2014)."); r.AppendLine(); // Check to see if it is in the Pokedex if (i * 0x200 > PokeDex && i * 0x200 < PokeDex + 0x900) { r.Append("Problem lies in the Pokedex. "); if (i * 0x200 == PokeDex + 0x400) { r.Append("Remove a language flag for a species < 585, ie Petilil"); } } break; } return(r.ToString()); }
public SAV7(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G7SM] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); Exportable = !Data.SequenceEqual(new byte[Data.Length]); // Load Info getBlockInfo(); getSAVOffsets(); HeldItems = Legal.HeldItems_SM; Personal = PersonalTable.SM; if (!Exportable) { resetBoxes(); } var demo = new byte[0x4C4].SequenceEqual(Data.Skip(PCLayout).Take(0x4C4)); if (demo) { PokeDex = -1; // Disabled } }
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++; } } }
public override string getBoxName(int box) { int offset = getBoxOffset(BoxCount); return(PKX.getG3Str(Data.Skip(offset + box * 9).Take(9).ToArray(), Japanese)); }
public override string getBoxName(int box) { return(PKX.getG1Str(Data.Skip(BoxNamesOffset + box * 9).Take(9).ToArray(), Japanese)); }