Add custom save type loading (hacks)

plugin adds a reader -> reader checks if it is a non-PKHeX.Core save type (they'd implement their own savefile/etc type) -> returns a matching save object if so

basically bypasses the base PKHeX logic
This commit is contained in:
Kurt
2021-02-13 01:53:38 -08:00
parent 6e4908b21e
commit 4e92195b80
2 changed files with 45 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
namespace PKHeX.Core
{
#if !(EXCLUDE_EMULATOR_FORMATS && EXCLUDE_HACKS)
/// <summary>
/// Provides handling for recognizing atypical save file formats.
/// </summary>
@@ -19,4 +20,21 @@ public interface ISaveHandler
/// <returns>Null if not a valid save file for this handler's format. Returns an object containing header, footer, and inner data references.</returns>
SaveHandlerSplitResult? TrySplit(byte[] input);
}
#endif
#if !EXCLUDE_HACKS
/// <summary>
/// Provides handling for recognizing atypical save file formats.
/// </summary>
public interface ISaveReader : ISaveHandler
{
/// <summary>
/// Reads a save file from the <see cref="data"/>
/// </summary>
/// <param name="data">Raw input data</param>
/// <param name="path">Optional file path.</param>
/// <returns>Save File object, or null if invalid. Check <see cref="ISaveHandler"/> if it is compatible first.</returns>
SaveFile? ReadSaveFile(byte[] data, string? path = null);
}
#endif
}

View File

@@ -61,6 +61,15 @@ public static class SaveUtil
private static readonly SaveHandlerGCI DolphinHandler = new();
#if !EXCLUDE_HACKS
/// <summary>
/// Specialized readers for loading save files from non-standard games (e.g. hacks).
/// </summary>
// ReSharper disable once CollectionNeverUpdated.Global
public static readonly List<ISaveReader> CustomSaveReaders = new();
#endif
#if !EXCLUDE_EMULATOR_FORMATS
/// <summary>
/// Pre-formatters for loading save files from non-standard formats (e.g. emulators).
/// </summary>
@@ -70,6 +79,7 @@ public static class SaveUtil
new SaveHandlerDeSmuME(),
new SaveHandlerARDS(),
};
#endif
internal static readonly HashSet<int> SizesSWSH = new()
{
@@ -487,7 +497,7 @@ private static GameVersion GetIsG8SAV(byte[] data)
public static SaveFile? GetVariantSAV(string path)
{
var data = File.ReadAllBytes(path);
var sav = GetVariantSAV(data);
var sav = GetVariantSAV(data, path);
if (sav == null)
return null;
sav.Metadata.SetExtraInfo(path);
@@ -496,13 +506,27 @@ private static GameVersion GetIsG8SAV(byte[] data)
/// <summary>Creates an instance of a SaveFile using the given save data.</summary>
/// <param name="data">Save data from which to create a SaveFile.</param>
/// <param name="path">Optional save file path, may help initialize a non-standard save file format.</param>
/// <returns>An appropriate type of save file for the given data, or null if the save data is invalid.</returns>
public static SaveFile? GetVariantSAV(byte[] data)
public static SaveFile? GetVariantSAV(byte[] data, string? path = null)
{
#if !EXCLUDE_HACKS
foreach (var h in CustomSaveReaders)
{
if (!h.IsRecognized(data.Length))
continue;
var custom = h.ReadSaveFile(data, path);
if (custom != null)
return custom;
}
#endif
var sav = GetVariantSAVInternal(data);
if (sav != null)
return sav;
#if !EXCLUDE_EMULATOR_FORMATS
foreach (var h in Handlers)
{
if (!h.IsRecognized(data.Length))
@@ -519,6 +543,7 @@ private static GameVersion GetIsG8SAV(byte[] data)
sav.Metadata.SetExtraInfo(split.Header, split.Footer);
return sav;
}
#endif
// unrecognized.
return null;