/// <summary> /// Process secure area in the DS/DSi file /// </summary> /// <param name="ndsHeader">NDS header representing the DS file</param> /// <param name="reader">BinaryReader representing the input stream</param> /// <param name="writer">BinaryWriter representing the output stream</param> private void ProcessSecureArea(NDSHeader ndsHeader, BinaryReader reader, BinaryWriter writer) { // If we're forcing the operation, tell the user if (decryptArgs.Force) { Console.WriteLine("File is not verified due to force flag being set."); } // If we're not forcing the operation, check to see if we should be proceeding else { bool?isDecrypted = CheckIfDecrypted(reader); if (isDecrypted == null) { Console.WriteLine("File has an empty secure area, cannot proceed"); return; } else if (decryptArgs.Encrypt ^ isDecrypted.Value) { Console.WriteLine("File is already " + (decryptArgs.Encrypt ? "encrypted" : "decrypted")); return; } } ProcessARM9(ndsHeader, reader, writer); Console.WriteLine("File has been " + (decryptArgs.Encrypt ? "encrypted" : "decrypted")); }
/// <summary> /// First common initialization step /// </summary> /// <param name="ndsHeader">NDS header representing the DS file</param> private void Init1(NDSHeader ndsHeader) { Buffer.BlockCopy(Constants.NDSEncryptionData, 0, cardHash, 0, 4 * (1024 + 18)); arg2 = new uint[] { ndsHeader.Gamecode, ndsHeader.Gamecode >> 1, ndsHeader.Gamecode << 1 }; Init2(); Init2(); }
/// <summary> /// Process an input file given the input values /// </summary> public bool ProcessFile() { 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))) { NDSHeader header = NDSHeader.Read(reader); if (header == null) { Console.WriteLine("Error: Not a DS or DSi Rom!"); return(false); } // Process the secure area ProcessSecureArea(header, reader, writer); } return(true); } 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 DS or DSi file and try again."); return(false); } }
/// <summary> /// Process the secure ARM9 region of the file, if possible /// </summary> /// <param name="ndsHeader">NDS header representing the DS file</param> /// <param name="reader">BinaryReader representing the input stream</param> /// <param name="writer">BinaryWriter representing the output stream</param> private void ProcessARM9(NDSHeader ndsHeader, BinaryReader reader, BinaryWriter writer) { // Seek to the beginning of the secure area reader.BaseStream.Seek(0x4000, SeekOrigin.Begin); writer.BaseStream.Seek(0x4000, SeekOrigin.Begin); // Grab the first two blocks uint p0 = reader.ReadUInt32(); uint p1 = reader.ReadUInt32(); // Perform the initialization steps Init1(ndsHeader); if (!decryptArgs.Encrypt) { Decrypt(ref p1, ref p0); } arg2[1] <<= 1; arg2[2] >>= 1; Init2(); // If we're decrypting, set the proper flags if (!decryptArgs.Encrypt) { Decrypt(ref p1, ref p0); if (p0 == Constants.MAGIC30 && p1 == Constants.MAGIC34) { p0 = 0xE7FFDEFF; p1 = 0xE7FFDEFF; } writer.Write(p0); writer.Write(p1); } // Ensure alignment reader.BaseStream.Seek(0x4008, SeekOrigin.Begin); writer.BaseStream.Seek(0x4008, SeekOrigin.Begin); // Loop throgh the main encryption step uint size = 0x800 - 8; while (size > 0) { p0 = reader.ReadUInt32(); p1 = reader.ReadUInt32(); if (decryptArgs.Encrypt) { Encrypt(ref p1, ref p0); } else { Decrypt(ref p1, ref p0); } writer.Write(p0); writer.Write(p1); size -= 8; } // Replace the header explicitly if we're encrypting if (decryptArgs.Encrypt) { reader.BaseStream.Seek(0x4000, SeekOrigin.Begin); writer.BaseStream.Seek(0x4000, SeekOrigin.Begin); p0 = reader.ReadUInt32(); p1 = reader.ReadUInt32(); if (p0 == 0xE7FFDEFF && p1 == 0xE7FFDEFF) { p0 = Constants.MAGIC30; p1 = Constants.MAGIC34; } Encrypt(ref p1, ref p0); Init1(ndsHeader); Encrypt(ref p1, ref p0); writer.Write(p0); writer.Write(p1); } }