pkNX/pkNX.Game/File/GameFileMapping.cs
2018-11-13 19:44:43 -08:00

310 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using pkNX.Containers;
using pkNX.Structures;
namespace pkNX.Game
{
/// <summary>
/// Handles file retrieval and lifetime management for a <see cref="GameLocation"/>'s <see cref="IFileContainer"/> data.
/// </summary>
public class GameFileMapping
{
private readonly Dictionary<GameFile, IFileContainer> Cache = new Dictionary<GameFile, IFileContainer>();
private readonly IReadOnlyCollection<GameFileReference> FileMap;
public readonly ContainerHandler ProgressTracker = new ContainerHandler();
public readonly CancellationTokenSource TokenSource = new CancellationTokenSource();
private readonly GameLocation ROM;
public GameFileMapping(GameLocation rom) => FileMap = GetMapping((ROM = rom).Game);
internal IFileContainer GetFile(GameFile file, int language)
{
if (file == GameFile.GameText || file == GameFile.StoryText)
file += language; // shift to localized language
if (Cache.TryGetValue(file, out var container))
return container;
var info = FileMap.FirstOrDefault(f => f.File == file);
if (info == null)
throw new ArgumentException($"Unknown {nameof(GameFile)} provided.", file.ToString());
var basePath = info.Parent == ContainerParent.ExeFS ? ROM.ExeFS : ROM.RomFS;
container = info.Get(basePath);
Cache.Add(file, container);
return container;
}
internal void SaveAll()
{
foreach (var container in Cache)
{
var c = container.Value;
c.SaveAs(c.FilePath, ProgressTracker, TokenSource.Token);
Cache.Remove(container.Key);
}
}
public static IReadOnlyCollection<GameFileReference> GetMapping(GameVersion game)
{
switch (game)
{
case GameVersion.SN: return SN;
case GameVersion.MN: return MN;
case GameVersion.US: return US;
case GameVersion.UM: return UM;
case GameVersion.XY: return XY;
case GameVersion.GG: return GG;
case GameVersion.ORASDEMO:
case GameVersion.ORAS: return AO;
case GameVersion.SMDEMO: return SMDEMO;
}
return null;
}
#region Games
private static readonly GameFileReference[] XY =
{
new GameFileReference(005, GameFile.MoveSprites),
new GameFileReference(012, GameFile.Encounters),
new GameFileReference(038, GameFile.TrainerData),
new GameFileReference(039, GameFile.TrainerClass),
new GameFileReference(040, GameFile.TrainerPoke),
new GameFileReference(041, GameFile.MapGameRegion),
new GameFileReference(042, GameFile.MapMatrix),
new GameFileReference(072, GameFile.GameText0),
new GameFileReference(073, GameFile.GameText1),
new GameFileReference(074, GameFile.GameText2),
new GameFileReference(075, GameFile.GameText3),
new GameFileReference(076, GameFile.GameText4),
new GameFileReference(077, GameFile.GameText5),
new GameFileReference(078, GameFile.GameText6),
new GameFileReference(079, GameFile.GameText7),
new GameFileReference(080, GameFile.StoryText0),
new GameFileReference(081, GameFile.StoryText1),
new GameFileReference(082, GameFile.StoryText2),
new GameFileReference(083, GameFile.StoryText3),
new GameFileReference(084, GameFile.StoryText4),
new GameFileReference(085, GameFile.StoryText5),
new GameFileReference(086, GameFile.StoryText6),
new GameFileReference(087, GameFile.StoryText7),
new GameFileReference(104, GameFile.Wallpaper),
new GameFileReference(165, GameFile.TitleScreen),
new GameFileReference(203, GameFile.FacilityPokeNormal),
new GameFileReference(204, GameFile.FacilityTrainerNormal),
new GameFileReference(205, GameFile.FacilityPokeSuper),
new GameFileReference(206, GameFile.FacilityTrainerSuper),
new GameFileReference(212, GameFile.MoveStats),
new GameFileReference(213, GameFile.EggMoves),
new GameFileReference(214, GameFile.Learnsets),
new GameFileReference(215, GameFile.Evolutions),
new GameFileReference(216, GameFile.MegaEvolutions),
new GameFileReference(218, GameFile.PersonalStats),
new GameFileReference(220, GameFile.ItemStats),
};
private static readonly GameFileReference[] AO =
{
new GameFileReference(013, GameFile.Encounters),
new GameFileReference(036, GameFile.TrainerData),
new GameFileReference(037, GameFile.TrainerClass),
new GameFileReference(038, GameFile.TrainerPoke),
new GameFileReference(039, GameFile.MapGameRegion),
new GameFileReference(040, GameFile.MapMatrix),
new GameFileReference(071, GameFile.GameText0),
new GameFileReference(072, GameFile.GameText1),
new GameFileReference(073, GameFile.GameText2),
new GameFileReference(074, GameFile.GameText3),
new GameFileReference(075, GameFile.GameText4),
new GameFileReference(076, GameFile.GameText5),
new GameFileReference(077, GameFile.GameText6),
new GameFileReference(078, GameFile.GameText7),
new GameFileReference(079, GameFile.StoryText0),
new GameFileReference(080, GameFile.StoryText1),
new GameFileReference(081, GameFile.StoryText2),
new GameFileReference(082, GameFile.StoryText3),
new GameFileReference(083, GameFile.StoryText4),
new GameFileReference(084, GameFile.StoryText5),
new GameFileReference(085, GameFile.StoryText6),
new GameFileReference(086, GameFile.StoryText7),
new GameFileReference(103, GameFile.Wallpaper),
new GameFileReference(152, GameFile.TitleScreen),
new GameFileReference(182, GameFile.FacilityPokeNormal),
new GameFileReference(183, GameFile.FacilityTrainerNormal),
new GameFileReference(184, GameFile.FacilityPokeSuper),
new GameFileReference(185, GameFile.FacilityTrainerSuper),
new GameFileReference(189, GameFile.MoveStats),
new GameFileReference(190, GameFile.EggMoves),
new GameFileReference(191, GameFile.Learnsets),
new GameFileReference(192, GameFile.Evolutions),
new GameFileReference(193, GameFile.MegaEvolutions),
new GameFileReference(195, GameFile.PersonalStats),
new GameFileReference(197, GameFile.ItemStats),
};
#endregion
#region Gen7
private static readonly GameFileReference[] SMDEMO =
{
new GameFileReference(011, GameFile.MoveStats),
new GameFileReference(012, GameFile.EggMoves),
new GameFileReference(013, GameFile.Learnsets),
new GameFileReference(014, GameFile.Evolutions),
new GameFileReference(015, GameFile.MegaEvolutions),
new GameFileReference(017, GameFile.PersonalStats),
new GameFileReference(019, GameFile.ItemStats),
new GameFileReference(030, GameFile.GameText0),
new GameFileReference(031, GameFile.GameText1),
new GameFileReference(032, GameFile.GameText2),
new GameFileReference(033, GameFile.GameText3),
new GameFileReference(034, GameFile.GameText4),
new GameFileReference(035, GameFile.GameText5),
new GameFileReference(036, GameFile.GameText6),
new GameFileReference(037, GameFile.GameText7),
new GameFileReference(038, GameFile.GameText8),
new GameFileReference(039, GameFile.GameText9),
new GameFileReference(040, GameFile.StoryText0),
new GameFileReference(041, GameFile.StoryText1),
new GameFileReference(042, GameFile.StoryText2),
new GameFileReference(043, GameFile.StoryText3),
new GameFileReference(044, GameFile.StoryText4),
new GameFileReference(045, GameFile.StoryText5),
new GameFileReference(046, GameFile.StoryText6),
new GameFileReference(047, GameFile.StoryText7),
new GameFileReference(048, GameFile.StoryText8),
new GameFileReference(049, GameFile.StoryText9),
new GameFileReference(076, GameFile.ZoneData),
new GameFileReference(091, GameFile.WorldData),
new GameFileReference(101, GameFile.TrainerClass),
new GameFileReference(102, GameFile.TrainerData),
new GameFileReference(103, GameFile.TrainerPoke),
};
private static readonly GameFileReference[] SM =
{
new GameFileReference(011, GameFile.MoveStats),
new GameFileReference(012, GameFile.EggMoves),
new GameFileReference(013, GameFile.Learnsets),
new GameFileReference(014, GameFile.Evolutions),
new GameFileReference(015, GameFile.MegaEvolutions),
new GameFileReference(017, GameFile.PersonalStats),
new GameFileReference(019, GameFile.ItemStats),
new GameFileReference(030, GameFile.GameText0),
new GameFileReference(031, GameFile.GameText1),
new GameFileReference(032, GameFile.GameText2),
new GameFileReference(033, GameFile.GameText3),
new GameFileReference(034, GameFile.GameText4),
new GameFileReference(035, GameFile.GameText5),
new GameFileReference(036, GameFile.GameText6),
new GameFileReference(037, GameFile.GameText7),
new GameFileReference(038, GameFile.GameText8),
new GameFileReference(039, GameFile.GameText9),
new GameFileReference(040, GameFile.StoryText0),
new GameFileReference(041, GameFile.StoryText1),
new GameFileReference(042, GameFile.StoryText2),
new GameFileReference(043, GameFile.StoryText3),
new GameFileReference(044, GameFile.StoryText4),
new GameFileReference(045, GameFile.StoryText5),
new GameFileReference(046, GameFile.StoryText6),
new GameFileReference(047, GameFile.StoryText7),
new GameFileReference(048, GameFile.StoryText8),
new GameFileReference(049, GameFile.StoryText9),
new GameFileReference(077, GameFile.ZoneData),
new GameFileReference(091, GameFile.WorldData),
new GameFileReference(104, GameFile.TrainerClass),
new GameFileReference(105, GameFile.TrainerData),
new GameFileReference(106, GameFile.TrainerPoke),
new GameFileReference(155, GameFile.EncounterStatic),
new GameFileReference(267, GameFile.Pickup),
new GameFileReference(277, GameFile.FacilityPokeNormal),
new GameFileReference(278, GameFile.FacilityTrainerNormal),
new GameFileReference(279, GameFile.FacilityPokeSuper),
new GameFileReference(280, GameFile.FacilityTrainerSuper),
};
/// <summary>
/// Ultra Sun &amp; Ultra Moon
/// </summary>
private static readonly GameFileReference[] UU =
{
new GameFileReference(011, GameFile.MoveStats),
new GameFileReference(012, GameFile.EggMoves),
new GameFileReference(013, GameFile.Learnsets),
new GameFileReference(014, GameFile.Evolutions),
new GameFileReference(015, GameFile.MegaEvolutions),
new GameFileReference(017, GameFile.PersonalStats),
new GameFileReference(019, GameFile.ItemStats),
new GameFileReference(030, GameFile.GameText0),
new GameFileReference(031, GameFile.GameText1),
new GameFileReference(032, GameFile.GameText2),
new GameFileReference(033, GameFile.GameText3),
new GameFileReference(034, GameFile.GameText4),
new GameFileReference(035, GameFile.GameText5),
new GameFileReference(036, GameFile.GameText6),
new GameFileReference(037, GameFile.GameText7),
new GameFileReference(038, GameFile.GameText8),
new GameFileReference(039, GameFile.GameText9),
new GameFileReference(040, GameFile.StoryText0),
new GameFileReference(041, GameFile.StoryText1),
new GameFileReference(042, GameFile.StoryText2),
new GameFileReference(043, GameFile.StoryText3),
new GameFileReference(044, GameFile.StoryText4),
new GameFileReference(045, GameFile.StoryText5),
new GameFileReference(046, GameFile.StoryText6),
new GameFileReference(047, GameFile.StoryText7),
new GameFileReference(048, GameFile.StoryText8),
new GameFileReference(049, GameFile.StoryText9),
new GameFileReference(077, GameFile.ZoneData),
new GameFileReference(091, GameFile.WorldData),
new GameFileReference(105, GameFile.TrainerClass),
new GameFileReference(106, GameFile.TrainerData),
new GameFileReference(107, GameFile.TrainerPoke),
new GameFileReference(159, GameFile.EncounterStatic),
new GameFileReference(271, GameFile.Pickup),
new GameFileReference(281, GameFile.FacilityPokeNormal),
new GameFileReference(282, GameFile.FacilityTrainerNormal),
new GameFileReference(283, GameFile.FacilityPokeSuper),
new GameFileReference(284, GameFile.FacilityTrainerSuper),
};
/// <summary>
/// Let's Go Pikachu &amp; Let's Go Eevee
/// </summary>
private static readonly GameFileReference[] GG =
{
};
#endregion
#region Split Versions
private static readonly GameFileReference[] SN = SM.Concat(new[] {new GameFileReference(082, GameFile.Encounters)}).ToArray();
private static readonly GameFileReference[] MN = SM.Concat(new[] {new GameFileReference(083, GameFile.Encounters)}).ToArray();
private static readonly GameFileReference[] US = UU.Concat(new[] {new GameFileReference(082, GameFile.Encounters)}).ToArray();
private static readonly GameFileReference[] UM = UU.Concat(new[] {new GameFileReference(083, GameFile.Encounters)}).ToArray();
#endregion
}
}