using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace PKHeX.Core
{
///
/// Logic for detecting supported binary object formats.
///
public static class FileUtil
{
///
/// Attempts to get a binary object from the provided path.
///
///
/// Reference savefile used for PC Binary compatibility checks.
/// Supported file object reference, null if none found.
public static object GetSupportedFile(string path, SaveFile reference = null)
{
try
{
var fi = new FileInfo(path);
if (IsFileTooBig(fi.Length) || IsFileTooSmall(fi.Length))
return null;
var data = File.ReadAllBytes(path);
var ext = Path.GetExtension(path);
return GetSupportedFile(data, ext, reference);
}
catch (Exception e)
{
Debug.WriteLine(MessageStrings.MsgFileInUse);
Debug.WriteLine(e.Message);
return null;
}
}
///
/// Attempts to get a binary object from the provided inputs.
///
/// Binary data for the file.
/// File extension used as a hint.
/// Reference savefile used for PC Binary compatibility checks.
/// Supported file object reference, null if none found.
public static object GetSupportedFile(byte[] data, string ext, SaveFile reference = null)
{
if (TryGetSAV(data, out var sav))
return sav;
if (TryGetMemoryCard(data, out var mc))
return mc;
if (TryGetPKM(data, out var pk, ext))
return pk;
if (TryGetPCBoxBin(data, out IEnumerable pks, reference))
return pks;
if (TryGetBattleVideo(data, out BattleVideo bv))
return bv;
if (TryGetMysteryGift(data, out MysteryGift g, ext))
return g;
return null;
}
///
/// Checks if the length is too big to be a detectable file.
///
/// File size
public static bool IsFileTooBig(long length)
{
if (length <= 0x100000)
return false;
if (length == SaveUtil.SIZE_G4BR)
return false;
if (SAV3GCMemoryCard.IsMemoryCardSize(length))
return false; // pbr/GC have size > 1MB
return true;
}
///
/// Checks if the length is too small to be a detectable file.
///
/// File size
public static bool IsFileTooSmall(long length) => length < 0x20;
///
/// Tries to get an object from the input parameters.
///
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
public static bool TryGetSAV(byte[] data, out SaveFile sav)
{
sav = SaveUtil.GetVariantSAV(data);
return sav != null;
}
///
/// Tries to get an object from the input parameters.
///
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
public static bool TryGetMemoryCard(byte[] data, out SAV3GCMemoryCard memcard)
{
if (!SAV3GCMemoryCard.IsMemoryCardSize(data))
{
memcard = null;
return false;
}
memcard = new SAV3GCMemoryCard(data);
return true;
}
///
/// Tries to get an object from the input parameters.
///
/// Binary data
/// Output result
/// Format hint
/// Reference savefile used for PC Binary compatibility checks.
/// True if file object reference is valid, false if none found.
public static bool TryGetPKM(byte[] data, out PKM pk, string ext, ITrainerInfo sav = null)
{
if (ext == ".pgt") // size collision with pk6
{
pk = default(PKM);
return false;
}
var format = PKX.GetPKMFormatFromExtension(ext, sav?.Generation ?? 6);
pk = PKMConverter.GetPKMfromBytes(data, prefer: format);
return pk != null;
}
///
/// Tries to get an object from the input parameters.
///
/// Binary data
/// Output result
/// Reference savefile used for PC Binary compatibility checks.
/// True if file object reference is valid, false if none found.
public static bool TryGetPCBoxBin(byte[] data, out IEnumerable pkms, SaveFile SAV)
{
if (SAV == null)
{
pkms = Enumerable.Empty();
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();
return false;
}
///
/// Tries to get a object from the input parameters.
///
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
public static bool TryGetBattleVideo(byte[] data, out BattleVideo bv)
{
bv = BattleVideo.GetVariantBattleVideo(data);
return bv != null;
}
///
/// Tries to get a object from the input parameters.
///
/// Binary data
/// Output result
/// Format hint
/// True if file object reference is valid, false if none found.
public static bool TryGetMysteryGift(byte[] data, out MysteryGift mg, string ext)
{
mg = MysteryGift.GetMysteryGift(data, ext);
return mg != null;
}
///
/// Gets a Temp location File Name for the .
///
/// Data to be exported
/// Data is to be encrypted
/// Path to temporary file location to write to.
public static string GetPKMTempFileName(PKM pk, bool encrypt)
{
string fn = pk.FileNameWithoutExtension;
string filename = fn + (encrypt ? $".ek{pk.Format}" : $".{pk.Extension}");
return Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
}
///
/// Gets a from the provided path, which is to be loaded to the .
///
/// or file path.
/// Generation Info
/// New reference from the file.
public static PKM GetSingleFromPath(string file, ITrainerInfo SAV)
{
var fi = new FileInfo(file);
if (!fi.Exists)
return null;
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);
}
}
}