diff --git a/BurnOutSharp/External/libmspack/CAB/Decompressor.cs b/BurnOutSharp/External/libmspack/CAB/Decompressor.cs
index 6028a2eb..57e1492d 100644
--- a/BurnOutSharp/External/libmspack/CAB/Decompressor.cs
+++ b/BurnOutSharp/External/libmspack/CAB/Decompressor.cs
@@ -354,59 +354,44 @@ namespace LibMSPackSharp.CAB
}
}
+ // Close existing file handles
+ System.Close(State?.InputFileHandle);
+ System.Close(State?.OutputFileHandle);
+
// Allocate generic decompression state
- if (State == null)
+ State = new DecompressState()
{
- State = new DecompressState() { Sys = System };
+ Folder = fol,
+ Data = fol.Data,
+ Offset = 0,
+ Block = 0,
+ Outlen = 0,
- State.Sys.Read = SysRead;
- State.Sys.Write = SysWrite;
- }
+ Sys = System,
- // Do we need to change folder or reset the current folder?
- if ((State.Folder != fol) || (State.Offset > file.Header.FolderOffset) || State.DecompressorState == null)
- {
- // Free any existing decompressor
- FreeDecompressionState();
+ InputCabinet = fol.Data.Cab,
+ InputFileHandle = System.Open(fol.Data.Cab.Filename, OpenMode.MSPACK_SYS_OPEN_READ),
+ OutputFileHandle = null, // Required for skipping existing data
+ InputPointer = 0,
+ InputEnd = 0,
+ };
- // Do we need to open a new cab file?
- if (State.InputFileHandle == null || (fol.Data.Cab != State.InputCabinet))
- {
- // Close previous file handle if from a different cab
- System.Close(State.InputFileHandle);
- System.Close(State.OutputFileHandle);
+ State.Sys.Read = SysRead;
+ State.Sys.Write = SysWrite;
- State.InputCabinet = fol.Data.Cab;
- State.InputFileHandle = System.Open(fol.Data.Cab.Filename, OpenMode.MSPACK_SYS_OPEN_READ);
- if (State.InputFileHandle == null)
- return Error = Error.MSPACK_ERR_OPEN;
- }
-
- // Seek to start of data blocks
- if (!System.Seek(State.InputFileHandle, fol.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
- return Error = Error.MSPACK_ERR_SEEK;
-
- // Set up decompressor
- if (InitDecompressionState(fol.Header.CompType) != Error.MSPACK_ERR_OK)
- return Error;
-
- // Initialise new folder state
- State.Folder = fol;
- State.Data = fol.Data;
- State.Offset = 0;
- State.Block = 0;
- State.Outlen = 0;
- State.InputPointer = State.InputEnd = 0;
-
- // Read_error lasts for the lifetime of a decompressor
- ReadError = Error.MSPACK_ERR_OK;
- }
-
- // Open file for output
- FileStream fh = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE);
- if (fh == null)
+ if (State.InputFileHandle == null)
return Error = Error.MSPACK_ERR_OPEN;
+ // Seek to start of data blocks
+ if (!System.Seek(State.InputFileHandle, fol.Data.Offset, SeekMode.MSPACK_SYS_SEEK_START))
+ return Error = Error.MSPACK_ERR_SEEK;
+
+ // Set up decompressor
+ if (InitDecompressionState(fol.Header.CompType) != Error.MSPACK_ERR_OK)
+ return Error;
+
+ // ReadError lasts for the lifetime of a decompressor
+ ReadError = Error.MSPACK_ERR_OK;
Error = Error.MSPACK_ERR_OK;
// If file has more than 0 bytes
@@ -417,31 +402,29 @@ namespace LibMSPackSharp.CAB
// Get to correct offset.
// - use null fh to say 'no writing' to cabd_sys_write()
- // - if cabd_sys_read() has an error, it will set self.ReadError
+ // - if SysRead() has an error, it will set self.ReadError
// and pass back MSPACK_ERR_READ
- State.OutputFileHandle = null;
if ((bytes = file.Header.FolderOffset - State.Offset) != 0)
{
- State.OutputFileHandle = fh;
- InitDecompressionState(fol.Header.CompType);
-
error = State.Decompress(State.DecompressorState, bytes);
Error = (error == Error.MSPACK_ERR_READ) ? ReadError : error;
}
+ // Open the output file handle
+ State.OutputFileHandle = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE);
+ if (State.OutputFileHandle == null)
+ return Error = Error.MSPACK_ERR_OPEN;
+
// If getting to the correct offset was error free, unpack file
if (Error == Error.MSPACK_ERR_OK)
{
- State.OutputFileHandle = fh;
- InitDecompressionState(fol.Header.CompType);
-
+ UpdateDecompressionState();
error = State.Decompress(State.DecompressorState, filelen);
Error = (error == Error.MSPACK_ERR_READ) ? ReadError : error;
}
}
// Close output file
- System.Close(fh);
System.Close(State.OutputFileHandle);
return Error;
@@ -543,6 +526,36 @@ namespace LibMSPackSharp.CAB
return Error = (State.DecompressorState != null) ? Error.MSPACK_ERR_OK : Error.MSPACK_ERR_NOMEMORY;
}
+ ///
+ /// Updates the decompression state with a new output
+ ///
+ internal Error UpdateDecompressionState()
+ {
+ switch (State.CompressionType & CompressionType.COMPTYPE_MASK)
+ {
+ case CompressionType.COMPTYPE_NONE:
+ (State.DecompressorState as NoneState).Output = State.OutputFileHandle;
+ break;
+
+ case CompressionType.COMPTYPE_MSZIP:
+ (State.DecompressorState as MSZIPDStream).Output = State.OutputFileHandle;
+ break;
+
+ case CompressionType.COMPTYPE_QUANTUM:
+ (State.DecompressorState as QTMDStream).Output = State.OutputFileHandle;
+ break;
+
+ case CompressionType.COMPTYPE_LZX:
+ (State.DecompressorState as LZXDStream).Output = State.OutputFileHandle;
+ break;
+
+ default:
+ return Error = Error.MSPACK_ERR_DATAFORMAT;
+ }
+
+ return Error = (State.DecompressorState != null) ? Error.MSPACK_ERR_OK : Error.MSPACK_ERR_NOMEMORY;
+ }
+
///
/// Frees decompression state, according to which method was used.
///
@@ -654,7 +667,12 @@ namespace LibMSPackSharp.CAB
///
internal static int SysWrite(object file, byte[] buffer, int pointer, int bytes)
{
- if (file is Decompressor self)
+ // Null output file means skip those bytes
+ if (file == null)
+ {
+ return bytes;
+ }
+ else if (file is Decompressor self)
{
self.State.Offset += (uint)bytes;
if (self.State.OutputFileHandle != null)
diff --git a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
index 13ffd178..42e3827d 100644
--- a/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
+++ b/BurnOutSharp/External/libmspack/Compression/MSZIP.cs
@@ -742,7 +742,7 @@ namespace LibMSPackSharp.Compression
if (!CompressionStream.MakeDecodeTable(19, 7, bl_len, bl_table, msb: false))
return Error.INF_ERR_BITLENTBL;
- // Read literal / distance code lengths */
+ // Read literal / distance code lengths
for (i = 0; i < (lit_codes + dist_codes); i++)
{
// Single-level huffman lookup