pkNX/pkNX.Game/GameLocation.cs
sora10pls 414b49e8e0 Update GameLocation.cs
No need to check ExeFS since RomFS can already differentiate the games.
2021-09-04 14:57:32 -04:00

121 lines
4.5 KiB
C#

using System;
using System.IO;
using System.Linq;
using pkNX.Structures;
namespace pkNX.Game
{
/// <summary>
/// Environment Data where the Game's Data is located on the user's machine.
/// </summary>
public sealed class GameLocation
{
/// <summary>
/// Location of the RomFS
/// </summary>
public string RomFS { get; }
/// <summary>
/// Location of the ExeFS.
/// </summary>
public string ExeFS { get; }
/// <summary>
/// Game version the files belong to.
/// </summary>
public GameVersion Game { get; }
private GameLocation(string romfs, string exefs, GameVersion game)
{
Game = game;
RomFS = romfs;
ExeFS = exefs;
}
/// <summary>
/// Determines the <see cref="GameVersion"/> of the input directory and detects the location of files for editing.
/// </summary>
/// <param name="dir">Directory the game data is in</param>
/// <returns>New <see cref="GameLocation"/> object with references to file paths.</returns>
public static GameLocation GetGame(string dir)
{
if (dir == null || !Directory.Exists(dir))
return null;
var dirs = Directory.GetDirectories(dir);
var romfs = Array.Find(dirs, z => Path.GetFileName(z).StartsWith("rom", StringComparison.CurrentCultureIgnoreCase));
var exefs = Array.Find(dirs, z => Path.GetFileName(z).StartsWith("exe", StringComparison.CurrentCultureIgnoreCase));
if (romfs == null && exefs == null)
return null;
var files = Directory.GetFiles(romfs, "*", SearchOption.AllDirectories);
var game = GetGameFromCount(files.Length, romfs, exefs);
if (game == GameVersion.Invalid)
return null;
return new GameLocation(romfs, exefs, game);
}
private const int FILECOUNT_XY = 271;
private const int FILECOUNT_ORASDEMO = 301;
private const int FILECOUNT_ORAS = 299;
private const int FILECOUNT_SMDEMO = 239;
private const int FILECOUNT_SM = 311;
private const int FILECOUNT_USUM = 333;
private const int FILECOUNT_GG = 27818;
private const int FILECOUNT_SWSH = 41702;
private const int FILECOUNT_SWSH_1 = 41951; // Ver. 1.1.0 update (Galarian Slowpoke)
private const int FILECOUNT_SWSH_2 = 46867; // Ver. 1.2.0 update (Isle of Armor)
private const int FILECOUNT_SWSH_3 = 50494; // Ver. 1.3.0 update (Crown Tundra)
private static GameVersion GetGameFromCount(int fileCount, string romfs, string exefs)
{
string GetTitleID() => BitConverter.ToString(File.ReadAllBytes(Path.Combine(exefs, "main.npdm")).Skip(0x290).Take(0x08).Reverse().ToArray()).Replace("-", "");
switch (fileCount)
{
case FILECOUNT_XY: return GameVersion.XY;
case FILECOUNT_ORASDEMO: return GameVersion.ORASDEMO;
case FILECOUNT_ORAS: return GameVersion.ORAS;
case FILECOUNT_SMDEMO: return GameVersion.SMDEMO;
case FILECOUNT_SM:
{
var encdata = Path.Combine(romfs, "a", "0", "8", "2");
if (File.Exists(encdata) && new FileInfo(encdata).Length != 0)
return GameVersion.SN;
return GameVersion.MN;
}
case FILECOUNT_USUM:
{
var encdata = Path.Combine(romfs, "a", "0", "8", "2");
if (File.Exists(encdata) && new FileInfo(encdata).Length != 0)
return GameVersion.US;
return GameVersion.UM;
}
case FILECOUNT_GG:
{
bool eevee = Directory.Exists(Path.Combine(romfs, "bin", "movies", "EEVEE_GO"));
if (eevee)
return GameVersion.GE;
return GameVersion.GP;
}
case FILECOUNT_SWSH:
case FILECOUNT_SWSH_1:
case FILECOUNT_SWSH_2:
case FILECOUNT_SWSH_3:
{
if (exefs == null)
return GameVersion.SWSH;
return GetTitleID() == "0100ABF008968000" ? GameVersion.SW : GameVersion.SH;
}
default:
return GameVersion.Invalid;
}
}
}
}