mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
168 lines
6.8 KiB
C#
168 lines
6.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using LibHac;
|
|
using LibHac.Savefile;
|
|
|
|
namespace hactoolnet
|
|
{
|
|
public static class Program
|
|
{
|
|
public static void Main(string[] args)
|
|
{
|
|
Console.OutputEncoding = Encoding.UTF8;
|
|
var ctx = new Context();
|
|
ctx.Options = CliParser.Parse(args);
|
|
if (ctx.Options == null) return;
|
|
|
|
using (var logger = new ProgressBar())
|
|
{
|
|
ctx.Logger = logger;
|
|
OpenKeyset(ctx);
|
|
|
|
if (ctx.Options.RunCustom)
|
|
{
|
|
CustomTask(ctx);
|
|
return;
|
|
}
|
|
|
|
switch (ctx.Options.InFileType)
|
|
{
|
|
case FileType.Nca:
|
|
ProcessNca.Process(ctx);
|
|
break;
|
|
case FileType.Pfs0:
|
|
break;
|
|
case FileType.Romfs:
|
|
ProcessRomfs.Process(ctx);
|
|
break;
|
|
case FileType.Nax0:
|
|
break;
|
|
case FileType.SwitchFs:
|
|
ProcessSwitchFs.Process(ctx);
|
|
break;
|
|
case FileType.Save:
|
|
ProcessSave(ctx);
|
|
break;
|
|
case FileType.Xci:
|
|
ProcessXci.Process(ctx);
|
|
break;
|
|
case FileType.Keygen:
|
|
ProcessKeygen(ctx);
|
|
break;
|
|
case FileType.Pk11:
|
|
ProcessPackage.ProcessPk11(ctx);
|
|
break;
|
|
case FileType.Pk21:
|
|
ProcessPackage.ProcessPk21(ctx);
|
|
break;
|
|
case FileType.Kip1:
|
|
ProcessKip.ProcessKip1(ctx);
|
|
break;
|
|
case FileType.Ini1:
|
|
ProcessKip.ProcessIni1(ctx);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void OpenKeyset(Context ctx)
|
|
{
|
|
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
|
var homeKeyFile = Path.Combine(home, ".switch", "prod.keys");
|
|
var homeTitleKeyFile = Path.Combine(home, ".switch", "title.keys");
|
|
var homeConsoleKeyFile = Path.Combine(home, ".switch", "console.keys");
|
|
var keyFile = ctx.Options.Keyfile;
|
|
var titleKeyFile = ctx.Options.TitleKeyFile;
|
|
var consoleKeyFile = ctx.Options.ConsoleKeyFile;
|
|
|
|
if (keyFile == null && File.Exists(homeKeyFile))
|
|
{
|
|
keyFile = homeKeyFile;
|
|
}
|
|
|
|
if (titleKeyFile == null && File.Exists(homeTitleKeyFile))
|
|
{
|
|
titleKeyFile = homeTitleKeyFile;
|
|
}
|
|
|
|
if (consoleKeyFile == null && File.Exists(homeConsoleKeyFile))
|
|
{
|
|
consoleKeyFile = homeConsoleKeyFile;
|
|
}
|
|
|
|
ctx.Keyset = ExternalKeys.ReadKeyFile(keyFile, titleKeyFile, consoleKeyFile, ctx.Logger);
|
|
if (ctx.Options.SdSeed != null)
|
|
{
|
|
ctx.Keyset.SetSdSeed(ctx.Options.SdSeed.ToBytes());
|
|
}
|
|
}
|
|
|
|
private static void ProcessSave(Context ctx)
|
|
{
|
|
using (var file = new FileStream(ctx.Options.InFile, FileMode.Open, FileAccess.ReadWrite))
|
|
{
|
|
var save = new Savefile(ctx.Keyset, file, ctx.Options.EnableHash, ctx.Logger);
|
|
|
|
if (ctx.Options.OutDir != null)
|
|
{
|
|
save.Extract(ctx.Options.OutDir, ctx.Logger);
|
|
}
|
|
|
|
if (ctx.Options.DebugOutDir != null)
|
|
{
|
|
var dir = ctx.Options.DebugOutDir;
|
|
Directory.CreateDirectory(dir);
|
|
|
|
File.WriteAllBytes(Path.Combine(dir, "L0_0_MasterHashA"), save.Header.MasterHashA);
|
|
File.WriteAllBytes(Path.Combine(dir, "L0_1_MasterHashB"), save.Header.MasterHashB);
|
|
File.WriteAllBytes(Path.Combine(dir, "L0_2_DuplexMasterA"), save.Header.DuplexMasterA);
|
|
File.WriteAllBytes(Path.Combine(dir, "L0_3_DuplexMasterB"), save.Header.DuplexMasterB);
|
|
save.DuplexL1A.WriteAllBytes(Path.Combine(dir, "L0_4_DuplexL1A"), ctx.Logger);
|
|
save.DuplexL1B.WriteAllBytes(Path.Combine(dir, "L0_5_DuplexL1B"), ctx.Logger);
|
|
save.DuplexDataA.WriteAllBytes(Path.Combine(dir, "L0_6_DuplexDataA"), ctx.Logger);
|
|
save.DuplexDataB.WriteAllBytes(Path.Combine(dir, "L0_7_DuplexDataB"), ctx.Logger);
|
|
save.JournalData.WriteAllBytes(Path.Combine(dir, "L0_9_JournalData"), ctx.Logger);
|
|
|
|
save.DuplexData.WriteAllBytes(Path.Combine(dir, "L1_0_DuplexData"), ctx.Logger);
|
|
save.JournalTable.WriteAllBytes(Path.Combine(dir, "L2_0_JournalTable"), ctx.Logger);
|
|
save.JournalBitmapUpdatedPhysical.WriteAllBytes(Path.Combine(dir, "L2_1_JournalBitmapUpdatedPhysical"), ctx.Logger);
|
|
save.JournalBitmapUpdatedVirtual.WriteAllBytes(Path.Combine(dir, "L2_2_JournalBitmapUpdatedVirtual"), ctx.Logger);
|
|
save.JournalBitmapUnassigned.WriteAllBytes(Path.Combine(dir, "L2_3_JournalBitmapUnassigned"), ctx.Logger);
|
|
save.JournalLayer1Hash.WriteAllBytes(Path.Combine(dir, "L2_4_Layer1Hash"), ctx.Logger);
|
|
save.JournalLayer2Hash.WriteAllBytes(Path.Combine(dir, "L2_5_Layer2Hash"), ctx.Logger);
|
|
save.JournalLayer3Hash.WriteAllBytes(Path.Combine(dir, "L2_6_Layer3Hash"), ctx.Logger);
|
|
save.JournalFat.WriteAllBytes(Path.Combine(dir, "L2_7_FAT"), ctx.Logger);
|
|
|
|
save.IvfcStreamSource.CreateStream().WriteAllBytes(Path.Combine(dir, "L3_0_SaveData"), ctx.Logger);
|
|
}
|
|
|
|
if (ctx.Options.SignSave)
|
|
{
|
|
if (save.SignHeader(ctx.Keyset))
|
|
{
|
|
ctx.Logger.LogMessage("Successfully signed save file");
|
|
}
|
|
else
|
|
{
|
|
ctx.Logger.LogMessage("Unable to sign save file. Do you have all the required keys?");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void ProcessKeygen(Context ctx)
|
|
{
|
|
Console.WriteLine(ExternalKeys.PrintKeys(ctx.Keyset));
|
|
}
|
|
|
|
// For running random stuff
|
|
// ReSharper disable once UnusedParameter.Local
|
|
private static void CustomTask(Context ctx)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|