Gen7 Config refactoring

Old pk3DS only supported 0/1 for xy/oras; need to have a little more
flexibility than that!
This commit is contained in:
Kaphotics
2016-10-29 21:11:52 -07:00
parent 0028d6426c
commit 4f253a6da0
5 changed files with 276 additions and 57 deletions

View File

@@ -0,0 +1,26 @@
using System.IO;
namespace pk3DS
{
public class GARCReference
{
public readonly int FileNumber;
public readonly string Name;
private int A => (FileNumber / 100) % 10;
private int B => (FileNumber / 10) % 10;
private int C => (FileNumber / 1) % 10;
public readonly bool LanguageVariant;
public string Reference => Path.Combine("a", A.ToString(), B.ToString(), C.ToString());
public GARCReference(int file, string name, bool lv = false)
{
Name = name;
FileNumber = file;
LanguageVariant = lv;
}
public GARCReference getRelativeGARC(int offset, string name = "")
{
return new GARCReference(FileNumber + offset, name);
}
}
}

164
pk3DS/Game/GameConfig.cs Normal file
View File

@@ -0,0 +1,164 @@
using System.Collections.Generic;
using System.Linq;
namespace pk3DS
{
public class GameConfig
{
private const int FILECOUNT_XY = 271;
private const int FILECOUNT_ORASDEMO = 301;
private const int FILECOUNT_ORAS = 299;
private const int FILECOUNT_SMDEMO = 238;
private const int FILECOUNT_SM = 1;
public readonly List<GARCReference> Files = new List<GARCReference>();
public GARCReference getGARC(string name) { return Files.FirstOrDefault(file => file.Name == name); }
public bool XY => Version == GameVersion.XY;
public bool ORAS => Version == GameVersion.ORAS || Version == GameVersion.ORASDEMO;
public bool SM => Version == GameVersion.SM || Version == GameVersion.SMDEMO;
private readonly GameVersion Version = GameVersion.Invalid;
public bool IsRebuildable(int fileCount)
{
switch (fileCount)
{
case FILECOUNT_XY:
return Version == GameVersion.XY;
case FILECOUNT_ORAS:
return Version == GameVersion.ORAS;
case FILECOUNT_ORASDEMO:
return Version == GameVersion.ORASDEMO;
case FILECOUNT_SMDEMO:
return Version == GameVersion.SMDEMO;
case FILECOUNT_SM:
return Version == GameVersion.SM;
}
return false;
}
public GameConfig(int fileCount)
{
GameVersion game = GameVersion.Invalid;
switch (fileCount)
{
case FILECOUNT_XY:
game = GameVersion.XY;
break;
case FILECOUNT_ORAS:
case FILECOUNT_ORASDEMO:
game = GameVersion.ORAS;
break;
case FILECOUNT_SMDEMO:
case FILECOUNT_SM:
game = GameVersion.SM;
break;
}
if (game == GameVersion.Invalid)
return;
Files.AddRange(getGameFiles(game));
Version = game;
}
public GameConfig(GameVersion game)
{
Files.AddRange(getGameFiles(game));
Version = game;
}
private static IEnumerable<GARCReference> getGameFiles(GameVersion game)
{
switch (game)
{
case GameVersion.XY:
return setupXY();
case GameVersion.ORASDEMO:
case GameVersion.ORAS:
return setupORAS();
case GameVersion.SMDEMO:
case GameVersion.SM:
return setupSM();
default:
return null;
}
}
private static IEnumerable<GARCReference> setupXY()
{
return new[]
{
new GARCReference(005,"movesprite"),
new GARCReference(012,"encdata"),
new GARCReference(038, "trdata"),
new GARCReference(040, "trpoke"),
new GARCReference(041, "mapGR"),
new GARCReference(042, "mapMatrix"),
new GARCReference(104, "wallpaper"),
new GARCReference(165, "titlescreen"),
new GARCReference(203, "maisonpkN"),
new GARCReference(204, "maisontrN"),
new GARCReference(205, "maisonpkS"),
new GARCReference(206, "maisontrS"),
new GARCReference(212, "move"),
new GARCReference(213, "eggmove"),
new GARCReference(214, "levelup"),
new GARCReference(215, "evolution"),
new GARCReference(216, "megaevo"),
new GARCReference(218, "personal"),
new GARCReference(220, "item"),
// Varied
new GARCReference(072, "gametext", true),
new GARCReference(080, "storytext", true),
};
}
private static IEnumerable<GARCReference> setupORAS()
{
return new[]
{
new GARCReference(013, "encdata"),
new GARCReference(036, "trdata"),
new GARCReference(038, "trpoke"),
new GARCReference(039, "mapGR"),
new GARCReference(040, "mapMatrix"),
new GARCReference(103, "wallpaper"),
new GARCReference(152, "titlescreen"),
new GARCReference(182, "maisonpkN"),
new GARCReference(183, "maisontrN"),
new GARCReference(184, "maisonpkS"),
new GARCReference(185, "maisontrS"),
new GARCReference(189, "move"),
new GARCReference(190, "eggmove"),
new GARCReference(191, "levelup"),
new GARCReference(192, "evolution"),
new GARCReference(193, "megaevo"),
new GARCReference(195, "personal"),
new GARCReference(197, "item"),
// Varied
new GARCReference(071, "gametext", true),
new GARCReference(079, "storytext", true),
};
}
private static IEnumerable<GARCReference> setupSM()
{
return new[]
{
new GARCReference(011, "move"),
new GARCReference(012, "eggmove"),
new GARCReference(013, "levelup"),
new GARCReference(014, "evolution"),
new GARCReference(015, "megaevo"),
new GARCReference(017, "personal"),
new GARCReference(019, "item"),
new GARCReference(081, "encdata"),
new GARCReference(101, "trclass"),
new GARCReference(102, "trdata"),
new GARCReference(013, "trpoke"),
// Varied
new GARCReference(030, "gametext", true),
new GARCReference(040, "storytext", true),
};
}
}
}

48
pk3DS/Game/GameVersion.cs Normal file
View File

@@ -0,0 +1,48 @@
namespace pk3DS
{
public enum GameVersion
{
// Not actually stored values, but assigned as properties.
XD = -11,
COLO = -10,
BATREV = -7,
RSBOX = -5,
GS = -4,
C = -3,
// Indicators
Invalid = -2,
Any = -1,
Unknown = 0,
// Version IDs, also stored in PKM structure
/*Gen3*/
S = 1, R = 2, E = 3, FR = 4, LG = 5, CXD = 15,
/*Gen4*/
D = 10, P = 11, Pt = 12, HG = 7, SS = 8,
/*Gen5*/
W = 20, B = 21, W2 = 22, B2 = 23,
/*Gen6*/
X = 24, Y = 25, AS = 26, OR = 27,
/*Gen7*/
SN = 30, MN = 31,
// Game Groupings (SaveFile type)
RBY = 98,
GSC = 99,
RS = 100,
FRLG = 101,
DP = 102,
HGSS = 103,
BW = 104,
B2W2 = 105,
XY = 106,
ORASDEMO = 107,
ORAS = 108,
SM = 109,
SMDEMO,
// Extra Game Groupings (Generation)
Gen1, Gen2, Gen3, Gen4, Gen5, Gen6, Gen7
}
}

View File

@@ -123,13 +123,13 @@ private void changeLanguage(object sender, EventArgs e)
while (threads > 0) Thread.Sleep(50);
// Gather the Text Language Strings
updateStatus($"GARC Get: {"gametext"} @ {getGARCFileName("gametext")}... ");
threadGet(RomFSPath + getGARCFileName("gametext"), "gametext", true, true);
threadGet(Path.Combine(RomFSPath, getGARCFileName("gametext")), "gametext", true, true);
while (threads > 0) Thread.Sleep(50);
if (!Directory.Exists("personal"))
{
updateStatus($"GARC Get: {"personal"} @ {getGARCFileName("personal")}... ");
threadGet(RomFSPath + getGARCFileName("personal"), "personal", true, true);
threadGet(Path.Combine(RomFSPath, getGARCFileName("personal")), "personal", true, true);
}
while (threads > 0) Thread.Sleep(50);
// Refresh Personal Stats
@@ -152,13 +152,13 @@ private void formClosing(object sender, FormClosingEventArgs e)
// Set the GameText back as other forms may have edited it.
updateStatus($"GARC Get: {"gametext"} @ {getGARCFileName("gametext")}... ");
threadSet(RomFSPath + getGARCFileName("gametext"), "gametext", false);
threadSet(Path.Combine(RomFSPath, getGARCFileName("gametext")), "gametext", false);
while (threads > 0) Thread.Sleep(100);
Thread.Sleep(200); // Small gap between beeps for faster computers.
updateStatus($"GARC Get: {"personal"} @ {getGARCFileName("personal")}... ");
threadSet(RomFSPath + getGARCFileName("personal"), "personal", false);
threadSet(Path.Combine(RomFSPath, getGARCFileName("personal")), "personal", false);
while (threads > 0) Thread.Sleep(100);
if (Directory.Exists("gametext")) Directory.Delete("gametext", true);
@@ -264,23 +264,18 @@ private void updateGameInfo()
? "pk3DS" // nothing else
: "pk3DS - " + SMDH.AppInfo[AILang[Language]].ShortDescription;
}
private int checkGameType(string[] files)
private static GameConfig checkGameType(string[] files)
{
try
{
if (files.Length > 1000)
return -1;
int aFiles = Directory.GetFiles(Path.Combine(Directory.GetParent(files[0]).FullName, "a"),
"*", SearchOption.AllDirectories).Length;
if (aFiles == 271)
return 0; // XY
if (aFiles == 299)
return 1; // ORAS
if (aFiles == 301) // rootFiles == meh
return 1;
return null;
string[] fileArr = Directory.GetFiles(Path.Combine(Directory.GetParent(files[0]).FullName, "a"), "*", SearchOption.AllDirectories);
int fileCount = fileArr.Count(file => Path.GetFileName(file)?.Length == 1);
return new GameConfig(fileCount);
}
catch { }
return -1;
return null;
}
private bool checkIfRomFS(string path)
{
@@ -289,17 +284,19 @@ private bool checkIfRomFS(string path)
// Check to see if the folder is romfs
if (fi.Name == "a")
{
int game = checkGameType(Directory.GetFiles(path, "*", SearchOption.AllDirectories));
if (game < 0) // Unknown
var cfg = checkGameType(Directory.GetFiles(path, "*", SearchOption.AllDirectories));
if (cfg == null || cfg.Files.Count == 0)
{
DialogResult dr = Util.Prompt(MessageBoxButtons.YesNoCancel, "Loading Override Options:", "Yes - OR/AS" + Environment.NewLine + "No - X/Y" + Environment.NewLine + "Cancel - Abort", "Path:" + Environment.NewLine + path);
if (dr == DialogResult.Yes) { oras = true; }
else if (dr == DialogResult.No) { oras = false; }
if (dr == DialogResult.Yes) { cfg = new GameConfig(GameVersion.ORAS); }
else if (dr == DialogResult.No) { cfg = new GameConfig(GameVersion.XY); }
else { RomFSPath = null; oras = false; return false; }
}
else
oras = game == 1;
RomFSPath = path;
Config = cfg;
oras = Config.ORAS;
backupGARCs(false, allGARCs);
backupCROs(false, RomFSPath);
return true;
@@ -589,7 +586,7 @@ private void fileGet(string[] files, bool skipDecompression = true, bool skipGet
{
string GARC = getGARCFileName(toEdit);
updateStatus($"GARC Get: {toEdit} @ {GARC}... ");
threadGet(RomFSPath + GARC, toEdit, true, skipDecompression);
threadGet(Path.Combine(RomFSPath, GARC), toEdit, true, skipDecompression);
while (threads > 0) Thread.Sleep(50);
}
}
@@ -600,7 +597,7 @@ private void fileSet(IEnumerable<string> files, bool keep = false)
{
string GARC = getGARCFileName(toEdit);
updateStatus($"GARC Set: {toEdit} @ {GARC}... ");
threadSet(RomFSPath + GARC, toEdit);
threadSet(Path.Combine(RomFSPath, GARC), toEdit);
while (threads > 0) Thread.Sleep(50);
if (!keep && Directory.Exists(toEdit)) Directory.Delete(toEdit, true);
}
@@ -782,7 +779,8 @@ private void backupCROs(bool overwrite, string path)
private void B_Rebuild3DS_Click(object sender, EventArgs e)
{
// Ensure that the romfs paths are valid
if (checkGameType(Directory.GetFiles(TB_Path.Text, "*", SearchOption.AllDirectories)) >= 0)
string[] files = Directory.GetFiles(TB_Path.Text, "*", SearchOption.AllDirectories);
if (!Config.IsRebuildable(files.Length))
{
Util.Error("RomFS file count does not match the default game file count.");
return;
@@ -874,42 +872,22 @@ private void Menu_Shuffler_Click(object sender, EventArgs e)
}
// GARC Requests
internal static GameConfig Config;
private string getGARCFileName(string requestedGARC)
{
return getGARCFileName(requestedGARC, Language);
var garc = Config.getGARC(requestedGARC);
if (garc.LanguageVariant)
garc = garc.getRelativeGARC(Language);
return garc.Reference;
}
internal static string getGARCFileName(string requestedGARC, int lang)
{
string ans = "";
switch (requestedGARC)
{
case "movesprite": ans = getGARCPath(0, 0, 5); break;
case "encdata": ans = oras ? getGARCPath(0, 1, 3) : getGARCPath(0, 1, 2); break;
case "trdata": ans = oras ? getGARCPath(0, 3, 6) : getGARCPath(0, 3, 8); break;
case "trpoke": ans = oras ? getGARCPath(0, 3, 8) : getGARCPath(0, 4, 0); break;
case "mapGR": ans = oras ? getGARCPath(0, 3, 9) : getGARCPath(0, 4, 1); break;
case "mapMatrix": ans = oras ? getGARCPath(0, 4, 0) : getGARCPath(0, 4, 2); break;
case "gametext": ans = oras ? getGARCPath(0, 7, 1 + lang) : getGARCPath(0, 7, 2 + lang); break;
case "storytext": ans = oras ? getGARCPath(0, 7 + (lang + 9) / 10, (10 + lang + 9) % 10) : getGARCPath(0, 8, lang); break;
case "wallpaper": ans = oras ? getGARCPath(1, 0, 3) : getGARCPath(1, 0, 4); break;
case "titlescreen": ans = oras ? getGARCPath(1, 5, 2) : getGARCPath(1, 6, 5); break;
case "maisonpkN": ans = oras ? getGARCPath(1, 8, 2) : getGARCPath(2, 0, 3); break;
case "maisontrN": ans = oras ? getGARCPath(1, 8, 3) : getGARCPath(2, 0, 4); break;
case "maisonpkS": ans = oras ? getGARCPath(1, 8, 4) : getGARCPath(2, 0, 5); break;
case "maisontrS": ans = oras ? getGARCPath(1, 8, 5) : getGARCPath(2, 0, 6); break;
case "move": ans = oras ? getGARCPath(1, 8, 9) : getGARCPath(2, 1, 2); break;
case "eggmove": ans = oras ? getGARCPath(1, 9, 0) : getGARCPath(2, 1, 3); break;
case "levelup": ans = oras ? getGARCPath(1, 9, 1) : getGARCPath(2, 1, 4); break;
case "evolution": ans = oras ? getGARCPath(1, 9, 2) : getGARCPath(2, 1, 5); break;
case "megaevo": ans = oras ? getGARCPath(1, 9, 3) : getGARCPath(2, 1, 6); break;
case "personal": ans = oras ? getGARCPath(1, 9, 5) : getGARCPath(2, 1, 8); break;
case "item": ans = oras ? getGARCPath(1, 9, 7) : getGARCPath(2, 2, 0); break;
}
return ans;
}
internal static string getGARCPath(int A, int B, int C)
{
return string.Format("{0}a{0}{1}{0}{2}{0}{3}", Path.DirectorySeparatorChar, A, B, C);
var garc = Config.getGARC(requestedGARC);
if (garc.LanguageVariant)
garc = garc.getRelativeGARC(lang);
return garc.Reference;
}
public bool getGARC(string infile, string outfolder, bool PB, bool bypassExt = false)
{
@@ -963,7 +941,7 @@ public void backupGARCs(bool overwrite, params string[] g)
string dest = "backup" + Path.DirectorySeparatorChar + s +
$" ({GARC.Replace(Path.DirectorySeparatorChar.ToString(), "")})";
if (overwrite || !File.Exists(dest))
File.Copy(RomFSPath + GARC, dest);
File.Copy(Path.Combine(RomFSPath, GARC), dest);
}
}
public void restoreGARCs(bool oras_define, params string[] g)
@@ -971,7 +949,7 @@ public void restoreGARCs(bool oras_define, params string[] g)
oras = oras_define;
foreach (string s in g)
{
string dest = RomFSPath + getGARCFileName(s);
string dest = Path.Combine(RomFSPath, getGARCFileName(s));
string src = "backup" + Path.DirectorySeparatorChar + s +
$" ({getGARCFileName(s).Replace(Path.DirectorySeparatorChar.ToString(), "")})";
File.Copy(src, dest, true);

View File

@@ -60,12 +60,15 @@
<Compile Include="3DS\CTR.cs" />
<Compile Include="3DS\ExeFS.cs" />
<Compile Include="3DS\BCLIM.cs" />
<Compile Include="Game\GameVersion.cs" />
<Compile Include="Game\GARCReference.cs" />
<Compile Include="Misc\About.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Misc\About.Designer.cs">
<DependentUpon>About.cs</DependentUpon>
</Compile>
<Compile Include="Game\GameConfig.cs" />
<Compile Include="Randomizer.cs" />
<Compile Include="3DS\RomFS.cs" />
<Compile Include="Structs.cs" />