Throw error for BD-Video hybrid discs without layerbreak

This commit is contained in:
Deterous
2024-02-03 23:15:13 +09:00
parent e9bb0ae00a
commit 8e45432aab
3 changed files with 137 additions and 101 deletions
+97 -58
View File
@@ -174,21 +174,16 @@ namespace IRDKit
return; return;
} }
// Only one ISO is being processed string irdPath;
if (!string.IsNullOrEmpty(opt.IRDPath) && opt.ISOPath.Count() == 1) // Save to given output path and filename, if only 1 IRD is being created
{ if (opt.ISOPath.Count() == 1)
// Save to given output path and filename, if only 1 IRD is being created irdPath = ISO2IRD(isoPath, irdPath: opt.IRDPath, hexKey: opt.Key, keyPath: opt.KeyFile, getKeyLog: opt.GetKeyLog, layerbreak: opt.Layerbreak, verbose: opt.Verbose);
string irdPath = ISO2IRD(isoPath, irdPath: opt.IRDPath, hexKey: opt.Key, keyPath: opt.KeyFile, getKeyLog: opt.GetKeyLog, layerbreak: opt.Layerbreak, verbose: opt.Verbose); // Save to given output path, if more than 1 IRD is being created
if (irdPath != null)
Console.WriteLine($"IRD saved to {irdPath}");
}
else else
{ irdPath = ISO2IRD(isoPath, irdPath: Path.GetDirectoryName(opt.IRDPath), verbose: opt.Verbose);
// Save to given output path, if more than 1 IRD is being created
string irdPath = ISO2IRD(isoPath, irdPath: Path.GetDirectoryName(opt.IRDPath), verbose: opt.Verbose); if (irdPath != null)
if (irdPath != null) Console.WriteLine($"IRD saved to {irdPath}");
Console.WriteLine($"IRD saved to {irdPath}");
}
} }
} }
@@ -661,7 +656,16 @@ namespace IRDKit
public static string ISO2IRD(string isoPath, string irdPath = null, string hexKey = null, string keyPath = null, string getKeyLog = null, long? layerbreak = null, bool verbose = false) public static string ISO2IRD(string isoPath, string irdPath = null, string hexKey = null, string keyPath = null, string getKeyLog = null, long? layerbreak = null, bool verbose = false)
{ {
// Check file exists // Check file exists
FileInfo iso = new(isoPath); FileInfo iso;
try
{
iso = new(isoPath);
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
}
if (!iso.Exists) if (!iso.Exists)
{ {
Console.Error.WriteLine($"{nameof(isoPath)} is not a valid file or directory"); Console.Error.WriteLine($"{nameof(isoPath)} is not a valid file or directory");
@@ -685,18 +689,21 @@ namespace IRDKit
// Get disc key from hex string // Get disc key from hex string
byte[] discKey = Convert.FromHexString(hexKey); byte[] discKey = Convert.FromHexString(hexKey);
if (discKey == null || discKey.Length != 16) if (discKey == null || discKey.Length != 16)
throw new ArgumentException(hexKey); Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
else
Console.WriteLine($"Creating {irdPath} with Key: {hexKey}"); {
IRD ird1 = new ReIRD(isoPath, discKey, layerbreak); Console.WriteLine($"Creating {irdPath} with Key: {hexKey}");
ird1.Write(irdPath); IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
if (verbose) ird1.Write(irdPath);
ird1.Print(); if (verbose)
return irdPath; ird1.Print();
return irdPath;
}
} }
catch (ArgumentException) catch (ArgumentException e)
{ {
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically..."); Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -708,20 +715,26 @@ namespace IRDKit
// Create new reproducible redump-style IRD with a given key file // Create new reproducible redump-style IRD with a given key file
if (keyPath != null) if (keyPath != null)
{ {
// Read key from .key file
byte[] discKey = File.ReadAllBytes(keyPath);
try try
{ {
IRD ird2 = new ReIRD(isoPath, discKey, layerbreak); // Read key from .key file
Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}"); byte[] discKey = File.ReadAllBytes(keyPath);
ird2.Write(irdPath); if (discKey == null || discKey.Length != 16)
if (verbose) Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
ird2.Print(); else
return irdPath; {
IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
ird1.Write(irdPath);
if (verbose)
ird1.Print();
return irdPath;
}
} }
catch (ArgumentException) catch (ArgumentException e)
{ {
Console.Error.WriteLine($"{Convert.ToHexString(discKey)} is not a valid key, detecting key automatically..."); Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -736,12 +749,17 @@ namespace IRDKit
try try
{ {
Console.WriteLine($"Creating {irdPath} with key from: {getKeyLog}"); Console.WriteLine($"Creating {irdPath} with key from: {getKeyLog}");
IRD ird3 = new ReIRD(isoPath, getKeyLog); IRD ird1 = new ReIRD(isoPath, getKeyLog);
ird3.Write(irdPath); ird1.Write(irdPath);
if (verbose) if (verbose)
ird3.Print(); ird1.Print();
return irdPath; return irdPath;
} }
catch (ArgumentException e)
{
Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
}
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
Console.Error.WriteLine("File not found, failed to create IRD"); Console.Error.WriteLine("File not found, failed to create IRD");
@@ -758,20 +776,23 @@ namespace IRDKit
try try
{ {
// Read key from .key file // Read key from .key file
byte[] discKey = File.ReadAllBytes(keyfilePath); byte[] discKey = File.ReadAllBytes(keyPath);
if (discKey == null || discKey.Length != 16) if (discKey == null || discKey.Length != 16)
throw new ArgumentException(keyfilePath); Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
else
Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}"); {
IRD ird2 = new ReIRD(isoPath, discKey, layerbreak); IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
ird2.Write(irdPath); Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
if (verbose) ird1.Write(irdPath);
ird2.Print(); if (verbose)
return irdPath; ird1.Print();
return irdPath;
}
} }
catch (ArgumentException) catch (ArgumentException e)
{ {
Console.Error.WriteLine("Given key file not valid, detecting key automatically..."); Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@@ -788,13 +809,18 @@ namespace IRDKit
// Found .getkey.log file, check it is valid // Found .getkey.log file, check it is valid
try try
{ {
Console.WriteLine($"Creating {irdPath} with key from: {logfilePath}"); Console.WriteLine($"Creating {irdPath} with key from: {getKeyLog}");
IRD ird3 = new ReIRD(isoPath, logfilePath); IRD ird1 = new ReIRD(isoPath, getKeyLog);
ird3.Write(irdPath); ird1.Write(irdPath);
if (verbose) if (verbose)
ird3.Print(); ird1.Print();
return irdPath; return irdPath;
} }
catch (ArgumentException e)
{
Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
}
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
Console.Error.WriteLine("File not found, failed to create IRD"); Console.Error.WriteLine("File not found, failed to create IRD");
@@ -868,11 +894,24 @@ namespace IRDKit
// Create IRD with key from redump // Create IRD with key from redump
Console.WriteLine($"Creating {irdPath} with Key from redump.org: {Convert.ToHexString(key)}"); Console.WriteLine($"Creating {irdPath} with Key from redump.org: {Convert.ToHexString(key)}");
IRD ird = new ReIRD(isoPath, key, layerbreak); try
ird.Write(irdPath); {
if (verbose) IRD ird = new ReIRD(isoPath, key, layerbreak);
ird.Print(); ird.Write(irdPath);
return irdPath; if (verbose)
ird.Print();
return irdPath;
}
catch (ArgumentException e)
{
Console.Error.WriteLine(e.Message + ", failed to create IRD");
return null;
}
catch (FileNotFoundException)
{
Console.Error.WriteLine("File not found, failed to create IRD");
return null;
}
} }
#endregion #endregion
-1
View File
@@ -539,7 +539,6 @@ namespace LibIRD
/// <exception cref="InvalidDataException"></exception> /// <exception cref="InvalidDataException"></exception>
private protected void ParseGetKeyLog(string getKeyLog) private protected void ParseGetKeyLog(string getKeyLog)
{ {
// Validate .getkey.log file path // Validate .getkey.log file path
ArgumentNullException.ThrowIfNull(getKeyLog, nameof(getKeyLog)); ArgumentNullException.ThrowIfNull(getKeyLog, nameof(getKeyLog));
if (!File.Exists(getKeyLog)) if (!File.Exists(getKeyLog))
+40 -42
View File
@@ -1,6 +1,8 @@
using System; using DiscUtils.Iso9660;
using System;
using System.IO; using System.IO;
using System.IO.Hashing; using System.IO.Hashing;
using System.Security;
namespace LibIRD namespace LibIRD
{ {
@@ -51,15 +53,6 @@ namespace LibIRD
/// </summary> /// </summary>
public class ReIRD : IRD public class ReIRD : IRD
{ {
#region Properties
/// <summary>
/// ISO file size
/// </summary>
private long Size { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
@@ -67,25 +60,11 @@ namespace LibIRD
/// </summary> /// </summary>
/// <param name="isoPath">Path to the ISO</param> /// <param name="isoPath">Path to the ISO</param>
/// <param name="getKeyLog">Path to the GetKey log file</param> /// <param name="getKeyLog">Path to the GetKey log file</param>
/// <param name="layerbreak">Layerbreak value, in sectors</param>
/// <exception cref="InvalidDataException"></exception> /// <exception cref="InvalidDataException"></exception>
public ReIRD(string isoPath, string getKeyLog, long? layerbreak = null) : base(isoPath, getKeyLog, true) public ReIRD(string isoPath, string getKeyLog) : base(isoPath, getKeyLog, true)
{ {
// Generate Unique Identifier using ISO CRC32 // Generate Unique Identifier using ISO CRC32
UID = GenerateUID(isoPath); UID = GenerateUID(isoPath);
// Determine ISO file size
Size = CalculateSize(isoPath);
// Generate Data 2 using Disc ID
DiscID = GenerateID(Size);
// Generate Disc PIC
byte[] pic = GeneratePIC(Size, layerbreak * SectorSize);
// Check that GetKey log matches expected PIC
if (!((ReadOnlySpan<byte>)PIC).SequenceEqual(pic))
throw new InvalidDataException("Unexpected PIC in .getkey.log");
} }
/// <summary> /// <summary>
@@ -101,16 +80,16 @@ namespace LibIRD
UID = GenerateUID(isoPath); UID = GenerateUID(isoPath);
// Determine ISO file size // Determine ISO file size
Size = CalculateSize(isoPath); long size = CalculateSize(isoPath);
// Set Disc Key // Set Disc Key
DiscKey = key; DiscKey = key;
// Generate Data 2 using Disc ID // Generate Data 2 using Disc ID
DiscID = GenerateID(Size, region); DiscID = GenerateID(size, region);
// Generate Disc PIC // Generate Disc PIC
PIC = GeneratePIC(Size, layerbreak * SectorSize); PIC = GeneratePIC(isoPath, size, layerbreak * SectorSize);
// Generate IRD fields // Generate IRD fields
GenerateIRD(isoPath, true); GenerateIRD(isoPath, true);
@@ -143,12 +122,13 @@ namespace LibIRD
/// <param name="layerbreak">Layer break value, byte at which disc layers are split across</param> /// <param name="layerbreak">Layer break value, byte at which disc layers are split across</param>
/// <param name="exactIRD">True to generate a PIC in 3k3y style (0x03 at 115th byte for BD-50 discs)</param> /// <param name="exactIRD">True to generate a PIC in 3k3y style (0x03 at 115th byte for BD-50 discs)</param>
/// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentException"></exception>
private static byte[] GeneratePIC(long size, long? layerbreak = null, bool exactIRD = false) private static byte[] GeneratePIC(string isoPath, long size, long? layerbreak = null, bool exactIRD = false)
{ {
// Validate size // Validate size
if (size <= 0 || (size % SectorSize) != 0) if (size <= 0 || (size % SectorSize) != 0)
throw new ArgumentException("ISO Size in bytes must be a positive integer multiple of 2048", nameof(size)); throw new ArgumentException("ISO Size in bytes must be a positive integer multiple of 2048", nameof(size));
// Validate layerbreak
// Validate provided layerbreak
if (layerbreak != null) if (layerbreak != null)
{ {
if (layerbreak <= 0 || (layerbreak >= size)) if (layerbreak <= 0 || (layerbreak >= size))
@@ -156,8 +136,16 @@ namespace LibIRD
if (layerbreak >= 2 * BDLayerSize || layerbreak % SectorSize != 0) if (layerbreak >= 2 * BDLayerSize || layerbreak % SectorSize != 0)
throw new ArgumentException("Unexpected layerbreak value", nameof(size)); throw new ArgumentException("Unexpected layerbreak value", nameof(size));
} }
// If layerbreak value was not set, assume it is a non-hybrid disc with default layerbreak else
long layer_break = layerbreak ?? BDLayerSize; {
// If no layerbreak provided, ensure ISO is not BD-Video hybrid
using FileStream fs = new FileStream(isoPath, FileMode.Open, FileAccess.Read) ?? throw new FileNotFoundException(isoPath);
CDReader reader = new(fs, true, true);
if (reader.DirectoryExists("\\BDMV"))
throw new ArgumentException("Layerbreak must be provided for BD-Video hybrid discs");
// Assume disc has default layerbreak
layerbreak = BDLayerSize;
}
// Generate the PIC based on the size and layerbreak of the ISO // Generate the PIC based on the size and layerbreak of the ISO
byte[] pic; byte[] pic;
@@ -167,7 +155,7 @@ namespace LibIRD
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 = (layer_break / 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),
@@ -175,7 +163,7 @@ namespace LibIRD
(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 - (layer_break / 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),
@@ -257,11 +245,16 @@ namespace LibIRD
/// <exception cref="FileNotFoundException"></exception> /// <exception cref="FileNotFoundException"></exception>
private static uint GenerateUID(string isoPath) private static uint GenerateUID(string isoPath)
{ {
// Validate ISO path
ArgumentNullException.ThrowIfNull(isoPath, nameof(isoPath));
// Check file exists // Check file exists
var iso = new FileInfo(isoPath); FileInfo iso;
try
{
iso = new FileInfo(isoPath);
}
catch (Exception e)
{
throw new ArgumentException("Invalid ISO Path: " + e.Message);
}
if (!iso.Exists) if (!iso.Exists)
throw new FileNotFoundException(nameof(isoPath)); throw new FileNotFoundException(nameof(isoPath));
@@ -286,11 +279,16 @@ namespace LibIRD
/// <exception cref="FileNotFoundException"></exception> /// <exception cref="FileNotFoundException"></exception>
private static long CalculateSize(string isoPath) private static long CalculateSize(string isoPath)
{ {
// Validate ISO path
ArgumentNullException.ThrowIfNull(isoPath, nameof(isoPath));
// Check file exists // Check file exists
var iso = new FileInfo(isoPath); FileInfo iso;
try
{
iso = new FileInfo(isoPath);
}
catch (Exception e)
{
throw new ArgumentException("Invalid ISO Path: " + e.Message);
}
if (!iso.Exists) if (!iso.Exists)
throw new FileNotFoundException(nameof(isoPath)); throw new FileNotFoundException(nameof(isoPath));