hactoolnet: Add option to replace a savedata's entire contents

This commit is contained in:
Alex Barney 2019-05-08 18:06:29 -05:00
parent 26ac0ed975
commit c766a413e2
4 changed files with 44 additions and 29 deletions

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;net46</TargetFrameworks>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -46,6 +46,7 @@ namespace hactoolnet
new CliOption("normaldir", 1, (o, a) => o.NormalDir = a[0]),
new CliOption("securedir", 1, (o, a) => o.SecureDir = a[0]),
new CliOption("logodir", 1, (o, a) => o.LogoDir = a[0]),
new CliOption("repack", 1, (o, a) => o.RepackSource = a[0]),
new CliOption("listapps", 0, (o, a) => o.ListApps = true),
new CliOption("listtitles", 0, (o, a) => o.ListTitles = true),
new CliOption("listncas", 0, (o, a) => o.ListNcas = true),
@ -235,6 +236,7 @@ namespace hactoolnet
sb.AppendLine(" --sign Sign the save file. (Requires device_key in key file)");
sb.AppendLine(" --trim Trim garbage data in the save file. (Requires device_key in key file)");
sb.AppendLine(" --listfiles List files in save file.");
sb.AppendLine(" --repack <dir> Replaces the contents of the save data with the specified directory.");
sb.AppendLine(" --replacefile <filename in save> <file> Replaces a file in the save data");
sb.AppendLine("NDV0 (Delta) options:");
sb.AppendLine(" Input delta patch can be a delta NCA file or a delta fragment file.");

View file

@ -39,6 +39,7 @@ namespace hactoolnet
public string LogoDir;
public string ReplaceFileSource;
public string ReplaceFileDest;
public string RepackSource;
public bool ListApps;
public bool ListTitles;
public bool ListNcas;

View file

@ -16,6 +16,8 @@ namespace hactoolnet
{
using (var file = new LocalStorage(ctx.Options.InFile, FileAccess.ReadWrite))
{
bool signNeeded = ctx.Options.SignSave;
var save = new SaveDataFileSystem(ctx.Keyset, file, ctx.Options.IntegrityLevel, true);
if (ctx.Options.Validate)
@ -30,12 +32,13 @@ namespace hactoolnet
if (ctx.Options.DebugOutDir != null)
{
// todo
string dir = ctx.Options.DebugOutDir;
ExportSaveDebug(ctx, dir, save);
}
try
{
if (ctx.Options.ReplaceFileDest != null && ctx.Options.ReplaceFileSource != null)
{
string destFilename = ctx.Options.ReplaceFileDest;
@ -56,26 +59,34 @@ namespace hactoolnet
}
}
if (save.Commit(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?");
signNeeded = true;
}
return;
if (ctx.Options.RepackSource != null)
{
var source = new LocalFileSystem(ctx.Options.RepackSource);
save.CleanDirectoryRecursively("/");
save.Commit(ctx.Keyset);
source.CopyFileSystem(save);
signNeeded = true;
}
}
finally
{
save.Commit(ctx.Keyset);
}
if (ctx.Options.SignSave || ctx.Options.TrimSave)
{
if (ctx.Options.TrimSave)
{
save.FsTrim();
signNeeded = true;
ctx.Logger.LogMessage("Trimmed save file");
}
if (signNeeded)
{
if (save.Commit(ctx.Keyset))
{
ctx.Logger.LogMessage("Successfully signed save file");
@ -90,14 +101,14 @@ namespace hactoolnet
if (ctx.Options.ListFiles)
{
foreach (DirectoryEntry entry in save.EnumerateEntries().Where(x => x.Type == DirectoryEntryType.File))
foreach (DirectoryEntry entry in save.EnumerateEntries())
{
ctx.Logger.LogMessage(entry.FullPath);
}
}
ctx.Logger.LogMessage(save.Print());
//ctx.Logger.LogMessage(PrintFatLayout(save));
//ctx.Logger.LogMessage(PrintFatLayout(save.SaveDataFileSystemCore));
}
}