Keep tweaking extraction

This commit is contained in:
Matt Nadareski
2025-07-28 21:14:51 -04:00
parent b3321f9c9a
commit 79943560bc

View File

@@ -118,7 +118,8 @@ namespace SabreTools.Serialization.Wrappers
/// <param name="outDir">Path to the output directory</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Indicates if all files were able to be extracted</returns>
public static bool ExtractAll(string filename, string outDir, bool includeDebug)
/// <remarks>Will extract all items found in the set with forward-only reading</remarks>
public static bool ExtractSet(string filename, string outDir, bool includeDebug)
{
// Get a wrapper for the set
var current = OpenSet(filename);
@@ -144,13 +145,24 @@ namespace SabreTools.Serialization.Wrappers
return true;
}
/// <summary>
/// Extract a cabinet to an output directory, if possible
/// </summary>
/// <param name="filename">Filename for one cabinet in the set</param>
/// <param name="outDir">Path to the output directory</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Indicates if all files were able to be extracted</returns>
/// <remarks>Will read spanned folders but won't attempt to extract unrelated folders</remarks>
public bool ExtractAll(string filename, string outDir, bool includeDebug)
=> ExtractCabinet(filename, outDir, forwardOnly: false, includeDebug);
/// <summary>
/// Extract a cabinet file to an output directory, if possible
/// </summary>
/// <param name="filename">Filename for one cabinet in the set</param>
/// <param name="outDir">Path to the output directory</param>
/// <param name="forwardOnly">Indicates if the cabinet set should only be read forward</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <param name="forwardOnly">Indicates if decompression should be done forward-only</param>
/// <returns>Indicates if all files were able to be extracted</returns>
private bool ExtractCabinet(string filename, string outDir, bool forwardOnly, bool includeDebug)
{
@@ -183,9 +195,14 @@ namespace SabreTools.Serialization.Wrappers
/// <param name="outDir">Path to the output directory</param>
/// <param name="folder">Folder containing the blocks to decompress</param>
/// <param name="folderIndex">Index of the folder in the cabinet</param>
/// <param name="forwardOnly">Indicates if the cabinet set should only be read forward</param>
/// <param name="forwardOnly">Indicates if decompression should be done forward-only</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
private void ExtractFolder(string filename, string outDir, CFFOLDER? folder, int folderIndex, bool forwardOnly, bool includeDebug)
private void ExtractFolder(string filename,
string outDir,
CFFOLDER? folder,
int folderIndex,
bool forwardOnly,
bool includeDebug)
{
// Decompress the blocks, if possible
using var blockStream = DecompressBlocks(filename, folder, folderIndex, forwardOnly);
@@ -448,12 +465,14 @@ namespace SabreTools.Serialization.Wrappers
/// <param name="filename">Filename for one cabinet in the set</param>
/// <param name="folder">Folder containing the blocks to decompress</param>
/// <param name="folderIndex">Index of the folder in the cabinet</param>
/// <param name="forwardOnly">Indicates if the cabinet set should only be read forward</param>
/// <param name="forwardOnly">Indicates if decompression should be done forward-only</param>
/// <returns>Stream representing the decompressed data on success, null otherwise</returns>
public Stream? DecompressBlocks(string filename, CFFOLDER? folder, int folderIndex, bool forwardOnly)
{
// Ensure data blocks
var dataBlocks = GetDataBlocks(filename, folder, folderIndex, skipPrev: forwardOnly, skipNext: false);
var dataBlocks = forwardOnly
? GetDataBlocksForward(filename, folder, folderIndex)
: GetDataBlocks(filename, folder, folderIndex);
if (dataBlocks == null || dataBlocks.Length == 0)
return null;
@@ -481,15 +500,15 @@ namespace SabreTools.Serialization.Wrappers
// MS-ZIP
case CompressionType.TYPE_MSZIP:
long position = ms.Position;
long preMsZipPosition = ms.Position;
mszip.CopyTo(db.CompressedData, ms);
long decompressedSize = ms.Position - position;
long msZipDecompressedSize = ms.Position - preMsZipPosition;
// Pad to the correct size but throw a warning about this
if (decompressedSize < db.UncompressedSize)
if (msZipDecompressedSize < db.UncompressedSize)
{
Console.Error.WriteLine($"Data block {i} in folder {folderIndex} had mismatching sizes. Expected: {db.UncompressedSize}, Got: {decompressedSize}");
byte[] padding = new byte[db.UncompressedSize - decompressedSize];
Console.Error.WriteLine($"Data block {i} in folder {folderIndex} had mismatching sizes. Expected: {db.UncompressedSize}, Got: {msZipDecompressedSize}");
byte[] padding = new byte[db.UncompressedSize - msZipDecompressedSize];
ms.Write(padding, 0, padding.Length);
}
@@ -580,6 +599,16 @@ namespace SabreTools.Serialization.Wrappers
return [.. prevBlocks, .. folder.DataBlocks, .. nextBlocks];
}
/// <summary>
/// Get the set of data blocks for a folder using forward reading only
/// </summary>
/// <param name="filename">Filename for one cabinet in the set</param>
/// <param name="folder">Folder containing the blocks to decompress</param>
/// <param name="folderIndex">Index of the folder in the cabinet</param>
/// <returns>Array of data blocks on success, null otherwise</returns>
private CFDATA[]? GetDataBlocksForward(string filename, CFFOLDER? folder, int folderIndex)
=> GetDataBlocks(filename, folder, folderIndex, skipPrev: true, skipNext: false);
/// <summary>
/// Get all files for the current folder index
/// </summary>