mirror of
https://github.com/kwsch/pk3DS.git
synced 2026-08-27 20:26:04 -05:00
Refactor backup/restore method
Now restores all files; users can still manually restore individual files. Closes #31
This commit is contained in:
224
pk3DS/Game/GameBackup.cs
Normal file
224
pk3DS/Game/GameBackup.cs
Normal file
@@ -0,0 +1,224 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace pk3DS
|
||||
{
|
||||
public static class GameBackup
|
||||
{
|
||||
private const string bakpath = "backup";
|
||||
private const string bakexefs = "exefs";
|
||||
private const string baka = "a";
|
||||
private const string bakdll = "dll";
|
||||
|
||||
public static void backupFiles(this GameConfig config, bool overwrite = false)
|
||||
{
|
||||
// Users may use pk3DS for multiple games, and even the same game but from different paths.
|
||||
// A simple way is to create a backup for each unique game, but... some carts may be pre-patched.
|
||||
// Just save the backup based on the folder name, as the user may move that parent folder.
|
||||
// Store a text file in each backup to keep track of its origin in case they rename the folder.
|
||||
|
||||
if (!Directory.Exists(bakpath))
|
||||
Directory.CreateDirectory(bakpath);
|
||||
|
||||
var gamePath = new DirectoryInfo(config.RomFS).Parent;
|
||||
string gameFolder = gamePath.Name;
|
||||
string gameBackup = Path.Combine(bakpath, gameFolder);
|
||||
if (!Directory.Exists(gameBackup))
|
||||
Directory.CreateDirectory(gameBackup);
|
||||
|
||||
string bak_exefs = Path.Combine(gameBackup, bakexefs);
|
||||
string bak_a = Path.Combine(gameBackup, baka);
|
||||
string bak_dll = Path.Combine(gameBackup, bakdll);
|
||||
if (!Directory.Exists(bak_exefs))
|
||||
Directory.CreateDirectory(bak_exefs);
|
||||
if (!Directory.Exists(bak_a))
|
||||
Directory.CreateDirectory(bak_a);
|
||||
if (!Directory.Exists(bak_dll))
|
||||
Directory.CreateDirectory(bak_dll);
|
||||
|
||||
// Backup files
|
||||
if (config.ExeFS != null) // exefs
|
||||
backupExeFS(config, overwrite, bak_exefs);
|
||||
if (config.RomFS != null) // a
|
||||
backupGARC(config, overwrite, bak_a);
|
||||
if (config.RomFS != null) // dll
|
||||
backupDLL(config, overwrite, bak_dll);
|
||||
|
||||
File.WriteAllText(Path.Combine(gameBackup, "bakinfo.txt"), "Backup created from the following location:" + Environment.NewLine + gamePath.FullName);
|
||||
}
|
||||
private static void backupExeFS(GameConfig config, bool overwrite, string bak_exefs)
|
||||
{
|
||||
var files = Directory.GetFiles(config.ExeFS);
|
||||
foreach (var f in files)
|
||||
{
|
||||
string dest = Path.Combine(bak_exefs, Path.GetFileName(f));
|
||||
if (overwrite || !File.Exists(dest))
|
||||
File.Copy(f, dest);
|
||||
}
|
||||
}
|
||||
private static void backupGARC(GameConfig config, bool overwrite, string bak_a)
|
||||
{
|
||||
var files = config.Files.Select(file => file.Name);
|
||||
foreach (var f in files)
|
||||
{
|
||||
string GARC = config.getGARCFileName(f);
|
||||
string name = f + $" ({GARC.Replace(Path.DirectorySeparatorChar.ToString(), "")})";
|
||||
string src = Path.Combine(config.RomFS, GARC);
|
||||
string dest = Path.Combine(bak_a, name);
|
||||
if (overwrite || !File.Exists(dest))
|
||||
File.Copy(src, dest);
|
||||
}
|
||||
}
|
||||
private static void backupDLL(GameConfig config, bool overwrite, string bak_dll)
|
||||
{
|
||||
string path = config.RomFS;
|
||||
string[] files = Directory.GetFiles(path);
|
||||
string[] CROs = files.Where(x => new FileInfo(x).Name.Contains("Dll")).ToArray();
|
||||
string[] CRSs = files.Where(x => new FileInfo(x).Extension.Contains("crs")).ToArray();
|
||||
string[] CRRs = Directory.Exists(Path.Combine(path, ".crr"))
|
||||
? Directory.GetFiles(Path.Combine(path, ".crr"))
|
||||
: new string[0];
|
||||
|
||||
int count = CROs.Length + CRSs.Length + CRRs.Length;
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
if (!Directory.Exists(bak_dll))
|
||||
Directory.CreateDirectory(bak_dll);
|
||||
|
||||
foreach (string src in CROs.Concat(CRSs))
|
||||
{
|
||||
string dest = Path.Combine(bak_dll, Path.GetFileName(src));
|
||||
if (overwrite || !File.Exists(dest))
|
||||
File.Copy(src, dest);
|
||||
}
|
||||
|
||||
if (CRRs.Length <= 0)
|
||||
return;
|
||||
|
||||
// Separate folder for the .crr
|
||||
string CRRBAKPATH = Path.Combine(bak_dll, ".crr");
|
||||
if (!Directory.Exists(CRRBAKPATH))
|
||||
Directory.CreateDirectory(CRRBAKPATH);
|
||||
|
||||
foreach (string src in CRRs)
|
||||
{
|
||||
string dest = Path.Combine(CRRBAKPATH, Path.GetFileName(src));
|
||||
if (overwrite || !File.Exists(dest))
|
||||
File.Copy(src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] restoreFiles(this GameConfig config)
|
||||
{
|
||||
// Do the same process as backing up, but copy files in the opposite direction.
|
||||
|
||||
string gameFolder = new DirectoryInfo(config.RomFS).Parent.Name;
|
||||
string gameBackup = Path.Combine(bakpath, gameFolder);
|
||||
if (!Directory.Exists(gameBackup))
|
||||
return new[] {"Unable to find the backup folder for this game.", $"Expected:\n{gameBackup}"};
|
||||
|
||||
string bak_exefs = Path.Combine(gameBackup, bakexefs);
|
||||
string bak_a = Path.Combine(gameBackup, baka);
|
||||
string bak_dll = Path.Combine(gameBackup, bakdll);
|
||||
|
||||
int[] count = new int[3];
|
||||
|
||||
// restore exefs
|
||||
if (Directory.Exists(bak_exefs))
|
||||
count[0] = restoreExeFS(config, bak_exefs);
|
||||
if (Directory.Exists(bak_a))
|
||||
count[1] = restoreGARC(config, bak_a);
|
||||
if (Directory.Exists(bak_dll))
|
||||
count[2] = restoreDLL(config, bak_dll);
|
||||
|
||||
string[] sources = { "ExeFS", "'a'", "CRO" };
|
||||
var info = count.Select((c, i) => $"{sources[i]}: {c}");
|
||||
var result = string.Join(Environment.NewLine, info);
|
||||
return new[] {result};
|
||||
}
|
||||
private static int restoreExeFS(GameConfig config, string bak_exefs)
|
||||
{
|
||||
int count = 0;
|
||||
var files = Directory.GetFiles(config.ExeFS);
|
||||
foreach (var f in files)
|
||||
{
|
||||
string dest = Path.Combine(bak_exefs, Path.GetFileName(f));
|
||||
if (File.Exists(dest))
|
||||
{
|
||||
File.Copy(dest, f);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Unable to find backup: " + dest);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
private static int restoreGARC(GameConfig config, string bak_a)
|
||||
{
|
||||
int count = 0;
|
||||
var files = config.Files.Select(file => file.Name);
|
||||
foreach (var f in files)
|
||||
{
|
||||
string GARC = config.getGARCFileName(f);
|
||||
string name = f + $" ({GARC.Replace(Path.DirectorySeparatorChar.ToString(), "")})";
|
||||
string src = Path.Combine(config.RomFS, GARC);
|
||||
string dest = Path.Combine(bak_a, name);
|
||||
if (File.Exists(dest))
|
||||
{
|
||||
File.Copy(dest, src);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Unable to find backup: " + dest);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
private static int restoreDLL(GameConfig config, string bak_dll)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
string path = config.RomFS;
|
||||
string[] files = Directory.GetFiles(path);
|
||||
string[] CROs = files.Where(x => new FileInfo(x).Name.Contains("Dll")).ToArray();
|
||||
string[] CRSs = files.Where(x => new FileInfo(x).Extension.Contains("crs")).ToArray();
|
||||
string[] CRRs = Directory.Exists(Path.Combine(path, ".crr"))
|
||||
? Directory.GetFiles(Path.Combine(path, ".crr"))
|
||||
: new string[0];
|
||||
|
||||
if (CROs.Length + CRSs.Length + CRRs.Length <= 0)
|
||||
return 0;
|
||||
|
||||
foreach (string src in CROs.Concat(CRSs))
|
||||
{
|
||||
string dest = Path.Combine(bak_dll, Path.GetFileName(src));
|
||||
if (File.Exists(dest))
|
||||
{
|
||||
File.Copy(dest, src);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Unable to find backup: " + dest);
|
||||
}
|
||||
|
||||
if (CRRs.Length <= 0)
|
||||
return count;
|
||||
|
||||
// Separate folder for the .crr
|
||||
string CRRBAKPATH = Path.Combine(bak_dll, ".crr");
|
||||
foreach (string src in CRRs)
|
||||
{
|
||||
string dest = Path.Combine(CRRBAKPATH, Path.GetFileName(src));
|
||||
if (File.Exists(dest))
|
||||
{
|
||||
File.Copy(dest, src);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Unable to find backup: " + dest);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ private GARC.lzGARC getlzGARC(string file)
|
||||
return new GARC.lzGARC(File.ReadAllBytes(getGARCPath(file)));
|
||||
}
|
||||
|
||||
private string RomFS, ExeFS;
|
||||
public string RomFS, ExeFS;
|
||||
|
||||
public GARCReference getGARCReference(string name) { return Files.FirstOrDefault(f => f.Name == name); }
|
||||
public TextVariableCode getVariableCode(string name) { return Variables.FirstOrDefault(v => v.Name == name); }
|
||||
|
||||
@@ -70,21 +70,31 @@ private void L_About_Click(object sender, EventArgs e)
|
||||
}
|
||||
private void L_GARCInfo_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (RomFSPath != null)
|
||||
{
|
||||
string s = "Game Type: " + Config.Version + Environment.NewLine;
|
||||
s = Config.Files.Select(file => file.Name).Aggregate(s, (current, t) => current + string.Format(Environment.NewLine + "{0} - {1}", t, Config.getGARCFileName(t)));
|
||||
if (RomFSPath == null)
|
||||
return;
|
||||
|
||||
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, s, "Copy to Clipboard?")) return;
|
||||
string s = "Game Type: " + Config.Version + Environment.NewLine;
|
||||
s = Config.Files.Select(file => file.Name).Aggregate(s, (current, t) => current + string.Format(Environment.NewLine + "{0} - {1}", t, Config.getGARCFileName(t)));
|
||||
|
||||
try { Clipboard.SetText(s); }
|
||||
catch { Util.Alert("Unable to copy to Clipboard."); }
|
||||
}
|
||||
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, s, "Copy to Clipboard?")) return;
|
||||
|
||||
try { Clipboard.SetText(s); }
|
||||
catch { Util.Alert("Unable to copy to Clipboard."); }
|
||||
}
|
||||
private void L_Game_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Restore Original Files?"))
|
||||
restoreGARCs(Config.Files.Select(file => file.Name).ToArray());
|
||||
if (DialogResult.Yes != Util.Prompt(MessageBoxButtons.YesNo, "Restore Original Files?"))
|
||||
return;
|
||||
|
||||
string[] result = Config.restoreFiles();
|
||||
if (result.Length == 2) // error
|
||||
{
|
||||
Util.Alert(result);
|
||||
return;
|
||||
}
|
||||
|
||||
Util.Alert("Restored files:", result[0], "The program will now close.");
|
||||
Application.Exit(); // do not call closing events that repackage personal/gametext
|
||||
}
|
||||
|
||||
private void B_Open_Click(object sender, EventArgs e)
|
||||
@@ -203,8 +213,7 @@ private void openQuick(string path)
|
||||
if (RTB_Status.Text.Length > 0) RTB_Status.Clear();
|
||||
updateStatus("Data found! Loading persistent data for subforms...", false);
|
||||
Config.Initialize(RomFSPath, ExeFSPath, Language);
|
||||
backupGARCs(false, Config.Files.Select(file => file.Name).ToArray());
|
||||
backupCROs(false, RomFSPath);
|
||||
Config.backupFiles();
|
||||
}
|
||||
|
||||
// Enable Rebuilding options if all files have been found
|
||||
@@ -289,7 +298,6 @@ private static GameConfig checkGameType(string[] files)
|
||||
if (files.Length > 1000)
|
||||
return null;
|
||||
string[] fileArr = Directory.GetFiles(Path.Combine(Directory.GetParent(files[0]).FullName, "a"), "*", SearchOption.AllDirectories);
|
||||
var afiles = fileArr.Where(file => Path.GetFileName(file)?.Length == 1).ToArray();
|
||||
int fileCount = fileArr.Count(file => Path.GetFileName(file)?.Length == 1);
|
||||
return new GameConfig(fileCount);
|
||||
}
|
||||
@@ -781,7 +789,6 @@ private void B_TitleScreen_Click(object sender, EventArgs e)
|
||||
// RomFS File Requesting Method Wrapper
|
||||
private void fileGet(string[] files, bool skipDecompression = true, bool skipGet = false)
|
||||
{
|
||||
if (ModifierKeys == (Keys.Control | Keys.Shift)) restoreGARCs(files.ToArray());
|
||||
if (skipGet || skipBoth) return;
|
||||
foreach (string toEdit in files)
|
||||
{
|
||||
@@ -998,42 +1005,6 @@ private void B_Static_Click(object sender, EventArgs e)
|
||||
}
|
||||
new StaticEncounterEditor6().ShowDialog();
|
||||
}
|
||||
private void backupCROs(bool overwrite, string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
return;
|
||||
|
||||
string[] files = Directory.GetFiles(path);
|
||||
string[] CROs = files.Where(x => new FileInfo(x).Name.Contains("Dll")).ToArray();
|
||||
string[] CRSs = files.Where(x => new FileInfo(x).Extension.Contains("crs")).ToArray();
|
||||
string[] CRRs = Directory.Exists(Path.Combine(path, ".crr"))
|
||||
? Directory.GetFiles(Path.Combine(path, ".crr"))
|
||||
: new string[0];
|
||||
|
||||
int count = CROs.Length + CRSs.Length + CRRs.Length;
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
// Somewhat unique ID for the dlls to separate backup folders between versions
|
||||
string CROBAKPATH = Path.Combine("backup", "DLL_" + count);
|
||||
|
||||
if (!Directory.Exists(CROBAKPATH))
|
||||
Directory.CreateDirectory(CROBAKPATH);
|
||||
|
||||
foreach (string file in CROs.Concat(CRSs).Where(file => overwrite || !File.Exists(Path.Combine(CROBAKPATH, Path.GetFileName(file)))))
|
||||
File.Copy(file, Path.Combine(CROBAKPATH, Path.GetFileName(file)));
|
||||
|
||||
if (CRRs.Length <= 0)
|
||||
return;
|
||||
|
||||
// Separate folder for the .crr
|
||||
string CRRBAKPATH = Path.Combine(CROBAKPATH, ".crr");
|
||||
if (!Directory.Exists(CRRBAKPATH))
|
||||
Directory.CreateDirectory(CRRBAKPATH);
|
||||
|
||||
foreach (string file in CRRs.Where(file => overwrite || !File.Exists(Path.Combine(CRRBAKPATH, Path.GetFileName(file)))))
|
||||
File.Copy(file, Path.Combine(CRRBAKPATH, Path.GetFileName(file)));
|
||||
}
|
||||
|
||||
// 3DS Building
|
||||
private void B_Rebuild3DS_Click(object sender, EventArgs e)
|
||||
@@ -1185,32 +1156,6 @@ private void threadSet(string outfile, string infolder, int padBytes, bool PB =
|
||||
new Thread(() => setGARC(outfile, infolder, padBytes, PB)).Start();
|
||||
}
|
||||
|
||||
private static void backupGARCs(bool overwrite, params string[] g)
|
||||
{
|
||||
if (!Directory.Exists("backup")) Directory.CreateDirectory("backup");
|
||||
foreach (string s in g)
|
||||
{
|
||||
string GARC = Config.getGARCFileName(s);
|
||||
string dest = "backup" + Path.DirectorySeparatorChar + s +
|
||||
$" ({GARC.Replace(Path.DirectorySeparatorChar.ToString(), "")})";
|
||||
if (overwrite || !File.Exists(dest))
|
||||
File.Copy(Path.Combine(RomFSPath, GARC), dest);
|
||||
}
|
||||
}
|
||||
private static void restoreGARCs(params string[] g)
|
||||
{
|
||||
foreach (string s in g)
|
||||
{
|
||||
string dest = Path.Combine(RomFSPath, Config.getGARCFileName(s));
|
||||
string src = "backup" + Path.DirectorySeparatorChar + s +
|
||||
$" ({Config.getGARCFileName(s).Replace(Path.DirectorySeparatorChar.ToString(), "")})";
|
||||
File.Copy(src, dest, true);
|
||||
if (s == "personal" || s == "gametext")
|
||||
Util.Alert("In order to restore " + s + ", restart the program. While exiting, hold the Control Key to prevent writebacks.");
|
||||
}
|
||||
Util.Alert(g.Length + " files restored.");
|
||||
}
|
||||
|
||||
// Text Requests
|
||||
internal static string[] getText(TextName file)
|
||||
{
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
<Compile Include="3DS\CTR.cs" />
|
||||
<Compile Include="3DS\ExeFS.cs" />
|
||||
<Compile Include="3DS\BCLIM.cs" />
|
||||
<Compile Include="Game\GameBackup.cs" />
|
||||
<Compile Include="Game\GameRNG.cs" />
|
||||
<Compile Include="Game\GameVersion.cs" />
|
||||
<Compile Include="Game\GARCFile.cs" />
|
||||
|
||||
Reference in New Issue
Block a user