mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-24 15:13:23 +00:00
libmspack cleanup
This commit is contained in:
36
BurnOutSharp/External/libmspack/BaseDecompressState.cs
vendored
Normal file
36
BurnOutSharp/External/libmspack/BaseDecompressState.cs
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
public abstract class BaseDecompressState
|
||||
{
|
||||
/// <summary>
|
||||
/// System wrapper for I/O operations
|
||||
/// </summary>
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Persistent error state of the state
|
||||
/// </summary>
|
||||
public Error Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public FileStream InputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public FileStream OutputFileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
32
BurnOutSharp/External/libmspack/BaseDecompressor.cs
vendored
Normal file
32
BurnOutSharp/External/libmspack/BaseDecompressor.cs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of common fields shared by all decompressors
|
||||
/// </summary>
|
||||
public abstract class BaseDecompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// System wrapper for I/O operations
|
||||
/// </summary>
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Persistent error state of the decompressor
|
||||
/// </summary>
|
||||
public Error Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the internal buffer
|
||||
/// </summary>
|
||||
public int BufferSize { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,10 @@
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
public class Implementation
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Base class for decompressor-used objects
|
||||
/// </summary>
|
||||
public abstract class BaseHeader { }
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace LibMSPackSharp.CAB
|
||||
/// <see cref="Decompressor.Open(string)"/>
|
||||
/// <see cref="Decompressor.Close(Cabinet)"/>
|
||||
/// <see cref="Decompressor.Search(string)"/>
|
||||
public class Cabinet
|
||||
public class Cabinet : BaseHeader
|
||||
{
|
||||
#region Internal
|
||||
|
||||
|
||||
91
BurnOutSharp/External/libmspack/CAB/Constants.cs
vendored
91
BurnOutSharp/External/libmspack/CAB/Constants.cs
vendored
@@ -1,91 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2018 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
/* Cabinet (.CAB) files are a form of file archive. Each cabinet contains
|
||||
* "folders", which are compressed spans of data. Each cabinet has
|
||||
* "files", whose metadata is in the cabinet header, but whose actual data
|
||||
* is stored compressed in one of the "folders". Cabinets can span more
|
||||
* than one physical file on disk, in which case they are a "cabinet set",
|
||||
* and usually the last folder of each cabinet extends into the next
|
||||
* cabinet.
|
||||
*
|
||||
* For a complete description of the format, see the MSDN site:
|
||||
* http://msdn.microsoft.com/en-us/library/bb267310.aspx
|
||||
*/
|
||||
|
||||
/* Notes on compliance with cabinet specification:
|
||||
*
|
||||
* One of the main changes between cabextract 0.6 and libmspack's cab
|
||||
* decompressor is the move from block-oriented decompression to
|
||||
* stream-oriented decompression.
|
||||
*
|
||||
* cabextract would read one data block from disk, decompress it with the
|
||||
* appropriate method, then write the decompressed data. The CAB
|
||||
* specification is specifically designed to work like this, as it ensures
|
||||
* compression matches do not span the maximum decompressed block size
|
||||
* limit of 32kb.
|
||||
*
|
||||
* However, the compression algorithms used are stream oriented, with
|
||||
* specific hacks added to them to enforce the "individual 32kb blocks"
|
||||
* rule in CABs. In other file formats, they do not have this limitation.
|
||||
*
|
||||
* In order to make more generalised decompressors, libmspack's CAB
|
||||
* decompressor has moved from being block-oriented to more stream
|
||||
* oriented. This also makes decompression slightly faster.
|
||||
*
|
||||
* However, this leads to incompliance with the CAB specification. The
|
||||
* CAB controller can no longer ensure each block of input given to the
|
||||
* decompressors is matched with their output. The "decompressed size" of
|
||||
* each individual block is thrown away.
|
||||
*
|
||||
* Each CAB block is supposed to be seen as individually compressed. This
|
||||
* means each consecutive data block can have completely different
|
||||
* "uncompressed" sizes, ranging from 1 to 32768 bytes. However, in
|
||||
* reality, all data blocks in a folder decompress to exactly 32768 bytes,
|
||||
* excepting the final block.
|
||||
*
|
||||
* Given this situation, the decompression algorithms are designed to
|
||||
* realign their input bitstreams on 32768 output-byte boundaries, and
|
||||
* various other special cases have been made. libmspack will not
|
||||
* correctly decompress LZX or Quantum compressed folders where the blocks
|
||||
* do not follow this "32768 bytes until last block" pattern. It could be
|
||||
* implemented if needed, but hopefully this is not necessary -- it has
|
||||
* not been seen in over 3Gb of CAB archives.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
// CAB data blocks are <= 32768 bytes in uncompressed form.Uncompressed
|
||||
// blocks have zero growth. MSZIP guarantees that it won't grow above
|
||||
// uncompressed size by more than 12 bytes.LZX guarantees it won't grow
|
||||
// more than 6144 bytes.Quantum has no documentation, but the largest
|
||||
// block seen in the wild is 337 bytes above uncompressed size.
|
||||
|
||||
public const int CAB_BLOCKMAX = 32768;
|
||||
public const int CAB_INPUTMAX = CAB_BLOCKMAX + 6144;
|
||||
|
||||
// input buffer needs to be CAB_INPUTMAX + 1 byte to allow for max-sized block
|
||||
// plus 1 trailer byte added by cabd_sys_read_block() for Quantum alignment.
|
||||
//
|
||||
// When MSCABD_PARAM_SALVAGE is set, block size is not checked so can be
|
||||
// up to 65535 bytes, so max input buffer size needed is 65535 + 1
|
||||
|
||||
public const int CAB_INPUTMAX_SALVAGE = 65535;
|
||||
public const int CAB_INPUTBUF = CAB_INPUTMAX_SALVAGE + 1;
|
||||
|
||||
// There are no more than 65535 data blocks per folder, so a folder cannot
|
||||
// be more than 32768*65535 bytes in length.As files cannot span more than
|
||||
// one folder, this is also their max offset, length and offset+length limit.
|
||||
|
||||
public const int CAB_FOLDERMAX = 65535;
|
||||
public const int CAB_LENGTHMAX = CAB_BLOCKMAX * CAB_FOLDERMAX;
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,10 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class DecompressState
|
||||
public class DecompressState : BaseDecompressState
|
||||
{
|
||||
/// <summary>
|
||||
/// Current folder we're extracting from
|
||||
@@ -39,11 +38,6 @@ namespace LibMSPackSharp.CAB
|
||||
/// </summary>
|
||||
public long Outlen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Special I/O code for decompressor
|
||||
/// </summary>
|
||||
public SystemImpl Sys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of compression used by folder
|
||||
/// </summary>
|
||||
@@ -57,23 +51,13 @@ namespace LibMSPackSharp.CAB
|
||||
/// <summary>
|
||||
/// Decompressor state
|
||||
/// </summary>
|
||||
public object DecompressorState { get; set; }
|
||||
public BaseDecompressState DecompressorState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cabinet where input data comes from
|
||||
/// </summary>
|
||||
public Cabinet InputCabinet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public FileStream InputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public FileStream OutputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input data consumed
|
||||
/// </summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using LibMSPackSharp.Compression;
|
||||
using static LibMSPackSharp.CAB.Constants;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
@@ -29,24 +29,18 @@ namespace LibMSPackSharp.CAB
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateCABDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyCABDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public DecompressState State { get; set; }
|
||||
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public int BufferSize { get; set; }
|
||||
|
||||
public int SearchBufferSize { get; set; }
|
||||
|
||||
public bool FixMSZip { get; set; }
|
||||
|
||||
public bool Salvage { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
|
||||
public Error ReadError { get; set; }
|
||||
|
||||
#endregion
|
||||
@@ -294,6 +288,7 @@ namespace LibMSPackSharp.CAB
|
||||
/// <see cref="Close(Cabinet)"/>
|
||||
public Error Prepend(Cabinet cab, Cabinet prevcab) => Merge(prevcab, cab);
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Extracts a file from a cabinet or cabinet set.
|
||||
///
|
||||
@@ -367,7 +362,7 @@ namespace LibMSPackSharp.CAB
|
||||
Block = 0,
|
||||
Outlen = 0,
|
||||
|
||||
Sys = System,
|
||||
System = System,
|
||||
|
||||
InputCabinet = fol.Data.Cab,
|
||||
InputFileHandle = System.Open(fol.Data.Cab.Filename, OpenMode.MSPACK_SYS_OPEN_READ),
|
||||
@@ -376,8 +371,8 @@ namespace LibMSPackSharp.CAB
|
||||
InputEnd = 0,
|
||||
};
|
||||
|
||||
State.Sys.Read = SysRead;
|
||||
State.Sys.Write = SysWrite;
|
||||
State.System.Read = SysRead;
|
||||
State.System.Write = SysWrite;
|
||||
|
||||
if (State.InputFileHandle == null)
|
||||
return Error = Error.MSPACK_ERR_OPEN;
|
||||
@@ -501,22 +496,22 @@ namespace LibMSPackSharp.CAB
|
||||
{
|
||||
case CompressionType.COMPTYPE_NONE:
|
||||
State.Decompress = None.Decompress;
|
||||
State.DecompressorState = None.Init(State.Sys, State.InputFileHandle, State.OutputFileHandle, BufferSize);
|
||||
State.DecompressorState = None.Init(State.System, State.InputFileHandle, State.OutputFileHandle, BufferSize);
|
||||
break;
|
||||
|
||||
case CompressionType.COMPTYPE_MSZIP:
|
||||
State.Decompress = MSZIP.Decompress;
|
||||
State.DecompressorState = MSZIP.Init(State.Sys, State.InputFileHandle, State.OutputFileHandle, BufferSize, FixMSZip);
|
||||
State.DecompressorState = MSZIP.Init(State.System, State.InputFileHandle, State.OutputFileHandle, BufferSize, FixMSZip);
|
||||
break;
|
||||
|
||||
case CompressionType.COMPTYPE_QUANTUM:
|
||||
State.Decompress = QTM.Decompress;
|
||||
State.DecompressorState = QTM.Init(State.Sys, State.InputFileHandle, State.OutputFileHandle, ((ushort)ct >> 8) & 0x1f, BufferSize);
|
||||
State.DecompressorState = QTM.Init(State.System, State.InputFileHandle, State.OutputFileHandle, ((ushort)ct >> 8) & 0x1f, BufferSize);
|
||||
break;
|
||||
|
||||
case CompressionType.COMPTYPE_LZX:
|
||||
State.Decompress = LZX.Decompress;
|
||||
State.DecompressorState = LZX.Init(State.Sys, State.InputFileHandle, State.OutputFileHandle, ((ushort)ct >> 8) & 0x1f, 0, BufferSize, 0, false);
|
||||
State.DecompressorState = LZX.Init(State.System, State.InputFileHandle, State.OutputFileHandle, ((ushort)ct >> 8) & 0x1f, 0, BufferSize, 0, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -534,19 +529,10 @@ namespace LibMSPackSharp.CAB
|
||||
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;
|
||||
State.DecompressorState.OutputFileHandle = State.OutputFileHandle;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
2
BurnOutSharp/External/libmspack/CHM/CHM.cs
vendored
2
BurnOutSharp/External/libmspack/CHM/CHM.cs
vendored
@@ -21,7 +21,7 @@ namespace LibMSPackSharp.CHM
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class CHM
|
||||
public class CHM : BaseHeader
|
||||
{
|
||||
#region Internal
|
||||
|
||||
|
||||
53
BurnOutSharp/External/libmspack/CHM/Constants.cs
vendored
53
BurnOutSharp/External/libmspack/CHM/Constants.cs
vendored
@@ -1,53 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
public class Constants
|
||||
{
|
||||
// _PMGHeader
|
||||
internal const int pmgl_Signature = 0x0000;
|
||||
internal const int pmgl_QuickRefSize = 0x0004;
|
||||
internal const int pmgl_PMGIEntries = 0x0008; // Unknown1 in PMGL
|
||||
internal const int pmgl_PrevChunk = 0x000C; // Not in PMGI
|
||||
internal const int pmgl_NextChunk = 0x0010; // Not in PMGI
|
||||
internal const int pmgl_PMGLEntries = 0x0014; // Not in PMGI
|
||||
internal const int pmgl_headerSIZEOF = 0x0014;
|
||||
internal const int pmgi_headerSIZEOF = 0x000C;
|
||||
|
||||
// _LZXControlData
|
||||
internal const int lzxcd_Length = 0x0000;
|
||||
internal const int lzxcd_Signature = 0x0004;
|
||||
internal const int lzxcd_Version = 0x0008;
|
||||
internal const int lzxcd_ResetInterval = 0x000C;
|
||||
internal const int lzxcd_WindowSize = 0x0010;
|
||||
internal const int lzxcd_CacheSize = 0x0014;
|
||||
internal const int lzxcd_Unknown1 = 0x0018;
|
||||
internal const int lzxcd_SIZEOF = 0x001C;
|
||||
|
||||
// _LZXResetTable
|
||||
internal const int lzxrt_Unknown1 = 0x0000;
|
||||
internal const int lzxrt_NumEntries = 0x0004;
|
||||
internal const int lzxrt_EntrySize = 0x0008;
|
||||
internal const int lzxrt_TableOffset = 0x000C;
|
||||
internal const int lzxrt_UncompLen = 0x0010;
|
||||
internal const int lzxrt_CompLen = 0x0018;
|
||||
internal const int lzxrt_FrameLen = 0x0020;
|
||||
internal const int lzxrt_Entries = 0x0028;
|
||||
internal const int lzxrt_headerSIZEOF = 0x0028;
|
||||
|
||||
// Filenames of the system files used for decompression.
|
||||
// - Content and ControlData are essential.
|
||||
// - ResetTable is preferred, but SpanInfo can be used if not available
|
||||
internal const string ContentName = "::DataSpace/Storage/MSCompressed/Content";
|
||||
internal const string ControlName = "::DataSpace/Storage/MSCompressed/ControlData";
|
||||
internal const string SpanInfoName = "::DataSpace/Storage/MSCompressed/SpanInfo";
|
||||
internal const string ResetTableName = "::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable";
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,11 @@
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
public class DecompressState
|
||||
public class DecompressState : BaseDecompressState
|
||||
{
|
||||
/// <summary>
|
||||
/// CHM file being decompressed
|
||||
@@ -33,20 +32,5 @@ namespace LibMSPackSharp.CHM
|
||||
/// LZX decompressor state
|
||||
/// </summary>
|
||||
public LZXDStream State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Special I/O code for decompressor
|
||||
/// </summary>
|
||||
public SystemImpl Sys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public FileStream InputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public FileStream OutputFileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using LibMSPackSharp.Compression;
|
||||
using static LibMSPackSharp.CHM.Constants;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
@@ -29,16 +29,12 @@ namespace LibMSPackSharp.CHM
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateCHMDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyCHMDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public DecompressState State { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functionality
|
||||
@@ -62,10 +58,7 @@ namespace LibMSPackSharp.CHM
|
||||
/// </param>
|
||||
/// <returns>a pointer to a mschmd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Close(CHM)"/>
|
||||
public CHM Open(string filename)
|
||||
{
|
||||
return RealOpen(filename, true);
|
||||
}
|
||||
public CHM Open(string filename) => RealOpen(filename, true);
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened CHM helpfile.
|
||||
@@ -137,8 +130,8 @@ namespace LibMSPackSharp.CHM
|
||||
State.Header = chm;
|
||||
State.Offset = 0;
|
||||
State.State = null;
|
||||
State.Sys = System;
|
||||
State.Sys.Write = SysWrite;
|
||||
State.System = System;
|
||||
State.System.Write = SysWrite;
|
||||
State.InputFileHandle = null;
|
||||
State.OutputFileHandle = null;
|
||||
}
|
||||
@@ -279,10 +272,7 @@ namespace LibMSPackSharp.CHM
|
||||
/// <see cref="Close(CHM)"/>
|
||||
/// <see cref="FastFind(CHM, string, DecompressFile)"/>
|
||||
/// <see cref="Extract(DecompressFile, string)"/>
|
||||
public CHM FastOpen(string filename)
|
||||
{
|
||||
return RealOpen(filename, false);
|
||||
}
|
||||
public CHM FastOpen(string filename) => RealOpen(filename, false);
|
||||
|
||||
/// <summary>
|
||||
/// Finds file details quickly.
|
||||
@@ -587,7 +577,7 @@ namespace LibMSPackSharp.CHM
|
||||
length -= State.Offset;
|
||||
|
||||
// Initialise LZX stream
|
||||
State.State = LZX.Init(State.Sys, State.InputFileHandle, State.OutputFileHandle, window_bits, reset_interval / LZX.LZX_FRAME_SIZE, 4096, length, false);
|
||||
State.State = LZX.Init(State.System, State.InputFileHandle, State.OutputFileHandle, window_bits, reset_interval / LZX.LZX_FRAME_SIZE, 4096, length, false);
|
||||
|
||||
if (State.State == null)
|
||||
Error = Error.MSPACK_ERR_NOMEMORY;
|
||||
|
||||
@@ -11,33 +11,15 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public abstract class CompressionStream
|
||||
public abstract class CompressionStream : BaseDecompressState
|
||||
{
|
||||
private const int CHAR_BIT = 8;
|
||||
|
||||
public const int BITBUF_WIDTH = 4 * CHAR_BIT;
|
||||
|
||||
/// <summary>
|
||||
/// I/O routines
|
||||
/// </summary>
|
||||
public SystemImpl Sys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public FileStream Input { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public FileStream Output { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
|
||||
#region I/O buffering
|
||||
|
||||
public byte[] InputBuffer { get; set; }
|
||||
@@ -135,7 +117,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
public Error ReadInput()
|
||||
{
|
||||
int read = Sys.Read(Input, InputBuffer, 0, (int)InputBufferSize);
|
||||
int read = System.Read(InputFileHandle, InputBuffer, 0, (int)InputBufferSize);
|
||||
if (read < 0)
|
||||
return Error = Error.MSPACK_ERR_READ;
|
||||
|
||||
|
||||
@@ -7,415 +7,39 @@
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using LibMSPackSharp.Compression;
|
||||
using LibMSPackSharp.KWAJ;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public class Implementation
|
||||
/// <summary>
|
||||
/// In the KWAJ LZH format, there is no special 'eof' marker, it just
|
||||
/// ends. Depending on how many bits are left in the final byte when
|
||||
/// the stream ends, that might be enough to start another literal or
|
||||
/// match. The only easy way to detect that we've come to an end is to
|
||||
/// guard all bit-reading. We allow fake bits to be read once we reach
|
||||
/// the end of the stream, but we check if we then consumed any of
|
||||
/// those fake bits, after doing the READ_BITS / READ_HUFFSYM. This
|
||||
/// isn't how the default ReadInput works (it simply lets
|
||||
/// 2 fake bytes in then stops), so we implement our own.
|
||||
/// </summary>
|
||||
public class LZHKWAJ
|
||||
{
|
||||
#region Generic KWAJ Definitions
|
||||
|
||||
private const byte kwajh_Signature1 = 0x00;
|
||||
private const byte kwajh_Signature2 = 0x04;
|
||||
private const byte kwajh_CompMethod = 0x08;
|
||||
private const byte kwajh_DataOffset = 0x0a;
|
||||
private const byte kwajh_Flags = 0x0c;
|
||||
private const byte kwajh_SIZEOF = 0x0e;
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJ Decompression Definitions
|
||||
|
||||
// Input buffer size during decompression - not worth parameterising IMHO
|
||||
private const int KWAJ_INPUT_SIZE = (2048);
|
||||
|
||||
// Huffman codes that are 9 bits or less are decoded immediately
|
||||
public const int KWAJ_TABLEBITS = (9);
|
||||
|
||||
// Number of codes in each huffman table
|
||||
|
||||
public const int KWAJ_MATCHLEN1_SYMS = (16);
|
||||
public const int KWAJ_MATCHLEN2_SYMS = (16);
|
||||
public const int KWAJ_LITLEN_SYMS = (32);
|
||||
public const int KWAJ_OFFSET_SYMS = (64);
|
||||
public const int KWAJ_LITERAL_SYMS = (256);
|
||||
|
||||
// Define decoding table sizes
|
||||
|
||||
public const int KWAJ_TABLESIZE = (1 << KWAJ_TABLEBITS);
|
||||
|
||||
//public const int KWAJ_MATCHLEN1_TBLSIZE = (KWAJ_MATCHLEN1_SYMS * 4);
|
||||
public const int KWAJ_MATCHLEN1_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_MATCHLEN1_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_MATCHLEN2_TBLSIZE = (KWAJ_MATCHLEN2_SYMS * 4);
|
||||
public const int KWAJ_MATCHLEN2_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_MATCHLEN2_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_LITLEN_TBLSIZE = (KWAJ_LITLEN_SYMS * 4);
|
||||
public const int KWAJ_LITLEN_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_LITLEN_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_OFFSET_TBLSIZE = (KWAJ_OFFSET_SYMS * 4);
|
||||
public const int KWAJ_OFFSET_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_OFFSET_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_LITERAL_TBLSIZE = (KWAJ_LITERAL_SYMS * 4);
|
||||
public const int KWAJ_LITERAL_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_LITERAL_SYMS * 2));
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_OPEN
|
||||
|
||||
/// <summary>
|
||||
/// Opens a KWAJ file without decompressing, reads header
|
||||
/// </summary>
|
||||
public static Header Open(Decompressor d, string filename)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self == null)
|
||||
return null;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
FileStream fh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
HeaderImpl hdr = new HeaderImpl();
|
||||
if (fh != null && hdr != null)
|
||||
{
|
||||
hdr.FileHandle = fh;
|
||||
self.Error = ReadHeaders(sys, fh, hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fh == null)
|
||||
self.Error = Error.MSPACK_ERR_OPEN;
|
||||
if (hdr == null)
|
||||
self.Error = Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
if (self.Error != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
if (fh != null)
|
||||
sys.Close(fh);
|
||||
|
||||
hdr = null;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_CLOSE
|
||||
|
||||
/// <summary>
|
||||
/// Closes a KWAJ file
|
||||
/// </summary>
|
||||
public static void Close(Decompressor d, Header hdr)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
HeaderImpl hdr_p = hdr as HeaderImpl;
|
||||
|
||||
if (self?.System == null || hdr_p == null)
|
||||
return;
|
||||
|
||||
// Close the file handle associated
|
||||
self.System.Close(hdr_p.FileHandle);
|
||||
|
||||
self.Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_READ_HEADERS
|
||||
|
||||
/// <summary>
|
||||
/// Reads the headers of a KWAJ format file
|
||||
/// </summary>
|
||||
public static Error ReadHeaders(SystemImpl sys, FileStream fh, Header hdr)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Read in the header
|
||||
byte[] buf = new byte[16];
|
||||
if (sys.Read(fh, buf, 0, kwajh_SIZEOF) != kwajh_SIZEOF)
|
||||
{
|
||||
return Error.MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
// Check for "KWAJ" signature
|
||||
if ((BitConverter.ToUInt32(buf, kwajh_Signature1) != 0x4A41574B) ||
|
||||
(BitConverter.ToUInt32(buf, kwajh_Signature2) != 0xD127F088))
|
||||
{
|
||||
return Error.MSPACK_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
// Basic header fields
|
||||
hdr.CompressionType = (CompressionType)BitConverter.ToUInt16(buf, kwajh_CompMethod);
|
||||
hdr.DataOffset = BitConverter.ToUInt16(buf, kwajh_DataOffset);
|
||||
hdr.Headers = (OptionalHeaderFlag)BitConverter.ToUInt16(buf, kwajh_Flags);
|
||||
hdr.Length = 0;
|
||||
hdr.Filename = null;
|
||||
hdr.Extra = null;
|
||||
hdr.ExtraLength = 0;
|
||||
|
||||
// Optional headers
|
||||
|
||||
// 4 bytes: length of unpacked file
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASLENGTH))
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, 4) != 4)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
hdr.Length = BitConverter.ToUInt32(buf, 0);
|
||||
}
|
||||
|
||||
// 2 bytes: unknown purpose
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN1))
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, 2) != 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
// 2 bytes: length of section, then [length] bytes: unknown purpose
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN2))
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, 2) != 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
i = BitConverter.ToUInt16(buf, 0);
|
||||
if (sys.Seek(fh, i, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
// Filename and extension
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME) || hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
|
||||
{
|
||||
int len;
|
||||
|
||||
// Allocate memory for maximum length filename
|
||||
char[] fn = new char[13];
|
||||
int fnPtr = 0;
|
||||
|
||||
// Copy filename if present
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME))
|
||||
{
|
||||
// Read and copy up to 9 bytes of a null terminated string
|
||||
if ((len = sys.Read(fh, buf, 0, 9)) < 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((fn[fnPtr++] = (char)buf[i]) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
// If string was 9 bytes with no null terminator, reject it
|
||||
if (i == 9 && buf[8] != '\0')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
// Seek to byte after string ended in file
|
||||
if (sys.Seek(fh, i + 1 - len, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
fnPtr--; // Remove the null terminator
|
||||
}
|
||||
|
||||
// Copy extension if present
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
|
||||
{
|
||||
fn[fnPtr++] = '.';
|
||||
|
||||
// Read and copy up to 4 bytes of a null terminated string
|
||||
if ((len = sys.Read(fh, buf, 0, 4)) < 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((fn[fnPtr++] = (char)buf[i]) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
// If string was 4 bytes with no null terminator, reject it
|
||||
if (i == 4 && buf[3] != '\0')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
// Seek to byte after string ended in file
|
||||
if (sys.Seek(fh, i + 1 - len, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
fnPtr--; // Remove the null terminator
|
||||
}
|
||||
|
||||
fn[fnPtr] = '\0';
|
||||
}
|
||||
|
||||
// 2 bytes: extra text length then [length] bytes of extra text data
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASEXTRATEXT))
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, 2) != 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
i = BitConverter.ToUInt16(buf, 0);
|
||||
byte[] extra = new byte[i + 1];
|
||||
if (sys.Read(fh, extra, 0, i) != i)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
extra[i] = 0x00;
|
||||
hdr.Extra = Encoding.ASCII.GetString(extra, 0, extra.Length);
|
||||
hdr.ExtraLength = (ushort)i;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_EXTRACT
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses a KWAJ file
|
||||
/// </summary>
|
||||
public static Error Extract(Decompressor d, Header hdr, string filename)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
if (hdr == null)
|
||||
return self.Error = Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
FileStream fh = (hdr as HeaderImpl)?.FileHandle;
|
||||
if (fh == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
// Seek to the compressed data
|
||||
if (sys.Seek(fh, hdr.DataOffset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return self.Error = Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Open file for output
|
||||
FileStream outfh;
|
||||
if ((outfh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
|
||||
return self.Error = Error.MSPACK_ERR_OPEN;
|
||||
|
||||
self.Error = Error.MSPACK_ERR_OK;
|
||||
|
||||
// Decompress based on format
|
||||
if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_NONE ||
|
||||
hdr.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
|
||||
{
|
||||
// NONE is a straight copy. XOR is a copy xored with 0xFF
|
||||
byte[] buf = new byte[KWAJ_INPUT_SIZE];
|
||||
|
||||
int read, i;
|
||||
while ((read = sys.Read(fh, buf, 0, KWAJ_INPUT_SIZE)) > 0)
|
||||
{
|
||||
if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
|
||||
{
|
||||
for (i = 0; i < read; i++)
|
||||
{
|
||||
buf[i] ^= 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (sys.Write(outfh, buf, 0, read) != read)
|
||||
{
|
||||
self.Error = Error.MSPACK_ERR_WRITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (read < 0)
|
||||
self.Error = Error.MSPACK_ERR_READ;
|
||||
}
|
||||
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_SZDD)
|
||||
{
|
||||
self.Error = LZSS.Decompress(sys, fh, outfh, KWAJ_INPUT_SIZE, LZSSMode.LZSS_MODE_EXPAND);
|
||||
}
|
||||
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_LZH)
|
||||
{
|
||||
LZHKWAJStream lzh = LZHInit(sys, fh, outfh);
|
||||
self.Error = (lzh != null) ? LZHDecompress(lzh) : Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_MSZIP)
|
||||
{
|
||||
MSZIPDStream zip = MSZIP.Init(sys, fh, outfh, KWAJ_INPUT_SIZE, false);
|
||||
self.Error = (zip != null) ? MSZIP.DecompressKWAJ(zip) : Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.Error = Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Close output file
|
||||
sys.Close(outfh);
|
||||
|
||||
return self.Error;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_DECOMPRESS
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks directly from input to output
|
||||
/// </summary>
|
||||
public static Error Decompress(Decompressor d, string input, string output)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
Header hdr;
|
||||
if ((hdr = Open(d, input)) == null)
|
||||
return self.Error;
|
||||
|
||||
Error error = Extract(d, hdr, output);
|
||||
Close(d, hdr);
|
||||
return self.Error = error;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_ERROR
|
||||
|
||||
/// <summary>
|
||||
/// Returns the last error that occurred
|
||||
/// </summary>
|
||||
public static Error LastError(Decompressor d)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
return (self != null) ? self.Error : Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LZH_INIT, LZH_DECOMPRESS, LZH_FREE
|
||||
|
||||
/* In the KWAJ LZH format, there is no special 'eof' marker, it just
|
||||
* ends. Depending on how many bits are left in the final byte when
|
||||
* the stream ends, that might be enough to start another literal or
|
||||
* match. The only easy way to detect that we've come to an end is to
|
||||
* guard all bit-reading. We allow fake bits to be read once we reach
|
||||
* the end of the stream, but we check if we then consumed any of
|
||||
* those fake bits, after doing the READ_BITS / READ_HUFFSYM. This
|
||||
* isn't how the default readbits.h read_input() works (it simply lets
|
||||
* 2 fake bytes in then stops), so we implement our own.
|
||||
*/
|
||||
|
||||
private static LZHKWAJStream LZHInit(SystemImpl sys, FileStream input, FileStream output)
|
||||
public static LZHKWAJStream Init(SystemImpl sys, FileStream input, FileStream output)
|
||||
{
|
||||
if (sys == null || input == null || output == null)
|
||||
return null;
|
||||
|
||||
return new LZHKWAJStream()
|
||||
{
|
||||
Sys = sys,
|
||||
Input = input,
|
||||
Output = output,
|
||||
System = sys,
|
||||
InputFileHandle = input,
|
||||
OutputFileHandle = output,
|
||||
};
|
||||
}
|
||||
|
||||
private static Error LZHDecompress(LZHKWAJStream lzh)
|
||||
public static Error Decompress(LZHKWAJStream lzh)
|
||||
{
|
||||
uint bit_buffer;
|
||||
int bits_left, i;
|
||||
@@ -464,7 +88,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -506,7 +130,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
lzh.BitsLeft = bits_left;
|
||||
}
|
||||
|
||||
err = LZHReadLens(lzh, types[0], KWAJ_MATCHLEN1_SYMS, lzh.MATCHLEN1_len);
|
||||
err = ReadLens(lzh, types[0], KWAJ_MATCHLEN1_SYMS, lzh.MATCHLEN1_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
@@ -532,7 +156,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
lzh.BitsLeft = bits_left;
|
||||
}
|
||||
|
||||
err = LZHReadLens(lzh, types[1], KWAJ_MATCHLEN2_SYMS, lzh.MATCHLEN2_len);
|
||||
err = ReadLens(lzh, types[1], KWAJ_MATCHLEN2_SYMS, lzh.MATCHLEN2_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
@@ -558,7 +182,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
lzh.BitsLeft = bits_left;
|
||||
}
|
||||
|
||||
err = LZHReadLens(lzh, types[2], KWAJ_LITLEN_SYMS, lzh.LITLEN_len);
|
||||
err = ReadLens(lzh, types[2], KWAJ_LITLEN_SYMS, lzh.LITLEN_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
@@ -584,7 +208,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
lzh.BitsLeft = bits_left;
|
||||
}
|
||||
|
||||
err = LZHReadLens(lzh, types[3], KWAJ_OFFSET_SYMS, lzh.OFFSET_len);
|
||||
err = ReadLens(lzh, types[3], KWAJ_OFFSET_SYMS, lzh.OFFSET_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
@@ -610,7 +234,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
lzh.BitsLeft = bits_left;
|
||||
}
|
||||
|
||||
err = LZHReadLens(lzh, types[4], KWAJ_LITERAL_SYMS, lzh.LITERAL_len);
|
||||
err = ReadLens(lzh, types[4], KWAJ_LITERAL_SYMS, lzh.LITERAL_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
@@ -642,7 +266,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -702,7 +326,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -766,7 +390,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -826,7 +450,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -864,7 +488,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
|
||||
//WRITE_BYTE
|
||||
{
|
||||
if (lzh.Sys.Write(lzh.Output, lzh.Window, pos, 1) != 1)
|
||||
if (lzh.System.Write(lzh.OutputFileHandle, lzh.Window, pos, 1) != 1)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
}
|
||||
|
||||
@@ -886,7 +510,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -948,7 +572,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -999,7 +623,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
|
||||
//WRITE_BYTE
|
||||
{
|
||||
if (lzh.Sys.Write(lzh.Output, lzh.Window, pos, 1) != 1)
|
||||
if (lzh.System.Write(lzh.OutputFileHandle, lzh.Window, pos, 1) != 1)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
}
|
||||
|
||||
@@ -1011,7 +635,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public static Error LZHReadLens(LZHKWAJStream lzh, uint type, uint numsyms, byte[] lens)
|
||||
private static Error ReadLens(LZHKWAJStream lzh, uint type, uint numsyms, byte[] lens)
|
||||
{
|
||||
uint bit_buffer;
|
||||
int bits_left;
|
||||
@@ -1052,7 +676,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1096,7 +720,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1143,7 +767,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1190,7 +814,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1239,7 +863,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1283,7 +907,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1326,7 +950,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1380,7 +1004,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((err = LZHReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
if ((err = ReadInput(lzh)) != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
i_ptr = lzh.InputPointer;
|
||||
@@ -1426,7 +1050,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public static Error LZHReadInput(LZHKWAJStream lzh)
|
||||
private static Error ReadInput(LZHKWAJStream lzh)
|
||||
{
|
||||
int read;
|
||||
if (lzh.InputEnd != 0)
|
||||
@@ -1437,7 +1061,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
}
|
||||
else
|
||||
{
|
||||
read = lzh.Sys.Read(lzh.Input, lzh.InputBuffer, 0, KWAJ_INPUT_SIZE);
|
||||
read = lzh.System.Read(lzh.InputFileHandle, lzh.InputBuffer, 0, KWAJ_INPUT_SIZE);
|
||||
if (read < 0)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
@@ -1454,7 +1078,5 @@ namespace LibMSPackSharp.KWAJ
|
||||
lzh.InputLength = read;
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -7,27 +7,27 @@
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using LibMSPackSharp.Compression;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public class LZHKWAJStream : CompressionStream
|
||||
{
|
||||
// Huffman code lengths
|
||||
|
||||
public byte[] MATCHLEN1_len { get; set; } = new byte[Implementation.KWAJ_MATCHLEN1_SYMS];
|
||||
public byte[] MATCHLEN2_len { get; set; } = new byte[Implementation.KWAJ_MATCHLEN2_SYMS];
|
||||
public byte[] LITLEN_len { get; set; } = new byte[Implementation.KWAJ_LITLEN_SYMS];
|
||||
public byte[] OFFSET_len { get; set; } = new byte[Implementation.KWAJ_OFFSET_SYMS];
|
||||
public byte[] LITERAL_len { get; set; } = new byte[Implementation.KWAJ_LITERAL_SYMS];
|
||||
public byte[] MATCHLEN1_len { get; set; } = new byte[KWAJ_MATCHLEN1_SYMS];
|
||||
public byte[] MATCHLEN2_len { get; set; } = new byte[KWAJ_MATCHLEN2_SYMS];
|
||||
public byte[] LITLEN_len { get; set; } = new byte[KWAJ_LITLEN_SYMS];
|
||||
public byte[] OFFSET_len { get; set; } = new byte[KWAJ_OFFSET_SYMS];
|
||||
public byte[] LITERAL_len { get; set; } = new byte[KWAJ_LITERAL_SYMS];
|
||||
|
||||
// Huffman decoding tables
|
||||
|
||||
public ushort[] MATCHLEN1_table { get; set; } = new ushort[Implementation.KWAJ_MATCHLEN1_TBLSIZE];
|
||||
public ushort[] MATCHLEN2_table { get; set; } = new ushort[Implementation.KWAJ_MATCHLEN2_TBLSIZE];
|
||||
public ushort[] LITLEN_table { get; set; } = new ushort[Implementation.KWAJ_LITLEN_TBLSIZE];
|
||||
public ushort[] OFFSET_table { get; set; } = new ushort[Implementation.KWAJ_OFFSET_TBLSIZE];
|
||||
public ushort[] LITERAL_table { get; set; } = new ushort[Implementation.KWAJ_LITERAL_TBLSIZE];
|
||||
public ushort[] MATCHLEN1_table { get; set; } = new ushort[KWAJ_MATCHLEN1_TBLSIZE];
|
||||
public ushort[] MATCHLEN2_table { get; set; } = new ushort[KWAJ_MATCHLEN2_TBLSIZE];
|
||||
public ushort[] LITLEN_table { get; set; } = new ushort[KWAJ_LITLEN_TBLSIZE];
|
||||
public ushort[] OFFSET_table { get; set; } = new ushort[KWAJ_OFFSET_TBLSIZE];
|
||||
public ushort[] LITERAL_table { get; set; } = new ushort[KWAJ_LITERAL_TBLSIZE];
|
||||
|
||||
// History window
|
||||
|
||||
374
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
374
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
@@ -191,8 +191,6 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
private static void ResetState(LZXDStream lzx)
|
||||
{
|
||||
int i;
|
||||
|
||||
lzx.R0 = 1;
|
||||
lzx.R1 = 1;
|
||||
lzx.R2 = 1;
|
||||
@@ -201,12 +199,12 @@ namespace LibMSPackSharp.Compression
|
||||
lzx.BlockType = LZXBlockType.LZX_BLOCKTYPE_INVALID0;
|
||||
|
||||
// Initialise tables to 0 (because deltas will be applied to them)
|
||||
for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
|
||||
for (int i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++)
|
||||
{
|
||||
lzx.MAINTREE_len[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
for (int i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
lzx.LENGTH_len[i] = 0;
|
||||
}
|
||||
@@ -307,9 +305,9 @@ namespace LibMSPackSharp.Compression
|
||||
Window = new byte[window_size],
|
||||
InputBuffer = new byte[input_buffer_size],
|
||||
|
||||
Sys = system,
|
||||
Input = input,
|
||||
Output = output,
|
||||
System = system,
|
||||
InputFileHandle = input,
|
||||
OutputFileHandle = output,
|
||||
Offset = 0,
|
||||
Length = output_length,
|
||||
|
||||
@@ -472,7 +470,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
try { lzx.Sys.Write(lzx.Output, lzx.e8_buf, lzx.OutputPointer, i); }
|
||||
try { lzx.System.Write(lzx.OutputFileHandle, lzx.e8_buf, lzx.OutputPointer, i); }
|
||||
catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
|
||||
|
||||
lzx.OutputPointer += i;
|
||||
@@ -512,7 +510,7 @@ namespace LibMSPackSharp.Compression
|
||||
Console.WriteLine($"{lzx.BlockRemaining} bytes remaining at reset interval");
|
||||
if (warned == 0)
|
||||
{
|
||||
lzx.Sys.Message(null, "WARNING; invalid reset interval detected during LZX decompression");
|
||||
lzx.System.Message(null, "WARNING; invalid reset interval detected during LZX decompression");
|
||||
warned++;
|
||||
}
|
||||
}
|
||||
@@ -577,182 +575,6 @@ namespace LibMSPackSharp.Compression
|
||||
}
|
||||
}
|
||||
|
||||
// Read header if necessary
|
||||
if (lzx.HeaderRead == 0)
|
||||
{
|
||||
// Read 1 bit. if bit=0, intel_filesize = 0.
|
||||
// if bit=1, read intel filesize (32 bits)
|
||||
j = 0;
|
||||
|
||||
//READ_BITS(i, 1)
|
||||
{
|
||||
//ENSURE_BITS(1)
|
||||
{
|
||||
while (bits_left < (1))
|
||||
{
|
||||
//READ_BYTES
|
||||
{
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b0 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b1 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//INJECT_BITS((b1 << 8) | b0, 16)
|
||||
{
|
||||
bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left);
|
||||
bits_left += (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (1))); //PEEK_BITS(1)
|
||||
|
||||
//REMOVE_BITS(1)
|
||||
{
|
||||
bit_buffer <<= (1);
|
||||
bits_left -= (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
//READ_BITS(i, 16)
|
||||
{
|
||||
//ENSURE_BITS(16)
|
||||
{
|
||||
while (bits_left < (16))
|
||||
{
|
||||
//READ_BYTES
|
||||
{
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b0 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b1 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//INJECT_BITS((b1 << 8) | b0, 16)
|
||||
{
|
||||
bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left);
|
||||
bits_left += (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16)
|
||||
|
||||
//REMOVE_BITS(16)
|
||||
{
|
||||
bit_buffer <<= (16);
|
||||
bits_left -= (16);
|
||||
}
|
||||
}
|
||||
|
||||
//READ_BITS(j, 16)
|
||||
{
|
||||
//ENSURE_BITS(16)
|
||||
{
|
||||
while (bits_left < (16))
|
||||
{
|
||||
//READ_BYTES
|
||||
{
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b0 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b1 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//INJECT_BITS((b1 << 8) | b0, 16)
|
||||
{
|
||||
bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left);
|
||||
bits_left += (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(j) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16)
|
||||
|
||||
//REMOVE_BITS(16)
|
||||
{
|
||||
bit_buffer <<= (16);
|
||||
bits_left -= (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lzx.IntelFileSize = (i << 16) | j;
|
||||
lzx.HeaderRead = 1;
|
||||
}
|
||||
|
||||
// Calculate size of frame: all frames are 32k except the final frame
|
||||
// which is 32kb or less. this can only be calculated when lzx.Length
|
||||
// has been filled in.
|
||||
@@ -789,7 +611,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
//READ_BITS(lzx.BlockType, 3)
|
||||
{
|
||||
//ENSURE_BITS(3)
|
||||
//ENSURE_BITS(3) // THIS IS NOT 3 BECAUSE OF OTHER CODE I FOUND
|
||||
{
|
||||
while (bits_left < (3))
|
||||
{
|
||||
@@ -841,6 +663,182 @@ namespace LibMSPackSharp.Compression
|
||||
}
|
||||
}
|
||||
|
||||
// Read header if necessary
|
||||
if (lzx.HeaderRead == 0)
|
||||
{
|
||||
// Read 1 bit. if bit=0, intel_filesize = 0.
|
||||
// if bit=1, read intel filesize (32 bits)
|
||||
j = 0;
|
||||
|
||||
//READ_BITS(i, 1)
|
||||
{
|
||||
//ENSURE_BITS(1)
|
||||
{
|
||||
while (bits_left < (1))
|
||||
{
|
||||
//READ_BYTES
|
||||
{
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b0 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b1 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//INJECT_BITS((b1 << 8) | b0, 16)
|
||||
{
|
||||
bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left);
|
||||
bits_left += (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (1))); //PEEK_BITS(1)
|
||||
|
||||
//REMOVE_BITS(1)
|
||||
{
|
||||
bit_buffer <<= (1);
|
||||
bits_left -= (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
//READ_BITS(i, 16)
|
||||
{
|
||||
//ENSURE_BITS(16)
|
||||
{
|
||||
while (bits_left < (16))
|
||||
{
|
||||
//READ_BYTES
|
||||
{
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b0 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b1 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//INJECT_BITS((b1 << 8) | b0, 16)
|
||||
{
|
||||
bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left);
|
||||
bits_left += (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(i) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16)
|
||||
|
||||
//REMOVE_BITS(16)
|
||||
{
|
||||
bit_buffer <<= (16);
|
||||
bits_left -= (16);
|
||||
}
|
||||
}
|
||||
|
||||
//READ_BITS(j, 16)
|
||||
{
|
||||
//ENSURE_BITS(16)
|
||||
{
|
||||
while (bits_left < (16))
|
||||
{
|
||||
//READ_BYTES
|
||||
{
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b0 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//READ_IF_NEEDED
|
||||
{
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (lzx.ReadInput() != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
i_ptr = lzx.InputPointer;
|
||||
i_end = lzx.InputLength;
|
||||
}
|
||||
}
|
||||
|
||||
byte b1 = lzx.InputBuffer[i_ptr++];
|
||||
|
||||
//INJECT_BITS((b1 << 8) | b0, 16)
|
||||
{
|
||||
bit_buffer |= (uint)((b1 << 8) | b0) << (CompressionStream.BITBUF_WIDTH - (16) - bits_left);
|
||||
bits_left += (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(j) = (int)(bit_buffer >> (CompressionStream.BITBUF_WIDTH - (16))); //PEEK_BITS(16)
|
||||
|
||||
//REMOVE_BITS(16)
|
||||
{
|
||||
bit_buffer <<= (16);
|
||||
bits_left -= (16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lzx.IntelFileSize = (i << 16) | j;
|
||||
lzx.HeaderRead = 1;
|
||||
}
|
||||
|
||||
//READ_BITS(i, 16)
|
||||
{
|
||||
//ENSURE_BITS(16)
|
||||
@@ -2415,7 +2413,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Write a frame
|
||||
i = (int)((out_bytes < frame_size) ? out_bytes : frame_size);
|
||||
try { lzx.Output.Write(lzx.e8_buf, lzx.OutputPointer, i); }
|
||||
try { lzx.System.Write(lzx.OutputFileHandle, lzx.e8_buf, lzx.OutputPointer, i); }
|
||||
catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
|
||||
}
|
||||
else
|
||||
@@ -2425,7 +2423,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Write a frame
|
||||
i = (int)((out_bytes < frame_size) ? out_bytes : frame_size);
|
||||
try { lzx.Output.Write(lzx.Window, lzx.OutputPointer, i); }
|
||||
try { lzx.System.Write(lzx.OutputFileHandle, lzx.Window, lzx.OutputPointer, i); }
|
||||
catch { return lzx.Error = Error.MSPACK_ERR_WRITE; }
|
||||
}
|
||||
|
||||
|
||||
@@ -112,9 +112,9 @@ namespace LibMSPackSharp.Compression
|
||||
InputBuffer = new byte[input_buffer_size],
|
||||
|
||||
// Initialise decompression state
|
||||
Sys = system,
|
||||
Input = input,
|
||||
Output = output,
|
||||
System = system,
|
||||
InputFileHandle = input,
|
||||
OutputFileHandle = output,
|
||||
InputBufferSize = (uint)input_buffer_size,
|
||||
InputEnd = 0,
|
||||
Error = Error.MSPACK_ERR_OK,
|
||||
@@ -176,7 +176,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
if (zip.Sys.Write(zip.Output, zip.Window, zip.OutputPointer, i) != i)
|
||||
if (zip.System.Write(zip.OutputFileHandle, zip.Window, zip.OutputPointer, i) != i)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
zip.OutputPointer += i;
|
||||
@@ -279,7 +279,7 @@ namespace LibMSPackSharp.Compression
|
||||
if (zip.BytesOutput == 0 && zip.WindowPosition > 0)
|
||||
zip.FlushWindow(zip, zip.WindowPosition);
|
||||
|
||||
zip.Sys.Message(null, $"MSZIP error, {MSZIP_FRAME_SIZE - zip.BytesOutput} bytes of data lost.");
|
||||
zip.System.Message(null, $"MSZIP error, {MSZIP_FRAME_SIZE - zip.BytesOutput} bytes of data lost.");
|
||||
for (i = zip.BytesOutput; i < MSZIP_FRAME_SIZE; i++)
|
||||
{
|
||||
zip.Window[i] = 0x00;
|
||||
@@ -298,7 +298,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Write a frame
|
||||
i = (out_bytes < zip.BytesOutput) ? (int)out_bytes : zip.BytesOutput;
|
||||
if (zip.Sys.Write(zip.Output, zip.Window, zip.OutputPointer, i) != i)
|
||||
if (zip.System.Write(zip.OutputFileHandle, zip.Window, zip.OutputPointer, i) != i)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
// mspack errors (i.e. read errors) are fatal and can't be recovered
|
||||
@@ -536,7 +536,7 @@ namespace LibMSPackSharp.Compression
|
||||
}
|
||||
|
||||
// Write inflated block
|
||||
try { zip.Sys.Write(zip.Output, zip.Window, 0, zip.BytesOutput); }
|
||||
try { zip.System.Write(zip.OutputFileHandle, zip.Window, 0, zip.BytesOutput); }
|
||||
catch { return zip.Error = Error.MSPACK_ERR_WRITE; }
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace LibMSPackSharp.Compression
|
||||
{
|
||||
return new NoneState()
|
||||
{
|
||||
Sys = sys,
|
||||
Input = input,
|
||||
Output = output,
|
||||
System = sys,
|
||||
InputFileHandle = input,
|
||||
OutputFileHandle = output,
|
||||
Buffer = new byte[bufsize],
|
||||
BufferSize = bufsize,
|
||||
};
|
||||
@@ -36,10 +36,10 @@ namespace LibMSPackSharp.Compression
|
||||
{
|
||||
run = (bytes > state.BufferSize) ? state.BufferSize : (int)bytes;
|
||||
|
||||
if (state.Sys.Read(state.Input, state.Buffer, 0, run) != run)
|
||||
if (state.System.Read(state.InputFileHandle, state.Buffer, 0, run) != run)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (state.Sys.Write(state.Output, state.Buffer, 0, run) != run)
|
||||
if (state.System.Write(state.OutputFileHandle, state.Buffer, 0, run) != run)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
|
||||
bytes -= run;
|
||||
|
||||
@@ -7,21 +7,13 @@
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
/// <summary>
|
||||
/// The "not compressed" method decompressor
|
||||
/// </summary>
|
||||
public class NoneState
|
||||
public class NoneState : BaseDecompressState
|
||||
{
|
||||
public SystemImpl Sys { get; set; }
|
||||
|
||||
public FileStream Input { get; set; }
|
||||
|
||||
public FileStream Output { get; set; }
|
||||
|
||||
public byte[] Buffer { get; set; }
|
||||
|
||||
public int BufferSize { get; set; }
|
||||
|
||||
@@ -116,9 +116,9 @@ namespace LibMSPackSharp.Compression
|
||||
InputBuffer = new byte[input_buffer_size],
|
||||
|
||||
// Initialise decompression state
|
||||
Sys = system,
|
||||
Input = input,
|
||||
Output = output,
|
||||
System = system,
|
||||
InputFileHandle = input,
|
||||
OutputFileHandle = output,
|
||||
InputBufferSize = (uint)input_buffer_size,
|
||||
WindowSize = window_size,
|
||||
WindowPosition = 0,
|
||||
@@ -203,7 +203,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
if (qtm.Sys.Write(qtm.Output, qtm.Window, qtm.OutputPointer, i) != i)
|
||||
if (qtm.System.Write(qtm.OutputFileHandle, qtm.Window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
qtm.OutputPointer += i;
|
||||
@@ -1223,7 +1223,7 @@ namespace LibMSPackSharp.Compression
|
||||
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
if (qtm.Sys.Write(qtm.Output, window, qtm.OutputPointer, i) != i)
|
||||
if (qtm.System.Write(qtm.OutputFileHandle, window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
out_bytes -= i;
|
||||
@@ -1388,7 +1388,7 @@ namespace LibMSPackSharp.Compression
|
||||
if (i >= out_bytes)
|
||||
break;
|
||||
|
||||
if (qtm.Sys.Write(qtm.Output, window, qtm.OutputPointer, i) != i)
|
||||
if (qtm.System.Write(qtm.OutputFileHandle, window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
out_bytes -= i;
|
||||
@@ -1403,7 +1403,7 @@ namespace LibMSPackSharp.Compression
|
||||
{
|
||||
i = (int)out_bytes;
|
||||
|
||||
if (qtm.Sys.Write(qtm.Output, window, qtm.OutputPointer, i) != i)
|
||||
if (qtm.System.Write(qtm.OutputFileHandle, window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
qtm.OutputPointer += i;
|
||||
|
||||
196
BurnOutSharp/External/libmspack/Constants.cs
vendored
Normal file
196
BurnOutSharp/External/libmspack/Constants.cs
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
internal class Constants
|
||||
{
|
||||
#region CAB
|
||||
|
||||
// CAB data blocks are <= 32768 bytes in uncompressed form.Uncompressed
|
||||
// blocks have zero growth. MSZIP guarantees that it won't grow above
|
||||
// uncompressed size by more than 12 bytes.LZX guarantees it won't grow
|
||||
// more than 6144 bytes.Quantum has no documentation, but the largest
|
||||
// block seen in the wild is 337 bytes above uncompressed size.
|
||||
|
||||
public const int CAB_BLOCKMAX = 32768;
|
||||
public const int CAB_INPUTMAX = CAB_BLOCKMAX + 6144;
|
||||
|
||||
// input buffer needs to be CAB_INPUTMAX + 1 byte to allow for max-sized block
|
||||
// plus 1 trailer byte added by cabd_sys_read_block() for Quantum alignment.
|
||||
//
|
||||
// When MSCABD_PARAM_SALVAGE is set, block size is not checked so can be
|
||||
// up to 65535 bytes, so max input buffer size needed is 65535 + 1
|
||||
|
||||
public const int CAB_INPUTMAX_SALVAGE = 65535;
|
||||
public const int CAB_INPUTBUF = CAB_INPUTMAX_SALVAGE + 1;
|
||||
|
||||
// There are no more than 65535 data blocks per folder, so a folder cannot
|
||||
// be more than 32768*65535 bytes in length.As files cannot span more than
|
||||
// one folder, this is also their max offset, length and offset+length limit.
|
||||
|
||||
public const int CAB_FOLDERMAX = 65535;
|
||||
public const int CAB_LENGTHMAX = CAB_BLOCKMAX * CAB_FOLDERMAX;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CHM
|
||||
|
||||
// _PMGHeader
|
||||
public const int pmgl_Signature = 0x0000;
|
||||
public const int pmgl_QuickRefSize = 0x0004;
|
||||
public const int pmgl_PMGIEntries = 0x0008; // Unknown1 in PMGL
|
||||
public const int pmgl_PrevChunk = 0x000C; // Not in PMGI
|
||||
public const int pmgl_NextChunk = 0x0010; // Not in PMGI
|
||||
public const int pmgl_PMGLEntries = 0x0014; // Not in PMGI
|
||||
public const int pmgl_headerSIZEOF = 0x0014;
|
||||
public const int pmgi_headerSIZEOF = 0x000C;
|
||||
|
||||
// _LZXControlData
|
||||
public const int lzxcd_Length = 0x0000;
|
||||
public const int lzxcd_Signature = 0x0004;
|
||||
public const int lzxcd_Version = 0x0008;
|
||||
public const int lzxcd_ResetInterval = 0x000C;
|
||||
public const int lzxcd_WindowSize = 0x0010;
|
||||
public const int lzxcd_CacheSize = 0x0014;
|
||||
public const int lzxcd_Unknown1 = 0x0018;
|
||||
public const int lzxcd_SIZEOF = 0x001C;
|
||||
|
||||
// _LZXResetTable
|
||||
public const int lzxrt_Unknown1 = 0x0000;
|
||||
public const int lzxrt_NumEntries = 0x0004;
|
||||
public const int lzxrt_EntrySize = 0x0008;
|
||||
public const int lzxrt_TableOffset = 0x000C;
|
||||
public const int lzxrt_UncompLen = 0x0010;
|
||||
public const int lzxrt_CompLen = 0x0018;
|
||||
public const int lzxrt_FrameLen = 0x0020;
|
||||
public const int lzxrt_Entries = 0x0028;
|
||||
public const int lzxrt_headerSIZEOF = 0x0028;
|
||||
|
||||
// Filenames of the system files used for decompression.
|
||||
// - Content and ControlData are essential.
|
||||
// - ResetTable is preferred, but SpanInfo can be used if not available
|
||||
public const string ContentName = "::DataSpace/Storage/MSCompressed/Content";
|
||||
public const string ControlName = "::DataSpace/Storage/MSCompressed/ControlData";
|
||||
public const string SpanInfoName = "::DataSpace/Storage/MSCompressed/SpanInfo";
|
||||
public const string ResetTableName = "::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable";
|
||||
|
||||
#endregion
|
||||
|
||||
#region HLP
|
||||
|
||||
// None currently
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJ
|
||||
|
||||
public const byte kwajh_Signature1 = 0x00;
|
||||
public const byte kwajh_Signature2 = 0x04;
|
||||
public const byte kwajh_CompMethod = 0x08;
|
||||
public const byte kwajh_DataOffset = 0x0a;
|
||||
public const byte kwajh_Flags = 0x0c;
|
||||
public const byte kwajh_SIZEOF = 0x0e;
|
||||
|
||||
// Input buffer size during decompression - not worth parameterising IMHO
|
||||
public const int KWAJ_INPUT_SIZE = (2048);
|
||||
|
||||
// Huffman codes that are 9 bits or less are decoded immediately
|
||||
public const int KWAJ_TABLEBITS = (9);
|
||||
|
||||
// Number of codes in each huffman table
|
||||
|
||||
public const int KWAJ_MATCHLEN1_SYMS = (16);
|
||||
public const int KWAJ_MATCHLEN2_SYMS = (16);
|
||||
public const int KWAJ_LITLEN_SYMS = (32);
|
||||
public const int KWAJ_OFFSET_SYMS = (64);
|
||||
public const int KWAJ_LITERAL_SYMS = (256);
|
||||
|
||||
// Define decoding table sizes
|
||||
|
||||
public const int KWAJ_TABLESIZE = (1 << KWAJ_TABLEBITS);
|
||||
|
||||
//public const int KWAJ_MATCHLEN1_TBLSIZE = (KWAJ_MATCHLEN1_SYMS * 4);
|
||||
public const int KWAJ_MATCHLEN1_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_MATCHLEN1_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_MATCHLEN2_TBLSIZE = (KWAJ_MATCHLEN2_SYMS * 4);
|
||||
public const int KWAJ_MATCHLEN2_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_MATCHLEN2_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_LITLEN_TBLSIZE = (KWAJ_LITLEN_SYMS * 4);
|
||||
public const int KWAJ_LITLEN_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_LITLEN_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_OFFSET_TBLSIZE = (KWAJ_OFFSET_SYMS * 4);
|
||||
public const int KWAJ_OFFSET_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_OFFSET_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_LITERAL_TBLSIZE = (KWAJ_LITERAL_SYMS * 4);
|
||||
public const int KWAJ_LITERAL_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_LITERAL_SYMS * 2));
|
||||
|
||||
#endregion
|
||||
|
||||
#region LIT
|
||||
|
||||
// None currently
|
||||
|
||||
#endregion
|
||||
|
||||
#region OAB
|
||||
|
||||
// _Header
|
||||
public const int oabhead_VersionHi = 0x0000;
|
||||
public const int oabhead_VersionLo = 0x0004;
|
||||
public const int oabhead_BlockMax = 0x0008;
|
||||
public const int oabhead_TargetSize = 0x000c;
|
||||
public const int oabhead_SIZEOF = 0x0010;
|
||||
|
||||
// _Block
|
||||
public const int oabblk_Flags = 0x0000;
|
||||
public const int oabblk_CompSize = 0x0004;
|
||||
public const int oabblk_UncompSize = 0x0008;
|
||||
public const int oabblk_CRC = 0x000c;
|
||||
public const int oabblk_SIZEOF = 0x0010;
|
||||
|
||||
// _PatchHeader
|
||||
public const int patchhead_VersionHi = 0x0000;
|
||||
public const int patchhead_VersionLo = 0x0004;
|
||||
public const int patchhead_BlockMax = 0x0008;
|
||||
public const int patchhead_SourceSize = 0x000c;
|
||||
public const int patchhead_TargetSize = 0x0010;
|
||||
public const int patchhead_SourceCRC = 0x0014;
|
||||
public const int patchhead_TargetCRC = 0x0018;
|
||||
public const int patchhead_SIZEOF = 0x001c;
|
||||
|
||||
// _PatchBlock
|
||||
public const int patchblk_PatchSize = 0x0000;
|
||||
public const int patchblk_TargetSize = 0x0004;
|
||||
public const int patchblk_SourceSize = 0x0008;
|
||||
public const int patchblk_CRC = 0x000c;
|
||||
public const int patchblk_SIZEOF = 0x0010;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDD
|
||||
|
||||
/// <summary>
|
||||
/// Input buffer size during decompression - not worth parameterising IMHO
|
||||
/// </summary>
|
||||
public const int SZDD_INPUT_SIZE = 2048;
|
||||
|
||||
public static readonly byte[] expandSignature = new byte[8]
|
||||
{
|
||||
0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33
|
||||
};
|
||||
|
||||
public static readonly byte[] qbasicSignature = new byte[8]
|
||||
{
|
||||
0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1
|
||||
};
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
{
|
||||
// TODO
|
||||
public class Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public int Dummy { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
{
|
||||
public class CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
{
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
{
|
||||
public class DecompressorImpl : Decompressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,19 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// <see cref="Library.DestroyKWAJCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
/// <remarks>
|
||||
/// !!! MATCH THIS TO NUM OF PARAMS IN MSPACK.H !!!
|
||||
/// </remarks>
|
||||
public int[] Param { get; set; } = new int[2];
|
||||
|
||||
public Error Error { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Reads an input file and creates a compressed output file in the
|
||||
/// KWAJ compressed file format.The KWAJ compression format is quick
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2010 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
public class CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
// TODO
|
||||
|
||||
/// <remarks>
|
||||
/// !!! MATCH THIS TO NUM OF PARAMS IN MSPACK.H !!!
|
||||
/// </remarks>
|
||||
public int[] Param { get; set; } = new int[2];
|
||||
|
||||
public Error Error { get; set; }
|
||||
}
|
||||
}
|
||||
301
BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs
vendored
301
BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs
vendored
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using LibMSPackSharp.Compression;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
@@ -25,8 +29,10 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateKWAJDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyKWAJDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
#region Public Functionality
|
||||
|
||||
/// <summary>
|
||||
/// Opens a KWAJ file and reads the header.
|
||||
///
|
||||
@@ -39,17 +45,37 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// The filename pointer should be considered "in use" until close() is
|
||||
/// called on the KWAJ file.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mskwaj_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="filename">
|
||||
/// the filename of the KWAJ compressed file. This is
|
||||
/// passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>a pointer to a mskwajd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Close"/>
|
||||
public Func<Decompressor, string, Header> Open;
|
||||
/// <returns>A pointer to a mskwajd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Close(Header)"/>
|
||||
public Header Open(string filename)
|
||||
{
|
||||
FileStream fh = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
Header hdr = new Header();
|
||||
if (fh != null && hdr != null)
|
||||
{
|
||||
hdr.FileHandle = fh;
|
||||
Error = ReadHeaders(fh, hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fh == null)
|
||||
Error = Error.MSPACK_ERR_OPEN;
|
||||
if (hdr == null)
|
||||
Error = Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(fh);
|
||||
hdr = null;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened KWAJ file.
|
||||
@@ -58,13 +84,18 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// with it. The KWAJ header pointer is now invalid and cannot be
|
||||
/// used again.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mskwaj_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="kwaj">the KWAJ file to close</param>
|
||||
/// <see cref="Open"/>
|
||||
public Action<Decompressor, Header> Close;
|
||||
/// <param name="hdr">The KWAJ file to close</param>
|
||||
/// <see cref="Open(string)"/>
|
||||
public void Close(Header hdr)
|
||||
{
|
||||
if (System == null || hdr == null)
|
||||
return;
|
||||
|
||||
// Close the file handle associated
|
||||
System.Close(hdr.FileHandle);
|
||||
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the compressed data from a KWAJ file.
|
||||
@@ -72,17 +103,81 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// This decompresses the compressed KWAJ data stream and writes it to
|
||||
/// an output file.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mskwaj_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="kwaj">the KWAJ file to extract data from</param>
|
||||
/// <param name="hdr">The KWAJ file to extract data from</param>
|
||||
/// <param name="filename">
|
||||
/// the filename to write the decompressed data to. This
|
||||
/// is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, Header, string, Error> Extract;
|
||||
public Error Extract(Header hdr, string filename)
|
||||
{
|
||||
FileStream fh = hdr?.FileHandle;
|
||||
if (fh == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
// Seek to the compressed data
|
||||
if (System.Seek(fh, hdr.DataOffset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return Error = Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Open file for output
|
||||
FileStream outfh;
|
||||
if ((outfh = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
|
||||
return Error = Error.MSPACK_ERR_OPEN;
|
||||
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
|
||||
// Decompress based on format
|
||||
if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_NONE ||
|
||||
hdr.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
|
||||
{
|
||||
// NONE is a straight copy. XOR is a copy xored with 0xFF
|
||||
byte[] buf = new byte[KWAJ_INPUT_SIZE];
|
||||
|
||||
int read, i;
|
||||
while ((read = System.Read(fh, buf, 0, KWAJ_INPUT_SIZE)) > 0)
|
||||
{
|
||||
if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
|
||||
{
|
||||
for (i = 0; i < read; i++)
|
||||
{
|
||||
buf[i] ^= 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (System.Write(outfh, buf, 0, read) != read)
|
||||
{
|
||||
Error = Error.MSPACK_ERR_WRITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (read < 0)
|
||||
Error = Error.MSPACK_ERR_READ;
|
||||
}
|
||||
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_SZDD)
|
||||
{
|
||||
Error = LZSS.Decompress(System, fh, outfh, KWAJ_INPUT_SIZE, LZSSMode.LZSS_MODE_EXPAND);
|
||||
}
|
||||
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_LZH)
|
||||
{
|
||||
LZHKWAJStream lzh = LZHKWAJ.Init(System, fh, outfh);
|
||||
Error = (lzh != null) ? LZHKWAJ.Decompress(lzh) : Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_MSZIP)
|
||||
{
|
||||
MSZIPDStream zip = MSZIP.Init(System, fh, outfh, KWAJ_INPUT_SIZE, false);
|
||||
Error = (zip != null) ? MSZIP.DecompressKWAJ(zip) : Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
Error = Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Close output file
|
||||
System.Close(outfh);
|
||||
|
||||
return Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an KWAJ file to an output file in one step.
|
||||
@@ -106,21 +201,159 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, string, string, Error> Decompress;
|
||||
public Error Decompress(string input, string output)
|
||||
{
|
||||
Header hdr = Open(input) as Header;
|
||||
if (hdr == null)
|
||||
return Error;
|
||||
|
||||
Error error = Extract(hdr, output);
|
||||
Close(hdr);
|
||||
return Error = error;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
///
|
||||
/// This is useful for open() which does not return an
|
||||
/// error code directly.
|
||||
/// Reads the headers of a KWAJ format file
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mskwaj_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Search"/>
|
||||
public Func<Decompressor, Error> LastError;
|
||||
private Error ReadHeaders(FileStream fh, Header hdr)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Read in the header
|
||||
byte[] buf = new byte[16];
|
||||
if (System.Read(fh, buf, 0, kwajh_SIZEOF) != kwajh_SIZEOF)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
// Check for "KWAJ" signature
|
||||
if ((BitConverter.ToUInt32(buf, kwajh_Signature1) != 0x4A41574B) ||
|
||||
(BitConverter.ToUInt32(buf, kwajh_Signature2) != 0xD127F088))
|
||||
{
|
||||
return Error.MSPACK_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
// Basic header fields
|
||||
hdr.CompressionType = (CompressionType)BitConverter.ToUInt16(buf, kwajh_CompMethod);
|
||||
hdr.DataOffset = BitConverter.ToUInt16(buf, kwajh_DataOffset);
|
||||
hdr.Headers = (OptionalHeaderFlag)BitConverter.ToUInt16(buf, kwajh_Flags);
|
||||
hdr.Length = 0;
|
||||
hdr.Filename = null;
|
||||
hdr.Extra = null;
|
||||
hdr.ExtraLength = 0;
|
||||
|
||||
// Optional headers
|
||||
|
||||
// 4 bytes: length of unpacked file
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASLENGTH))
|
||||
{
|
||||
if (System.Read(fh, buf, 0, 4) != 4)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
hdr.Length = BitConverter.ToUInt32(buf, 0);
|
||||
}
|
||||
|
||||
// 2 bytes: unknown purpose
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN1))
|
||||
{
|
||||
if (System.Read(fh, buf, 0, 2) != 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
// 2 bytes: length of section, then [length] bytes: unknown purpose
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN2))
|
||||
{
|
||||
if (System.Read(fh, buf, 0, 2) != 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
i = BitConverter.ToUInt16(buf, 0);
|
||||
if (System.Seek(fh, i, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
// Filename and extension
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME) || hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
|
||||
{
|
||||
int len;
|
||||
|
||||
// Allocate memory for maximum length filename
|
||||
char[] fn = new char[13];
|
||||
int fnPtr = 0;
|
||||
|
||||
// Copy filename if present
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME))
|
||||
{
|
||||
// Read and copy up to 9 bytes of a null terminated string
|
||||
if ((len = System.Read(fh, buf, 0, 9)) < 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((fn[fnPtr++] = (char)buf[i]) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
// If string was 9 bytes with no null terminator, reject it
|
||||
if (i == 9 && buf[8] != '\0')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
// Seek to byte after string ended in file
|
||||
if (System.Seek(fh, i + 1 - len, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
fnPtr--; // Remove the null terminator
|
||||
}
|
||||
|
||||
// Copy extension if present
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
|
||||
{
|
||||
fn[fnPtr++] = '.';
|
||||
|
||||
// Read and copy up to 4 bytes of a null terminated string
|
||||
if ((len = System.Read(fh, buf, 0, 4)) < 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((fn[fnPtr++] = (char)buf[i]) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
// If string was 4 bytes with no null terminator, reject it
|
||||
if (i == 4 && buf[3] != '\0')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
// Seek to byte after string ended in file
|
||||
if (System.Seek(fh, i + 1 - len, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
fnPtr--; // Remove the null terminator
|
||||
}
|
||||
|
||||
fn[fnPtr] = '\0';
|
||||
}
|
||||
|
||||
// 2 bytes: extra text length then [length] bytes of extra text data
|
||||
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASEXTRATEXT))
|
||||
{
|
||||
if (System.Read(fh, buf, 0, 2) != 2)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
i = BitConverter.ToUInt16(buf, 0);
|
||||
byte[] extra = new byte[i + 1];
|
||||
if (System.Read(fh, extra, 0, i) != i)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
extra[i] = 0x00;
|
||||
hdr.Extra = Encoding.ASCII.GetString(extra, 0, extra.Length);
|
||||
hdr.ExtraLength = (ushort)i;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2010 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
public class DecompressorImpl : Decompressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
/// <summary>
|
||||
@@ -21,7 +23,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class Header
|
||||
public class Header : BaseHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// The compression type
|
||||
@@ -58,5 +60,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
/// Length of extra uncompressed data in the header
|
||||
/// </summary>
|
||||
public ushort ExtraLength { get; set; }
|
||||
|
||||
public FileStream FileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2010 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
public class HeaderImpl : Header
|
||||
{
|
||||
public FileStream FileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,6 @@ namespace LibMSPackSharp.LIT
|
||||
// TODO
|
||||
public class Compressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
public SystemImpl System { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.LIT
|
||||
{
|
||||
public class CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
namespace LibMSPackSharp.LIT
|
||||
{
|
||||
// TODO
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.LIT
|
||||
{
|
||||
public class DecompressorImpl : Decompressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.LIT
|
||||
{
|
||||
public class Implementation
|
||||
{
|
||||
}
|
||||
}
|
||||
19
BurnOutSharp/External/libmspack/Library.cs
vendored
19
BurnOutSharp/External/libmspack/Library.cs
vendored
@@ -374,13 +374,8 @@ namespace LibMSPackSharp
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new SZDD.DecompressorImpl()
|
||||
return new SZDD.Decompressor()
|
||||
{
|
||||
Open = SZDD.Implementation.Open,
|
||||
Close = SZDD.Implementation.Close,
|
||||
Extract = SZDD.Implementation.Extract,
|
||||
Decompress = SZDD.Implementation.Decompress,
|
||||
LastError = SZDD.Implementation.LastError,
|
||||
System = sys,
|
||||
Error = Error.MSPACK_ERR_OK,
|
||||
};
|
||||
@@ -428,13 +423,8 @@ namespace LibMSPackSharp
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new KWAJ.DecompressorImpl()
|
||||
return new KWAJ.Decompressor()
|
||||
{
|
||||
Open = KWAJ.Implementation.Open,
|
||||
Close = KWAJ.Implementation.Close,
|
||||
Extract = KWAJ.Implementation.Extract,
|
||||
Decompress = KWAJ.Implementation.Decompress,
|
||||
LastError = KWAJ.Implementation.LastError,
|
||||
System = sys,
|
||||
Error = Error.MSPACK_ERR_OK,
|
||||
};
|
||||
@@ -482,11 +472,8 @@ namespace LibMSPackSharp
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new OAB.DecompressorImpl()
|
||||
return new OAB.Decompressor()
|
||||
{
|
||||
Decompress = OAB.Implementation.Decompress,
|
||||
DecompressIncremental = OAB.Implementation.DecompressIncremental,
|
||||
SetParam = OAB.Implementation.Param,
|
||||
System = sys,
|
||||
BufferSize = 4096,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,12 @@ namespace LibMSPackSharp.OAB
|
||||
/// <see cref="Library.DestroyOABCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Compress a full OAB file.
|
||||
///
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* © 2013 Intel Corporation
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
public class CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
}
|
||||
}
|
||||
445
BurnOutSharp/External/libmspack/OAB/Decompressor.cs
vendored
445
BurnOutSharp/External/libmspack/OAB/Decompressor.cs
vendored
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using LibMSPackSharp.Compression;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
@@ -25,8 +28,10 @@ namespace LibMSPackSharp.OAB
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateOABDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyOABDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
#region Public Functionality
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses a full Offline Address Book file.
|
||||
///
|
||||
@@ -34,20 +39,170 @@ namespace LibMSPackSharp.OAB
|
||||
/// it will be read and the decompressed contents will be written to
|
||||
/// the output file.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msoab_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// the filename of the input file. This is passed
|
||||
/// The filename of the input file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// the filename of the output file. This is passed
|
||||
/// The filename of the output file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, string, string, Error> Decompress;
|
||||
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Error Decompress(string input, string output)
|
||||
{
|
||||
byte[] hdrbuf = new byte[oabhead_SIZEOF];
|
||||
LZXDStream lzx = null;
|
||||
Error ret = Error.MSPACK_ERR_OK;
|
||||
|
||||
FileStream infh = System.Open(input, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (System.Read(infh, hdrbuf, 0, oabhead_SIZEOF) != oabhead_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (BitConverter.ToUInt32(hdrbuf, oabhead_VersionHi) != 3 ||
|
||||
BitConverter.ToUInt32(hdrbuf, oabhead_VersionLo) != 1)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_SIGNATURE;
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint block_max = BitConverter.ToUInt32(hdrbuf, oabhead_BlockMax);
|
||||
uint target_size = BitConverter.ToUInt32(hdrbuf, oabhead_TargetSize);
|
||||
|
||||
FileStream outfh = System.Open(output, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte[] buf = new byte[BufferSize];
|
||||
|
||||
SystemImpl oabd_sys = System;
|
||||
oabd_sys.Read = SysRead;
|
||||
oabd_sys.Write = SysWrite;
|
||||
|
||||
InternalFile in_ofh = new InternalFile();
|
||||
in_ofh.OrigSys = System;
|
||||
in_ofh.OrigFile = infh;
|
||||
|
||||
InternalFile out_ofh = new InternalFile();
|
||||
out_ofh.OrigSys = System;
|
||||
out_ofh.OrigFile = outfh;
|
||||
|
||||
while (target_size != 0)
|
||||
{
|
||||
if (System.Read(infh, buf, 0, oabblk_SIZEOF) != oabblk_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint blk_flags = BitConverter.ToUInt32(buf, oabblk_Flags);
|
||||
uint blk_csize = BitConverter.ToUInt32(buf, oabblk_CompSize);
|
||||
uint blk_dsize = BitConverter.ToUInt32(buf, oabblk_UncompSize);
|
||||
uint blk_crc = BitConverter.ToUInt32(buf, oabblk_CRC);
|
||||
|
||||
if (blk_dsize > block_max || blk_dsize > target_size || blk_flags > 1)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (blk_flags == 0)
|
||||
{
|
||||
// Uncompressed block
|
||||
if (blk_dsize != blk_csize)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = CopyFileHandle(infh, outfh, (int)blk_dsize, buf, BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// LZX compressed block
|
||||
int window_bits = 17;
|
||||
|
||||
while (window_bits < 25 && (1U << window_bits) < blk_dsize)
|
||||
{
|
||||
window_bits++;
|
||||
}
|
||||
|
||||
in_ofh.Available = (int)blk_csize;
|
||||
out_ofh.CRC = 0xffffffff;
|
||||
|
||||
lzx = LZX.Init(oabd_sys, in_ofh.OrigFile, out_ofh.OrigFile, window_bits, 0, BufferSize, blk_dsize, true);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_NOMEMORY;
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.Decompress(lzx, blk_dsize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lzx = null;
|
||||
|
||||
// Consume any trailing padding bytes before the next block
|
||||
ret = CopyFileHandle(infh, null, in_ofh.Available, buf, BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_ofh.CRC != blk_crc)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_CHECKSUM;
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
target_size -= blk_dsize;
|
||||
}
|
||||
|
||||
System.Close(outfh);
|
||||
System.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an Offline Address Book with an incremental patch file.
|
||||
@@ -63,25 +218,184 @@ namespace LibMSPackSharp.OAB
|
||||
/// in incorrect data being decompressed, which will then fail a checksum
|
||||
/// test.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msoab_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// the filename of the input file. This is passed
|
||||
/// The filename of the input file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="base">
|
||||
/// the filename of the base file to which the
|
||||
/// <param name="basePath">
|
||||
/// The filename of the base file to which the
|
||||
/// incremental patch shall be applied. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// the filename of the output file. This is passed
|
||||
/// The filename of the output file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, string, string, string, Error> DecompressIncremental;
|
||||
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Error DecompressIncremental(string input, string basePath, string output)
|
||||
{
|
||||
byte[] hdrbuf = new byte[patchhead_SIZEOF];
|
||||
LZXDStream lzx = null;
|
||||
int window_bits;
|
||||
uint window_size;
|
||||
Error ret = Error.MSPACK_ERR_OK;
|
||||
|
||||
FileStream infh = System.Open(input, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (System.Read(infh, hdrbuf, 0, patchhead_SIZEOF) != patchhead_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (BitConverter.ToUInt32(hdrbuf, patchhead_VersionHi) != 3 ||
|
||||
BitConverter.ToUInt32(hdrbuf, patchhead_VersionLo) != 2)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_SIGNATURE;
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint block_max = BitConverter.ToUInt32(hdrbuf, patchhead_BlockMax);
|
||||
uint target_size = BitConverter.ToUInt32(hdrbuf, patchhead_TargetSize);
|
||||
|
||||
// We use it for reading block headers too
|
||||
if (block_max < patchblk_SIZEOF)
|
||||
block_max = patchblk_SIZEOF;
|
||||
|
||||
FileStream basefh = System.Open(basePath, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (basefh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
FileStream outfh = System.Open(output, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte[] buf = new byte[BufferSize];
|
||||
|
||||
SystemImpl oabd_sys = System;
|
||||
oabd_sys.Read = SysRead;
|
||||
oabd_sys.Write = SysWrite;
|
||||
|
||||
InternalFile in_ofh = new InternalFile();
|
||||
in_ofh.OrigSys = System;
|
||||
in_ofh.OrigFile = infh;
|
||||
|
||||
InternalFile out_ofh = new InternalFile();
|
||||
out_ofh.OrigSys = System;
|
||||
out_ofh.OrigFile = outfh;
|
||||
|
||||
while (target_size != 0)
|
||||
{
|
||||
if (System.Read(infh, buf, 0, patchblk_SIZEOF) != patchblk_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint blk_csize = BitConverter.ToUInt32(buf, patchblk_PatchSize);
|
||||
uint blk_dsize = BitConverter.ToUInt32(buf, patchblk_TargetSize);
|
||||
uint blk_ssize = BitConverter.ToUInt32(buf, patchblk_SourceSize);
|
||||
uint blk_crc = BitConverter.ToUInt32(buf, patchblk_CRC);
|
||||
|
||||
if (blk_dsize > block_max || blk_dsize > target_size || blk_ssize > block_max)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
window_size = (uint)((blk_ssize + 32767) & ~32767);
|
||||
window_size += blk_dsize;
|
||||
window_bits = 17;
|
||||
|
||||
while (window_bits < 25 && (1U << window_bits) < window_size)
|
||||
window_bits++;
|
||||
|
||||
in_ofh.Available = (int)blk_csize;
|
||||
out_ofh.CRC = 0xffffffff;
|
||||
|
||||
lzx = LZX.Init(oabd_sys, in_ofh.OrigFile, out_ofh.OrigFile, window_bits, 0, 4096, blk_dsize, true);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_NOMEMORY;
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.SetReferenceData(lzx, System, basefh, blk_ssize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.Decompress(lzx, blk_dsize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lzx = null;
|
||||
|
||||
// Consume any trailing padding bytes before the next block
|
||||
ret = CopyFileHandle(infh, null, in_ofh.Available, buf, BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_ofh.CRC != blk_crc)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_CHECKSUM;
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
target_size -= blk_dsize;
|
||||
}
|
||||
|
||||
System.Close(outfh);
|
||||
System.Close(basefh);
|
||||
System.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets an OAB decompression engine parameter. Available only in OAB
|
||||
@@ -91,16 +405,95 @@ namespace LibMSPackSharp.OAB
|
||||
/// buffer by decompressors? The minimum value is 16. The default value
|
||||
/// is 4096.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msoab_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="param">the parameter to set</param>
|
||||
/// <param name="value">the value to set the parameter to</param>
|
||||
/// <param name="param">The parameter to set</param>
|
||||
/// <param name="value">The value to set the parameter to</param>
|
||||
/// <returns>
|
||||
/// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
|
||||
/// is a problem with either parameter or value.
|
||||
/// </returns>
|
||||
public Func<Decompressor, Parameters, int, Error> SetParam;
|
||||
public Error SetParam(Parameters param, int value)
|
||||
{
|
||||
if (param == Parameters.MSOABD_PARAM_DECOMPBUF && value >= 16)
|
||||
{
|
||||
// Must be at least 16 bytes (patchblk_SIZEOF, oabblk_SIZEOF)
|
||||
BufferSize = value;
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region I/O Methods
|
||||
|
||||
private static int SysRead(object baseFile, byte[] buf, int pointer, int size)
|
||||
{
|
||||
InternalFile file = baseFile as InternalFile;
|
||||
if (file == null)
|
||||
return 0;
|
||||
|
||||
int bytes_read;
|
||||
|
||||
if (size > file.Available)
|
||||
size = file.Available;
|
||||
|
||||
bytes_read = file.OrigSys.Read(file.OrigFile, buf, pointer, size);
|
||||
if (bytes_read < 0)
|
||||
return bytes_read;
|
||||
|
||||
file.Available -= bytes_read;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
private static int SysWrite(object baseFile, byte[] buf, int pointer, int size)
|
||||
{
|
||||
// Null output file means skip those bytes
|
||||
if (baseFile == null)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
else if (baseFile is InternalFile file)
|
||||
{
|
||||
int bytes_written = file.OrigSys.Write(file.OrigFile, buf, pointer, size);
|
||||
if (bytes_written > 0)
|
||||
file.CRC = Checksum.CRC32(buf, 0, bytes_written, file.CRC);
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
else if (baseFile is FileStream impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Write(impl, buf, pointer, size);
|
||||
}
|
||||
|
||||
// Unknown file to write to
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
private Error CopyFileHandle(FileStream infh, FileStream outfh, int bytes_to_copy, byte[] buf, int buf_size)
|
||||
{
|
||||
while (bytes_to_copy != 0)
|
||||
{
|
||||
int run = buf_size;
|
||||
if (run > bytes_to_copy)
|
||||
run = bytes_to_copy;
|
||||
|
||||
if (System.Read(infh, buf, 0, run) != run)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (outfh != null && System.Write(outfh, buf, 0, run) != run)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
|
||||
bytes_to_copy -= run;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* © 2013 Intel Corporation
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
public class DecompressorImpl : Decompressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public int BufferSize { get; set; }
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
@@ -1,491 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* © 2013 Intel Corporation
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
/* The Exchange Online Addressbook (OAB or sometimes OAL) is distributed
|
||||
* as a .LZX file in one of two forms. Either a "full download" containing
|
||||
* the entire address list, or an incremental binary patch which should be
|
||||
* applied to a previous version of the full decompressed data.
|
||||
*
|
||||
* The contents and format of the decompressed OAB are not handled here.
|
||||
*
|
||||
* For a complete description of the format, see the MSDN site:
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/cc463914 - [MS-OXOAB].pdf
|
||||
* http://msdn.microsoft.com/en-us/library/cc483133 - [MS-PATCH].pdf
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
public class Implementation
|
||||
{
|
||||
#region OAB decompression definitions
|
||||
|
||||
private const int oabhead_VersionHi = 0x0000;
|
||||
private const int oabhead_VersionLo = 0x0004;
|
||||
private const int oabhead_BlockMax = 0x0008;
|
||||
private const int oabhead_TargetSize = 0x000c;
|
||||
private const int oabhead_SIZEOF = 0x0010;
|
||||
|
||||
private const int oabblk_Flags = 0x0000;
|
||||
private const int oabblk_CompSize = 0x0004;
|
||||
private const int oabblk_UncompSize = 0x0008;
|
||||
private const int oabblk_CRC = 0x000c;
|
||||
private const int oabblk_SIZEOF = 0x0010;
|
||||
|
||||
private const int patchhead_VersionHi = 0x0000;
|
||||
private const int patchhead_VersionLo = 0x0004;
|
||||
private const int patchhead_BlockMax = 0x0008;
|
||||
private const int patchhead_SourceSize = 0x000c;
|
||||
private const int patchhead_TargetSize = 0x0010;
|
||||
private const int patchhead_SourceCRC = 0x0014;
|
||||
private const int patchhead_TargetCRC = 0x0018;
|
||||
private const int patchhead_SIZEOF = 0x001c;
|
||||
|
||||
private const int patchblk_PatchSize = 0x0000;
|
||||
private const int patchblk_TargetSize = 0x0004;
|
||||
private const int patchblk_SourceSize = 0x0008;
|
||||
private const int patchblk_CRC = 0x000c;
|
||||
private const int patchblk_SIZEOF = 0x0010;
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_SYS_READ
|
||||
|
||||
private static int SysRead(object baseFile, byte[] buf, int pointer, int size)
|
||||
{
|
||||
InternalFile file = baseFile as InternalFile;
|
||||
if (file == null)
|
||||
return 0;
|
||||
|
||||
int bytes_read;
|
||||
|
||||
if (size > file.Available)
|
||||
size = file.Available;
|
||||
|
||||
bytes_read = file.OrigSys.Read(file.OrigFile, buf, pointer, size);
|
||||
if (bytes_read < 0)
|
||||
return bytes_read;
|
||||
|
||||
file.Available -= bytes_read;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_SYS_WRITE
|
||||
|
||||
private static int SysWrite(object baseFile, byte[] buf, int pointer, int size)
|
||||
{
|
||||
// Null output file means skip those bytes
|
||||
if (baseFile == null)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
else if (baseFile is InternalFile file)
|
||||
{
|
||||
int bytes_written = file.OrigSys.Write(file.OrigFile, buf, pointer, size);
|
||||
if (bytes_written > 0)
|
||||
file.CRC = Checksum.CRC32(buf, 0, bytes_written, file.CRC);
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
else if (baseFile is FileStream impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Write(impl, buf, pointer, size);
|
||||
}
|
||||
|
||||
// Unknown file to write to
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_DECOMPRESS
|
||||
|
||||
public static Error Decompress(Decompressor d, string input, string output)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
byte[] hdrbuf = new byte[oabhead_SIZEOF];
|
||||
LZXDStream lzx = null;
|
||||
Error ret = Error.MSPACK_ERR_OK;
|
||||
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
FileStream infh = sys.Open(input, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sys.Read(infh, hdrbuf, 0, oabhead_SIZEOF) != oabhead_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (BitConverter.ToUInt32(hdrbuf, oabhead_VersionHi) != 3 ||
|
||||
BitConverter.ToUInt32(hdrbuf, oabhead_VersionLo) != 1)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_SIGNATURE;
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint block_max = BitConverter.ToUInt32(hdrbuf, oabhead_BlockMax);
|
||||
uint target_size = BitConverter.ToUInt32(hdrbuf, oabhead_TargetSize);
|
||||
|
||||
FileStream outfh = sys.Open(output, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte[] buf = new byte[self.BufferSize];
|
||||
|
||||
SystemImpl oabd_sys = sys;
|
||||
oabd_sys.Read = SysRead;
|
||||
oabd_sys.Write = SysWrite;
|
||||
|
||||
InternalFile in_ofh = new InternalFile();
|
||||
in_ofh.OrigSys = sys;
|
||||
in_ofh.OrigFile = infh;
|
||||
|
||||
InternalFile out_ofh = new InternalFile();
|
||||
out_ofh.OrigSys = sys;
|
||||
out_ofh.OrigFile = outfh;
|
||||
|
||||
while (target_size != 0)
|
||||
{
|
||||
if (sys.Read(infh, buf, 0, oabblk_SIZEOF) != oabblk_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint blk_flags = BitConverter.ToUInt32(buf, oabblk_Flags);
|
||||
uint blk_csize = BitConverter.ToUInt32(buf, oabblk_CompSize);
|
||||
uint blk_dsize = BitConverter.ToUInt32(buf, oabblk_UncompSize);
|
||||
uint blk_crc = BitConverter.ToUInt32(buf, oabblk_CRC);
|
||||
|
||||
if (blk_dsize > block_max || blk_dsize > target_size || blk_flags > 1)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (blk_flags == 0)
|
||||
{
|
||||
// Uncompressed block
|
||||
if (blk_dsize != blk_csize)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = CopyFileHandle(sys, infh, outfh, (int)blk_dsize, buf, self.BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// LZX compressed block
|
||||
int window_bits = 17;
|
||||
|
||||
while (window_bits < 25 && (1U << window_bits) < blk_dsize)
|
||||
{
|
||||
window_bits++;
|
||||
}
|
||||
|
||||
in_ofh.Available = (int)blk_csize;
|
||||
out_ofh.CRC = 0xffffffff;
|
||||
|
||||
lzx = LZX.Init(oabd_sys, in_ofh.OrigFile, out_ofh.OrigFile, window_bits, 0, self.BufferSize, blk_dsize, true);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_NOMEMORY;
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.Decompress(lzx, blk_dsize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lzx = null;
|
||||
|
||||
// Consume any trailing padding bytes before the next block
|
||||
ret = CopyFileHandle(sys, infh, null, in_ofh.Available, buf, self.BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_ofh.CRC != blk_crc)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_CHECKSUM;
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
target_size -= blk_dsize;
|
||||
}
|
||||
|
||||
sys.Close(outfh);
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_DECOMPRESS_INCREMENTAL
|
||||
|
||||
public static Error DecompressIncremental(Decompressor d, string input, string basePath, string output)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
byte[] hdrbuf = new byte[patchhead_SIZEOF];
|
||||
LZXDStream lzx = null;
|
||||
int window_bits;
|
||||
uint window_size;
|
||||
Error ret = Error.MSPACK_ERR_OK;
|
||||
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
FileStream infh = sys.Open(input, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sys.Read(infh, hdrbuf, 0, patchhead_SIZEOF) != patchhead_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (BitConverter.ToUInt32(hdrbuf, patchhead_VersionHi) != 3 ||
|
||||
BitConverter.ToUInt32(hdrbuf, patchhead_VersionLo) != 2)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_SIGNATURE;
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint block_max = BitConverter.ToUInt32(hdrbuf, patchhead_BlockMax);
|
||||
uint target_size = BitConverter.ToUInt32(hdrbuf, patchhead_TargetSize);
|
||||
|
||||
// We use it for reading block headers too
|
||||
if (block_max < patchblk_SIZEOF)
|
||||
block_max = patchblk_SIZEOF;
|
||||
|
||||
FileStream basefh = sys.Open(basePath, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (basefh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
FileStream outfh = sys.Open(output, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte[] buf = new byte[self.BufferSize];
|
||||
|
||||
SystemImpl oabd_sys = sys;
|
||||
oabd_sys.Read = SysRead;
|
||||
oabd_sys.Write = SysWrite;
|
||||
|
||||
InternalFile in_ofh = new InternalFile();
|
||||
in_ofh.OrigSys = sys;
|
||||
in_ofh.OrigFile = infh;
|
||||
|
||||
InternalFile out_ofh = new InternalFile();
|
||||
out_ofh.OrigSys = sys;
|
||||
out_ofh.OrigFile = outfh;
|
||||
|
||||
while (target_size != 0)
|
||||
{
|
||||
if (sys.Read(infh, buf, 0, patchblk_SIZEOF) != patchblk_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint blk_csize = BitConverter.ToUInt32(buf, patchblk_PatchSize);
|
||||
uint blk_dsize = BitConverter.ToUInt32(buf, patchblk_TargetSize);
|
||||
uint blk_ssize = BitConverter.ToUInt32(buf, patchblk_SourceSize);
|
||||
uint blk_crc = BitConverter.ToUInt32(buf, patchblk_CRC);
|
||||
|
||||
if (blk_dsize > block_max || blk_dsize > target_size || blk_ssize > block_max)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
window_size = (uint)((blk_ssize + 32767) & ~32767);
|
||||
window_size += blk_dsize;
|
||||
window_bits = 17;
|
||||
|
||||
while (window_bits < 25 && (1U << window_bits) < window_size)
|
||||
window_bits++;
|
||||
|
||||
in_ofh.Available = (int)blk_csize;
|
||||
out_ofh.CRC = 0xffffffff;
|
||||
|
||||
lzx = LZX.Init(oabd_sys, in_ofh.OrigFile, out_ofh.OrigFile, window_bits, 0, 4096, blk_dsize, true);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_NOMEMORY;
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.SetReferenceData(lzx, sys, basefh, blk_ssize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.Decompress(lzx, blk_dsize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
lzx = null;
|
||||
|
||||
// Consume any trailing padding bytes before the next block
|
||||
ret = CopyFileHandle(sys, infh, null, in_ofh.Available, buf, self.BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_ofh.CRC != blk_crc)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_CHECKSUM;
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
target_size -= blk_dsize;
|
||||
}
|
||||
|
||||
sys.Close(outfh);
|
||||
sys.Close(basefh);
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Error CopyFileHandle(SystemImpl sys, FileStream infh, FileStream outfh, int bytes_to_copy, byte[] buf, int buf_size)
|
||||
{
|
||||
while (bytes_to_copy != 0)
|
||||
{
|
||||
int run = buf_size;
|
||||
if (run > bytes_to_copy)
|
||||
run = bytes_to_copy;
|
||||
|
||||
if (sys.Read(infh, buf, 0, run) != run)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (outfh != null && sys.Write(outfh, buf, 0, run) != run)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
|
||||
bytes_to_copy -= run;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_PARAM
|
||||
|
||||
public static Error Param(Decompressor d, Parameters param, int value)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self != null && param == Parameters.MSOABD_PARAM_DECOMPBUF && value >= 16)
|
||||
{
|
||||
// must be at least 16 bytes (patchblk_SIZEOF, oabblk_SIZEOF)
|
||||
self.BufferSize = value;
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,14 @@ namespace LibMSPackSharp.SZDD
|
||||
/// <see cref="Library.DestroySZDDCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Reads an input file and creates a compressed output file in the
|
||||
/// SZDD compressed file format. The SZDD compression format is quick
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
public class CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
}
|
||||
}
|
||||
188
BurnOutSharp/External/libmspack/SZDD/Decompressor.cs
vendored
188
BurnOutSharp/External/libmspack/SZDD/Decompressor.cs
vendored
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LibMSPackSharp.Compression;
|
||||
using static LibMSPackSharp.Constants;
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
@@ -25,8 +29,10 @@ namespace LibMSPackSharp.SZDD
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateSZDDDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroySZDDDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
public class Decompressor : BaseDecompressor
|
||||
{
|
||||
#region Public Functionality
|
||||
|
||||
/// <summary>
|
||||
/// Opens a SZDD file and reads the header.
|
||||
///
|
||||
@@ -39,17 +45,37 @@ namespace LibMSPackSharp.SZDD
|
||||
/// The filename pointer should be considered "in use" until close() is
|
||||
/// called on the SZDD file.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="filename">
|
||||
/// the filename of the SZDD compressed file. This is
|
||||
/// The filename of the SZDD compressed file. This is
|
||||
/// passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>a pointer to a msszddd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Close"/>
|
||||
public Func<Decompressor, string, Header> Open;
|
||||
/// <returns>A pointer to a msszddd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Close(Header)"/>
|
||||
public Header Open(string filename)
|
||||
{
|
||||
FileStream fh = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
Header hdr = new Header();
|
||||
if (fh != null && hdr != null)
|
||||
{
|
||||
hdr.FileHandle = fh;
|
||||
Error = ReadHeaders(fh, hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fh == null)
|
||||
Error = Error.MSPACK_ERR_OPEN;
|
||||
if (hdr == null)
|
||||
Error = Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
System.Close(fh);
|
||||
hdr = null;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened SZDD file.
|
||||
@@ -59,13 +85,18 @@ namespace LibMSPackSharp.SZDD
|
||||
///
|
||||
/// The SZDD header pointer is now invalid and cannot be used again.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="szdd">the SZDD file to close</param>
|
||||
/// <see cref="Open"/>
|
||||
public Action<Decompressor, Header> Close;
|
||||
/// <param name="szdd">The SZDD file to close</param>
|
||||
/// <see cref="Open(string)"/>
|
||||
public void Close(Header hdr)
|
||||
{
|
||||
if (System == null || hdr == null)
|
||||
return;
|
||||
|
||||
// Close the file handle associated
|
||||
System.Close(hdr.FileHandle);
|
||||
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the compressed data from a SZDD file.
|
||||
@@ -73,17 +104,46 @@ namespace LibMSPackSharp.SZDD
|
||||
/// This decompresses the compressed SZDD data stream and writes it to
|
||||
/// an output file.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="szdd">the SZDD file to extract data from</param>
|
||||
/// <param name="hdr">The SZDD file to extract data from</param>
|
||||
/// <param name="filename">
|
||||
/// filename the filename to write the decompressed data to. This
|
||||
/// The filename to write the decompressed data to. This
|
||||
/// is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, Header, string, Error> Extract;
|
||||
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Error Extract(Header hdr, string filename)
|
||||
{
|
||||
if (hdr == null)
|
||||
return Error = Error.MSPACK_ERR_ARGS;
|
||||
|
||||
FileStream fh = hdr.FileHandle;
|
||||
if (fh == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
// Seek to the compressed data
|
||||
long dataOffset = (hdr.Format == Format.MSSZDD_FMT_NORMAL) ? 14 : 12;
|
||||
if (System.Seek(fh, dataOffset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return Error = Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Open file for output
|
||||
FileStream outfh = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
return Error = Error.MSPACK_ERR_OPEN;
|
||||
|
||||
// Decompress the data
|
||||
Error = LZSS.Decompress(
|
||||
System,
|
||||
fh,
|
||||
outfh,
|
||||
SZDD_INPUT_SIZE,
|
||||
hdr.Format == Format.MSSZDD_FMT_NORMAL
|
||||
? LZSSMode.LZSS_MODE_EXPAND
|
||||
: LZSSMode.LZSS_MODE_QBASIC);
|
||||
|
||||
// Close output file
|
||||
System.Close(outfh);
|
||||
|
||||
return Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an SZDD file to an output file in one step.
|
||||
@@ -94,35 +154,73 @@ namespace LibMSPackSharp.SZDD
|
||||
/// open() then extract() then close(), if you do not need to know the
|
||||
/// SZDD output size or missing character.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// the filename of the input SZDD file. This is passed
|
||||
/// The filename of the input SZDD file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// the filename to write the decompressed data to. This
|
||||
/// The filename to write the decompressed data to. This
|
||||
/// is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, string, string, Error> Decompress;
|
||||
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Error Decompress(string input, string output)
|
||||
{
|
||||
Header hdr = Open(input) as Header;
|
||||
if (hdr == null)
|
||||
return Error;
|
||||
|
||||
Error error = Extract(hdr, output);
|
||||
Close(hdr);
|
||||
return Error = error;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
///
|
||||
/// This is useful for open() which does not return an
|
||||
/// error code directly.
|
||||
/// Reads the headers of an SZDD format file
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Extract"/>
|
||||
/// <see cref="Decompress"/>
|
||||
public Func<Decompressor, Error> LastError;
|
||||
private Error ReadHeaders(FileStream fh, Header hdr)
|
||||
{
|
||||
// Read and check signature
|
||||
byte[] buf = new byte[8];
|
||||
if (System.Read(fh, buf, 0, 8) != 8)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (buf.SequenceEqual(expandSignature))
|
||||
{
|
||||
// Common SZDD
|
||||
hdr.Format = Format.MSSZDD_FMT_NORMAL;
|
||||
|
||||
// Read the rest of the header
|
||||
if (System.Read(fh, buf, 0, 6) != 6)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (buf[0] != 0x41)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
hdr.MissingChar = (char)buf[1];
|
||||
hdr.Length = BitConverter.ToUInt32(buf, 2);
|
||||
}
|
||||
if (buf.SequenceEqual(qbasicSignature))
|
||||
{
|
||||
// Special QBasic SZDD
|
||||
hdr.Format = Format.MSSZDD_FMT_QBASIC;
|
||||
if (System.Read(fh, buf, 0, 4) != 4)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
hdr.MissingChar = '\0';
|
||||
hdr.Length = BitConverter.ToUInt32(buf, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Error.MSPACK_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
public class DecompressorImpl : Decompressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
/// <summary>
|
||||
@@ -21,7 +23,7 @@ namespace LibMSPackSharp.SZDD
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class Header
|
||||
public class Header : BaseHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// The file format
|
||||
@@ -41,5 +43,7 @@ namespace LibMSPackSharp.SZDD
|
||||
/// an MS-DOS filename (except ".") are valid.
|
||||
/// </summary>
|
||||
public char MissingChar { get; set; }
|
||||
|
||||
public FileStream FileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
public class HeaderImpl : Header
|
||||
{
|
||||
public FileStream FileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
public class Implementation
|
||||
{
|
||||
/// <summary>
|
||||
/// Input buffer size during decompression - not worth parameterising IMHO
|
||||
/// </summary>
|
||||
private const int SZDD_INPUT_SIZE = 2048;
|
||||
|
||||
#region SZDDD_OPEN
|
||||
|
||||
/// <summary>
|
||||
/// Opens an SZDD file without decompressing, reads header
|
||||
/// </summary>
|
||||
public static Header Open(Decompressor d, string filename)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self == null)
|
||||
return null;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
FileStream fh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
HeaderImpl hdr = new HeaderImpl();
|
||||
if (fh != null && hdr != null)
|
||||
{
|
||||
hdr.FileHandle = fh;
|
||||
self.Error = ReadHeaders(sys, fh, hdr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fh == null)
|
||||
self.Error = Error.MSPACK_ERR_OPEN;
|
||||
if (hdr == null)
|
||||
self.Error = Error.MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
if (self.Error != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
sys.Close(fh);
|
||||
hdr = null;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDDD_CLOSE
|
||||
|
||||
/// <summary>
|
||||
/// Closes an SZDD file
|
||||
/// </summary>
|
||||
public static void Close(Decompressor d, Header hdr)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
HeaderImpl hdr_p = hdr as HeaderImpl;
|
||||
|
||||
if (self?.System == null || hdr == null)
|
||||
return;
|
||||
|
||||
// Close the file handle associated
|
||||
self.System.Close(hdr_p.FileHandle);
|
||||
|
||||
self.Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDDD_READ_HEADERS
|
||||
|
||||
private static byte[] expandSignature = new byte[8]
|
||||
{
|
||||
0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33
|
||||
};
|
||||
|
||||
private static byte[] qbasicSignature = new byte[8]
|
||||
{
|
||||
0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Reads the headers of an SZDD format file
|
||||
/// </summary>
|
||||
public static Error ReadHeaders(SystemImpl sys, FileStream fh, Header hdr)
|
||||
{
|
||||
// Read and check signature
|
||||
byte[] buf = new byte[8];
|
||||
if (sys.Read(fh, buf, 0, 8) != 8)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (buf.SequenceEqual(expandSignature))
|
||||
{
|
||||
// Common SZDD
|
||||
hdr.Format = Format.MSSZDD_FMT_NORMAL;
|
||||
|
||||
// Read the rest of the header
|
||||
if (sys.Read(fh, buf, 0, 6) != 6)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (buf[0] != 0x41)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
hdr.MissingChar = (char)buf[1];
|
||||
hdr.Length = BitConverter.ToUInt32(buf, 2);
|
||||
}
|
||||
if (buf.SequenceEqual(qbasicSignature))
|
||||
{
|
||||
// Special QBasic SZDD
|
||||
hdr.Format = Format.MSSZDD_FMT_QBASIC;
|
||||
if (sys.Read(fh, buf, 0, 4) != 4)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
hdr.MissingChar = '\0';
|
||||
hdr.Length = BitConverter.ToUInt32(buf, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Error.MSPACK_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDDD_EXTRACT
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an SZDD file
|
||||
/// </summary>
|
||||
public static Error Extract(Decompressor d, Header hdr, string filename)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
if (hdr == null)
|
||||
return self.Error = Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
FileStream fh = (hdr as HeaderImpl)?.FileHandle;
|
||||
if (fh == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
// Seek to the compressed data
|
||||
long dataOffset = (hdr.Format == Format.MSSZDD_FMT_NORMAL) ? 14 : 12;
|
||||
if (sys.Seek(fh, dataOffset, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return self.Error = Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Open file for output
|
||||
FileStream outfh;
|
||||
if ((outfh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
|
||||
return self.Error = Error.MSPACK_ERR_OPEN;
|
||||
|
||||
// Decompress the data
|
||||
self.Error = LZSS.Decompress(
|
||||
sys,
|
||||
fh,
|
||||
outfh,
|
||||
SZDD_INPUT_SIZE,
|
||||
hdr.Format == Format.MSSZDD_FMT_NORMAL
|
||||
? LZSSMode.LZSS_MODE_EXPAND
|
||||
: LZSSMode.LZSS_MODE_QBASIC);
|
||||
|
||||
// Close output file
|
||||
sys.Close(outfh);
|
||||
|
||||
return self.Error;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDDD_DECOMPRESS
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks directly from input to output
|
||||
/// </summary>
|
||||
public static Error Decompress(Decompressor d, string input, string output)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
Header hdr;
|
||||
if ((hdr = Open(d, input)) == null)
|
||||
return self.Error;
|
||||
|
||||
Error error = Extract(d, hdr, output);
|
||||
Close(d, hdr);
|
||||
return self.Error = error;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDDD_ERROR
|
||||
|
||||
/// <summary>
|
||||
/// Returns the last error that occurred
|
||||
/// </summary>
|
||||
public static Error LastError(Decompressor d)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
return (self != null) ? self.Error : Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user