diff --git a/.gitignore b/.gitignore
index 976661b..6a54c30 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
@@ -184,7 +184,7 @@ publish/
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
+#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
@@ -206,9 +206,6 @@ PublishScripts/
*.nuget.props
*.nuget.targets
-# Nuget personal access tokens and Credentials
-# nuget.config
-
# Microsoft Azure Build Output
csx/
*.build.csdef
@@ -297,6 +294,17 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
@@ -353,6 +361,9 @@ ASALocalRun/
# Local History for Visual Studio
.localhistory/
+# Visual Studio History (VSHistory) files
+.vshistory/
+
# BeatPulse healthcheck temp database
healthchecksdb
@@ -384,5 +395,4 @@ FodyWeavers.xsd
*.msp
# JetBrains Rider
-.idea/
*.sln.iml
\ No newline at end of file
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 6be3437..bf1135c 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -15,5 +15,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("206c6c47-87b1-477f-b6e6-f7e7c1a92f8f")]
-[assembly: AssemblyFileVersion("1.6.0")]
-[assembly: AssemblyVersion("1.6.0")]
+[assembly: AssemblyFileVersion("2.0.0")]
+[assembly: AssemblyVersion("2.0.0")]
diff --git a/Properties/PublishProfiles/Dependent.pubxml b/Properties/PublishProfiles/Dependent.pubxml
new file mode 100644
index 0000000..e534582
--- /dev/null
+++ b/Properties/PublishProfiles/Dependent.pubxml
@@ -0,0 +1,18 @@
+
+
+
+
+ Release
+ Any CPU
+ bin\Release\Dependent
+ FileSystem
+ <_TargetId>Folder
+ net6.0-windows
+ win-x64
+ false
+ true
+ false
+
+
\ No newline at end of file
diff --git a/Properties/PublishProfiles/Portable.pubxml b/Properties/PublishProfiles/Portable.pubxml
new file mode 100644
index 0000000..73c0484
--- /dev/null
+++ b/Properties/PublishProfiles/Portable.pubxml
@@ -0,0 +1,20 @@
+
+
+
+
+ Release
+ Any CPU
+ bin\Release\Portable
+ FileSystem
+ <_TargetId>Folder
+ net6.0-windows
+ win-x64
+ true
+ true
+ false
+ true
+ true
+
+
\ No newline at end of file
diff --git a/XCI Explorer.csproj b/XCI Explorer.csproj
index 71c9199..3a90001 100644
--- a/XCI Explorer.csproj
+++ b/XCI Explorer.csproj
@@ -15,4 +15,10 @@
+
+
+ Always
+ true
+
+
\ No newline at end of file
diff --git a/XCI_Explorer.Helpers/BetterBinaryReader.cs b/XCI_Explorer.Helpers/BetterBinaryReader.cs
deleted file mode 100644
index 21368b6..0000000
--- a/XCI_Explorer.Helpers/BetterBinaryReader.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using System;
-using System.IO;
-
-namespace XCI_Explorer.Helpers
-{
- public class BetterBinaryReader : IDisposable
- {
- public string FileName;
- public bool Initiated;
- public Stream Stream;
- private BinaryReader br;
-
- public BetterBinaryReader()
- {
- Initiated = false;
- }
-
- public BetterBinaryReader(string file)
- {
- Initiated = false;
- Load(file);
- }
-
- public BetterBinaryReader(Stream s)
- {
- Initiated = false;
- FileName = "";
- Stream = s;
- br = new BinaryReader(Stream);
- }
-
- public void Dispose()
- {
- Initiated = false;
- br.Close();
- br = null;
- Stream.Close();
- Stream = null;
- }
-
- public void Load(string file)
- {
- FileName = file;
- Stream = new FileStream(file, FileMode.Open);
- br = new BinaryReader(Stream);
- Initiated = true;
- }
-
- public void Seek(long o)
- {
- if (o > -1)
- {
- Stream.Seek(o, SeekOrigin.Begin);
- }
- }
-
- public void Skip(long o)
- {
- Stream.Seek(o, SeekOrigin.Current);
- }
-
- public long Position()
- {
- return Stream.Position;
- }
-
- public int Read()
- {
- return br.ReadBytes(1)[0];
- }
-
- public int Read(byte[] buffer, int index, int count)
- {
- return br.Read(buffer, index, count);
- }
-
- public int Read(char[] buffer, int index, int count)
- {
- return br.Read(buffer, index, count);
- }
-
- public byte[] ReadBytes(int l)
- {
- if (l >= 0 && l <= 2147483647)
- {
- return br.ReadBytes(l);
- }
- return new byte[0];
- }
-
- public Stream ReadBytesButLonger(long l)
- {
- MemoryStream memoryStream = new MemoryStream();
- for (long num = 0L; num < l; num++)
- {
- }
- Console.WriteLine(memoryStream.Length);
- return memoryStream;
- }
-
- public string ReadCharsAsString(int l)
- {
- return new string(br.ReadChars(l));
- }
-
- public short ReadShort()
- {
- return br.ReadInt16();
- }
-
- public short ReadInt16()
- {
- return br.ReadInt16();
- }
-
- public int ReadInt()
- {
- return br.ReadInt32();
- }
-
- public int ReadInt32()
- {
- return br.ReadInt32();
- }
-
- public long ReadLong()
- {
- return br.ReadInt64();
- }
-
- public long ReadInt64()
- {
- return br.ReadInt64();
- }
-
- public string ReadString()
- {
- return br.ReadString();
- }
-
- private long GreatestDivisor(long n)
- {
- long result = 0L;
- for (long num = 1L; num < n / 64; num++)
- {
- if (n % num == 0L && num != n)
- {
- result = num;
- }
- }
- return result;
- }
- }
-}
diff --git a/XCI_Explorer.Helpers/BetterTreeNode.cs b/XCI_Explorer.Helpers/BetterTreeNode.cs
index 89589a5..129fb7b 100644
--- a/XCI_Explorer.Helpers/BetterTreeNode.cs
+++ b/XCI_Explorer.Helpers/BetterTreeNode.cs
@@ -1,18 +1,17 @@
using System.Windows.Forms;
-namespace XCI_Explorer.Helpers
-{
- public class BetterTreeNode : TreeNode
- {
- public long Offset;
- public long Size;
- public string ExpectedHash;
- public string ActualHash;
- public long HashedRegionSize;
+namespace XCI_Explorer.Helpers;
- public BetterTreeNode(string t)
- {
- base.Text = t;
- }
+public class BetterTreeNode : TreeNode
+{
+ public long Offset;
+ public long Size;
+ public string ExpectedHash;
+ public string ActualHash;
+ public long HashedRegionSize;
+
+ public BetterTreeNode(string t)
+ {
+ Text = t;
}
}
diff --git a/XCI_Explorer/CNMT.cs b/XCI_Explorer/CNMT.cs
index c7ab6d5..33d2975 100644
--- a/XCI_Explorer/CNMT.cs
+++ b/XCI_Explorer/CNMT.cs
@@ -1,80 +1,79 @@
using System;
using System.Linq;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+internal static class CNMT
{
- internal static class CNMT
+ public class CNMT_Header
{
- public class CNMT_Header
+ public byte[] Data;
+ public long TitleID;
+ public int TitleVersion;
+ public byte Type;
+ public byte Reserved1;
+ public short Offset;
+ public short ContentCount;
+ public short MetaCount;
+ public byte[] Reserved2;
+
+ public enum TitleType
{
- public byte[] Data;
- public long TitleID;
- public int TitleVersion;
- public byte Type;
- public byte Reserved1;
- public short Offset;
- public short ContentCount;
- public short MetaCount;
- public byte[] Reserved2;
-
- public enum TitleType
- {
- SYSTEM_PROGRAMS = 0x01,
- SYSTEM_DATA_ARCHIVES,
- SYSTEM_UPDATE,
- FIRMWARE_PACKAGE_A,
- FIRMWARE_PACKAGE_B,
- REGULAR_APPLICATION = 0x80,
- UPDATE_TITLE,
- ADD_ON_CONTENT,
- DELTA_TITLE
- }
-
- public CNMT_Header(byte[] data)
- {
- Data = data;
- TitleID = BitConverter.ToInt64(data, 0);
- TitleVersion = BitConverter.ToInt32(data, 8);
- Type = Data[12];
- Reserved1 = Data[13];
- Offset = BitConverter.ToInt16(data, 14);
- ContentCount = BitConverter.ToInt16(data, 16);
- MetaCount = BitConverter.ToInt16(data, 16);
- Reserved2 = Data.Skip(20).Take(12).ToArray();
- }
+ SYSTEM_PROGRAMS = 0x01,
+ SYSTEM_DATA_ARCHIVES,
+ SYSTEM_UPDATE,
+ FIRMWARE_PACKAGE_A,
+ FIRMWARE_PACKAGE_B,
+ REGULAR_APPLICATION = 0x80,
+ UPDATE_TITLE,
+ ADD_ON_CONTENT,
+ DELTA_TITLE
}
- public class CNMT_Entry
+ public CNMT_Header(byte[] data)
{
- public byte[] Data;
- public byte[] Hash;
- public byte[] NcaId;
- public long Size;
- public byte Type;
- public byte Reserved;
-
- public enum ContentType
- {
- META,
- PROGRAM,
- DATA,
- CONTROL,
- OFFLINE_MANUAL,
- LEGAL,
- GAME_UPDATE
- }
-
- public CNMT_Entry(byte[] data)
- {
- Data = data;
- Hash = Data.Skip(0).Take(32).ToArray();
- NcaId = Data.Skip(32).Take(16).ToArray();
- Size = BitConverter.ToInt32(data, 48) + BitConverter.ToInt16(data, 52) * 65536;
- Type = Data[54];
- Reserved = Data[55];
- }
+ Data = data;
+ TitleID = BitConverter.ToInt64(data, 0);
+ TitleVersion = BitConverter.ToInt32(data, 8);
+ Type = Data[12];
+ Reserved1 = Data[13];
+ Offset = BitConverter.ToInt16(data, 14);
+ ContentCount = BitConverter.ToInt16(data, 16);
+ MetaCount = BitConverter.ToInt16(data, 16);
+ Reserved2 = Data.Skip(20).Take(12).ToArray();
}
-
- public static CNMT_Header[] CNMT_Headers = new CNMT_Header[1];
}
+
+ public class CNMT_Entry
+ {
+ public byte[] Data;
+ public byte[] Hash;
+ public byte[] NcaId;
+ public long Size;
+ public byte Type;
+ public byte Reserved;
+
+ public enum ContentType
+ {
+ META,
+ PROGRAM,
+ DATA,
+ CONTROL,
+ OFFLINE_MANUAL,
+ LEGAL,
+ GAME_UPDATE
+ }
+
+ public CNMT_Entry(byte[] data)
+ {
+ Data = data;
+ Hash = Data.Skip(0).Take(32).ToArray();
+ NcaId = Data.Skip(32).Take(16).ToArray();
+ Size = BitConverter.ToInt32(data, 48) + BitConverter.ToInt16(data, 52) * 65536;
+ Type = Data[54];
+ Reserved = Data[55];
+ }
+ }
+
+ public static CNMT_Header[] CNMT_Headers = new CNMT_Header[1];
}
diff --git a/XCI_Explorer/CenterWinDialog.cs b/XCI_Explorer/CenterWinDialog.cs
index de53275..0119610 100644
--- a/XCI_Explorer/CenterWinDialog.cs
+++ b/XCI_Explorer/CenterWinDialog.cs
@@ -1,69 +1,77 @@
using System;
-using System.Windows.Forms;
-using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+public class CenterWinDialog : IDisposable
{
- public class CenterWinDialog : IDisposable
+ private int mTries = 0;
+ private Form mOwner;
+
+ public CenterWinDialog(Form owner)
{
- private int mTries = 0;
- private Form mOwner;
-
- public CenterWinDialog(Form owner)
+ mOwner = owner;
+ if (owner.WindowState != FormWindowState.Minimized)
{
- mOwner = owner;
- if (owner.WindowState != FormWindowState.Minimized)
- {
- owner.BeginInvoke(new MethodInvoker(findDialog));
- }
+ 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; }
}
+
+ private void findDialog()
+ {
+ // Enumerate windows to find the message box
+ if (mTries < 0)
+ {
+ return;
+ }
+ EnumThreadWndProc callback = new(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(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.cs b/XCI_Explorer/CertForm.cs
index 24e353a..40b55a4 100644
--- a/XCI_Explorer/CertForm.cs
+++ b/XCI_Explorer/CertForm.cs
@@ -2,19 +2,18 @@
using System.IO;
using System.Windows.Forms;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+public partial class CertForm : Form
{
- public partial class CertForm : Form
+ public CertForm(MainForm mainForm)
{
- public CertForm(MainForm mainForm)
- {
- InitializeComponent();
- FileStream fileStream = new FileStream(mainForm.TB_File.Text, FileMode.Open, FileAccess.Read);
- byte[] array = new byte[512];
- fileStream.Position = 28672L;
- fileStream.Read(array, 0, 512);
- hbxHexView.ByteProvider = new DynamicByteProvider(array);
- fileStream.Close();
- }
+ InitializeComponent();
+ FileStream fileStream = new(mainForm.TB_File.Text, FileMode.Open, FileAccess.Read);
+ byte[] array = new byte[512];
+ fileStream.Position = 28672L;
+ fileStream.Read(array, 0, 512);
+ hbxHexView.ByteProvider = new DynamicByteProvider(array);
+ fileStream.Close();
}
}
diff --git a/XCI_Explorer/HFS0.cs b/XCI_Explorer/HFS0.cs
index 761e350..a98e5e6 100644
--- a/XCI_Explorer/HFS0.cs
+++ b/XCI_Explorer/HFS0.cs
@@ -2,51 +2,50 @@ using System;
using System.Linq;
using System.Text;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+internal static class HFS0
{
- internal static class HFS0
+ public class HFS0_Header
{
- public class HFS0_Header
+ public byte[] Data;
+ public string Magic;
+ public int FileCount;
+ public int StringTableSize;
+ public int Reserved;
+
+ public HFS0_Header(byte[] data)
{
- public byte[] Data;
- public string Magic;
- public int FileCount;
- public int StringTableSize;
- public int Reserved;
-
- public HFS0_Header(byte[] data)
- {
- Data = data;
- Magic = Encoding.UTF8.GetString(Data.Take(4).ToArray());
- FileCount = BitConverter.ToInt32(data, 4);
- StringTableSize = BitConverter.ToInt32(data, 8);
- Reserved = BitConverter.ToInt32(data, 12);
- }
+ Data = data;
+ Magic = Encoding.UTF8.GetString(Data.Take(4).ToArray());
+ FileCount = BitConverter.ToInt32(data, 4);
+ StringTableSize = BitConverter.ToInt32(data, 8);
+ Reserved = BitConverter.ToInt32(data, 12);
}
-
- public class HSF0_Entry
- {
- public byte[] Data;
- public long Offset;
- public long Size;
- public int Name_ptr;
- public int HashedRegionSize;
- public long Padding;
- public byte[] Hash;
- public string Name;
-
- public HSF0_Entry(byte[] data)
- {
- Data = data;
- Offset = BitConverter.ToInt64(data, 0);
- Size = BitConverter.ToInt64(data, 8);
- Name_ptr = BitConverter.ToInt32(data, 16);
- HashedRegionSize = BitConverter.ToInt32(data, 20);
- Padding = BitConverter.ToInt64(data, 24);
- Hash = Data.Skip(32).Take(32).ToArray();
- }
- }
-
- public static HFS0_Header[] HFS0_Headers = new HFS0_Header[1];
}
+
+ public class HSF0_Entry
+ {
+ public byte[] Data;
+ public long Offset;
+ public long Size;
+ public int Name_ptr;
+ public int HashedRegionSize;
+ public long Padding;
+ public byte[] Hash;
+ public string Name;
+
+ public HSF0_Entry(byte[] data)
+ {
+ Data = data;
+ Offset = BitConverter.ToInt64(data, 0);
+ Size = BitConverter.ToInt64(data, 8);
+ Name_ptr = BitConverter.ToInt32(data, 16);
+ HashedRegionSize = BitConverter.ToInt32(data, 20);
+ Padding = BitConverter.ToInt64(data, 24);
+ Hash = Data.Skip(32).Take(32).ToArray();
+ }
+ }
+
+ public static HFS0_Header[] HFS0_Headers = new HFS0_Header[1];
}
diff --git a/XCI_Explorer/MainForm.Designer.cs b/XCI_Explorer/MainForm.Designer.cs
index e2ce910..aefd75a 100644
--- a/XCI_Explorer/MainForm.Designer.cs
+++ b/XCI_Explorer/MainForm.Designer.cs
@@ -36,17 +36,19 @@ namespace XCI_Explorer
this.TB_File = new System.Windows.Forms.TextBox();
this.TABC_Main = new System.Windows.Forms.TabControl();
this.TABP_XCI = new System.Windows.Forms.TabPage();
+ this.TB_GameRev = new System.Windows.Forms.RichTextBox();
+ this.label12 = new System.Windows.Forms.Label();
this.B_TrimXCI = new System.Windows.Forms.Button();
this.TB_ProdCode = new System.Windows.Forms.TextBox();
this.label8 = new System.Windows.Forms.Label();
this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.label11 = new System.Windows.Forms.Label();
this.TB_Dev = new System.Windows.Forms.TextBox();
this.label10 = new System.Windows.Forms.Label();
this.TB_Name = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.PB_GameIcon = new System.Windows.Forms.PictureBox();
this.CB_RegionName = new System.Windows.Forms.ComboBox();
- this.TB_GameRev = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.B_ViewCert = new System.Windows.Forms.Button();
@@ -87,9 +89,9 @@ namespace XCI_Explorer
//
// B_LoadROM
//
- this.B_LoadROM.Location = new System.Drawing.Point(4, 12);
+ this.B_LoadROM.Location = new System.Drawing.Point(4, 11);
this.B_LoadROM.Name = "B_LoadROM";
- this.B_LoadROM.Size = new System.Drawing.Size(75, 23);
+ this.B_LoadROM.Size = new System.Drawing.Size(75, 21);
this.B_LoadROM.TabIndex = 0;
this.B_LoadROM.Text = "Load Game";
this.B_LoadROM.UseVisualStyleBackColor = true;
@@ -98,31 +100,31 @@ namespace XCI_Explorer
// TB_File
//
this.TB_File.AllowDrop = true;
- this.TB_File.Location = new System.Drawing.Point(85, 13);
+ this.TB_File.Location = new System.Drawing.Point(85, 12);
this.TB_File.Name = "TB_File";
this.TB_File.ReadOnly = true;
- this.TB_File.Size = new System.Drawing.Size(258, 20);
+ this.TB_File.Size = new System.Drawing.Size(268, 21);
this.TB_File.TabIndex = 1;
- this.TB_File.DragDrop += new System.Windows.Forms.DragEventHandler(this.TB_File_DragDrop);
- this.TB_File.DragEnter += new System.Windows.Forms.DragEventHandler(this.TB_File_DragEnter);
//
// TABC_Main
//
this.TABC_Main.Controls.Add(this.TABP_XCI);
this.TABC_Main.Controls.Add(this.tabPage2);
- this.TABC_Main.Location = new System.Drawing.Point(4, 41);
+ this.TABC_Main.Location = new System.Drawing.Point(4, 38);
this.TABC_Main.Name = "TABC_Main";
this.TABC_Main.SelectedIndex = 0;
- this.TABC_Main.Size = new System.Drawing.Size(355, 485);
+ this.TABC_Main.Size = new System.Drawing.Size(364, 511);
this.TABC_Main.TabIndex = 2;
//
// TABP_XCI
//
+ this.TABP_XCI.AllowDrop = true;
+ this.TABP_XCI.Controls.Add(this.TB_GameRev);
+ this.TABP_XCI.Controls.Add(this.label12);
this.TABP_XCI.Controls.Add(this.B_TrimXCI);
this.TABP_XCI.Controls.Add(this.TB_ProdCode);
this.TABP_XCI.Controls.Add(this.label8);
this.TABP_XCI.Controls.Add(this.groupBox2);
- this.TABP_XCI.Controls.Add(this.TB_GameRev);
this.TABP_XCI.Controls.Add(this.label7);
this.TABP_XCI.Controls.Add(this.groupBox1);
this.TABP_XCI.Controls.Add(this.TB_ExactUsedSpace);
@@ -142,16 +144,37 @@ namespace XCI_Explorer
this.TABP_XCI.Location = new System.Drawing.Point(4, 22);
this.TABP_XCI.Name = "TABP_XCI";
this.TABP_XCI.Padding = new System.Windows.Forms.Padding(3);
- this.TABP_XCI.Size = new System.Drawing.Size(347, 459);
+ this.TABP_XCI.Size = new System.Drawing.Size(356, 485);
this.TABP_XCI.TabIndex = 0;
this.TABP_XCI.Text = "Main";
this.TABP_XCI.UseVisualStyleBackColor = true;
+ this.TABP_XCI.Click += new System.EventHandler(this.TABP_XCI_Click);
+ this.TABP_XCI.DragDrop += new System.Windows.Forms.DragEventHandler(this.TB_File_DragDrop);
+ this.TABP_XCI.DragEnter += new System.Windows.Forms.DragEventHandler(this.TB_File_DragEnter);
+ //
+ // TB_GameRev
+ //
+ this.TB_GameRev.Location = new System.Drawing.Point(15, 63);
+ this.TB_GameRev.Name = "TB_GameRev";
+ this.TB_GameRev.ReadOnly = true;
+ this.TB_GameRev.Size = new System.Drawing.Size(237, 99);
+ this.TB_GameRev.TabIndex = 23;
+ this.TB_GameRev.Text = "";
+ //
+ // label12
+ //
+ this.label12.AutoSize = true;
+ this.label12.Location = new System.Drawing.Point(75, 48);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(125, 12);
+ this.label12.TabIndex = 22;
+ this.label12.Text = "0 BASE, 0 UPD, 0 DLC";
//
// B_TrimXCI
//
- this.B_TrimXCI.Location = new System.Drawing.Point(90, 207);
+ this.B_TrimXCI.Location = new System.Drawing.Point(307, 178);
this.B_TrimXCI.Name = "B_TrimXCI";
- this.B_TrimXCI.Size = new System.Drawing.Size(70, 23);
+ this.B_TrimXCI.Size = new System.Drawing.Size(38, 46);
this.B_TrimXCI.TabIndex = 21;
this.B_TrimXCI.Text = "Trim XCI";
this.B_TrimXCI.UseVisualStyleBackColor = true;
@@ -159,76 +182,87 @@ namespace XCI_Explorer
//
// TB_ProdCode
//
- this.TB_ProdCode.Location = new System.Drawing.Point(238, 115);
+ this.TB_ProdCode.Location = new System.Drawing.Point(258, 141);
this.TB_ProdCode.Name = "TB_ProdCode";
this.TB_ProdCode.ReadOnly = true;
- this.TB_ProdCode.Size = new System.Drawing.Size(69, 20);
+ this.TB_ProdCode.Size = new System.Drawing.Size(87, 21);
this.TB_ProdCode.TabIndex = 20;
//
// label8
//
this.label8.AutoSize = true;
- this.label8.Location = new System.Drawing.Point(235, 99);
+ this.label8.Location = new System.Drawing.Point(258, 126);
this.label8.Name = "label8";
- this.label8.Size = new System.Drawing.Size(75, 13);
+ this.label8.Size = new System.Drawing.Size(83, 12);
this.label8.TabIndex = 19;
this.label8.Text = "Product Code:";
//
// groupBox2
//
+ this.groupBox2.Controls.Add(this.label11);
this.groupBox2.Controls.Add(this.TB_Dev);
this.groupBox2.Controls.Add(this.label10);
this.groupBox2.Controls.Add(this.TB_Name);
this.groupBox2.Controls.Add(this.label9);
this.groupBox2.Controls.Add(this.PB_GameIcon);
this.groupBox2.Controls.Add(this.CB_RegionName);
- this.groupBox2.Location = new System.Drawing.Point(22, 296);
+ this.groupBox2.Location = new System.Drawing.Point(15, 285);
this.groupBox2.Name = "groupBox2";
- this.groupBox2.Size = new System.Drawing.Size(301, 154);
+ this.groupBox2.Size = new System.Drawing.Size(330, 178);
this.groupBox2.TabIndex = 18;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Game Infos";
//
+ // label11
+ //
+ this.label11.AutoSize = true;
+ this.label11.Location = new System.Drawing.Point(6, 69);
+ this.label11.Name = "label11";
+ this.label11.Size = new System.Drawing.Size(59, 12);
+ this.label11.TabIndex = 25;
+ this.label11.Text = "Language:";
+ this.label11.Click += new System.EventHandler(this.label11_Click);
+ //
// TB_Dev
//
- this.TB_Dev.Location = new System.Drawing.Point(6, 117);
+ this.TB_Dev.Location = new System.Drawing.Point(6, 138);
this.TB_Dev.Name = "TB_Dev";
this.TB_Dev.ReadOnly = true;
- this.TB_Dev.Size = new System.Drawing.Size(145, 20);
+ this.TB_Dev.Size = new System.Drawing.Size(154, 21);
this.TB_Dev.TabIndex = 24;
//
// label10
//
this.label10.AutoSize = true;
- this.label10.Location = new System.Drawing.Point(3, 101);
+ this.label10.Location = new System.Drawing.Point(6, 123);
this.label10.Name = "label10";
- this.label10.Size = new System.Drawing.Size(59, 13);
+ this.label10.Size = new System.Drawing.Size(65, 12);
this.label10.TabIndex = 23;
this.label10.Text = "Developer:";
//
// TB_Name
//
- this.TB_Name.Location = new System.Drawing.Point(6, 66);
+ this.TB_Name.Location = new System.Drawing.Point(6, 35);
this.TB_Name.Name = "TB_Name";
this.TB_Name.ReadOnly = true;
- this.TB_Name.Size = new System.Drawing.Size(145, 20);
+ this.TB_Name.Size = new System.Drawing.Size(154, 21);
this.TB_Name.TabIndex = 22;
//
// label9
//
this.label9.AutoSize = true;
- this.label9.Location = new System.Drawing.Point(3, 50);
+ this.label9.Location = new System.Drawing.Point(6, 20);
this.label9.Name = "label9";
- this.label9.Size = new System.Drawing.Size(38, 13);
+ this.label9.Size = new System.Drawing.Size(35, 12);
this.label9.TabIndex = 21;
this.label9.Text = "Name:";
//
// PB_GameIcon
//
this.PB_GameIcon.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
- this.PB_GameIcon.Location = new System.Drawing.Point(190, 43);
+ this.PB_GameIcon.Location = new System.Drawing.Point(172, 20);
this.PB_GameIcon.Name = "PB_GameIcon";
- this.PB_GameIcon.Size = new System.Drawing.Size(105, 105);
+ this.PB_GameIcon.Size = new System.Drawing.Size(152, 147);
this.PB_GameIcon.TabIndex = 18;
this.PB_GameIcon.TabStop = false;
//
@@ -236,28 +270,20 @@ namespace XCI_Explorer
//
this.CB_RegionName.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.CB_RegionName.FormattingEnabled = true;
- this.CB_RegionName.Location = new System.Drawing.Point(77, 14);
+ this.CB_RegionName.Location = new System.Drawing.Point(6, 84);
this.CB_RegionName.Name = "CB_RegionName";
- this.CB_RegionName.Size = new System.Drawing.Size(138, 21);
+ this.CB_RegionName.Size = new System.Drawing.Size(154, 20);
this.CB_RegionName.TabIndex = 17;
this.CB_RegionName.SelectedIndexChanged += new System.EventHandler(this.CB_RegionName_SelectedIndexChanged);
//
- // TB_GameRev
- //
- this.TB_GameRev.Location = new System.Drawing.Point(24, 115);
- this.TB_GameRev.Name = "TB_GameRev";
- this.TB_GameRev.ReadOnly = true;
- this.TB_GameRev.Size = new System.Drawing.Size(124, 20);
- this.TB_GameRev.TabIndex = 16;
- //
// label7
//
this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(21, 99);
+ this.label7.Location = new System.Drawing.Point(11, 48);
this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(82, 13);
+ this.label7.Size = new System.Drawing.Size(59, 12);
this.label7.TabIndex = 15;
- this.label7.Text = "Game Revision:";
+ this.label7.Text = "Contents:";
//
// groupBox1
//
@@ -265,18 +291,18 @@ namespace XCI_Explorer
this.groupBox1.Controls.Add(this.B_ClearCert);
this.groupBox1.Controls.Add(this.B_ImportCert);
this.groupBox1.Controls.Add(this.B_ExportCert);
- this.groupBox1.Location = new System.Drawing.Point(22, 234);
+ this.groupBox1.Location = new System.Drawing.Point(15, 230);
this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(301, 52);
+ this.groupBox1.Size = new System.Drawing.Size(330, 49);
this.groupBox1.TabIndex = 14;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Cert";
//
// B_ViewCert
//
- this.B_ViewCert.Location = new System.Drawing.Point(156, 19);
+ this.B_ViewCert.Location = new System.Drawing.Point(168, 18);
this.B_ViewCert.Name = "B_ViewCert";
- this.B_ViewCert.Size = new System.Drawing.Size(66, 23);
+ this.B_ViewCert.Size = new System.Drawing.Size(74, 21);
this.B_ViewCert.TabIndex = 3;
this.B_ViewCert.Text = "View Cert";
this.B_ViewCert.UseVisualStyleBackColor = true;
@@ -284,9 +310,9 @@ namespace XCI_Explorer
//
// B_ClearCert
//
- this.B_ClearCert.Location = new System.Drawing.Point(229, 19);
+ this.B_ClearCert.Location = new System.Drawing.Point(250, 18);
this.B_ClearCert.Name = "B_ClearCert";
- this.B_ClearCert.Size = new System.Drawing.Size(66, 23);
+ this.B_ClearCert.Size = new System.Drawing.Size(74, 21);
this.B_ClearCert.TabIndex = 2;
this.B_ClearCert.Text = "Clear Cert";
this.B_ClearCert.UseVisualStyleBackColor = true;
@@ -294,9 +320,9 @@ namespace XCI_Explorer
//
// B_ImportCert
//
- this.B_ImportCert.Location = new System.Drawing.Point(83, 19);
+ this.B_ImportCert.Location = new System.Drawing.Point(86, 18);
this.B_ImportCert.Name = "B_ImportCert";
- this.B_ImportCert.Size = new System.Drawing.Size(67, 23);
+ this.B_ImportCert.Size = new System.Drawing.Size(74, 21);
this.B_ImportCert.TabIndex = 1;
this.B_ImportCert.Text = "Import Cert";
this.B_ImportCert.UseVisualStyleBackColor = true;
@@ -304,9 +330,9 @@ namespace XCI_Explorer
//
// B_ExportCert
//
- this.B_ExportCert.Location = new System.Drawing.Point(7, 19);
+ this.B_ExportCert.Location = new System.Drawing.Point(6, 18);
this.B_ExportCert.Name = "B_ExportCert";
- this.B_ExportCert.Size = new System.Drawing.Size(70, 23);
+ this.B_ExportCert.Size = new System.Drawing.Size(74, 21);
this.B_ExportCert.TabIndex = 0;
this.B_ExportCert.Text = "Export Cert";
this.B_ExportCert.UseVisualStyleBackColor = true;
@@ -314,120 +340,120 @@ namespace XCI_Explorer
//
// TB_ExactUsedSpace
//
- this.TB_ExactUsedSpace.Location = new System.Drawing.Point(166, 181);
+ this.TB_ExactUsedSpace.Location = new System.Drawing.Point(152, 203);
this.TB_ExactUsedSpace.Name = "TB_ExactUsedSpace";
this.TB_ExactUsedSpace.ReadOnly = true;
- this.TB_ExactUsedSpace.Size = new System.Drawing.Size(157, 20);
+ this.TB_ExactUsedSpace.Size = new System.Drawing.Size(152, 21);
this.TB_ExactUsedSpace.TabIndex = 13;
//
// TB_ROMExactSize
//
- this.TB_ROMExactSize.Location = new System.Drawing.Point(166, 154);
+ this.TB_ROMExactSize.Location = new System.Drawing.Point(152, 178);
this.TB_ROMExactSize.Name = "TB_ROMExactSize";
this.TB_ROMExactSize.ReadOnly = true;
- this.TB_ROMExactSize.Size = new System.Drawing.Size(157, 20);
+ this.TB_ROMExactSize.Size = new System.Drawing.Size(152, 21);
this.TB_ROMExactSize.TabIndex = 12;
//
// TB_UsedSpace
//
- this.TB_UsedSpace.Location = new System.Drawing.Point(91, 181);
+ this.TB_UsedSpace.Location = new System.Drawing.Point(77, 203);
this.TB_UsedSpace.Name = "TB_UsedSpace";
this.TB_UsedSpace.ReadOnly = true;
- this.TB_UsedSpace.Size = new System.Drawing.Size(69, 20);
+ this.TB_UsedSpace.Size = new System.Drawing.Size(69, 21);
this.TB_UsedSpace.TabIndex = 11;
//
// TB_ROMSize
//
- this.TB_ROMSize.Location = new System.Drawing.Point(91, 154);
+ this.TB_ROMSize.Location = new System.Drawing.Point(77, 178);
this.TB_ROMSize.Name = "TB_ROMSize";
this.TB_ROMSize.ReadOnly = true;
- this.TB_ROMSize.Size = new System.Drawing.Size(69, 20);
+ this.TB_ROMSize.Size = new System.Drawing.Size(69, 21);
this.TB_ROMSize.TabIndex = 10;
//
// label6
//
this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(18, 181);
+ this.label6.Location = new System.Drawing.Point(4, 203);
this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(67, 13);
+ this.label6.Size = new System.Drawing.Size(71, 12);
this.label6.TabIndex = 9;
this.label6.Text = "Used space:";
//
// label5
//
this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(27, 157);
+ this.label5.Location = new System.Drawing.Point(13, 181);
this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(58, 13);
+ this.label5.Size = new System.Drawing.Size(59, 12);
this.label5.TabIndex = 8;
this.label5.Text = "ROM Size:";
//
// TB_MKeyRev
//
- this.TB_MKeyRev.Location = new System.Drawing.Point(24, 68);
+ this.TB_MKeyRev.Location = new System.Drawing.Point(191, 21);
this.TB_MKeyRev.Name = "TB_MKeyRev";
this.TB_MKeyRev.ReadOnly = true;
- this.TB_MKeyRev.Size = new System.Drawing.Size(124, 20);
+ this.TB_MKeyRev.Size = new System.Drawing.Size(154, 21);
this.TB_MKeyRev.TabIndex = 7;
//
// label4
//
this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(21, 52);
+ this.label4.Location = new System.Drawing.Point(189, 6);
this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(104, 13);
+ this.label4.Size = new System.Drawing.Size(119, 12);
this.label4.TabIndex = 6;
this.label4.Text = "MasterKey Revision:";
//
// TB_SDKVer
//
- this.TB_SDKVer.Location = new System.Drawing.Point(238, 68);
+ this.TB_SDKVer.Location = new System.Drawing.Point(258, 102);
this.TB_SDKVer.Name = "TB_SDKVer";
this.TB_SDKVer.ReadOnly = true;
- this.TB_SDKVer.Size = new System.Drawing.Size(69, 20);
+ this.TB_SDKVer.Size = new System.Drawing.Size(87, 21);
this.TB_SDKVer.TabIndex = 5;
//
// label3
//
this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(235, 52);
+ this.label3.Location = new System.Drawing.Point(258, 87);
this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(70, 13);
+ this.label3.Size = new System.Drawing.Size(77, 12);
this.label3.TabIndex = 4;
this.label3.Text = "SDK Version:";
//
// TB_Capacity
//
- this.TB_Capacity.Location = new System.Drawing.Point(238, 23);
+ this.TB_Capacity.Location = new System.Drawing.Point(258, 63);
this.TB_Capacity.Name = "TB_Capacity";
this.TB_Capacity.ReadOnly = true;
- this.TB_Capacity.Size = new System.Drawing.Size(69, 20);
+ this.TB_Capacity.Size = new System.Drawing.Size(87, 21);
this.TB_Capacity.TabIndex = 3;
//
// label2
//
this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(235, 7);
+ this.label2.Location = new System.Drawing.Point(258, 48);
this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(51, 13);
+ this.label2.Size = new System.Drawing.Size(59, 12);
this.label2.TabIndex = 2;
this.label2.Text = "Capacity:";
//
// label1
//
this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(21, 7);
+ this.label1.Location = new System.Drawing.Point(12, 6);
this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(44, 13);
+ this.label1.Size = new System.Drawing.Size(59, 12);
this.label1.TabIndex = 1;
this.label1.Text = "Title ID:";
//
// TB_TID
//
- this.TB_TID.Location = new System.Drawing.Point(24, 23);
+ this.TB_TID.Location = new System.Drawing.Point(15, 21);
this.TB_TID.Name = "TB_TID";
this.TB_TID.ReadOnly = true;
- this.TB_TID.Size = new System.Drawing.Size(124, 20);
+ this.TB_TID.Size = new System.Drawing.Size(170, 21);
this.TB_TID.TabIndex = 0;
//
// tabPage2
@@ -443,7 +469,7 @@ namespace XCI_Explorer
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
- this.tabPage2.Size = new System.Drawing.Size(347, 459);
+ this.tabPage2.Size = new System.Drawing.Size(356, 485);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Partitions";
this.tabPage2.UseVisualStyleBackColor = true;
@@ -451,18 +477,18 @@ namespace XCI_Explorer
// LB_HashedRegionSize
//
this.LB_HashedRegionSize.AutoSize = true;
- this.LB_HashedRegionSize.Location = new System.Drawing.Point(6, 416);
+ this.LB_HashedRegionSize.Location = new System.Drawing.Point(6, 439);
this.LB_HashedRegionSize.Name = "LB_HashedRegionSize";
- this.LB_HashedRegionSize.Size = new System.Drawing.Size(101, 13);
+ this.LB_HashedRegionSize.Size = new System.Drawing.Size(107, 12);
this.LB_HashedRegionSize.TabIndex = 7;
this.LB_HashedRegionSize.Text = "HashedRegionSize:";
//
// LB_ActualHash
//
this.LB_ActualHash.AutoSize = true;
- this.LB_ActualHash.Location = new System.Drawing.Point(6, 443);
+ this.LB_ActualHash.Location = new System.Drawing.Point(6, 464);
this.LB_ActualHash.Name = "LB_ActualHash";
- this.LB_ActualHash.Size = new System.Drawing.Size(68, 13);
+ this.LB_ActualHash.Size = new System.Drawing.Size(77, 12);
this.LB_ActualHash.TabIndex = 6;
this.LB_ActualHash.Text = "Actual Hash:";
this.LB_ActualHash.DoubleClick += new System.EventHandler(this.LB_ActualHash_DoubleClick);
@@ -470,9 +496,9 @@ namespace XCI_Explorer
// LB_ExpectedHash
//
this.LB_ExpectedHash.AutoSize = true;
- this.LB_ExpectedHash.Location = new System.Drawing.Point(6, 430);
+ this.LB_ExpectedHash.Location = new System.Drawing.Point(6, 452);
this.LB_ExpectedHash.Name = "LB_ExpectedHash";
- this.LB_ExpectedHash.Size = new System.Drawing.Size(73, 13);
+ this.LB_ExpectedHash.Size = new System.Drawing.Size(77, 12);
this.LB_ExpectedHash.TabIndex = 5;
this.LB_ExpectedHash.Text = "Header Hash:";
this.LB_ExpectedHash.DoubleClick += new System.EventHandler(this.LB_ExpectedHash_DoubleClick);
@@ -480,9 +506,9 @@ namespace XCI_Explorer
// B_Extract
//
this.B_Extract.Enabled = false;
- this.B_Extract.Location = new System.Drawing.Point(296, 367);
+ this.B_Extract.Location = new System.Drawing.Point(296, 394);
this.B_Extract.Name = "B_Extract";
- this.B_Extract.Size = new System.Drawing.Size(48, 23);
+ this.B_Extract.Size = new System.Drawing.Size(48, 21);
this.B_Extract.TabIndex = 4;
this.B_Extract.Text = "Extract";
this.B_Extract.UseVisualStyleBackColor = true;
@@ -491,27 +517,27 @@ namespace XCI_Explorer
// LB_DataSize
//
this.LB_DataSize.AutoSize = true;
- this.LB_DataSize.Location = new System.Drawing.Point(6, 403);
+ this.LB_DataSize.Location = new System.Drawing.Point(6, 427);
this.LB_DataSize.Name = "LB_DataSize";
- this.LB_DataSize.Size = new System.Drawing.Size(30, 13);
+ this.LB_DataSize.Size = new System.Drawing.Size(35, 12);
this.LB_DataSize.TabIndex = 3;
this.LB_DataSize.Text = "Size:";
//
// LB_DataOffset
//
this.LB_DataOffset.AutoSize = true;
- this.LB_DataOffset.Location = new System.Drawing.Point(6, 390);
+ this.LB_DataOffset.Location = new System.Drawing.Point(6, 415);
this.LB_DataOffset.Name = "LB_DataOffset";
- this.LB_DataOffset.Size = new System.Drawing.Size(38, 13);
+ this.LB_DataOffset.Size = new System.Drawing.Size(47, 12);
this.LB_DataOffset.TabIndex = 2;
this.LB_DataOffset.Text = "Offset:";
//
// LB_SelectedData
//
this.LB_SelectedData.AutoSize = true;
- this.LB_SelectedData.Location = new System.Drawing.Point(6, 367);
+ this.LB_SelectedData.Location = new System.Drawing.Point(6, 394);
this.LB_SelectedData.Name = "LB_SelectedData";
- this.LB_SelectedData.Size = new System.Drawing.Size(51, 13);
+ this.LB_SelectedData.Size = new System.Drawing.Size(53, 12);
this.LB_SelectedData.TabIndex = 1;
this.LB_SelectedData.Text = "FileName";
//
@@ -521,7 +547,7 @@ namespace XCI_Explorer
this.TV_Partitions.HideSelection = false;
this.TV_Partitions.Location = new System.Drawing.Point(3, 3);
this.TV_Partitions.Name = "TV_Partitions";
- this.TV_Partitions.Size = new System.Drawing.Size(341, 361);
+ this.TV_Partitions.Size = new System.Drawing.Size(350, 385);
this.TV_Partitions.TabIndex = 0;
this.TV_Partitions.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.TV_Partitions_AfterSelect);
//
@@ -533,9 +559,9 @@ namespace XCI_Explorer
// MainForm
//
this.AllowDrop = true;
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(362, 529);
+ this.ClientSize = new System.Drawing.Size(370, 553);
this.Controls.Add(this.TABC_Main);
this.Controls.Add(this.TB_File);
this.Controls.Add(this.B_LoadROM);
@@ -555,6 +581,7 @@ namespace XCI_Explorer
this.tabPage2.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
+
}
#endregion
@@ -591,7 +618,6 @@ namespace XCI_Explorer
private TextBox TB_ROMSize;
private Label label6;
private Label label5;
- private TextBox TB_GameRev;
private Label label7;
private GroupBox groupBox1;
private Button B_ClearCert;
@@ -617,5 +643,8 @@ namespace XCI_Explorer
private Label LB_HashedRegionSize;
private BackgroundWorker backgroundWorker1;
private Button B_TrimXCI;
+ private Label label11;
+ private Label label12;
+ private RichTextBox TB_GameRev;
}
}
\ No newline at end of file
diff --git a/XCI_Explorer/MainForm.cs b/XCI_Explorer/MainForm.cs
index aa9b14a..ca76fda 100644
--- a/XCI_Explorer/MainForm.cs
+++ b/XCI_Explorer/MainForm.cs
@@ -15,162 +15,1429 @@ using System.Xml.Linq;
using XCI_Explorer.Helpers;
using XTSSharp;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+public partial class MainForm : Form
{
- public partial class MainForm : Form
+ public List chars = new();
+ public byte[] NcaHeaderEncryptionKey1_Prod;
+ public byte[] NcaHeaderEncryptionKey2_Prod;
+ public string Mkey;
+ public double UsedSize;
+ private Image[] Icons = new Image[16];
+ private readonly string[] Language = new string[16] {
+ "American English",
+ "British English",
+ "Japanese",
+ "French",
+ "German",
+ "Latin American Spanish",
+ "Spanish",
+ "Italian",
+ "Dutch",
+ "Canadian French",
+ "Portuguese",
+ "Russian",
+ "Korean",
+ "Traditional Chinese",
+ "Simplified Chinese",
+ "???"
+ };
+
+ public MainForm()
{
- public List chars = new List();
- public byte[] NcaHeaderEncryptionKey1_Prod;
- public byte[] NcaHeaderEncryptionKey2_Prod;
- public string Mkey;
- public double UsedSize;
- private Image[] Icons = new Image[16];
- private string[] Language = new string[16] {
- "American English",
- "British English",
- "Japanese",
- "French",
- "German",
- "Latin American Spanish",
- "Spanish",
- "Italian",
- "Dutch",
- "Canadian French",
- "Portuguese",
- "Russian",
- "Korean",
- "Traditional Chinese",
- "Simplified Chinese",
- "???"
- };
+ InitializeComponent();
- public MainForm()
+ Text = $"XCI Explorer v{getAssemblyVersion()}";
+
+ LB_SelectedData.Text = "";
+ LB_DataOffset.Text = "";
+ LB_DataSize.Text = "";
+ LB_HashedRegionSize.Text = "";
+ LB_ActualHash.Text = "";
+ LB_ExpectedHash.Text = "";
+
+ Show();
+
+ //MAC - Set Current Directory to application directory so it can find the keys
+ String startupPath = Application.StartupPath;
+ Directory.SetCurrentDirectory(startupPath);
+
+ if (!File.Exists("keys.txt"))
{
- InitializeComponent();
-
- this.Text = "XCI Explorer v" + getAssemblyVersion();
-
- LB_SelectedData.Text = "";
- LB_DataOffset.Text = "";
- LB_DataSize.Text = "";
- LB_HashedRegionSize.Text = "";
- LB_ActualHash.Text = "";
- LB_ExpectedHash.Text = "";
-
- //MAC - Set Current Directory to application directory so it can find the keys
- String startupPath = Application.StartupPath;
- Directory.SetCurrentDirectory(startupPath);
+ new CenterWinDialog(this);
+ 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 HttpClient client = new();
+ using HttpResponseMessage response = client.Send(new HttpRequestMessage(HttpMethod.Get, Util.Base64Decode("aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L0Z2M25GRzJR")));
+ using Stream stream = response.Content.ReadAsStream();
+ using FileStream fs = new("keys.txt", FileMode.CreateNew);
+ stream.CopyTo(fs);
+ }
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 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"))
- {
- MessageBox.Show("keys.txt failed to load.\nPlease include keys.txt in the root folder.");
- Environment.Exit(0);
- }
- }
-
- if (!File.Exists($"tools{Path.DirectorySeparatorChar}hactool.exe"))
- {
- Directory.CreateDirectory("tools");
- MessageBox.Show("hactool.exe is missing.\nPlease include hactool.exe in the 'tools' folder.");
+ new CenterWinDialog(this);
+ MessageBox.Show("keys.txt failed to load.\nPlease include keys.txt in the root folder.");
Environment.Exit(0);
}
-
- getKey();
-
- //MAC - Set the double clicked file name into the UI and process file
- String[] args = Environment.GetCommandLineArgs();
- if (args.Length > 1)
- {
- TB_File.Text = args[1];
- Application.DoEvents();
- ProcessFile();
- }
-
}
- private string getAssemblyVersion()
+ if (!File.Exists(Path.Join("tools", "hactool.exe")))
{
- string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
- string[] versionArray = assemblyVersion.Split('.');
-
- assemblyVersion = string.Join(".", versionArray.Take(3));
-
- return assemblyVersion;
+ Directory.CreateDirectory("tools");
+ new CenterWinDialog(this);
+ MessageBox.Show("hactool.exe is missing.\nPlease include hactool.exe in the 'tools' folder.");
+ Environment.Exit(0);
}
- private void getKey()
+ getKey();
+
+ //MAC - Set the double clicked file name into the UI and process file
+ String[] args = Environment.GetCommandLineArgs();
+ if (args.Length > 1)
{
- string text = (from x in File.ReadAllLines("keys.txt")
- select x.Split('=') into x
- where x.Length > 1
- select x).ToDictionary((string[] x) => x[0].Trim(), (string[] x) => x[1])["header_key"].Replace(" ", "");
- NcaHeaderEncryptionKey1_Prod = Util.StringToByteArray(text.Remove(32, 32));
- NcaHeaderEncryptionKey2_Prod = Util.StringToByteArray(text.Remove(0, 32));
+ TB_File.Text = args[1];
+ Application.DoEvents();
+ ProcessFile();
}
- public bool getMKey()
+ }
+
+ private string getAssemblyVersion()
+ {
+ string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ string[] versionArray = assemblyVersion.Split('.');
+
+ assemblyVersion = string.Join(".", versionArray.Take(3));
+
+ return assemblyVersion;
+ }
+
+ private void getKey()
+ {
+ string text = (from x in File.ReadAllLines("keys.txt")
+ select x.Split('=') into x
+ where x.Length > 1
+ select x).ToDictionary((string[] x) => x[0].Trim(), (string[] x) => x[1])["header_key"].Replace(" ", "");
+ NcaHeaderEncryptionKey1_Prod = Util.StringToByteArray(text.Remove(32, 32));
+ NcaHeaderEncryptionKey2_Prod = Util.StringToByteArray(text.Remove(0, 32));
+ }
+
+ public bool getMKey()
+ {
+ Dictionary dictionary = (from x in File.ReadAllLines("keys.txt")
+ select x.Split('=') into x
+ where x.Length > 1
+ select x).ToDictionary((string[] x) => x[0].Trim(), (string[] x) => x[1]);
+ Mkey = "master_key_";
+ string MkeyL = "master_key_";
+ if (NCA.NCA_Headers[0].MasterKeyRev == 0 || NCA.NCA_Headers[0].MasterKeyRev == 1)
+ {
+ Mkey += "00";
+ }
+ else if (NCA.NCA_Headers[0].MasterKeyRev < 17)
+ {
+ int num = NCA.NCA_Headers[0].MasterKeyRev - 1;
+ string capchar = num.ToString("X");
+ string lowchar = capchar.ToLower();
+ Mkey += $"0{capchar}";
+ MkeyL += $"0{lowchar}";
+ }
+ else if (NCA.NCA_Headers[0].MasterKeyRev >= 17)
+ {
+ int num2 = NCA.NCA_Headers[0].MasterKeyRev - 1;
+ string capchar = num2.ToString("X");
+ string lowchar = capchar.ToLower();
+ Mkey += num2.ToString();
+ MkeyL += num2.ToString();
+ }
+ try
+ {
+ Mkey = dictionary[Mkey].Replace(" ", "");
+ return true;
+ }
+ catch
{
- Dictionary dictionary = (from x in File.ReadAllLines("keys.txt")
- select x.Split('=') into x
- where x.Length > 1
- select x).ToDictionary((string[] x) => x[0].Trim(), (string[] x) => x[1]);
- Mkey = "master_key_";
- string MkeyL = "master_key_";
- if (NCA.NCA_Headers[0].MasterKeyRev == 0 || NCA.NCA_Headers[0].MasterKeyRev == 1)
- {
- Mkey += "00";
- }
- else if (NCA.NCA_Headers[0].MasterKeyRev < 17)
- {
- int num = NCA.NCA_Headers[0].MasterKeyRev - 1;
- string capchar = num.ToString("X");
- string lowchar = capchar.ToLower();
- Mkey = Mkey + "0" + capchar;
- MkeyL = MkeyL + "0" + lowchar;
- }
- else if (NCA.NCA_Headers[0].MasterKeyRev >= 17)
- {
- int num2 = NCA.NCA_Headers[0].MasterKeyRev - 1;
- string capchar = num2.ToString("X");
- string lowchar = capchar.ToLower();
- Mkey += num2.ToString();
- MkeyL += num2.ToString();
- }
try
{
- Mkey = dictionary[Mkey].Replace(" ", "");
+ MkeyL = dictionary[MkeyL].Replace(" ", "");
return true;
}
catch
{
+ return false;
+ }
+ }
+ }
+
+ private void ProcessFile()
+ {
+ // Code needs refactoring
+ LB_SelectedData.Text = "";
+ LB_DataOffset.Text = "";
+ LB_DataSize.Text = "";
+ LB_HashedRegionSize.Text = "";
+ LB_ExpectedHash.Text = "";
+ LB_ActualHash.Text = "";
+ B_Extract.Enabled = false;
+
+ try
+ {
+ if (CheckNSP())
+ {
+ B_TrimXCI.Enabled = false;
+ B_ExportCert.Enabled = false;
+ B_ImportCert.Enabled = false;
+ B_ViewCert.Enabled = false;
+ B_ClearCert.Enabled = false;
+
+ LoadNSP();
+ }
+ else if (CheckXCI())
+ {
+ B_TrimXCI.Enabled = true;
+ B_ExportCert.Enabled = true;
+ B_ImportCert.Enabled = true;
+ B_ViewCert.Enabled = true;
+ B_ClearCert.Enabled = true;
+
+ LoadXCI();
+ }
+ else
+ {
+ TB_File.Text = null;
+ new CenterWinDialog(this);
+ MessageBox.Show("File is corrupt or unsupported.");
+ }
+ }
+ catch (Exception e)
+ {
+ new CenterWinDialog(this);
+ MessageBox.Show($"File is corrupt or unsupported.\nException: {e.Message}");
+ }
+
+ }
+
+ private void B_LoadROM_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog openFileDialog = new()
+ {
+ Filter = "Switch Game File (*.xci, *.nsp, *.nsz)|*.xci;*.nsp;*.nsz|All Files (*.*)|*.*"
+ };
+ new CenterWinDialog(this);
+ if (openFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ TB_File.Text = openFileDialog.FileName;
+ ProcessFile();
+ }
+ }
+
+ private void LoadXCI()
+ {
+ string[] array = new string[5]
+ {
+ "B",
+ "KB",
+ "MB",
+ "GB",
+ "TB"
+ };
+ double num = new FileInfo(TB_File.Text).Length;
+ TB_ROMExactSize.Text = $"({num} bytes)";
+ int num2 = 0;
+ while (num >= 1024.0 && num2 < array.Length - 1)
+ {
+ num2++;
+ num /= 1024.0;
+ }
+ TB_ROMSize.Text = $"{num:0.##} {array[num2]}";
+ double num3 = UsedSize = XCI.XCI_Headers[0].CardSize2 * 512 + 512;
+ TB_ExactUsedSpace.Text = $"({num3} bytes)";
+ if (isTrimmed())
+ {
+ B_TrimXCI.Enabled = false;
+ }
+
+ num2 = 0;
+ while (num3 >= 1024.0 && num2 < array.Length - 1)
+ {
+ num2++;
+ num3 /= 1024.0;
+ }
+ TB_UsedSpace.Text = $"{num3:0.##} {array[num2]}";
+ TB_Capacity.Text = Util.GetCapacity(XCI.XCI_Headers[0].CardSize1);
+ LoadPartitions();
+ LoadNCAData();
+ LoadGameInfos();
+ }
+
+ // Giba's better implementation (more native)
+ public void LoadNSP()
+ {
+ CB_RegionName.Items.Clear();
+ CB_RegionName.Enabled = true;
+ TB_TID.Text = "";
+ TB_Capacity.Text = "";
+ TB_MKeyRev.Text = "";
+ TB_SDKVer.Text = "";
+ TB_GameRev.Text = "";
+ TB_ProdCode.Text = "";
+ TB_Name.Text = "";
+ TB_Dev.Text = "";
+
+ int basenum = 0;
+ int updnum = 0;
+ int dlcnum = 0;
+ string pversion = "";
+ int patchflag = 0;
+ int patchnum = 0;
+ string patchver = "";
+ int baseflag = 0;
+ string[] basetitle = new string[5];
+ string[] updtitle = new string[10];
+ string[] dlctitle = new string[300];
+
+ PB_GameIcon.BackgroundImage = null;
+ Array.Clear(Icons, 0, Icons.Length);
+ TV_Partitions.Nodes.Clear();
+ FileInfo fi = new(TB_File.Text);
+ string contentType = "";
+
+ // Maximum number of files in NSP to read in
+ const int MAXFILES = 250;
+
+ //Get File Size
+ string[] array_fs = new string[5] { "B", "KB", "MB", "GB", "TB" };
+ double num_fs = fi.Length;
+ int num2_fs = 0;
+ TB_ROMExactSize.Text = $"({num_fs} bytes)";
+ TB_ExactUsedSpace.Text = TB_ROMExactSize.Text;
+
+ while (num_fs >= 1024.0 && num2_fs < array_fs.Length - 1)
+ {
+ num2_fs++;
+ num_fs /= 1024.0;
+ }
+ TB_ROMSize.Text = $"{num_fs:0.##} {array_fs[num2_fs]}";
+ TB_UsedSpace.Text = TB_ROMSize.Text;
+
+ LoadNSPPartitions();
+
+ Process process = new();
+ try
+ {
+ FileStream fileStream = File.OpenRead(TB_File.Text);
+ string ncaTarget = "";
+ string xmlVersion = "";
+
+ List chars = new();
+ byte[] array = new byte[16];
+ byte[] array2 = new byte[24];
+ fileStream.Read(array, 0, 16);
+ PFS0.PFS0_Headers[0] = new(array);
+ if (!PFS0.PFS0_Headers[0].Magic.Contains("PFS0"))
+ {
+ return;
+ }
+ PFS0.PFS0_Entry[] array3;
+ array3 = new PFS0.PFS0_Entry[Math.Max(PFS0.PFS0_Headers[0].FileCount, MAXFILES)]; //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
+
+ for (int m = 0; m < PFS0.PFS0_Headers[0].FileCount; m++)
+ {
+ fileStream.Position = 16 + 24 * m;
+ fileStream.Read(array2, 0, 24);
+ array3[m] = new(array2);
+
+ if (m == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
+ {
+ break;
+ }
+ }
+ for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
+ {
+ fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + array3[n].Name_ptr;
+ int num4;
+ while ((num4 = fileStream.ReadByte()) != 0 && num4 != 0)
+ {
+ chars.Add((char)num4);
+ }
+ array3[n].Name = new(chars.ToArray());
+ chars.Clear();
+
+ if (array3[n].Name.EndsWith(".cnmt.xml"))
+ {
+ byte[] array4 = new byte[array3[n].Size];
+ fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
+ fileStream.Read(array4, 0, (int)array3[n].Size);
+
+ XDocument xml = XDocument.Parse(Encoding.UTF8.GetString(array4));
+ TB_TID.Text = xml.Element("ContentMeta").Element("Id").Value.Remove(1, 2).ToUpper(); //id
+ pversion = xml.Element("ContentMeta").Element("Version").Value; //version
+ contentType = xml.Element("ContentMeta").Element("Type").Value; //content
+ var test = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
+
+ if (contentType == "Patch")
+ {
+ patchflag = 1;
+ if (Convert.ToInt32(pversion) > patchnum)
+ {
+ patchnum = Convert.ToInt32(pversion);
+ xmlVersion = $"v{xml.Element("ContentMeta").Element("Version").Value}";
+ int number = Convert.ToInt32(pversion);
+ patchver = $"v{Convert.ToString((double)number / 65536)}";
+ }
+
+ updtitle[updnum] = $"[{TB_TID.Text}][v{pversion}]";
+ updnum++;
+ }
+ else if (contentType == "Application")
+ {
+ baseflag = 1;
+ if (patchflag != 1)
+ {
+ xmlVersion = $"v{xml.Element("ContentMeta").Element("Version").Value}";
+ }
+
+ basetitle[basenum] = $"[{TB_TID.Text}][v{pversion}]";
+ basenum++;
+ }
+ else
+ {
+ if (baseflag == 0 && patchflag == 0)
+ {
+ xmlVersion = $"v{xml.Element("ContentMeta").Element("Version").Value}";
+ }
+
+ dlctitle[dlcnum] = $"[{TB_TID.Text}][v{pversion}]";
+ dlcnum++;
+ }
+
+ if (contentType != "AddOnContent")
+ {
+ foreach (XElement xe in xml.Descendants("Content"))
+ {
+ if (xe.Element("Type").Value != "Control")
+ {
+ continue;
+ }
+
+ ncaTarget = $"{xe.Element("Id").Value}.nca";
+ break;
+ }
+ }
+ else //This is a DLC
+ {
+ foreach (XElement xe in xml.Descendants("Content"))
+ {
+ if (xe.Element("Type").Value != "Meta")
+ {
+ continue;
+ }
+
+ ncaTarget = $"{xe.Element("Id").Value}.cnmt.nca";
+ break;
+ }
+ }
+ }
+
+ if (n == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
+ {
+ break;
+ }
+ }
+
+ if (string.IsNullOrEmpty(ncaTarget))
+ {
+ //Missing content metadata xml. Read from content metadata nca instead
+ for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
+ {
+ if (array3[n].Name.EndsWith(".cnmt.nca"))
+ {
+ try
+ {
+ File.Delete("meta");
+ Directory.Delete("data", true);
+ }
+ catch { }
+
+ using (FileStream fileStream2 = File.OpenWrite("meta"))
+ {
+ fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
+ byte[] buffer = new byte[8192];
+ long num = array3[n].Size;
+ int num4;
+ while ((num4 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
+ {
+ fileStream2.Write(buffer, 0, num4);
+ num -= num4;
+ }
+ fileStream2.Close();
+ }
+
+ process = new()
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ FileName = Path.Join("tools", "hactool.exe"),
+ Arguments = "-k keys.txt --section0dir=data meta",
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ CreateNoWindow = true
+ }
+ };
+ process.Start();
+
+ string masterkey = "";
+ while (!process.StandardOutput.EndOfStream)
+ {
+ string output = process.StandardOutput.ReadLine();
+ if (output.StartsWith("Master Key Revision"))
+ {
+ masterkey = Regex.Replace(output, @"\s+", " ");
+ }
+ }
+ process.WaitForExit();
+
+ if (!Directory.Exists("data"))
+ {
+ new CenterWinDialog(this);
+ MessageBox.Show($"{masterkey} is missing!");
+ }
+ else
+ {
+ try
+ {
+ string[] cnmt = Directory.GetFiles("data", "*.cnmt");
+ if (cnmt.Length == 0)
+ {
+ return;
+ }
+ using FileStream fileStream3 = File.OpenRead(cnmt[0]);
+ byte[] buffer = new byte[32];
+ byte[] buffer2 = new byte[56];
+ CNMT.CNMT_Header[] array7 = new CNMT.CNMT_Header[1];
+
+ fileStream3.Read(buffer, 0, 32);
+ array7[0] = new CNMT.CNMT_Header(buffer);
+
+ byte[] TitleID = BitConverter.GetBytes(array7[0].TitleID);
+ Array.Reverse(TitleID);
+ TB_TID.Text = BitConverter.ToString(TitleID).Replace("-", "");
+
+ if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.REGULAR_APPLICATION)
+ {
+ contentType = "Application";
+ baseflag = 1;
+ if (patchflag != 1)
+ {
+ xmlVersion = $"v{array7[0].TitleVersion}";
+ }
+
+ basetitle[basenum] = $"[{TB_TID.Text}][v{array7[0].TitleVersion}]";
+ basenum++;
+ }
+ else if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.UPDATE_TITLE)
+ {
+ contentType = "Patch";
+
+ patchflag = 1;
+ if (array7[0].TitleVersion > patchnum)
+ {
+ patchnum = array7[0].TitleVersion;
+ xmlVersion = $"v{array7[0].TitleVersion}";
+ int number = Convert.ToInt32(array7[0].TitleVersion);
+ patchver = $"v{Convert.ToString((double)number / 65536)}";
+ }
+
+ updtitle[updnum] = $"[{TB_TID.Text}][v{array7[0].TitleVersion}]";
+ updnum++;
+ }
+ else if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.ADD_ON_CONTENT)
+ {
+ if (baseflag == 0 && patchflag == 0)
+ {
+ xmlVersion = $"v{array7[0].TitleVersion}";
+ }
+
+ contentType = "AddOnContent";
+ dlctitle[dlcnum] = $"[{TB_TID.Text}][v{array7[0].TitleVersion}]";
+ dlcnum++;
+ }
+
+ fileStream3.Position = array7[0].Offset + 32;
+ CNMT.CNMT_Entry[] array9 = new CNMT.CNMT_Entry[array7[0].ContentCount];
+ for (int k = 0; k < array7[0].ContentCount; k++)
+ {
+ fileStream3.Read(buffer2, 0, 56);
+ array9[k] = new CNMT.CNMT_Entry(buffer2);
+ if (array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.CONTROL || array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.DATA)
+ {
+ ncaTarget = $"{BitConverter.ToString(array9[k].NcaId).ToLower().Replace("-", "")}.nca";
+ break;
+ }
+ }
+
+ fileStream3.Close();
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+ }
+
+ for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
+ {
+ if (array3[n].Name.Equals(ncaTarget))
+ {
+ Directory.CreateDirectory("tmp");
+
+ byte[] array5 = new byte[64 * 1024];
+ fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
+
+ using (Stream output = File.Create(Path.Join("tmp", ncaTarget)))
+ {
+ long Size = array3[n].Size;
+ int result = 0;
+ while ((result = fileStream.Read(array5, 0, (int)Math.Min(array5.Length, Size))) > 0)
+ {
+ output.Write(array5, 0, result);
+ Size -= result;
+ }
+ }
+
+ break;
+ }
+
+ if (n == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
+ {
+ break;
+ }
+ }
+
+ fileStream.Close();
+
+ if (contentType != "AddOnContent")
+ {
+ process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ FileName = Path.Join("tools", "hactool.exe"),
+ Arguments = $"-k keys.txt --romfsdir=tmp tmp/{ncaTarget}",
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }
+ };
+
+ process.Start();
+ process.WaitForExit();
+ process.Close();
+ byte[] flux = new byte[200];
+
try
{
- MkeyL = dictionary[MkeyL].Replace(" ", "");
- return true;
+ byte[] source = File.ReadAllBytes(Path.Join("tmp", "control.nacp"));
+ NACP.NACP_Datas[0] = new NACP.NACP_Data(source.Skip(0x3000).Take(0x1000).ToArray());
+
+ for (int i = 0; i < NACP.NACP_Strings.Length; i++)
+ {
+ NACP.NACP_Strings[i] = new NACP.NACP_String(source.Skip(i * 0x300).Take(0x300).ToArray());
+
+ if (NACP.NACP_Strings[i].Check != 0)
+ {
+ CB_RegionName.Items.Add(Language[i]);
+ string icon_filename = Path.Join("tmp", $"icon_{Language[i].Replace(" ", "")}.dat");
+ if (File.Exists(icon_filename))
+ {
+ using Bitmap original = new(icon_filename);
+ Icons[i] = new Bitmap(original);
+ PB_GameIcon.BackgroundImage = Icons[i];
+ }
+ }
+ }
+
+ string gameVer = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
+ if (xmlVersion.Trim() == "")
+ {
+ TB_GameRev.Text = $"GENERAL:{Environment.NewLine}({gameVer}){Environment.NewLine}";
+ }
+ else
+ {
+ string cache = $"GENERAL:{Environment.NewLine}{gameVer}{((patchflag == 1) ? $" ({patchver})" : "")}{Environment.NewLine}";
+
+ if (basenum != 0)
+ {
+ cache += $"BASE:{Environment.NewLine}";
+ for (int i = 0; i < basenum; i++)
+ {
+ cache += basetitle[i] + Environment.NewLine;
+ }
+ }
+ else
+ {
+ cache += $"BASE:{Environment.NewLine}EMPTY{Environment.NewLine}";
+ }
+ if (updnum != 0)
+ {
+ cache += $"UPD:{Environment.NewLine}";
+ for (int i = 0; i < updnum; i++)
+ {
+ cache += updtitle[i] + Environment.NewLine;
+ }
+ }
+ else
+ {
+ cache += $"UPD:{Environment.NewLine}EMPTY{Environment.NewLine}";
+ }
+ if (dlcnum != 0)
+ {
+ cache += $"DLC:{Environment.NewLine}";
+ for (int i = 0; i < dlcnum; i++)
+ {
+ if (i < dlcnum - 1)
+ {
+ cache += dlctitle[i] + Environment.NewLine;
+ }
+ else
+ {
+ cache += dlctitle[i];
+ }
+ }
+ }
+ else
+ {
+ cache += $"DLC:{Environment.NewLine}EMPTY";
+ }
+ TB_GameRev.Text = cache;
+ label12.Text = $"{basenum} BASE, {updnum} UPD, {dlcnum} DLC";
+ }
+
+ TB_ProdCode.Text = NACP.NACP_Datas[0].GameProd.Replace("\0", "");
+ if (TB_ProdCode.Text == "")
+ {
+ TB_ProdCode.Text = "No Prod. ID";
+ }
+
+ for (int z = 0; z < NACP.NACP_Strings.Length; z++)
+ {
+ if (NACP.NACP_Strings[z].GameName.Replace("\0", "") != "")
+ {
+ TB_Name.Text = NACP.NACP_Strings[z].GameName.Replace("\0", "");
+ break;
+ }
+ }
+ for (int z = 0; z < NACP.NACP_Strings.Length; z++)
+ {
+ if (NACP.NACP_Strings[z].GameAuthor.Replace("\0", "") != "")
+ {
+ TB_Dev.Text = NACP.NACP_Strings[z].GameAuthor.Replace("\0", "");
+ break;
+ }
+ }
+ }
+ catch { }
+
+ }
+ else
+ {
+ if (xmlVersion.Trim() == "")
+ {
+ TB_GameRev.Text = $"GENERAL:{Environment.NewLine}{Environment.NewLine}";
+ }
+ else
+ {
+ string gameVer = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
+ string cache = $"GENERAL:{Environment.NewLine}{gameVer}{((patchflag == 1) ? $" ({patchver})" : "")}{Environment.NewLine}";
+
+ if (basenum != 0)
+ {
+ cache += $"BASE:{Environment.NewLine}";
+ for (int i = 0; i < basenum; i++)
+ {
+ cache += basetitle[i] + Environment.NewLine;
+ }
+ }
+ else
+ {
+ cache += $"BASE:{Environment.NewLine} EMPTY {Environment.NewLine}";
+ }
+ if (updnum != 0)
+ {
+ cache += $"UPD:{Environment.NewLine}";
+ for (int i = 0; i < updnum; i++)
+ {
+ cache += updtitle[i] + Environment.NewLine;
+ }
+ }
+ else
+ {
+ cache += $"UPD:{Environment.NewLine} EMPTY {Environment.NewLine}";
+ }
+ if (dlcnum != 0)
+ {
+ cache += $"DLC:{Environment.NewLine}";
+ for (int i = 0; i < dlcnum; i++)
+ {
+ if (i < dlcnum - 1)
+ {
+ cache += dlctitle[i] + Environment.NewLine;
+ }
+ else
+ {
+ cache += dlctitle[i];
+ }
+ }
+ }
+ else
+ {
+ cache += $"DLC:{Environment.NewLine}EMPTY";
+ }
+ TB_GameRev.Text = cache;
+ label12.Text = $"{basenum} BASE, {updnum} UPD, {dlcnum} DLC";
+ }
+ TB_ProdCode.Text = "No Prod. ID";
+ }
+
+ // Lets get SDK Version, Distribution Type and Masterkey revision
+ // This is far from the best aproach, but it's what we have for now
+ process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ FileName = Path.Join("tools", "hactool.exe"),
+ Arguments = $"-k keys.txt tmp/{ncaTarget}",
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }
+ };
+ process.Start();
+ StreamReader sr = process.StandardOutput;
+
+ while (sr.Peek() >= 0)
+ {
+ string str;
+ string[] strArray;
+ str = sr.ReadLine();
+ strArray = str.Split(':');
+ if (strArray[0] == "SDK Version")
+ {
+ TB_SDKVer.Text = strArray[1].Trim();
+ }
+ else if (strArray[0] == "Master Key Revision")
+ {
+ string MasterKey = strArray[1].Trim();
+ int keyblob;
+
+ MasterKey = MasterKey.Split(new char[2] { 'x', ' ' })[1];
+ keyblob = Convert.ToInt32(MasterKey, 16);
+ MasterKey = Util.GetMkey((byte)(keyblob + 1));
+ TB_MKeyRev.Text = MasterKey;
+ break;
+ }
+ }
+ process.WaitForExit();
+ process.Close();
+ }
+ catch { }
+
+ try
+ {
+ File.Delete("meta");
+ Directory.Delete("data", true);
+ }
+ catch
+ {
+ }
+
+ try
+ {
+ Directory.Delete("tmp", true);
+ }
+ catch
+ {
+ }
+
+ TB_Capacity.Text = "eShop";
+
+ if (TB_Name.Text.Trim() != "")
+ {
+ CB_RegionName.SelectedIndex = 0;
+ }
+ }
+
+ private void LoadGameInfos()
+ {
+ CB_RegionName.Items.Clear();
+ CB_RegionName.Enabled = true;
+ TB_Name.Text = "";
+ TB_Dev.Text = "";
+ PB_GameIcon.BackgroundImage = null;
+
+ int basenum = 0;
+ int updnum = 0;
+ int dlcnum = 0;
+ int patchflag = 0;
+ int patchnum = 0;
+ string patchver = "";
+ int baseflag = 0;
+ string[] basetitle = new string[5];
+ string[] updtitle = new string[10];
+ string[] dlctitle = new string[300];
+ string xmlVersion = "";
+ string saveTID = "";
+
+ Array.Clear(Icons, 0, Icons.Length);
+ if (getMKey())
+ {
+ using FileStream fileStream = File.OpenRead(TB_File.Text);
+ List ncaTarget = new();
+ string GameRevision = "";
+
+ for (int si = 0; si < SecureSize.Length; si++)
+ {
+ if (SecureSize[si] > 0x4E20000)
+ {
+ continue;
+ }
+
+ if (!SecureName[si].EndsWith(".cnmt.nca"))
+ {
+ continue;
+ }
+
+ try
+ {
+ File.Delete("meta");
+ Directory.Delete("data", true);
}
catch
{
- return false;
+ }
+
+ using (FileStream fileStream2 = File.OpenWrite("meta"))
+ {
+ fileStream.Position = SecureOffset[si];
+ byte[] fsBuffer = new byte[8192];
+ long num = SecureSize[si];
+ int num4;
+ while ((num4 = fileStream.Read(fsBuffer, 0, 8192)) > 0 && num > 0)
+ {
+ fileStream2.Write(fsBuffer, 0, num4);
+ num -= num4;
+ }
+ fileStream2.Close();
+ }
+
+ Process process1 = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ FileName = Path.Join("tools", "hactool.exe"),
+ Arguments = "-k keys.txt --section0dir=data meta",
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }
+ };
+ process1.Start();
+ process1.WaitForExit();
+
+ string[] cnmt = Directory.GetFiles("data", "*.cnmt");
+ if (cnmt.Length == 0)
+ {
+ continue;
+ }
+
+ using FileStream fileStream3 = File.OpenRead(cnmt[0]);
+ byte[] buffer = new byte[32];
+ byte[] buffer2 = new byte[56];
+ CNMT.CNMT_Header[] array7 = new CNMT.CNMT_Header[1];
+
+ fileStream3.Read(buffer, 0, 32);
+ array7[0] = new CNMT.CNMT_Header(buffer);
+
+ byte[] TitleID = BitConverter.GetBytes(array7[0].TitleID);
+ Array.Reverse(TitleID);
+ saveTID = BitConverter.ToString(TitleID).Replace("-", "");
+
+ if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.REGULAR_APPLICATION)
+ {
+ baseflag = 1;
+ if (patchflag != 1)
+ {
+ xmlVersion = $"v{array7[0].TitleVersion}";
+ }
+
+ basetitle[basenum] = $"[{saveTID}][v{array7[0].TitleVersion}]";
+ basenum++;
+ }
+ else if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.UPDATE_TITLE)
+ {
+ patchflag = 1;
+ if (array7[0].TitleVersion > patchnum)
+ {
+ patchnum = array7[0].TitleVersion;
+ xmlVersion = $"v{array7[0].TitleVersion}";
+ int number = Convert.ToInt32(array7[0].TitleVersion);
+ patchver = $"v{Convert.ToString((double)number / 65536)}";
+ }
+
+ updtitle[updnum] = $"[{saveTID}][v{array7[0].TitleVersion}]";
+ updnum++;
+ }
+ else if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.ADD_ON_CONTENT)
+ {
+ if (patchflag == 0 && baseflag == 0)
+ {
+ xmlVersion = $"v{array7[0].TitleVersion}";
+ }
+
+ dlctitle[dlcnum] = $"[{saveTID}][v{array7[0].TitleVersion}]";
+ dlcnum++;
+ }
+
+ fileStream3.Position = array7[0].Offset + 32;
+ CNMT.CNMT_Entry[] array9 = new CNMT.CNMT_Entry[array7[0].ContentCount];
+ for (int k = 0; k < array7[0].ContentCount; k++)
+ {
+ fileStream3.Read(buffer2, 0, 56);
+ array9[k] = new CNMT.CNMT_Entry(buffer2);
+ if (array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.CONTROL || array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.DATA)
+ {
+ ncaTarget.Add($"{BitConverter.ToString(array9[k].NcaId).ToLower().Replace("-", "")}.nca");
+ break;
+ }
+ }
+ fileStream3.Close();
+
+ }
+
+ for (int si = 0; si < SecureSize.Length; si++)
+ {
+ if (SecureSize[si] > 0x4E20000)
+ {
+ continue;
+ }
+
+ if (!ncaTarget.Contains(SecureName[si]))
+ {
+ continue;
+ }
+
+ try
+ {
+ File.Delete("meta");
+ Directory.Delete("data", true);
+ }
+ catch
+ {
+ }
+
+ using (FileStream fileStream2 = File.OpenWrite("meta"))
+ {
+ fileStream.Position = SecureOffset[si];
+ byte[] buffer = new byte[8192];
+ long num = SecureSize[si];
+ int num2;
+ while ((num2 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
+ {
+ fileStream2.Write(buffer, 0, num2);
+ num -= num2;
+ }
+ fileStream2.Close();
+ }
+
+
+ Process process = new();
+ process.StartInfo = new ProcessStartInfo
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ FileName = Path.Join("tools", "hactool.exe"),
+ Arguments = "-k keys.txt --romfsdir=data meta",
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+ process.Start();
+ process.WaitForExit();
+
+ if (!File.Exists(Path.Join("data", "control.nacp")))
+ {
+ continue;
+ }
+
+ byte[] source = File.ReadAllBytes(Path.Join("data", "control.nacp"));
+ NACP.NACP_Datas[0] = new NACP.NACP_Data(source.Skip(0x3000).Take(0x1000).ToArray());
+
+ string GameVer = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
+ Version version1, version2;
+ if (!Version.TryParse(Regex.Replace(GameRevision, @"[^\d.].*$", ""), out version1))
+ {
+ version1 = new Version();
+ }
+ if (!Version.TryParse(Regex.Replace(GameVer, @"[^\d.].*$", ""), out version2))
+ {
+ version2 = new Version();
+ }
+ if (version2.CompareTo(version1) > 0)
+ {
+ GameRevision = GameVer;
+
+ for (int i = 0; i < NACP.NACP_Strings.Length; i++)
+ {
+ NACP.NACP_Strings[i] = new NACP.NACP_String(source.Skip(i * 0x300).Take(0x300).ToArray());
+ if (NACP.NACP_Strings[i].Check == 0 || CB_RegionName.Items.Contains(Language[i]))
+ {
+ continue;
+ }
+
+ CB_RegionName.Items.Add(Language[i]);
+ string icon_filename = Path.Join("data", $"icon_{Language[i].Replace(" ", "")}.dat");
+ if (File.Exists(icon_filename))
+ {
+ using Bitmap original = new(icon_filename);
+ Icons[i] = new Bitmap(original);
+ PB_GameIcon.BackgroundImage = Icons[i];
+ }
+ }
+ TB_ProdCode.Text = NACP.NACP_Datas[0].GameProd;
+ if (TB_ProdCode.Text == "")
+ {
+ TB_ProdCode.Text = "No Prod. ID";
+ }
+ try
+ {
+ File.Delete("meta");
+ Directory.Delete("data", true);
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ string gameVer = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
+ string cache = $"GENERAL:{Environment.NewLine}{gameVer}{((patchflag == 1) ? $" ({patchver})" : "")}{Environment.NewLine}";
+
+ if (basenum != 0)
+ {
+ cache += $"BASE:{Environment.NewLine}";
+ for (int i = 0; i < basenum; i++)
+ {
+ cache += basetitle[i] + System.Environment.NewLine;
+ }
+ }
+ else
+ {
+ cache += $"BASE:{Environment.NewLine}EMPTY{Environment.NewLine}";
+ }
+ if (updnum != 0)
+ {
+ cache += $"UPD:{Environment.NewLine}";
+ for (int i = 0; i < updnum; i++)
+ {
+ cache += updtitle[i] + Environment.NewLine;
+ }
+ }
+ else
+ {
+ cache += $"UPD:{Environment.NewLine}EMPTY{Environment.NewLine}";
+ }
+ if (dlcnum != 0)
+ {
+ cache += $"DLC:{Environment.NewLine}";
+ for (int i = 0; i < dlcnum; i++)
+ {
+ if (i < dlcnum - 1)
+ {
+ cache += dlctitle[i] + Environment.NewLine;
+ }
+ else
+ {
+ cache += dlctitle[i];
+ }
+ }
+ }
+ else
+ {
+ cache += $"DLC:{Environment.NewLine}EMPTY";
+ }
+ TB_GameRev.Text = cache;
+ label12.Text = $"{basenum} BASE, {updnum} UPD, {dlcnum} DLC";
+
+ CB_RegionName.SelectedIndex = 0;
+
+ fileStream.Close();
+ }
+ else
+ {
+ TB_Dev.Text = $"{Mkey} not found";
+ TB_Name.Text = $"{Mkey} not found";
+ }
+ }
+
+ private void LoadNCAData()
+ {
+ NCA.NCA_Headers[0] = new NCA.NCA_Header(DecryptNCAHeader(gameNcaOffset));
+ TB_TID.Text = $"0{NCA.NCA_Headers[0].TitleID.ToString("X")}";
+ TB_SDKVer.Text = $"{NCA.NCA_Headers[0].SDKVersion4}.{NCA.NCA_Headers[0].SDKVersion3}.{NCA.NCA_Headers[0].SDKVersion2}.{NCA.NCA_Headers[0].SDKVersion1}";
+ TB_MKeyRev.Text = Util.GetMkey(NCA.NCA_Headers[0].MasterKeyRev);
+ }
+
+ //https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa
+ public static string ByteArrayToString(byte[] ba)
+ {
+ StringBuilder hex = new(ba.Length * 2 + 2);
+ hex.Append("0x");
+ foreach (byte b in ba)
+ {
+ hex.AppendFormat("{0:x2}", b);
+ }
+
+ return hex.ToString();
+ }
+
+ public static string SHA256Bytes(byte[] ba)
+ {
+ SHA256 mySHA256 = SHA256.Create();
+ byte[] hashValue;
+ hashValue = mySHA256.ComputeHash(ba);
+ return ByteArrayToString(hashValue);
+ }
+
+ public bool isTrimmed() => TB_ROMExactSize.Text == TB_ExactUsedSpace.Text;
+
+ private void LoadPartitions()
+ {
+ string actualHash;
+ byte[] hashBuffer;
+ long offset;
+
+ TV_Partitions.Nodes.Clear();
+ TV_Parti = new TreeViewFileSystem(TV_Partitions);
+ rootNode = new BetterTreeNode("root")
+ {
+ Offset = -1L,
+ Size = -1L
+ };
+ TV_Partitions.Nodes.Add(rootNode);
+ bool LogoPartition = false;
+ FileStream fileStream = new(TB_File.Text, FileMode.Open, FileAccess.Read);
+ HFS0.HSF0_Entry[] array = new HFS0.HSF0_Entry[HFS0.HFS0_Headers[0].FileCount];
+ fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition + 16 + 64 * HFS0.HFS0_Headers[0].FileCount;
+ long num = XCI.XCI_Headers[0].HFS0OffsetPartition + XCI.XCI_Headers[0].HFS0SizeParition;
+ byte[] array2 = new byte[64];
+ byte[] array3 = new byte[16];
+ byte[] array4 = new byte[24];
+ for (int i = 0; i < HFS0.HFS0_Headers[0].FileCount; i++)
+ {
+ fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition + 16 + 64 * i;
+ fileStream.Read(array2, 0, 64);
+ array[i] = new HFS0.HSF0_Entry(array2);
+ fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition + 16 + 64 * HFS0.HFS0_Headers[0].FileCount + array[i].Name_ptr;
+ int num2;
+ while ((num2 = fileStream.ReadByte()) != 0 && num2 != 0)
+ {
+ chars.Add((char)num2);
+ }
+ array[i].Name = new string(chars.ToArray());
+ chars.Clear();
+ offset = num + array[i].Offset;
+ hashBuffer = new byte[array[i].HashedRegionSize];
+ fileStream.Position = offset;
+ fileStream.Read(hashBuffer, 0, array[i].HashedRegionSize);
+ actualHash = SHA256Bytes(hashBuffer);
+
+ TV_Parti.AddFile($"{array[i].Name}.hfs0", rootNode, offset, array[i].Size, array[i].HashedRegionSize, ByteArrayToString(array[i].Hash), actualHash);
+ BetterTreeNode betterTreeNode = TV_Parti.AddDir(array[i].Name, rootNode);
+ HFS0.HFS0_Header[] array5 = new HFS0.HFS0_Header[1];
+ fileStream.Position = array[i].Offset + num;
+ fileStream.Read(array3, 0, 16);
+ array5[0] = new HFS0.HFS0_Header(array3);
+ if (array[i].Name == "secure")
+ {
+ SecureSize = new long[array5[0].FileCount];
+ SecureOffset = new long[array5[0].FileCount];
+ SecureName = new string[array5[0].FileCount];
+ }
+ if (array[i].Name == "normal")
+ {
+ NormalSize = new long[array5[0].FileCount];
+ NormalOffset = new long[array5[0].FileCount];
+ }
+ if (array[i].Name == "logo")
+ {
+ if (array5[0].FileCount > 0)
+ {
+ LogoPartition = true;
+ }
+ }
+ HFS0.HSF0_Entry[] array6 = new HFS0.HSF0_Entry[array5[0].FileCount];
+ for (int j = 0; j < array5[0].FileCount; j++)
+ {
+ fileStream.Position = array[i].Offset + num + 16 + 64 * j;
+ fileStream.Read(array2, 0, 64);
+ array6[j] = new HFS0.HSF0_Entry(array2);
+ fileStream.Position = array[i].Offset + num + 16 + 64 * array5[0].FileCount + array6[j].Name_ptr;
+ while ((num2 = fileStream.ReadByte()) != 0 && num2 != 0)
+ {
+ chars.Add((char)num2);
+ }
+ array6[j].Name = new string(chars.ToArray());
+ chars.Clear();
+ if (array[i].Name == "secure")
+ {
+ SecureSize[j] = array6[j].Size;
+ SecureOffset[j] = array[i].Offset + array6[j].Offset + num + 16 + array5[0].StringTableSize + array5[0].FileCount * 64;
+ SecureName[j] = array6[j].Name;
+ }
+ if (array[i].Name == "normal")
+ {
+ NormalSize[j] = array6[j].Size;
+ NormalOffset[j] = array[i].Offset + array6[j].Offset + num + 16 + array5[0].StringTableSize + array5[0].FileCount * 64;
+ }
+ offset = array[i].Offset + array6[j].Offset + num + 16 + array5[0].StringTableSize + array5[0].FileCount * 64;
+ hashBuffer = new byte[array6[j].HashedRegionSize];
+ fileStream.Position = offset;
+ fileStream.Read(hashBuffer, 0, array6[j].HashedRegionSize);
+ actualHash = SHA256Bytes(hashBuffer);
+
+ TV_Parti.AddFile(array6[j].Name, betterTreeNode, offset, array6[j].Size, array6[j].HashedRegionSize, ByteArrayToString(array6[j].Hash), actualHash);
+ TreeNode[] array7 = TV_Partitions.Nodes.Find(betterTreeNode.Text, true);
+ if (array7.Length != 0)
+ {
+ TV_Parti.AddFile(array6[j].Name, (BetterTreeNode)array7[0], 0L, 0L);
}
}
}
-
- private void ProcessFile()
+ long num3 = -9223372036854775808L;
+ for (int k = 0; k < SecureSize.Length; k++)
+ {
+ if (SecureSize[k] > num3)
+ {
+ gameNcaSize = SecureSize[k];
+ gameNcaOffset = SecureOffset[k];
+ num3 = SecureSize[k];
+ }
+ }
+ PFS0Offset = gameNcaOffset + 32768;
+ fileStream.Position = PFS0Offset;
+ fileStream.Read(array3, 0, 16);
+ PFS0.PFS0_Headers[0] = new(array3);
+ if (PFS0.PFS0_Headers[0].FileCount == 2 || !LogoPartition)
+ {
+ PFS0.PFS0_Entry[] array8;
+ try
+ {
+ array8 = new PFS0.PFS0_Entry[PFS0.PFS0_Headers[0].FileCount];
+ }
+ catch (Exception ex)
+ {
+ array8 = new PFS0.PFS0_Entry[0];
+ Debug.WriteLine($"Partitions Error: {ex.Message}");
+ }
+ for (int m = 0; m < PFS0.PFS0_Headers[0].FileCount; m++)
+ {
+ fileStream.Position = PFS0Offset + 16 + 24 * m;
+ fileStream.Read(array4, 0, 24);
+ array8[m] = new(array4);
+ PFS0Size += array8[m].Size;
+ }
+ TV_Parti.AddFile("boot.psf0", rootNode, PFS0Offset, 16 + 24 * PFS0.PFS0_Headers[0].FileCount + 64 + PFS0Size);
+ BetterTreeNode betterTreeNode2 = TV_Parti.AddDir("boot", rootNode);
+ for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
+ {
+ fileStream.Position = PFS0Offset + 16 + 24 * PFS0.PFS0_Headers[0].FileCount + array8[n].Name_ptr;
+ int num4;
+ while ((num4 = fileStream.ReadByte()) != 0 && num4 != 0)
+ {
+ chars.Add((char)num4);
+ }
+ array8[n].Name = new string(chars.ToArray());
+ chars.Clear();
+ TV_Parti.AddFile(array8[n].Name, betterTreeNode2, PFS0Offset + array8[n].Offset + 16 + PFS0.PFS0_Headers[0].StringTableSize + PFS0.PFS0_Headers[0].FileCount * 24, array8[n].Size);
+ TreeNode[] array9 = TV_Partitions.Nodes.Find(betterTreeNode2.Text, true);
+ if (array9.Length != 0)
+ {
+ TV_Parti.AddFile(array8[n].Name, (BetterTreeNode)array9[0], 0L, 0L);
+ }
+ }
+ }
+ fileStream.Close();
+ }
+
+
+ private void LoadNSPPartitions()
+ {
+ long offset;
+
+ TV_Partitions.Nodes.Clear();
+ TV_Parti = new TreeViewFileSystem(TV_Partitions);
+ rootNode = new BetterTreeNode("root")
+ {
+ Offset = -1L,
+ Size = -1L
+ };
+ TV_Partitions.Nodes.Add(rootNode);
+
+
+ // Maximum number of files in NSP to read in
+ const int MAXFILES = 250;
+
+ FileStream fileStream = File.OpenRead(TB_File.Text);
+ List chars = new();
+ byte[] array = new byte[16];
+ byte[] array2 = new byte[24];
+ fileStream.Read(array, 0, 16);
+ PFS0.PFS0_Headers[0] = new(array);
+ if (!PFS0.PFS0_Headers[0].Magic.Contains("PFS0"))
+ {
+ return;
+ }
+ PFS0.PFS0_Entry[] array3;
+ array3 = new PFS0.PFS0_Entry[Math.Max(PFS0.PFS0_Headers[0].FileCount, MAXFILES)]; //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
+ for (int m = 0; m < PFS0.PFS0_Headers[0].FileCount; m++)
+ {
+ fileStream.Position = 16 + 24 * m;
+ fileStream.Read(array2, 0, 24);
+ array3[m] = new(array2);
+
+ if (m == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
+ {
+ break;
+ }
+ }
+ for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
+ {
+ fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + array3[n].Name_ptr;
+ int num4;
+ while ((num4 = fileStream.ReadByte()) != 0 && num4 != 0)
+ {
+ chars.Add((char)num4);
+ }
+ array3[n].Name = new(chars.ToArray());
+ chars.Clear();
+ offset = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
+ fileStream.Position = offset;
+
+ TV_Parti.AddFile(array3[n].Name, rootNode, offset, array3[n].Size);
+ }
+
+ fileStream.Close();
+ }
+
+
+ private void TV_Partitions_AfterSelect(object sender, TreeViewEventArgs e)
+ {
+ BetterTreeNode betterTreeNode = (BetterTreeNode)TV_Partitions.SelectedNode;
+ if (betterTreeNode.Offset == -1)
{
- using CenterWinDialog center = new CenterWinDialog(this);
- // Code needs refactoring
LB_SelectedData.Text = "";
LB_DataOffset.Text = "";
LB_DataSize.Text = "";
@@ -178,1301 +1445,468 @@ namespace XCI_Explorer
LB_ExpectedHash.Text = "";
LB_ActualHash.Text = "";
B_Extract.Enabled = false;
-
- try
- {
- if (CheckNSP())
- {
- B_TrimXCI.Enabled = false;
- B_ExportCert.Enabled = false;
- B_ImportCert.Enabled = false;
- B_ViewCert.Enabled = false;
- B_ClearCert.Enabled = false;
-
- LoadNSP();
- }
- else if (CheckXCI())
- {
- B_TrimXCI.Enabled = true;
- B_ExportCert.Enabled = true;
- B_ImportCert.Enabled = true;
- B_ViewCert.Enabled = true;
- B_ClearCert.Enabled = true;
-
- LoadXCI();
- }
- else
- {
- TB_File.Text = null;
- MessageBox.Show("File is corrupt or unsupported.");
- }
- }
- catch (Exception e)
- {
- MessageBox.Show("Error: " + e.ToString() + "\nFile is corrupt or unsupported.");
- }
-
+ return;
}
- private void B_LoadROM_Click(object sender, EventArgs e)
+ selectedOffset = betterTreeNode.Offset;
+ selectedSize = betterTreeNode.Size;
+ string expectedHash = betterTreeNode.ExpectedHash;
+ string actualHash = betterTreeNode.ActualHash;
+ long HashedRegionSize = betterTreeNode.HashedRegionSize;
+
+ LB_DataOffset.Text = $"Offset: 0x{selectedOffset:X}";
+ LB_SelectedData.Text = e.Node.Text;
+ if (backgroundWorker1.IsBusy != true)
{
- 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)
- {
- TB_File.Text = openFileDialog.FileName;
- ProcessFile();
- }
+ B_Extract.Enabled = true;
+ }
+ string[] array = new string[5]
+ {
+ "B",
+ "KB",
+ "MB",
+ "GB",
+ "TB"
+ };
+ double num = selectedSize;
+ int num2 = 0;
+ while (num >= 1024.0 && num2 < array.Length - 1)
+ {
+ num2++;
+ num /= 1024.0;
+ }
+ LB_DataSize.Text = $"Size: 0x{selectedSize.ToString("X")} ({num}{array[num2]})";
+
+ if (HashedRegionSize != 0)
+ {
+ LB_HashedRegionSize.Text = $"HashedRegionSize: 0x{HashedRegionSize:X}";
+ }
+ else
+ {
+ LB_HashedRegionSize.Text = "";
}
- private void LoadXCI()
+ if (!string.IsNullOrEmpty(expectedHash))
{
- string[] array = new string[5]
- {
- "B",
- "KB",
- "MB",
- "GB",
- "TB"
- };
- double num = (double)new FileInfo(TB_File.Text).Length;
- TB_ROMExactSize.Text = "(" + num.ToString() + " bytes)";
- int num2 = 0;
- while (num >= 1024.0 && num2 < array.Length - 1)
- {
- num2++;
- num /= 1024.0;
- }
- TB_ROMSize.Text = $"{num:0.##} {array[num2]}";
- double num3 = UsedSize = (double)(XCI.XCI_Headers[0].CardSize2 * 512 + 512);
- TB_ExactUsedSpace.Text = "(" + num3.ToString() + " bytes)";
- if (isTrimmed())
- B_TrimXCI.Enabled = false;
- num2 = 0;
- while (num3 >= 1024.0 && num2 < array.Length - 1)
- {
- num2++;
- num3 /= 1024.0;
- }
- TB_UsedSpace.Text = $"{num3:0.##} {array[num2]}";
- TB_Capacity.Text = Util.GetCapacity(XCI.XCI_Headers[0].CardSize1);
- LoadPartitions();
- LoadNCAData();
- LoadGameInfos();
+ LB_ExpectedHash.Text = $"Header Hash: {expectedHash[..32]}";
+ }
+ else
+ {
+ LB_ExpectedHash.Text = "";
}
- // Giba's better implementation (more native)
- public void LoadNSP()
+ if (!string.IsNullOrEmpty(actualHash))
{
- CB_RegionName.Items.Clear();
- CB_RegionName.Enabled = true;
- TB_TID.Text = "";
- TB_Capacity.Text = "";
- TB_MKeyRev.Text = "";
- TB_SDKVer.Text = "";
- TB_GameRev.Text = "";
- TB_ProdCode.Text = "";
- TB_Name.Text = "";
- TB_Dev.Text = "";
- PB_GameIcon.BackgroundImage = null;
- Array.Clear(Icons, 0, Icons.Length);
- TV_Partitions.Nodes.Clear();
- FileInfo fi = new FileInfo(TB_File.Text);
- string contentType = "";
-
- // Maximum number of files in NSP to read in
- const int MAXFILES = 250;
-
- //Get File Size
- string[] array_fs = new string[5] { "B", "KB", "MB", "GB", "TB" };
- double num_fs = (double)fi.Length;
- int num2_fs = 0;
- TB_ROMExactSize.Text = "(" + num_fs.ToString() + " bytes)";
- TB_ExactUsedSpace.Text = TB_ROMExactSize.Text;
-
- while (num_fs >= 1024.0 && num2_fs < array_fs.Length - 1)
+ LB_ActualHash.Text = $"Actual Hash: {actualHash[..32]}";
+ if (actualHash == expectedHash)
{
- num2_fs++;
- num_fs /= 1024.0;
- }
- TB_ROMSize.Text = $"{num_fs:0.##} {array_fs[num2_fs]}";
- TB_UsedSpace.Text = TB_ROMSize.Text;
-
- Process process = new Process();
- try
- {
- FileStream fileStream = File.OpenRead(TB_File.Text);
- string ncaTarget = "";
- string xmlVersion = "";
-
- List chars = new List();
- byte[] array = new byte[16];
- byte[] array2 = new byte[24];
- fileStream.Read(array, 0, 16);
- PFS0.PFS0_Headers[0] = new PFS0.PFS0_Header(array);
- if (!PFS0.PFS0_Headers[0].Magic.Contains("PFS0"))
- {
- return;
- }
- PFS0.PFS0_Entry[] array3;
- array3 = new PFS0.PFS0_Entry[Math.Max(PFS0.PFS0_Headers[0].FileCount, MAXFILES)]; //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
-
- for (int m = 0; m < PFS0.PFS0_Headers[0].FileCount; m++)
- {
- fileStream.Position = 16 + 24 * m;
- fileStream.Read(array2, 0, 24);
- array3[m] = new PFS0.PFS0_Entry(array2);
-
- if (m == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
- {
- break;
- }
- }
- for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
- {
- fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + array3[n].Name_ptr;
- int num4;
- while ((num4 = fileStream.ReadByte()) != 0 && num4 != 0)
- {
- chars.Add((char)num4);
- }
- array3[n].Name = new string(chars.ToArray());
- chars.Clear();
-
- // Console.WriteLine("FC: " + PFS0.PFS0_Headers[0].FileCount.ToString() + " Name: " + array3[n].Name);
-
- if (array3[n].Name.EndsWith(".cnmt.xml"))
- {
- byte[] array4 = new byte[array3[n].Size];
- fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
- fileStream.Read(array4, 0, (int)array3[n].Size);
-
- XDocument xml = XDocument.Parse(Encoding.UTF8.GetString(array4));
- TB_TID.Text = xml.Element("ContentMeta").Element("Id").Value.Remove(1, 2).ToUpper();
- contentType = xml.Element("ContentMeta").Element("Type").Value;
- if (contentType == "Patch")
- xmlVersion = "v" + xml.Element("ContentMeta").Element("Version").Value;
-
- /*string titleIDBaseGame = TB_TID.Text;
- if (contentType != "Application") {
- string titleIdBase = TB_TID.Text.Substring(0, 13);
- if (contentType == "Patch") //UPDATE
- {
- titleIDBaseGame = titleIdBase + "000";
- }
- else //DLC
- {
- long tmp = long.Parse(titleIdBase, System.Globalization.NumberStyles.HexNumber) - 1;
- titleIDBaseGame = string.Format("0{0:X8}", tmp) + "000";
- }
- }*/
- //data.TitleIDBaseGame = titleIDBaseGame;
-
- if (contentType != "AddOnContent")
- {
- foreach (XElement xe in xml.Descendants("Content"))
- {
- if (xe.Element("Type").Value != "Control")
- {
- continue;
- }
-
- ncaTarget = xe.Element("Id").Value + ".nca";
- break;
- }
- }
- else //This is a DLC
- {
- foreach (XElement xe in xml.Descendants("Content"))
- {
- if (xe.Element("Type").Value != "Meta")
- {
- continue;
- }
-
- ncaTarget = xe.Element("Id").Value + ".cnmt.nca";
- break;
- }
- }
- }
-
- if (n == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
- {
- break;
- }
- }
-
- if (String.IsNullOrEmpty(ncaTarget))
- {
- //Missing content metadata xml. Read from content metadata nca instead
- for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
- {
- if (array3[n].Name.EndsWith(".cnmt.nca"))
- {
- try
- {
- File.Delete("meta");
- Directory.Delete("data", true);
- }
- catch { }
-
- using (FileStream fileStream2 = File.OpenWrite("meta"))
- {
- fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
- byte[] buffer = new byte[8192];
- long num = array3[n].Size;
- int num4;
- while ((num4 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
- {
- fileStream2.Write(buffer, 0, num4);
- num -= num4;
- }
- fileStream2.Close();
- }
-
- process = new Process();
- process.StartInfo = new ProcessStartInfo
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe",
- Arguments = "-k keys.txt --section0dir=data meta",
- UseShellExecute = false,
- RedirectStandardOutput = true,
- CreateNoWindow = true
- };
- process.Start();
-
- string masterkey = "";
- while (!process.StandardOutput.EndOfStream)
- {
- string output = process.StandardOutput.ReadLine();
- if (output.StartsWith("Master Key Revision"))
- {
- masterkey = Regex.Replace(output, @"\s+", " ");
- }
- }
- process.WaitForExit();
-
- if (!Directory.Exists("data"))
- {
- MessageBox.Show(masterkey + " is missing!");
- }
- else
- {
- try
- {
- string[] cnmt = Directory.GetFiles("data", "*.cnmt");
- if (cnmt.Length != 0)
- {
- using (FileStream fileStream3 = File.OpenRead(cnmt[0]))
- {
- byte[] buffer = new byte[32];
- byte[] buffer2 = new byte[56];
- CNMT.CNMT_Header[] array7 = new CNMT.CNMT_Header[1];
-
- fileStream3.Read(buffer, 0, 32);
- array7[0] = new CNMT.CNMT_Header(buffer);
-
- byte[] TitleID = BitConverter.GetBytes(array7[0].TitleID);
- Array.Reverse(TitleID);
- TB_TID.Text = BitConverter.ToString(TitleID).Replace("-", "");
- xmlVersion = "v" + array7[0].TitleVersion.ToString();
-
- if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.REGULAR_APPLICATION)
- {
- contentType = "Application";
- }
- else if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.UPDATE_TITLE)
- {
- contentType = "Patch";
- }
- else if (array7[0].Type == (byte)CNMT.CNMT_Header.TitleType.ADD_ON_CONTENT)
- {
- contentType = "AddOnContent";
- }
-
- fileStream3.Position = array7[0].Offset + 32;
- CNMT.CNMT_Entry[] array9 = new CNMT.CNMT_Entry[array7[0].ContentCount];
- for (int k = 0; k < array7[0].ContentCount; k++)
- {
- fileStream3.Read(buffer2, 0, 56);
- array9[k] = new CNMT.CNMT_Entry(buffer2);
- if (array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.CONTROL || array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.DATA)
- {
- ncaTarget = BitConverter.ToString(array9[k].NcaId).ToLower().Replace("-", "") + ".nca";
- break;
- }
- }
-
- fileStream3.Close();
- }
- }
- }
- catch { }
- }
- }
- }
- }
-
- for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
- {
- if (array3[n].Name.Equals(ncaTarget))
- {
- Directory.CreateDirectory("tmp");
-
- byte[] array5 = new byte[64 * 1024];
- fileStream.Position = 16 + 24 * PFS0.PFS0_Headers[0].FileCount + PFS0.PFS0_Headers[0].StringTableSize + array3[n].Offset;
-
- using (Stream output = File.Create($"tmp{Path.DirectorySeparatorChar}" + ncaTarget))
- {
- long Size = array3[n].Size;
- int result = 0;
- while ((result = fileStream.Read(array5, 0, (int)Math.Min(array5.Length, Size))) > 0)
- {
- output.Write(array5, 0, result);
- Size -= result;
- }
- }
-
- break;
- }
-
- if (n == MAXFILES - 1) //Dump of TitleID 01009AA000FAA000 reports more than 10000000 files here, so it breaks the program. Standard is to have only 20 files
- {
- break;
- }
- }
-
- fileStream.Close();
-
- if (contentType != "AddOnContent")
- {
- process = new Process();
- process.StartInfo = new ProcessStartInfo
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe",
- Arguments = "-k keys.txt --romfsdir=tmp tmp/" + ncaTarget,
- UseShellExecute = false,
- CreateNoWindow = true
- };
-
- process.Start();
- process.WaitForExit();
- process.Close();
- byte[] flux = new byte[200];
-
- try
- {
- byte[] source = File.ReadAllBytes($"tmp{Path.DirectorySeparatorChar}control.nacp");
- NACP.NACP_Datas[0] = new NACP.NACP_Data(source.Skip(0x3000).Take(0x1000).ToArray());
-
- for (int i = 0; i < NACP.NACP_Strings.Length; i++)
- {
- NACP.NACP_Strings[i] = new NACP.NACP_String(source.Skip(i * 0x300).Take(0x300).ToArray());
-
- if (NACP.NACP_Strings[i].Check != 0)
- {
- CB_RegionName.Items.Add(Language[i]);
- string icon_filename = $"tmp{Path.DirectorySeparatorChar}icon_" + Language[i].Replace(" ", "") + ".dat";
- if (File.Exists(icon_filename))
- {
- using (Bitmap original = new Bitmap(icon_filename))
- {
- Icons[i] = new Bitmap(original);
- PB_GameIcon.BackgroundImage = Icons[i];
- }
- }
- }
- }
- if (xmlVersion.Trim() == "")
- {
- TB_GameRev.Text = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
- }
- else
- {
- TB_GameRev.Text = xmlVersion + " (" + NACP.NACP_Datas[0].GameVer.Replace("\0", "") + ")";
- }
- TB_ProdCode.Text = NACP.NACP_Datas[0].GameProd.Replace("\0", "");
- if (TB_ProdCode.Text == "")
- {
- TB_ProdCode.Text = "No Prod. ID";
- }
-
- for (int z = 0; z < NACP.NACP_Strings.Length; z++)
- {
- if (NACP.NACP_Strings[z].GameName.Replace("\0", "") != "")
- {
- TB_Name.Text = NACP.NACP_Strings[z].GameName.Replace("\0", "");
- break;
- }
- }
- for (int z = 0; z < NACP.NACP_Strings.Length; z++)
- {
- if (NACP.NACP_Strings[z].GameAuthor.Replace("\0", "") != "")
- {
- TB_Dev.Text = NACP.NACP_Strings[z].GameAuthor.Replace("\0", "");
- break;
- }
- }
- }
- catch { }
-
- /*if (contentType == "Patch") {
- }*/
- }
- else
- {
- TB_GameRev.Text = "";
- TB_ProdCode.Text = "No Prod. ID";
- }
-
- // Lets get SDK Version, Distribution Type and Masterkey revision
- // This is far from the best aproach, but it's what we have for now
- process = new Process();
- process.StartInfo = new ProcessStartInfo
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe",
- Arguments = "-k keys.txt tmp/" + ncaTarget,
- RedirectStandardOutput = true,
- UseShellExecute = false,
- CreateNoWindow = true
- };
- process.Start();
- StreamReader sr = process.StandardOutput;
-
- while (sr.Peek() >= 0)
- {
- string str;
- string[] strArray;
- str = sr.ReadLine();
- strArray = str.Split(':');
- if (strArray[0] == "SDK Version")
- {
- TB_SDKVer.Text = strArray[1].Trim();
- }
- else if (strArray[0] == "Master Key Revision")
- {
- string MasterKey = strArray[1].Trim();
- int keyblob;
-
- MasterKey = MasterKey.Split(new char[2] { 'x', ' ' })[1];
- keyblob = Convert.ToInt32(MasterKey, 16);
- MasterKey = Util.GetMkey((byte)(keyblob + 1));
- TB_MKeyRev.Text = MasterKey;
- break;
- }
- }
- process.WaitForExit();
- process.Close();
- }
- catch { }
-
- try
- {
- File.Delete("meta");
- Directory.Delete("data", true);
- }
- catch { }
-
- try
- {
- Directory.Delete("tmp", true);
- }
- catch { }
-
- TB_Capacity.Text = "eShop";
-
- if (TB_Name.Text.Trim() != "")
- {
- CB_RegionName.SelectedIndex = 0;
- }
- }
-
- private void LoadGameInfos()
- {
- CB_RegionName.Items.Clear();
- CB_RegionName.Enabled = true;
- TB_Name.Text = "";
- TB_Dev.Text = "";
- PB_GameIcon.BackgroundImage = null;
- Array.Clear(Icons, 0, Icons.Length);
- if (getMKey())
- {
- using (FileStream fileStream = File.OpenRead(TB_File.Text))
- {
- List ncaTarget = new List();
- string GameRevision = "";
-
- for (int si = 0; si < SecureSize.Length; si++)
- {
- if (SecureSize[si] > 0x4E20000) continue;
-
- if (SecureName[si].EndsWith(".cnmt.nca"))
- {
- try
- {
- File.Delete("meta");
- Directory.Delete("data", true);
- }
- catch { }
-
- using (FileStream fileStream2 = File.OpenWrite("meta"))
- {
- fileStream.Position = SecureOffset[si];
- byte[] buffer = new byte[8192];
- long num = SecureSize[si];
- int num4;
- while ((num4 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
- {
- fileStream2.Write(buffer, 0, num4);
- num -= num4;
- }
- fileStream2.Close();
- }
-
- Process process = new Process();
- process.StartInfo = new ProcessStartInfo
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe",
- Arguments = "-k keys.txt --section0dir=data meta",
- UseShellExecute = false,
- CreateNoWindow = true
- };
- process.Start();
- process.WaitForExit();
-
- string[] cnmt = Directory.GetFiles("data", "*.cnmt");
- if (cnmt.Length != 0)
- {
- using (FileStream fileStream3 = File.OpenRead(cnmt[0]))
- {
- byte[] buffer = new byte[32];
- byte[] buffer2 = new byte[56];
- CNMT.CNMT_Header[] array7 = new CNMT.CNMT_Header[1];
-
- fileStream3.Read(buffer, 0, 32);
- array7[0] = new CNMT.CNMT_Header(buffer);
-
- fileStream3.Position = array7[0].Offset + 32;
- CNMT.CNMT_Entry[] array9 = new CNMT.CNMT_Entry[array7[0].ContentCount];
- for (int k = 0; k < array7[0].ContentCount; k++)
- {
- fileStream3.Read(buffer2, 0, 56);
- array9[k] = new CNMT.CNMT_Entry(buffer2);
- if (array9[k].Type == (byte)CNMT.CNMT_Entry.ContentType.CONTROL)
- {
- ncaTarget.Add(BitConverter.ToString(array9[k].NcaId).ToLower().Replace("-", "") + ".nca");
- break;
- }
- }
-
- fileStream3.Close();
- }
- }
- }
- }
-
- for (int si = 0; si < SecureSize.Length; si++)
- {
- if (SecureSize[si] > 0x4E20000) continue;
-
- if (ncaTarget.Contains(SecureName[si]))
- {
- try
- {
- File.Delete("meta");
- Directory.Delete("data", true);
- }
- catch { }
-
- using (FileStream fileStream2 = File.OpenWrite("meta"))
- {
- fileStream.Position = SecureOffset[si];
- byte[] buffer = new byte[8192];
- long num = SecureSize[si];
- int num2;
- while ((num2 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
- {
- fileStream2.Write(buffer, 0, num2);
- num -= num2;
- }
- fileStream2.Close();
- }
-
- Process process = new Process();
- process.StartInfo = new ProcessStartInfo
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- FileName = $"tools{Path.DirectorySeparatorChar}hactool.exe",
- Arguments = "-k keys.txt --romfsdir=data meta",
- UseShellExecute = false,
- CreateNoWindow = true
- };
- process.Start();
- process.WaitForExit();
-
- if (File.Exists($"data{Path.DirectorySeparatorChar}control.nacp"))
- {
- byte[] source = File.ReadAllBytes($"data{Path.DirectorySeparatorChar}control.nacp");
- NACP.NACP_Datas[0] = new NACP.NACP_Data(source.Skip(0x3000).Take(0x1000).ToArray());
-
- string GameVer = NACP.NACP_Datas[0].GameVer.Replace("\0", "");
- Version version1, version2;
- if (!Version.TryParse(Regex.Replace(GameRevision, @"[^\d.].*$", ""), out version1))
- {
- version1 = new Version();
- }
- if (!Version.TryParse(Regex.Replace(GameVer, @"[^\d.].*$", ""), out version2))
- {
- version2 = new Version();
- }
- if (version2.CompareTo(version1) > 0)
- {
- GameRevision = GameVer;
-
- for (int i = 0; i < NACP.NACP_Strings.Length; i++)
- {
- NACP.NACP_Strings[i] = new NACP.NACP_String(source.Skip(i * 0x300).Take(0x300).ToArray());
- if (NACP.NACP_Strings[i].Check != 0 && !CB_RegionName.Items.Contains(Language[i]))
- {
- CB_RegionName.Items.Add(Language[i]);
- string icon_filename = $"data{Path.DirectorySeparatorChar}icon_" + Language[i].Replace(" ", "") + ".dat";
- if (File.Exists(icon_filename))
- {
- using (Bitmap original = new Bitmap(icon_filename))
- {
- Icons[i] = new Bitmap(original);
- PB_GameIcon.BackgroundImage = Icons[i];
- }
- }
- }
- }
- TB_ProdCode.Text = NACP.NACP_Datas[0].GameProd;
- if (TB_ProdCode.Text == "")
- {
- TB_ProdCode.Text = "No Prod. ID";
- }
- try
- {
- File.Delete("meta");
- Directory.Delete("data", true);
- }
- catch { }
- }
- }
- }
- }
-
- TB_GameRev.Text = GameRevision;
- CB_RegionName.SelectedIndex = 0;
-
- fileStream.Close();
- }
+ LB_ActualHash.ForeColor = Color.Green;
}
else
{
- TB_Dev.Text = Mkey + " not found";
- TB_Name.Text = Mkey + " not found";
+ LB_ActualHash.ForeColor = Color.Red;
}
}
-
- private void LoadNCAData()
+ else
{
- NCA.NCA_Headers[0] = new NCA.NCA_Header(DecryptNCAHeader(gameNcaOffset));
- TB_TID.Text = "0" + NCA.NCA_Headers[0].TitleID.ToString("X");
- TB_SDKVer.Text = $"{NCA.NCA_Headers[0].SDKVersion4}.{NCA.NCA_Headers[0].SDKVersion3}.{NCA.NCA_Headers[0].SDKVersion2}.{NCA.NCA_Headers[0].SDKVersion1}";
- TB_MKeyRev.Text = Util.GetMkey(NCA.NCA_Headers[0].MasterKeyRev);
+ LB_ActualHash.Text = "";
+ }
+ }
+
+ public bool CheckXCI()
+ {
+ FileStream fileStream = new(TB_File.Text, FileMode.Open, FileAccess.Read);
+ byte[] array = new byte[61440];
+ byte[] array2 = new byte[16];
+ fileStream.Read(array, 0, 61440);
+ XCI.XCI_Headers[0] = new XCI.XCI_Header(array);
+ if (!XCI.XCI_Headers[0].Magic.Contains("HEAD"))
+ {
+ return false;
+ }
+ fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition;
+ fileStream.Read(array2, 0, 16);
+ HFS0.HFS0_Headers[0] = new HFS0.HFS0_Header(array2);
+ fileStream.Close();
+ return true;
+ }
+
+ public bool CheckNSP()
+ {
+ FileStream fileStream = File.OpenRead(TB_File.Text);
+ byte[] array = new byte[16];
+ fileStream.Read(array, 0, 16);
+ PFS0.PFS0_Headers[0] = new(array);
+ fileStream.Close();
+ if (!PFS0.PFS0_Headers[0].Magic.Contains("PFS0"))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void B_ExportCert_Click(object sender, EventArgs e)
+ {
+ new CenterWinDialog(this);
+ if (!File.Exists(TB_File.Text))
+ {
+ MessageBox.Show("File not found");
+ return;
}
- //https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa
- public static string ByteArrayToString(byte[] ba)
+ SaveFileDialog saveFileDialog = new SaveFileDialog();
+ saveFileDialog.Filter = "gamecard_cert.dat (*.dat)|*.dat";
+ saveFileDialog.FileName = Path.GetFileName("gamecard_cert.dat");
+ if (saveFileDialog.ShowDialog() != DialogResult.OK)
{
- StringBuilder hex = new StringBuilder(ba.Length * 2 + 2);
- hex.Append("0x");
- foreach (byte b in ba)
- hex.AppendFormat("{0:x2}", b);
- return hex.ToString();
+ return;
}
- public static string SHA256Bytes(byte[] ba)
+ FileStream fileStream = new(TB_File.Text, FileMode.Open, FileAccess.Read);
+ byte[] array = new byte[512];
+ fileStream.Position = 28672L;
+ fileStream.Read(array, 0, 512);
+ File.WriteAllBytes(saveFileDialog.FileName, array);
+ fileStream.Close();
+ MessageBox.Show($"Cert successfully exported to:\n\n{saveFileDialog.FileName}");
+ }
+
+ private void B_ImportCert_Click(object sender, EventArgs e)
+ {
+ new CenterWinDialog(this);
+ if (!File.Exists(TB_File.Text))
{
- SHA256 mySHA256 = SHA256.Create();
- byte[] hashValue;
- hashValue = mySHA256.ComputeHash(ba);
- return ByteArrayToString(hashValue);
+ MessageBox.Show("File not found");
+ return;
+ }
+ OpenFileDialog openFileDialog = new OpenFileDialog();
+ openFileDialog.Filter = "gamecard_cert (*.dat)|*.dat|All files (*.*)|*.*";
+ if (openFileDialog.ShowDialog() == DialogResult.OK && new FileInfo(openFileDialog.FileName).Length == 512)
+ {
+ using (Stream stream = File.Open(TB_File.Text, FileMode.Open))
+ {
+ stream.Position = 28672L;
+ stream.Write(File.ReadAllBytes(openFileDialog.FileName), 0, 512);
+ }
+ MessageBox.Show($"Cert successfully imported from:\n\n{openFileDialog.FileName}");
+ }
+ }
+
+ private void B_ViewCert_Click(object sender, EventArgs e)
+ {
+ new CenterWinDialog(this);
+ if (!File.Exists(TB_File.Text))
+ {
+ MessageBox.Show("File not found");
+ return;
+ }
+ CertForm cert = new(this)
+ {
+ Text = $"Cert Data - {TB_File.Text}"
+ };
+ cert.Show();
+ }
+
+ private void B_ClearCert_Click(object sender, EventArgs e)
+ {
+ new CenterWinDialog(this);
+
+ if (!File.Exists(TB_File.Text))
+ {
+ MessageBox.Show("File not found");
+ return;
}
- public bool isTrimmed()
+ if (MessageBox.Show("The cert will be deleted permanently.\nContinue?", "XCI Explorer", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
- return TB_ROMExactSize.Text == TB_ExactUsedSpace.Text;
+ return;
}
- private void LoadPartitions()
+ using Stream stream = File.Open(TB_File.Text, FileMode.Open);
+ byte[] array = new byte[512];
+ for (int i = 0; i < array.Length; i++)
{
- string actualHash;
- byte[] hashBuffer;
- long offset;
+ array[i] = byte.MaxValue;
+ }
+ stream.Position = 28672L;
+ stream.Write(array, 0, array.Length);
- TV_Partitions.Nodes.Clear();
- TV_Parti = new TreeViewFileSystem(TV_Partitions);
- rootNode = new BetterTreeNode("root");
- rootNode.Offset = -1L;
- rootNode.Size = -1L;
- TV_Partitions.Nodes.Add(rootNode);
- bool LogoPartition = false;
- FileStream fileStream = new FileStream(TB_File.Text, FileMode.Open, FileAccess.Read);
- HFS0.HSF0_Entry[] array = new HFS0.HSF0_Entry[HFS0.HFS0_Headers[0].FileCount];
- fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition + 16 + 64 * HFS0.HFS0_Headers[0].FileCount;
- long num = XCI.XCI_Headers[0].HFS0OffsetPartition + XCI.XCI_Headers[0].HFS0SizeParition;
- byte[] array2 = new byte[64];
- byte[] array3 = new byte[16];
- byte[] array4 = new byte[24];
- for (int i = 0; i < HFS0.HFS0_Headers[0].FileCount; i++)
- {
- fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition + 16 + 64 * i;
- fileStream.Read(array2, 0, 64);
- array[i] = new HFS0.HSF0_Entry(array2);
- fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition + 16 + 64 * HFS0.HFS0_Headers[0].FileCount + array[i].Name_ptr;
- int num2;
- while ((num2 = fileStream.ReadByte()) != 0 && num2 != 0)
- {
- chars.Add((char)num2);
- }
- array[i].Name = new string(chars.ToArray());
- chars.Clear();
- offset = num + array[i].Offset;
- hashBuffer = new byte[array[i].HashedRegionSize];
- fileStream.Position = offset;
- fileStream.Read(hashBuffer, 0, array[i].HashedRegionSize);
- actualHash = SHA256Bytes(hashBuffer);
+ new CenterWinDialog(this);
+ MessageBox.Show("Cert deleted.");
- TV_Parti.AddFile(array[i].Name + ".hfs0", rootNode, offset, array[i].Size, array[i].HashedRegionSize, ByteArrayToString(array[i].Hash), actualHash);
- BetterTreeNode betterTreeNode = TV_Parti.AddDir(array[i].Name, rootNode);
- HFS0.HFS0_Header[] array5 = new HFS0.HFS0_Header[1];
- fileStream.Position = array[i].Offset + num;
- fileStream.Read(array3, 0, 16);
- array5[0] = new HFS0.HFS0_Header(array3);
- if (array[i].Name == "secure")
- {
- SecureSize = new long[array5[0].FileCount];
- SecureOffset = new long[array5[0].FileCount];
- SecureName = new string[array5[0].FileCount];
- }
- if (array[i].Name == "normal")
- {
- NormalSize = new long[array5[0].FileCount];
- NormalOffset = new long[array5[0].FileCount];
- }
- if (array[i].Name == "logo")
- {
- if (array5[0].FileCount > 0)
- {
- LogoPartition = true;
- }
- }
- HFS0.HSF0_Entry[] array6 = new HFS0.HSF0_Entry[array5[0].FileCount];
- for (int j = 0; j < array5[0].FileCount; j++)
- {
- fileStream.Position = array[i].Offset + num + 16 + 64 * j;
- fileStream.Read(array2, 0, 64);
- array6[j] = new HFS0.HSF0_Entry(array2);
- fileStream.Position = array[i].Offset + num + 16 + 64 * array5[0].FileCount + array6[j].Name_ptr;
- while ((num2 = fileStream.ReadByte()) != 0 && num2 != 0)
- {
- chars.Add((char)num2);
- }
- array6[j].Name = new string(chars.ToArray());
- chars.Clear();
- if (array[i].Name == "secure")
- {
- SecureSize[j] = array6[j].Size;
- SecureOffset[j] = array[i].Offset + array6[j].Offset + num + 16 + array5[0].StringTableSize + array5[0].FileCount * 64;
- SecureName[j] = array6[j].Name;
- }
- if (array[i].Name == "normal")
- {
- NormalSize[j] = array6[j].Size;
- NormalOffset[j] = array[i].Offset + array6[j].Offset + num + 16 + array5[0].StringTableSize + array5[0].FileCount * 64;
- }
- offset = array[i].Offset + array6[j].Offset + num + 16 + array5[0].StringTableSize + array5[0].FileCount * 64;
- hashBuffer = new byte[array6[j].HashedRegionSize];
- fileStream.Position = offset;
- fileStream.Read(hashBuffer, 0, array6[j].HashedRegionSize);
- actualHash = SHA256Bytes(hashBuffer);
+ }
- TV_Parti.AddFile(array6[j].Name, betterTreeNode, offset, array6[j].Size, array6[j].HashedRegionSize, ByteArrayToString(array6[j].Hash), actualHash);
- TreeNode[] array7 = TV_Partitions.Nodes.Find(betterTreeNode.Text, true);
- if (array7.Length != 0)
- {
- TV_Parti.AddFile(array6[j].Name, (BetterTreeNode)array7[0], 0L, 0L);
- }
- }
- }
- long num3 = -9223372036854775808L;
- for (int k = 0; k < SecureSize.Length; k++)
- {
- if (SecureSize[k] > num3)
- {
- gameNcaSize = SecureSize[k];
- gameNcaOffset = SecureOffset[k];
- num3 = SecureSize[k];
- }
- }
- PFS0Offset = gameNcaOffset + 32768;
- fileStream.Position = PFS0Offset;
- fileStream.Read(array3, 0, 16);
- PFS0.PFS0_Headers[0] = new PFS0.PFS0_Header(array3);
- if (PFS0.PFS0_Headers[0].FileCount == 2 || !LogoPartition)
- {
- PFS0.PFS0_Entry[] array8;
- try
- {
- array8 = new PFS0.PFS0_Entry[PFS0.PFS0_Headers[0].FileCount];
- }
- catch (Exception ex)
- {
- array8 = new PFS0.PFS0_Entry[0];
- Debug.WriteLine("Partitions Error: " + ex.Message);
- }
- for (int m = 0; m < PFS0.PFS0_Headers[0].FileCount; m++)
- {
- fileStream.Position = PFS0Offset + 16 + 24 * m;
- fileStream.Read(array4, 0, 24);
- array8[m] = new PFS0.PFS0_Entry(array4);
- PFS0Size += array8[m].Size;
- }
- TV_Parti.AddFile("boot.psf0", rootNode, PFS0Offset, 16 + 24 * PFS0.PFS0_Headers[0].FileCount + 64 + PFS0Size);
- BetterTreeNode betterTreeNode2 = TV_Parti.AddDir("boot", rootNode);
- for (int n = 0; n < PFS0.PFS0_Headers[0].FileCount; n++)
- {
- fileStream.Position = PFS0Offset + 16 + 24 * PFS0.PFS0_Headers[0].FileCount + array8[n].Name_ptr;
- int num4;
- while ((num4 = fileStream.ReadByte()) != 0 && num4 != 0)
- {
- chars.Add((char)num4);
- }
- array8[n].Name = new string(chars.ToArray());
- chars.Clear();
- TV_Parti.AddFile(array8[n].Name, betterTreeNode2, PFS0Offset + array8[n].Offset + 16 + PFS0.PFS0_Headers[0].StringTableSize + PFS0.PFS0_Headers[0].FileCount * 24, array8[n].Size);
- TreeNode[] array9 = TV_Partitions.Nodes.Find(betterTreeNode2.Text, true);
- if (array9.Length != 0)
- {
- TV_Parti.AddFile(array8[n].Name, (BetterTreeNode)array9[0], 0L, 0L);
- }
- }
- }
- fileStream.Close();
+ private void B_Extract_Click(object sender, EventArgs e)
+ {
+ SaveFileDialog saveFileDialog = new SaveFileDialog
+ {
+ FileName = LB_SelectedData.Text
+ };
+
+ if (saveFileDialog.ShowDialog() != DialogResult.OK)
+ {
+ return;
}
- private void TV_Partitions_AfterSelect(object sender, TreeViewEventArgs e)
+ if (backgroundWorker1.IsBusy)
{
- BetterTreeNode betterTreeNode = (BetterTreeNode)TV_Partitions.SelectedNode;
- if (betterTreeNode.Offset != -1)
- {
- selectedOffset = betterTreeNode.Offset;
- selectedSize = betterTreeNode.Size;
- string expectedHash = betterTreeNode.ExpectedHash;
- string actualHash = betterTreeNode.ActualHash;
- long HashedRegionSize = betterTreeNode.HashedRegionSize;
-
- LB_DataOffset.Text = "Offset: 0x" + selectedOffset.ToString("X");
- LB_SelectedData.Text = e.Node.Text;
- if (backgroundWorker1.IsBusy != true)
- {
- B_Extract.Enabled = true;
- }
- string[] array = new string[5]
- {
- "B",
- "KB",
- "MB",
- "GB",
- "TB"
- };
- double num = (double)selectedSize;
- int num2 = 0;
- while (num >= 1024.0 && num2 < array.Length - 1)
- {
- num2++;
- num /= 1024.0;
- }
- LB_DataSize.Text = "Size: 0x" + selectedSize.ToString("X") + " (" + num.ToString() + array[num2] + ")";
-
- if (HashedRegionSize != 0)
- {
- LB_HashedRegionSize.Text = "HashedRegionSize: 0x" + HashedRegionSize.ToString("X");
- }
- else
- {
- LB_HashedRegionSize.Text = "";
- }
-
- if (!string.IsNullOrEmpty(expectedHash))
- {
- LB_ExpectedHash.Text = "Header Hash: " + expectedHash.Substring(0, 32);
- }
- else
- {
- LB_ExpectedHash.Text = "";
- }
-
- if (!string.IsNullOrEmpty(actualHash))
- {
- LB_ActualHash.Text = "Actual Hash: " + actualHash.Substring(0, 32);
- if (actualHash == expectedHash)
- {
- LB_ActualHash.ForeColor = System.Drawing.Color.Green;
- }
- else
- {
- LB_ActualHash.ForeColor = System.Drawing.Color.Red;
- }
- }
- else
- {
- LB_ActualHash.Text = "";
- }
-
- }
- else
- {
- LB_SelectedData.Text = "";
- LB_DataOffset.Text = "";
- LB_DataSize.Text = "";
- LB_HashedRegionSize.Text = "";
- LB_ExpectedHash.Text = "";
- LB_ActualHash.Text = "";
- B_Extract.Enabled = false;
- }
+ return;
}
- public bool CheckXCI()
- {
- FileStream fileStream = new FileStream(TB_File.Text, FileMode.Open, FileAccess.Read);
- byte[] array = new byte[61440];
- byte[] array2 = new byte[16];
- fileStream.Read(array, 0, 61440);
- XCI.XCI_Headers[0] = new XCI.XCI_Header(array);
- if (!XCI.XCI_Headers[0].Magic.Contains("HEAD"))
- {
- return false;
- }
- fileStream.Position = XCI.XCI_Headers[0].HFS0OffsetPartition;
- fileStream.Read(array2, 0, 16);
- HFS0.HFS0_Headers[0] = new HFS0.HFS0_Header(array2);
- fileStream.Close();
- return true;
- }
+ B_Extract.Enabled = false;
+ B_LoadROM.Enabled = false;
+ B_TrimXCI.Enabled = false;
+ B_ImportCert.Enabled = false;
+ B_ClearCert.Enabled = false;
- public bool CheckNSP()
- {
- FileStream fileStream = File.OpenRead(TB_File.Text);
- byte[] array = new byte[16];
- fileStream.Read(array, 0, 16);
- PFS0.PFS0_Headers[0] = new PFS0.PFS0_Header(array);
- fileStream.Close();
- if (!PFS0.PFS0_Headers[0].Magic.Contains("PFS0"))
- {
- return false;
- }
- return true;
- }
+ // Start the asynchronous operation.
+ backgroundWorker1.RunWorkerAsync(saveFileDialog.FileName);
+ }
- 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();
- saveFileDialog.Filter = "gamecard_cert.dat (*.dat)|*.dat";
- saveFileDialog.FileName = Path.GetFileName("gamecard_cert.dat");
- if (saveFileDialog.ShowDialog() == DialogResult.OK)
- {
- FileStream fileStream = new FileStream(TB_File.Text, FileMode.Open, FileAccess.Read);
- byte[] array = new byte[512];
- fileStream.Position = 28672L;
- fileStream.Read(array, 0, 512);
- File.WriteAllBytes(saveFileDialog.FileName, array);
- fileStream.Close();
- MessageBox.Show("Cert successfully exported to:\n\n" + saveFileDialog.FileName);
- }
- }
- else
- {
- MessageBox.Show("File not found");
- }
- }
+ public byte[] DecryptNCAHeader(long offset)
+ {
+ byte[] array = new byte[3072];
- private void B_ImportCert_Click(object sender, EventArgs e)
+ if (!File.Exists(TB_File.Text))
{
- using CenterWinDialog center = new CenterWinDialog(this);
- if (Util.checkFile(TB_File.Text))
- {
- OpenFileDialog openFileDialog = new OpenFileDialog();
- openFileDialog.Filter = "gamecard_cert (*.dat)|*.dat|All files (*.*)|*.*";
- if (openFileDialog.ShowDialog() == DialogResult.OK && new FileInfo(openFileDialog.FileName).Length == 512)
- {
- using (Stream stream = File.Open(TB_File.Text, FileMode.Open))
- {
- stream.Position = 28672L;
- stream.Write(File.ReadAllBytes(openFileDialog.FileName), 0, 512);
- }
- MessageBox.Show("Cert successfully imported from:\n\n" + openFileDialog.FileName);
- }
- }
- else
- {
- MessageBox.Show("File not found");
- }
- }
-
- 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);
- cert.Text = "Cert Data - " + TB_File.Text;
- cert.Show();
- }
- else
- {
- MessageBox.Show("File not found");
- }
- }
-
- 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)
- {
- using (Stream stream = File.Open(TB_File.Text, FileMode.Open))
- {
- byte[] array = new byte[512];
- for (int i = 0; i < array.Length; i++)
- {
- array[i] = byte.MaxValue;
- }
- stream.Position = 28672L;
- stream.Write(array, 0, array.Length);
- MessageBox.Show("Cert deleted.");
- }
- }
- }
- else
- {
- MessageBox.Show("File not found");
- }
- }
-
- private void B_Extract_Click(object sender, EventArgs e)
- {
- SaveFileDialog saveFileDialog = new SaveFileDialog();
- saveFileDialog.FileName = LB_SelectedData.Text;
- if (saveFileDialog.ShowDialog() == DialogResult.OK)
- {
- if (backgroundWorker1.IsBusy != true)
- {
- B_Extract.Enabled = false;
- B_LoadROM.Enabled = false;
- B_TrimXCI.Enabled = false;
- B_ImportCert.Enabled = false;
- B_ClearCert.Enabled = false;
-
- // Start the asynchronous operation.
- backgroundWorker1.RunWorkerAsync(saveFileDialog.FileName);
- }
- }
- }
-
- public byte[] DecryptNCAHeader(long offset)
- {
- byte[] array = new byte[3072];
- if (File.Exists(TB_File.Text))
- {
- FileStream fileStream = new FileStream(TB_File.Text, FileMode.Open, FileAccess.Read);
- fileStream.Position = offset;
- fileStream.Read(array, 0, 3072);
- File.WriteAllBytes(TB_File.Text + ".tmp", array);
- Xts xts = XtsAes128.Create(NcaHeaderEncryptionKey1_Prod, NcaHeaderEncryptionKey2_Prod);
- using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(TB_File.Text + ".tmp")))
- {
- using (XtsStream xtsStream = new XtsStream(binaryReader.BaseStream, xts, 512))
- {
- xtsStream.Read(array, 0, 3072);
- }
- }
- File.Delete(TB_File.Text + ".tmp");
- fileStream.Close();
- }
return array;
}
- private void CB_RegionName_SelectedIndexChanged(object sender, EventArgs e)
+ FileStream fileStream = new(TB_File.Text, FileMode.Open, FileAccess.Read)
{
- int num = Array.FindIndex(Language, (string element) => element.StartsWith(CB_RegionName.Text, StringComparison.Ordinal));
- // Icons for 1-2 Switch in some languages are "missing"
- // This just shows the first real icon instead of a blank
- if (Icons[num] != null)
+ Position = offset
+ };
+ fileStream.Read(array, 0, 3072);
+ File.WriteAllBytes($"{TB_File.Text}.tmp", array);
+ Xts xts = XtsAes128.Create(NcaHeaderEncryptionKey1_Prod, NcaHeaderEncryptionKey2_Prod);
+ using (BinaryReader binaryReader = new(File.OpenRead($"{TB_File.Text}.tmp")))
+ {
+ using XtsStream xtsStream = new(binaryReader.BaseStream, xts, 512);
+ xtsStream.Read(array, 0, 3072);
+ }
+ File.Delete($"{TB_File.Text}.tmp");
+ fileStream.Close();
+ return array;
+ }
+
+ private void CB_RegionName_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ int num = Array.FindIndex(Language, (string element) => element.StartsWith(CB_RegionName.Text, StringComparison.Ordinal));
+ // Icons for 1-2 Switch in some languages are "missing"
+ // This just shows the first real icon instead of a blank
+ if (Icons[num] != null)
+ {
+ PB_GameIcon.BackgroundImage = Icons[num];
+ }
+ else
+ {
+ for (int i = 0; i < CB_RegionName.Items.Count; i++)
{
- PB_GameIcon.BackgroundImage = Icons[num];
- }
- else
- {
- for (int i = 0; i < CB_RegionName.Items.Count; i++)
+ if (Icons[i] == null)
{
- if (Icons[i] != null)
- {
- PB_GameIcon.BackgroundImage = Icons[i];
- break;
- }
+ continue;
}
- }
- TB_Name.Text = NACP.NACP_Strings[num].GameName;
- TB_Dev.Text = NACP.NACP_Strings[num].GameAuthor;
- }
- 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)
- {
- using CenterWinDialog centerInner = new CenterWinDialog(this);
- if (!isTrimmed())
- {
- FileStream fileStream = new FileStream(TB_File.Text, FileMode.Open, FileAccess.Write);
- fileStream.SetLength((long)UsedSize);
- fileStream.Close();
- B_TrimXCI.Enabled = false;
- MessageBox.Show("Done.");
- string[] array = new string[5]
- {
- "B",
- "KB",
- "MB",
- "GB",
- "TB"
- };
- double num = (double)new FileInfo(TB_File.Text).Length;
- TB_ROMExactSize.Text = "(" + num.ToString() + " bytes)";
- int num2 = 0;
- while (num >= 1024.0 && num2 < array.Length - 1)
- {
- num2++;
- num /= 1024.0;
- }
- TB_ROMSize.Text = $"{num:0.##} {array[num2]}";
- double num3 = UsedSize = (double)(XCI.XCI_Headers[0].CardSize2 * 512 + 512);
- TB_ExactUsedSpace.Text = "(" + num3.ToString() + " bytes)";
- num2 = 0;
- while (num3 >= 1024.0 && num2 < array.Length - 1)
- {
- num2++;
- num3 /= 1024.0;
- }
- TB_UsedSpace.Text = $"{num3:0.##} {array[num2]}";
- }
- }
- }
- else
- {
- MessageBox.Show("File not found");
+ PB_GameIcon.BackgroundImage = Icons[i];
+ break;
}
}
+ TB_Name.Text = NACP.NACP_Strings[num].GameName;
+ TB_Dev.Text = NACP.NACP_Strings[num].GameAuthor;
+ }
- private void LB_ExpectedHash_DoubleClick(object sender, EventArgs e)
+ private void B_TrimXCI_Click(object sender, EventArgs e)
+ {
+ new CenterWinDialog(this);
+
+ if (!File.Exists(TB_File.Text))
{
- BetterTreeNode betterTreeNode = (BetterTreeNode)TV_Partitions.SelectedNode;
- if (betterTreeNode.Offset != -1)
- {
- Clipboard.SetText(betterTreeNode.ExpectedHash);
- }
+ MessageBox.Show("File not found");
+ return;
}
- private void LB_ActualHash_DoubleClick(object sender, EventArgs e)
+ if (MessageBox.Show("Trim XCI?", "XCI Explorer", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
- BetterTreeNode betterTreeNode = (BetterTreeNode)TV_Partitions.SelectedNode;
- if (betterTreeNode.Offset != -1)
- {
- Clipboard.SetText(betterTreeNode.ActualHash);
- }
+ return;
}
- private void TB_File_DragDrop(object sender, DragEventArgs e)
+ new CenterWinDialog(this);
+
+ if (isTrimmed())
{
- if (backgroundWorker1.IsBusy != true)
- {
- string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
- TB_File.Text = files[0];
- ProcessFile();
- }
+ return;
}
- private void TB_File_DragEnter(object sender, DragEventArgs e)
+ FileStream fileStream = new(TB_File.Text, FileMode.Open, FileAccess.Write);
+ fileStream.SetLength((long)UsedSize);
+ fileStream.Close();
+ B_TrimXCI.Enabled = false;
+ MessageBox.Show("Done.");
+ string[] array = new string[5]
{
- if (backgroundWorker1.IsBusy != true)
- {
- if (e.Data.GetDataPresent(DataFormats.FileDrop))
- {
- e.Effect = DragDropEffects.Copy;
- }
- else
- {
- e.Effect = DragDropEffects.None;
- }
- }
+ "B",
+ "KB",
+ "MB",
+ "GB",
+ "TB"
+ };
+ double num = new FileInfo(TB_File.Text).Length;
+ TB_ROMExactSize.Text = $"({num} bytes)";
+ int num2 = 0;
+ while (num >= 1024.0 && num2 < array.Length - 1)
+ {
+ num2++;
+ num /= 1024.0;
}
-
- private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
+ TB_ROMSize.Text = $"{num:0.##} {array[num2]}";
+ double num3 = UsedSize = XCI.XCI_Headers[0].CardSize2 * 512 + 512;
+ TB_ExactUsedSpace.Text = $"({num3} bytes)";
+ num2 = 0;
+ while (num3 >= 1024.0 && num2 < array.Length - 1)
{
- BackgroundWorker worker = sender as BackgroundWorker;
- string fileName = (string)e.Argument;
-
- using (FileStream fileStream = File.OpenRead(TB_File.Text))
- {
- using (FileStream fileStream2 = File.OpenWrite(fileName))
- {
- new BinaryReader(fileStream);
- new BinaryWriter(fileStream2);
- fileStream.Position = selectedOffset;
- byte[] buffer = new byte[8192];
- long num = selectedSize;
- int num2;
- while ((num2 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
- {
- fileStream2.Write(buffer, 0, num2);
- num -= num2;
- }
- fileStream.Close();
- }
- }
+ num2++;
+ num3 /= 1024.0;
}
+ TB_UsedSpace.Text = $"{num3:0.##} {array[num2]}";
+ }
- private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ private void LB_ExpectedHash_DoubleClick(object sender, EventArgs e)
+ {
+ BetterTreeNode betterTreeNode = (BetterTreeNode)TV_Partitions.SelectedNode;
+ if (betterTreeNode.Offset != -1)
{
- using CenterWinDialog center = new CenterWinDialog(this);
- B_Extract.Enabled = true;
- B_LoadROM.Enabled = true;
- B_TrimXCI.Enabled = true;
- B_ImportCert.Enabled = true;
- B_ClearCert.Enabled = true;
-
- if (e.Error != null)
- {
- MessageBox.Show("Error: " + e.Error.Message);
- }
- else
- {
- MessageBox.Show("Done extracting NCA!");
- }
+ Clipboard.SetText(betterTreeNode.ExpectedHash);
}
}
-}
+
+ private void LB_ActualHash_DoubleClick(object sender, EventArgs e)
+ {
+ BetterTreeNode betterTreeNode = (BetterTreeNode)TV_Partitions.SelectedNode;
+ if (betterTreeNode.Offset != -1)
+ {
+ Clipboard.SetText(betterTreeNode.ActualHash);
+ }
+ }
+
+ private void TB_File_DragDrop(object sender, DragEventArgs e)
+ {
+ if (backgroundWorker1.IsBusy != true)
+ {
+ string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
+ TB_File.Text = files[0];
+ ProcessFile();
+ }
+ }
+
+ private void TB_File_DragEnter(object sender, DragEventArgs e)
+ {
+ if (backgroundWorker1.IsBusy)
+ {
+ return;
+ }
+
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ e.Effect = DragDropEffects.Copy;
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ }
+
+ private void TABP_XCI_DragDrop(object sender, DragEventArgs e)
+ {
+ if (backgroundWorker1.IsBusy)
+ {
+ return;
+ }
+
+ string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
+ TB_File.Text = files[0];
+ ProcessFile();
+ }
+
+ private void TABP_XCI_DragEnter(object sender, DragEventArgs e)
+ {
+ if (backgroundWorker1.IsBusy)
+ {
+ return;
+ }
+
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ e.Effect = DragDropEffects.Copy;
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ }
+
+ private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
+ {
+ BackgroundWorker worker = sender as BackgroundWorker;
+ string fileName = (string)e.Argument;
+
+ using FileStream fileStream = File.OpenRead(TB_File.Text);
+ using FileStream fileStream2 = File.OpenWrite(fileName);
+ new BinaryReader(fileStream);
+ new BinaryWriter(fileStream2);
+ fileStream.Position = selectedOffset;
+ long num = selectedSize;
+
+ if (selectedSize < 10000)
+ {
+ byte[] buffer = new byte[1];
+ int num2;
+ while ((num2 = fileStream.Read(buffer, 0, 1)) > 0 && num > 0)
+ {
+ fileStream2.Write(buffer, 0, num2);
+ num -= num2;
+ }
+ }
+ else
+ {
+ byte[] buffer = new byte[8192];
+ int num2;
+ while ((num2 = fileStream.Read(buffer, 0, 8192)) > 0 && num > 0)
+ {
+ fileStream2.Write(buffer, 0, num2);
+ num -= num2;
+ }
+ }
+
+ fileStream.Close();
+ }
+
+ private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ new CenterWinDialog(this);
+ B_Extract.Enabled = true;
+ B_LoadROM.Enabled = true;
+ B_TrimXCI.Enabled = true;
+ B_ImportCert.Enabled = true;
+ B_ClearCert.Enabled = true;
+
+ if (e.Error != null)
+ {
+ MessageBox.Show($"Error: {e.Error.Message}");
+ }
+ else
+ {
+ MessageBox.Show("Done extracting NCA!");
+ }
+ }
+
+ private void TABP_XCI_Click(object sender, EventArgs e)
+ {
+
+ }
+
+ private void label11_Click(object sender, EventArgs e)
+ {
+
+ }
+
+}
\ No newline at end of file
diff --git a/XCI_Explorer/NACP.cs b/XCI_Explorer/NACP.cs
index cb9c647..a46d9db 100644
--- a/XCI_Explorer/NACP.cs
+++ b/XCI_Explorer/NACP.cs
@@ -1,42 +1,41 @@
using System.Linq;
using System.Text;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+public static class NACP
{
- public static class NACP
+ public class NACP_String
{
- public class NACP_String
+ public byte[] Data;
+ public byte Check;
+ public string GameName;
+ public string GameAuthor;
+
+ public NACP_String(byte[] data)
{
- public byte[] Data;
- public byte Check;
- public string GameName;
- public string GameAuthor;
-
- public NACP_String(byte[] data)
- {
- Data = data;
- Check = Data[0];
- GameName = Encoding.UTF8.GetString(Data.Take(512).ToArray());
- GameAuthor = Encoding.UTF8.GetString(Data.Skip(512).Take(256).ToArray());
- }
+ Data = data;
+ Check = Data[0];
+ GameName = Encoding.UTF8.GetString(Data.Take(512).ToArray());
+ GameAuthor = Encoding.UTF8.GetString(Data.Skip(512).Take(256).ToArray());
}
-
- public class NACP_Data
- {
- public byte[] Data;
- public string GameVer;
- public string GameProd;
-
- public NACP_Data(byte[] data)
- {
- Data = data;
- GameVer = Encoding.UTF8.GetString(Data.Skip(0x60).Take(16).ToArray());
- GameProd = Encoding.UTF8.GetString(Data.Skip(0xA8).Take(8).ToArray());
- }
- }
-
- public static NACP_String[] NACP_Strings = new NACP_String[16];
-
- public static NACP_Data[] NACP_Datas = new NACP_Data[1];
}
+
+ public class NACP_Data
+ {
+ public byte[] Data;
+ public string GameVer;
+ public string GameProd;
+
+ public NACP_Data(byte[] data)
+ {
+ Data = data;
+ GameVer = Encoding.UTF8.GetString(Data.Skip(0x60).Take(16).ToArray());
+ GameProd = Encoding.UTF8.GetString(Data.Skip(0xA8).Take(8).ToArray());
+ }
+ }
+
+ public static NACP_String[] NACP_Strings = new NACP_String[16];
+
+ public static NACP_Data[] NACP_Datas = new NACP_Data[1];
}
diff --git a/XCI_Explorer/NCA.cs b/XCI_Explorer/NCA.cs
index f23ba9b..a789be6 100644
--- a/XCI_Explorer/NCA.cs
+++ b/XCI_Explorer/NCA.cs
@@ -2,34 +2,33 @@ using System;
using System.Linq;
using System.Text;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+internal static class NCA
{
- internal static class NCA
+ public class NCA_Header
{
- public class NCA_Header
+ public byte[] Data;
+ public string Magic;
+ public long TitleID;
+ public byte SDKVersion1;
+ public byte SDKVersion2;
+ public byte SDKVersion3;
+ public byte SDKVersion4;
+ public byte MasterKeyRev;
+
+ public NCA_Header(byte[] data)
{
- public byte[] Data;
- public string Magic;
- public long TitleID;
- public byte SDKVersion1;
- public byte SDKVersion2;
- public byte SDKVersion3;
- public byte SDKVersion4;
- public byte MasterKeyRev;
-
- public NCA_Header(byte[] data)
- {
- Data = data;
- Magic = Encoding.UTF8.GetString(Data.Skip(512).Take(4).ToArray());
- TitleID = BitConverter.ToInt64(data, 528);
- SDKVersion1 = Data[540];
- SDKVersion2 = Data[541];
- SDKVersion3 = Data[542];
- SDKVersion4 = Data[543];
- MasterKeyRev = Data[544];
- }
+ Data = data;
+ Magic = Encoding.UTF8.GetString(Data.Skip(512).Take(4).ToArray());
+ TitleID = BitConverter.ToInt64(data, 528);
+ SDKVersion1 = Data[540];
+ SDKVersion2 = Data[541];
+ SDKVersion3 = Data[542];
+ SDKVersion4 = Data[543];
+ MasterKeyRev = Data[544];
}
-
- public static NCA_Header[] NCA_Headers = new NCA_Header[1];
}
+
+ public static NCA_Header[] NCA_Headers = new NCA_Header[1];
}
diff --git a/XCI_Explorer/PFS0.cs b/XCI_Explorer/PFS0.cs
index b36158f..303e935 100644
--- a/XCI_Explorer/PFS0.cs
+++ b/XCI_Explorer/PFS0.cs
@@ -2,47 +2,46 @@ using System;
using System.Linq;
using System.Text;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+internal static class PFS0
{
- internal static class PFS0
+ public class PFS0_Header
{
- public class PFS0_Header
+ public byte[] Data;
+ public string Magic;
+ public int FileCount;
+ public int StringTableSize;
+ public int Reserved;
+
+ public PFS0_Header(byte[] data)
{
- public byte[] Data;
- public string Magic;
- public int FileCount;
- public int StringTableSize;
- public int Reserved;
-
- public PFS0_Header(byte[] data)
- {
- Data = data;
- Magic = Encoding.UTF8.GetString(Data.Take(4).ToArray());
- FileCount = BitConverter.ToInt32(data, 4);
- StringTableSize = BitConverter.ToInt32(data, 8);
- Reserved = BitConverter.ToInt32(data, 12);
- }
+ Data = data;
+ Magic = Encoding.UTF8.GetString(Data.Take(4).ToArray());
+ FileCount = BitConverter.ToInt32(data, 4);
+ StringTableSize = BitConverter.ToInt32(data, 8);
+ Reserved = BitConverter.ToInt32(data, 12);
}
-
- public class PFS0_Entry
- {
- public byte[] Data;
- public long Offset;
- public long Size;
- public int Name_ptr;
- public int Reserved;
- public string Name;
-
- public PFS0_Entry(byte[] data)
- {
- Data = data;
- Offset = BitConverter.ToInt64(data, 0);
- Size = BitConverter.ToInt64(data, 8);
- Name_ptr = BitConverter.ToInt32(data, 16);
- Reserved = BitConverter.ToInt32(data, 20);
- }
- }
-
- public static PFS0_Header[] PFS0_Headers = new PFS0_Header[1];
}
+
+ public class PFS0_Entry
+ {
+ public byte[] Data;
+ public long Offset;
+ public long Size;
+ public int Name_ptr;
+ public int Reserved;
+ public string Name;
+
+ public PFS0_Entry(byte[] data)
+ {
+ Data = data;
+ Offset = BitConverter.ToInt64(data, 0);
+ Size = BitConverter.ToInt64(data, 8);
+ Name_ptr = BitConverter.ToInt32(data, 16);
+ Reserved = BitConverter.ToInt32(data, 20);
+ }
+ }
+
+ public static PFS0_Header[] PFS0_Headers = new PFS0_Header[1];
}
diff --git a/XCI_Explorer/Program.cs b/XCI_Explorer/Program.cs
index 2c9f687..0094802 100644
--- a/XCI_Explorer/Program.cs
+++ b/XCI_Explorer/Program.cs
@@ -1,28 +1,26 @@
using System;
+using System.IO;
using System.Windows.Forms;
-namespace XCI_Explorer
-{
- internal static class Program
- {
- [STAThread]
- private static void Main()
- {
- AppDomain.CurrentDomain.AssemblyResolve += (Object sender, ResolveEventArgs args) =>
- {
- System.Reflection.AssemblyName embeddedAssembly = new System.Reflection.AssemblyName(args.Name);
- String resourceName = "XCI_Explorer" + "." + embeddedAssembly.Name + ".dll";
+namespace XCI_Explorer;
- using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
- {
- Byte[] assemblyData = new Byte[stream.Length];
- stream.Read(assemblyData, 0, assemblyData.Length);
- return System.Reflection.Assembly.Load(assemblyData);
- }
- };
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new MainForm());
- }
+internal static class Program
+{
+ [STAThread]
+ private static void Main()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs args) =>
+ {
+ System.Reflection.AssemblyName embeddedAssembly = new System.Reflection.AssemblyName(args.Name);
+ string resourceName = "XCI_Explorer" + "." + embeddedAssembly.Name + ".dll";
+
+ using Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
+ byte[] assemblyData = new byte[stream.Length];
+ stream.Read(assemblyData, 0, assemblyData.Length);
+ return System.Reflection.Assembly.Load(assemblyData);
+ };
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
}
}
diff --git a/XCI_Explorer/TreeViewFileSystem.cs b/XCI_Explorer/TreeViewFileSystem.cs
index 1a54ce3..8cda4f9 100644
--- a/XCI_Explorer/TreeViewFileSystem.cs
+++ b/XCI_Explorer/TreeViewFileSystem.cs
@@ -1,40 +1,40 @@
using System.Windows.Forms;
using XCI_Explorer.Helpers;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+public class TreeViewFileSystem
{
- public class TreeViewFileSystem
+ public TreeView treeView;
+
+ public TreeViewFileSystem(TreeView tv)
{
- public TreeView treeView;
+ }
- public TreeViewFileSystem(TreeView tv)
+ public BetterTreeNode AddDir(string name, BetterTreeNode parent = null)
+ {
+ BetterTreeNode betterTreeNode = new(name)
{
- }
+ Offset = -1L,
+ Size = -1L
+ };
+ parent.Nodes.Add(betterTreeNode);
+ return betterTreeNode;
+ }
- public BetterTreeNode AddDir(string name, BetterTreeNode parent = null)
- {
- BetterTreeNode betterTreeNode = new BetterTreeNode(name);
- betterTreeNode.Offset = -1L;
- betterTreeNode.Size = -1L;
- parent.Nodes.Add(betterTreeNode);
- return betterTreeNode;
- }
+ public BetterTreeNode AddFile(string name, BetterTreeNode parent, long offset, long size) => AddFile(name, parent, offset, size, 0, "", "");
- public BetterTreeNode AddFile(string name, BetterTreeNode parent, long offset, long size)
+ public BetterTreeNode AddFile(string name, BetterTreeNode parent, long offset, long size, long HashedRegionSize, string ExpectedHash, string ActualHash)
+ {
+ BetterTreeNode betterTreeNode = new(name)
{
- return AddFile(name, parent, offset, size, 0, "", "");
- }
-
- public BetterTreeNode AddFile(string name, BetterTreeNode parent, long offset, long size, long HashedRegionSize, string ExpectedHash, string ActualHash)
- {
- BetterTreeNode betterTreeNode = new BetterTreeNode(name);
- betterTreeNode.Offset = offset;
- betterTreeNode.Size = size;
- betterTreeNode.ExpectedHash = ExpectedHash;
- betterTreeNode.ActualHash = ActualHash;
- betterTreeNode.HashedRegionSize = HashedRegionSize;
- parent.Nodes.Add(betterTreeNode);
- return betterTreeNode;
- }
+ Offset = offset,
+ Size = size,
+ ExpectedHash = ExpectedHash,
+ ActualHash = ActualHash,
+ HashedRegionSize = HashedRegionSize
+ };
+ parent.Nodes.Add(betterTreeNode);
+ return betterTreeNode;
}
}
diff --git a/XCI_Explorer/Util.cs b/XCI_Explorer/Util.cs
index a7ce235..f9b6716 100644
--- a/XCI_Explorer/Util.cs
+++ b/XCI_Explorer/Util.cs
@@ -1,130 +1,73 @@
using System;
-using System.IO;
using System.Linq;
+using System.Text;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+internal static class Util
{
- internal static class Util
+ public static string GetCapacity(int id)
{
- public static string GetCapacity(int id)
+ return id switch
{
- switch (id)
- {
- case 250:
- return "1GB";
- case 248:
- return "2GB";
- case 240:
- return "4GB";
- case 224:
- return "8GB";
- case 225:
- return "16GB";
- case 226:
- return "32GB";
- default:
- return "?";
- }
- }
-
- public static string GetMkey(byte id)
- {
- switch (id)
- {
- case 0:
- case 1:
- return "MasterKey0 (1.0.0-2.3.0)";
- case 2:
- return "MasterKey1 (3.0.0)";
- case 3:
- return "MasterKey2 (3.0.1-3.0.2)";
- case 4:
- return "MasterKey3 (4.0.0-4.1.0)";
- case 5:
- return "MasterKey4 (5.0.0-5.1.0)";
- case 6:
- return "MasterKey5 (6.0.0-6.1.0)";
- case 7:
- return "MasterKey6 (6.2.0)";
- case 8:
- return "MasterKey7 (7.0.0-8.0.1)";
- case 9:
- 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-12.0.3)";
- case 12:
- return "MasterKey11 (12.1.0)";
- case 13:
- return "MasterKey12 (13.0.0-?)";
- case 14:
- return "MasterKey13";
- case 15:
- return "MasterKey14";
- case 16:
- return "MasterKey15";
- case 17:
- return "MasterKey16";
- case 18:
- return "MasterKey17";
- case 19:
- return "MasterKey18";
- case 20:
- return "MasterKey19";
- case 21:
- return "MasterKey20";
- case 22:
- return "MasterKey21";
- case 23:
- return "MasterKey22";
- case 24:
- return "MasterKey23";
- case 25:
- return "MasterKey24";
- case 26:
- return "MasterKey25";
- case 27:
- return "MasterKey26";
- case 28:
- return "MasterKey27";
- case 29:
- return "MasterKey28";
- case 30:
- return "MasterKey29";
- case 31:
- return "MasterKey30";
- case 32:
- return "MasterKey31";
- case 33:
- return "MasterKey32";
- default:
- return "?";
- }
- }
-
- public static bool checkFile(string filepath)
- {
- return File.Exists(filepath);
- }
-
- public static byte[] StringToByteArray(string hex)
- {
- return (from x in Enumerable.Range(0, hex.Length)
- where x % 2 == 0
- select Convert.ToByte(hex.Substring(x, 2), 16)).ToArray();
- }
-
- public static string Base64Encode(string plainText)
- {
- var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
- return System.Convert.ToBase64String(plainTextBytes);
- }
-
- public static string Base64Decode(string base64EncodedData)
- {
- var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
- return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
- }
+ 250 => "1GB",
+ 248 => "2GB",
+ 240 => "4GB",
+ 224 => "8GB",
+ 225 => "16GB",
+ 226 => "32GB",
+ _ => "?",
+ };
}
+
+ public static string GetMkey(byte id)
+ {
+ return id switch
+ {
+ 0 or 1 => "MasterKey0 (1.0.0-2.3.0)",
+ 2 => "MasterKey1 (3.0.0)",
+ 3 => "MasterKey2 (3.0.1-3.0.2)",
+ 4 => "MasterKey3 (4.0.0-4.1.0)",
+ 5 => "MasterKey4 (5.0.0-5.1.0)",
+ 6 => "MasterKey5 (6.0.0-6.1.0)",
+ 7 => "MasterKey6 (6.2.0)",
+ 8 => "MasterKey7 (7.0.0-8.0.1)",
+ 9 => "MasterKey8 (8.1.0-8.1.1)",
+ 10 => "MasterKey9 (9.0.0-9.0.1)",
+ 11 => "MasterKey10 (9.1.0-12.0.3)",
+ 12 => "MasterKey11 (12.1.0)",
+ 13 => "MasterKey12 (13.0.0-13.2.1)",
+ 14 => "MasterKey13 (14.0.0-14.1.2)",
+ 15 => "MasterKey14 (15.0.0-?)",
+ 16 => "MasterKey15",
+ 17 => "MasterKey16",
+ 18 => "MasterKey17",
+ 19 => "MasterKey18",
+ 20 => "MasterKey19",
+ 21 => "MasterKey20",
+ 22 => "MasterKey21",
+ 23 => "MasterKey22",
+ 24 => "MasterKey23",
+ 25 => "MasterKey24",
+ 26 => "MasterKey25",
+ 27 => "MasterKey26",
+ 28 => "MasterKey27",
+ 29 => "MasterKey28",
+ 30 => "MasterKey29",
+ 31 => "MasterKey30",
+ 32 => "MasterKey31",
+ 33 => "MasterKey32",
+ _ => "?",
+ };
+ }
+
+ public static byte[] StringToByteArray(string hex) => (from x in Enumerable.Range(0, hex.Length)
+ where x % 2 == 0
+ select Convert.ToByte(hex.Substring(x, 2), 16)).ToArray();
+
+ public static string Base64Encode(string plainText)
+ => Convert.ToBase64String(Encoding.UTF8.GetBytes(plainText));
+
+ public static string Base64Decode(string base64EncodedData)
+ => Encoding.UTF8.GetString(Convert.FromBase64String(base64EncodedData));
}
diff --git a/XCI_Explorer/XCI.cs b/XCI_Explorer/XCI.cs
index 6a22152..613597b 100644
--- a/XCI_Explorer/XCI.cs
+++ b/XCI_Explorer/XCI.cs
@@ -2,30 +2,29 @@ using System;
using System.Linq;
using System.Text;
-namespace XCI_Explorer
+namespace XCI_Explorer;
+
+public static class XCI
{
- public static class XCI
+ public class XCI_Header
{
- public class XCI_Header
+ public byte[] Data;
+ public string Magic;
+ public byte CardSize1;
+ public long CardSize2;
+ public long HFS0OffsetPartition;
+ public long HFS0SizeParition;
+
+ public XCI_Header(byte[] data)
{
- public byte[] Data;
- public string Magic;
- public byte CardSize1;
- public long CardSize2;
- public long HFS0OffsetPartition;
- public long HFS0SizeParition;
-
- public XCI_Header(byte[] data)
- {
- Data = data;
- Magic = Encoding.UTF8.GetString(Data.Skip(256).Take(4).ToArray());
- CardSize1 = Data[269];
- CardSize2 = BitConverter.ToInt64(data, 280);
- HFS0OffsetPartition = BitConverter.ToInt64(data, 304);
- HFS0SizeParition = BitConverter.ToInt64(data, 312);
- }
+ Data = data;
+ Magic = Encoding.UTF8.GetString(Data.Skip(256).Take(4).ToArray());
+ CardSize1 = Data[269];
+ CardSize2 = BitConverter.ToInt64(data, 280);
+ HFS0OffsetPartition = BitConverter.ToInt64(data, 304);
+ HFS0SizeParition = BitConverter.ToInt64(data, 312);
}
-
- public static XCI_Header[] XCI_Headers = new XCI_Header[1];
}
+
+ public static XCI_Header[] XCI_Headers = new XCI_Header[1];
}
diff --git a/XTSSharp/RandomAccessSectorStream.cs b/XTSSharp/RandomAccessSectorStream.cs
index 4ed6ed2..6361b40 100644
--- a/XTSSharp/RandomAccessSectorStream.cs
+++ b/XTSSharp/RandomAccessSectorStream.cs
@@ -1,195 +1,190 @@
using System;
using System.IO;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class RandomAccessSectorStream : Stream
{
- public class RandomAccessSectorStream : Stream
+ private readonly byte[] _buffer;
+ private readonly int _bufferSize;
+ private readonly SectorStream _s;
+ private readonly bool _isStreamOwned;
+ private bool _bufferDirty;
+ private bool _bufferLoaded;
+ private int _bufferPos;
+ public override bool CanRead => _s.CanRead;
+ public override bool CanSeek => _s.CanSeek;
+ public override bool CanWrite => _s.CanWrite;
+ public override long Length => _s.Length + _bufferPos;
+
+ public override long Position
{
- private readonly byte[] _buffer;
- private readonly int _bufferSize;
- private readonly SectorStream _s;
- private readonly bool _isStreamOwned;
- private bool _bufferDirty;
- private bool _bufferLoaded;
- private int _bufferPos;
- public override bool CanRead => _s.CanRead;
- public override bool CanSeek => _s.CanSeek;
- public override bool CanWrite => _s.CanWrite;
- public override long Length => _s.Length + _bufferPos;
-
- public override long Position {
- get {
- if (!_bufferLoaded)
- {
- return _s.Position + _bufferPos;
- }
- return _s.Position - _bufferSize + _bufferPos;
- }
- set {
- if (value < 0)
- {
- throw new ArgumentOutOfRangeException("value");
- }
- long num = value % _bufferSize;
- long position = value - num;
- if (_bufferLoaded)
- {
- long num2 = _s.Position - _bufferSize;
- if (value > num2 && value < num2 + _bufferSize)
- {
- _bufferPos = (int)num;
- return;
- }
- }
- if (_bufferDirty)
- {
- WriteSector();
- }
- _s.Position = position;
- ReadSector();
- _bufferPos = (int)num;
- }
- }
-
- public RandomAccessSectorStream(SectorStream s)
- : this(s, false)
+ get
{
- }
-
- public RandomAccessSectorStream(SectorStream s, bool isStreamOwned)
- {
- _s = s;
- _isStreamOwned = isStreamOwned;
- _buffer = new byte[s.SectorSize];
- _bufferSize = s.SectorSize;
- }
-
- protected override void Dispose(bool disposing)
- {
- Flush();
- base.Dispose(disposing);
- if (_isStreamOwned)
+ if (!_bufferLoaded)
{
- _s.Dispose();
+ return _s.Position + _bufferPos;
}
+ return _s.Position - _bufferSize + _bufferPos;
}
-
- public override void Flush()
+ set
{
+ if (value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+ long num = value % _bufferSize;
+ long position = value - num;
+ if (_bufferLoaded)
+ {
+ long num2 = _s.Position - _bufferSize;
+ if (value > num2 && value < num2 + _bufferSize)
+ {
+ _bufferPos = (int)num;
+ return;
+ }
+ }
if (_bufferDirty)
{
WriteSector();
}
+ _s.Position = position;
+ ReadSector();
+ _bufferPos = (int)num;
}
+ }
- public override long Seek(long offset, SeekOrigin origin)
+ public RandomAccessSectorStream(SectorStream s)
+ : this(s, false)
+ {
+ }
+
+ public RandomAccessSectorStream(SectorStream s, bool isStreamOwned)
+ {
+ _s = s;
+ _isStreamOwned = isStreamOwned;
+ _buffer = new byte[s.SectorSize];
+ _bufferSize = s.SectorSize;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ Flush();
+ base.Dispose(disposing);
+ if (_isStreamOwned)
{
- long num;
- switch (origin)
- {
- case SeekOrigin.Begin:
- num = offset;
- break;
- case SeekOrigin.End:
- num = Length - offset;
- break;
- default:
- num = Position + offset;
- break;
- }
- Position = num;
- return num;
+ _s.Dispose();
}
+ }
- public override void SetLength(long value)
+ public override void Flush()
+ {
+ if (_bufferDirty)
{
- long num = value % _s.SectorSize;
- if (num > 0)
- {
- value = value - num + _bufferSize;
- }
- _s.SetLength(value);
+ WriteSector();
}
+ }
- public override int Read(byte[] buffer, int offset, int count)
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ long num = origin switch
{
- long position = Position;
- if (position + count > _s.Length)
+ SeekOrigin.Begin => offset,
+ SeekOrigin.End => Length - offset,
+ _ => Position + offset,
+ };
+ Position = num;
+ return num;
+ }
+
+ public override void SetLength(long value)
+ {
+ long num = value % _s.SectorSize;
+ if (num > 0)
+ {
+ value = value - num + _bufferSize;
+ }
+ _s.SetLength(value);
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ long position = Position;
+ if (position + count > _s.Length)
+ {
+ count = (int)(_s.Length - position);
+ }
+ if (!_bufferLoaded)
+ {
+ ReadSector();
+ }
+ int num = 0;
+ while (count > 0)
+ {
+ int num2 = Math.Min(count, _bufferSize - _bufferPos);
+ Buffer.BlockCopy(_buffer, _bufferPos, buffer, offset, num2);
+ offset += num2;
+ _bufferPos += num2;
+ count -= num2;
+ num += num2;
+ if (_bufferPos == _bufferSize)
{
- count = (int)(_s.Length - position);
+ ReadSector();
}
+ }
+ return num;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ while (count > 0)
+ {
if (!_bufferLoaded)
{
ReadSector();
}
- int num = 0;
- while (count > 0)
- {
- int num2 = Math.Min(count, _bufferSize - _bufferPos);
- Buffer.BlockCopy(_buffer, _bufferPos, buffer, offset, num2);
- offset += num2;
- _bufferPos += num2;
- count -= num2;
- num += num2;
- if (_bufferPos == _bufferSize)
- {
- ReadSector();
- }
- }
- return num;
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- while (count > 0)
- {
- if (!_bufferLoaded)
- {
- ReadSector();
- }
- int num = Math.Min(count, _bufferSize - _bufferPos);
- Buffer.BlockCopy(buffer, offset, _buffer, _bufferPos, num);
- offset += num;
- _bufferPos += num;
- count -= num;
- _bufferDirty = true;
- if (_bufferPos == _bufferSize)
- {
- WriteSector();
- }
- }
- }
-
- private void ReadSector()
- {
- if (_bufferLoaded && _bufferDirty)
+ int num = Math.Min(count, _bufferSize - _bufferPos);
+ Buffer.BlockCopy(buffer, offset, _buffer, _bufferPos, num);
+ offset += num;
+ _bufferPos += num;
+ count -= num;
+ _bufferDirty = true;
+ if (_bufferPos == _bufferSize)
{
WriteSector();
}
- if (_s.Position != _s.Length)
- {
- int num = _s.Read(_buffer, 0, _buffer.Length);
- if (num != _bufferSize)
- {
- Array.Clear(_buffer, num, _buffer.Length - num);
- }
- _bufferLoaded = true;
- _bufferPos = 0;
- _bufferDirty = false;
- }
- }
-
- private void WriteSector()
- {
- if (_bufferLoaded)
- {
- _s.Seek(-_bufferSize, SeekOrigin.Current);
- }
- _s.Write(_buffer, 0, _bufferSize);
- _bufferDirty = false;
- _bufferLoaded = false;
- _bufferPos = 0;
- Array.Clear(_buffer, 0, _bufferSize);
}
}
+
+ private void ReadSector()
+ {
+ if (_bufferLoaded && _bufferDirty)
+ {
+ WriteSector();
+ }
+ if (_s.Position != _s.Length)
+ {
+ int num = _s.Read(_buffer, 0, _buffer.Length);
+ if (num != _bufferSize)
+ {
+ Array.Clear(_buffer, num, _buffer.Length - num);
+ }
+ _bufferLoaded = true;
+ _bufferPos = 0;
+ _bufferDirty = false;
+ }
+ }
+
+ private void WriteSector()
+ {
+ if (_bufferLoaded)
+ {
+ _s.Seek(-_bufferSize, SeekOrigin.Current);
+ }
+ _s.Write(_buffer, 0, _bufferSize);
+ _bufferDirty = false;
+ _bufferLoaded = false;
+ _bufferPos = 0;
+ Array.Clear(_buffer, 0, _bufferSize);
+ }
}
diff --git a/XTSSharp/SectorStream.cs b/XTSSharp/SectorStream.cs
index c6a5bb9..70506fc 100644
--- a/XTSSharp/SectorStream.cs
+++ b/XTSSharp/SectorStream.cs
@@ -1,119 +1,115 @@
using System;
using System.IO;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class SectorStream : Stream
{
- public class SectorStream : Stream
+ private readonly Stream _baseStream;
+ private readonly long _offset;
+ private ulong _currentSector;
+
+ public int SectorSize
{
- private readonly Stream _baseStream;
- private readonly long _offset;
- private ulong _currentSector;
+ get;
+ private set;
+ }
- public int SectorSize {
- get;
- private set;
- }
+ public override bool CanRead => _baseStream.CanRead;
+ public override bool CanSeek => _baseStream.CanSeek;
+ public override bool CanWrite => _baseStream.CanWrite;
+ public override long Length => _baseStream.Length - _offset;
- public override bool CanRead => _baseStream.CanRead;
- public override bool CanSeek => _baseStream.CanSeek;
- public override bool CanWrite => _baseStream.CanWrite;
- public override long Length => _baseStream.Length - _offset;
-
- public override long Position {
- get {
- return _baseStream.Position - _offset;
- }
- set {
- ValidateSizeMultiple(value);
- _baseStream.Position = value + _offset;
- _currentSector = (ulong)(value / SectorSize);
- }
- }
-
- protected ulong CurrentSector => _currentSector;
-
- public SectorStream(Stream baseStream, int sectorSize)
- : this(baseStream, sectorSize, 0L)
+ public override long Position
+ {
+ get
{
+ return _baseStream.Position - _offset;
}
-
- public SectorStream(Stream baseStream, int sectorSize, long offset)
- {
- SectorSize = sectorSize;
- _baseStream = baseStream;
- _offset = offset;
- }
-
- private void ValidateSizeMultiple(long value)
- {
- if (value % SectorSize == 0L)
- {
- return;
- }
- throw new ArgumentException($"Value needs to be a multiple of {SectorSize}");
- }
-
- protected void ValidateSize(long value)
- {
- if (value == SectorSize)
- {
- return;
- }
- throw new ArgumentException($"Value needs to be {SectorSize}");
- }
-
- protected void ValidateSize(int value)
- {
- if (value == SectorSize)
- {
- return;
- }
- throw new ArgumentException($"Value needs to be {SectorSize}");
- }
-
- public override void Flush()
- {
- _baseStream.Flush();
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- long num;
- switch (origin)
- {
- case SeekOrigin.Begin:
- num = offset;
- break;
- case SeekOrigin.End:
- num = Length - offset;
- break;
- default:
- num = Position + offset;
- break;
- }
- Position = num;
- return num;
- }
-
- public override void SetLength(long value)
+ set
{
ValidateSizeMultiple(value);
- _baseStream.SetLength(value);
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- ValidateSize(count);
- int result = _baseStream.Read(buffer, offset, count);
- _currentSector++;
- return result;
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- ValidateSize(count);
- _baseStream.Write(buffer, offset, count);
- _currentSector++;
+ _baseStream.Position = value + _offset;
+ _currentSector = (ulong)(value / SectorSize);
}
}
+
+ protected ulong CurrentSector => _currentSector;
+
+ public SectorStream(Stream baseStream, int sectorSize)
+ : this(baseStream, sectorSize, 0L)
+ {
+ }
+
+ public SectorStream(Stream baseStream, int sectorSize, long offset)
+ {
+ SectorSize = sectorSize;
+ _baseStream = baseStream;
+ _offset = offset;
+ }
+
+ private void ValidateSizeMultiple(long value)
+ {
+ if (value % SectorSize == 0L)
+ {
+ return;
+ }
+ throw new ArgumentException($"Value needs to be a multiple of {SectorSize}");
+ }
+
+ protected void ValidateSize(long value)
+ {
+ if (value == SectorSize)
+ {
+ return;
+ }
+ throw new ArgumentException($"Value needs to be {SectorSize}");
+ }
+
+ protected void ValidateSize(int value)
+ {
+ if (value == SectorSize)
+ {
+ return;
+ }
+ throw new ArgumentException($"Value needs to be {SectorSize}");
+ }
+
+ public override void Flush()
+ {
+ _baseStream.Flush();
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ long num = origin switch
+ {
+ SeekOrigin.Begin => offset,
+ SeekOrigin.End => Length - offset,
+ _ => Position + offset,
+ };
+ Position = num;
+ return num;
+ }
+
+ public override void SetLength(long value)
+ {
+ ValidateSizeMultiple(value);
+ _baseStream.SetLength(value);
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ ValidateSize(count);
+ int result = _baseStream.Read(buffer, offset, count);
+ _currentSector++;
+ return result;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ ValidateSize(count);
+ _baseStream.Write(buffer, offset, count);
+ _currentSector++;
+ }
}
diff --git a/XTSSharp/Xts.cs b/XTSSharp/Xts.cs
index 7a1fa13..04391b8 100644
--- a/XTSSharp/Xts.cs
+++ b/XTSSharp/Xts.cs
@@ -1,66 +1,65 @@
using System;
using System.Security.Cryptography;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class Xts
{
- public class Xts
+ private readonly SymmetricAlgorithm _key1;
+ private readonly SymmetricAlgorithm _key2;
+
+ protected Xts(Func create, byte[] key1, byte[] key2)
{
- private readonly SymmetricAlgorithm _key1;
- private readonly SymmetricAlgorithm _key2;
-
- protected Xts(Func create, byte[] key1, byte[] key2)
+ if (create == null)
{
- if (create == null)
- {
- throw new ArgumentNullException("create");
- }
- if (key1 == null)
- {
- throw new ArgumentNullException("key1");
- }
- if (key2 == null)
- {
- throw new ArgumentNullException("key2");
- }
- _key1 = create();
- _key2 = create();
- if (key1.Length != key2.Length)
- {
- throw new ArgumentException("Key lengths don't match");
- }
- _key1.KeySize = key1.Length * 8;
- _key2.KeySize = key2.Length * 8;
- _key1.Key = key1;
- _key2.Key = key2;
- _key1.Mode = CipherMode.ECB;
- _key2.Mode = CipherMode.ECB;
- _key1.Padding = PaddingMode.None;
- _key2.Padding = PaddingMode.None;
- _key1.BlockSize = 128;
- _key2.BlockSize = 128;
+ throw new ArgumentNullException(nameof(create));
}
-
- public XtsCryptoTransform CreateEncryptor()
+ if (key1 == null)
{
- return new XtsCryptoTransform(_key1.CreateEncryptor(), _key2.CreateEncryptor(), false);
+ throw new ArgumentNullException(nameof(key1));
}
-
- public XtsCryptoTransform CreateDecryptor()
+ if (key2 == null)
{
- return new XtsCryptoTransform(_key1.CreateDecryptor(), _key2.CreateEncryptor(), true);
+ throw new ArgumentNullException(nameof(key2));
}
-
- protected static byte[] VerifyKey(int expectedSize, byte[] key)
+ _key1 = create();
+ _key2 = create();
+ if (key1.Length != key2.Length)
{
- if (key == null)
- {
- throw new ArgumentNullException("key");
- }
- if (key.Length * 8 != expectedSize)
- {
- throw new ArgumentException($"Expected key length of {expectedSize} bits, got {key.Length * 8}");
- }
- return key;
+ throw new ArgumentException("Key lengths don't match");
}
+ _key1.KeySize = key1.Length * 8;
+ _key2.KeySize = key2.Length * 8;
+ _key1.Key = key1;
+ _key2.Key = key2;
+ _key1.Mode = CipherMode.ECB;
+ _key2.Mode = CipherMode.ECB;
+ _key1.Padding = PaddingMode.None;
+ _key2.Padding = PaddingMode.None;
+ _key1.BlockSize = 128;
+ _key2.BlockSize = 128;
+ }
+
+ public XtsCryptoTransform CreateEncryptor()
+ {
+ return new XtsCryptoTransform(_key1.CreateEncryptor(), _key2.CreateEncryptor(), false);
+ }
+
+ public XtsCryptoTransform CreateDecryptor()
+ {
+ return new XtsCryptoTransform(_key1.CreateDecryptor(), _key2.CreateEncryptor(), true);
+ }
+
+ protected static byte[] VerifyKey(int expectedSize, byte[] key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key));
+ }
+ if (key.Length * 8 != expectedSize)
+ {
+ throw new ArgumentException($"Expected key length of {expectedSize} bits, got {key.Length * 8}");
+ }
+ return key;
}
}
diff --git a/XTSSharp/XtsAes128.cs b/XTSSharp/XtsAes128.cs
index 5b1df9d..a8b242b 100644
--- a/XTSSharp/XtsAes128.cs
+++ b/XTSSharp/XtsAes128.cs
@@ -1,33 +1,32 @@
using System;
using System.Security.Cryptography;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class XtsAes128 : Xts
{
- public class XtsAes128 : Xts
+ private const int KEY_LENGTH = 128;
+ private const int KEY_BYTE_LENGTH = 16;
+
+ protected XtsAes128(Func create, byte[] key1, byte[] key2)
+ : base(create, VerifyKey(128, key1), VerifyKey(128, key2))
{
- private const int KEY_LENGTH = 128;
- private const int KEY_BYTE_LENGTH = 16;
+ }
- protected XtsAes128(Func create, byte[] key1, byte[] key2)
- : base(create, Xts.VerifyKey(128, key1), Xts.VerifyKey(128, key2))
- {
- }
+ public static Xts Create(byte[] key1, byte[] key2)
+ {
+ VerifyKey(128, key1);
+ VerifyKey(128, key2);
+ return new XtsAes128(Aes.Create, key1, key2);
+ }
- public static Xts Create(byte[] key1, byte[] key2)
- {
- Xts.VerifyKey(128, key1);
- Xts.VerifyKey(128, key2);
- return new XtsAes128(Aes.Create, key1, key2);
- }
-
- public static Xts Create(byte[] key)
- {
- Xts.VerifyKey(256, key);
- byte[] array = new byte[16];
- byte[] array2 = new byte[16];
- Buffer.BlockCopy(key, 0, array, 0, 16);
- Buffer.BlockCopy(key, 16, array2, 0, 16);
- return new XtsAes128(Aes.Create, array, array2);
- }
+ public static Xts Create(byte[] key)
+ {
+ VerifyKey(256, key);
+ byte[] array = new byte[16];
+ byte[] array2 = new byte[16];
+ Buffer.BlockCopy(key, 0, array, 0, 16);
+ Buffer.BlockCopy(key, 16, array2, 0, 16);
+ return new XtsAes128(Aes.Create, array, array2);
}
}
diff --git a/XTSSharp/XtsAes256.cs b/XTSSharp/XtsAes256.cs
index fd789c0..98f3eae 100644
--- a/XTSSharp/XtsAes256.cs
+++ b/XTSSharp/XtsAes256.cs
@@ -1,33 +1,32 @@
using System;
using System.Security.Cryptography;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class XtsAes256 : Xts
{
- public class XtsAes256 : Xts
+ private const int KEY_LENGTH = 256;
+ private const int KEY_BYTE_LENGTH = 32;
+
+ protected XtsAes256(Func create, byte[] key1, byte[] key2)
+ : base(create, VerifyKey(256, key1), VerifyKey(256, key2))
{
- private const int KEY_LENGTH = 256;
- private const int KEY_BYTE_LENGTH = 32;
+ }
- protected XtsAes256(Func create, byte[] key1, byte[] key2)
- : base(create, Xts.VerifyKey(256, key1), Xts.VerifyKey(256, key2))
- {
- }
+ public static Xts Create(byte[] key1, byte[] key2)
+ {
+ VerifyKey(256, key1);
+ VerifyKey(256, key2);
+ return new XtsAes256(Aes.Create, key1, key2);
+ }
- public static Xts Create(byte[] key1, byte[] key2)
- {
- Xts.VerifyKey(256, key1);
- Xts.VerifyKey(256, key2);
- return new XtsAes256(Aes.Create, key1, key2);
- }
-
- public static Xts Create(byte[] key)
- {
- Xts.VerifyKey(512, key);
- byte[] array = new byte[32];
- byte[] array2 = new byte[32];
- Buffer.BlockCopy(key, 0, array, 0, 32);
- Buffer.BlockCopy(key, 32, array2, 0, 32);
- return new XtsAes256(Aes.Create, array, array2);
- }
+ public static Xts Create(byte[] key)
+ {
+ VerifyKey(512, key);
+ byte[] array = new byte[32];
+ byte[] array2 = new byte[32];
+ Buffer.BlockCopy(key, 0, array, 0, 32);
+ Buffer.BlockCopy(key, 32, array2, 0, 32);
+ return new XtsAes256(Aes.Create, array, array2);
}
}
diff --git a/XTSSharp/XtsCryptoTransform.cs b/XTSSharp/XtsCryptoTransform.cs
index 64a2daf..e9b76b5 100644
--- a/XTSSharp/XtsCryptoTransform.cs
+++ b/XTSSharp/XtsCryptoTransform.cs
@@ -1,142 +1,141 @@
using System;
using System.Security.Cryptography;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class XtsCryptoTransform : IDisposable
{
- public class XtsCryptoTransform : IDisposable
+ private readonly byte[] _cc = new byte[16];
+ private readonly bool _decrypting;
+ private readonly ICryptoTransform _key1;
+ private readonly ICryptoTransform _key2;
+ private readonly byte[] _pp = new byte[16];
+ private readonly byte[] _t = new byte[16];
+ private readonly byte[] _tweak = new byte[16];
+
+ public XtsCryptoTransform(ICryptoTransform key1, ICryptoTransform key2, bool decrypting)
{
- private readonly byte[] _cc = new byte[16];
- private readonly bool _decrypting;
- private readonly ICryptoTransform _key1;
- private readonly ICryptoTransform _key2;
- private readonly byte[] _pp = new byte[16];
- private readonly byte[] _t = new byte[16];
- private readonly byte[] _tweak = new byte[16];
-
- public XtsCryptoTransform(ICryptoTransform key1, ICryptoTransform key2, bool decrypting)
+ if (key1 == null)
{
- if (key1 == null)
- {
- throw new ArgumentNullException("key1");
- }
- if (key2 == null)
- {
- throw new ArgumentNullException("key2");
- }
- _key1 = key1;
- _key2 = key2;
- _decrypting = decrypting;
+ throw new ArgumentNullException(nameof(key1));
}
-
- public void Dispose()
+ if (key2 == null)
{
- _key1.Dispose();
- _key2.Dispose();
+ throw new ArgumentNullException(nameof(key2));
}
+ _key1 = key1;
+ _key2 = key2;
+ _decrypting = decrypting;
+ }
- public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, ulong sector)
+ public void Dispose()
+ {
+ _key1.Dispose();
+ _key2.Dispose();
+ }
+
+ public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, ulong sector)
+ {
+ FillArrayFromSectorLittleEndian(_tweak, sector);
+ int num = inputCount >> 4;
+ int num2 = inputCount & 0xF;
+ _key2.TransformBlock(_tweak, 0, _tweak.Length, _t, 0);
+ int num3 = (num2 != 0) ? (num - 1) : num;
+ for (int i = 0; i < num3; i++)
{
- FillArrayFromSectorLittleEndian(_tweak, sector);
- int num = inputCount >> 4;
- int num2 = inputCount & 0xF;
- _key2.TransformBlock(_tweak, 0, _tweak.Length, _t, 0);
- int num3 = (num2 != 0) ? (num - 1) : num;
- for (int i = 0; i < num3; i++)
+ TweakCrypt(inputBuffer, inputOffset, outputBuffer, outputOffset, _t);
+ inputOffset += 16;
+ outputOffset += 16;
+ }
+ if (num2 > 0)
+ {
+ if (_decrypting)
{
- TweakCrypt(inputBuffer, inputOffset, outputBuffer, outputOffset, _t);
- inputOffset += 16;
- outputOffset += 16;
- }
- if (num2 > 0)
- {
- if (_decrypting)
+ Buffer.BlockCopy(_t, 0, _cc, 0, 16);
+ MultiplyByX(_cc);
+ TweakCrypt(inputBuffer, inputOffset, _pp, 0, _cc);
+ int j;
+ for (j = 0; j < num2; j++)
{
- Buffer.BlockCopy(_t, 0, _cc, 0, 16);
- MultiplyByX(_cc);
- TweakCrypt(inputBuffer, inputOffset, _pp, 0, _cc);
- int j;
- for (j = 0; j < num2; j++)
- {
- _cc[j] = inputBuffer[16 + j + inputOffset];
- outputBuffer[16 + j + outputOffset] = _pp[j];
- }
- for (; j < 16; j++)
- {
- _cc[j] = _pp[j];
- }
- TweakCrypt(_cc, 0, outputBuffer, outputOffset, _t);
+ _cc[j] = inputBuffer[16 + j + inputOffset];
+ outputBuffer[16 + j + outputOffset] = _pp[j];
}
- else
+ for (; j < 16; j++)
{
- TweakCrypt(inputBuffer, inputOffset, _cc, 0, _t);
- int k;
- for (k = 0; k < num2; k++)
- {
- _pp[k] = inputBuffer[16 + k + inputOffset];
- outputBuffer[16 + k + outputOffset] = _cc[k];
- }
- for (; k < 16; k++)
- {
- _pp[k] = _cc[k];
- }
- TweakCrypt(_pp, 0, outputBuffer, outputOffset, _t);
+ _cc[j] = _pp[j];
}
+ TweakCrypt(_cc, 0, outputBuffer, outputOffset, _t);
}
- return inputCount;
- }
-
- private static void FillArrayFromSectorBigEndian(byte[] value, ulong sector)
- {
- value[7] = (byte)((sector >> 56) & 0xFF);
- value[6] = (byte)((sector >> 48) & 0xFF);
- value[5] = (byte)((sector >> 40) & 0xFF);
- value[4] = (byte)((sector >> 32) & 0xFF);
- value[3] = (byte)((sector >> 24) & 0xFF);
- value[2] = (byte)((sector >> 16) & 0xFF);
- value[1] = (byte)((sector >> 8) & 0xFF);
- value[0] = (byte)(sector & 0xFF);
- }
-
- private static void FillArrayFromSectorLittleEndian(byte[] value, ulong sector)
- {
- value[8] = (byte)((sector >> 56) & 0xFF);
- value[9] = (byte)((sector >> 48) & 0xFF);
- value[10] = (byte)((sector >> 40) & 0xFF);
- value[11] = (byte)((sector >> 32) & 0xFF);
- value[12] = (byte)((sector >> 24) & 0xFF);
- value[13] = (byte)((sector >> 16) & 0xFF);
- value[14] = (byte)((sector >> 8) & 0xFF);
- value[15] = (byte)(sector & 0xFF);
- }
-
- private void TweakCrypt(byte[] inputBuffer, int inputOffset, byte[] outputBuffer, int outputOffset, byte[] t)
- {
- for (int i = 0; i < 16; i++)
+ else
{
- outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ t[i]);
+ TweakCrypt(inputBuffer, inputOffset, _cc, 0, _t);
+ int k;
+ for (k = 0; k < num2; k++)
+ {
+ _pp[k] = inputBuffer[16 + k + inputOffset];
+ outputBuffer[16 + k + outputOffset] = _cc[k];
+ }
+ for (; k < 16; k++)
+ {
+ _pp[k] = _cc[k];
+ }
+ TweakCrypt(_pp, 0, outputBuffer, outputOffset, _t);
}
- _key1.TransformBlock(outputBuffer, outputOffset, 16, outputBuffer, outputOffset);
- for (int j = 0; j < 16; j++)
- {
- outputBuffer[j + outputOffset] = (byte)(outputBuffer[j + outputOffset] ^ t[j]);
- }
- MultiplyByX(t);
}
+ return inputCount;
+ }
- private static void MultiplyByX(byte[] i)
+ private static void FillArrayFromSectorBigEndian(byte[] value, ulong sector)
+ {
+ value[7] = (byte)((sector >> 56) & 0xFF);
+ value[6] = (byte)((sector >> 48) & 0xFF);
+ value[5] = (byte)((sector >> 40) & 0xFF);
+ value[4] = (byte)((sector >> 32) & 0xFF);
+ value[3] = (byte)((sector >> 24) & 0xFF);
+ value[2] = (byte)((sector >> 16) & 0xFF);
+ value[1] = (byte)((sector >> 8) & 0xFF);
+ value[0] = (byte)(sector & 0xFF);
+ }
+
+ private static void FillArrayFromSectorLittleEndian(byte[] value, ulong sector)
+ {
+ value[8] = (byte)((sector >> 56) & 0xFF);
+ value[9] = (byte)((sector >> 48) & 0xFF);
+ value[10] = (byte)((sector >> 40) & 0xFF);
+ value[11] = (byte)((sector >> 32) & 0xFF);
+ value[12] = (byte)((sector >> 24) & 0xFF);
+ value[13] = (byte)((sector >> 16) & 0xFF);
+ value[14] = (byte)((sector >> 8) & 0xFF);
+ value[15] = (byte)(sector & 0xFF);
+ }
+
+ private void TweakCrypt(byte[] inputBuffer, int inputOffset, byte[] outputBuffer, int outputOffset, byte[] t)
+ {
+ for (int i = 0; i < 16; i++)
{
- byte b = 0;
- byte b2 = 0;
- for (int j = 0; j < 16; j++)
- {
- b2 = (byte)(i[j] >> 7);
- i[j] = (byte)(((i[j] << 1) | b) & 0xFF);
- b = b2;
- }
- if (b2 > 0)
- {
- i[0] ^= 135;
- }
+ outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ t[i]);
+ }
+ _key1.TransformBlock(outputBuffer, outputOffset, 16, outputBuffer, outputOffset);
+ for (int j = 0; j < 16; j++)
+ {
+ outputBuffer[j + outputOffset] = (byte)(outputBuffer[j + outputOffset] ^ t[j]);
+ }
+ MultiplyByX(t);
+ }
+
+ private static void MultiplyByX(byte[] i)
+ {
+ byte b = 0;
+ byte b2 = 0;
+ for (int j = 0; j < 16; j++)
+ {
+ b2 = (byte)(i[j] >> 7);
+ i[j] = (byte)(((i[j] << 1) | b) & 0xFF);
+ b = b2;
+ }
+ if (b2 > 0)
+ {
+ i[0] ^= 135;
}
}
}
diff --git a/XTSSharp/XtsSectorStream.cs b/XTSSharp/XtsSectorStream.cs
index 3ec039b..2e85eba 100644
--- a/XTSSharp/XtsSectorStream.cs
+++ b/XTSSharp/XtsSectorStream.cs
@@ -1,74 +1,73 @@
using System.IO;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class XtsSectorStream : SectorStream
{
- public class XtsSectorStream : SectorStream
+ public const int DEFAULT_SECTOR_SIZE = 512;
+ private readonly byte[] _tempBuffer;
+ private readonly Xts _xts;
+ private XtsCryptoTransform _decryptor;
+ private XtsCryptoTransform _encryptor;
+
+ public XtsSectorStream(Stream baseStream, Xts xts)
+ : this(baseStream, xts, 512)
{
- public const int DEFAULT_SECTOR_SIZE = 512;
- private readonly byte[] _tempBuffer;
- private readonly Xts _xts;
- private XtsCryptoTransform _decryptor;
- private XtsCryptoTransform _encryptor;
+ }
- public XtsSectorStream(Stream baseStream, Xts xts)
- : this(baseStream, xts, 512)
+ public XtsSectorStream(Stream baseStream, Xts xts, int sectorSize)
+ : this(baseStream, xts, sectorSize, 0L)
+ {
+ }
+
+ public XtsSectorStream(Stream baseStream, Xts xts, int sectorSize, long offset)
+ : base(baseStream, sectorSize, offset)
+ {
+ _xts = xts;
+ _tempBuffer = new byte[sectorSize];
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (_encryptor != null)
{
+ _encryptor.Dispose();
}
-
- public XtsSectorStream(Stream baseStream, Xts xts, int sectorSize)
- : this(baseStream, xts, sectorSize, 0L)
+ if (_decryptor != null)
{
- }
-
- public XtsSectorStream(Stream baseStream, Xts xts, int sectorSize, long offset)
- : base(baseStream, sectorSize, offset)
- {
- _xts = xts;
- _tempBuffer = new byte[sectorSize];
- }
-
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- if (_encryptor != null)
- {
- _encryptor.Dispose();
- }
- if (_decryptor != null)
- {
- _decryptor.Dispose();
- }
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- ValidateSize(count);
- if (count != 0)
- {
- ulong currentSector = base.CurrentSector;
- if (_encryptor == null)
- {
- _encryptor = _xts.CreateEncryptor();
- }
- int count2 = _encryptor.TransformBlock(buffer, offset, count, _tempBuffer, 0, currentSector);
- base.Write(_tempBuffer, 0, count2);
- }
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- ValidateSize(count);
- ulong currentSector = base.CurrentSector;
- int num = base.Read(_tempBuffer, 0, count);
- if (num == 0)
- {
- return 0;
- }
- if (_decryptor == null)
- {
- _decryptor = _xts.CreateDecryptor();
- }
- return _decryptor.TransformBlock(_tempBuffer, 0, num, buffer, offset, currentSector);
+ _decryptor.Dispose();
}
}
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ ValidateSize(count);
+ if (count != 0)
+ {
+ ulong currentSector = base.CurrentSector;
+ if (_encryptor == null)
+ {
+ _encryptor = _xts.CreateEncryptor();
+ }
+ int count2 = _encryptor.TransformBlock(buffer, offset, count, _tempBuffer, 0, currentSector);
+ base.Write(_tempBuffer, 0, count2);
+ }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ ValidateSize(count);
+ ulong currentSector = base.CurrentSector;
+ int num = base.Read(_tempBuffer, 0, count);
+ if (num == 0)
+ {
+ return 0;
+ }
+ if (_decryptor == null)
+ {
+ _decryptor = _xts.CreateDecryptor();
+ }
+ return _decryptor.TransformBlock(_tempBuffer, 0, num, buffer, offset, currentSector);
+ }
}
diff --git a/XTSSharp/XtsStream.cs b/XTSSharp/XtsStream.cs
index f17bd1a..58d248c 100644
--- a/XTSSharp/XtsStream.cs
+++ b/XTSSharp/XtsStream.cs
@@ -1,22 +1,21 @@
using System.IO;
-namespace XTSSharp
+namespace XTSSharp;
+
+public class XtsStream : RandomAccessSectorStream
{
- public class XtsStream : RandomAccessSectorStream
+ public XtsStream(Stream baseStream, Xts xts)
+ : this(baseStream, xts, 512)
{
- public XtsStream(Stream baseStream, Xts xts)
- : this(baseStream, xts, 512)
- {
- }
+ }
- public XtsStream(Stream baseStream, Xts xts, int sectorSize)
- : base(new XtsSectorStream(baseStream, xts, sectorSize), true)
- {
- }
+ public XtsStream(Stream baseStream, Xts xts, int sectorSize)
+ : base(new XtsSectorStream(baseStream, xts, sectorSize), true)
+ {
+ }
- public XtsStream(Stream baseStream, Xts xts, int sectorSize, long offset)
- : base(new XtsSectorStream(baseStream, xts, sectorSize, offset), true)
- {
- }
+ public XtsStream(Stream baseStream, Xts xts, int sectorSize, long offset)
+ : base(new XtsSectorStream(baseStream, xts, sectorSize, offset), true)
+ {
}
}