2 Commits
Author SHA1 Message Date
Deterous 8ab6a9d694 Fix file hash for split files with irregular filesize 2024-02-07 09:32:56 +09:00
Deterous bc3df52e75 Cleanup 2024-02-05 09:20:59 +09:00
8 changed files with 73 additions and 63 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>0.4.0</Version> <Version>0.4.1</Version>
<!-- Package Properties --> <!-- Package Properties -->
<Authors>Deterous</Authors> <Authors>Deterous</Authors>
+7 -5
View File
@@ -31,7 +31,7 @@ namespace IRDKit
public string IRDPath { get; set; } public string IRDPath { get; set; }
[Option('b', "layerbreak", HelpText = "Layerbreak value in bytes (use with BD-Video hybrid discs). Default: 12219392")] [Option('b', "layerbreak", HelpText = "Layerbreak value in bytes (use with BD-Video hybrid discs). Default: 12219392")]
public long? Layerbreak { get; set; } public long? Layerbreak { get; set; }
[Option('k', "key", HelpText = "Hexadecimal representation of the disc key")] [Option('k', "key", HelpText = "Hexadecimal representation of the disc key")]
public string Key { get; set; } public string Key { get; set; }
@@ -68,9 +68,9 @@ namespace IRDKit
public bool Recurse { get; set; } public bool Recurse { get; set; }
} }
/// <summary> /// <summary>
/// IRD diff command /// IRD diff command
/// </summary> /// </summary>
[Verb("diff", HelpText = "Compare two IRDs and print their differences")] [Verb("diff", HelpText = "Compare two IRDs and print their differences")]
public class DiffOptions public class DiffOptions
{ {
@@ -610,7 +610,9 @@ namespace IRDKit
missingOffsets1.Add(IRD2.FileKeys[i]); missingOffsets1.Add(IRD2.FileKeys[i]);
} }
// Print the file offsets that differ // Print the file offsets that differ
printText.AppendLine($"File Offsets not Present in {irdPath1}: {string.Join(", ", missingOffsets1)}"); if (missingOffsets1.Count > 0)
printText.AppendLine($"File Offsets not Present in {irdPath1}: {string.Join(", ", missingOffsets1)}");
if (missingOffsets2.Count > 0)
printText.AppendLine($"File Offsets not Present in {irdPath2}: {string.Join(", ", missingOffsets2)}"); printText.AppendLine($"File Offsets not Present in {irdPath2}: {string.Join(", ", missingOffsets2)}");
// Print any extra config data difference // Print any extra config data difference
+7 -8
View File
@@ -946,23 +946,22 @@ namespace LibIRD
if (fileClusters[i].Offset < smallestOffset) if (fileClusters[i].Offset < smallestOffset)
smallestOffset = fileClusters[i].Offset; smallestOffset = fileClusters[i].Offset;
} }
int firstSector = (int)(smallestOffset);
// If already encountered file offset, skip this file // If already encountered file offset, skip this file
if (Array.Exists(FileKeys, element => element == firstSector)) if (Array.Exists(FileKeys, element => element == smallestOffset))
continue; continue;
if (fileClusters.Length > 1) if (fileClusters.Length > 1)
Console.WriteLine($"Split file detected: {filePath}"); Console.WriteLine($"Split file detected: {filePath}");
// Add file offset to keys // Add file offset to keys
FileKeys[FileCount] = firstSector; FileKeys[FileCount] = smallestOffset;
// Determine whether file is in encrypted or decrypted region // Determine whether file is in encrypted or decrypted region
bool encrypted = false; bool encrypted = false;
for (int i = RegionCount - 1; i > 0; i--) for (int i = RegionCount - 1; i > 0; i--)
{ {
if (RegionStart[i] <= firstSector) if (RegionStart[i] <= smallestOffset)
{ {
encrypted = i % 2 == 1; encrypted = i % 2 == 1;
break; break;
@@ -986,7 +985,7 @@ namespace LibIRD
throw new InvalidFileSystemException("Disc region ended unexpectedly"); throw new InvalidFileSystemException("Disc region ended unexpectedly");
// Decrypt sector if necessary // Decrypt sector if necessary
if (encrypted) if (encrypted)
buf = DecryptSector(buf, firstSector + j); buf = DecryptSector(buf, (int)fileClusters[i].Offset + j);
// Hash sector // Hash sector
md5.TransformBlock(buf, 0, numBytes, null, 0); md5.TransformBlock(buf, 0, numBytes, null, 0);
} }
@@ -999,7 +998,7 @@ namespace LibIRD
throw new InvalidFileSystemException("Disc region ended unexpectedly"); throw new InvalidFileSystemException("Disc region ended unexpectedly");
// Decrypt partial sector if necessary // Decrypt partial sector if necessary
if (encrypted) if (encrypted)
buf = DecryptSector(buf, firstSector + (int)(fileClusters[i].Count / SectorSize)); buf = DecryptSector(buf, (int)fileClusters[i].Offset + (int)(fileClusters[i].Count / SectorSize));
// Hash partial sector // Hash partial sector
md5.TransformBlock(buf, 0, (int)(fileClusters[i].Count % SectorSize), null, 0); md5.TransformBlock(buf, 0, (int)(fileClusters[i].Count % SectorSize), null, 0);
} }
@@ -1064,7 +1063,7 @@ namespace LibIRD
CountFiles(dirInfo); CountFiles(dirInfo);
} }
#endregion #endregion
#region IRD File #region IRD File
@@ -1250,7 +1249,7 @@ namespace LibIRD
uint fileCount = br.ReadUInt32(); uint fileCount = br.ReadUInt32();
long[] fileKeys = new long[fileCount]; long[] fileKeys = new long[fileCount];
byte[][] fileHashes = new byte[fileCount][]; byte[][] fileHashes = new byte[fileCount][];
for (int i = 0; i < fileCount; i++) for (int i = 0; i < fileCount; i++)
{ {
fileKeys[i] = br.ReadInt64(); fileKeys[i] = br.ReadInt64();
fileHashes[i] = br.ReadBytes(16); fileHashes[i] = br.ReadBytes(16);
+1 -1
View File
@@ -6,7 +6,7 @@
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers> <RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>0.4.0</Version> <Version>0.4.1</Version>
<PackageOutputPath>../nupkg</PackageOutputPath> <PackageOutputPath>../nupkg</PackageOutputPath>
<!-- Package Properties --> <!-- Package Properties -->
+7 -2
View File
@@ -27,7 +27,7 @@ namespace LibIRD
/// A field within the PS3_DISC.SFB file /// A field within the PS3_DISC.SFB file
/// </summary> /// </summary>
/// <remarks>string Key, string Value</remarks> /// <remarks>string Key, string Value</remarks>
public Dictionary<string, string> Field { get; private set; } public Dictionary<string, string> Field { get; private set; }
/// <summary> /// <summary>
/// Constructor using a PARAM.SFO file path /// Constructor using a PARAM.SFO file path
@@ -131,6 +131,11 @@ namespace LibIRD
} }
} }
/// <summary>
/// Define JSON options once
/// </summary>
private readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true };
/// <summary> /// <summary>
/// Prints parameters extracted from PS3_DISC.SFB to a json object /// Prints parameters extracted from PS3_DISC.SFB to a json object
/// </summary> /// </summary>
@@ -138,7 +143,7 @@ namespace LibIRD
public void PrintJson(string jsonPath = null) public void PrintJson(string jsonPath = null)
{ {
// Serialise PS3_Disc.SFB data to a JSON object // Serialise PS3_Disc.SFB data to a JSON object
string json = JsonSerializer.Serialize(Field, new JsonSerializerOptions { WriteIndented = true }); string json = JsonSerializer.Serialize(Field, JsonOpts);
// If no path given, output to console // If no path given, output to console
if (jsonPath == null) if (jsonPath == null)
+10 -5
View File
@@ -103,7 +103,7 @@ namespace LibIRD
- keyOffset[i]; - keyOffset[i];
// Read ith key name // Read ith key name
string key = Encoding.ASCII.GetString(br.ReadBytes((int) keyLen)).TrimEnd('\0'); string key = Encoding.ASCII.GetString(br.ReadBytes((int)keyLen)).TrimEnd('\0');
// Move stream to ith data // Move stream to ith data
sfoStream.Position = dataTableStart + dataOffset[i]; sfoStream.Position = dataTableStart + dataOffset[i];
@@ -112,13 +112,13 @@ namespace LibIRD
Field[key] = dataFormat[i] switch Field[key] = dataFormat[i] switch
{ {
// Non-null-terminated UTF-8 String // Non-null-terminated UTF-8 String
0x0004 => Encoding.UTF8.GetString(br.ReadBytes((int) dataLength[i])), 0x0004 => Encoding.UTF8.GetString(br.ReadBytes((int)dataLength[i])),
// Null-terminated UTF-8 String // Null-terminated UTF-8 String
0x0204 => Encoding.UTF8.GetString(br.ReadBytes((int) dataLength[i])).TrimEnd('\0'), 0x0204 => Encoding.UTF8.GetString(br.ReadBytes((int)dataLength[i])).TrimEnd('\0'),
// Integer // Integer
0x0404 => br.ReadInt32().ToString(), 0x0404 => br.ReadInt32().ToString(),
// Unknown data format, assume null-terminated string // Unknown data format, assume null-terminated string
_ => Encoding.UTF8.GetString(br.ReadBytes((int) dataLength[i])).TrimEnd('\0'), _ => Encoding.UTF8.GetString(br.ReadBytes((int)dataLength[i])).TrimEnd('\0'),
}; };
} }
} }
@@ -159,6 +159,11 @@ namespace LibIRD
} }
} }
/// <summary>
/// Define JSON options once
/// </summary>
private readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true };
/// <summary> /// <summary>
/// Prints parameters extracted from PARAM.SFO to a json object /// Prints parameters extracted from PARAM.SFO to a json object
/// </summary> /// </summary>
@@ -166,7 +171,7 @@ namespace LibIRD
public void PrintJson(string jsonPath = null) public void PrintJson(string jsonPath = null)
{ {
// Serialise PS3_Disc.SFB data to a JSON object // Serialise PS3_Disc.SFB data to a JSON object
string json = JsonSerializer.Serialize(Field, new JsonSerializerOptions { WriteIndented = true }); string json = JsonSerializer.Serialize(Field, JsonOpts);
// If no path given, output to console // If no path given, output to console
if (jsonPath == null) if (jsonPath == null)
+36 -37
View File
@@ -2,7 +2,6 @@
using System; using System;
using System.IO; using System.IO;
using System.IO.Hashing; using System.IO.Hashing;
using System.Security;
namespace LibIRD namespace LibIRD
{ {
@@ -152,62 +151,62 @@ namespace LibIRD
if (size > BDLayerSize) // if BD-50 if (size > BDLayerSize) // if BD-50
{ {
// Layer 0 start sector = 0x01000000 // Layer 0 start sector = 0x01000000
long l0_start_sector = 1048576; long l0_start_sector = 1048576;
// Layer 0 end sector = start sector + layerbreak - 2 // Layer 0 end sector = start sector + layerbreak - 2
long l0_end_sector = ((long)layerbreak / SectorSize) + l0_start_sector - 2; long l0_end_sector = ((long)layerbreak / SectorSize) + l0_start_sector - 2;
// Convert end sector location to hex values for PIC // Convert end sector location to hex values for PIC
byte[] l0es = [(byte)((l0_end_sector >> 24) & 0xFF), byte[] l0es = [(byte)((l0_end_sector >> 24) & 0xFF),
(byte)((l0_end_sector >> 16) & 0xFF), (byte)((l0_end_sector >> 16) & 0xFF),
(byte)((l0_end_sector >> 8) & 0xFF), (byte)((l0_end_sector >> 8) & 0xFF),
(byte)((l0_end_sector >> 0) & 0xFF)]; (byte)((l0_end_sector >> 0) & 0xFF)];
// Layer 1 start sector = end of disc (0x01EFFFFE) - layerbreak + 2 // Layer 1 start sector = end of disc (0x01EFFFFE) - layerbreak + 2
long l1_start_sector = 32505854 - ((long)layerbreak! / SectorSize) + 2; long l1_start_sector = 32505854 - ((long)layerbreak! / SectorSize) + 2;
// Convert start of start sector location to hex values for PIC // Convert start of start sector location to hex values for PIC
byte[] l1ss = [(byte)((l1_start_sector >> 24) & 0xFF), byte[] l1ss = [(byte)((l1_start_sector >> 24) & 0xFF),
(byte)((l1_start_sector >> 16) & 0xFF), (byte)((l1_start_sector >> 16) & 0xFF),
(byte)((l1_start_sector >> 8) & 0xFF), (byte)((l1_start_sector >> 8) & 0xFF),
(byte)((l1_start_sector >> 0) & 0xFF)]; (byte)((l1_start_sector >> 0) & 0xFF)];
// Total sectors used = num_sectors + Layer 0 start + sectors_between_layers (usually 0x01358C00 - 0x00CA73FE - 3) // Total sectors used = num_sectors + Layer 0 start + sectors_between_layers (usually 0x01358C00 - 0x00CA73FE - 3)
long total_sectors = (size / SectorSize) + l0_start_sector + (l1_start_sector - l0_end_sector - 3); long total_sectors = (size / SectorSize) + l0_start_sector + (l1_start_sector - l0_end_sector - 3);
byte[] ts = BitConverter.GetBytes((uint) total_sectors); byte[] ts = BitConverter.GetBytes((uint)total_sectors);
// Define the PIC // Define the PIC
pic = [ pic = [
// Initial portion of PIC (24 bytes) // Initial portion of PIC (24 bytes)
// [4098 bytes] [2x 0x00] ["DI"] [v1] [10units] [DI num] // [4098 bytes] [2x 0x00] ["DI"] [v1] [10units] [DI num]
0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x10, 0x00, 0x00, 0x20, 0x00, 0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x10, 0x00, 0x00, 0x20, 0x00,
// ["BDR"] [2 layers] // ["BDR"] [2 layers]
0x42, 0x44, 0x4F, 0x01, 0x21, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x4F, 0x01, 0x21, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
// Total sectors used on disc (4 bytes) // Total sectors used on disc (4 bytes)
ts[3], ts[2], ts[1], ts[0], ts[3], ts[2], ts[1], ts[0],
// 1st Layer sector start location (4 bytes) // 1st Layer sector start location (4 bytes)
0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
// 1st Layer sector end location (4 bytes), 0x00CA73FE for default BD layerbreak of 12219392 // 1st Layer sector end location (4 bytes), 0x00CA73FE for default BD layerbreak of 12219392
l0es[0], l0es[1], l0es[2], l0es[3], l0es[0], l0es[1], l0es[2], l0es[3],
// 32 bytes of zeros // 32 bytes of zeros
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,
// Initial portion of PIC again, for 2nd layer // Initial portion of PIC again, for 2nd layer
// ["DI"] [v1] [11unit][DI num] // ["DI"] [v1] [11unit][DI num]
0x44, 0x49, 0x01, 0x11, 0x00, 0x01, 0x20, 0x00, 0x44, 0x49, 0x01, 0x11, 0x00, 0x01, 0x20, 0x00,
// ["BDR"] [2 layers] // ["BDR"] [2 layers]
0x42, 0x44, 0x4F, 0x01, 0x21, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44, 0x4F, 0x01, 0x21, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
// Total sectors used on disc // Total sectors used on disc
ts[3], ts[2], ts[1], ts[0], ts[3], ts[2], ts[1], ts[0],
// 2nd Layer sector start location, 0x01358C00 for default BD layerbreak of 12219392 // 2nd Layer sector start location, 0x01358C00 for default BD layerbreak of 12219392
l1ss[0], l1ss[1], l1ss[2], l1ss[3], l1ss[0], l1ss[1], l1ss[2], l1ss[3],
// 2nd Layer sector end location // 2nd Layer sector end location
0x01, 0xEF, 0xFF, 0xFE, 0x01, 0xEF, 0xFF, 0xFE,
// Remaining 32 bytes are zeroes // 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 // 3k3y style: 0x03 at last byte
if (exactIRD) if (exactIRD)
pic[114] = 0x03; pic[114] = 0x03;
} }
else // if BD-25 else // if BD-25
{ {
// Total sectors used on disc: num_sectors + layer_sector_end (0x00100000) - 1 // Total sectors used on disc: num_sectors + layer_sector_end (0x00100000) - 1