diff --git a/IRDKit/IRDKit.csproj b/IRDKit/IRDKit.csproj
index caff1f8..374381a 100644
--- a/IRDKit/IRDKit.csproj
+++ b/IRDKit/IRDKit.csproj
@@ -8,13 +8,14 @@
./nupkg
net6.0;net7.0;net8.0
win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64
+ latest
0.1.0
Deterous
Library for ISO Rebuild Data
- Copyright (c) 2023 Deterous
-
+ Copyright (c) Deterous 2023
+ README.md
https://github.com/Deterous/LibIRD
git
ps3 iso ird redump
diff --git a/LibIRD/IRD.cs b/LibIRD/IRD.cs
index ce42334..a160393 100644
--- a/LibIRD/IRD.cs
+++ b/LibIRD/IRD.cs
@@ -33,32 +33,32 @@ namespace LibIRD
/// IRD file signature
///
/// "3IRD"
- private static readonly byte[] Magic = { 0x33, 0x49, 0x52, 0x44 };
+ private static readonly byte[] Magic = [0x33, 0x49, 0x52, 0x44];
///
/// MD5 hash of null
///
- private static readonly byte[] NullMD5 = new byte[] { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e };
+ private static readonly byte[] NullMD5 = [0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e];
///
/// AES CBC Encryption Key for Data 1 (Disc Key)
///
- private static readonly byte[] D1AesKey = { 0x38, 0x0B, 0xCF, 0x0B, 0x53, 0x45, 0x5B, 0x3C, 0x78, 0x17, 0xAB, 0x4F, 0xA3, 0xBA, 0x90, 0xED };
+ private static readonly byte[] D1AesKey = [0x38, 0x0B, 0xCF, 0x0B, 0x53, 0x45, 0x5B, 0x3C, 0x78, 0x17, 0xAB, 0x4F, 0xA3, 0xBA, 0x90, 0xED];
///
/// AES CBC Initial Value for Data 1 (Disc Key)
///
- private static readonly byte[] D1AesIV = { 0x69, 0x47, 0x47, 0x72, 0xAF, 0x6F, 0xDA, 0xB3, 0x42, 0x74, 0x3A, 0xEF, 0xAA, 0x18, 0x62, 0x87 };
+ private static readonly byte[] D1AesIV = [0x69, 0x47, 0x47, 0x72, 0xAF, 0x6F, 0xDA, 0xB3, 0x42, 0x74, 0x3A, 0xEF, 0xAA, 0x18, 0x62, 0x87];
///
/// AES CBC Encryption Key for Data 2 (Disc ID)
///
- private static readonly byte[] D2AesKey = { 0x7C, 0xDD, 0x0E, 0x02, 0x07, 0x6E, 0xFE, 0x45, 0x99, 0xB1, 0xB8, 0x2C, 0x35, 0x99, 0x19, 0xB3 };
+ private static readonly byte[] D2AesKey = [0x7C, 0xDD, 0x0E, 0x02, 0x07, 0x6E, 0xFE, 0x45, 0x99, 0xB1, 0xB8, 0x2C, 0x35, 0x99, 0x19, 0xB3];
///
/// AES CBC Initial Value for Data 2 (Disc ID)
///
- private static readonly byte[] D2AesIV = { 0x22, 0x26, 0x92, 0x8D, 0x44, 0x03, 0x2F, 0x43, 0x6A, 0xFD, 0x26, 0x7E, 0x74, 0x8B, 0x23, 0x93 };
+ private static readonly byte[] D2AesIV = [0x22, 0x26, 0x92, 0x8D, 0x44, 0x03, 0x2F, 0x43, 0x6A, 0xFD, 0x26, 0x7E, 0x74, 0x8B, 0x23, 0x93];
#endregion
@@ -88,7 +88,7 @@ namespace LibIRD
///
/// Extra Config
///
- /// Reserved, usually set to 0x0000
+ /// Usually set to 0x0000, set to 0x0001 for redump-style IRDs
public ushort ExtraConfig { get; set; } = 0x0000; // Default to zero
///
@@ -217,7 +217,7 @@ namespace LibIRD
/// The same value stored in PARAM.SFO / VERSION
///
/// 5 bytes, ASCII, e.g. "01.20"
- public string GameVersion { get; private set; }
+ public string DiscVersion { get; private set; }
///
/// The same value stored in PARAM.SFO / APP_VER
@@ -312,7 +312,7 @@ namespace LibIRD
string titleID,
string title,
string sysVersion,
- string gameVersion,
+ string discVersion,
string appVersion,
byte[] header,
byte[] footer,
@@ -329,7 +329,7 @@ namespace LibIRD
TitleID = titleID;
Title = title;
SystemVersion = sysVersion;
- GameVersion = gameVersion;
+ DiscVersion = discVersion;
AppVersion = appVersion;
HeaderLength = (uint)header.Length;
Header = header;
@@ -476,10 +476,8 @@ namespace LibIRD
private protected static byte[] GenerateD2(byte[] d2)
{
// Validate id
- if (d2 == null)
- throw new ArgumentNullException(nameof(d2));
- if (d2.Length != 16)
- throw new ArgumentException("Disc ID must be a byte array of length 16", nameof(d2));
+ if (d2 == null) throw new ArgumentNullException(nameof(d2));
+ if (d2.Length != 16) throw new ArgumentException("Disc ID must be a byte array of length 16", nameof(d2));
// Setup AES encryption
using Aes aes = Aes.Create() ?? throw new InvalidOperationException("AES not available. Change your system settings");
@@ -639,33 +637,26 @@ namespace LibIRD
// New ISO Reader from DiscUtils
CDReader reader = new(fs, true, true);
- // Redump-style IRDs set the lowest bit of ExtraConfig to 1
- ExtraConfig |= 0x01;
-
- // If generating redump-style IRD, read PS3 Metadata from PS3_DISC.SFB
+ // If generating redump-style IRD
if (redump)
{
+ // Redump-style IRDs set the lowest bit of ExtraConfig to 1
+ ExtraConfig |= 0x01;
+
+ // Redump-style IRDs use fields in PS3_DISC.SFB
using DiscUtils.Streams.SparseStream s = reader.OpenFile("PS3_DISC.SFB", FileMode.Open, FileAccess.Read);
// Parse PS3_DISC.SFB file
PS3_DiscSFB ps3_DiscSFB = new(s);
- // Redump-style IRDs use the TITLE ID
+ // If a valid TITLE_ID field is present, remove the hyphen to fit into standard IRD file
if (ps3_DiscSFB.Field.ContainsKey("TITLE_ID") && ps3_DiscSFB.Field["TITLE_ID"].Length == 10 && ps3_DiscSFB.Field["TITLE_ID"][4] == '-')
- {
- // Use the TITLE_ID from PS3_DISC.SFB
TitleID = string.Concat(ps3_DiscSFB.Field["TITLE_ID"].AsSpan(0, 4), ps3_DiscSFB.Field["TITLE_ID"].AsSpan(5, 5));
- }
- else
- {
- // Valid Title ID not found in PS3_DISC.SFB, use the one in PS3_GAME/PARAM.SFO
- redump = false;
- }
// If the version field is present, this is a multi-game disc
// Redump-style IRDs use the VERSION field from PS3_DISC.SFB instead of VERSION from PARAM.SFO
if (ps3_DiscSFB.Field.ContainsKey("VERSION"))
- GameVersion = ps3_DiscSFB.Field["VERSION"];
+ DiscVersion = ps3_DiscSFB.Field["VERSION"];
}
// Read PS3 Metadata from PARAM.SFO
@@ -673,12 +664,11 @@ namespace LibIRD
{
// Parse PARAM.SFO file
ParamSFO paramSFO = new(s);
- // Store required values for IRD
- if (!redump)
- TitleID = paramSFO["TITLE_ID"];
+ // If PS3_DISC.SFB did not set TitleID, use PARAM.SFO TITLE_ID
+ TitleID ??= paramSFO["TITLE_ID"];
Title = paramSFO["TITLE"];
- if (GameVersion == null)
- GameVersion = paramSFO["VERSION"];
+ // If PS3_DISC.SFB did not set DiscVersion, use PARAM.SFO VERSION
+ DiscVersion ??= paramSFO["VERSION"];
AppVersion = paramSFO["APP_VER"];
}
@@ -706,7 +696,7 @@ namespace LibIRD
// Determine file offsets and hashes
uint fileCount = FileCount;
FileCount = 0;
- ProcessFiles(fs, reader, rootDir);
+ HashFiles(fs, reader, rootDir);
if (FileCount != fileCount)
throw new InvalidFileSystemException("Unexpected ISO filesystem error: ");
Array.Sort(FileKeys, FileHashes);
@@ -923,12 +913,13 @@ namespace LibIRD
///
///
///
- private void ProcessFiles(FileStream fs, CDReader reader, DiscDirectoryInfo dir)
+ private void HashFiles(FileStream fs, CDReader reader, DiscDirectoryInfo dir)
{
// Process all files in current directory
foreach (DiscFileInfo fileInfo in dir.GetFiles())
{
string filePath = fileInfo.FullName;
+
// Try get the first sector from the file extents instead
DiscUtils.Streams.StreamExtent[] fileExtents = reader.PathToExtents(filePath);
if (fileExtents == null || fileExtents.Length <= 0)
@@ -992,7 +983,7 @@ namespace LibIRD
// Recursively process all subfolders of current directory
foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
{
- ProcessFiles(fs, reader, dirInfo);
+ HashFiles(fs, reader, dirInfo);
}
}
@@ -1081,10 +1072,10 @@ namespace LibIRD
bw.Write(systemVersionBuf, 0, 4);
// PARAM.SFO / VERSION
- byte[] buf = Encoding.ASCII.GetBytes(GameVersion);
- byte[] gameVersionBuf = new byte[5];
- Array.Copy(buf, 0, gameVersionBuf, 0, buf.Length);
- bw.Write(gameVersionBuf, 0, 5);
+ byte[] buf = Encoding.ASCII.GetBytes(DiscVersion);
+ byte[] discVersionBuf = new byte[5];
+ Array.Copy(buf, 0, discVersionBuf, 0, buf.Length);
+ bw.Write(discVersionBuf, 0, 5);
// PARAM.SFO / APP_VER
buf = Encoding.ASCII.GetBytes(AppVersion);
@@ -1198,7 +1189,7 @@ namespace LibIRD
// Read System, Game, and App Version
string sysVersion = Encoding.ASCII.GetString(br.ReadBytes(4));
- string gameVersion = Encoding.ASCII.GetString(br.ReadBytes(5));
+ string discVersion = Encoding.ASCII.GetString(br.ReadBytes(5));
string appVersion = Encoding.ASCII.GetString(br.ReadBytes(5));
// Read UID (for Version 7)
@@ -1259,7 +1250,7 @@ namespace LibIRD
titleID,
title,
sysVersion,
- gameVersion,
+ discVersion,
appVersion,
header,
footer,
@@ -1290,7 +1281,7 @@ namespace LibIRD
print.AppendLine($"Title ID: {TitleID}");
print.AppendLine($"Title: {Title}");
print.AppendLine($"PUP Version: {SystemVersion}");
- print.AppendLine($"Game Version: {GameVersion}");
+ print.AppendLine($"Disc Version: {DiscVersion}");
print.AppendLine($"App Version: {AppVersion}");
print.AppendLine($"Regions: {RegionCount}");
print.AppendLine($"Files: {FileCount}");
diff --git a/LibIRD/LibIRD.csproj b/LibIRD/LibIRD.csproj
index 49978c5..d46aebe 100644
--- a/LibIRD/LibIRD.csproj
+++ b/LibIRD/LibIRD.csproj
@@ -4,12 +4,13 @@
net6.0;net7.0;net8.0
win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64
+ latest
0.1.0
Deterous
Library for ISO Rebuild Data
- Copyright (c) 2023 Deterous
+ Copyright (c) Deterous 2023
README.md
https://github.com/Deterous/LibIRD
git
diff --git a/LibIRD/PS3_DiscSFB.cs b/LibIRD/PS3_DiscSFB.cs
index bfe60fa..fb1932a 100644
--- a/LibIRD/PS3_DiscSFB.cs
+++ b/LibIRD/PS3_DiscSFB.cs
@@ -77,7 +77,7 @@ namespace LibIRD
// Process all field headers
sfbStream.Seek(0x20, SeekOrigin.Begin);
string field = Encoding.ASCII.GetString(br.ReadBytes(0x10)).Trim('\0');
- Field = new Dictionary { };
+ Field = [];
while (field != null && field != "")
{
// Find location of value
diff --git a/LibIRD/ReIRD.cs b/LibIRD/ReIRD.cs
index ab11d64..c869ecc 100644
--- a/LibIRD/ReIRD.cs
+++ b/LibIRD/ReIRD.cs
@@ -131,12 +131,12 @@ namespace LibIRD
private static byte[] GenerateID(long size, Region region = Region.NONE)
{
if (size > BDLayerSize) // if BD-50, Disc ID is fixed
- return new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ return [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
else // else if BD-25, Disc ID has a byte referring to disc region
{
- return new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x02, 0x00, (byte)region, 0x00, 0x00, 0x00, 0x01 };
+ return [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x00, 0x02, 0x00, (byte)region, 0x00, 0x00, 0x00, 0x01 ];
}
}
@@ -164,7 +164,7 @@ namespace LibIRD
byte[] total_sectors = BitConverter.GetBytes((uint)(size / SectorSize + 8067071));
// Initial portion of PIC (24 bytes)
- pic = new byte[]{
+ pic = [
// [4098 bytes] [2x 0x00] ["DI"] [v1] [10units] [DI num]
0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x10, 0x00, 0x00, 0x20, 0x00,
// ["BDR"] [2 layers]
@@ -190,7 +190,7 @@ namespace LibIRD
// 2nd Layer sector end location
0x01, 0xEF, 0xFF, 0xFE,
// Remaining 32 bytes are zeroes
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ];
// 3k3y style: 0x03 at last byte
if (exactIRD)
pic[114] = 0x03;
@@ -204,8 +204,8 @@ namespace LibIRD
byte[] end_sector = BitConverter.GetBytes((uint)(size / SectorSize + 1048574));
// Initial portion of PIC (24 bytes)
- pic = new byte[]{ 0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x08, 0x00, 0x00, 0x20, 0x00,
- 0x42, 0x44, 0x4F, 0x01, 0x11, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ pic = [ 0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x08, 0x00, 0x00, 0x20, 0x00,
+ 0x42, 0x44, 0x4F, 0x01, 0x11, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
// Total sectors used on disc (4 bytes)
total_sectors[3], total_sectors[2], total_sectors[1], total_sectors[0],
// Layer sector start location (4 bytes)
@@ -217,7 +217,7 @@ namespace LibIRD
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ];
}
return pic;