hactoolnet: Add an option to replace a file in save data

This commit is contained in:
Alex Barney 2018-12-11 15:11:44 -06:00
parent 9e3c41ed2c
commit 1b3a0363ce
3 changed files with 45 additions and 1 deletions

View file

@ -50,6 +50,12 @@ namespace hactoolnet
new CliOption("sign", 0, (o, a) => o.SignSave = true),
new CliOption("title", 1, (o, a) => o.TitleId = ParseTitleId(a[0])),
new CliOption("bench", 1, (o, a) => o.BenchType = a[0]),
new CliOption("replacefile", 2, (o, a) =>
{
o.ReplaceFileDest = a[0];
o.ReplaceFileSource = a[1];
})
};
public static Options Parse(string[] args)
@ -204,11 +210,12 @@ namespace hactoolnet
sb.AppendLine(" --romfsdir <dir> Specify RomFS directory path. (--title must be specified)");
sb.AppendLine(" --savedir <dir> Specify save file directory path.");
sb.AppendLine(" -y, --verify Verify all titles, or verify a single title if --title is set.");
sb.AppendLine("Savefile options:");
sb.AppendLine("Save data options:");
sb.AppendLine(" --outdir <dir> Specify directory path to save contents to.");
sb.AppendLine(" --debugoutdir <dir> Specify directory path to save intermediate data to for debugging.");
sb.AppendLine(" --sign Sign the save file. (Requires device_key in key file)");
sb.AppendLine(" --listfiles List files in save file.");
sb.AppendLine(" --replacefile <filename in save> <file> Replaces a file in the save data");
sb.AppendLine("Keygen options:");
sb.AppendLine(" --outdir <dir> Specify directory path to save key files to.");

View file

@ -33,6 +33,8 @@ namespace hactoolnet
public string NormalDir;
public string SecureDir;
public string LogoDir;
public string ReplaceFileSource;
public string ReplaceFileDest;
public bool ListApps;
public bool ListTitles;
public bool ListNcas;

View file

@ -94,6 +94,39 @@ namespace hactoolnet
duplexDataB.WriteAllBytes(Path.Combine(duplexDir, "DataB"), ctx.Logger);
}
if (ctx.Options.ReplaceFileDest != null && ctx.Options.ReplaceFileSource != null)
{
string destFilename = ctx.Options.ReplaceFileDest;
if (!destFilename.StartsWith("/")) destFilename = '/' + destFilename;
using (IStorage inFile = new FileStream(ctx.Options.ReplaceFileSource, FileMode.Open, FileAccess.Read).AsStorage(false))
{
using (IStorage outFile = save.OpenFile(destFilename))
{
if (inFile.Length != outFile.Length)
{
ctx.Logger.LogMessage($"Replacement file must be the same size as the original file. ({outFile.Length} bytes)");
return;
}
inFile.CopyTo(outFile, ctx.Logger);
ctx.Logger.LogMessage($"Replaced file {destFilename}");
}
}
if (save.CommitHeader(ctx.Keyset))
{
ctx.Logger.LogMessage("Successfully signed save file");
}
else
{
ctx.Logger.LogMessage("ERROR: Unable to sign save file. Do you have all the required keys?");
}
return;
}
if (ctx.Options.SignSave)
{
if (save.CommitHeader(ctx.Keyset))
@ -104,6 +137,8 @@ namespace hactoolnet
{
ctx.Logger.LogMessage("Unable to sign save file. Do you have all the required keys?");
}
return;
}
if (ctx.Options.ListFiles)