Attempt to support net40 with ST.Hashing

This commit is contained in:
Deterous
2024-03-05 14:52:30 +09:00
parent ea3f6d3f96
commit b6bb5f0582
5 changed files with 147 additions and 141 deletions
+107 -103
View File
@@ -2,12 +2,12 @@
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.IO.Hashing;
using System.Security.Cryptography;
using System.Text;
using LibIRD.DiscUtils;
using LibIRD.DiscUtils.Iso9660;
using LibIRD.DiscUtils.Streams;
using SabreTools.Hashing;
namespace LibIRD
{
@@ -803,9 +803,11 @@ namespace LibIRD
// Begin a GZip stream to write header to
using MemoryStream headerStream = new();
#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
using (GZipStream gzs = new(headerStream, CompressionLevel.Optimal))
using GZipStream gzStream = new(headerStream, CompressionMode.Compress);
#endif
{
// Start reading data from the beginning of the ISO file
@@ -817,7 +819,7 @@ namespace LibIRD
for (int i = 0; i < FirstDataSector; i++)
{
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
using MemoryStream footerStream = new();
#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
using (GZipStream gzs = new(footerStream, CompressionLevel.Optimal))
using GZipStream gzStream = new(footerStream, CompressionMode.Compress);
#endif
{
// Start reading data from after last file (PS3UPDAT.PUP)
@@ -849,7 +853,7 @@ namespace LibIRD
while (numBytes != 0)
{
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
byte[] crc32;
Crc32 isoHasher = new();
HashWrapper isoHasher = new(HashType.CRC32);
// Initialise MD5 region hashes
List<int> regions = [];
@@ -1077,7 +1081,7 @@ namespace LibIRD
// If making redump-style IRD, save CRC32 hash to UID field
if (redump)
{
crc32 = isoHasher.GetCurrentHash();
crc32 = isoHasher.CurrentHashBytes;
UID = BitConverter.ToUInt32(crc32, 0);
}
return;
@@ -1109,7 +1113,7 @@ namespace LibIRD
// Hash ISO
if (redump)
isoHasher.Append(new ReadOnlySpan<byte>(buf, 0, numBytes));
isoHasher.Process(buf, 0, numBytes);
// Hash regions
List<int> regionsEnded = [];
@@ -1241,112 +1245,112 @@ namespace LibIRD
// Create new stream to uncompressed IRD contents
using MemoryStream stream = new();
// Write IRD data to stream in order
using (BinaryWriter bw = new(stream, Encoding.UTF8, true))
// Write IRD data to stream as UTF8
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
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++)
{
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);
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);
// Calculate the little-endian 32-bit "IEEE 802.3" CRC value of the IRD contents so far
stream.Position = 0;
Crc32 crc32 = new();
crc32.Append(stream);
byte[] crc = crc32.GetCurrentHash();
string crc32String = HashTool.GetStreamHash(stream, HashType.CRC32);
byte[] crc32 = HexStringToByteArray(crc32String);
// Write final CRC value to the stream
stream.Write(crc, 0, 4);
stream.Write(crc32, 0, 4);
// Create the IRD file stream
using FileStream fs = new(irdPath, FileMode.Create, FileAccess.Write);
// Create a GZipped IRD file stream
#if NET6_0_OR_GREATER
using GZipStream gzStream = new(fs, CompressionLevel.SmallestSize);
#else
#elif NETCOREAPP || NET45_OR_GREATER
using GZipStream gzStream = new(fs, CompressionLevel.Optimal);
#else
using GZipStream gzStream = new(fs, CompressionMode.Compress);
#endif
// Write entire gzipped IRD stream to file
stream.Position = 0;
@@ -1374,7 +1378,7 @@ namespace LibIRD
// Check for IRD file signature
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");
// Read file version
+3 -2
View File
@@ -2,8 +2,9 @@
<PropertyGroup>
<!-- 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>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<LangVersion>latest</LangVersion>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -28,7 +29,7 @@
<ItemGroup>
<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 Condition="$(TargetFramework.StartsWith(`netcoreapp3`)) OR $(TargetFramework.StartsWith(`net5`))">
+3 -8
View File
@@ -1,6 +1,6 @@
using System;
using System.IO;
using System.IO.Hashing;
using SabreTools.Hashing;
namespace LibIRD
{
@@ -252,13 +252,8 @@ namespace LibIRD
throw new FileNotFoundException(nameof(isoPath));
// Compute CRC32 hash
byte[] crc32;
using (FileStream fs = File.OpenRead(isoPath))
{
Crc32 hasher = new();
hasher.Append(fs);
crc32 = hasher.GetCurrentHash();
}
string crc32String = HashTool.GetFileHash(isoPath, HashType.CRC32); // TODO: Output byte[] once ST.Hashing supports it
byte[] crc32 = HexStringToByteArray(crc32String);
// Redump ISO CRC32 hash is used as the Unique ID in the reproducible IRD
return BitConverter.ToUInt32(crc32, 0);