Generate PIC for hybrid discs using layerbreak
This commit is contained in:
+12
-14
@@ -406,8 +406,7 @@ namespace LibIRD
|
||||
private protected static byte[] GenerateD1(byte[] key)
|
||||
{
|
||||
// Validate key
|
||||
if (key == null)
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
ArgumentNullException.ThrowIfNull(key, nameof(key));
|
||||
if (key.Length != 16)
|
||||
throw new ArgumentException("Disc Key must be a byte array of length 16", nameof(key));
|
||||
|
||||
@@ -441,8 +440,7 @@ namespace LibIRD
|
||||
private protected static byte[] GenerateDiscKey(byte[] d1)
|
||||
{
|
||||
// Validate key
|
||||
if (d1 == null)
|
||||
throw new ArgumentNullException(nameof(d1));
|
||||
ArgumentNullException.ThrowIfNull(d1, nameof(d1));
|
||||
if (d1.Length != 16)
|
||||
throw new ArgumentException("Disc Key must be a byte array of length 16", nameof(d1));
|
||||
|
||||
@@ -476,7 +474,7 @@ namespace LibIRD
|
||||
private protected static byte[] GenerateD2(byte[] d2)
|
||||
{
|
||||
// Validate id
|
||||
if (d2 == null) throw new ArgumentNullException(nameof(d2));
|
||||
ArgumentNullException.ThrowIfNull(d2, nameof(d2));
|
||||
if (d2.Length != 16) throw new ArgumentException("Disc ID must be a byte array of length 16", nameof(d2));
|
||||
|
||||
// Setup AES encryption
|
||||
@@ -509,8 +507,7 @@ namespace LibIRD
|
||||
private protected static byte[] GenerateDiscID(byte[] d2)
|
||||
{
|
||||
// Validate id
|
||||
if (d2 == null)
|
||||
throw new ArgumentNullException(nameof(d2));
|
||||
ArgumentNullException.ThrowIfNull(d2 , nameof(d2));
|
||||
if (d2.Length != 16)
|
||||
throw new ArgumentException("Disc ID must be a byte array of length 16", nameof(d2));
|
||||
|
||||
@@ -545,8 +542,7 @@ namespace LibIRD
|
||||
{
|
||||
|
||||
// Validate .getkey.log file path
|
||||
if (getKeyLog == null)
|
||||
throw new ArgumentNullException(nameof(getKeyLog));
|
||||
ArgumentNullException.ThrowIfNull(getKeyLog, nameof(getKeyLog));
|
||||
if (!File.Exists(getKeyLog))
|
||||
throw new FileNotFoundException(nameof(getKeyLog));
|
||||
|
||||
@@ -643,20 +639,22 @@ namespace LibIRD
|
||||
// Redump-style IRDs set the lowest bit of ExtraConfig to 1
|
||||
ExtraConfig |= 0x01;
|
||||
|
||||
// Redump-style IRDs use fields in PS3_DISC.SFB
|
||||
// Redump-style IRDs use fields from 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);
|
||||
|
||||
bool title_id_found = ps3_DiscSFB.Field.TryGetValue("TITLE_ID", out string 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] == '-')
|
||||
TitleID = string.Concat(ps3_DiscSFB.Field["TITLE_ID"].AsSpan(0, 4), ps3_DiscSFB.Field["TITLE_ID"].AsSpan(5, 5));
|
||||
if (title_id_found && title_id.Length == 10 && title_id[4] == '-')
|
||||
TitleID = string.Concat(title_id.AsSpan(0, 4), title_id.AsSpan(5, 5));
|
||||
|
||||
// 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"))
|
||||
DiscVersion = ps3_DiscSFB.Field["VERSION"];
|
||||
bool version_found = ps3_DiscSFB.Field.TryGetValue("VERSION", out string disc_version);
|
||||
if (version_found)
|
||||
DiscVersion = disc_version;
|
||||
}
|
||||
|
||||
// Read PS3 Metadata from PARAM.SFO
|
||||
|
||||
+45
-15
@@ -144,37 +144,65 @@ namespace LibIRD
|
||||
/// Generates the PIC data for a given ISO size in bytes
|
||||
/// </summary>
|
||||
/// <param name="size">Total ISO size in number of bytes</param>
|
||||
/// <param name="layerbreak">Layer break value, byte at which disc layers are split across</param>
|
||||
/// <param name="layer_break">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>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
private static byte[] GeneratePIC(long size, long layerbreak = BDLayerSize, bool exactIRD = false)
|
||||
private static byte[] GeneratePIC(long size, long? layerbreak = null, bool exactIRD = false)
|
||||
{
|
||||
// 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));
|
||||
// Validate layerbreak
|
||||
if (layerbreak == 0 || (layerbreak != BDLayerSize && layerbreak >= size))
|
||||
if (layerbreak != null)
|
||||
{
|
||||
if (layerbreak <= 0 || (layerbreak >= size))
|
||||
throw new ArgumentException("Layerbreak in bytes must be a positive integer less than the ISO Size", nameof(size));
|
||||
if (layerbreak >= 2 * BDLayerSize || layerbreak % SectorSize != 0)
|
||||
throw new ArgumentException("Unexpected layerbreak value", nameof(size));
|
||||
}
|
||||
// If layerbreak value was not set, assume it is a non-hybrid disc with default layerbreak
|
||||
long layer_break = layerbreak ?? BDLayerSize;
|
||||
|
||||
// TODO: Generate correct PICs for Hybrid PS3 discs (BD-50 with layerbreak value other than 12219392)
|
||||
// Generate the PIC based on the size and layerbreak of the ISO
|
||||
byte[] pic;
|
||||
if (size > BDLayerSize) // if BD-50
|
||||
{
|
||||
// num_sectors + layer_sector_end (0x00100000) + sectors_between_layers (0x01358C00 - 0x00CA73FE) - 3
|
||||
byte[] total_sectors = BitConverter.GetBytes((uint)(size / SectorSize + 8067071));
|
||||
// Layer 0 start sector = 0x01000000
|
||||
long l0_start_sector = 1048576;
|
||||
|
||||
// Initial portion of PIC (24 bytes)
|
||||
// Layer 0 end sector = start sector + layerbreak - 2
|
||||
long l0_end_sector = layer_break + l0_start_sector - 2;
|
||||
// Convert end sector location to hex values for PIC
|
||||
byte[] l0es = [(byte)((l0_end_sector >> 24) & 0xFF),
|
||||
(byte)((l0_end_sector >> 16) & 0xFF),
|
||||
(byte)((l0_end_sector >> 8) & 0xFF),
|
||||
(byte)((l0_end_sector >> 0) & 0xFF)];
|
||||
|
||||
// Layer 1 start sector = end of disc (0x01EFFFFE) - layerbreak + 2
|
||||
long l1_start_sector = 32505854 - layer_break + 2;
|
||||
// Convert start of start sector location to hex values for PIC
|
||||
byte[] l1ss = [(byte)((l1_start_sector >> 24) & 0xFF),
|
||||
(byte)((l1_start_sector >> 16) & 0xFF),
|
||||
(byte)((l1_start_sector >> 8) & 0xFF),
|
||||
(byte)((l1_start_sector >> 0) & 0xFF)];
|
||||
|
||||
// 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);
|
||||
byte[] ts = BitConverter.GetBytes((uint) total_sectors);
|
||||
|
||||
// Define the PIC
|
||||
pic = [
|
||||
// Initial portion of PIC (24 bytes)
|
||||
// [4098 bytes] [2x 0x00] ["DI"] [v1] [10units] [DI num]
|
||||
0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x10, 0x00, 0x00, 0x20, 0x00,
|
||||
// ["BDR"] [2 layers]
|
||||
0x42, 0x44, 0x4F, 0x01, 0x21, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Total sectors used on disc (4 bytes)
|
||||
total_sectors[3], total_sectors[2], total_sectors[1], total_sectors[0],
|
||||
ts[3], ts[2], ts[1], ts[0],
|
||||
// 1st Layer sector start location (4 bytes)
|
||||
0x00, 0x10, 0x00, 0x00,
|
||||
// 1st Layer sector end location (4 bytes)
|
||||
0x00, 0xCA, 0x73, 0xFE,
|
||||
// 1st Layer sector end location (4 bytes), 0x00CA73FE for default BD layerbreak of 12219392
|
||||
l0es[0], l0es[1], l0es[2], l0es[3],
|
||||
// 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,
|
||||
@@ -184,9 +212,9 @@ namespace LibIRD
|
||||
// ["BDR"] [2 layers]
|
||||
0x42, 0x44, 0x4F, 0x01, 0x21, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Total sectors used on disc
|
||||
total_sectors[3], total_sectors[2], total_sectors[1], total_sectors[0],
|
||||
// 2nd Layer sector start location
|
||||
0x01, 0x35, 0x8C, 0x00,
|
||||
ts[3], ts[2], ts[1], ts[0],
|
||||
// 2nd Layer sector start location, 0x01358C00 for default BD layerbreak of 12219392
|
||||
l1ss[0], l1ss[1], l1ss[2], l1ss[3],
|
||||
// 2nd Layer sector end location
|
||||
0x01, 0xEF, 0xFF, 0xFE,
|
||||
// Remaining 32 bytes are zeroes
|
||||
@@ -203,8 +231,10 @@ namespace LibIRD
|
||||
// Layer sector end location: num_sectors + layer_sector_end (0x00100000) - 2
|
||||
byte[] end_sector = BitConverter.GetBytes((uint)(size / SectorSize + 1048574));
|
||||
|
||||
// Define the PIC
|
||||
pic = [
|
||||
// Initial portion of PIC (24 bytes)
|
||||
pic = [ 0x10, 0x02, 0x00, 0x00, 0x44, 0x49, 0x01, 0x08, 0x00, 0x00, 0x20, 0x00,
|
||||
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],
|
||||
|
||||
Reference in New Issue
Block a user