diff --git a/Be.Windows.Forms.HexBox.dll b/Be.Windows.Forms.HexBox.dll deleted file mode 100644 index d2ee54d..0000000 Binary files a/Be.Windows.Forms.HexBox.dll and /dev/null differ diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 29b5cf7..6be3437 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -11,9 +11,9 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("XCI Explorer")] -[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyCopyright("Open Source")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("206c6c47-87b1-477f-b6e6-f7e7c1a92f8f")] -[assembly: AssemblyFileVersion("1.5.0")] -[assembly: AssemblyVersion("1.5.0")] +[assembly: AssemblyFileVersion("1.6.0")] +[assembly: AssemblyVersion("1.6.0")] diff --git a/XCI Explorer.csproj b/XCI Explorer.csproj index 82a2c48..71c9199 100644 --- a/XCI Explorer.csproj +++ b/XCI Explorer.csproj @@ -1,95 +1,18 @@ - - + - {89DBE891-22C7-40FF-A3D3-36F26224E09D} - Debug - AnyCPU + net6.0-windows WinExe XCI-Explorer - .NETFramework - v4.8 - 4 True - - - - - - AnyCPU - - - bin\Debug\ - true - full - false + false + true + true - bin\Release\ - true - pdbonly - true - - - XCI_Explorer + false + None - - packages\Be.Windows.Forms.HexBox.1.6.1\lib\net40\Be.Windows.Forms.HexBox.dll - False - - - - - - - - + - - - Form - - - CertForm.cs - - - - - - - Form - - - MainForm.cs - - - - - - - - - - - - - - - - - - - - - MainForm.cs - - - - - - - - - - \ No newline at end of file diff --git a/XCI Explorer.sln b/XCI Explorer.sln index 5822052..ac7a1d4 100644 --- a/XCI Explorer.sln +++ b/XCI Explorer.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28803.156 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31825.309 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XCI Explorer", "XCI Explorer.csproj", "{89DBE891-22C7-40FF-A3D3-36F26224E09D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XCI Explorer", "XCI Explorer.csproj", "{AF04D4B2-34AC-4514-A1A1-19810A25D308}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,15 +11,15 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {89DBE891-22C7-40FF-A3D3-36F26224E09D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89DBE891-22C7-40FF-A3D3-36F26224E09D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89DBE891-22C7-40FF-A3D3-36F26224E09D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89DBE891-22C7-40FF-A3D3-36F26224E09D}.Release|Any CPU.Build.0 = Release|Any CPU + {AF04D4B2-34AC-4514-A1A1-19810A25D308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF04D4B2-34AC-4514-A1A1-19810A25D308}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF04D4B2-34AC-4514-A1A1-19810A25D308}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF04D4B2-34AC-4514-A1A1-19810A25D308}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F9C853DD-FEA7-470E-B594-C72A1C93ECBB} + SolutionGuid = {B3F75FD3-9C94-4E83-83BD-783E98162C92} EndGlobalSection EndGlobal diff --git a/XCI_Explorer/CenterWinDialog.cs b/XCI_Explorer/CenterWinDialog.cs new file mode 100644 index 0000000..de53275 --- /dev/null +++ b/XCI_Explorer/CenterWinDialog.cs @@ -0,0 +1,69 @@ +using System; +using System.Windows.Forms; +using System.Text; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace XCI_Explorer +{ + public class CenterWinDialog : IDisposable + { + private int mTries = 0; + private Form mOwner; + + public CenterWinDialog(Form owner) + { + mOwner = owner; + if (owner.WindowState != FormWindowState.Minimized) + { + owner.BeginInvoke(new MethodInvoker(findDialog)); + } + } + + private void findDialog() + { + // Enumerate windows to find the message box + if (mTries < 0) return; + EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow); + if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) + { + if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog)); + } + } + private bool checkWindow(IntPtr hWnd, IntPtr lp) + { + // Checks if is a dialog + StringBuilder sb = new StringBuilder(260); + GetClassName(hWnd, sb, sb.Capacity); + if (sb.ToString() != "#32770") return true; + // Got it + Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size); + RECT dlgRect; + GetWindowRect(hWnd, out dlgRect); + MoveWindow(hWnd, + frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) / 2, + frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) / 2, + dlgRect.Right - dlgRect.Left, + dlgRect.Bottom - dlgRect.Top, true); + return false; + } + public void Dispose() + { + mTries = -1; + } + + // P/Invoke declarations + private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp); + [DllImport("user32.dll")] + private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp); + [DllImport("kernel32.dll")] + private static extern int GetCurrentThreadId(); + [DllImport("user32.dll")] + private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen); + [DllImport("user32.dll")] + private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); + [DllImport("user32.dll")] + private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint); + private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } + } +} \ No newline at end of file diff --git a/XCI_Explorer/CertForm.resx b/XCI_Explorer/CertForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/XCI_Explorer/CertForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/XCI_Explorer/MainForm.cs b/XCI_Explorer/MainForm.cs index 32baec1..8420ee3 100644 --- a/XCI_Explorer/MainForm.cs +++ b/XCI_Explorer/MainForm.cs @@ -5,7 +5,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; -using System.Net; +using System.Net.Http; using System.Reflection; using System.Security.Cryptography; using System.Text; @@ -63,12 +63,14 @@ namespace XCI_Explorer if (!File.Exists("keys.txt")) { + if (MessageBox.Show("keys.txt is missing.\nDo you want to automatically download it now?\n\nBy pressing 'Yes' you agree that you own these keys.\n", "XCI Explorer", MessageBoxButtons.YesNo) == DialogResult.Yes) { - using (var client = new WebClient()) - { - client.DownloadFile(Util.Base64Decode("aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L2NWR3JQSHp6"), "keys.txt"); - } + using HttpClient client = new(); + using HttpResponseMessage response = client.Send(new HttpRequestMessage(HttpMethod.Get, Util.Base64Decode("aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L1d1TXZBaTN2"))); + using Stream stream = response.Content.ReadAsStream(); + using FileStream fs = new("keys.txt", FileMode.CreateNew); + stream.CopyTo(fs); } if (!File.Exists("keys.txt")) @@ -95,6 +97,7 @@ namespace XCI_Explorer Application.DoEvents(); ProcessFile(); } + } private string getAssemblyVersion() @@ -166,6 +169,7 @@ namespace XCI_Explorer private void ProcessFile() { + using CenterWinDialog center = new CenterWinDialog(this); // Code needs refactoring LB_SelectedData.Text = ""; LB_DataOffset.Text = ""; @@ -212,6 +216,7 @@ namespace XCI_Explorer private void B_LoadROM_Click(object sender, EventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Switch Game File (*.xci, *.nsp, *.nsz)|*.xci;*.nsp;*.nsz|All Files (*.*)|*.*"; if (openFileDialog.ShowDialog() == DialogResult.OK) @@ -548,7 +553,9 @@ namespace XCI_Explorer { WindowStyle = ProcessWindowStyle.Hidden, FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe", - Arguments = "-k keys.txt --romfsdir=tmp tmp/" + ncaTarget + Arguments = "-k keys.txt --romfsdir=tmp tmp/" + ncaTarget, + UseShellExecute = false, + CreateNoWindow = true }; process.Start(); @@ -651,22 +658,10 @@ namespace XCI_Explorer string MasterKey = strArray[1].Trim(); int keyblob; - if (MasterKey.Contains("Unknown")) - { - if (int.TryParse(new string(MasterKey.TakeWhile(Char.IsDigit).ToArray()), out keyblob)) - { - MasterKey = Util.GetMkey((byte)(keyblob + 1)).Replace("MasterKey", ""); - } - TB_MKeyRev.Text = "MasterKey" + MasterKey; - } - else - { - MasterKey = MasterKey.Split(new char[2] { 'x', ' ' })[1]; - keyblob = Convert.ToInt32(MasterKey, 16); - MasterKey = Util.GetMkey((byte)(keyblob + 1)); - TB_MKeyRev.Text = MasterKey; - } - + MasterKey = MasterKey.Split(new char[2] { 'x', ' ' })[1]; + keyblob = Convert.ToInt32(MasterKey, 16); + MasterKey = Util.GetMkey((byte)(keyblob + 1)); + TB_MKeyRev.Text = MasterKey; break; } } @@ -743,7 +738,9 @@ namespace XCI_Explorer { WindowStyle = ProcessWindowStyle.Hidden, FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe", - Arguments = "-k keys.txt --section0dir=data meta" + Arguments = "-k keys.txt --section0dir=data meta", + UseShellExecute = false, + CreateNoWindow = true }; process.Start(); process.WaitForExit(); @@ -811,7 +808,9 @@ namespace XCI_Explorer { WindowStyle = ProcessWindowStyle.Hidden, FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe", - Arguments = "-k keys.txt --romfsdir=data meta" + Arguments = "-k keys.txt --romfsdir=data meta", + UseShellExecute = false, + CreateNoWindow = true }; process.Start(); process.WaitForExit(); @@ -901,7 +900,7 @@ namespace XCI_Explorer public static string SHA256Bytes(byte[] ba) { - SHA256 mySHA256 = SHA256Managed.Create(); + SHA256 mySHA256 = SHA256.Create(); byte[] hashValue; hashValue = mySHA256.ComputeHash(ba); return ByteArrayToString(hashValue); @@ -1185,6 +1184,7 @@ namespace XCI_Explorer private void B_ExportCert_Click(object sender, EventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); if (Util.checkFile(TB_File.Text)) { SaveFileDialog saveFileDialog = new SaveFileDialog(); @@ -1198,7 +1198,7 @@ namespace XCI_Explorer fileStream.Read(array, 0, 512); File.WriteAllBytes(saveFileDialog.FileName, array); fileStream.Close(); - MessageBox.Show("cert successfully exported to:\n\n" + saveFileDialog.FileName); + MessageBox.Show("Cert successfully exported to:\n\n" + saveFileDialog.FileName); } } else @@ -1209,6 +1209,7 @@ namespace XCI_Explorer private void B_ImportCert_Click(object sender, EventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); if (Util.checkFile(TB_File.Text)) { OpenFileDialog openFileDialog = new OpenFileDialog(); @@ -1231,6 +1232,7 @@ namespace XCI_Explorer private void B_ViewCert_Click(object sender, EventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); if (Util.checkFile(TB_File.Text)) { CertForm cert = new CertForm(this); @@ -1245,6 +1247,7 @@ namespace XCI_Explorer private void B_ClearCert_Click(object sender, EventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); if (Util.checkFile(TB_File.Text)) { if (MessageBox.Show("The cert will be deleted permanently.\nContinue?", "XCI Explorer", MessageBoxButtons.YesNo) == DialogResult.Yes) @@ -1284,8 +1287,6 @@ namespace XCI_Explorer // Start the asynchronous operation. backgroundWorker1.RunWorkerAsync(saveFileDialog.FileName); - - MessageBox.Show("Extracting NCA\nPlease wait..."); } } } @@ -1339,6 +1340,7 @@ namespace XCI_Explorer private void B_TrimXCI_Click(object sender, EventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); if (Util.checkFile(TB_File.Text)) { if (MessageBox.Show("Trim XCI?", "XCI Explorer", MessageBoxButtons.YesNo) == DialogResult.Yes) @@ -1458,6 +1460,7 @@ namespace XCI_Explorer private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { + using CenterWinDialog center = new CenterWinDialog(this); B_Extract.Enabled = true; B_LoadROM.Enabled = true; B_TrimXCI.Enabled = true; diff --git a/XCI_Explorer/Util.cs b/XCI_Explorer/Util.cs index 3583c85..a7ce235 100644 --- a/XCI_Explorer/Util.cs +++ b/XCI_Explorer/Util.cs @@ -49,55 +49,55 @@ namespace XCI_Explorer case 8: return "MasterKey7 (7.0.0-8.0.1)"; case 9: - return "MasterKey8 (8.1.0)"; + return "MasterKey8 (8.1.0-8.1.1)"; case 10: return "MasterKey9 (9.0.0-9.0.1)"; case 11: - return "MasterKey10 (9.1.0-9.2.0)"; + return "MasterKey10 (9.1.0-12.0.3)"; case 12: - return "MasterKey11 (?)"; + return "MasterKey11 (12.1.0)"; case 13: - return "MasterKey12 (?)"; + return "MasterKey12 (13.0.0-?)"; case 14: - return "MasterKey13 (?)"; + return "MasterKey13"; case 15: - return "MasterKey14 (?)"; + return "MasterKey14"; case 16: - return "MasterKey15 (?)"; + return "MasterKey15"; case 17: - return "MasterKey16 (?)"; + return "MasterKey16"; case 18: - return "MasterKey17 (?)"; + return "MasterKey17"; case 19: - return "MasterKey18 (?)"; + return "MasterKey18"; case 20: - return "MasterKey19 (?)"; + return "MasterKey19"; case 21: - return "MasterKey20 (?)"; + return "MasterKey20"; case 22: - return "MasterKey21 (?)"; + return "MasterKey21"; case 23: - return "MasterKey22 (?)"; + return "MasterKey22"; case 24: - return "MasterKey23 (?)"; + return "MasterKey23"; case 25: - return "MasterKey24 (?)"; + return "MasterKey24"; case 26: - return "MasterKey25 (?)"; + return "MasterKey25"; case 27: - return "MasterKey26 (?)"; + return "MasterKey26"; case 28: - return "MasterKey27 (?)"; + return "MasterKey27"; case 29: - return "MasterKey28 (?)"; + return "MasterKey28"; case 30: - return "MasterKey29 (?)"; + return "MasterKey29"; case 31: - return "MasterKey30 (?)"; + return "MasterKey30"; case 32: - return "MasterKey31 (?)"; + return "MasterKey31"; case 33: - return "MasterKey32 (?)"; + return "MasterKey32"; default: return "?"; } diff --git a/app.config b/app.config deleted file mode 100644 index 3e0e37c..0000000 --- a/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages.config b/packages.config deleted file mode 100644 index c42a902..0000000 --- a/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/SOURCE.txt b/tools/SOURCE.txt new file mode 100644 index 0000000..6cf508d --- /dev/null +++ b/tools/SOURCE.txt @@ -0,0 +1,6 @@ +Source: https://github.com/SciresM/hactool/releases/tag/1.4.0 + +Algorithm Hash Path +--------- ---- ---- +SHA256 36E9A221C8A7949C86ADA9388EB703C90663AEDFE9F65B6032429614C5E1ABE8 hactool-1.4.0-win.zip +SHA256 01E6CCB916C74071645DF84F13E05D0185C9B2F5D748E469C84A157A53395CF9 hactool.exe diff --git a/tools/hactool.exe b/tools/hactool.exe new file mode 100644 index 0000000..fa78409 Binary files /dev/null and b/tools/hactool.exe differ