Attempt to support net40 with ST.Hashing
This commit is contained in:
@@ -5,9 +5,11 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetName>irdkit</TargetName>
|
<TargetName>irdkit</TargetName>
|
||||||
<AssemblyName>irdkit</AssemblyName>
|
<AssemblyName>irdkit</AssemblyName>
|
||||||
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
|
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||||
<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>
|
||||||
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>0.6.1</Version>
|
<Version>0.6.1</Version>
|
||||||
|
|
||||||
@@ -28,7 +30,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.3" />
|
<PackageReference Include="SabreTools.Hashing" Version="1.1.2" />
|
||||||
|
<PackageReference Include="SabreTools.RedumpLib" Version="1.3.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+29
-26
@@ -2,13 +2,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.IO.Hashing;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using CommandLine;
|
using CommandLine;
|
||||||
using LibIRD;
|
using LibIRD;
|
||||||
|
using SabreTools.Hashing;
|
||||||
using SabreTools.RedumpLib.Web;
|
using SabreTools.RedumpLib.Web;
|
||||||
|
|
||||||
namespace IRDKit
|
namespace IRDKit
|
||||||
@@ -704,7 +704,7 @@ namespace IRDKit
|
|||||||
for (int i = 0; i < regionCount; i++)
|
for (int i = 0; i < regionCount; i++)
|
||||||
{
|
{
|
||||||
if (!IRD1.RegionHashes[i].SequenceEqual(IRD2.RegionHashes[i]))
|
if (!IRD1.RegionHashes[i].SequenceEqual(IRD2.RegionHashes[i]))
|
||||||
printText.AppendLine($"Region {i} Hash: {Convert.ToHexString(IRD1.RegionHashes[i])} vs {Convert.ToHexString(IRD2.RegionHashes[i])}");
|
printText.AppendLine($"Region {i} Hash: {LibIRD.IRD.ByteArrayToHexString(IRD1.RegionHashes[i])} vs {LibIRD.IRD.ByteArrayToHexString(IRD2.RegionHashes[i])}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the difference in number of files, if not 0
|
// Print the difference in number of files, if not 0
|
||||||
@@ -720,7 +720,7 @@ namespace IRDKit
|
|||||||
if (j == -1)
|
if (j == -1)
|
||||||
missingOffsets2.Add(IRD1.FileKeys[i]);
|
missingOffsets2.Add(IRD1.FileKeys[i]);
|
||||||
if (j != -1 && !IRD1.FileHashes[i].SequenceEqual(IRD2.FileHashes[j]))
|
if (j != -1 && !IRD1.FileHashes[i].SequenceEqual(IRD2.FileHashes[j]))
|
||||||
printText.AppendLine($"File Hash at Offset {IRD1.FileKeys[i]}: {Convert.ToHexString(IRD1.FileHashes[i])} vs {Convert.ToHexString(IRD2.FileHashes[j])}");
|
printText.AppendLine($"File Hash at Offset {IRD1.FileKeys[i]}: {LibIRD.IRD.ByteArrayToHexString(IRD1.FileHashes[i])} vs {LibIRD.IRD.ByteArrayToHexString(IRD2.FileHashes[j])}");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < IRD2.FileKeys.Length; i++)
|
for (int i = 0; i < IRD2.FileKeys.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -748,15 +748,15 @@ namespace IRDKit
|
|||||||
|
|
||||||
// Print any data 1 key difference
|
// Print any data 1 key difference
|
||||||
if (!IRD1.Data1Key.SequenceEqual(IRD2.Data1Key))
|
if (!IRD1.Data1Key.SequenceEqual(IRD2.Data1Key))
|
||||||
printText.AppendLine($"Data 1 Key: {Convert.ToHexString(IRD1.Data1Key)} vs {Convert.ToHexString(IRD2.Data1Key)}");
|
printText.AppendLine($"Data 1 Key: {LibIRD.IRD.ByteArrayToHexString(IRD1.Data1Key)} vs {LibIRD.IRD.ByteArrayToHexString(IRD2.Data1Key)}");
|
||||||
|
|
||||||
// Print any data 2 key difference
|
// Print any data 2 key difference
|
||||||
if (!IRD1.Data2Key.SequenceEqual(IRD2.Data2Key))
|
if (!IRD1.Data2Key.SequenceEqual(IRD2.Data2Key))
|
||||||
printText.AppendLine($"Data 2 Key: {Convert.ToHexString(IRD1.Data2Key)} vs {Convert.ToHexString(IRD2.Data2Key)}");
|
printText.AppendLine($"Data 2 Key: {LibIRD.IRD.ByteArrayToHexString(IRD1.Data2Key)} vs {LibIRD.IRD.ByteArrayToHexString(IRD2.Data2Key)}");
|
||||||
|
|
||||||
// Print any PIC difference
|
// Print any PIC difference
|
||||||
if (!IRD1.PIC.SequenceEqual(IRD2.PIC))
|
if (!IRD1.PIC.SequenceEqual(IRD2.PIC))
|
||||||
printText.AppendLine($"PIC: {Convert.ToHexString(IRD1.PIC)} vs {Convert.ToHexString(IRD2.PIC)}");
|
printText.AppendLine($"PIC: {LibIRD.IRD.ByteArrayToHexString(IRD1.PIC)} vs {LibIRD.IRD.ByteArrayToHexString(IRD2.PIC)}");
|
||||||
|
|
||||||
// Write formatted string to file if output path provided, otherwise to console
|
// Write formatted string to file if output path provided, otherwise to console
|
||||||
if (outPath != null)
|
if (outPath != null)
|
||||||
@@ -808,7 +808,7 @@ namespace IRDKit
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Get disc key from hex string
|
// Get disc key from hex string
|
||||||
byte[] discKey = Convert.FromHexString(hexKey);
|
byte[] discKey = LibIRD.IRD.HexStringToByteArray(hexKey);
|
||||||
if (discKey == null || discKey.Length != 16)
|
if (discKey == null || discKey.Length != 16)
|
||||||
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
|
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
|
||||||
else
|
else
|
||||||
@@ -844,7 +844,7 @@ namespace IRDKit
|
|||||||
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
|
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
|
Console.WriteLine($"Creating {irdPath} with Key: {LibIRD.IRD.ByteArrayToHexString(discKey)}");
|
||||||
IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
|
IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
|
||||||
ird1.Write(irdPath);
|
ird1.Write(irdPath);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@@ -892,7 +892,7 @@ namespace IRDKit
|
|||||||
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
|
Console.Error.WriteLine($"{hexKey} is not a valid key, detecting key automatically...");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Creating {irdPath} with Key: {Convert.ToHexString(discKey)}");
|
Console.WriteLine($"Creating {irdPath} with Key: {LibIRD.IRD.ByteArrayToHexString(discKey)}");
|
||||||
IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
|
IRD ird1 = new ReIRD(isoPath, discKey, layerbreak);
|
||||||
ird1.Write(irdPath);
|
ird1.Write(irdPath);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@@ -934,22 +934,17 @@ namespace IRDKit
|
|||||||
Console.WriteLine("No key provided... Searching for key on redump.org");
|
Console.WriteLine("No key provided... Searching for key on redump.org");
|
||||||
|
|
||||||
// Compute CRC32 hash
|
// Compute CRC32 hash
|
||||||
byte[] crc32;
|
string crc32String = HashTool.GetFileHash(isoPath, HashType.CRC32); // TODO: Output byte[] once ST.Hashing supports it
|
||||||
uint crc32UInt;
|
uint crc32UInt = BitConverter.ToUInt32(LibIRD.IRD.HexStringToByteArray(crc32String), 0);
|
||||||
using (FileStream fs = File.OpenRead(isoPath))
|
|
||||||
{
|
|
||||||
Crc32 hasher = new();
|
|
||||||
hasher.Append(fs);
|
|
||||||
crc32 = hasher.GetCurrentHash();
|
|
||||||
crc32UInt = BitConverter.ToUInt32(crc32);
|
|
||||||
// Change endianness
|
|
||||||
Array.Reverse(crc32);
|
|
||||||
}
|
|
||||||
string crc32_hash = Convert.ToHexString(crc32).ToLower();
|
|
||||||
|
|
||||||
// Search for ISO on redump.org
|
// Search for ISO on redump.org
|
||||||
|
#if !NETFRAMEWORK
|
||||||
RedumpHttpClient redump = new();
|
RedumpHttpClient redump = new();
|
||||||
List<int> ids = redump.CheckSingleSitePage("http://redump.org/discs/system/ps3/quicksearch/" + crc32_hash).ConfigureAwait(false).GetAwaiter().GetResult();
|
List<int> ids = redump.CheckSingleSitePage("http://redump.org/discs/system/ps3/quicksearch/" + crc32String).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
#else
|
||||||
|
RedumpWebClient redump = new();
|
||||||
|
List<int> ids = redump.CheckSingleSitePage("http://redump.org/discs/system/ps3/quicksearch/" + crc32String);
|
||||||
|
#endif
|
||||||
int id;
|
int id;
|
||||||
if (ids.Count == 0)
|
if (ids.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -965,10 +960,14 @@ namespace IRDKit
|
|||||||
SHA1 hasher = SHA1.Create();
|
SHA1 hasher = SHA1.Create();
|
||||||
sha1 = hasher.ComputeHash(fs);
|
sha1 = hasher.ComputeHash(fs);
|
||||||
}
|
}
|
||||||
string sha1_hash = Convert.ToHexString(sha1).ToLower();
|
string sha1_hash = LibIRD.IRD.ByteArrayToHexString(sha1).ToLower();
|
||||||
|
|
||||||
// Search redump.org for SHA1 hash
|
// Search redump.org for SHA1 hash
|
||||||
|
#if !NETFRAMEWORK
|
||||||
List<int> ids2 = redump.CheckSingleSitePage("http://redump.org/discs/system/ps3/quicksearch/" + sha1_hash).ConfigureAwait(false).GetAwaiter().GetResult();
|
List<int> ids2 = redump.CheckSingleSitePage("http://redump.org/discs/system/ps3/quicksearch/" + sha1_hash).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
#else
|
||||||
|
List<int> ids2 = redump.CheckSingleSitePage("http://redump.org/discs/system/ps3/quicksearch/" + sha1_hash);
|
||||||
|
#endif
|
||||||
if (ids2.Count == 0)
|
if (ids2.Count == 0)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine("ISO not found in redump and no valid key provided, cannot create IRD");
|
Console.Error.WriteLine("ISO not found in redump and no valid key provided, cannot create IRD");
|
||||||
@@ -988,7 +987,11 @@ namespace IRDKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Download key file from redump.org
|
// Download key file from redump.org
|
||||||
|
#if !NETFRAMEWORK
|
||||||
byte[] key = redump.GetByteArrayAsync($"http://redump.org/disc/{id}/key").ConfigureAwait(false).GetAwaiter().GetResult();
|
byte[] key = redump.GetByteArrayAsync($"http://redump.org/disc/{id}/key").ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
#else
|
||||||
|
byte[] key = redump.DownloadData($"http://redump.org/disc/{id}/key");
|
||||||
|
#endif
|
||||||
if (key.Length != 16)
|
if (key.Length != 16)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine("Invalid key obtained from redump and no valid key provided, cannot create IRD");
|
Console.Error.WriteLine("Invalid key obtained from redump and no valid key provided, cannot create IRD");
|
||||||
@@ -996,7 +999,7 @@ 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: {LibIRD.IRD.ByteArrayToHexString(key)}");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IRD ird = new ReIRD(isoPath, key, layerbreak, crc32UInt);
|
IRD ird = new ReIRD(isoPath, key, layerbreak, crc32UInt);
|
||||||
@@ -1045,7 +1048,7 @@ namespace IRDKit
|
|||||||
if (filename == null)
|
if (filename == null)
|
||||||
throw new ArgumentException($"Cannot determine DAT filename for {irdPath}");
|
throw new ArgumentException($"Cannot determine DAT filename for {irdPath}");
|
||||||
if (serial)
|
if (serial)
|
||||||
filename += $" [{ird.TitleID[..4]}-{ird.TitleID[4..9]}]";
|
filename += $" [{ird.TitleID.Substring(0, 4)}-{ird.TitleID.Substring(5, 5)}]";
|
||||||
if (crc)
|
if (crc)
|
||||||
filename += $" [{ird.UID:X8}]";
|
filename += $" [{ird.UID:X8}]";
|
||||||
|
|
||||||
@@ -1071,7 +1074,7 @@ namespace IRDKit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Helper Functions
|
#region Helper Functions
|
||||||
|
|
||||||
|
|||||||
+107
-103
@@ -2,12 +2,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.IO.Hashing;
|
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using LibIRD.DiscUtils;
|
using LibIRD.DiscUtils;
|
||||||
using LibIRD.DiscUtils.Iso9660;
|
using LibIRD.DiscUtils.Iso9660;
|
||||||
using LibIRD.DiscUtils.Streams;
|
using LibIRD.DiscUtils.Streams;
|
||||||
|
using SabreTools.Hashing;
|
||||||
|
|
||||||
namespace LibIRD
|
namespace LibIRD
|
||||||
{
|
{
|
||||||
@@ -803,9 +803,11 @@ namespace LibIRD
|
|||||||
// Begin a GZip stream to write header to
|
// Begin a GZip stream to write header to
|
||||||
using MemoryStream headerStream = new();
|
using MemoryStream headerStream = new();
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
using (GZipStream gzs = new(headerStream, CompressionLevel.SmallestSize))
|
using GZipStream gzStream = new(headerStream, CompressionLevel.SmallestSize);
|
||||||
|
#elif NETCOREAPP || NET45_OR_GREATER
|
||||||
|
using GZipStream gzStream = new(headerStream, CompressionLevel.Optimal);
|
||||||
#else
|
#else
|
||||||
using (GZipStream gzs = new(headerStream, CompressionLevel.Optimal))
|
using GZipStream gzStream = new(headerStream, CompressionMode.Compress);
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// Start reading data from the beginning of the ISO file
|
// Start reading data from the beginning of the ISO file
|
||||||
@@ -817,7 +819,7 @@ namespace LibIRD
|
|||||||
for (int i = 0; i < FirstDataSector; i++)
|
for (int i = 0; i < FirstDataSector; i++)
|
||||||
{
|
{
|
||||||
numBytes = fs.Read(buf, 0, buf.Length);
|
numBytes = fs.Read(buf, 0, buf.Length);
|
||||||
gzs.Write(buf, 0, numBytes);
|
gzStream.Write(buf, 0, numBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,9 +837,11 @@ namespace LibIRD
|
|||||||
// Begin a GZip stream to write footer to
|
// Begin a GZip stream to write footer to
|
||||||
using MemoryStream footerStream = new();
|
using MemoryStream footerStream = new();
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
using (GZipStream gzs = new(footerStream, CompressionLevel.SmallestSize))
|
using GZipStream gzStream = new(footerStream, CompressionLevel.SmallestSize);
|
||||||
|
#elif NETCOREAPP || NET45_OR_GREATER
|
||||||
|
using GZipStream gzStream = new(footerStream, CompressionLevel.Optimal);
|
||||||
#else
|
#else
|
||||||
using (GZipStream gzs = new(footerStream, CompressionLevel.Optimal))
|
using GZipStream gzStream = new(footerStream, CompressionMode.Compress);
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// Start reading data from after last file (PS3UPDAT.PUP)
|
// Start reading data from after last file (PS3UPDAT.PUP)
|
||||||
@@ -849,7 +853,7 @@ namespace LibIRD
|
|||||||
while (numBytes != 0)
|
while (numBytes != 0)
|
||||||
{
|
{
|
||||||
numBytes = fs.Read(buf, 0, buf.Length);
|
numBytes = fs.Read(buf, 0, buf.Length);
|
||||||
gzs.Write(buf, 0, numBytes);
|
gzStream.Write(buf, 0, numBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1038,7 +1042,7 @@ namespace LibIRD
|
|||||||
{
|
{
|
||||||
// Initialise CRC32 ISO hasher, only used if making redump-style IRD
|
// Initialise CRC32 ISO hasher, only used if making redump-style IRD
|
||||||
byte[] crc32;
|
byte[] crc32;
|
||||||
Crc32 isoHasher = new();
|
HashWrapper isoHasher = new(HashType.CRC32);
|
||||||
|
|
||||||
// Initialise MD5 region hashes
|
// Initialise MD5 region hashes
|
||||||
List<int> regions = [];
|
List<int> regions = [];
|
||||||
@@ -1077,7 +1081,7 @@ namespace LibIRD
|
|||||||
// If making redump-style IRD, save CRC32 hash to UID field
|
// If making redump-style IRD, save CRC32 hash to UID field
|
||||||
if (redump)
|
if (redump)
|
||||||
{
|
{
|
||||||
crc32 = isoHasher.GetCurrentHash();
|
crc32 = isoHasher.CurrentHashBytes;
|
||||||
UID = BitConverter.ToUInt32(crc32, 0);
|
UID = BitConverter.ToUInt32(crc32, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1109,7 +1113,7 @@ namespace LibIRD
|
|||||||
|
|
||||||
// Hash ISO
|
// Hash ISO
|
||||||
if (redump)
|
if (redump)
|
||||||
isoHasher.Append(new ReadOnlySpan<byte>(buf, 0, numBytes));
|
isoHasher.Process(buf, 0, numBytes);
|
||||||
|
|
||||||
// Hash regions
|
// Hash regions
|
||||||
List<int> regionsEnded = [];
|
List<int> regionsEnded = [];
|
||||||
@@ -1241,112 +1245,112 @@ namespace LibIRD
|
|||||||
// Create new stream to uncompressed IRD contents
|
// Create new stream to uncompressed IRD contents
|
||||||
using MemoryStream stream = new();
|
using MemoryStream stream = new();
|
||||||
|
|
||||||
// Write IRD data to stream in order
|
// Write IRD data to stream as UTF8
|
||||||
using (BinaryWriter bw = new(stream, Encoding.UTF8, true))
|
using BinaryWriter bw = new(stream, Encoding.UTF8);
|
||||||
|
|
||||||
|
// IRD File Signature
|
||||||
|
bw.Write(Magic);
|
||||||
|
|
||||||
|
// IRD File Version
|
||||||
|
bw.Write(Version);
|
||||||
|
|
||||||
|
// PARAM.SFO / TITLE_ID
|
||||||
|
byte[] titleIDBuf = Encoding.ASCII.GetBytes(TitleID);
|
||||||
|
bw.Write(titleIDBuf, 0, 9);
|
||||||
|
|
||||||
|
// PARAM.SFO / TITLE
|
||||||
|
bw.Write(Title);
|
||||||
|
|
||||||
|
// PARAM.SFO / PS3_SYSTEM_VER
|
||||||
|
byte[] systemVersionBuf = Encoding.ASCII.GetBytes(SystemVersion);
|
||||||
|
bw.Write(systemVersionBuf, 0, 4);
|
||||||
|
|
||||||
|
// PARAM.SFO / VERSION
|
||||||
|
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);
|
||||||
|
byte[] appVersionBuf = new byte[5];
|
||||||
|
Array.Copy(buf, 0, appVersionBuf, 0, buf.Length);
|
||||||
|
bw.Write(appVersionBuf, 0, 5);
|
||||||
|
|
||||||
|
// IRD Unique Identifier, for version 7
|
||||||
|
if (_version == 7)
|
||||||
|
bw.Write(UID);
|
||||||
|
|
||||||
|
// Compress Header
|
||||||
|
bw.Write(HeaderLength);
|
||||||
|
bw.Write(Header, 0, (int)HeaderLength);
|
||||||
|
|
||||||
|
// Compress Footer
|
||||||
|
bw.Write(FooterLength);
|
||||||
|
bw.Write(Footer, 0, (int)FooterLength);
|
||||||
|
|
||||||
|
// Number of regions hashed
|
||||||
|
bw.Write(RegionCount);
|
||||||
|
|
||||||
|
// Hashes for each region
|
||||||
|
for (int i = 0; i < RegionCount; i++)
|
||||||
{
|
{
|
||||||
// IRD File Signature
|
if (RegionHashes[i] == null)
|
||||||
bw.Write(Magic);
|
bw.Write(NullMD5);
|
||||||
|
else
|
||||||
// IRD File Version
|
bw.Write(RegionHashes[i], 0, 16);
|
||||||
bw.Write(Version);
|
|
||||||
|
|
||||||
// PARAM.SFO / TITLE_ID
|
|
||||||
byte[] titleIDBuf = Encoding.ASCII.GetBytes(TitleID);
|
|
||||||
bw.Write(titleIDBuf, 0, 9);
|
|
||||||
|
|
||||||
// PARAM.SFO / TITLE
|
|
||||||
bw.Write(Title);
|
|
||||||
|
|
||||||
// PARAM.SFO / PS3_SYSTEM_VER
|
|
||||||
byte[] systemVersionBuf = Encoding.ASCII.GetBytes(SystemVersion);
|
|
||||||
bw.Write(systemVersionBuf, 0, 4);
|
|
||||||
|
|
||||||
// PARAM.SFO / VERSION
|
|
||||||
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);
|
|
||||||
byte[] appVersionBuf = new byte[5];
|
|
||||||
Array.Copy(buf, 0, appVersionBuf, 0, buf.Length);
|
|
||||||
bw.Write(appVersionBuf, 0, 5);
|
|
||||||
|
|
||||||
// IRD Unique Identifier, for version 7
|
|
||||||
if (_version == 7)
|
|
||||||
bw.Write(UID);
|
|
||||||
|
|
||||||
// Compress Header
|
|
||||||
bw.Write(HeaderLength);
|
|
||||||
bw.Write(Header, 0, (int)HeaderLength);
|
|
||||||
|
|
||||||
// Compress Footer
|
|
||||||
bw.Write(FooterLength);
|
|
||||||
bw.Write(Footer, 0, (int)FooterLength);
|
|
||||||
|
|
||||||
// Number of regions hashed
|
|
||||||
bw.Write(RegionCount);
|
|
||||||
|
|
||||||
// Hashes for each region
|
|
||||||
for (int i = 0; i < RegionCount; i++)
|
|
||||||
{
|
|
||||||
if (RegionHashes[i] == null)
|
|
||||||
bw.Write(NullMD5);
|
|
||||||
else
|
|
||||||
bw.Write(RegionHashes[i], 0, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of files hashed
|
|
||||||
bw.Write(FileCount);
|
|
||||||
|
|
||||||
// Hashes for each file
|
|
||||||
for (int i = 0; i < FileCount; i++)
|
|
||||||
{
|
|
||||||
bw.Write(FileKeys[i]);
|
|
||||||
if (FileHashes[i] == null)
|
|
||||||
bw.Write(NullMD5);
|
|
||||||
else
|
|
||||||
bw.Write(FileHashes[i], 0, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserved fields
|
|
||||||
bw.Write(ExtraConfig);
|
|
||||||
bw.Write(Attachments);
|
|
||||||
|
|
||||||
// PIC data is placed here for Version 9
|
|
||||||
if (_version >= 9)
|
|
||||||
bw.Write(PIC, 0, 115);
|
|
||||||
|
|
||||||
// Disc Authentication keys
|
|
||||||
bw.Write(Data1Key, 0, 16);
|
|
||||||
bw.Write(Data2Key, 0, 16);
|
|
||||||
|
|
||||||
// PIC data is placed here prior to Version 9
|
|
||||||
if (_version < 9)
|
|
||||||
bw.Write(PIC, 0, 115);
|
|
||||||
|
|
||||||
// IRD Unique Identifier, for versions after 7
|
|
||||||
if (_version > 7)
|
|
||||||
bw.Write(UID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Number of files hashed
|
||||||
|
bw.Write(FileCount);
|
||||||
|
|
||||||
|
// Hashes for each file
|
||||||
|
for (int i = 0; i < FileCount; i++)
|
||||||
|
{
|
||||||
|
bw.Write(FileKeys[i]);
|
||||||
|
if (FileHashes[i] == null)
|
||||||
|
bw.Write(NullMD5);
|
||||||
|
else
|
||||||
|
bw.Write(FileHashes[i], 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserved fields
|
||||||
|
bw.Write(ExtraConfig);
|
||||||
|
bw.Write(Attachments);
|
||||||
|
|
||||||
|
// PIC data is placed here for Version 9
|
||||||
|
if (_version >= 9)
|
||||||
|
bw.Write(PIC, 0, 115);
|
||||||
|
|
||||||
|
// Disc Authentication keys
|
||||||
|
bw.Write(Data1Key, 0, 16);
|
||||||
|
bw.Write(Data2Key, 0, 16);
|
||||||
|
|
||||||
|
// PIC data is placed here prior to Version 9
|
||||||
|
if (_version < 9)
|
||||||
|
bw.Write(PIC, 0, 115);
|
||||||
|
|
||||||
|
// IRD Unique Identifier, for versions after 7
|
||||||
|
if (_version > 7)
|
||||||
|
bw.Write(UID);
|
||||||
|
|
||||||
// Calculate the little-endian 32-bit "IEEE 802.3" CRC value of the IRD contents so far
|
// Calculate the little-endian 32-bit "IEEE 802.3" CRC value of the IRD contents so far
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
Crc32 crc32 = new();
|
string crc32String = HashTool.GetStreamHash(stream, HashType.CRC32);
|
||||||
crc32.Append(stream);
|
byte[] crc32 = HexStringToByteArray(crc32String);
|
||||||
byte[] crc = crc32.GetCurrentHash();
|
|
||||||
|
|
||||||
// Write final CRC value to the stream
|
// Write final CRC value to the stream
|
||||||
stream.Write(crc, 0, 4);
|
stream.Write(crc32, 0, 4);
|
||||||
|
|
||||||
// Create the IRD file stream
|
// Create the IRD file stream
|
||||||
using FileStream fs = new(irdPath, FileMode.Create, FileAccess.Write);
|
using FileStream fs = new(irdPath, FileMode.Create, FileAccess.Write);
|
||||||
// Create a GZipped IRD file stream
|
// Create a GZipped IRD file stream
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
using GZipStream gzStream = new(fs, CompressionLevel.SmallestSize);
|
using GZipStream gzStream = new(fs, CompressionLevel.SmallestSize);
|
||||||
#else
|
#elif NETCOREAPP || NET45_OR_GREATER
|
||||||
using GZipStream gzStream = new(fs, CompressionLevel.Optimal);
|
using GZipStream gzStream = new(fs, CompressionLevel.Optimal);
|
||||||
|
#else
|
||||||
|
using GZipStream gzStream = new(fs, CompressionMode.Compress);
|
||||||
#endif
|
#endif
|
||||||
// Write entire gzipped IRD stream to file
|
// Write entire gzipped IRD stream to file
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
@@ -1374,7 +1378,7 @@ namespace LibIRD
|
|||||||
|
|
||||||
// Check for IRD file signature
|
// Check for IRD file signature
|
||||||
byte[] magic = br.ReadBytes(4);
|
byte[] magic = br.ReadBytes(4);
|
||||||
if (!((ReadOnlySpan<byte>)Magic).SequenceEqual(magic))
|
if (magic == null || magic.Length != 4 || magic[0] != Magic[0] || magic[1] != Magic[1] || magic[2] != Magic[2] || magic[3] != Magic[3])
|
||||||
throw new InvalidDataException("IRD file not recognised");
|
throw new InvalidDataException("IRD file not recognised");
|
||||||
|
|
||||||
// Read file version
|
// Read file version
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- Assembly Properties -->
|
||||||
<TargetFrameworks>net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
<TargetFrameworks>net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||||
<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>
|
||||||
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
@@ -28,7 +29,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
<PackageReference Include="SabreTools.Hashing" Version="1.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`netcoreapp3`)) OR $(TargetFramework.StartsWith(`net5`))">
|
<ItemGroup Condition="$(TargetFramework.StartsWith(`netcoreapp3`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||||
|
|||||||
+3
-8
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Hashing;
|
using SabreTools.Hashing;
|
||||||
|
|
||||||
namespace LibIRD
|
namespace LibIRD
|
||||||
{
|
{
|
||||||
@@ -252,13 +252,8 @@ namespace LibIRD
|
|||||||
throw new FileNotFoundException(nameof(isoPath));
|
throw new FileNotFoundException(nameof(isoPath));
|
||||||
|
|
||||||
// Compute CRC32 hash
|
// Compute CRC32 hash
|
||||||
byte[] crc32;
|
string crc32String = HashTool.GetFileHash(isoPath, HashType.CRC32); // TODO: Output byte[] once ST.Hashing supports it
|
||||||
using (FileStream fs = File.OpenRead(isoPath))
|
byte[] crc32 = HexStringToByteArray(crc32String);
|
||||||
{
|
|
||||||
Crc32 hasher = new();
|
|
||||||
hasher.Append(fs);
|
|
||||||
crc32 = hasher.GetCurrentHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redump ISO CRC32 hash is used as the Unique ID in the reproducible IRD
|
// Redump ISO CRC32 hash is used as the Unique ID in the reproducible IRD
|
||||||
return BitConverter.ToUInt32(crc32, 0);
|
return BitConverter.ToUInt32(crc32, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user