mirror of
https://github.com/SabreTools/NDecrypt.git
synced 2026-09-24 07:45:00 +00:00
Remove reliance on BinaryReader/Writer
This commit is contained in:
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using NDecrypt.Core;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.N3DS;
|
||||
using static NDecrypt.Core.Helper;
|
||||
using CIADeserializer = SabreTools.Serialization.Deserializers.CIA;
|
||||
@@ -71,8 +72,8 @@ namespace NDecrypt.N3DS
|
||||
try
|
||||
{
|
||||
// Open the read and write on the same file for inplace processing
|
||||
using var reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||
using var writer = new BinaryWriter(File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
|
||||
using var reader = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
|
||||
// Deserialize the CIA information
|
||||
var cia = ReadCIA(reader);
|
||||
@@ -99,9 +100,9 @@ namespace NDecrypt.N3DS
|
||||
/// Process all partitions in the content file data of a CIA header
|
||||
/// </summary>
|
||||
/// <param name="cia">CIA representing the 3DS CIA file</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
private void ProcessAllPartitions(CIA cia, BinaryReader reader, BinaryWriter writer)
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessAllPartitions(CIA cia, Stream reader, Stream writer)
|
||||
{
|
||||
// Iterate over all NCCH partitions
|
||||
for (int p = 0; p < cia.Partitions!.Length; p++)
|
||||
@@ -119,12 +120,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessPartition(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// If we're forcing the operation, tell the user
|
||||
if (decryptArgs.Force)
|
||||
@@ -238,21 +239,21 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private bool ProcessExtendedHeader(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // mediaUnitSize;
|
||||
|
||||
if (ncchHeader.ExtendedHeaderSizeInBytes > 0)
|
||||
{
|
||||
reader.BaseStream.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
|
||||
reader.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
|
||||
|
||||
@@ -274,19 +275,19 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFileEntries(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // mediaUnitSize;
|
||||
|
||||
reader.BaseStream.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
var exefsHeader = N3DSDeserializer.ParseExeFSHeader(reader.BaseStream);
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
var exefsHeader = N3DSDeserializer.ParseExeFSHeader(reader);
|
||||
|
||||
// If the header failed to read, log and return
|
||||
if (exefsHeader?.FileHeaders == null)
|
||||
@@ -310,8 +311,8 @@ namespace NDecrypt.N3DS
|
||||
var firstCipher = CreateAESCipher(NormalKey[partitionIndex], exefsIVWithOffsetForHeader, decryptArgs.Encrypt);
|
||||
var secondCipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffsetForHeader, !decryptArgs.Encrypt);
|
||||
|
||||
reader.BaseStream.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
reader.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
|
||||
if (datalenM > 0)
|
||||
{
|
||||
@@ -339,19 +340,19 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFilenameTable(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // mediaUnitSize;
|
||||
|
||||
reader.BaseStream.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
|
||||
|
||||
@@ -366,13 +367,13 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // mediaUnitSize;
|
||||
@@ -385,8 +386,8 @@ namespace NDecrypt.N3DS
|
||||
|
||||
var exeFS = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffset, decryptArgs.Encrypt);
|
||||
|
||||
reader.BaseStream.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
|
||||
if (exefsSizeM > 0)
|
||||
{
|
||||
for (int i = 0; i < exefsSizeM; i++)
|
||||
@@ -415,13 +416,13 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void DecryptExeFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// If the ExeFS size is 0, we log and return
|
||||
if (ncchHeader.ExeFSSizeInMediaUnits == 0)
|
||||
@@ -447,14 +448,14 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
/// TODO: See how much can be extracted into a common method with Encrypt
|
||||
private void DecryptRomFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // ncsdHeader.MediaUnitSize;
|
||||
@@ -471,8 +472,8 @@ namespace NDecrypt.N3DS
|
||||
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], ncchHeader.RomFSIV(), decryptArgs.Encrypt);
|
||||
|
||||
reader.BaseStream.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
if (romfsSizeM > 0)
|
||||
{
|
||||
for (int i = 0; i < romfsSizeM; i++)
|
||||
@@ -496,21 +497,21 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void UpdateDecryptCryptoAndMasks(NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryWriter writer)
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // ncsdHeader.MediaUnitSize;
|
||||
|
||||
// Write the new CryptoMethod
|
||||
writer.BaseStream.Seek((tableEntry.Offset * mediaUnitSize) + 0x18B, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset * mediaUnitSize) + 0x18B, SeekOrigin.Begin);
|
||||
writer.Write((byte)CryptoMethod.Original);
|
||||
writer.Flush();
|
||||
|
||||
// Write the new BitMasks flag
|
||||
writer.BaseStream.Seek((tableEntry.Offset * mediaUnitSize) + 0x18F, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset * mediaUnitSize) + 0x18F, SeekOrigin.Begin);
|
||||
BitMasks flag = ncchHeader.Flags!.BitMasks;
|
||||
flag &= (BitMasks)((byte)(BitMasks.FixedCryptoKey | BitMasks.NewKeyYGenerator) ^ 0xFF);
|
||||
flag |= BitMasks.NoCrypto;
|
||||
@@ -528,13 +529,13 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void EncryptExeFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// If the ExeFS size is 0, we log and return
|
||||
if (ncchHeader.ExeFSSizeInMediaUnits == 0)
|
||||
@@ -561,14 +562,14 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
/// TODO: See how much can be extracted into a common method with Decrypt
|
||||
private void EncryptRomFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // ncsdHeader.MediaUnitSize;
|
||||
@@ -600,8 +601,8 @@ namespace NDecrypt.N3DS
|
||||
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], ncchHeader.RomFSIV(), decryptArgs.Encrypt);
|
||||
|
||||
reader.BaseStream.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
if (romfsSizeM > 0)
|
||||
{
|
||||
for (int i = 0; i < romfsSizeM; i++)
|
||||
@@ -626,17 +627,17 @@ namespace NDecrypt.N3DS
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void UpdateEncryptCryptoAndMasks(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
PartitionTableEntry tableEntry,
|
||||
BinaryWriter writer)
|
||||
Stream writer)
|
||||
{
|
||||
// TODO: Determine how to figure out the MediaUnitSize without an NCSD header. Is it a default value?
|
||||
uint mediaUnitSize = 0x200; // ncsdHeader.MediaUnitSize;
|
||||
|
||||
// Write the new CryptoMethod
|
||||
writer.BaseStream.Seek((tableEntry.Offset * mediaUnitSize) + 0x18B, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset * mediaUnitSize) + 0x18B, SeekOrigin.Begin);
|
||||
|
||||
// For partitions 1 and up, set crypto-method to 0x00
|
||||
if (partitionIndex > 0)
|
||||
@@ -650,7 +651,7 @@ namespace NDecrypt.N3DS
|
||||
writer.Flush();
|
||||
|
||||
// Write the new BitMasks flag
|
||||
writer.BaseStream.Seek((tableEntry.Offset * mediaUnitSize) + 0x18F, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset * mediaUnitSize) + 0x18F, SeekOrigin.Begin);
|
||||
BitMasks flag = ncchHeader.Flags!.BitMasks;
|
||||
flag &= (BitMasks.FixedCryptoKey | BitMasks.NewKeyYGenerator | BitMasks.NoCrypto) ^ (BitMasks)0xFF;
|
||||
|
||||
@@ -667,13 +668,13 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Read from a stream and get a CIA header, if possible
|
||||
/// </summary>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <returns>CIA header object, null on error</returns>
|
||||
private static CIA? ReadCIA(BinaryReader reader)
|
||||
private static CIA? ReadCIA(Stream reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
return CIADeserializer.DeserializeStream(reader.BaseStream);
|
||||
return CIADeserializer.DeserializeStream(reader);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using NDecrypt.Core;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.N3DS;
|
||||
using static NDecrypt.Core.Helper;
|
||||
using N3DSDeserializer = SabreTools.Serialization.Deserializers.N3DS;
|
||||
@@ -69,11 +70,11 @@ namespace NDecrypt.N3DS
|
||||
try
|
||||
{
|
||||
// Open the read and write on the same file for inplace processing
|
||||
using var reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||
using var writer = new BinaryWriter(File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
|
||||
using var reader = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
|
||||
// Deserialize the cart information
|
||||
var cart = ReadCart(reader);
|
||||
var cart = N3DSDeserializer.DeserializeStream(reader);
|
||||
if (cart?.Header == null || cart?.CardInfoHeader?.InitialData?.BackupHeader == null)
|
||||
{
|
||||
Console.WriteLine("Error: Not a 3DS cart image!");
|
||||
@@ -97,9 +98,9 @@ namespace NDecrypt.N3DS
|
||||
/// Process all partitions in the partition table of an NCSD header
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
private void ProcessAllPartitions(Cart cart, BinaryReader reader, BinaryWriter writer)
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessAllPartitions(Cart cart, Stream reader, Stream writer)
|
||||
{
|
||||
// Check the partitions table
|
||||
if (cart.Header?.PartitionsTable == null)
|
||||
@@ -127,12 +128,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessPartition(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// If we're forcing the operation, tell the user
|
||||
if (decryptArgs.Force)
|
||||
@@ -244,12 +245,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private bool ProcessExtendedHeader(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -258,8 +259,8 @@ namespace NDecrypt.N3DS
|
||||
if (cart.Partitions![partitionIndex]!.ExtendedHeaderSizeInBytes > 0)
|
||||
{
|
||||
// Seek to the extended header
|
||||
reader.BaseStream.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
|
||||
reader.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
|
||||
writer.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
|
||||
|
||||
@@ -273,7 +274,7 @@ namespace NDecrypt.N3DS
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
|
||||
reader.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||
reader.Seek(0, SeekOrigin.Begin);
|
||||
#endif
|
||||
writer.Flush();
|
||||
return true;
|
||||
@@ -290,12 +291,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFileEntries(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -303,8 +304,8 @@ namespace NDecrypt.N3DS
|
||||
uint exeFsHeaderOffset = (partitionOffsetMU + exeFsOffsetMU) * cart.MediaUnitSize();
|
||||
uint exeFsOffset = (partitionOffsetMU + exeFsOffsetMU + 1) * cart.MediaUnitSize();
|
||||
|
||||
reader.BaseStream.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
var exefsHeader = N3DSDeserializer.ParseExeFSHeader(reader.BaseStream);
|
||||
reader.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
var exefsHeader = N3DSDeserializer.ParseExeFSHeader(reader);
|
||||
|
||||
// If the header failed to read, log and return
|
||||
if (exefsHeader == null)
|
||||
@@ -330,8 +331,8 @@ namespace NDecrypt.N3DS
|
||||
var secondCipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffsetForHeader, !decryptArgs.Encrypt);
|
||||
|
||||
// Seek to the file entry
|
||||
reader.BaseStream.Seek(exeFsOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(exeFsOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
reader.Seek(exeFsOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.Seek(exeFsOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (datalenM > 0)
|
||||
@@ -366,12 +367,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFilenameTable(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -379,8 +380,8 @@ namespace NDecrypt.N3DS
|
||||
uint exeFsHeaderOffset = (partitionOffsetMU + exeFsOffsetMU) * cart.MediaUnitSize();
|
||||
|
||||
// Seek to the ExeFS header
|
||||
reader.BaseStream.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
reader.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
writer.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
|
||||
|
||||
@@ -394,7 +395,7 @@ namespace NDecrypt.N3DS
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
|
||||
reader.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||
reader.Seek(0, SeekOrigin.Begin);
|
||||
#endif
|
||||
writer.Flush();
|
||||
}
|
||||
@@ -404,12 +405,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private bool ProcessExeFS(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -434,8 +435,8 @@ namespace NDecrypt.N3DS
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffset, decryptArgs.Encrypt);
|
||||
|
||||
// Seek to the ExeFS
|
||||
reader.BaseStream.Seek(exeFsOffset, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(exeFsOffset, SeekOrigin.Begin);
|
||||
reader.Seek(exeFsOffset, SeekOrigin.Begin);
|
||||
writer.Seek(exeFsOffset, SeekOrigin.Begin);
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (exefsSizeM > 0)
|
||||
@@ -472,12 +473,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void DecryptExeFS(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// If the ExeFS size is 0, we log and return
|
||||
if (cart.Partitions![partitionIndex]!.ExeFSSizeInMediaUnits == 0)
|
||||
@@ -502,13 +503,13 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
/// TODO: See how much can be extracted into a common method with Encrypt
|
||||
private bool DecryptRomFS(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -531,8 +532,8 @@ namespace NDecrypt.N3DS
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], cart.RomFSIV(partitionIndex), decryptArgs.Encrypt);
|
||||
|
||||
// Seek to the RomFS
|
||||
reader.BaseStream.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
reader.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
writer.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (romfsSizeM > 0)
|
||||
@@ -565,22 +566,22 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
private static void UpdateDecryptCryptoAndMasks(Cart cart, int partitionIndex, BinaryWriter writer)
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private static void UpdateDecryptCryptoAndMasks(Cart cart, int partitionIndex, Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
uint partitionOffset = partitionOffsetMU * cart.MediaUnitSize();
|
||||
|
||||
// Seek to the CryptoMethod location
|
||||
writer.BaseStream.Seek(partitionOffset + 0x18B, SeekOrigin.Begin);
|
||||
writer.Seek(partitionOffset + 0x18B, SeekOrigin.Begin);
|
||||
|
||||
// Write the new CryptoMethod
|
||||
writer.Write((byte)CryptoMethod.Original);
|
||||
writer.Flush();
|
||||
|
||||
// Seek to the BitMasks location
|
||||
writer.BaseStream.Seek(partitionOffset + 0x18F, SeekOrigin.Begin);
|
||||
writer.Seek(partitionOffset + 0x18F, SeekOrigin.Begin);
|
||||
|
||||
// Write the new BitMasks flag
|
||||
BitMasks flag = cart.Partitions![partitionIndex]!.Flags!.BitMasks;
|
||||
@@ -599,12 +600,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void EncryptExeFS(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// If the ExeFS size is 0, we log and return
|
||||
if (cart.Partitions![partitionIndex]!.ExeFSSizeInMediaUnits == 0)
|
||||
@@ -632,13 +633,13 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
/// TODO: See how much can be extracted into a common method with Decrypt
|
||||
private bool EncryptRomFS(Cart cart,
|
||||
int partitionIndex,
|
||||
BinaryReader reader,
|
||||
BinaryWriter writer)
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -679,8 +680,8 @@ namespace NDecrypt.N3DS
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], cart.RomFSIV(partitionIndex), decryptArgs.Encrypt);
|
||||
|
||||
// Seek to the RomFS
|
||||
reader.BaseStream.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
reader.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
writer.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (romfsSizeM > 0)
|
||||
@@ -713,8 +714,8 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
private static void UpdateEncryptCryptoAndMasks(Cart cart, int partitionIndex, BinaryWriter writer)
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private static void UpdateEncryptCryptoAndMasks(Cart cart, int partitionIndex, Stream writer)
|
||||
{
|
||||
// Get required offsets
|
||||
uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
|
||||
@@ -724,7 +725,7 @@ namespace NDecrypt.N3DS
|
||||
var backupHeader = cart.CardInfoHeader!.InitialData!.BackupHeader;
|
||||
|
||||
// Seek to the CryptoMethod location
|
||||
writer.BaseStream.Seek(partitionOffset + 0x18B, SeekOrigin.Begin);
|
||||
writer.Seek(partitionOffset + 0x18B, SeekOrigin.Begin);
|
||||
|
||||
// Write the new CryptoMethod
|
||||
// - For partitions 1 and up, set crypto-method to 0x00
|
||||
@@ -734,7 +735,7 @@ namespace NDecrypt.N3DS
|
||||
writer.Flush();
|
||||
|
||||
// Seek to the BitMasks location
|
||||
writer.BaseStream.Seek(partitionOffset + 0x18F, SeekOrigin.Begin);
|
||||
writer.Seek(partitionOffset + 0x18F, SeekOrigin.Begin);
|
||||
|
||||
// Write the new BitMasks flag
|
||||
BitMasks flag = cart.Partitions![partitionIndex]!.Flags!.BitMasks;
|
||||
@@ -745,55 +746,5 @@ namespace NDecrypt.N3DS
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Serialization
|
||||
|
||||
/// <summary>
|
||||
/// Read from a stream and get N3DS cart image, if possible
|
||||
/// </summary>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <returns>N3DS cart image object, null on error</returns>
|
||||
private static Cart? ReadCart(BinaryReader reader)
|
||||
{
|
||||
var cart = new Cart();
|
||||
|
||||
try
|
||||
{
|
||||
cart.Header = N3DSDeserializer.ParseNCSDHeader(reader.BaseStream);
|
||||
if (cart.Header == null)
|
||||
return null;
|
||||
|
||||
if (cart.Header.PartitionsFSType == FilesystemType.Normal
|
||||
|| cart.Header.PartitionsFSType == FilesystemType.None)
|
||||
{
|
||||
cart.CardInfoHeader = N3DSDeserializer.ParseCardInfoHeader(reader.BaseStream);
|
||||
if (cart.CardInfoHeader == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
cart.Partitions = new NCCHHeader[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// Check the entry is valid
|
||||
var tableEntry = cart.Header.PartitionsTable![i];
|
||||
if (tableEntry == null || tableEntry.Offset == 0 || tableEntry.Length == 0)
|
||||
continue;
|
||||
|
||||
// Seek to the beginning of the NCCH partition
|
||||
long offset = tableEntry.Offset * cart.Header.ImageSizeInMediaUnits;
|
||||
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
cart.Partitions[i] = N3DSDeserializer.ParseNCCHHeader(reader.BaseStream, skipSignature: false);
|
||||
}
|
||||
|
||||
return cart;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NDecrypt.Core;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.Nitro;
|
||||
using NitroDeserializer = SabreTools.Serialization.Deserializers.Nitro;
|
||||
|
||||
@@ -40,11 +41,11 @@ namespace NDecrypt.Nitro
|
||||
try
|
||||
{
|
||||
// Open the read and write on the same file for inplace processing
|
||||
using var reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||
using var writer = new BinaryWriter(File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
|
||||
using var reader = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
|
||||
// Deserialize the cart information
|
||||
Cart? cart = ReadCart(reader);
|
||||
Cart? cart = NitroDeserializer.DeserializeStream(reader);
|
||||
if (cart == null)
|
||||
{
|
||||
Console.WriteLine("Error: Not a DS or DSi Rom!");
|
||||
@@ -66,11 +67,11 @@ namespace NDecrypt.Nitro
|
||||
|
||||
/// <summary>
|
||||
/// Process secure area in the DS/DSi file
|
||||
/// </summary>
|
||||
/// </summary>s
|
||||
/// <param name="cart">Cart 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(Cart cart, BinaryReader reader, BinaryWriter writer)
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessSecureArea(Cart cart, Stream reader, Stream writer)
|
||||
{
|
||||
// If we're forcing the operation, tell the user
|
||||
if (decryptArgs.Force)
|
||||
@@ -101,11 +102,11 @@ namespace NDecrypt.Nitro
|
||||
/// <summary>
|
||||
/// Determine if the current file is already decrypted or not (or has an empty secure area)
|
||||
/// </summary>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <returns>True if the file has known values for a decrypted file, null if it's empty, false otherwise</returns>
|
||||
private static bool? CheckIfDecrypted(BinaryReader reader)
|
||||
private static bool? CheckIfDecrypted(Stream reader)
|
||||
{
|
||||
reader.BaseStream.Seek(0x4000, SeekOrigin.Begin);
|
||||
reader.Seek(0x4000, SeekOrigin.Begin);
|
||||
uint firstValue = reader.ReadUInt32();
|
||||
uint secondValue = reader.ReadUInt32();
|
||||
|
||||
@@ -161,13 +162,13 @@ namespace NDecrypt.Nitro
|
||||
/// Process the secure ARM9 region of the file, if possible
|
||||
/// </summary>
|
||||
/// <param name="commonHeader">CommonHeader representing the DS header</param>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <param name="writer">BinaryWriter representing the output stream</param>
|
||||
private void ProcessARM9(CommonHeader commonHeader, BinaryReader reader, BinaryWriter writer)
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessARM9(CommonHeader commonHeader, Stream reader, Stream writer)
|
||||
{
|
||||
// Seek to the beginning of the secure area
|
||||
reader.BaseStream.Seek(0x4000, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(0x4000, SeekOrigin.Begin);
|
||||
reader.Seek(0x4000, SeekOrigin.Begin);
|
||||
writer.Seek(0x4000, SeekOrigin.Begin);
|
||||
|
||||
// Grab the first two blocks
|
||||
uint p0 = reader.ReadUInt32();
|
||||
@@ -195,8 +196,8 @@ namespace NDecrypt.Nitro
|
||||
}
|
||||
|
||||
// Ensure alignment
|
||||
reader.BaseStream.Seek(0x4008, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(0x4008, SeekOrigin.Begin);
|
||||
reader.Seek(0x4008, SeekOrigin.Begin);
|
||||
writer.Seek(0x4008, SeekOrigin.Begin);
|
||||
|
||||
// Loop throgh the main encryption step
|
||||
uint size = 0x800 - 8;
|
||||
@@ -219,8 +220,8 @@ namespace NDecrypt.Nitro
|
||||
// Replace the header explicitly if we're encrypting
|
||||
if (decryptArgs.Encrypt)
|
||||
{
|
||||
reader.BaseStream.Seek(0x4000, SeekOrigin.Begin);
|
||||
writer.BaseStream.Seek(0x4000, SeekOrigin.Begin);
|
||||
reader.Seek(0x4000, SeekOrigin.Begin);
|
||||
writer.Seek(0x4000, SeekOrigin.Begin);
|
||||
|
||||
p0 = reader.ReadUInt32();
|
||||
p1 = reader.ReadUInt32();
|
||||
@@ -361,26 +362,5 @@ namespace NDecrypt.Nitro
|
||||
_cardHash[i + 18 + 1] = tmp2;
|
||||
}
|
||||
}
|
||||
|
||||
#region Serialization
|
||||
|
||||
/// <summary>
|
||||
/// Read from a stream and get an NDS/NDSi Cart, if possible
|
||||
/// </summary>
|
||||
/// <param name="reader">BinaryReader representing the input stream</param>
|
||||
/// <returns>NDS/NDSi Cart object, null on error</returns>
|
||||
private static Cart? ReadCart(BinaryReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
return NitroDeserializer.DeserializeStream(reader.BaseStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user