mirror of
https://github.com/kwsch/pk3DS.git
synced 2026-10-02 05:46:47 -05:00
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:
26
pk3DS/Game/GARCReference.cs
Normal file
26
pk3DS/Game/GARCReference.cs
Normal 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
164
pk3DS/Game/GameConfig.cs
Normal 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
48
pk3DS/Game/GameVersion.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user