diff --git a/NDecrypt/N3DS/CIATool.cs b/NDecrypt/N3DS/CIATool.cs
new file mode 100644
index 0000000..61e6f2d
--- /dev/null
+++ b/NDecrypt/N3DS/CIATool.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using NDecrypt.N3DS.Headers;
+
+namespace NDecrypt.N3DS
+{
+ // https://www.3dbrew.org/wiki/CIA
+ internal class CIATool : ITool
+ {
+ ///
+ /// Name of the input CIA file
+ ///
+ private readonly string filename;
+
+ ///
+ /// Flag to detrmine if development keys should be used
+ ///
+ private readonly bool development;
+
+ ///
+ /// Flag to determine if encrypting or decrypting
+ ///
+ private readonly bool encrypt;
+
+ ///
+ /// Flag to determine if forcing operations
+ ///
+ private readonly bool force;
+
+ public CIATool(string filename, bool development, bool encrypt, bool force)
+ {
+ this.filename = filename;
+ this.development = development;
+ this.encrypt = encrypt;
+ this.force = force;
+ }
+
+ #region Common Methods
+
+ ///
+ /// Process an input file given the input values
+ ///
+ public bool ProcessFile()
+ {
+ // Ensure the constants are all set
+ Constants.Init();
+ if (Constants.IsReady != true)
+ {
+ Console.WriteLine("Could not read keys from keys.bin. Please make sure the file exists and try again.");
+ return false;
+ }
+
+ try
+ {
+ // Open the read and write on the same file for inplace processing
+ using (BinaryReader reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
+ using (BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)))
+ {
+ CIAHeader header = CIAHeader.Read(reader);
+ if (header == null)
+ {
+ Console.WriteLine("Error: Not a 3DS Rom!");
+ return false;
+ }
+
+ // TODO: Implement CIA encrypt/decrypt
+ return false;
+ }
+ }
+ catch
+ {
+ Console.WriteLine($"An error has occurred. {filename} may be corrupted if it was partially processed.");
+ Console.WriteLine("Please check that the file was a valid 3DS or New 3DS file and try again.");
+ return false;
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/NDecrypt/N3DS/Headers/CIAHeader.cs b/NDecrypt/N3DS/Headers/CIAHeader.cs
new file mode 100644
index 0000000..748585a
--- /dev/null
+++ b/NDecrypt/N3DS/Headers/CIAHeader.cs
@@ -0,0 +1,114 @@
+using System.IO;
+
+namespace NDecrypt.N3DS.Headers
+{
+ internal class CIAHeader
+ {
+ ///
+ /// Archive header size, usually 0x2020 bytes
+ ///
+ public uint HeaderSize { get; private set; }
+
+ ///
+ /// Type
+ ///
+ public ushort Type { get; private set; }
+
+ ///
+ /// Version
+ ///
+ public ushort Version { get; private set; }
+
+ ///
+ /// Certificate chain size
+ ///
+ public int CertificateChainSize { get; private set; }
+
+ ///
+ /// Ticket size
+ ///
+ public int TicketSize { get; private set; }
+
+ ///
+ /// TMD file size
+ ///
+ public int TMDFileSize { get; private set; }
+
+ ///
+ /// Meta size (0 if no Meta data is present)
+ ///
+ public int MetaSize { get; private set; }
+
+ ///
+ /// Content size
+ ///
+ public long ContentSize { get; private set; }
+
+ ///
+ /// Content Index
+ ///
+ public byte[] ContentIndex { get; private set; }
+
+ ///
+ /// Certificate chain
+ ///
+ public byte[] CertificateChain { get; set; }
+
+ ///
+ /// Ticket
+ ///
+ public byte[] Ticket { get; set; }
+
+ ///
+ /// TMD file data
+ ///
+ public byte[] TMDFileData { get; set; }
+
+ ///
+ /// Content file data
+ ///
+ public byte[] ContentFileData { get; set; }
+
+ ///
+ /// Meta file data (Not a necessary component)
+ ///
+ public MetaFile MetaFileData { get; set; }
+
+ ///
+ /// Read from a stream and get a CIA header, if possible
+ ///
+ /// BinaryReader representing the input stream
+ /// CIA header object, null on error
+ public static CIAHeader Read(BinaryReader reader)
+ {
+ CIAHeader header = new CIAHeader();
+
+ try
+ {
+ header.HeaderSize = reader.ReadUInt32();
+ header.Type = reader.ReadUInt16();
+ header.Version = reader.ReadUInt16();
+ header.CertificateChainSize = reader.ReadInt32();
+ header.TicketSize = reader.ReadInt32();
+ header.TMDFileSize = reader.ReadInt32();
+ header.MetaSize = reader.ReadInt32();
+ header.ContentSize = reader.ReadInt64();
+ header.ContentIndex = reader.ReadBytes(0x2000);
+
+ header.CertificateChain = reader.ReadBytes(header.CertificateChainSize);
+ header.Ticket = reader.ReadBytes(header.TicketSize);
+ header.TMDFileData = reader.ReadBytes(header.TMDFileSize);
+ header.ContentFileData = reader.ReadBytes((int)header.ContentSize);
+
+ if (header.MetaSize > 0)
+ header.MetaFileData = MetaFile.Read(reader);
+
+ return header;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NDecrypt/N3DS/Headers/MetaFile.cs b/NDecrypt/N3DS/Headers/MetaFile.cs
new file mode 100644
index 0000000..8625550
--- /dev/null
+++ b/NDecrypt/N3DS/Headers/MetaFile.cs
@@ -0,0 +1,57 @@
+using System.IO;
+
+namespace NDecrypt.N3DS.Headers
+{
+ internal class MetaFile
+ {
+ ///
+ /// Title ID dependency list - Taken from the application's ExHeader
+ ///
+ public byte[] TitleIDDependencyList { get; private set; }
+
+ ///
+ /// Reserved
+ ///
+ public byte[] Reserved1 { get; private set; }
+
+ ///
+ /// Core Version
+ ///
+ public uint CoreVersion { get; private set; }
+
+ ///
+ /// Reserved
+ ///
+ public byte[] Reserved2 { get; private set; }
+
+ ///
+ /// Icon Data(.ICN) - Taken from the application's ExeFS
+ ///
+ public byte[] IconData { get; private set; }
+
+ ///
+ /// Read from a stream and get the Metafile data, if possible
+ ///
+ /// BinaryReader representing the input stream
+ /// Metafile data object, null on error
+ public static MetaFile Read(BinaryReader reader)
+ {
+ MetaFile metaFile = new MetaFile();
+
+ try
+ {
+ metaFile.TitleIDDependencyList = reader.ReadBytes(0x180);
+ metaFile.Reserved1 = reader.ReadBytes(0x180);
+ metaFile.CoreVersion = reader.ReadUInt32();
+ metaFile.Reserved2 = reader.ReadBytes(0xFC);
+ metaFile.IconData = reader.ReadBytes(0x36C0);
+
+ return metaFile;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NDecrypt/Program.cs b/NDecrypt/Program.cs
index eabb6b2..ec847c2 100644
--- a/NDecrypt/Program.cs
+++ b/NDecrypt/Program.cs
@@ -18,6 +18,7 @@ namespace NDecrypt
iQueDS,
N3DS,
iQue3DS,
+ N3DSCIA,
}
public static void Main(string[] args)
@@ -139,6 +140,9 @@ More than one path can be specified at a time.");
case FileType.N3DS:
Console.WriteLine("File recognized as Nintendo 3DS");
return new ThreeDSTool(filename, development, encrypt, force);
+ // case FileType.N3DSCIA:
+ // Console.WriteLine("File recognized as Nintendo 3DS");
+ // return new CIATool(filename, development, encrypt, force);
case FileType.NULL:
default:
Console.WriteLine($"Unrecognized file format for {filename}. Expected *.nds, *.srl, *.dsi, *.3ds");
@@ -165,6 +169,9 @@ More than one path can be specified at a time.");
else if (filename.EndsWith(".3ds", StringComparison.OrdinalIgnoreCase))
return FileType.N3DS;
+
+ else if (filename.EndsWith(".cia", StringComparison.OrdinalIgnoreCase))
+ return FileType.N3DSCIA;
return FileType.NULL;
}