From fd18b425d1b0d7f75c6dc6108c2f2709d277f937 Mon Sep 17 00:00:00 2001
From: Deterous <138427222+Deterous@users.noreply.github.com>
Date: Wed, 1 Nov 2023 17:48:40 +1300
Subject: [PATCH] Cleanup
---
BuildIRD/BuildIRD.cs | 14 ++-
LibIRD/IRD.cs | 187 +++++++++++++++++++------------------
LibIRD/PS3ISO.cs | 2 +-
LibIRD/Utilities.cs | 63 ++++---------
PrintParams/PrintParams.cs | 2 +-
5 files changed, 128 insertions(+), 140 deletions(-)
diff --git a/BuildIRD/BuildIRD.cs b/BuildIRD/BuildIRD.cs
index 7a5038e..99d74f6 100644
--- a/BuildIRD/BuildIRD.cs
+++ b/BuildIRD/BuildIRD.cs
@@ -1,5 +1,6 @@
using LibIRD;
using System;
+using System.Text;
namespace BuildIRD
{
@@ -7,12 +8,19 @@ namespace BuildIRD
{
static void Main()
{
- byte[] discKey = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ Console.OutputEncoding = Encoding.UTF8;
+
+ // Create new reproducible redump-style IRD with a key
+ byte[] discKey = new byte[] { 0x1A, 0x2D, 0x88, 0xFC, 0x19, 0x37, 0x27, 0x44, 0x11, 0x5E, 0xE9, 0x83, 0xA0, 0x47, 0xE2, 0xD5 };
IRD ird1 = new ReIRD("./game.iso", discKey);
- IRD ird2 = new ReIRD("./game.iso", "./log.getkey.log");
ird1.Write("./test1.ird");
+ Console.WriteLine("IRD for " + ird1.Title + " created");
+
+ // Create new reproducible redump-style IRD with a GetKey log
+ string logPath = "./log.getkey.log";
+ IRD ird2 = new ReIRD("./game.iso", logPath);
ird2.Write("./test2.ird");
- Console.WriteLine(ird1.Title);
+ Console.WriteLine("IRD for " + ird2.Title + " created");
}
}
}
diff --git a/LibIRD/IRD.cs b/LibIRD/IRD.cs
index da246b9..b0cc17e 100644
--- a/LibIRD/IRD.cs
+++ b/LibIRD/IRD.cs
@@ -8,8 +8,9 @@ using System.Text;
namespace LibIRD
{
///
- /// ISO Rebuild Data: Generation and writing to IRD file
+ /// ISO Rebuild Data
///
+ /// Generates IRD fields and writes to an IRD file
public class IRD : PS3ISO
{
#region Constants
@@ -18,7 +19,7 @@ namespace LibIRD
/// IRD file signature
///
/// "3IRD"
- private static readonly byte[] Magic = new byte[] { 0x33, 0x49, 0x52, 0x44 };
+ private static readonly byte[] Magic = { 0x33, 0x49, 0x52, 0x44 };
///
/// AES CBC Encryption Key for Data 1 (Disc Key)
@@ -66,14 +67,16 @@ namespace LibIRD
public uint UID { get; set; } = 0x00000000; // Default to zeroed UID
///
- /// Extra Config, usually 0x0000
+ /// Extra Config
///
- public ushort ExtraConfig { get; set; } = 0x0000;
+ /// Reserved, usually set to 0x0000
+ public ushort ExtraConfig { get; set; } = 0x0000; // Default to zero
///
- /// Attachments, usually 0x0000
+ /// Attachments
///
- public ushort Attachments { get; set; } = 0x0000;
+ /// Reserved, usually set to 0x0000
+ public ushort Attachments { get; set; } = 0x0000; // Default to zero
///
/// D1 key
@@ -139,12 +142,12 @@ namespace LibIRD
private protected void GenerateD1(byte[] key)
{
// Validate key
- if (key == null || key.Length <= 0)
+ if (key == null)
throw new ArgumentNullException(nameof(key));
if (key.Length != 16)
throw new ArgumentException("Disc Key must be a byte array of length 16", nameof(key));
- // AES decryption
+ // Setup AES decryption
using Aes aes = Aes.Create() ?? throw new InvalidOperationException("AES not available. Change your system settings");
// Set AES settings
@@ -154,14 +157,14 @@ namespace LibIRD
aes.Mode = CipherMode.CBC;
// Perform AES decryption
- using ICryptoTransform decryptor = aes.CreateDecryptor();
- MemoryStream ms = new();
- CryptoStream cs = new(ms, decryptor, CryptoStreamMode.Write);
+ using MemoryStream stream = new();
+ using ICryptoTransform dec = aes.CreateDecryptor();
+ using CryptoStream cs = new(stream, dec, CryptoStreamMode.Write);
cs.Write(key, 0, 16);
cs.FlushFinalBlock();
- Data1Key = ms.ToArray();
- ms.Close();
- cs.Close();
+
+ // Save decrypted key to field
+ Data1Key = stream.ToArray();
}
///
@@ -173,12 +176,12 @@ namespace LibIRD
private protected void GenerateD2(byte[] id)
{
// Validate id
- if (id == null || id.Length <= 0)
+ if (id == null)
throw new ArgumentNullException(nameof(id));
if (id.Length != 16)
throw new ArgumentException("Disc ID must be a byte array of length 16", nameof(id));
- // AES encryption
+ // Setup AES encryption
using Aes aes = Aes.Create() ?? throw new InvalidOperationException("AES not available. Change your system settings");
// Set AES settings
@@ -188,14 +191,14 @@ namespace LibIRD
aes.Mode = CipherMode.CBC;
// Perform AES encryption
- using ICryptoTransform encryptor = aes.CreateEncryptor();
- MemoryStream ms = new();
- CryptoStream cs = new(ms, encryptor, CryptoStreamMode.Write);
+ using MemoryStream stream = new();
+ using ICryptoTransform enc = aes.CreateEncryptor();
+ using CryptoStream cs = new(stream, enc, CryptoStreamMode.Write);
cs.Write(id, 0, 16);
cs.FlushFinalBlock();
- Data2Key = ms.ToArray();
- ms.Close();
- cs.Close();
+
+ // Save encrypted key to field
+ Data2Key = stream.ToArray();
}
#endregion
@@ -207,7 +210,7 @@ namespace LibIRD
///
private protected IRD(string isoPath) : base(isoPath)
{
- // Assumes that derived class will set private variables and generate in its own constructor
+ // Assumes that internally derived class will set D1/D2/PIC in its own constructor
}
///
@@ -228,78 +231,78 @@ namespace LibIRD
///
/// Constructor that reads required fields from .getkey.log file
///
- ///
- ///
+ /// Path to the ISO
+ /// Path to the .getkey.log file
+ ///
+ ///
public IRD(string isoPath, string getKeyLog) : base(isoPath)
{
// Validate .getkey.log file path
- if (getKeyLog == null || !File.Exists(getKeyLog))
+ if (getKeyLog == null)
throw new ArgumentNullException(nameof(getKeyLog));
-
- // Initialise fields
- byte[] discKey;
- byte[] discID;
- byte[] discPIC;
+ if (!File.Exists(getKeyLog))
+ throw new FileNotFoundException(nameof(getKeyLog));
// Read from .getkey.log file
- using (var sr = File.OpenText(getKeyLog))
+ using StreamReader sr = File.OpenText(getKeyLog);
+
+ // Determine whether GetKey was successful
+ string line;
+ while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("get_dec_key succeeded!") == false) ;
+ if (line == null)
+ throw new InvalidDataException(".getkey.log contains errors");
+
+ // Look for Disc Key in log
+ byte[] discKey;
+ while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("disc_key = ") == false) ;
+ if (line == null)
+ throw new InvalidDataException("Could not find Disc Key in .getkey.log");
+ // Get Disc Key from log
+ string discKeyStr = line["disc_key = ".Length..];
+ // Validate Disc Key from log
+ if (discKeyStr.Length != 32)
+ throw new InvalidDataException("Unexpected Disc Key in .getkey.log");
+ // Convert Disc Key to byte array
+ discKey = Utilities.HexToBytes(discKeyStr);
+
+ // Read Disc ID
+ byte[] discID;
+ while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("disc_id = ") == false) ;
+ if (line == null)
+ throw new InvalidDataException("Could not find Disc ID in .getkey.log");
+ // Get Disc ID from log
+ string discIDStr = line["disc_id = ".Length..];
+ // Validate Disc ID from log
+ if (discIDStr.Length != 32)
+ throw new InvalidDataException("Unexpected Disc ID in .getkey.log");
+ // Replace X's in Disc ID with 00000001
+ discIDStr = discIDStr[..24] + "00000001";
+ // Convert Disc ID to byte array
+ discID = Utilities.HexToBytes(discIDStr);
+
+ // Look for PIC in log
+ byte[] discPIC;
+ while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("PIC:") == false) ;
+ if (line == null)
+ throw new InvalidDataException("Could not find PIC in .getkey.log");
+ // Get PIC from log
+ string discPICStr = "";
+ for (int i = 0; i < 8; i++)
+ discPICStr += sr.ReadLine() ?? throw new InvalidDataException("Incomplete PIC in .getkey.log");
+ // Validate PIC from log
+ if (discPICStr.Length != 256)
+ throw new InvalidDataException("Unexpected PIC in .getkey.log");
+ // Convert PIC to byte array
+ discPIC = Utilities.HexToBytes(discPICStr[..230]);
+
+ // Double check for warnings in .getkey.log
+ while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("WARNING") == false && line.Trim().StartsWith("SUCCESS") == false)
{
- string line;
-
- // Determine whether GetKey was successful
- while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("get_dec_key succeeded!") == false) ;
- if (line == null)
+ string t = line.Trim();
+ if (t.StartsWith("WARNING"))
throw new InvalidDataException(".getkey.log contains errors");
-
- // Look for Disc Key in log
- while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("disc_key = ") == false) ;
- if (line == null)
- throw new InvalidDataException("Could not find Disc Key in .getkey.log");
- // Get Disc Key from log
- string discKeyStr = line["disc_key = ".Length..];
- // Validate Disc Key from log
- if (discKeyStr.Length != 32)
- throw new InvalidDataException("Unexpected Disc Key in .getkey.log");
- // Convert Disc Key to byte array
- discKey = Utilities.HexToBytes(discKeyStr);
-
- // Read Disc ID
- while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("disc_id = ") == false) ;
- if (line == null)
- throw new InvalidDataException("Could not find Disc ID in .getkey.log");
- // Get Disc ID from log
- string discIDStr = line["disc_id = ".Length..];
- // Validate Disc ID from log
- if (discIDStr.Length != 32)
- throw new InvalidDataException("Unexpected Disc ID in .getkey.log");
- // Replace X's in Disc ID with 00000001
- discIDStr = discIDStr[..24] + "00000001";
- // Convert Disc ID to byte array
- discID = Utilities.HexToBytes(discIDStr);
-
- // Look for PIC in log
- while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("PIC:") == false) ;
- if (line == null)
- throw new InvalidDataException("Could not find PIC in .getkey.log");
- // Get PIC from log
- string discPICStr = "";
- for (int i = 0; i < 8; i++)
- discPICStr += sr.ReadLine() ?? throw new InvalidDataException("Incomplete PIC in .getkey.log");
- // Validate PIC from log
- if (discPICStr.Length != 256)
- throw new InvalidDataException("Unexpected PIC in .getkey.log");
- // Convert PIC to byte array
- discPIC = Utilities.HexToBytes(discPICStr[..230]);
-
- // Check for warnings in .getkey.log
- while ((line = sr.ReadLine()) != null && line.Trim().StartsWith("WARNING") == false && line.Trim().StartsWith("SUCCESS") == false)
- {
- string t = line.Trim();
- if (t.StartsWith("WARNING"))
- throw new InvalidDataException(".getkey.log contains errors");
- else if (t.StartsWith("SUCCESS"))
- break;
- }
+ else if (t.StartsWith("SUCCESS"))
+ break;
}
// Parse DiscKey, DiscID, and PIC
@@ -315,15 +318,16 @@ namespace LibIRD
///
/// Write IRD data to file
///
- /// Path to IRD file to be written to
+ /// Path to the ISO
+ ///
public void Write(string irdPath)
{
// Validate irdPath
if (irdPath == null || irdPath.Length <= 0)
throw new ArgumentNullException(nameof(irdPath));
- // Create new stream to write to
- MemoryStream stream = new();
+ // Create new stream to uncompressed IRD contents
+ using MemoryStream stream = new();
// Write IRD data to stream in order
using (BinaryWriter bw = new(stream, Encoding.UTF8, true))
@@ -410,7 +414,7 @@ namespace LibIRD
bw.Write(UID);
}
- // Calculate the little-endian 32-bit "IEEE 802.3" CRC value of the entire stream
+ // Calculate the little-endian 32-bit "IEEE 802.3" CRC value of the IRD contents so far
stream.Position = 0;
Crc32 crc32 = new();
crc32.Append(stream);
@@ -426,7 +430,6 @@ namespace LibIRD
// Write entire gzipped IRD stream to file
stream.Position = 0;
stream.CopyTo(gzStream);
- stream.Close();
}
#endregion
diff --git a/LibIRD/PS3ISO.cs b/LibIRD/PS3ISO.cs
index e69e4fc..cb4b138 100644
--- a/LibIRD/PS3ISO.cs
+++ b/LibIRD/PS3ISO.cs
@@ -195,7 +195,7 @@ namespace LibIRD
RegionHashes = new byte[RegionCount][];
for (int i = 0; i < RegionCount; i++)
RegionHashes[i] = NullMD5;
- FileCount = 1;
+ FileCount = 13;
FileKeys = new ulong[FileCount];
for (int i = 0; i < FileCount; i++)
FileKeys[i] = (ulong)(i * 16);
diff --git a/LibIRD/Utilities.cs b/LibIRD/Utilities.cs
index c4d28f6..16c6915 100644
--- a/LibIRD/Utilities.cs
+++ b/LibIRD/Utilities.cs
@@ -5,53 +5,30 @@ namespace LibIRD
internal class Utilities
{
// Helper function to convert a hex string to a byte array
- // Source: https://codereview.stackexchange.com/a/53846
+ // Original source: https://codereview.stackexchange.com/a/53846
private static int HexToInt(char c)
{
- switch (c)
+ return c switch
{
- case '0':
- return 0;
- case '1':
- return 1;
- case '2':
- return 2;
- case '3':
- return 3;
- case '4':
- return 4;
- case '5':
- return 5;
- case '6':
- return 6;
- case '7':
- return 7;
- case '8':
- return 8;
- case '9':
- return 9;
- case 'a':
- case 'A':
- return 10;
- case 'b':
- case 'B':
- return 11;
- case 'c':
- case 'C':
- return 12;
- case 'd':
- case 'D':
- return 13;
- case 'e':
- case 'E':
- return 14;
- case 'f':
- case 'F':
- return 15;
- default:
- throw new FormatException("Unrecognized hex char " + c);
- }
+ '0' => 0,
+ '1' => 1,
+ '2' => 2,
+ '3' => 3,
+ '4' => 4,
+ '5' => 5,
+ '6' => 6,
+ '7' => 7,
+ '8' => 8,
+ '9' => 9,
+ 'a' or 'A' => 10,
+ 'b' or 'B' => 11,
+ 'c' or 'C' => 12,
+ 'd' or 'D' => 13,
+ 'e' or 'E' => 14,
+ 'f' or 'F' => 15,
+ _ => throw new FormatException("Unrecognized hex char " + c),
+ };
}
private static readonly byte[,] ByteLookup = new byte[,]
diff --git a/PrintParams/PrintParams.cs b/PrintParams/PrintParams.cs
index 64b4f78..3948a8c 100644
--- a/PrintParams/PrintParams.cs
+++ b/PrintParams/PrintParams.cs
@@ -12,7 +12,7 @@ namespace PrintParams
if (File.Exists(filename))
{
- ParamSFO paramSFO = new ParamSFO("./PARAM.SFO");
+ ParamSFO paramSFO = new("./PARAM.SFO");
Console.WriteLine(paramSFO["TITLE_ID"]);
paramSFO.Print();
}