diff --git a/LibIRD/PS3ISO.cs b/LibIRD/PS3ISO.cs
index cb4b138..b0a2aea 100644
--- a/LibIRD/PS3ISO.cs
+++ b/LibIRD/PS3ISO.cs
@@ -103,82 +103,13 @@ namespace LibIRD
#endregion
- ///
- /// Process all files and subdirectories recursively
- ///
- ///
- ///
- private void ParseDir(CDReader reader, string path)
- {
- DiscDirectoryInfo dir = reader.GetDirectoryInfo(path);
-
- // Process all files in current directory
- foreach (DiscFileInfo fileInfo in dir.GetFiles())
- {
- // Save directory full path
- // Save offset
- // Save start sector (offset)
- // Save total sectors (count)
- }
-
- // Process all subfolders
- foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
- {
- // Save directory full path
- // Save offset
- // Save start sector (offset)
- // Save total sectors (count)
- ParseDir(reader, dirInfo.FullName);
- }
- }
-
- ///
- /// Determine PUP file offset via extent
- ///
- ///
- ///
- private void GetSystemVersion(FileStream fs, CDReader reader)
- {
-
- //DiscUtils.Streams.StreamExtent[] a = reader.PathToExtents("\\PS3_UPDATE\\PS3UPDAT.PUP");
- //long pupOffset = a[0].Start;
-
- // Determine PUP file offset via cluster
- DiscUtils.Streams.Range[] updateClusters = reader.PathToClusters("\\PS3_UPDATE\\PS3UPDAT.PUP");
- long pupOffset = updateClusters[0] != null ? 2048 * updateClusters[0].Offset : 0;
-
- // Check PUP file Magic
- fs.Seek(pupOffset, SeekOrigin.Begin);
- byte[] pupMagic = new byte[5];
- fs.Read(pupMagic, 0, pupMagic.Length);
- if (Encoding.ASCII.GetString(pupMagic) != "SCEUF")
- {
- // If magic is incorrect, set version to "0000" (unknown)
- SystemVersion = "0000";
- }
- else
- {
- // Determine location of version string
- fs.Seek(pupOffset + 0x3E, SeekOrigin.Begin);
- byte[] offset = new byte[2];
- fs.Read(offset, 0, 2);
- // Move stream to PUP version string
- Array.Reverse(offset);
- ushort versionOffset = BitConverter.ToUInt16(offset, 0);
- fs.Seek(pupOffset + versionOffset, SeekOrigin.Begin);
- // Read version string
- byte[] version = new byte[4];
- fs.Read(version, 0, version.Length);
- // Set version string
- SystemVersion = Encoding.ASCII.GetString(version);
- }
- }
-
///
/// Constructor for generating values from an ISO file
///
/// Path to the ISO
///
+ ///
+ ///
internal PS3ISO(string isoPath)
{
// Validate ISO path
@@ -198,14 +129,14 @@ namespace LibIRD
FileCount = 13;
FileKeys = new ulong[FileCount];
for (int i = 0; i < FileCount; i++)
- FileKeys[i] = (ulong)(i * 16);
+ FileKeys[i] = 0;
FileHashes = new byte[FileCount][];
for (int i = 0; i < FileCount; i++)
FileHashes[i] = NullMD5;
- // Process ISO file
+ // Parse ISO file as a file stream
using FileStream fs = new FileStream(isoPath, FileMode.Open, FileAccess.Read) ?? throw new FileNotFoundException(isoPath);
- // Validate ISO file
+ // Validate ISO file stream
if (!CDReader.Detect(fs))
throw new InvalidDataException("Not a valid ISO file");
@@ -217,7 +148,6 @@ namespace LibIRD
{
// Parse PARAM.SFO file
ParamSFO paramSFO = new(s);
-
// Store required values for IRD
TitleID = paramSFO["TITLE_ID"];
Title = paramSFO["TITLE"];
@@ -228,65 +158,187 @@ namespace LibIRD
// Determine system update version
GetSystemVersion(fs, reader);
+ // Read the ISO header
+ GetHeader(fs, reader);
- // Determine the extent of the Header (Sector 0 to first data sector)
- //DiscUtils.Streams.Range clusters = reader.PathToClusters("\\").First();
- //long firstSector = clusters.Offset;
- //long totalSectors = (long) Math.Ceiling(clusters.Count / 2048.0);
+ // Read the ISO footer
+ GetFooter(fs, reader);
- // Compress the header and store
- DiscUtils.Streams.Range[] sfbClusters = reader.PathToClusters("\\PS3_DISC.SFB");
- long firstSector = sfbClusters[0] != null ? sfbClusters[0].Offset : 0;
- using (MemoryStream headerStream = new())
- {
- using (GZipStream gzs = new(headerStream, CompressionLevel.SmallestSize))
- {
- fs.Seek(0, SeekOrigin.Begin);
- byte[] buf = new byte[2048];
- // Read all sectors before the first data sector
- for (int i = 0; i < firstSector; i++)
- {
- int numBytes = fs.Read(buf, 0, buf.Length);
- gzs.Write(buf, 0, numBytes);
- }
- }
- Header = headerStream.ToArray();
- HeaderLength = (uint)Header.Length;
- }
-
- // Compress the footer and store
- DiscUtils.Streams.StreamExtent[] updateBytes = reader.PathToExtents("\\PS3_UPDATE\\PS3UPDAT.PUP");
- long lastByte = updateBytes[^1].Start + updateBytes[^1].Length;
- using (MemoryStream footerStream = new())
- {
- using (GZipStream gzs = new(footerStream, CompressionLevel.SmallestSize))
- {
- // Start saving data from after last file
- fs.Seek(lastByte, SeekOrigin.Begin);
- byte[] buf = new byte[2048];
- int numBytes = 2048;
- // Keep reading data until there is none left to read
- while (numBytes != 0)
- {
- numBytes = fs.Read(buf, 0, buf.Length);
- gzs.Write(buf, 0, numBytes);
- }
- }
- Footer = footerStream.ToArray();
- FooterLength = (uint)Footer.Length;
- }
-
-
-
- // Get info on root directory
- //DiscDirectoryInfo rootDir = reader.GetDirectoryInfo("\\");
- // Recursively process all subdirectories
+ // Recursively process all directories and files in ISO
ParseDir(reader, "\\");
+ }
- // Calculate last sector
- //DiscDirectoryInfo lastFile = reader.
- //lastSector = lastFile.StartSector + lastFile.TotalSectors;
+ ///
+ /// Process all files and subdirectories recursively
+ ///
+ ///
+ ///
+ private void ParseDir(CDReader reader, string path)
+ {
+ // Process current directory
+ DiscDirectoryInfo dir = reader.GetDirectoryInfo(path);
+ // Process all files in current directory
+ foreach (DiscFileInfo fileInfo in dir.GetFiles())
+ {
+ // Save directory full path
+ // Save offset
+ // Save start sector (offset)
+ // Save total sectors (count)
+ }
+
+ // Recursively process all subfolders of current directory
+ foreach (DiscDirectoryInfo dirInfo in dir.GetDirectories())
+ {
+ // Save directory full path
+ // Save offset
+ // Save start sector (offset)
+ // Save total sectors (count)
+ ParseDir(reader, dirInfo.FullName);
+ }
+ }
+
+ ///
+ /// Retreives and stores the system version
+ ///
+ /// PS3UPDAT.PUP update file version number
+ /// ISO filestream
+ ///
+ ///
+ private void GetSystemVersion(FileStream fs, CDReader reader)
+ {
+ // Determine PUP file offset via cluster
+ long pupOffset;
+ DiscUtils.Streams.Range[] updateClusters = reader.PathToClusters("\\PS3_UPDATE\\PS3UPDAT.PUP");
+ if (updateClusters == null || updateClusters.Length <= 0)
+ {
+ // File too small for dedicated cluster, try get the offset from the file extents instead
+ DiscUtils.Streams.StreamExtent[] updateExtents = reader.PathToExtents("\\PS3_UPDATE\\PS3UPDAT.PUP");
+ if (updateExtents == null || updateExtents.Length <= 0)
+ throw new InvalidDataException("Unexpected PS3UPDAT.PUP file extent in ISO filestream");
+ pupOffset = updateExtents[0].Start;
+ }
+ else
+ {
+ // PS3UPDAT.PUP file begins at first byte of dedicated cluster
+ pupOffset = updateClusters[0] != null ? 2048 * updateClusters[0].Offset : 0;
+ }
+
+ // Check PUP file Magic
+ fs.Seek(pupOffset, SeekOrigin.Begin);
+ byte[] pupMagic = new byte[5];
+ fs.Read(pupMagic, 0, pupMagic.Length);
+ // If magic is incorrect, set version to "0000" (unknown)
+ if (Encoding.ASCII.GetString(pupMagic) != "SCEUF")
+ SystemVersion = "0000";
+ else
+ {
+ // Determine location of version string
+ fs.Seek(pupOffset + 0x3E, SeekOrigin.Begin);
+ byte[] offset = new byte[2];
+ fs.Read(offset, 0, 2);
+ // Move stream to PUP version string
+ Array.Reverse(offset);
+ ushort versionOffset = BitConverter.ToUInt16(offset, 0);
+ fs.Seek(pupOffset + versionOffset, SeekOrigin.Begin);
+ // Read version string
+ byte[] version = new byte[4];
+ fs.Read(version, 0, version.Length);
+ // Set version string
+ SystemVersion = Encoding.ASCII.GetString(version);
+ }
+ }
+
+ ///
+ /// Retreives and stores the header
+ ///
+ /// ISO filestream
+ ///
+ private void GetHeader(FileStream fs, CDReader reader)
+ {
+ // Determine the extent of the geader via cluster (Sector 0 to first data sector)
+ long firstSector;
+ DiscUtils.Streams.Range[] sfbClusters = reader.PathToClusters("\\PS3_DISC.SFB");
+ if (sfbClusters == null || sfbClusters.Length <= 0)
+ {
+ // File too small for dedicated cluster, try get the first sector from the file extents instead
+ DiscUtils.Streams.StreamExtent[] sfbExtents = reader.PathToExtents("\\PS3_DISC.SFB");
+ if (sfbExtents == null || sfbExtents.Length <= 0)
+ throw new InvalidDataException("Unexpected PS3UPDAT.PUP file extent in ISO filestream");
+ firstSector = sfbExtents[0].Start;
+ }
+ else
+ {
+ // End of header is at beginning of first byte of dedicated cluster
+ firstSector = sfbClusters[0] != null ? sfbClusters[0].Offset : 0;
+ }
+
+ // Begin a GZip stream to write header to
+ using MemoryStream headerStream = new();
+ using (GZipStream gzs = new(headerStream, CompressionLevel.SmallestSize))
+ {
+ // Start reading data from the beginning of the ISO file
+ fs.Seek(0, SeekOrigin.Begin);
+ byte[] buf = new byte[2048];
+ int numBytes;
+
+ // Read all data before the first data sector
+ for (int i = 0; i < firstSector; i++)
+ {
+ numBytes = fs.Read(buf, 0, buf.Length);
+ gzs.Write(buf, 0, numBytes);
+ }
+ }
+
+ // Save stream to field
+ Header = headerStream.ToArray();
+ HeaderLength = (uint)Header.Length;
+ }
+
+ ///
+ /// Retreives and stores the footer
+ ///
+ /// ISO filestream
+ ///
+ private void GetFooter(FileStream fs, CDReader reader)
+ {
+ // Determine the extent of the footer via cluster (After last data byte to last ISO sector)
+ long lastByte;
+ DiscUtils.Streams.StreamExtent[] updateBytes = reader.PathToExtents("\\PS3_UPDATE\\PS3UPDAT.PUP");
+ if (updateBytes == null || updateBytes.Length <= 0)
+ {
+ // File too small for dedicated cluster, try get the last byte from the file extents instead
+ DiscUtils.Streams.StreamExtent[] updateExtents = reader.PathToExtents("\\PS3_UPDATE\\PS3UPDAT.PUP");
+ if (updateExtents == null || updateExtents.Length <= 0)
+ throw new InvalidDataException("Unexpected PS3UPDAT.PUP file extent in ISO filestream");
+ lastByte = updateExtents[^1].Start + updateExtents[^1].Length;
+ }
+ else
+ {
+ // Start of footer is after last byte of dedicated cluster
+ lastByte = updateBytes[^1].Start + updateBytes[^1].Length;
+ }
+
+ // Begin a GZip stream to write footer to
+ using MemoryStream footerStream = new();
+ using (GZipStream gzs = new(footerStream, CompressionLevel.SmallestSize))
+ {
+ // Start reading data from after last file
+ fs.Seek(lastByte, SeekOrigin.Begin);
+ byte[] buf = new byte[2048];
+ int numBytes = 2048;
+
+ // Keep reading data until there is none left to read
+ while (numBytes != 0)
+ {
+ numBytes = fs.Read(buf, 0, buf.Length);
+ gzs.Write(buf, 0, numBytes);
+ }
+ }
+
+ // Save stream to field
+ Footer = footerStream.ToArray();
+ FooterLength = (uint)Footer.Length;
}
}
}