/// <summary> /// Gets the generation of the Pokemon data. /// </summary> /// <param name="data">Raw data representing a Pokemon.</param> /// <returns>An integer indicating the generation of the PKM file, or -1 if the data is invalid.</returns> public static int GetPKMDataFormat(byte[] data) { if (!PKX.IsPKM(data.Length)) { return(-1); } switch (data.Length) { case PKX.SIZE_1JLIST: case PKX.SIZE_1ULIST: return(1); case PKX.SIZE_2ULIST: case PKX.SIZE_2JLIST: return(2); case PKX.SIZE_3PARTY: case PKX.SIZE_3STORED: case PKX.SIZE_3CSTORED: case PKX.SIZE_3XSTORED: return(3); case PKX.SIZE_4PARTY: case PKX.SIZE_4STORED: case PKX.SIZE_5PARTY: if ((BitConverter.ToUInt16(data, 0x4) == 0) && (BitConverter.ToUInt16(data, 0x80) >= 0x3333 || data[0x5F] >= 0x10) && BitConverter.ToUInt16(data, 0x46) == 0) // PK5 { return(5); } return(4); case PKX.SIZE_6STORED: return(6); case PKX.SIZE_6PARTY: // collision with PGT, same size. if (BitConverter.ToUInt16(data, 0x4) != 0) // Bad Sanity? { return(-1); } if (BitConverter.ToUInt32(data, 0x06) == PKX.GetCHK(data)) { return(6); } if (BitConverter.ToUInt16(data, 0x58) != 0) // Encrypted? { for (int i = data.Length - 0x10; i < data.Length; i++) // 0x10 of 00's at the end != PK6 { if (data[i] != 0) { return(6); } } return(-1); } return(6); } return(-1); }
/// <summary> /// Gets a <see cref="PKM"/> from the provided <see cref="file"/> path, which is to be loaded to the <see cref="SaveFile"/>. /// </summary> /// <param name="file"><see cref="PKM"/> or <see cref="MysteryGift"/> file path.</param> /// <param name="sav">Generation Info</param> /// <returns>New <see cref="PKM"/> reference from the file.</returns> public static PKM?GetSingleFromPath(string file, ITrainerInfo sav) { var fi = new FileInfo(file); if (!fi.Exists) { return(null); } if (fi.Length == GP1.SIZE && TryGetGP1(File.ReadAllBytes(file), out var gp1)) { return(gp1?.ConvertToPB7(sav)); } if (!PKX.IsPKM(fi.Length) && !MysteryGift.IsMysteryGift(fi.Length)) { return(null); } var data = File.ReadAllBytes(file); var ext = fi.Extension; var mg = MysteryGift.GetMysteryGift(data, ext); var gift = mg?.ConvertToPKM(sav); if (gift != null) { return(gift); } int prefer = PKX.GetPKMFormatFromExtension(ext, sav.Generation); return(PKMConverter.GetPKMfromBytes(data, prefer: prefer)); }
/// <summary> /// Gets a <see cref="PKM"/> from the provided <see cref="file"/> path, which is to be loaded to the <see cref="SaveFile"/>. /// </summary> /// <param name="file"><see cref="PKM"/> or <see cref="MysteryGift"/> file path.</param> /// <param name="sav">Generation Info</param> /// <returns>New <see cref="PKM"/> reference from the file.</returns> public static PKM?GetSingleFromPath(string file, ITrainerInfo sav) { var fi = new FileInfo(file); if (!fi.Exists) { return(null); } if (fi.Length == GP1.SIZE && TryGetGP1(File.ReadAllBytes(file), out var gp1)) { return(gp1.ConvertToPB7(sav)); } if (!PKX.IsPKM(fi.Length) && !MysteryGift.IsMysteryGift(fi.Length)) { return(null); } var data = File.ReadAllBytes(file); var ext = fi.Extension; var mg = MysteryGift.GetMysteryGift(data, ext); var gift = mg?.ConvertToPKM(sav); if (gift != null) { return(gift); } _ = TryGetPKM(data, out var pk, ext, sav); return(pk); }
public static IEnumerable <PKM> GetPKMsFromPaths(IEnumerable <string> filepaths, int generation) { return(filepaths .Where(file => PKX.IsPKM(new FileInfo(file).Length)) .Select(File.ReadAllBytes) .Select(data => PKMConverter.GetPKMfromBytes(data, prefer: generation)) .Where(temp => temp != null)); }
public static IEnumerable <PKM> GetPKMsFromPaths(IEnumerable <string> files, int generation) { var result = files .Where(file => PKX.IsPKM(new FileInfo(file).Length)) .Select(File.ReadAllBytes) .Select(data => PKMConverter.GetPKMfromBytes(data, prefer: generation)); foreach (var pkm in result) { if (pkm?.Species is > 0) { yield return(pkm); } } }
/// <summary> /// Tries to get an <see cref="IEnumerable{T}"/> object from the input parameters. /// </summary> /// <param name="data">Binary data</param> /// <param name="pkms">Output result</param> /// <param name="sav">Reference savefile used for PC Binary compatibility checks.</param> /// <returns>True if file object reference is valid, false if none found.</returns> public static bool TryGetPCBoxBin(byte[] data, out IEnumerable <byte[]> pkms, SaveFile?sav) { if (sav == null) { pkms = Array.Empty <byte[]>(); return(false); } var length = data.Length; if (PKX.IsPKM(length / sav.SlotCount) || PKX.IsPKM(length / sav.BoxSlotCount)) { pkms = ArrayUtil.EnumerateSplit(data, length); return(true); } pkms = Array.Empty <byte[]>(); return(false); }
/// <summary> /// Tries to get an <see cref="IEnumerable{T}"/> object from the input parameters. /// </summary> /// <param name="data">Binary data</param> /// <param name="pkms">Output result</param> /// <param name="SAV">Reference savefile used for PC Binary compatibility checks.</param> /// <returns>True if file object reference is valid, false if none found.</returns> public static bool TryGetPCBoxBin(byte[] data, out IEnumerable <byte[]> pkms, SaveFile SAV) { if (SAV == null) { pkms = Enumerable.Empty <byte[]>(); return(false); } var length = data.Length; if (PKX.IsPKM(length / SAV.SlotCount) || PKX.IsPKM(length / SAV.BoxSlotCount)) { pkms = PKX.GetPKMDataFromConcatenatedBinary(data, length); return(true); } pkms = Enumerable.Empty <byte[]>(); return(false); }
/// <summary> /// Gets a blank file for the save file. If the template path exists, a template load will be attempted. /// </summary> /// <param name="sav">Save File to fetch a template for</param> /// <param name="templatePath">Path to look for a template in</param> /// <returns>Template if it exists, or a blank <see cref="PKM"/> from the <see cref="sav"/></returns> public static PKM LoadTemplate(this SaveFile sav, string templatePath = null) { var blank = sav.BlankPKM; if (!Directory.Exists(templatePath)) { return(blank); } var di = new DirectoryInfo(templatePath); string path = Path.Combine(templatePath, $"{di.Name}.{blank.Extension}"); if (!File.Exists(path) || !PKX.IsPKM(new FileInfo(path).Length)) { return(blank); } var pk = PKMConverter.GetPKMfromBytes(File.ReadAllBytes(path), prefer: blank.Format); return(PKMConverter.ConvertToType(pk, sav.BlankPKM.GetType(), out path) ?? blank); // no sneaky plz; reuse string }
public static void AddFromLocalFile(string file, ConcurrentBag <SlotCache> db, ITrainerInfo dest, ICollection <string> validExtensions) { var fi = new FileInfo(file); if (!validExtensions.Contains(fi.Extension) || !PKX.IsPKM(fi.Length)) { return; } var data = File.ReadAllBytes(file); _ = FileUtil.TryGetPKM(data, out var pk, fi.Extension, dest); if (pk?.Species is not > 0) { return; } var info = new SlotInfoFile(file); var entry = new SlotCache(info, pk); db.Add(entry); }
public static void AddFromLocalFile(string file, ConcurrentBag <SlotCache> db, ITrainerInfo dest, ICollection <string> validExtensions) { var fi = new FileInfo(file); if (!validExtensions.Contains(fi.Extension) || !PKX.IsPKM(fi.Length)) { return; } var data = File.ReadAllBytes(file); var prefer = PKX.GetPKMFormatFromExtension(fi.Extension, dest.Generation); var pk = PKMConverter.GetPKMfromBytes(data, prefer); if (pk?.Species is not > 0) { return; } var info = new SlotInfoFile(file); var entry = new SlotCache(info, pk); db.Add(entry); }
/// <summary> /// Gets the generation of the Pokemon data. /// </summary> /// <param name="data">Raw data representing a Pokemon.</param> /// <returns>An integer indicating the generation of the PKM file, or -1 if the data is invalid.</returns> public static int GetPKMDataFormat(ReadOnlySpan <byte> data) { if (!PKX.IsPKM(data.Length)) { return(-1); } switch (data.Length) { case PokeCrypto.SIZE_1JLIST or PokeCrypto.SIZE_1ULIST: return(1); case PokeCrypto.SIZE_2JLIST or PokeCrypto.SIZE_2ULIST: case PokeCrypto.SIZE_2STADIUM: return(2); case PokeCrypto.SIZE_3PARTY or PokeCrypto.SIZE_3STORED: case PokeCrypto.SIZE_3CSTORED: case PokeCrypto.SIZE_3XSTORED: return(3); case PokeCrypto.SIZE_4PARTY or PokeCrypto.SIZE_4STORED: case PokeCrypto.SIZE_5PARTY: if ((ReadUInt16LittleEndian(data[0x4..]) == 0) && (ReadUInt16LittleEndian(data[0x80..]) >= 0x3333 || data[0x5F] >= 0x10) && ReadUInt16LittleEndian(data[0x46..]) == 0) // PK5
/// <summary> /// Gets a blank file for the save file. If the template path exists, a template load will be attempted. /// </summary> /// <param name="sav">Save File to fetch a template for</param> /// <param name="templatePath">Path to look for a template in</param> /// <returns>Template if it exists, or a blank <see cref="PKM"/> from the <see cref="sav"/></returns> public static PKM LoadTemplate(this SaveFile sav, string templatePath) { if (!Directory.Exists(templatePath)) { return(LoadTemplate(sav)); } var di = new DirectoryInfo(templatePath); string path = Path.Combine(templatePath, $"{di.Name}.{sav.PKMType.Name.ToLower()}"); if (!File.Exists(path) || !PKX.IsPKM(new FileInfo(path).Length)) { return(LoadTemplate(sav)); } var pk = PKMConverter.GetPKMfromBytes(File.ReadAllBytes(path), prefer: sav.Generation); if (pk == null) { return(LoadTemplate(sav)); } return(PKMConverter.ConvertToType(pk, sav.BlankPKM.GetType(), out _) ?? LoadTemplate(sav)); }