Files
NDecrypt/NDecrypt.Core/DSTool.cs
2026-01-25 17:20:06 -05:00

169 lines
5.5 KiB
C#

using System;
using System.IO;
using System.Text;
#if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER
using SabreTools.IO.Extensions;
#endif
using SabreTools.Serialization.Wrappers;
namespace NDecrypt.Core
{
public class DSTool : ITool
{
/// <summary>
/// Decryption args to use while processing
/// </summary>
private readonly DecryptArgs _decryptArgs;
public DSTool(DecryptArgs decryptArgs)
{
_decryptArgs = decryptArgs;
}
#region Encrypt
/// <inheritdoc/>
public bool EncryptFile(string input, string? output, bool force)
{
try
{
// If the output is provided, copy the input file
if (output is not null)
File.Copy(input, output, overwrite: true);
else
output = input;
// Open the output file for processing
using var reader = File.Open(output, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Deserialize the cart information
var nitro = Nitro.Create(reader);
if (nitro is null)
{
Console.WriteLine("Error: Not a DS or DSi Rom!");
return false;
}
// Ensure the secure area was read
if (nitro.SecureArea is null)
{
Console.WriteLine("Error: Invalid secure area!");
return false;
}
// Encrypt the secure area
nitro.EncryptSecureArea(_decryptArgs.NitroEncryptionData, force);
// Write the encrypted secure area
using var writer = File.Open(output, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
writer.Seek(0x4000, SeekOrigin.Begin);
writer.Write(nitro.SecureArea);
writer.Flush();
return true;
}
catch
{
Console.WriteLine($"An error has occurred. {output} 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;
}
}
#endregion
#region Decrypt
/// <inheritdoc/>
public bool DecryptFile(string input, string? output, bool force)
{
try
{
// If the output is provided, copy the input file
if (output is not null)
File.Copy(input, output, overwrite: true);
else
output = input;
// Open the read and write on the same file for inplace processing
using var reader = File.Open(output, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Deserialize the cart information
var nitro = Nitro.Create(reader);
if (nitro is null)
{
Console.WriteLine("Error: Not a DS or DSi Rom!");
return false;
}
// Ensure the secure area was read
if (nitro.SecureArea is null)
{
Console.WriteLine("Error: Invalid secure area!");
return false;
}
// Decrypt the secure area
nitro.DecryptSecureArea(_decryptArgs.NitroEncryptionData, force);
// Write the decrypted secure area
using var writer = File.Open(output, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
writer.Seek(0x4000, SeekOrigin.Begin);
writer.Write(nitro.SecureArea);
writer.Flush();
return true;
}
catch
{
Console.WriteLine($"An error has occurred. {output} 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;
}
}
#endregion
#region Info
/// <inheritdoc/>
public string? GetInformation(string filename)
{
try
{
// Open the file for reading
using var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Deserialize the cart information
var cart = Nitro.Create(input);
if (cart?.Model is null)
return "Error: Not a DS/DSi cart image!";
// Get a string builder for the status
var sb = new StringBuilder();
sb.Append("\tSecure Area: ");
// Get the encryption status
bool? decrypted = cart.CheckIfDecrypted(out _);
if (decrypted is null)
sb.Append("Empty");
else if (decrypted == true)
sb.Append("Decrypted");
else
sb.Append("Encrypted");
// Return the status for the secure area
sb.Append(Environment.NewLine);
return sb.ToString();
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
#endregion
}
}