mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-22 23:05:03 +00:00
Add initial port of libmspack (nw)
This commit is contained in:
175
BurnOutSharp/External/libmspack/CAB/Cabinet.cs
vendored
Normal file
175
BurnOutSharp/External/libmspack/CAB/Cabinet.cs
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
/* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a single cabinet file.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
///
|
||||
/// If this cabinet is part of a merged cabinet set, the #files and #folders
|
||||
/// fields are common to all cabinets in the set, and will be identical.
|
||||
/// </summary>
|
||||
/// <see cref="Decompressor.Open"/>
|
||||
/// <see cref="Decompressor.Close"/>
|
||||
/// <see cref="Decompressor.Search"/>
|
||||
public class Cabinet
|
||||
{
|
||||
/// <summary>
|
||||
/// The next cabinet in a chained list, if this cabinet was opened with
|
||||
/// mscab_decompressor::search(). May be NULL to mark the end of the
|
||||
/// list.
|
||||
/// </summary>
|
||||
public Cabinet Next { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the cabinet. More correctly, the filename of the
|
||||
/// physical file that the cabinet resides in. This is given by the
|
||||
/// library user and may be in any format.
|
||||
/// </summary>
|
||||
public string Filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file offset of cabinet within the physical file it resides in.
|
||||
/// </summary>
|
||||
public long BaseOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the cabinet file in bytes.
|
||||
/// </summary>
|
||||
public uint Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The previous cabinet in a cabinet set, or NULL.
|
||||
/// </summary>
|
||||
public Cabinet PreviousCabinet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The next cabinet in a cabinet set, or NULL.
|
||||
/// </summary>
|
||||
public Cabinet NextCabinet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the previous cabinet in a cabinet set, or NULL.
|
||||
/// </summary>
|
||||
public string PreviousName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the next cabinet in a cabinet set, or NULL.
|
||||
/// </summary>
|
||||
public string NextName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the disk containing the previous cabinet in a cabinet, or NULL.
|
||||
/// </summary>
|
||||
public string PreviousInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the disk containing the next cabinet in a cabinet set, or NULL.
|
||||
/// </summary>
|
||||
public string NextInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of all files in the cabinet or cabinet set.
|
||||
/// </summary>
|
||||
public InternalFile Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of all folders in the cabinet or cabinet set.
|
||||
/// </summary>
|
||||
public Folder Folders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set ID of the cabinet. All cabinets in the same set should have
|
||||
/// the same set ID.
|
||||
/// </summary>
|
||||
public ushort SetID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The index number of the cabinet within the set. Numbering should
|
||||
/// start from 0 for the first cabinet in the set, and increment by 1 for
|
||||
/// each following cabinet.
|
||||
/// </summary>
|
||||
public ushort SetIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes reserved in the header area of the cabinet.
|
||||
///
|
||||
/// If this is non-zero and flags has MSCAB_HDR_RESV set, this data can
|
||||
/// be read by the calling application. It is of the given length,
|
||||
/// located at offset (base_offset + MSCAB_HDR_RESV_OFFSET) in the
|
||||
/// cabinet file.
|
||||
/// </summary>
|
||||
/// <see cref="Flags"/>
|
||||
public ushort HeaderResv { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Header flags.
|
||||
/// </summary>
|
||||
/// <see cref="PreviousName"/>
|
||||
/// <see cref="PreviousInfo"/>
|
||||
/// <see cref="NextName"/>
|
||||
/// <see cref="NextInfo"/>
|
||||
/// <see cref="HeaderResv"/>
|
||||
public HeaderFlags Flags { get; set; }
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/CAB/CabinetImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/CAB/CabinetImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class CabinetImpl : Cabinet
|
||||
{
|
||||
public long BlocksOffset { get; set; }
|
||||
|
||||
public int BlockResverved { get; set; }
|
||||
}
|
||||
}
|
||||
26
BurnOutSharp/External/libmspack/CAB/Compressor.cs
vendored
Normal file
26
BurnOutSharp/External/libmspack/CAB/Compressor.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public class Compressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
}
|
||||
}
|
||||
19
BurnOutSharp/External/libmspack/CAB/CompressorImpl.cs
vendored
Normal file
19
BurnOutSharp/External/libmspack/CAB/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
public class CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
}
|
||||
}
|
||||
58
BurnOutSharp/External/libmspack/CAB/DataBlockHeader.cs
vendored
Normal file
58
BurnOutSharp/External/libmspack/CAB/DataBlockHeader.cs
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class DataBlockHeader
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// CRC32 checksum of the data
|
||||
/// </summary>
|
||||
public uint Checksum { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compressed size of the data
|
||||
/// </summary>
|
||||
public ushort CompressedSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed size of the data
|
||||
/// </summary>
|
||||
public ushort UncompressedSize { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
private DataBlockHeader() { }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public static Error Create(byte[] data, out DataBlockHeader header)
|
||||
{
|
||||
header = null;
|
||||
if (data == null || data.Length < 0x08)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
header = new DataBlockHeader();
|
||||
|
||||
header.Checksum = BitConverter.ToUInt32(data, 0x00);
|
||||
header.CompressedSize = BitConverter.ToUInt16(data, 0x04);
|
||||
header.UncompressedSize = BitConverter.ToUInt16(data, 0x06);
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
BurnOutSharp/External/libmspack/CAB/DecompressState.cs
vendored
Normal file
91
BurnOutSharp/External/libmspack/CAB/DecompressState.cs
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class DecompressState
|
||||
{
|
||||
/// <summary>
|
||||
/// Current folder we're extracting from
|
||||
/// </summary>
|
||||
public Folder Folder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current folder split we're in
|
||||
/// </summary>
|
||||
public FolderData Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed offset within folder
|
||||
/// </summary>
|
||||
public uint Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Which block are we decompressing?
|
||||
/// </summary>
|
||||
public uint Block { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cumulative sum of block output sizes
|
||||
/// </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>
|
||||
public CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decompressor code
|
||||
/// </summary>
|
||||
public Func<object, long, Error> Decompress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decompressor state
|
||||
/// </summary>
|
||||
public object DecompressorState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cabinet where input data comes from
|
||||
/// </summary>
|
||||
public Cabinet InputCabinet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public object InputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public object OutputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input data consumed
|
||||
/// </summary>
|
||||
public int IPtr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input data end
|
||||
/// </summary>
|
||||
public int IEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// One input block of data
|
||||
/// </summary>
|
||||
public byte[] Input { get; set; } = new byte[Implementation.CAB_INPUTBUF];
|
||||
}
|
||||
}
|
||||
268
BurnOutSharp/External/libmspack/CAB/Decompressor.cs
vendored
Normal file
268
BurnOutSharp/External/libmspack/CAB/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// A decompressor for .CAB (Microsoft Cabinet) files
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="mspack_create_cab_decompressor()"/>
|
||||
/// <see cref="mspack_destroy_cab_decompressor()"/>
|
||||
public class Decompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a cabinet file and reads its contents.
|
||||
///
|
||||
/// If the file opened is a valid cabinet file, all headers will be read
|
||||
/// and a Cabinet structure will be returned, with a full list of
|
||||
/// folders and files.
|
||||
///
|
||||
/// In the case of an error occuring, NULL is returned and the error code
|
||||
/// is available from last_error().
|
||||
///
|
||||
/// The filename pointer should be considered "in use" until close() is
|
||||
/// called on the cabinet.
|
||||
/// </summary>
|
||||
/// <param name="decompressor">A self-referential pointer to the Decompressor instance being called</param>
|
||||
/// <param name="filename">The filename of the cabinet file. This is passed directly to SystemImpl::open().</param>
|
||||
/// <returns>A pointer to a Cabinet structure, or NULL on failure</returns>
|
||||
/// <see cref="Close"/>
|
||||
/// <see cref="Search"/>
|
||||
/// <see cref="LastError"/>
|
||||
public Func<Decompressor, string, CabinetImpl> Open;
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened cabinet or cabinet set.
|
||||
///
|
||||
/// This closes a cabinet, all cabinets associated with it via the
|
||||
/// Cabinet::next, Cabinet::prevcab and
|
||||
/// Cabinet::nextcab pointers, and all folders and files. All
|
||||
/// memory used by these entities is freed.
|
||||
///
|
||||
/// The cabinet pointer is now invalid and cannot be used again. All
|
||||
/// Folder and InternalFile pointers from that cabinet or cabinet
|
||||
/// set are also now invalid, and cannot be used again.
|
||||
///
|
||||
/// If the cabinet pointer given was created using search(), it MUST be
|
||||
/// the cabinet pointer returned by search() and not one of the later
|
||||
/// cabinet pointers further along the Cabinet::next chain.
|
||||
///
|
||||
/// If extra cabinets have been added using append() or prepend(), these
|
||||
/// will all be freed, even if the cabinet pointer given is not the first
|
||||
/// cabinet in the set. Do NOT close() more than one cabinet in the set.
|
||||
///
|
||||
/// The Cabinet::filename is not freed by the library, as it is
|
||||
/// not allocated by the library. The caller should free this itself if
|
||||
/// necessary, before it is lost forever.
|
||||
/// </summary>
|
||||
/// <param name="decompressor">A self-referential pointer to the Decompressor instance being called</param>
|
||||
/// <param name="cab">The cabinet to close</param>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Search"/>
|
||||
/// <see cref="Append"/>
|
||||
/// <see cref="Prepend"/>
|
||||
public Action<Decompressor, Cabinet> Close;
|
||||
|
||||
/// <summary>
|
||||
/// Searches a regular file for embedded cabinets.
|
||||
///
|
||||
/// This opens a normal file with the given filename and will search the
|
||||
/// entire file for embedded cabinet files
|
||||
///
|
||||
/// If any cabinets are found, the equivalent of open() is called on each
|
||||
/// potential cabinet file at the offset it was found. All successfully
|
||||
/// open()ed cabinets are kept in a list.
|
||||
///
|
||||
/// The first cabinet found will be returned directly as the result of
|
||||
/// this method. Any further cabinets found will be chained in a list
|
||||
/// using the Cabinet::next field.
|
||||
///
|
||||
/// In the case of an error occuring anywhere other than the simulated
|
||||
/// open(), NULL is returned and the error code is available from
|
||||
/// last_error().
|
||||
///
|
||||
/// If no error occurs, but no cabinets can be found in the file, NULL is
|
||||
/// returned and last_error() returns MSPACK_ERR_OK.
|
||||
///
|
||||
/// The filename pointer should be considered in use until close() is
|
||||
/// called on the cabinet.
|
||||
///
|
||||
/// close() should only be called on the result of search(), not on any
|
||||
/// subsequent cabinets in the Cabinet::next chain.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="filename">
|
||||
/// the filename of the file to search for cabinets. This
|
||||
/// is passed directly to SystemImpl::open().
|
||||
/// </param>
|
||||
/// <returns>a pointer to a Cabinet structure, or NULL</returns>
|
||||
/// <see cref="Close"/>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="LastError"/>
|
||||
public Func<Decompressor, string, Cabinet> Search;
|
||||
|
||||
/// <summary>
|
||||
/// Appends one Cabinet to another, forming or extending a cabinet
|
||||
/// set.
|
||||
///
|
||||
/// This will attempt to append one cabinet to another such that
|
||||
/// <tt>(cab->nextcab == nextcab) && (nextcab->prevcab == cab)</tt> and
|
||||
/// any folders split between the two cabinets are merged.
|
||||
///
|
||||
/// The cabinets MUST be part of a cabinet set -- a cabinet set is a
|
||||
/// cabinet that spans more than one physical cabinet file on disk -- and
|
||||
/// must be appropriately matched.
|
||||
///
|
||||
/// It can be determined if a cabinet has further parts to load by
|
||||
/// examining the Cabinet::flags field:
|
||||
///
|
||||
/// - if <tt>(flags & MSCAB_HDR_PREVCAB)</tt> is non-zero, there is a
|
||||
/// predecessor cabinet to open() and prepend(). Its MS-DOS
|
||||
/// case-insensitive filename is Cabinet::prevname
|
||||
/// - if <tt>(flags & MSCAB_HDR_NEXTCAB)</tt> is non-zero, there is a
|
||||
/// successor cabinet to open() and append(). Its MS-DOS case-insensitive
|
||||
/// filename is Cabinet::nextname
|
||||
///
|
||||
/// If the cabinets do not match, an error code will be returned. Neither
|
||||
/// cabinet has been altered, and both should be closed seperately.
|
||||
///
|
||||
/// Files and folders in a cabinet set are a single entity. All cabinets
|
||||
/// in a set use the same file list, which is updated as cabinets in the
|
||||
/// set are added. All pointers to Folder and InternalFile
|
||||
/// structures in either cabinet must be discarded and re-obtained after
|
||||
/// merging.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="cab">
|
||||
/// the cabinet which will be appended to,
|
||||
/// predecessor of nextcab
|
||||
/// </param>
|
||||
/// <param name="nextcab">
|
||||
/// the cabinet which will be appended,
|
||||
/// successor of cab
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="Prepend"/>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Close"/>
|
||||
public Func<Decompressor, Cabinet, Cabinet, Error> Append;
|
||||
|
||||
/// <summary>
|
||||
/// Prepends one Cabinet to another, forming or extending a
|
||||
/// cabinet set.
|
||||
///
|
||||
/// This will attempt to prepend one cabinet to another, such that
|
||||
/// <tt>(cab->prevcab == prevcab) && (prevcab->nextcab == cab)</tt>. In
|
||||
/// all other respects, it is identical to append(). See append() for the
|
||||
/// full documentation.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="cab">
|
||||
/// the cabinet which will be prepended to,
|
||||
/// successor of nextcab
|
||||
/// </param>
|
||||
/// <param name="nextcab">
|
||||
/// the cabinet which will be prepended,
|
||||
/// predecessor of cab
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="Append"/>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Close"/>
|
||||
public Func<Decompressor, Cabinet, Cabinet, Error> Prepend;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts a file from a cabinet or cabinet set.
|
||||
///
|
||||
/// This extracts a compressed file in a cabinet and writes it to the given
|
||||
/// filename.
|
||||
///
|
||||
/// The MS-DOS filename of the file, InternalFile::filename, is NOT USED
|
||||
/// by extract(). The caller must examine this MS-DOS filename, copy and
|
||||
/// change it as necessary, create directories as necessary, and provide
|
||||
/// the correct filename as a parameter, which will be passed unchanged
|
||||
/// to the decompressor's SystemImpl::open()
|
||||
///
|
||||
/// If the file belongs to a split folder in a multi-part cabinet set,
|
||||
/// and not enough parts of the cabinet set have been loaded and appended
|
||||
/// or prepended, an error will be returned immediately.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="file">the file to be decompressed</param>
|
||||
/// <param name="filename">the filename of the file being written to</param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, InternalFile, string, Error> Extract;
|
||||
|
||||
/// <summary>
|
||||
/// Sets a CAB decompression engine parameter.
|
||||
///
|
||||
/// The following parameters are defined:
|
||||
/// - #MSCABD_PARAM_SEARCHBUF: How many bytes should be allocated as a
|
||||
/// buffer when using search()? The minimum value is 4. The default
|
||||
/// value is 32768.
|
||||
/// - #MSCABD_PARAM_FIXMSZIP: If non-zero, extract() will ignore bad
|
||||
/// checksums and recover from decompression errors in MS-ZIP
|
||||
/// compressed folders. The default value is 0 (don't recover).
|
||||
/// - #MSCABD_PARAM_DECOMPBUF: How many bytes should be used as an input
|
||||
/// bit buffer by decompressors? The minimum value is 4. The default
|
||||
/// value is 4096.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Decompressor
|
||||
/// instance being called
|
||||
/// </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>
|
||||
/// <see cref="Search"/>
|
||||
/// <see cref="Extract"/>
|
||||
public Func<Decompressor, Parameters, int, Error> SetParam;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
///
|
||||
/// This is useful for open() and search(), which do not return an error
|
||||
/// code directly.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Search"/>
|
||||
public Func<Decompressor, Error> LastError;
|
||||
}
|
||||
}
|
||||
30
BurnOutSharp/External/libmspack/CAB/DecompressorImpl.cs
vendored
Normal file
30
BurnOutSharp/External/libmspack/CAB/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class DecompressorImpl : Decompressor
|
||||
{
|
||||
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; }
|
||||
}
|
||||
}
|
||||
113
BurnOutSharp/External/libmspack/CAB/Enums.cs
vendored
Normal file
113
BurnOutSharp/External/libmspack/CAB/Enums.cs
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
[Flags]
|
||||
public enum CompressionType : ushort
|
||||
{
|
||||
COMPTYPE_MASK = 0x000f,
|
||||
|
||||
COMPTYPE_NONE = 0x0000,
|
||||
COMPTYPE_MSZIP = 0x0001,
|
||||
COMPTYPE_QUANTUM = 0x0002,
|
||||
COMPTYPE_LZX = 0x0003,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FileAttributes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the file is write protected.
|
||||
/// </summary>
|
||||
MSCAB_ATTRIB_RDONLY = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the file is hidden.
|
||||
/// </summary>
|
||||
MSCAB_ATTRIB_HIDDEN = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the file is a operating system file.
|
||||
/// </summary>
|
||||
MSCAB_ATTRIB_SYSTEM = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the file is "archived".
|
||||
/// </summary>
|
||||
MSCAB_ATTRIB_ARCH = 0x20,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the file is an executable program.
|
||||
/// </summary>
|
||||
MSCAB_ATTRIB_EXEC = 0x40,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the filename is in UTF8 format rather than ISO-8859-1.
|
||||
/// </summary>
|
||||
MSCAB_ATTRIB_UTF_NAME = 0x80,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FileFlags : ushort
|
||||
{
|
||||
CONTINUED_FROM_PREV = 0xFFFD,
|
||||
CONTINUED_TO_NEXT = 0xFFFE,
|
||||
CONTINUED_PREV_AND_NEXT = 0xFFFF,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HeaderFlags : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the cabinet is part of a cabinet set, and has a predecessor cabinet.
|
||||
/// </summary>
|
||||
MSCAB_HDR_PREVCAB = 0x0001,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the cabinet is part of a cabinet set, and has a successor cabinet.
|
||||
/// </summary>
|
||||
MSCAB_HDR_NEXTCAB = 0x0002,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the cabinet has reserved header space.
|
||||
/// </summary>
|
||||
MSCAB_HDR_RESV = 0x0004,
|
||||
}
|
||||
|
||||
public enum Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Search buffer size.
|
||||
/// </summary>
|
||||
MSCABD_PARAM_SEARCHBUF = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Repair MS-ZIP streams?
|
||||
/// </summary>
|
||||
MSCABD_PARAM_FIXMSZIP = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Size of decompression buffer
|
||||
/// </summary>
|
||||
MSCABD_PARAM_DECOMPBUF = 2,
|
||||
|
||||
/// <summary>
|
||||
/// salvage data from bad cabinets?
|
||||
/// If enabled, open() will skip file with bad folder indices or filenames
|
||||
/// rather than reject the whole cabinet, and extract() will limit rather than
|
||||
/// reject files with invalid offsets and lengths, and bad data block checksums
|
||||
/// will be ignored. Available only in CAB decoder version 2 and above.
|
||||
/// </summary>
|
||||
MSCABD_PARAM_SALVAGE = 3,
|
||||
}
|
||||
|
||||
}
|
||||
61
BurnOutSharp/External/libmspack/CAB/Folder.cs
vendored
Normal file
61
BurnOutSharp/External/libmspack/CAB/Folder.cs
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a single folder in a cabinet or cabinet set.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
///
|
||||
/// A folder is a single compressed stream of data. When uncompressed, it
|
||||
/// holds the data of one or more files. A folder may be split across more
|
||||
/// than one cabinet.
|
||||
/// </summary>
|
||||
public class Folder
|
||||
{
|
||||
/// <summary>
|
||||
/// A pointer to the next folder in this cabinet or cabinet set, or NULL
|
||||
/// if this is the final folder.
|
||||
/// </summary>
|
||||
public Folder Next { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression format used by this folder.
|
||||
///
|
||||
/// The macro MSCABD_COMP_METHOD() should be used on this field to get
|
||||
/// the algorithm used. The macro MSCABD_COMP_LEVEL() should be used to get
|
||||
/// the "compression level".
|
||||
/// </summary>
|
||||
/// <see cref="MSCABD_COMP_METHOD()"/>
|
||||
/// <see cref="MSCABD_COMP_LEVEL()"/>
|
||||
public CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The total number of data blocks used by this folder. This includes
|
||||
/// data blocks present in other files, if this folder spans more than
|
||||
/// one cabinet.
|
||||
/// </summary>
|
||||
public ushort NumBlocks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the compression method used by a folder.
|
||||
/// </summary>
|
||||
/// <param name="compType">a <see cref="CompressionType"/> value</param>
|
||||
/// <returns>a <see cref="CompressionType"/> value</returns>
|
||||
public CompressionType MSCABD_COMP_LEVEL(CompressionType compType) => (CompressionType)((((ushort)compType) >> 8) & 0x1F);
|
||||
}
|
||||
}
|
||||
29
BurnOutSharp/External/libmspack/CAB/FolderData.cs
vendored
Normal file
29
BurnOutSharp/External/libmspack/CAB/FolderData.cs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// There is one of these for every cabinet a folder spans
|
||||
/// </summary>
|
||||
public class FolderData
|
||||
{
|
||||
public FolderData Next { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cabinet file of this folder span
|
||||
/// </summary>
|
||||
public Cabinet Cab { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cabinet offset of first datablock
|
||||
/// </summary>
|
||||
public long Offset { get; set; }
|
||||
};
|
||||
}
|
||||
36
BurnOutSharp/External/libmspack/CAB/FolderImpl.cs
vendored
Normal file
36
BurnOutSharp/External/libmspack/CAB/FolderImpl.cs
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class FolderImpl : Folder
|
||||
{
|
||||
/// <summary>
|
||||
/// Where are the data blocks?
|
||||
/// </summary>
|
||||
public FolderData Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// First file needing backwards merge
|
||||
/// </summary>
|
||||
public InternalFile MergePrev { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// First file needing forwards merge
|
||||
/// </summary>
|
||||
public InternalFile MergeNext { get; set; }
|
||||
}
|
||||
}
|
||||
1647
BurnOutSharp/External/libmspack/CAB/Implementation.cs
vendored
Normal file
1647
BurnOutSharp/External/libmspack/CAB/Implementation.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
90
BurnOutSharp/External/libmspack/CAB/InternalFile.cs
vendored
Normal file
90
BurnOutSharp/External/libmspack/CAB/InternalFile.cs
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a single file in a cabinet or cabinet set.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class InternalFile
|
||||
{
|
||||
/// <summary>
|
||||
/// The next file in the cabinet or cabinet set, or NULL if this is the final file.
|
||||
/// </summary>
|
||||
public InternalFile Next { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the file.
|
||||
///
|
||||
/// A null terminated string of up to 255 bytes in length, it may be in
|
||||
/// either ISO-8859-1 or UTF8 format, depending on the file attributes.
|
||||
/// </summary>
|
||||
/// <see cref="Attributes"/>
|
||||
public string Filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The uncompressed length of the file, in bytes.
|
||||
/// </summary>
|
||||
public uint Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File attributes.
|
||||
/// </summary>
|
||||
public FileAttributes Attributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified time, hour field.
|
||||
/// </summary>
|
||||
public byte LastModifiedTimeHour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified time, minute field.
|
||||
/// </summary>
|
||||
public byte LastModifiedTimeMinute { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified time, second field.
|
||||
/// </summary>
|
||||
public byte LastModifiedTimeSecond { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified date, day field.
|
||||
/// </summary>
|
||||
public byte LastModifiedDateDay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified date, month field.
|
||||
/// </summary>
|
||||
public byte LastModifiedDateMonth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified date, year field.
|
||||
/// </summary>
|
||||
public int LastModifiedDateYear { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the folder that contains this file.
|
||||
/// </summary>
|
||||
public Folder Folder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The uncompressed offset of this file in its folder.
|
||||
/// </summary>
|
||||
public uint Offset { get; set; }
|
||||
}
|
||||
}
|
||||
27
BurnOutSharp/External/libmspack/CAB/NoneState.cs
vendored
Normal file
27
BurnOutSharp/External/libmspack/CAB/NoneState.cs
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
/// <summary>
|
||||
/// The "not compressed" method decompressor
|
||||
/// </summary>
|
||||
public class NoneState
|
||||
{
|
||||
public SystemImpl Sys { get; set; }
|
||||
|
||||
public object Input { get; set; }
|
||||
|
||||
public object Output { get; set; }
|
||||
|
||||
public byte[] Buffer { get; set; }
|
||||
|
||||
public int BufferSize { get; set; }
|
||||
}
|
||||
}
|
||||
53
BurnOutSharp/External/libmspack/CHM/CompressFile.cs
vendored
Normal file
53
BurnOutSharp/External/libmspack/CHM/CompressFile.cs
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a file to be placed in a CHM helpfile.
|
||||
///
|
||||
/// A contiguous array of these structures should be passed to
|
||||
/// Compressor.Generate(). The array list is terminated with an
|
||||
/// entry whose InternalFile.Section field is set to #MSCHMC_ENDLIST, the
|
||||
/// other fields in this entry are ignored.
|
||||
/// </summary>
|
||||
public class CompressFile
|
||||
{
|
||||
/// <summary>
|
||||
/// One of #MSCHMC_ENDLIST, #MSCHMC_UNCOMP or #MSCHMC_MSCOMP.
|
||||
/// </summary>
|
||||
public SectionType Section { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the source file that will be added to the CHM. This
|
||||
/// is passed directly to mspack_system::open()
|
||||
/// </summary>
|
||||
public string Filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full path and filename of the file within the CHM helpfile, a
|
||||
/// UTF-1 encoded null-terminated string.
|
||||
/// </summary>
|
||||
public string CHMFilename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the file, in bytes. This will be adhered to strictly
|
||||
/// and a read error will be issued if this many bytes cannot be read
|
||||
/// from the real file at CHM generation time.
|
||||
/// </summary>
|
||||
public long Length { get; set; }
|
||||
}
|
||||
}
|
||||
157
BurnOutSharp/External/libmspack/CHM/Compressor.cs
vendored
Normal file
157
BurnOutSharp/External/libmspack/CHM/Compressor.cs
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A compressor for .CHM (Microsoft HTMLHelp) files.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateCHMCompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyCHMCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a CHM help file.
|
||||
///
|
||||
/// The help file will contain up to two sections, an Uncompressed
|
||||
/// section and potentially an MSCompressed (LZX compressed)
|
||||
/// section.
|
||||
///
|
||||
/// While the contents listing of a CHM file is always in lexical order,
|
||||
/// the file list passed in will be taken as the correct order for files
|
||||
/// within the sections. It is in your interest to place similar files
|
||||
/// together for better compression.
|
||||
///
|
||||
/// There are two modes of generation, to use a temporary file or not to
|
||||
/// use one. See use_temporary_file() for the behaviour of generate() in
|
||||
/// these two different modes.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="fileList">
|
||||
/// an array of mschmc_file structures, terminated
|
||||
/// with an entry whose mschmc_file::section field is
|
||||
/// #MSCHMC_ENDLIST. The order of the list is
|
||||
/// preserved within each section. The length of any
|
||||
/// mschmc_file::chm_filename string cannot exceed
|
||||
/// roughly 4096 bytes. Each source file must be able
|
||||
/// to supply as many bytes as given in the
|
||||
/// mschmc_file::length field.
|
||||
/// </param>
|
||||
/// <param name="outputFile">
|
||||
/// the file to write the generated CHM helpfile to.
|
||||
/// This is passed directly to mspack_system::open()
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="UseTemporaryFile"/>
|
||||
/// <see cref="SetParam"/>
|
||||
public Func<Compressor, CompressFile[], string, Error> Generate;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether a temporary file is used during CHM generation.
|
||||
///
|
||||
/// The CHM file format includes data about the compressed section (such
|
||||
/// as its overall size) that is stored in the output CHM file prior to
|
||||
/// the compressed section itself. This unavoidably requires that the
|
||||
/// compressed section has to be generated, before these details can be
|
||||
/// set. There are several ways this can be handled. Firstly, the
|
||||
/// compressed section could be generated entirely in memory before
|
||||
/// writing any of the output CHM file.This approach is not used in
|
||||
/// libmspack, as the compressed section can exceed the addressable
|
||||
/// memory space on most architectures.
|
||||
///
|
||||
/// libmspack has two options, either to write these unknowable sections
|
||||
/// with blank data, generate the compressed section, then re-open the
|
||||
/// output file for update once the compressed section has been
|
||||
/// completed, or to write the compressed section to a temporary file,
|
||||
/// then write the entire output file at once, performing a simple
|
||||
/// file-to-file copy for the compressed section.
|
||||
///
|
||||
/// The simple solution of buffering the entire compressed section in
|
||||
/// memory can still be used, if desired.As the temporary file's
|
||||
/// filename is passed directly to mspack_system::open(), it is possible
|
||||
/// for a custom mspack_system implementation to hold this file in memory,
|
||||
/// without writing to a disk.
|
||||
///
|
||||
/// If a temporary file is set, generate() performs the following
|
||||
/// sequence of events: the temporary file is opened for writing, the
|
||||
/// compression algorithm writes to the temporary file, the temporary
|
||||
/// file is closed.Then the output file is opened for writing and the
|
||||
/// temporary file is re-opened for reading.The output file is written
|
||||
/// and the temporary file is read from. Both files are then closed.The
|
||||
/// temporary file itself is not deleted. If that is desired, the
|
||||
/// temporary file should be deleted after the completion of generate(),
|
||||
/// if it exists.
|
||||
///
|
||||
/// If a temporary file is set not to be used, generate() performs the
|
||||
/// following sequence of events: the output file is opened for writing,
|
||||
/// then it is written and closed.The output file is then re-opened for
|
||||
/// update, the appropriate sections are seek() ed to and re-written, then
|
||||
/// the output file is closed.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="useTempFile">
|
||||
/// non-zero if the temporary file should be used,
|
||||
/// zero if the temporary file should not be used.
|
||||
/// </param>
|
||||
/// <param name="tempFile">
|
||||
/// a file to temporarily write compressed data to,
|
||||
/// before opening it for reading and copying the
|
||||
/// contents to the output file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="Generate"/>
|
||||
public Func<Compressor, bool, string, Error> UseTemporaryFile;
|
||||
|
||||
/// <summary>
|
||||
/// Sets a CHM compression engine parameter.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_compressor
|
||||
/// instance being called
|
||||
/// </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>
|
||||
/// <see cref="Generate"/>
|
||||
public Func<Compressor, Parameters, int, Error> SetParam;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="SetParam"/>
|
||||
/// <see cref="Generate"/>
|
||||
public Func<Compressor, Error> LastError;
|
||||
}
|
||||
}
|
||||
22
BurnOutSharp/External/libmspack/CHM/CompressorImpl.cs
vendored
Normal file
22
BurnOutSharp/External/libmspack/CHM/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/* 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 CompressorImpl : Compressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public string TempFile { get; set; }
|
||||
|
||||
public bool UseTempFile { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
}
|
||||
}
|
||||
52
BurnOutSharp/External/libmspack/CHM/DecompressFile.cs
vendored
Normal file
52
BurnOutSharp/External/libmspack/CHM/DecompressFile.cs
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a file stored in a CHM helpfile.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class DecompressFile
|
||||
{
|
||||
/// <summary>
|
||||
/// A pointer to the next file in the list, or NULL if this is the final file.
|
||||
/// </summary>
|
||||
public DecompressFile Next { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the section that this file is located in. Indirectly,
|
||||
/// it also points to the CHM helpfile the file is located in.
|
||||
/// </summary>
|
||||
public Section Section { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The offset within the section data that this file is located at.
|
||||
/// </summary>
|
||||
public long Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of this file, in bytes
|
||||
/// </summary>
|
||||
public long Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of this file -- a null terminated string in UTF-8.
|
||||
/// </summary>
|
||||
public string Filename { get; set; }
|
||||
}
|
||||
}
|
||||
51
BurnOutSharp/External/libmspack/CHM/DecompressState.cs
vendored
Normal file
51
BurnOutSharp/External/libmspack/CHM/DecompressState.cs
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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 LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
public class DecompressState
|
||||
{
|
||||
/// <summary>
|
||||
/// CHM file being decompressed
|
||||
/// </summary>
|
||||
public Header Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed offset within folder
|
||||
/// </summary>
|
||||
public long Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset in input file
|
||||
/// </summary>
|
||||
public long InOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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 object InputFileHandle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public object OutputFileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
185
BurnOutSharp/External/libmspack/CHM/Decompressor.cs
vendored
Normal file
185
BurnOutSharp/External/libmspack/CHM/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A decompressor for .CHM (Microsoft HTMLHelp) files
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateCHMDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyCHMDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a CHM helpfile and reads its contents.
|
||||
///
|
||||
/// If the file opened is a valid CHM helpfile, all headers will be read
|
||||
/// and a mschmd_header structure will be returned, with a full list of
|
||||
/// files.
|
||||
///
|
||||
/// In the case of an error occuring, NULL is returned and the error code
|
||||
/// is available from last_error().
|
||||
///
|
||||
/// The filename pointer should be considered "in use" until close() is
|
||||
/// called on the CHM helpfile.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="filename">
|
||||
/// the filename of the CHM helpfile. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>a pointer to a mschmd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Close"/>
|
||||
public Func<Decompressor, string, Header> Open;
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened CHM helpfile.
|
||||
///
|
||||
/// This closes a CHM helpfile, frees the mschmd_header and all
|
||||
/// mschmd_file structures associated with it (if any). This works on
|
||||
/// both helpfiles opened with open() and helpfiles opened with
|
||||
/// fast_open().
|
||||
///
|
||||
/// The CHM header pointer is now invalid and cannot be used again. All
|
||||
/// mschmd_file pointers referencing that CHM are also now invalid, and
|
||||
/// cannot be used again.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="chm">the CHM helpfile to close</param>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="FastOpen"/>
|
||||
public Action<Decompressor, Header> Close;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts a file from a CHM helpfile.
|
||||
///
|
||||
/// This extracts a file from a CHM helpfile and writes it to the given
|
||||
/// filename.The filename of the file, mscabd_file::filename, is not
|
||||
/// used by extract(), but can be used by the caller as a guide for
|
||||
/// constructing an appropriate filename.
|
||||
///
|
||||
/// This method works both with files found in the mschmd_header::files
|
||||
/// and mschmd_header::sysfiles list and mschmd_file structures generated
|
||||
/// on the fly by fast_find().
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="file">the file to be decompressed</param>
|
||||
/// <param name="filename">the filename of the file being written to</param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public Func<Decompressor, DecompressFile, string, Error> Extract;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
///
|
||||
/// This is useful for open() and fast_open(), which do not return an
|
||||
/// error code directly.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Extract"/>
|
||||
public Func<Decompressor, Error> LastError;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a CHM helpfile quickly.
|
||||
///
|
||||
/// If the file opened is a valid CHM helpfile, only essential headers
|
||||
/// will be read.A mschmd_header structure will be still be returned, as
|
||||
/// with open(), but the mschmd_header::files field will be NULL.No
|
||||
/// files details will be automatically read.The fast_find() method
|
||||
/// must be used to obtain file details.
|
||||
///
|
||||
/// In the case of an error occuring, NULL is returned and the error code
|
||||
/// is available from last_error().
|
||||
///
|
||||
/// The filename pointer should be considered "in use" until close() is
|
||||
/// called on the CHM helpfile.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="filename">
|
||||
/// the filename of the CHM helpfile. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <returns>a pointer to a mschmd_header structure, or NULL on failure</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Close"/>
|
||||
/// <see cref="FastFind"/>
|
||||
/// <see cref="Extract"/>
|
||||
public Func<Decompressor, string, Header> FastOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Finds file details quickly.
|
||||
///
|
||||
/// Instead of reading all CHM helpfile headers and building a list of
|
||||
/// files, fast_open() and fast_find() are intended for finding file
|
||||
/// details only when they are needed.The CHM file format includes an
|
||||
/// on-disk file index to allow this.
|
||||
///
|
||||
/// Given a case-sensitive filename, fast_find() will search the on-disk
|
||||
/// index for that file.
|
||||
///
|
||||
/// If the file was found, the caller-provided mschmd_file structure will
|
||||
/// be filled out like so:
|
||||
/// - section: the correct value for the found file
|
||||
/// - offset: the correct value for the found file
|
||||
/// - length: the correct value for the found file
|
||||
/// - all other structure elements: NULL or 0
|
||||
///
|
||||
/// If the file was not found, MSPACK_ERR_OK will still be returned as the
|
||||
/// result, but the caller-provided structure will be filled out like so:
|
||||
/// - section: NULL
|
||||
/// - offset: 0
|
||||
/// - length: 0
|
||||
/// - all other structure elements: NULL or 0
|
||||
///
|
||||
/// This method is intended to be used in conjunction with CHM helpfiles
|
||||
/// opened with fast_open(), but it also works with helpfiles opened
|
||||
/// using the regular open().
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mschm_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="chm">the CHM helpfile to search for the file</param>
|
||||
/// <param name="filename">the filename of the file to search for</param>
|
||||
/// <param name="f_ptr">a pointer to a caller-provded mschmd_file structure</param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Close"/>
|
||||
/// <see cref="FastFind"/>
|
||||
/// <see cref="Extract"/>
|
||||
public Func<Decompressor, Header, string, DecompressFile, Error> FastFind;
|
||||
}
|
||||
}
|
||||
20
BurnOutSharp/External/libmspack/CHM/DecompressorImpl.cs
vendored
Normal file
20
BurnOutSharp/External/libmspack/CHM/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/* 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 DecompressorImpl : Decompressor
|
||||
{
|
||||
public SystemImpl System { get; set; }
|
||||
|
||||
public DecompressState State { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
}
|
||||
}
|
||||
83
BurnOutSharp/External/libmspack/CHM/Enums.cs
vendored
Normal file
83
BurnOutSharp/External/libmspack/CHM/Enums.cs
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
public enum Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the "timestamp" of the CHM file
|
||||
/// generated. This is not a timestamp, see mschmd_header::timestamp
|
||||
/// for a description. If this timestamp is 0, generate() will use its
|
||||
/// own algorithm for making a unique ID, based on the lengths and
|
||||
/// names of files in the CHM itself. Defaults to 0, any value between
|
||||
/// 0 and (2^32)-1 is valid.
|
||||
/// </summary>
|
||||
MSCHMC_PARAM_TIMESTAMP = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Sets the "language" of the CHM file
|
||||
/// generated. This is not the language used in the CHM file, but the
|
||||
/// language setting of the user who ran the HTMLHelp compiler. It
|
||||
/// defaults to 0x0409. The valid range is between 0x0000 and 0x7F7F.
|
||||
/// </summary>
|
||||
MSCHMC_PARAM_LANGUAGE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Sets the size of the LZX history window,
|
||||
/// which is also the interval at which the compressed data stream can be
|
||||
/// randomly accessed. The value is not a size in bytes, but a power of
|
||||
/// two. The default value is 16 (which makes the window 2^16 bytes, or
|
||||
/// 64 kilobytes), the valid range is from 15 (32 kilobytes) to 21 (2
|
||||
/// megabytes).
|
||||
/// </summary>
|
||||
MSCHMC_PARAM_LZXWINDOW = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Sets the "density" of quick reference
|
||||
/// entries stored at the end of directory listing chunk. Each chunk is
|
||||
/// 4096 bytes in size, and contains as many file entries as there is
|
||||
/// room for. At the other end of the chunk, a list of "quick reference"
|
||||
/// pointers is included. The offset of every 'N'th file entry is given a
|
||||
/// quick reference, where N = (2 ^ density) + 1.The default density is
|
||||
/// 2. The smallest density is 0 (N = 2), the maximum is 10 (N = 1025). As
|
||||
/// each file entry requires at least 5 bytes, the maximum number of
|
||||
/// entries in a single chunk is roughly 800, so the maximum value 10
|
||||
/// can be used to indicate there are no quickrefs at all.
|
||||
/// </summary>
|
||||
MSCHMC_PARAM_DENSITY = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether or not to include quick lookup
|
||||
/// index chunk(s), in addition to normal directory listing chunks. A
|
||||
/// value of zero means no index chunks will be created, a non-zero value
|
||||
/// means index chunks will be created. The default is zero, "don't
|
||||
/// create an index".
|
||||
/// </summary>
|
||||
MSCHMC_PARAM_INDEX = 4,
|
||||
}
|
||||
|
||||
public enum SectionType
|
||||
{
|
||||
/// <summary>
|
||||
/// end of CHM file list
|
||||
/// </summary>
|
||||
MSCHMC_ENDLIST = 0,
|
||||
|
||||
/// <summary>
|
||||
/// this file is in the Uncompressed section
|
||||
/// </summary>
|
||||
MSCHMC_UNCOMP = 1,
|
||||
|
||||
/// <summary>
|
||||
/// this file is in the MSCompressed section
|
||||
/// </summary>
|
||||
MSCHMC_MSCOMP = 2,
|
||||
}
|
||||
}
|
||||
135
BurnOutSharp/External/libmspack/CHM/Header.cs
vendored
Normal file
135
BurnOutSharp/External/libmspack/CHM/Header.cs
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a CHM helpfile.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class Header
|
||||
{
|
||||
/// <summary>
|
||||
/// The version of the CHM file format used in this file.
|
||||
/// </summary>
|
||||
public uint Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The "timestamp" of the CHM helpfile.
|
||||
///
|
||||
/// It is the lower 32 bits of a 64-bit value representing the number of
|
||||
/// centiseconds since 1601-01-01 00:00:00 UTC, plus 42. It is not useful
|
||||
/// as a timestamp, but it is useful as a semi-unique ID.
|
||||
/// </summary>
|
||||
public uint Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default Language and Country ID (LCID) of the user who ran the
|
||||
/// HTMLHelp Compiler. This is not the language of the CHM file itself.
|
||||
/// </summary>
|
||||
public uint Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The filename of the CHM helpfile. This is given by the library user
|
||||
/// and may be in any format.
|
||||
/// </summary>
|
||||
public string Filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the CHM helpfile, in bytes.
|
||||
/// </summary>
|
||||
public long Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of all non-system files in the CHM helpfile.
|
||||
/// </summary>
|
||||
public DecompressFile Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of all system files in the CHM helpfile.
|
||||
///
|
||||
/// System files are files which begin with "::". They are meta-files
|
||||
/// generated by the CHM creation process.
|
||||
/// </summary>
|
||||
public DecompressFile SysFiles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The section 0 (uncompressed) data in this CHM helpfile.
|
||||
/// </summary>
|
||||
public UncompressedSection Sec0 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The section 1 (MSCompressed) data in this CHM helpfile.
|
||||
/// </summary>
|
||||
public MSCompressedSection Sec1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file offset of the first PMGL/PMGI directory chunk.
|
||||
/// </summary>
|
||||
public long DirOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of PMGL/PMGI directory chunks in this CHM helpfile.
|
||||
/// </summary>
|
||||
public uint NumChunks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The size of each PMGL/PMGI chunk, in bytes.
|
||||
/// </summary>
|
||||
public uint ChunkSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The "density" of the quick-reference section in PMGL/PMGI chunks.
|
||||
/// </summary>
|
||||
public uint Density { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The depth of the index tree.
|
||||
///
|
||||
/// - if 1, there are no PMGI chunks, only PMGL chunks.
|
||||
/// - if 2, there is 1 PMGI chunk. All chunk indices point to PMGL chunks.
|
||||
/// - if 3, the root PMGI chunk points to secondary PMGI chunks, which in turn point to PMGL chunks.
|
||||
/// - and so on...
|
||||
/// </summary>
|
||||
public uint Depth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of the root PMGI chunk.
|
||||
///
|
||||
/// If there is no index in the CHM helpfile, this will be 0xFFFFFFFF.
|
||||
/// </summary>
|
||||
public uint IndexRoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of the first PMGL chunk. Usually zero.
|
||||
/// Available only in CHM decoder version 2 and above.
|
||||
/// </summary>
|
||||
public uint FirstPMGL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of the last PMGL chunk. Usually num_chunks-1.
|
||||
/// Available only in CHM decoder version 2 and above.
|
||||
/// </summary>
|
||||
public uint LastPMGL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A cache of loaded chunks, filled in by mschm_decoder::fast_find().
|
||||
/// Available only in CHM decoder version 2 and above.
|
||||
/// </summary>
|
||||
public byte[][] ChunkCache { get; set; }
|
||||
}
|
||||
}
|
||||
1540
BurnOutSharp/External/libmspack/CHM/Implementation.cs
vendored
Normal file
1540
BurnOutSharp/External/libmspack/CHM/Implementation.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
47
BurnOutSharp/External/libmspack/CHM/MSCompressedSection.cs
vendored
Normal file
47
BurnOutSharp/External/libmspack/CHM/MSCompressedSection.cs
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents the LZX compressed section of a CHM helpfile.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class MSCompressedSection : Section
|
||||
{
|
||||
/// <summary>
|
||||
/// A pointer to the meta-file which represents all LZX compressed data.
|
||||
/// </summary>
|
||||
public DecompressFile Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the file which contains the LZX control data.
|
||||
/// </summary>
|
||||
public DecompressFile Control { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the file which contains the LZX reset table.
|
||||
/// </summary>
|
||||
public DecompressFile ResetTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the file which contains the LZX span information.
|
||||
/// Available only in CHM decoder version 2 and above.
|
||||
/// </summary>
|
||||
public DecompressFile SpanInfo { get; set; }
|
||||
}
|
||||
}
|
||||
41
BurnOutSharp/External/libmspack/CHM/Section.cs
vendored
Normal file
41
BurnOutSharp/External/libmspack/CHM/Section.cs
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents a section of a CHM helpfile.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
///
|
||||
/// Not used directly, but used as a generic base type for
|
||||
/// mschmd_sec_uncompressed and mschmd_sec_mscompressed.
|
||||
/// </summary>
|
||||
public class Section
|
||||
{
|
||||
/// <summary>
|
||||
/// A pointer to the CHM helpfile that contains this section.
|
||||
/// </summary>
|
||||
public Header Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The section ID. Either 0 for the uncompressed section
|
||||
/// mschmd_sec_uncompressed, or 1 for the LZX compressed section
|
||||
/// mschmd_sec_mscompressed. No other section IDs are known.
|
||||
/// </summary>
|
||||
public uint ID { get; set; }
|
||||
}
|
||||
}
|
||||
31
BurnOutSharp/External/libmspack/CHM/UncompressedSection.cs
vendored
Normal file
31
BurnOutSharp/External/libmspack/CHM/UncompressedSection.cs
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CHM
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents the uncompressed section of a CHM helpfile.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class UncompressedSection : Section
|
||||
{
|
||||
/// <summary>
|
||||
/// The file offset of where this section begins in the CHM helpfile.
|
||||
/// </summary>
|
||||
public long Offset { get; set; }
|
||||
}
|
||||
}
|
||||
111
BurnOutSharp/External/libmspack/Checksum.cs
vendored
Normal file
111
BurnOutSharp/External/libmspack/Checksum.cs
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
|
||||
* code or tables extracted from it, as desired without restriction.
|
||||
*
|
||||
* First, the polynomial itself and its table of feedback terms. The
|
||||
* polynomial is
|
||||
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
|
||||
*
|
||||
* Note that we take it "backwards" and put the highest-order term in
|
||||
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
|
||||
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
|
||||
* the MSB being 1
|
||||
*
|
||||
* Note that the usual hardware shift register implementation, which
|
||||
* is what we're using (we're merely optimizing it by doing eight-bit
|
||||
* chunks at a time) shifts bits into the lowest-order term. In our
|
||||
* implementation, that means shifting towards the right. Why do we
|
||||
* do it this way? Because the calculated CRC must be transmitted in
|
||||
* order from highest-order term to lowest-order term. UARTs transmit
|
||||
* characters in order from LSB to MSB. By storing the CRC this way
|
||||
* we hand it to the UART in the order low-byte to high-byte; the UART
|
||||
* sends each low-bit to hight-bit; and the result is transmission bit
|
||||
* by bit from highest- to lowest-order term without requiring any bit
|
||||
* shuffling on our part. Reception works similarly
|
||||
*
|
||||
* The feedback terms table consists of 256, 32-bit entries. Notes
|
||||
*
|
||||
* The table can be generated at runtime if desired; code to do so
|
||||
* is shown later. It might not be obvious, but the feedback
|
||||
* terms simply represent the results of eight shift/xor opera
|
||||
* tions for all combinations of data and CRC register values
|
||||
*
|
||||
* The values must be right-shifted by eight bits by the "updcrc
|
||||
* logic; the shift must be unsigned (bring in zeroes). On some
|
||||
* hardware you could probably optimize the shift in assembler by
|
||||
* using byte-swap instructions
|
||||
* polynomial $edb88320
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
public class Checksum
|
||||
{
|
||||
public static readonly uint[] CRC32Table = new uint[256]
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Return a 32-bit CRC of the contents of the buffer.
|
||||
/// </summary>
|
||||
public static uint CRC32(byte[] ss, int pointer, int len, uint val)
|
||||
{
|
||||
while (--len >= 0)
|
||||
val = CRC32Table[(val ^ ss[pointer++]) & 0xff] ^ (val >> 8);
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
460
BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
vendored
Normal file
460
BurnOutSharp/External/libmspack/Compression/CompressionStream.cs
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2013 Stuart Caie.
|
||||
*
|
||||
* The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
|
||||
* by Microsoft Corporation.
|
||||
*
|
||||
* libmspack is free software { get; set; } 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;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public abstract class CompressionStream
|
||||
{
|
||||
private const int CHAR_BIT = 8;
|
||||
|
||||
private const int BITBUF_WIDTH = 4 * CHAR_BIT;
|
||||
|
||||
/// <summary>
|
||||
/// I/O routines
|
||||
/// </summary>
|
||||
public SystemImpl Sys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public object Input { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public object Output { get; set; }
|
||||
|
||||
public Error Error { get; set; }
|
||||
|
||||
#region I/O buffering
|
||||
|
||||
public byte[] InputBuffer { get; set; }
|
||||
|
||||
public uint InputBufferSize { get; set; }
|
||||
|
||||
public int InputPointer { get; set; }
|
||||
|
||||
public int InputLength { get; set; }
|
||||
|
||||
public int OutputPointer { get; set; }
|
||||
|
||||
public int OutputLength { get; set; }
|
||||
|
||||
public uint BitBuffer { get; set; }
|
||||
|
||||
public uint BitsLeft { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Have we reached the end of input?
|
||||
/// </summary>
|
||||
public int InputEnd { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadBits Methods
|
||||
|
||||
/* This header defines macros that read data streams by
|
||||
* the individual bits
|
||||
*
|
||||
* INIT_BITS initialises bitstream state in state structure
|
||||
* STORE_BITS stores bitstream state in state structure
|
||||
* RESTORE_BITS restores bitstream state from state structure
|
||||
* ENSURE_BITS(n) ensure there are at least N bits in the bit buffer
|
||||
* READ_BITS(var,n) takes N bits from the buffer and puts them in var
|
||||
* PEEK_BITS(n) extracts without removing N bits from the bit buffer
|
||||
* REMOVE_BITS(n) removes N bits from the bit buffer
|
||||
*
|
||||
* READ_BITS simply calls ENSURE_BITS, PEEK_BITS and REMOVE_BITS,
|
||||
* which means it's limited to reading the number of bits you can
|
||||
* ensure at any one time. It also fails if asked to read zero bits.
|
||||
* If you need to read zero bits, or more bits than can be ensured in
|
||||
* one go, use READ_MANY_BITS instead.
|
||||
*
|
||||
* These macros have variable names baked into them, so to use them
|
||||
* you have to define some macros:
|
||||
* - BITS_TYPE: the type name of your state structure
|
||||
* - BITS_VAR: the variable that points to your state structure
|
||||
* - define BITS_ORDER_MSB if bits are read from the MSB, or
|
||||
* define BITS_ORDER_LSB if bits are read from the LSB
|
||||
* - READ_BYTES: some code that reads more data into the bit buffer,
|
||||
* it should use READ_IF_NEEDED (calls read_input if the byte buffer
|
||||
* is empty), then INJECT_BITS(data,n) to put data from the byte
|
||||
* buffer into the bit buffer.
|
||||
*
|
||||
* You also need to define some variables and structure members:
|
||||
* - byte[] i_ptr; // current position in the byte buffer
|
||||
* - byte[] i_end; // end of the byte buffer
|
||||
* - uint bit_buffer; // the bit buffer itself
|
||||
* - uint bits_left; // number of bits remaining
|
||||
*
|
||||
* If you use read_input() and READ_IF_NEEDED, they also expect these
|
||||
* structure members:
|
||||
* - struct mspack_system *sys; // to access sys->read()
|
||||
* - uint error; // to record/return read errors
|
||||
* - byte input_end; // to mark reaching the EOF
|
||||
* - byte[] inbuf; // the input byte buffer
|
||||
* - uint inbuf_size; // the size of the input byte buffer
|
||||
*
|
||||
* Your READ_BYTES implementation should read data from *i_ptr and
|
||||
* put them in the bit buffer. READ_IF_NEEDED will call read_input()
|
||||
* if i_ptr reaches i_end, and will fill up inbuf and set i_ptr to
|
||||
* the start of inbuf and i_end to the end of inbuf.
|
||||
*
|
||||
* If you're reading in MSB order, the routines work by using the area
|
||||
* beyond the MSB and the LSB of the bit buffer as a free source of
|
||||
* zeroes when shifting. This avoids having to mask any bits. So we
|
||||
* have to know the bit width of the bit buffer variable. We use
|
||||
* <limits.h> and CHAR_BIT to find the size of the bit buffer in bits.
|
||||
*
|
||||
* If you are reading in LSB order, bits need to be masked. Normally
|
||||
* this is done by computing the mask: N bits are masked by the value
|
||||
* (1<<N)-1). However, you can define BITS_LSB_TABLE to use a lookup
|
||||
* table instead of computing this. This adds two new macros,
|
||||
* PEEK_BITS_T and READ_BITS_T which work the same way as PEEK_BITS
|
||||
* and READ_BITS, except they use this lookup table. This is useful if
|
||||
* you need to look up a number of bits that are only known at
|
||||
* runtime, so the bit mask can't be turned into a constant by the
|
||||
* compiler.
|
||||
* The bit buffer datatype should be at least 32 bits wide: it must be
|
||||
* possible to ENSURE_BITS(17), so it must be possible to add 16 new bits
|
||||
* to the bit buffer when the bit buffer already has 1 to 15 bits left.
|
||||
*/
|
||||
|
||||
public void INIT_BITS()
|
||||
{
|
||||
InputPointer = 0;
|
||||
InputLength = 0;
|
||||
BitBuffer = 0;
|
||||
BitsLeft = 0;
|
||||
InputEnd = 0;
|
||||
}
|
||||
|
||||
public void STORE_BITS(int inputPointer, int inputLength, uint bitBuffer, uint bitsLeft)
|
||||
{
|
||||
InputPointer = inputPointer;
|
||||
InputLength = inputLength;
|
||||
BitBuffer = bitBuffer;
|
||||
BitsLeft = bitsLeft;
|
||||
}
|
||||
|
||||
public void RESTORE_BITS(ref int inputPointer, ref int inputLength, ref uint bitBuffer, ref uint bitsLeft)
|
||||
{
|
||||
inputPointer = InputPointer;
|
||||
inputLength = InputLength;
|
||||
bitBuffer = BitBuffer;
|
||||
bitsLeft = BitsLeft;
|
||||
}
|
||||
|
||||
public void ENSURE_BITS(int nbits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
while (bitsLeft < nbits)
|
||||
{
|
||||
READ_BYTES(ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void READ_BITS(ref int val, int nbits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
val = PEEK_BITS(nbits, bitBuffer);
|
||||
REMOVE_BITS(nbits, ref bitsLeft, ref bitBuffer);
|
||||
}
|
||||
|
||||
public Error READ_MANY_BITS(ref uint val, byte bits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
byte needed = bits, bitrun;
|
||||
val = 0;
|
||||
while (needed > 0)
|
||||
{
|
||||
if (bitsLeft <= (BITBUF_WIDTH - 16))
|
||||
{
|
||||
Error error = READ_BYTES(ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
bitrun = (byte)((bitsLeft < needed) ? bitsLeft : needed);
|
||||
val = (uint)((val << bitrun) | PEEK_BITS(bitrun, bitBuffer));
|
||||
REMOVE_BITS(bitrun, ref bitsLeft, ref bitBuffer);
|
||||
needed -= bitrun;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public int PEEK_BITS(int nbits, uint bitBuffer)
|
||||
{
|
||||
return (int)(bitBuffer & ((1 << (nbits)) - 1));
|
||||
}
|
||||
|
||||
public void REMOVE_BITS(int nbits, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
bitBuffer >>= nbits;
|
||||
bitsLeft -= (uint)nbits;
|
||||
}
|
||||
|
||||
public void INJECT_BITS(uint bitdata, int nbits, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
bitBuffer |= bitdata << (int)bitsLeft;
|
||||
bitsLeft += (uint)nbits;
|
||||
}
|
||||
|
||||
public abstract Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer);
|
||||
|
||||
// lsb_bit_mask[n] = (1 << n) - 1 */
|
||||
private static readonly ushort[] lsb_bit_mask = new ushort[17]
|
||||
{
|
||||
0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
|
||||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
||||
};
|
||||
|
||||
public int PEEK_BITS_T(int nbits)
|
||||
{
|
||||
return (int)(BitBuffer & lsb_bit_mask[nbits]);
|
||||
}
|
||||
|
||||
public void READ_BITS_T(ref int val, int nbits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
val = PEEK_BITS_T(nbits);
|
||||
REMOVE_BITS(nbits, ref bitsLeft, ref bitBuffer);
|
||||
}
|
||||
|
||||
public Error READ_IF_NEEDED(ref int iPtr, ref int iEnd)
|
||||
{
|
||||
if (iPtr >= iEnd)
|
||||
{
|
||||
if (ReadInput(this) != Error.MSPACK_ERR_OK)
|
||||
return Error;
|
||||
|
||||
iPtr = InputPointer;
|
||||
iEnd = InputLength;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private static Error ReadInput(CompressionStream p)
|
||||
{
|
||||
int read = p.Sys.Read(p.Input, p.InputBuffer, 0, (int)p.InputBufferSize);
|
||||
if (read < 0)
|
||||
return p.Error = Error.MSPACK_ERR_READ;
|
||||
|
||||
// We might overrun the input stream by asking for bits we don't use,
|
||||
// so fake 2 more bytes at the end of input
|
||||
if (read == 0)
|
||||
{
|
||||
if (p.InputEnd != 0)
|
||||
{
|
||||
Console.WriteLine("out of input bytes");
|
||||
return p.Error = Error.MSPACK_ERR_READ;
|
||||
}
|
||||
else
|
||||
{
|
||||
read = 2;
|
||||
p.InputBuffer[0] = p.InputBuffer[1] = 0;
|
||||
p.InputEnd = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update i_ptr and i_end
|
||||
p.InputPointer = 0;
|
||||
p.InputLength = read;
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadHuff Methods
|
||||
|
||||
private const int HUFF_MAXBITS = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the next huffman symbol from the input bitstream into var.
|
||||
/// Do not use this macro on a table unless build_decode_table() succeeded.
|
||||
/// </summary>
|
||||
public int READ_HUFFSYM(ushort[] decodingTable, ref uint var, int tablebits, byte[] lengthTable, int maxsymbols, ref int i, ref ushort sym, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
ENSURE_BITS(HUFF_MAXBITS, ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
sym = decodingTable[PEEK_BITS(tablebits, bitBuffer)];
|
||||
if (sym >= maxsymbols)
|
||||
{
|
||||
int ret = HUFF_TRAVERSE(decodingTable, tablebits, maxsymbols, ref i, ref sym, bitBuffer);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
var = sym;
|
||||
i = lengthTable[sym];
|
||||
REMOVE_BITS(i, ref bitsLeft, ref bitBuffer);
|
||||
return (int)Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public int HUFF_TRAVERSE(ushort[] decodingTable, int tablebits, int maxsymbols, ref int i, ref ushort sym, uint bitBuffer)
|
||||
{
|
||||
i = tablebits - 1;
|
||||
do
|
||||
{
|
||||
if (i++ > HUFF_MAXBITS)
|
||||
return HUFF_ERROR();
|
||||
|
||||
sym = decodingTable[(sym << 1) | ((bitBuffer >> i) & 1)];
|
||||
} while (sym >= maxsymbols);
|
||||
|
||||
return (int)Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public abstract int HUFF_ERROR();
|
||||
|
||||
/// <summary>
|
||||
/// This function was originally coded by David Tritscher.
|
||||
///
|
||||
/// It builds a fast huffman decoding table from
|
||||
/// a canonical huffman code lengths table.
|
||||
/// </summary>
|
||||
/// <param name="nsyms">total number of symbols in this huffman tree.</param>
|
||||
/// <param name="nbits">any symbols with a code length of nbits or less can be decoded in one lookup of the table.</param>
|
||||
/// <param name="length">A table to get code lengths from [0 to nsyms-1]</param>
|
||||
/// <param name="table">
|
||||
/// The table to fill up with decoded symbols and pointers.
|
||||
/// Should be ((1<<nbits) + (nsyms*2)) in length.
|
||||
/// </param>
|
||||
/// <returns>0 for OK or 1 for error</returns>
|
||||
public static int MakeDecodeTable(uint nsyms, uint nbits, byte[] length, ushort[] table)
|
||||
{
|
||||
ushort sym, next_symbol;
|
||||
uint leaf, fill;
|
||||
uint reverse;
|
||||
byte bit_num;
|
||||
uint pos = 0; // The current position in the decode table
|
||||
uint table_mask = (uint)(1 << (int)nbits);
|
||||
uint bit_mask = table_mask >> 1; // Don't do 0 length codes
|
||||
|
||||
// Fill entries for codes short enough for a direct mapping
|
||||
for (bit_num = 1; bit_num <= nbits; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
|
||||
// Reverse the significant bits
|
||||
fill = length[sym];
|
||||
reverse = pos >> (int)(nbits - fill);
|
||||
leaf = 0;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
if ((pos += bit_mask) > table_mask)
|
||||
return 1; // Table overrun
|
||||
|
||||
// Fill all possible lookups of this symbol with the symbol itself
|
||||
fill = bit_mask;
|
||||
next_symbol = (ushort)(1 << bit_num);
|
||||
|
||||
do
|
||||
{
|
||||
table[leaf] = sym;
|
||||
leaf += next_symbol;
|
||||
} while (--fill != 0);
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Exit with success if table is now complete
|
||||
if (pos == table_mask)
|
||||
return 0;
|
||||
|
||||
// Mark all remaining table entries as unused
|
||||
for (sym = (ushort)pos; sym < table_mask; sym++)
|
||||
{
|
||||
reverse = sym;
|
||||
leaf = 0;
|
||||
fill = nbits;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
table[leaf] = 0xFFFF;
|
||||
}
|
||||
|
||||
// next_symbol = base of allocation for long codes
|
||||
next_symbol = (ushort)(((table_mask >> 1) < nsyms) ? nsyms : (table_mask >> 1));
|
||||
|
||||
// Give ourselves room for codes to grow by up to 16 more bits.
|
||||
// codes now start at bit nbits+16 and end at (nbits+16-codelength)
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
for (bit_num = (byte)(nbits + 1); bit_num <= HUFF_MAXBITS; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
if (pos >= table_mask)
|
||||
return 1; // Table overflow
|
||||
|
||||
// Leaf = the first nbits of the code, reversed
|
||||
reverse = pos >> 16;
|
||||
leaf = 0;
|
||||
fill = nbits;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
for (fill = 0; fill < (bit_num - nbits); fill++)
|
||||
{
|
||||
// Ff this path hasn't been taken yet, 'allocate' two entries
|
||||
if (table[leaf] == 0xFFFF)
|
||||
{
|
||||
table[(next_symbol << 1)] = 0xFFFF;
|
||||
table[(next_symbol << 1) + 1] = 0xFFFF;
|
||||
table[leaf] = next_symbol++;
|
||||
}
|
||||
|
||||
// Follow the path and select either left or right for next bit
|
||||
leaf = (uint)(table[leaf] << 1);
|
||||
if (((pos >> (int)(15 - fill)) & 1) != 0)
|
||||
leaf++;
|
||||
}
|
||||
|
||||
table[leaf] = sym;
|
||||
pos += bit_mask;
|
||||
}
|
||||
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
|
||||
// Full table?
|
||||
return (pos == table_mask) ? 0 : 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
15
BurnOutSharp/External/libmspack/Compression/DES.cs
vendored
Normal file
15
BurnOutSharp/External/libmspack/Compression/DES.cs
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/* 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.Compression
|
||||
{
|
||||
public class des
|
||||
{
|
||||
}
|
||||
}
|
||||
114
BurnOutSharp/External/libmspack/Compression/Enums.cs
vendored
Normal file
114
BurnOutSharp/External/libmspack/Compression/Enums.cs
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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.Compression
|
||||
{
|
||||
public enum InflateErrorCode
|
||||
{
|
||||
INF_ERR_OK = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Unknown block type
|
||||
/// </summary>
|
||||
INF_ERR_BLOCKTYPE = -1,
|
||||
|
||||
/// <summary>
|
||||
/// Block size complement mismatch
|
||||
/// </summary>
|
||||
INF_ERR_COMPLEMENT = -2,
|
||||
|
||||
/// <summary>
|
||||
/// Error from flush_window callback
|
||||
/// </summary>
|
||||
INF_ERR_FLUSH = -3,
|
||||
|
||||
/// <summary>
|
||||
/// Too many bits in bit buffer
|
||||
/// </summary>
|
||||
INF_ERR_BITBUF = -4,
|
||||
|
||||
/// <summary>
|
||||
/// Too many symbols in blocktype 2 header
|
||||
/// </summary>
|
||||
INF_ERR_SYMLENS = -5,
|
||||
|
||||
/// <summary>
|
||||
/// Failed to build bitlens huffman table
|
||||
/// </summary>
|
||||
INF_ERR_BITLENTBL = -6,
|
||||
|
||||
/// <summary>
|
||||
/// Failed to build literals huffman table
|
||||
/// </summary>
|
||||
INF_ERR_LITERALTBL = -7,
|
||||
|
||||
/// <summary>
|
||||
/// Failed to build distance huffman table
|
||||
/// </summary>
|
||||
INF_ERR_DISTANCETBL = -8,
|
||||
|
||||
/// <summary>
|
||||
/// Bitlen RLE code goes over table size
|
||||
/// </summary>
|
||||
INF_ERR_BITOVERRUN = -9,
|
||||
|
||||
/// <summary>
|
||||
/// Invalid bit-length code
|
||||
/// </summary>
|
||||
INF_ERR_BADBITLEN = -10,
|
||||
|
||||
/// <summary>
|
||||
/// Out-of-range literal code
|
||||
/// </summary>
|
||||
INF_ERR_LITCODE = -11,
|
||||
|
||||
/// <summary>
|
||||
/// Out-of-range distance code
|
||||
/// </summary>
|
||||
INF_ERR_DISTCODE = -12,
|
||||
|
||||
/// <summary>
|
||||
/// Somehow, distance is beyond 32k
|
||||
/// </summary>
|
||||
INF_ERR_DISTANCE = -13,
|
||||
|
||||
/// <summary>
|
||||
/// Out of bits decoding huffman symbol
|
||||
/// </summary>
|
||||
INF_ERR_HUFFSYM = -14,
|
||||
}
|
||||
|
||||
public enum LZSSMode
|
||||
{
|
||||
LZSS_MODE_EXPAND = 0,
|
||||
|
||||
LZSS_MODE_MSHELP = 1,
|
||||
|
||||
LZSS_MODE_QBASIC = 2,
|
||||
}
|
||||
|
||||
public enum LZXBlockType : byte
|
||||
{
|
||||
LZX_BLOCKTYPE_INVALID0 = 0,
|
||||
|
||||
LZX_BLOCKTYPE_VERBATIM = 1,
|
||||
|
||||
LZX_BLOCKTYPE_ALIGNED = 2,
|
||||
|
||||
LZX_BLOCKTYPE_UNCOMPRESSED = 3,
|
||||
|
||||
LZX_BLOCKTYPE_INVALID4 = 4,
|
||||
|
||||
LZX_BLOCKTYPE_INVALID5 = 5,
|
||||
|
||||
LZX_BLOCKTYPE_INVALID6 = 6,
|
||||
|
||||
LZX_BLOCKTYPE_INVALID7 = 7,
|
||||
}
|
||||
}
|
||||
195
BurnOutSharp/External/libmspack/Compression/LZSS.cs
vendored
Normal file
195
BurnOutSharp/External/libmspack/Compression/LZSS.cs
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2010 Stuart Caie.
|
||||
*
|
||||
* LZSS is a derivative of LZ77 and was created by James Storer and
|
||||
* Thomas Szymanski in 1982. Haruhiko Okumura wrote a very popular C
|
||||
* implementation.
|
||||
*
|
||||
* 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.Compression
|
||||
{
|
||||
public class LZSS
|
||||
{
|
||||
#region LZSS compression / decompression definitions
|
||||
|
||||
public const int LZSS_WINDOW_SIZE = 4096;
|
||||
public const byte LZSS_WINDOW_FILL = 0x20;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an LZSS stream.
|
||||
///
|
||||
/// Input bytes will be read in as necessary using the system.read()
|
||||
/// function with the input file handle given.This will continue until
|
||||
/// system.read() returns 0 bytes, or an error.Errors will be passed
|
||||
/// out of the function as MSPACK_ERR_READ errors. Input streams should
|
||||
/// convey an "end of input stream" by refusing to supply all the bytes
|
||||
/// that LZSS asks for when they reach the end of the stream, rather
|
||||
/// than return an error code.
|
||||
///
|
||||
/// Output bytes will be passed to the system.write() function, using
|
||||
/// the output file handle given.More than one call may be made to
|
||||
/// system.write().
|
||||
///
|
||||
/// As EXPAND.EXE (SZDD/KWAJ), Microsoft Help and QBasic have slightly
|
||||
/// different encodings for the control byte and matches, a "mode"
|
||||
/// parameter is allowed, to choose the encoding.
|
||||
/// </summary>
|
||||
/// <param name="system">
|
||||
/// an mspack_system structure used to read from
|
||||
/// the input stream and write to the output
|
||||
/// stream, also to allocate and free memory.
|
||||
/// </param>
|
||||
/// <param name="input">an input stream with the LZSS data.</param>
|
||||
/// <param name="output">an output stream to write the decoded data to.</param>
|
||||
/// <param name="inputBufferSize">
|
||||
/// the number of bytes to use as an input
|
||||
/// bitstream buffer.
|
||||
/// </param>
|
||||
/// <param name="mode">one of LZSSMode values</param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public static Error Decompress(SystemImpl system, object input, object output, int inputBufferSize, LZSSMode mode)
|
||||
{
|
||||
uint i, c, mpos, len;
|
||||
int read;
|
||||
|
||||
// Check parameters
|
||||
if (system == null
|
||||
|| inputBufferSize < 1
|
||||
|| (mode != LZSSMode.LZSS_MODE_EXPAND && mode != LZSSMode.LZSS_MODE_MSHELP && mode != LZSSMode.LZSS_MODE_QBASIC))
|
||||
{
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
// Allocate memory
|
||||
byte[] window = new byte[LZSS_WINDOW_SIZE + inputBufferSize];
|
||||
|
||||
// Initialise decompression
|
||||
int inbuf = LZSS_WINDOW_SIZE;
|
||||
for (i = 0; i < LZSS_WINDOW_SIZE; i++)
|
||||
{
|
||||
window[i] = LZSS_WINDOW_FILL;
|
||||
}
|
||||
|
||||
uint pos = LZSS_WINDOW_SIZE - (uint)((mode == LZSSMode.LZSS_MODE_QBASIC) ? 18 : 16);
|
||||
uint invert = (uint)((mode == LZSSMode.LZSS_MODE_MSHELP) ? ~0 : 0);
|
||||
int iPtr = 0, iEnd = 0;
|
||||
|
||||
// Loop forever; exit condition is in ENSURE_BYTES macro
|
||||
for (; ; )
|
||||
{
|
||||
//ENSURE_BYTES
|
||||
if (iPtr >= iEnd)
|
||||
{
|
||||
read = system.Read(input, window, inbuf, inputBufferSize);
|
||||
if (read <= 0)
|
||||
{
|
||||
system.Free(window);
|
||||
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
iPtr = 0;
|
||||
iEnd = read;
|
||||
}
|
||||
|
||||
c = window[iPtr++] ^ invert;
|
||||
for (i = 0x01; (i & 0xFF) != 0; i <<= 1)
|
||||
{
|
||||
if (c != 0 & i != 0)
|
||||
{
|
||||
// Literal
|
||||
//ENSURE_BYTES
|
||||
if (iPtr >= iEnd)
|
||||
{
|
||||
read = system.Read(input, window, inbuf, inputBufferSize);
|
||||
if (read <= 0)
|
||||
{
|
||||
system.Free(window);
|
||||
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
iPtr = 0;
|
||||
iEnd = read;
|
||||
}
|
||||
|
||||
window[pos] = window[iPtr++];
|
||||
|
||||
//ENSURE_BYTES
|
||||
if (iPtr >= iEnd)
|
||||
{
|
||||
read = system.Read(input, window, inbuf, inputBufferSize);
|
||||
if (read <= 0)
|
||||
{
|
||||
system.Free(window);
|
||||
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
iPtr = 0;
|
||||
iEnd = read;
|
||||
}
|
||||
|
||||
pos++; pos &= LZSS_WINDOW_SIZE - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Match
|
||||
//ENSURE_BYTES
|
||||
if (iPtr >= iEnd)
|
||||
{
|
||||
read = system.Read(input, window, inbuf, inputBufferSize);
|
||||
if (read <= 0)
|
||||
{
|
||||
system.Free(window);
|
||||
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
iPtr = 0;
|
||||
iEnd = read;
|
||||
}
|
||||
|
||||
mpos = window[iPtr++];
|
||||
|
||||
//ENSURE_BYTES
|
||||
if (iPtr >= iEnd)
|
||||
{
|
||||
read = system.Read(input, window, inbuf, inputBufferSize);
|
||||
if (read <= 0)
|
||||
{
|
||||
system.Free(window);
|
||||
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
iPtr = 0;
|
||||
iEnd = read;
|
||||
}
|
||||
|
||||
mpos |= (uint)(window[iPtr] & 0xF0) << 4;
|
||||
len = (uint)(window[iPtr++] & 0x0F) + 3;
|
||||
while (len-- != 0)
|
||||
{
|
||||
window[pos] = window[mpos];
|
||||
|
||||
//WRITE_BYTE;
|
||||
if (system.Write(output, window, (int)pos, 1) != 1)
|
||||
{
|
||||
system.Free(window);
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
}
|
||||
|
||||
pos++;
|
||||
pos &= LZSS_WINDOW_SIZE - 1;
|
||||
mpos++;
|
||||
mpos &= LZSS_WINDOW_SIZE - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1147
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
Normal file
1147
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
159
BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
vendored
Normal file
159
BurnOutSharp/External/libmspack/Compression/LZXDStream.cs
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2013 Stuart Caie.
|
||||
*
|
||||
* The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
|
||||
* by Microsoft Corporation.
|
||||
*
|
||||
* libmspack is free software { get; set; } 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.Compression
|
||||
{
|
||||
public class LZXDStream : CompressionStream
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of bytes actually output
|
||||
/// </summary>
|
||||
public long Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overall decompressed length of stream
|
||||
/// </summary>
|
||||
public long Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decoding window
|
||||
/// </summary>
|
||||
public byte[] Window { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Window size
|
||||
/// </summary>
|
||||
public uint WindowSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// LZX DELTA reference data size
|
||||
/// </summary>
|
||||
public uint ReferenceDataSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of match_offset entries in table
|
||||
/// </summary>
|
||||
public uint NumOffsets { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decompression offset within window
|
||||
/// </summary>
|
||||
public uint WindowPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current frame offset within in window
|
||||
/// </summary>
|
||||
public uint FramePosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of 32kb frames processed
|
||||
/// </summary>
|
||||
public uint Frame { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Which frame do we reset the compressor?
|
||||
/// </summary>
|
||||
public uint ResetInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For the LRU offset system
|
||||
/// </summary>
|
||||
public uint R0 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For the LRU offset system
|
||||
/// </summary>
|
||||
public uint R1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For the LRU offset system
|
||||
/// </summary>
|
||||
public uint R2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed length of this LZX block
|
||||
/// </summary>
|
||||
public uint BlockLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed bytes still left to decode
|
||||
/// </summary>
|
||||
public uint BlockRemaining { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Magic header value used for transform
|
||||
/// </summary>
|
||||
public int IntelFileSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has intel E8 decoding started?
|
||||
/// </summary>
|
||||
public bool IntelStarted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of the current block
|
||||
/// </summary>
|
||||
public LZXBlockType BlockType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Have we started decoding at all yet?
|
||||
/// </summary>
|
||||
public byte HeaderRead { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Does stream follow LZX DELTA spec?
|
||||
/// </summary>
|
||||
public bool IsDelta { get; set; }
|
||||
|
||||
#region Huffman code lengths
|
||||
|
||||
public byte[] PRETREE_len { get; set; } = new byte[LZX.LZX_PRETREE_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
|
||||
public byte[] MAINTREE_len { get; set; } = new byte[LZX.LZX_MAINTREE_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
|
||||
public byte[] LENGTH_len { get; set; } = new byte[LZX.LZX_LENGTH_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
|
||||
public byte[] ALIGNED_len { get; set; } = new byte[LZX.LZX_ALIGNED_MAXSYMBOLS + LZX.LZX_LENTABLE_SAFETY];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Huffman decoding tables
|
||||
|
||||
public ushort[] PRETREE_table { get; set; } = new ushort[(1 << LZX.LZX_PRETREE_TABLEBITS) + (LZX.LZX_PRETREE_MAXSYMBOLS * 2)];
|
||||
public ushort[] MAINTREE_table { get; set; } = new ushort[(1 << LZX.LZX_MAINTREE_TABLEBITS) + (LZX.LZX_MAINTREE_MAXSYMBOLS * 2)];
|
||||
public ushort[] LENGTH_table { get; set; } = new ushort[(1 << LZX.LZX_LENGTH_TABLEBITS) + (LZX.LZX_LENGTH_MAXSYMBOLS * 2)];
|
||||
public ushort[] ALIGNED_table { get; set; } = new ushort[(1 << LZX.LZX_ALIGNED_TABLEBITS) + (LZX.LZX_ALIGNED_MAXSYMBOLS * 2)];
|
||||
|
||||
#endregion
|
||||
|
||||
public byte LENGTH_empty { get; set; }
|
||||
|
||||
// This is used purely for doing the intel E8 transform
|
||||
public byte[] e8_buf { get; set; } = new byte[LZX.LZX_FRAME_SIZE];
|
||||
|
||||
public override Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
Error error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
|
||||
byte b0 = InputBuffer[i_ptr++];
|
||||
|
||||
error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
|
||||
byte b1 = InputBuffer[i_ptr++];
|
||||
INJECT_BITS((uint)((b1 << 8) | b0), 16, ref bitsLeft, ref bitBuffer);
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)(Error = Error.MSPACK_ERR_DECRUNCH);
|
||||
}
|
||||
}
|
||||
727
BurnOutSharp/External/libmspack/Compression/MSZIP.cs
vendored
Normal file
727
BurnOutSharp/External/libmspack/Compression/MSZIP.cs
vendored
Normal file
@@ -0,0 +1,727 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* The deflate method was created by Phil Katz. MSZIP is equivalent to the
|
||||
* deflate method.
|
||||
*
|
||||
* 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;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public class MSZIP
|
||||
{
|
||||
#region MSZIP (deflate) compression / (inflate) decompression definitions
|
||||
|
||||
public const int MSZIP_FRAME_SIZE = 32768; // Size of LZ history window
|
||||
public const int MSZIP_LITERAL_MAXSYMBOLS = 288; // literal/length huffman tree
|
||||
public const int MSZIP_LITERAL_TABLEBITS = 9;
|
||||
public const int MSZIP_DISTANCE_MAXSYMBOLS = 32; // Distance huffman tree
|
||||
public const int MSZIP_DISTANCE_TABLEBITS = 6;
|
||||
|
||||
// If there are less direct lookup entries than symbols, the longer
|
||||
// code pointers will be <= maxsymbols. This must not happen, or we
|
||||
// will decode entries badly
|
||||
public static int MSZIP_LITERAL_TABLESIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((1 << MSZIP_LITERAL_TABLEBITS) < (MSZIP_LITERAL_MAXSYMBOLS * 2))
|
||||
return (MSZIP_LITERAL_MAXSYMBOLS * 4);
|
||||
else
|
||||
return ((1 << MSZIP_LITERAL_TABLEBITS) + (MSZIP_LITERAL_MAXSYMBOLS * 2));
|
||||
}
|
||||
}
|
||||
|
||||
public static int MSZIP_DISTANCE_TABLESIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((1 << MSZIP_DISTANCE_TABLEBITS) < (MSZIP_DISTANCE_MAXSYMBOLS * 2))
|
||||
return (MSZIP_DISTANCE_MAXSYMBOLS * 4);
|
||||
else
|
||||
return ((1 << MSZIP_DISTANCE_TABLEBITS) + (MSZIP_DISTANCE_MAXSYMBOLS * 2));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Match lengths for literal codes 257.. 285
|
||||
/// </summary>
|
||||
private static readonly ushort[] lit_lengths = new ushort[29]
|
||||
{
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
|
||||
31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Match offsets for distance codes 0 .. 29
|
||||
/// </summary>
|
||||
private static readonly ushort[] dist_offsets = new ushort[30]
|
||||
{
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
|
||||
513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Extra bits required for literal codes 257.. 285
|
||||
/// </summary>
|
||||
private static readonly byte[] lit_extrabits = new byte[29]
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
|
||||
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Extra bits required for distance codes 0 .. 29
|
||||
/// </summary>
|
||||
private static readonly byte[] dist_extrabits = new byte[30]
|
||||
{
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
|
||||
6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The order of the bit length Huffman code lengths
|
||||
/// </summary>
|
||||
private static readonly byte[] bitlen_order = new byte[19]
|
||||
{
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Allocates MS-ZIP decompression stream for decoding the given stream.
|
||||
///
|
||||
/// - uses system.alloc() to allocate memory
|
||||
///
|
||||
/// - returns null if not enough memory
|
||||
///
|
||||
/// - input_buffer_size is how many bytes to use as an input bitstream buffer
|
||||
///
|
||||
/// - if RepairMode is non-zero, errors in decompression will be skipped
|
||||
/// and 'holes' left will be filled with zero bytes. This allows at least
|
||||
/// a partial recovery of erroneous data.
|
||||
/// </summary>
|
||||
public static MSZIPDStream Init(SystemImpl system, object input, object output, int input_buffer_size, bool repair_mode)
|
||||
{
|
||||
if (system == null)
|
||||
return null;
|
||||
|
||||
// Round up input buffer size to multiple of two
|
||||
input_buffer_size = (input_buffer_size + 1) & -2;
|
||||
if (input_buffer_size < 2)
|
||||
return null;
|
||||
|
||||
// Allocate decompression state
|
||||
MSZIPDStream zip = new MSZIPDStream();
|
||||
|
||||
// Allocate input buffer
|
||||
zip.InputBuffer = new byte[input_buffer_size];
|
||||
|
||||
// Initialise decompression state
|
||||
zip.Sys = system;
|
||||
zip.Input = input;
|
||||
zip.Output = output;
|
||||
zip.InputBufferSize = (uint)input_buffer_size;
|
||||
zip.InputEnd = 0;
|
||||
zip.Error = Error.MSPACK_ERR_OK;
|
||||
zip.RepairMode = repair_mode;
|
||||
zip.FlushWindow = FlushWindow;
|
||||
|
||||
zip.InputPointer = zip.InputLength = 0;
|
||||
zip.OutputPointer = zip.OutputLength = 0;
|
||||
zip.BitBuffer = 0; zip.BitsLeft = 0;
|
||||
|
||||
return zip;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses, or decompresses more of, an MS-ZIP stream.
|
||||
///
|
||||
/// - out_bytes of data will be decompressed and the function will return
|
||||
/// with an MSPACK_ERR_OK return code.
|
||||
///
|
||||
/// - decompressing will stop as soon as out_bytes is reached. if the true
|
||||
/// amount of bytes decoded spills over that amount, they will be kept for
|
||||
/// a later invocation of mszipd_decompress().
|
||||
///
|
||||
/// - the output bytes will be passed to the system.write() function given in
|
||||
/// mszipd_init(), using the output file handle given in mszipd_init(). More
|
||||
/// than one call may be made to system.write()
|
||||
///
|
||||
/// - MS-ZIP will read input bytes as necessary using the system.read()
|
||||
/// function given in mszipd_init(), using the input file handle given in
|
||||
/// mszipd_init(). This will continue until system.read() returns 0 bytes,
|
||||
/// or an error.
|
||||
/// </summary>
|
||||
public static Error Decompress(object o, long out_bytes)
|
||||
{
|
||||
MSZIPDStream zip = (MSZIPDStream)o;
|
||||
if (zip == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
// For the bit buffer
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
|
||||
int i, state, error;
|
||||
|
||||
// Easy answers
|
||||
if (zip == null || (out_bytes < 0))
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return zip.Error;
|
||||
|
||||
// Flush out any stored-up bytes before we begin
|
||||
i = zip.OutputLength - zip.OutputPointer;
|
||||
if (i > out_bytes)
|
||||
i = (int)out_bytes;
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
if (zip.Sys.Write(zip.Output, zip.Window, zip.OutputPointer, i) != i)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
zip.OutputPointer += i;
|
||||
out_bytes -= i;
|
||||
}
|
||||
|
||||
if (out_bytes == 0)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
while (out_bytes > 0)
|
||||
{
|
||||
// Unpack another block
|
||||
zip.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
// Skip to next read 'CK' header
|
||||
i = (int)(bits_left & 7);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer); // Align to bytestream
|
||||
state = 0;
|
||||
|
||||
do
|
||||
{
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (i == 'C')
|
||||
state = 1;
|
||||
else if ((state == 1) && (i == 'K'))
|
||||
state = 2;
|
||||
else
|
||||
state = 0;
|
||||
} while (state != 2);
|
||||
|
||||
// Inflate a block, repair and realign if necessary
|
||||
zip.WindowPosition = 0;
|
||||
zip.BytesOutput = 0;
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
|
||||
if ((error = (int)Inflate(zip)) != 0)
|
||||
{
|
||||
Console.WriteLine($"inflate error {error}");
|
||||
if (zip.RepairMode)
|
||||
{
|
||||
// Recover partially-inflated buffers
|
||||
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.");
|
||||
for (i = zip.BytesOutput; i < MSZIP_FRAME_SIZE; i++)
|
||||
{
|
||||
zip.Window[i] = 0x00;
|
||||
}
|
||||
|
||||
zip.BytesOutput = MSZIP_FRAME_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return zip.Error = (error > 0) ? (Error)error : Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
}
|
||||
zip.OutputPointer = 0;
|
||||
zip.OutputLength = zip.BytesOutput;
|
||||
|
||||
// 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)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
// mspack errors (i.e. read errors) are fatal and can't be recovered
|
||||
if (error > 0 && zip.RepairMode)
|
||||
return (Error)error;
|
||||
|
||||
zip.OutputPointer += i;
|
||||
out_bytes -= i;
|
||||
}
|
||||
|
||||
if (out_bytes != 0)
|
||||
{
|
||||
Console.WriteLine("bytes left to output");
|
||||
return zip.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an entire MS-ZIP stream in a KWAJ file. Acts very much
|
||||
/// like mszipd_decompress(), but doesn't take an out_bytes parameter
|
||||
/// </summary>
|
||||
public static Error DecompressKWAJ(MSZIPDStream zip)
|
||||
{
|
||||
// For the bit buffer
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
|
||||
int i = 0, error, block_len = 0;
|
||||
|
||||
// Unpack blocks until block_len == 0
|
||||
for (; ; )
|
||||
{
|
||||
zip.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
// Align to bytestream, read block_len
|
||||
i = (int)(bits_left & 7);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer);
|
||||
zip.READ_BITS(ref block_len, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
block_len |= i << 8;
|
||||
|
||||
if (block_len == 0)
|
||||
break;
|
||||
|
||||
// Read "CK" header
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (i != 'C')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (i != 'K')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
// Inflate block
|
||||
zip.WindowPosition = 0;
|
||||
zip.BytesOutput = 0;
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
if ((error = (int)Inflate(zip)) != 0)
|
||||
{
|
||||
Console.WriteLine($"inflate error {error}");
|
||||
return zip.Error = (error > 0) ? (Error)error : Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
// Write inflated block
|
||||
if (zip.Sys.Write(zip.Output, zip.Window, 0, zip.BytesOutput) != zip.BytesOutput)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees all stream associated with an MS-ZIP data stream
|
||||
///
|
||||
/// - calls system.free() using the system pointer given in mszipd_init()
|
||||
/// </summary>
|
||||
public static void Free(MSZIPDStream zip)
|
||||
{
|
||||
if (zip != null)
|
||||
{
|
||||
SystemImpl sys = zip.Sys;
|
||||
sys.Free(zip.InputBuffer);
|
||||
sys.Free(zip);
|
||||
}
|
||||
}
|
||||
|
||||
private static InflateErrorCode ZipReadLens(MSZIPDStream zip)
|
||||
{
|
||||
// For the bit buffer and huffman decoding
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
|
||||
// Bitlen Huffman codes -- immediate lookup, 7 bit max code length
|
||||
ushort[] bl_table = new ushort[1 << 7];
|
||||
byte[] bl_len = new byte[19];
|
||||
|
||||
byte[] lens = new byte[MSZIP_LITERAL_MAXSYMBOLS + MSZIP_DISTANCE_MAXSYMBOLS];
|
||||
int lit_codes = 0, dist_codes = 0, code, last_code = 0, bitlen_codes = 0, i, run = 0;
|
||||
|
||||
zip.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
// Read the number of codes
|
||||
zip.READ_BITS(ref lit_codes, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
lit_codes += 257;
|
||||
zip.READ_BITS(ref dist_codes, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
dist_codes += 1;
|
||||
zip.READ_BITS(ref bitlen_codes, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
bitlen_codes += 4;
|
||||
|
||||
if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS)
|
||||
return InflateErrorCode.INF_ERR_SYMLENS;
|
||||
if (dist_codes > MSZIP_DISTANCE_MAXSYMBOLS)
|
||||
return InflateErrorCode.INF_ERR_SYMLENS;
|
||||
|
||||
// Read in the bit lengths in their unusual order
|
||||
for (i = 0; i < bitlen_codes; i++)
|
||||
{
|
||||
int blLenTemp = bl_len[bitlen_order[i]];
|
||||
zip.READ_BITS(ref blLenTemp, 3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
bl_len[bitlen_order[i]] = (byte)blLenTemp;
|
||||
}
|
||||
|
||||
while (i < 19)
|
||||
{
|
||||
bl_len[bitlen_order[i++]] = 0;
|
||||
}
|
||||
|
||||
// Create decoding table with an immediate lookup */
|
||||
if (MSZIPDStream.MakeDecodeTable(19, 7, bl_len, bl_table) != 0)
|
||||
return InflateErrorCode.INF_ERR_BITLENTBL;
|
||||
|
||||
// Read literal / distance code lengths
|
||||
for (i = 0; i < (lit_codes + dist_codes); i++)
|
||||
{
|
||||
// Single-level huffman lookup
|
||||
zip.ENSURE_BITS(7, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
code = bl_table[zip.PEEK_BITS(7, bit_buffer)];
|
||||
zip.REMOVE_BITS(bl_len[code], ref bits_left, ref bit_buffer);
|
||||
|
||||
if (code < 16)
|
||||
{
|
||||
lens[i] = (byte)(last_code = code);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case 16:
|
||||
zip.READ_BITS(ref run, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
run += 3;
|
||||
code = last_code;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
zip.READ_BITS(ref run, 3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
run += 3;
|
||||
code = 0;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
zip.READ_BITS(ref run, 7, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
run += 11;
|
||||
code = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.WriteLine($"bad code!: {code}");
|
||||
return InflateErrorCode.INF_ERR_BADBITLEN;
|
||||
}
|
||||
|
||||
if ((i + run) > (lit_codes + dist_codes))
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
while (run-- != 0)
|
||||
{
|
||||
lens[i++] = (byte)code;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy LITERAL code lengths and clear any remaining
|
||||
i = lit_codes;
|
||||
zip.Sys.Copy(lens, 0, zip.LITERAL_len, 0, i);
|
||||
while (i < MSZIP_LITERAL_MAXSYMBOLS)
|
||||
{
|
||||
zip.LITERAL_len[i++] = 0;
|
||||
}
|
||||
|
||||
i = dist_codes;
|
||||
zip.Sys.Copy(lens, lit_codes, zip.DISTANCE_len, 0, i);
|
||||
while (i < MSZIP_DISTANCE_MAXSYMBOLS)
|
||||
{
|
||||
zip.DISTANCE_len[i++] = 0;
|
||||
}
|
||||
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A clean implementation of RFC 1951 / inflate
|
||||
/// </summary>
|
||||
private static InflateErrorCode Inflate(MSZIPDStream zip)
|
||||
{
|
||||
int last_block = 0, block_type = 0, distance = 0, length = 0, this_run, i;
|
||||
|
||||
// For the bit buffer and huffman decoding
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
ushort sym = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
|
||||
zip.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
do
|
||||
{
|
||||
// Read in last block bit
|
||||
zip.READ_BITS(ref last_block, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
// Read in block type
|
||||
zip.READ_BITS(ref block_type, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
if (block_type == 0)
|
||||
{
|
||||
// Uncompressed block
|
||||
byte[] lens_buf = new byte[4];
|
||||
|
||||
// Go to byte boundary
|
||||
i = (int)(bits_left & 7);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer);
|
||||
|
||||
// Read 4 bytes of data, emptying the bit-buffer if necessary
|
||||
for (i = 0; (bits_left >= 8); i++)
|
||||
{
|
||||
if (i == 4)
|
||||
return InflateErrorCode.INF_ERR_BITBUF;
|
||||
|
||||
lens_buf[i] = (byte)zip.PEEK_BITS(8, bit_buffer);
|
||||
zip.REMOVE_BITS(8, ref bits_left, ref bit_buffer);
|
||||
}
|
||||
if (bits_left != 0) return InflateErrorCode.INF_ERR_BITBUF;
|
||||
while (i < 4)
|
||||
{
|
||||
zip.READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
lens_buf[i++] = zip.InputBuffer[i_ptr++];
|
||||
}
|
||||
|
||||
// Get the length and its complement
|
||||
length = lens_buf[0] | (lens_buf[1] << 8);
|
||||
i = lens_buf[2] | (lens_buf[3] << 8);
|
||||
if (length != (~i & 0xFFFF))
|
||||
return InflateErrorCode.INF_ERR_COMPLEMENT;
|
||||
|
||||
// Read and copy the uncompressed data into the window
|
||||
while (length > 0)
|
||||
{
|
||||
zip.READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
|
||||
this_run = length;
|
||||
if (this_run > (uint)(i_end - i_ptr)) this_run = i_end - i_ptr;
|
||||
if (this_run > (MSZIP_FRAME_SIZE - zip.WindowPosition))
|
||||
this_run = (int)(MSZIP_FRAME_SIZE - zip.WindowPosition);
|
||||
|
||||
zip.Sys.Copy(zip.InputBuffer, i_ptr, zip.Window, (int)zip.WindowPosition, this_run);
|
||||
zip.WindowPosition += (uint)this_run;
|
||||
i_ptr += this_run;
|
||||
length -= this_run;
|
||||
|
||||
// FLUSH_IF_NEEDED
|
||||
if (zip.WindowPosition == MSZIP_FRAME_SIZE)
|
||||
{
|
||||
if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_FLUSH;
|
||||
|
||||
zip.WindowPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((block_type == 1) || (block_type == 2))
|
||||
{
|
||||
// Huffman-compressed LZ77 block
|
||||
uint match_posn, code = 0;
|
||||
|
||||
if (block_type == 1)
|
||||
{
|
||||
// Block with fixed Huffman codes
|
||||
i = 0;
|
||||
while (i < 144)
|
||||
{
|
||||
zip.LITERAL_len[i++] = 8;
|
||||
}
|
||||
|
||||
while (i < 256)
|
||||
{
|
||||
zip.LITERAL_len[i++] = 9;
|
||||
}
|
||||
|
||||
while (i < 280)
|
||||
{
|
||||
zip.LITERAL_len[i++] = 7;
|
||||
}
|
||||
|
||||
while (i < 288)
|
||||
{
|
||||
zip.LITERAL_len[i++] = 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
zip.DISTANCE_len[i] = 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Block with dynamic Huffman codes
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
|
||||
if ((i = (int)ZipReadLens(zip)) != 0)
|
||||
return (InflateErrorCode)i;
|
||||
|
||||
zip.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
}
|
||||
|
||||
// Now huffman lengths are read for either kind of block,
|
||||
// create huffman decoding tables
|
||||
if (MSZIPDStream.MakeDecodeTable(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, zip.LITERAL_table) != 0)
|
||||
return InflateErrorCode.INF_ERR_LITERALTBL;
|
||||
|
||||
if (MSZIPDStream.MakeDecodeTable(MSZIP_DISTANCE_MAXSYMBOLS, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, zip.DISTANCE_table) != 0)
|
||||
return InflateErrorCode.INF_ERR_DISTANCETBL;
|
||||
|
||||
// Decode forever until end of block code
|
||||
for (; ; )
|
||||
{
|
||||
zip.READ_HUFFSYM(zip.LITERAL_table, ref code, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, MSZIP_LITERAL_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (code < 256)
|
||||
{
|
||||
zip.Window[zip.WindowPosition++] = (byte)code;
|
||||
|
||||
// FLUSH_IF_NEEDED
|
||||
if (zip.WindowPosition == MSZIP_FRAME_SIZE)
|
||||
{
|
||||
if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_FLUSH;
|
||||
|
||||
zip.WindowPosition = 0;
|
||||
}
|
||||
}
|
||||
else if (code == 256)
|
||||
{
|
||||
// END OF BLOCK CODE: loop break point
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
code -= 257; // Codes 257-285 are matches
|
||||
if (code >= 29)
|
||||
return InflateErrorCode.INF_ERR_LITCODE; // Codes 286-287 are illegal
|
||||
|
||||
zip.READ_BITS_T(ref length, lit_extrabits[code], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
length += lit_lengths[code];
|
||||
|
||||
zip.READ_HUFFSYM(zip.DISTANCE_table, ref code, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, MSZIP_DISTANCE_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (code >= 30)
|
||||
return InflateErrorCode.INF_ERR_DISTCODE;
|
||||
|
||||
zip.READ_BITS_T(ref distance, dist_extrabits[code], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
distance += dist_offsets[code];
|
||||
|
||||
// Match position is window position minus distance. If distance
|
||||
// is more than window position numerically, it must 'wrap
|
||||
// around' the frame size.
|
||||
match_posn = (uint)(((distance > zip.WindowPosition) ? MSZIP_FRAME_SIZE : 0) + zip.WindowPosition - distance);
|
||||
|
||||
// Copy match
|
||||
if (length < 12)
|
||||
{
|
||||
// Short match, use slower loop but no loop setup code
|
||||
while (length-- != 0)
|
||||
{
|
||||
zip.Window[zip.WindowPosition++] = zip.Window[match_posn++];
|
||||
match_posn &= MSZIP_FRAME_SIZE - 1;
|
||||
|
||||
// FLUSH_IF_NEEDED
|
||||
if (zip.WindowPosition == MSZIP_FRAME_SIZE)
|
||||
{
|
||||
if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_FLUSH;
|
||||
|
||||
zip.WindowPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Longer match, use faster loop but with setup expense
|
||||
int runsrc, rundest;
|
||||
do
|
||||
{
|
||||
this_run = length;
|
||||
if ((match_posn + this_run) > MSZIP_FRAME_SIZE)
|
||||
this_run = MSZIP_FRAME_SIZE - (int)match_posn;
|
||||
|
||||
if ((zip.WindowPosition + this_run) > MSZIP_FRAME_SIZE)
|
||||
this_run = MSZIP_FRAME_SIZE - (int)zip.WindowPosition;
|
||||
|
||||
rundest = (int)zip.WindowPosition;
|
||||
zip.WindowPosition += (uint)this_run;
|
||||
runsrc = (int)match_posn;
|
||||
match_posn += (uint)this_run;
|
||||
length -= this_run;
|
||||
|
||||
while (this_run-- != 0)
|
||||
{
|
||||
zip.Window[rundest++] = zip.Window[runsrc++];
|
||||
}
|
||||
|
||||
if (match_posn == MSZIP_FRAME_SIZE)
|
||||
match_posn = 0;
|
||||
|
||||
// FLUSH_IF_NEEDED
|
||||
if (zip.WindowPosition == MSZIP_FRAME_SIZE)
|
||||
{
|
||||
if (zip.FlushWindow(zip, MSZIP_FRAME_SIZE) != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_FLUSH;
|
||||
|
||||
zip.WindowPosition = 0;
|
||||
}
|
||||
} while (length > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// block_type == 3 -- bad block type
|
||||
return InflateErrorCode.INF_ERR_BLOCKTYPE;
|
||||
}
|
||||
} while (last_block == 0);
|
||||
|
||||
// Flush the remaining data
|
||||
if (zip.WindowPosition != 0)
|
||||
{
|
||||
if (zip.FlushWindow(zip, zip.WindowPosition) != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_FLUSH;
|
||||
}
|
||||
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
|
||||
// Return success
|
||||
return InflateErrorCode.INF_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// inflate() calls this whenever the window should be flushed. As
|
||||
/// MSZIP only expands to the size of the window, the implementation used
|
||||
/// simply keeps track of the amount of data flushed, and if more than 32k
|
||||
/// is flushed, an error is raised.
|
||||
/// </summary>
|
||||
private static Error FlushWindow(MSZIPDStream zip, uint data_flushed)
|
||||
{
|
||||
zip.BytesOutput += (int)data_flushed;
|
||||
if (zip.BytesOutput > MSZIP_FRAME_SIZE)
|
||||
{
|
||||
Console.WriteLine($"overflow: {data_flushed} bytes flushed, total is now {zip.BytesOutput}");
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
vendored
Normal file
64
BurnOutSharp/External/libmspack/Compression/MSZIPDStream.cs
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* The deflate method was created by Phil Katz. MSZIP is equivalent to the
|
||||
* deflate method.
|
||||
*
|
||||
* 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;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public class MSZIPDStream : CompressionStream
|
||||
{
|
||||
/// <summary>
|
||||
/// 32kb history window
|
||||
/// </summary>
|
||||
public byte[] Window { get; set; } = new byte[MSZIP.MSZIP_FRAME_SIZE];
|
||||
|
||||
/// <summary>
|
||||
/// Offset within window
|
||||
/// </summary>
|
||||
public uint WindowPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// inflate() will call this whenever the window should be emptied.
|
||||
/// </summary>
|
||||
public Func<MSZIPDStream, uint, Error> FlushWindow;
|
||||
|
||||
public bool RepairMode { get; set; }
|
||||
|
||||
public int BytesOutput { get; set; }
|
||||
|
||||
#region Huffman code lengths
|
||||
|
||||
public byte[] LITERAL_len { get; set; } = new byte[MSZIP.MSZIP_LITERAL_MAXSYMBOLS];
|
||||
public byte[] DISTANCE_len { get; set; } = new byte[MSZIP.MSZIP_DISTANCE_MAXSYMBOLS];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Huffman decoding tables
|
||||
|
||||
public ushort[] LITERAL_table { get; set; } = new ushort[MSZIP.MSZIP_LITERAL_TABLESIZE];
|
||||
public ushort[] DISTANCE_table { get; set; } = new ushort[MSZIP.MSZIP_DISTANCE_TABLESIZE];
|
||||
|
||||
#endregion
|
||||
|
||||
public override Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
Error error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
|
||||
INJECT_BITS(InputBuffer[i_ptr++], 8, ref bitsLeft, ref bitBuffer);
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)InflateErrorCode.INF_ERR_HUFFSYM;
|
||||
}
|
||||
}
|
||||
611
BurnOutSharp/External/libmspack/Compression/QTM.cs
vendored
Normal file
611
BurnOutSharp/External/libmspack/Compression/QTM.cs
vendored
Normal file
@@ -0,0 +1,611 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* The Quantum method was created by David Stafford, adapted by Microsoft
|
||||
* Corporation.
|
||||
*
|
||||
* This decompressor is based on an implementation by Matthew Russotto, used
|
||||
* with permission.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Quantum decompression implementation */
|
||||
|
||||
/* This decompressor was researched and implemented by Matthew Russotto. It
|
||||
* has since been tidied up by Stuart Caie. More information can be found at
|
||||
* http://www.speakeasy.org/~russotto/quantumcomp.html
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.Compression
|
||||
{
|
||||
public class QTM
|
||||
{
|
||||
public const int QTM_FRAME_SIZE = 32768;
|
||||
|
||||
/* Quantum static data tables:
|
||||
*
|
||||
* Quantum uses 'position slots' to represent match offsets. For every
|
||||
* match, a small 'position slot' number and a small offset from that slot
|
||||
* are encoded instead of one large offset.
|
||||
*
|
||||
* position_base[] is an index to the position slot bases
|
||||
*
|
||||
* extra_bits[] states how many bits of offset-from-base data is needed.
|
||||
*
|
||||
* length_base[] and length_extra[] are equivalent in function, but are
|
||||
* used for encoding selector 6 (variable length match) match lengths,
|
||||
* instead of match offsets.
|
||||
*
|
||||
* They are generated with the following code:
|
||||
* uint i, offset;
|
||||
* for (i = 0, offset = 0; i < 42; i++) {
|
||||
* position_base[i] = offset;
|
||||
* extra_bits[i] = ((i < 2) ? 0 : (i - 2)) >> 1;
|
||||
* offset += 1 << extra_bits[i];
|
||||
* }
|
||||
* for (i = 0, offset = 0; i < 26; i++) {
|
||||
* length_base[i] = offset;
|
||||
* length_extra[i] = (i < 2 ? 0 : i - 2) >> 2;
|
||||
* offset += 1 << length_extra[i];
|
||||
* }
|
||||
* length_base[26] = 254; length_extra[26] = 0;
|
||||
*/
|
||||
|
||||
private static readonly uint[] position_base = new uint[42]
|
||||
{
|
||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
|
||||
65536, 98304, 131072, 196608, 262144, 393216, 524288, 786432, 1048576, 1572864
|
||||
};
|
||||
|
||||
private static readonly byte[] extra_bits = new byte[42]
|
||||
{
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
|
||||
11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19
|
||||
};
|
||||
|
||||
private static readonly byte[] length_base = new byte[27]
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 18, 22, 26,
|
||||
30, 38, 46, 54, 62, 78, 94, 110, 126, 158, 190, 222, 254
|
||||
};
|
||||
|
||||
private static readonly byte[] length_extra = new byte[27]
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// allocates Quantum decompression state for decoding the given stream.
|
||||
///
|
||||
/// - returns null if window_bits is outwith the range 10 to 21 (inclusive).
|
||||
/// - uses system.alloc() to allocate memory
|
||||
/// - returns null if not enough memory
|
||||
/// - window_bits is the size of the Quantum window, from 1Kb(10) to 2Mb(21).
|
||||
/// - input_buffer_size is the number of bytes to use to store bitstream data.
|
||||
/// </summary>
|
||||
public static QTMDStream Init(SystemImpl system, object input, object output, int window_bits, int input_buffer_size)
|
||||
{
|
||||
uint window_size = (uint)(1 << window_bits);
|
||||
|
||||
if (system == null)
|
||||
return null;
|
||||
|
||||
// Quantum supports window sizes of 2^10 (1Kb) through 2^21 (2Mb)
|
||||
if (window_bits < 10 || window_bits > 21)
|
||||
return null;
|
||||
|
||||
// Round up input buffer size to multiple of two
|
||||
input_buffer_size = (input_buffer_size + 1) & -2;
|
||||
if (input_buffer_size < 2) return null;
|
||||
|
||||
// Allocate decompression state
|
||||
QTMDStream qtm = new QTMDStream();
|
||||
|
||||
// Allocate decompression window and input buffer
|
||||
qtm.Window = new byte[window_size];
|
||||
qtm.InputBuffer = new byte[input_buffer_size];
|
||||
|
||||
// Initialise decompression state
|
||||
qtm.Sys = system;
|
||||
qtm.Input = input;
|
||||
qtm.Output = output;
|
||||
qtm.InputBufferSize = (uint)input_buffer_size;
|
||||
qtm.WindowSize = window_size;
|
||||
qtm.WindowPosition = 0;
|
||||
qtm.FrameTODO = QTM_FRAME_SIZE;
|
||||
qtm.HeaderRead = 0;
|
||||
qtm.Error = Error.MSPACK_ERR_OK;
|
||||
|
||||
qtm.InputPointer = qtm.InputLength = 0;
|
||||
qtm.OutputPointer = qtm.OutputLength = 0;
|
||||
qtm.InputEnd = 0;
|
||||
qtm.BitsLeft = 0;
|
||||
qtm.BitBuffer = 0;
|
||||
|
||||
// Initialise arithmetic coding models
|
||||
// - model 4 depends on window size, ranges from 20 to 24
|
||||
// - model 5 depends on window size, ranges from 20 to 36
|
||||
// - model 6pos depends on window size, ranges from 20 to 42
|
||||
|
||||
int i = window_bits * 2;
|
||||
InitModel(qtm.Model0, qtm.Model0Symbols, 0, 64);
|
||||
InitModel(qtm.Model1, qtm.Model1Symbols, 64, 64);
|
||||
InitModel(qtm.Model2, qtm.Model2Symbols, 128, 64);
|
||||
InitModel(qtm.Model3, qtm.Model3Symbols, 192, 64);
|
||||
InitModel(qtm.Model4, qtm.Model4Symbols, 0, (i > 24) ? 24 : i);
|
||||
InitModel(qtm.Model5, qtm.Model5Symbols, 0, (i > 36) ? 36 : i);
|
||||
InitModel(qtm.Model6, qtm.Model6Symbols, 0, i);
|
||||
InitModel(qtm.Model6Len, qtm.Model6LenSymbols, 0, 27);
|
||||
InitModel(qtm.Model7, qtm.Model7Symbols, 0, 7);
|
||||
|
||||
// All ok
|
||||
return qtm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses, or decompresses more of, a Quantum stream.
|
||||
///
|
||||
/// - out_bytes of data will be decompressed and the function will return
|
||||
/// with an MSPACK_ERR_OK return code.
|
||||
///
|
||||
/// - decompressing will stop as soon as out_bytes is reached. if the true
|
||||
/// amount of bytes decoded spills over that amount, they will be kept for
|
||||
/// a later invocation of qtmd_decompress().
|
||||
///
|
||||
/// - the output bytes will be passed to the system.write() function given in
|
||||
/// qtmd_init(), using the output file handle given in qtmd_init(). More
|
||||
/// than one call may be made to system.write()
|
||||
///
|
||||
/// - Quantum will read input bytes as necessary using the system.read()
|
||||
/// function given in qtmd_init(), using the input file handle given in
|
||||
/// qtmd_init(). This will continue until system.read() returns 0 bytes,
|
||||
/// or an error.
|
||||
/// </summary>
|
||||
public static Error Decompress(object o, long out_bytes)
|
||||
{
|
||||
QTMDStream qtm = (QTMDStream)o;
|
||||
if (qtm == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
uint frame_end, match_offset, range = 0, extra = 0;
|
||||
int i_ptr = 0, i_end = 0, runsrc, rundest;
|
||||
int i, j, selector = 0, sym = 0, match_length;
|
||||
ushort symf = 0;
|
||||
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
|
||||
// Easy answers
|
||||
if (qtm == null || (out_bytes < 0))
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
|
||||
if (qtm.Error != Error.MSPACK_ERR_OK)
|
||||
return qtm.Error;
|
||||
|
||||
// Flush out any stored-up bytes before we begin
|
||||
i = qtm.OutputLength - qtm.OutputPointer;
|
||||
if (i > out_bytes)
|
||||
i = (int)out_bytes;
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
if (qtm.Sys.Write(qtm.Output, qtm.Window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
qtm.OutputPointer += i;
|
||||
out_bytes -= i;
|
||||
}
|
||||
|
||||
if (out_bytes == 0)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
// Restore local state
|
||||
qtm.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
byte[] window = qtm.Window;
|
||||
uint window_posn = qtm.WindowPosition;
|
||||
uint frame_todo = qtm.FrameTODO;
|
||||
|
||||
ushort high = qtm.High;
|
||||
ushort low = qtm.Low;
|
||||
ushort current = qtm.Current;
|
||||
|
||||
// While we do not have enough decoded bytes in reserve:
|
||||
while ((qtm.OutputLength - qtm.OutputPointer) < out_bytes)
|
||||
{
|
||||
// Read header if necessary. Initialises H, L and C
|
||||
if (qtm.HeaderRead == 0)
|
||||
{
|
||||
high = 0xFFFF;
|
||||
low = 0;
|
||||
int tempCurrent = current;
|
||||
qtm.READ_BITS(ref tempCurrent, 16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
current = (ushort)tempCurrent;
|
||||
qtm.HeaderRead = 1;
|
||||
}
|
||||
|
||||
// Decode more, up to the number of bytes needed, the frame boundary,
|
||||
// or the window boundary, whichever comes first
|
||||
frame_end = (uint)(window_posn + (out_bytes - (qtm.OutputLength - qtm.OutputPointer)));
|
||||
if ((window_posn + frame_todo) < frame_end)
|
||||
frame_end = window_posn + frame_todo;
|
||||
|
||||
if (frame_end > qtm.WindowSize)
|
||||
frame_end = qtm.WindowSize;
|
||||
|
||||
while (window_posn < frame_end)
|
||||
{
|
||||
GET_SYMBOL(qtm, qtm.Model7, ref selector, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (selector < 4)
|
||||
{
|
||||
// Literal byte
|
||||
QTMDModel mdl;
|
||||
switch (selector)
|
||||
{
|
||||
case 0: mdl = qtm.Model0; break;
|
||||
case 1: mdl = qtm.Model1; break;
|
||||
case 2: mdl = qtm.Model2; break;
|
||||
default: mdl = qtm.Model3; break;
|
||||
}
|
||||
|
||||
GET_SYMBOL(qtm, mdl, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
window[window_posn++] = (byte)sym;
|
||||
frame_todo--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Match repeated string
|
||||
switch (selector)
|
||||
{
|
||||
// Selector 4 = fixed length match (3 bytes)
|
||||
case 4:
|
||||
GET_SYMBOL(qtm, qtm.Model4, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
match_offset = position_base[sym] + extra + 1;
|
||||
match_length = 3;
|
||||
break;
|
||||
|
||||
// Selector 5 = fixed length match (4 bytes)
|
||||
case 5:
|
||||
GET_SYMBOL(qtm, qtm.Model5, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
match_offset = position_base[sym] + extra + 1;
|
||||
match_length = 4;
|
||||
break;
|
||||
|
||||
// Selector 6 = variable length match
|
||||
case 6:
|
||||
GET_SYMBOL(qtm, qtm.Model6Len, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
qtm.READ_MANY_BITS(ref extra, length_extra[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
match_length = (int)(length_base[sym] + extra + 5);
|
||||
|
||||
GET_SYMBOL(qtm, qtm.Model6, ref sym, ref range, ref symf, ref high, ref low, ref current, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
match_offset = position_base[sym] + extra + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Should be impossible, model7 can only return 0-6
|
||||
Console.WriteLine("got %d from selector", selector);
|
||||
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
rundest = (int)window_posn;
|
||||
frame_todo -= (uint)match_length;
|
||||
|
||||
// Does match destination wrap the window? This situation is possible
|
||||
// where the window size is less than the 32k frame size, but matches
|
||||
// must not go beyond a frame boundary */
|
||||
if ((window_posn + match_length) > qtm.WindowSize)
|
||||
{
|
||||
/* copy first part of match, before window end */
|
||||
i = (int)(qtm.WindowSize - window_posn);
|
||||
j = (int)(window_posn - match_offset);
|
||||
while (i-- != 0)
|
||||
{
|
||||
window[rundest++] = window[j++ & (qtm.WindowSize - 1)];
|
||||
}
|
||||
|
||||
// Flush currently stored data
|
||||
i = (int)(qtm.WindowSize - qtm.OutputPointer);
|
||||
|
||||
// This should not happen, but if it does then this code
|
||||
// can't handle the situation (can't flush up to the end of
|
||||
// the window, but can't break out either because we haven't
|
||||
// finished writing the match). bail out in this case */
|
||||
if (i > out_bytes)
|
||||
{
|
||||
Console.WriteLine($"during window-wrap match; {i} bytes to flush but only need {out_bytes}");
|
||||
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
if (qtm.Sys.Write(qtm.Output, qtm.Window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
out_bytes -= i;
|
||||
qtm.OutputPointer = 0;
|
||||
qtm.OutputLength = 0;
|
||||
|
||||
// Copy second part of match, after window wrap
|
||||
rundest = 0;
|
||||
i = (int)(match_length - (qtm.WindowSize - window_posn));
|
||||
while (i-- != 0)
|
||||
{
|
||||
window[rundest++] = window[j++ & (qtm.WindowSize - 1)];
|
||||
}
|
||||
|
||||
window_posn = (uint)(window_posn + match_length - qtm.WindowSize);
|
||||
|
||||
break; // Because "window_posn < frame_end" has now failed
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal match - output won't wrap window or frame end
|
||||
i = match_length;
|
||||
|
||||
// Does match _offset_ wrap the window?
|
||||
if (match_offset > window_posn)
|
||||
{
|
||||
// j = length from match offset to end of window
|
||||
j = (int)(match_offset - window_posn);
|
||||
if (j > (int)qtm.WindowSize)
|
||||
{
|
||||
Console.WriteLine("match offset beyond window boundaries");
|
||||
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
runsrc = (int)(qtm.WindowSize - j);
|
||||
if (j < i)
|
||||
{
|
||||
// If match goes over the window edge, do two copy runs
|
||||
i -= j;
|
||||
while (j-- > 0)
|
||||
{
|
||||
window[rundest++] = window[runsrc++];
|
||||
}
|
||||
|
||||
runsrc = 0;
|
||||
}
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
window[rundest++] = window[runsrc++];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
runsrc = (int)(rundest - match_offset);
|
||||
while (i-- > 0)
|
||||
{
|
||||
window[rundest++] = window[runsrc++];
|
||||
}
|
||||
}
|
||||
|
||||
window_posn += (uint)match_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qtm.OutputLength = (int)window_posn;
|
||||
|
||||
// If we subtracted too much from frame_todo, it will
|
||||
// wrap around past zero and go above its max value */
|
||||
if (frame_todo > QTM_FRAME_SIZE)
|
||||
{
|
||||
Console.WriteLine("overshot frame alignment");
|
||||
return qtm.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
// Another frame completed?
|
||||
if (frame_todo == 0)
|
||||
{
|
||||
// Re-align input
|
||||
if ((bits_left & 7) != 0)
|
||||
qtm.REMOVE_BITS((int)bits_left & 7, ref bits_left, ref bit_buffer);
|
||||
|
||||
// Special Quantum hack -- cabd.c injects a trailer byte to allow the
|
||||
// decompressor to realign itself. CAB Quantum blocks, unlike LZX
|
||||
// blocks, can have anything from 0 to 4 trailing null bytes. */
|
||||
do
|
||||
{
|
||||
qtm.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
} while (i != 0xFF);
|
||||
|
||||
qtm.HeaderRead = 0;
|
||||
|
||||
frame_todo = QTM_FRAME_SIZE;
|
||||
}
|
||||
|
||||
// Window wrap?
|
||||
if (window_posn == qtm.WindowSize)
|
||||
{
|
||||
// Flush all currently stored data
|
||||
i = (qtm.OutputLength - qtm.OutputPointer);
|
||||
|
||||
// Break out if we have more than enough to finish this request
|
||||
if (i >= out_bytes)
|
||||
break;
|
||||
|
||||
if (qtm.Sys.Write(qtm.Output, qtm.Window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
out_bytes -= i;
|
||||
qtm.OutputPointer = 0;
|
||||
qtm.OutputLength = 0;
|
||||
window_posn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_bytes != 0)
|
||||
{
|
||||
i = (int)out_bytes;
|
||||
if (qtm.Sys.Write(qtm.Output, qtm.Window, qtm.OutputPointer, i) != i)
|
||||
return qtm.Error = Error.MSPACK_ERR_WRITE;
|
||||
|
||||
qtm.OutputPointer += i;
|
||||
}
|
||||
|
||||
// Store local state
|
||||
qtm.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
qtm.WindowPosition = window_posn;
|
||||
qtm.FrameTODO = frame_todo;
|
||||
qtm.High = high;
|
||||
qtm.Low = low;
|
||||
qtm.Current = (ushort)current;
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees all state associated with a Quantum data stream
|
||||
/// - calls system.free() using the system pointer given in qtmd_init()
|
||||
/// </summary>
|
||||
public static void Free(QTMDStream qtm)
|
||||
{
|
||||
if (qtm != null)
|
||||
{
|
||||
SystemImpl sys = qtm.Sys;
|
||||
sys.Free(qtm.Window);
|
||||
sys.Free(qtm.InputBuffer);
|
||||
sys.Free(qtm);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arithmetic decoder:
|
||||
///
|
||||
/// GET_SYMBOL(model, var) fetches the next symbol from the stated model
|
||||
/// and puts it in var.
|
||||
///
|
||||
/// If necessary, qtmd_update_model() is called.
|
||||
/// </summary>
|
||||
private static void GET_SYMBOL(QTMDStream qtm, QTMDModel model, ref int var, ref uint range, ref ushort symf, ref ushort high, ref ushort low, ref ushort current,
|
||||
ref int i_ptr, ref int i_end, ref uint bit_buffer, ref uint bits_left)
|
||||
{
|
||||
range = (uint)(((high - low) & 0xFFFF) + 1);
|
||||
symf = (ushort)(((((current - low + 1) * model.Syms[0].CumFreq) - 1) / range) & 0xFFFF);
|
||||
|
||||
int i;
|
||||
for (i = 1; i < model.Entries; i++)
|
||||
{
|
||||
if (model.Syms[i].CumFreq <= symf)
|
||||
break;
|
||||
}
|
||||
|
||||
var = model.Syms[i - 1].Sym;
|
||||
|
||||
range = (ushort)((high - low) + 1);
|
||||
symf = model.Syms[0].CumFreq;
|
||||
high = (ushort)(low + ((model.Syms[i - 1].CumFreq * range) / symf) - 1);
|
||||
low = (ushort)(low + ((model.Syms[i].CumFreq * range) / symf));
|
||||
|
||||
do
|
||||
{
|
||||
model.Syms[--i].CumFreq += 8;
|
||||
} while (i > 0);
|
||||
|
||||
if (model.Syms[0].CumFreq > 3800)
|
||||
UpdateModel(model);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ((low & 0x8000) != (high & 0x8000))
|
||||
{
|
||||
// Underflow case
|
||||
if ((low & 0x4000) != 0 && (high & 0x4000) == 0)
|
||||
{
|
||||
current ^= 0x4000;
|
||||
low &= 0x3FFF;
|
||||
high |= 0x4000;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
low <<= 1;
|
||||
high = (ushort)((high << 1) | 1);
|
||||
qtm.ENSURE_BITS(1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
current = (ushort)((current << 1) | qtm.PEEK_BITS(1, bit_buffer));
|
||||
qtm.REMOVE_BITS(1, ref bits_left, ref bit_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateModel(QTMDModel model)
|
||||
{
|
||||
QTMDModelSym tmp;
|
||||
int i, j;
|
||||
|
||||
if (--model.ShiftsLeft != 0)
|
||||
{
|
||||
for (i = model.Entries - 1; i >= 0; i--)
|
||||
{
|
||||
/* -1, not -2; the 0 entry saves this */
|
||||
model.Syms[i].CumFreq >>= 1;
|
||||
if (model.Syms[i].CumFreq <= model.Syms[i + 1].CumFreq)
|
||||
{
|
||||
model.Syms[i].CumFreq = (ushort)(model.Syms[i + 1].CumFreq + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
model.ShiftsLeft = 50;
|
||||
for (i = 0; i < model.Entries; i++)
|
||||
{
|
||||
// No -1, want to include the 0 entry
|
||||
|
||||
// This converts CumFreqs into frequencies, then shifts right
|
||||
model.Syms[i].CumFreq -= model.Syms[i + 1].CumFreq;
|
||||
model.Syms[i].CumFreq++; // Avoid losing things entirely
|
||||
model.Syms[i].CumFreq >>= 1;
|
||||
}
|
||||
|
||||
// Now sort by frequencies, decreasing order -- this must be an
|
||||
// inplace selection sort, or a sort with the same (in)stability
|
||||
// characteristics
|
||||
for (i = 0; i < model.Entries - 1; i++)
|
||||
{
|
||||
for (j = i + 1; j < model.Entries; j++)
|
||||
{
|
||||
if (model.Syms[i].CumFreq < model.Syms[j].CumFreq)
|
||||
{
|
||||
tmp = model.Syms[i];
|
||||
model.Syms[i] = model.Syms[j];
|
||||
model.Syms[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then convert frequencies back to CumFreq
|
||||
for (i = model.Entries - 1; i >= 0; i--)
|
||||
{
|
||||
model.Syms[i].CumFreq += model.Syms[i + 1].CumFreq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitModel(QTMDModel model, QTMDModelSym[] syms, int start, int len)
|
||||
{
|
||||
model.ShiftsLeft = 4;
|
||||
model.Entries = len;
|
||||
model.Syms = syms;
|
||||
|
||||
for (int i = 0; i <= len; i++)
|
||||
{
|
||||
// Actual symbol
|
||||
syms[i].Sym = (ushort)(start + i);
|
||||
|
||||
// Current frequency of that symbol
|
||||
syms[i].CumFreq = (ushort)(len - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
BurnOutSharp/External/libmspack/Compression/QTMDModel.cs
vendored
Normal file
23
BurnOutSharp/External/libmspack/Compression/QTMDModel.cs
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* The Quantum method was created by David Stafford, adapted by Microsoft
|
||||
* 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.Compression
|
||||
{
|
||||
public class QTMDModel
|
||||
{
|
||||
public int ShiftsLeft { get; set; }
|
||||
|
||||
public int Entries { get; set; }
|
||||
|
||||
public QTMDModelSym[] Syms { get; set; }
|
||||
}
|
||||
}
|
||||
21
BurnOutSharp/External/libmspack/Compression/QTMDModelSym.cs
vendored
Normal file
21
BurnOutSharp/External/libmspack/Compression/QTMDModelSym.cs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* The Quantum method was created by David Stafford, adapted by Microsoft
|
||||
* 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.Compression
|
||||
{
|
||||
public class QTMDModelSym
|
||||
{
|
||||
public ushort Sym { get; set; }
|
||||
|
||||
public ushort CumFreq { get; set; }
|
||||
}
|
||||
}
|
||||
142
BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
vendored
Normal file
142
BurnOutSharp/External/libmspack/Compression/QTMDStream.cs
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2004 Stuart Caie.
|
||||
*
|
||||
* The Quantum method was created by David Stafford, adapted by Microsoft
|
||||
* 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.Compression
|
||||
{
|
||||
public class QTMDStream : CompressionStream
|
||||
{
|
||||
/// <summary>
|
||||
/// Decoding window
|
||||
/// </summary>
|
||||
public byte[] Window { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Window size
|
||||
/// </summary>
|
||||
public uint WindowSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decompression offset within window
|
||||
/// </summary>
|
||||
public uint WindowPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Bytes remaining for current frame
|
||||
/// </summary>
|
||||
public uint FrameTODO { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// High: arith coding state
|
||||
/// </summary>
|
||||
public ushort High { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Low: arith coding state
|
||||
/// </summary>
|
||||
public ushort Low { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current: arith coding state
|
||||
/// </summary>
|
||||
public ushort Current { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Have we started decoding a new frame?
|
||||
/// </summary>
|
||||
public byte HeaderRead { get; set; }
|
||||
|
||||
// Four literal models, each representing 64 symbols
|
||||
|
||||
/// <summary>
|
||||
/// For literals from 0 to 63 (selector = 0)
|
||||
/// </summary>
|
||||
public QTMDModel Model0 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For literals from 64 to 127 (selector = 1)
|
||||
/// </summary>
|
||||
public QTMDModel Model1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For literals from 128 to 191 (selector = 2)
|
||||
/// </summary>
|
||||
public QTMDModel Model2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For literals from 129 to 255 (selector = 3)
|
||||
/// </summary>
|
||||
public QTMDModel Model3 { get; set; }
|
||||
|
||||
// Three match models.
|
||||
|
||||
/// <summary>
|
||||
/// For match with fixed length of 3 bytes
|
||||
/// </summary>
|
||||
public QTMDModel Model4 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For match with fixed length of 4 bytes
|
||||
/// </summary>
|
||||
public QTMDModel Model5 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For variable length match, encoded with model6len model
|
||||
/// </summary>
|
||||
public QTMDModel Model6 { get; set; }
|
||||
|
||||
public QTMDModel Model6Len { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Selector model. 0-6 to say literal (0,1,2,3) or match (4,5,6)
|
||||
/// </summary>
|
||||
public QTMDModel Model7 { get; set; }
|
||||
|
||||
// Symbol arrays for all models
|
||||
|
||||
public QTMDModelSym[] Model0Symbols { get; set; } = new QTMDModelSym[64 + 1];
|
||||
|
||||
public QTMDModelSym[] Model1Symbols { get; set; } = new QTMDModelSym[64 + 1];
|
||||
|
||||
public QTMDModelSym[] Model2Symbols { get; set; } = new QTMDModelSym[64 + 1];
|
||||
|
||||
public QTMDModelSym[] Model3Symbols { get; set; } = new QTMDModelSym[64 + 1];
|
||||
|
||||
public QTMDModelSym[] Model4Symbols { get; set; } = new QTMDModelSym[24 + 1];
|
||||
|
||||
public QTMDModelSym[] Model5Symbols { get; set; } = new QTMDModelSym[36 + 1];
|
||||
|
||||
public QTMDModelSym[] Model6Symbols { get; set; } = new QTMDModelSym[42 + 1];
|
||||
|
||||
public QTMDModelSym[] Model6LenSymbols { get; set; } = new QTMDModelSym[27 + 1];
|
||||
|
||||
public QTMDModelSym[] Model7Symbols { get; set; } = new QTMDModelSym[7 + 1];
|
||||
|
||||
public override Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
Error error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
|
||||
byte b0 = InputBuffer[i_ptr++];
|
||||
|
||||
error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
|
||||
byte b1 = InputBuffer[i_ptr++];
|
||||
INJECT_BITS((uint)((b0 << 8) | b1), 16, ref bitsLeft, ref bitBuffer);
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)Error.MSPACK_ERR_OK;
|
||||
}
|
||||
}
|
||||
20
BurnOutSharp/External/libmspack/DefaultFileImpl.cs
vendored
Normal file
20
BurnOutSharp/External/libmspack/DefaultFileImpl.cs
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/* 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 class DefaultFileImpl
|
||||
{
|
||||
public Stream FileHandle { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
};
|
||||
}
|
||||
215
BurnOutSharp/External/libmspack/Enums.cs
vendored
Normal file
215
BurnOutSharp/External/libmspack/Enums.cs
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// All compressors and decompressors use the same set of error codes. Most
|
||||
/// methods return an error code directly.For methods which do not
|
||||
/// return error codes directly, the error code can be obtained with the
|
||||
/// last_error() method.
|
||||
/// </summary>
|
||||
public enum Error
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to indicate success.
|
||||
/// This error code is defined as zero, all other code are non-zero.
|
||||
/// </summary>
|
||||
MSPACK_ERR_OK = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A method was called with inappropriate arguments.
|
||||
/// </summary>
|
||||
MSPACK_ERR_ARGS = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Error opening file
|
||||
/// </summary>
|
||||
MSPACK_ERR_OPEN = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Error reading file
|
||||
/// </summary>
|
||||
MSPACK_ERR_READ = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Error writing file
|
||||
/// </summary>
|
||||
MSPACK_ERR_WRITE = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Seek error
|
||||
/// </summary>
|
||||
MSPACK_ERR_SEEK = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Out of memory
|
||||
/// </summary>
|
||||
MSPACK_ERR_NOMEMORY = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Bad "magic id" in file
|
||||
/// </summary>
|
||||
MSPACK_ERR_SIGNATURE = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Bad or corrupt file format
|
||||
/// </summary>
|
||||
MSPACK_ERR_DATAFORMAT = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Bad checksum or CRC
|
||||
/// </summary>
|
||||
MSPACK_ERR_CHECKSUM = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Error during compression
|
||||
/// </summary>
|
||||
MSPACK_ERR_CRUNCH = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Error during decompression
|
||||
/// </summary>
|
||||
MSPACK_ERR_DECRUNCH = 11,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The interface to request current version of
|
||||
/// </summary>
|
||||
public enum Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the overall library version
|
||||
/// </summary>
|
||||
MSPACK_VER_LIBRARY = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mspack_system version
|
||||
/// </summary>
|
||||
MSPACK_VER_SYSTEM = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mscab_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSCABD = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mscab_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSCABC = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mschm_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSCHMD = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mschm_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSCHMC = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mslit_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSLITD = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mslit_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSLITC = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mshlp_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSHLPD = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mshlp_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSHLPC = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the msszdd_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSSZDDD = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the msszdd_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSSZDDC = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mskwaj_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSKWAJD = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the mskwaj_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSKWAJC = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the msoab_decompressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSOABD = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Pass to mspack_version() to get the msoab_compressor version
|
||||
/// </summary>
|
||||
MSPACK_VER_MSOABC = 15,
|
||||
}
|
||||
|
||||
public enum OpenMode
|
||||
{
|
||||
/// <summary>
|
||||
/// mspack_system::open() mode: open existing file for reading.
|
||||
/// </summary>
|
||||
MSPACK_SYS_OPEN_READ = 0,
|
||||
|
||||
/// <summary>
|
||||
/// mspack_system::open() mode: open new file for writing
|
||||
/// </summary>
|
||||
MSPACK_SYS_OPEN_WRITE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// mspack_system::open() mode: open existing file for writing
|
||||
/// </summary>
|
||||
MSPACK_SYS_OPEN_UPDATE = 2,
|
||||
|
||||
/// <summary>
|
||||
/// mspack_system::open() mode: open existing file for writing
|
||||
/// </summary>
|
||||
MSPACK_SYS_OPEN_APPEND = 3,
|
||||
}
|
||||
|
||||
public enum SeekMode
|
||||
{
|
||||
/// <summary>
|
||||
/// mspack_system::seek() mode: seek relative to start of file
|
||||
/// </summary>
|
||||
MSPACK_SYS_SEEK_START = 0,
|
||||
|
||||
/// <summary>
|
||||
/// mspack_system::seek() mode: seek relative to current offset
|
||||
/// </summary>
|
||||
MSPACK_SYS_SEEK_CUR = 1,
|
||||
|
||||
/// <summary>
|
||||
/// mspack_system::seek() mode: seek relative to end of file
|
||||
/// </summary>
|
||||
MSPACK_SYS_SEEK_END = 2,
|
||||
}
|
||||
}
|
||||
23
BurnOutSharp/External/libmspack/HLP/Compressor.cs
vendored
Normal file
23
BurnOutSharp/External/libmspack/HLP/Compressor.cs
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
{
|
||||
public class Compressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/HLP/CompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/HLP/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
23
BurnOutSharp/External/libmspack/HLP/Decompressor.cs
vendored
Normal file
23
BurnOutSharp/External/libmspack/HLP/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.HLP
|
||||
{
|
||||
public class Decompressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/HLP/DecompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/HLP/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
15
BurnOutSharp/External/libmspack/HLP/Implementation.cs
vendored
Normal file
15
BurnOutSharp/External/libmspack/HLP/Implementation.cs
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/* 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 Implementation
|
||||
{
|
||||
}
|
||||
}
|
||||
139
BurnOutSharp/External/libmspack/KWAJ/Compressor.cs
vendored
Normal file
139
BurnOutSharp/External/libmspack/KWAJ/Compressor.cs
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
/// <summary>
|
||||
/// A compressor for the KWAJ file format.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateKWAJCompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyKWAJCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads an input file and creates a compressed output file in the
|
||||
/// KWAJ compressed file format.The KWAJ compression format is quick
|
||||
/// but gives poor compression.It is possible for the compressed output
|
||||
/// file to be larger than the input file.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// the name of the file to compressed. This is passed
|
||||
/// passed directly to mspack_system::open()
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// the name of the file to write compressed data to.
|
||||
/// This is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="length">
|
||||
/// the length of the uncompressed file, or -1 to indicate
|
||||
/// that this should be determined automatically by using
|
||||
/// mspack_system::seek() on the input file.
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="SetParam"/>
|
||||
public Func<Compressor, string, string, long, Error> Compress;
|
||||
|
||||
/// <summary>
|
||||
/// Sets an KWAJ compression engine parameter.
|
||||
///
|
||||
/// The following parameters are defined:
|
||||
///
|
||||
/// - #MSKWAJC_PARAM_COMP_TYPE: the compression method to use. Must
|
||||
/// be one of #MSKWAJC_COMP_NONE, #MSKWAJC_COMP_XOR, #MSKWAJ_COMP_SZDD
|
||||
/// or #MSKWAJ_COMP_LZH. The default is #MSKWAJ_COMP_LZH.
|
||||
///
|
||||
/// - #MSKWAJC_PARAM_INCLUDE_LENGTH: a boolean; should the compressed
|
||||
/// output file should include the uncompressed length of the input
|
||||
/// file in the header? This adds 4 bytes to the size of the output
|
||||
/// file. A value of zero says "no", non-zero says "yes". The default
|
||||
/// is "no".
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Compressor
|
||||
/// instance being called
|
||||
/// </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>
|
||||
/// <see cref="Generate"/>
|
||||
public Func<Compressor, Parameters, int, Error> SetParam;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the original filename of the file before compression,
|
||||
/// which will be stored in the header of the output file.
|
||||
///
|
||||
/// The filename should be a null-terminated string, it must be an
|
||||
/// MS-DOS "8.3" type filename (up to 8 bytes for the filename, then
|
||||
/// optionally a "." and up to 3 bytes for a filename extension).
|
||||
///
|
||||
/// If NULL is passed as the filename, no filename is included in the
|
||||
/// header. This is the default.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="filename">the original filename to use</param>
|
||||
/// <returns>
|
||||
/// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if the
|
||||
/// filename is too long
|
||||
/// </returns>
|
||||
public Func<Compressor, string, Error> SetFilename;
|
||||
|
||||
/// <summary>
|
||||
/// Sets arbitrary data that will be stored in the header of the
|
||||
/// output file, uncompressed. It can be up to roughly 64 kilobytes,
|
||||
/// as the overall size of the header must not exceed 65535 bytes.
|
||||
/// The data can contain null bytes if desired.
|
||||
///
|
||||
/// If NULL is passed as the data pointer, or zero is passed as the
|
||||
/// length, no extra data is included in the header. This is the
|
||||
/// default.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="data">a pointer to the data to be stored in the header</param>
|
||||
/// <param name="bytes">the length of the data in bytes</param>
|
||||
/// <returns>
|
||||
/// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS extra data
|
||||
/// is too long
|
||||
/// </returns>
|
||||
public Func<Compressor, byte[], int, int, Error> SetExtraData;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the Compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="Compress"/>
|
||||
public Func<Compressor, Error> LastError;
|
||||
}
|
||||
}
|
||||
25
BurnOutSharp/External/libmspack/KWAJ/CompressorImpl.cs
vendored
Normal file
25
BurnOutSharp/External/libmspack/KWAJ/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/* 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; }
|
||||
}
|
||||
}
|
||||
126
BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs
vendored
Normal file
126
BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
/// <summary>
|
||||
/// A decompressor for KWAJ compressed files.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateKWAJDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyKWAJDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a KWAJ file and reads the header.
|
||||
///
|
||||
/// If the file opened is a valid KWAJ file, all headers will be read and
|
||||
/// a mskwajd_header structure will be returned.
|
||||
///
|
||||
/// In the case of an error occuring, NULL is returned and the error code
|
||||
/// is available from last_error().
|
||||
///
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened KWAJ file.
|
||||
///
|
||||
/// This closes a KWAJ file and frees the mskwajd_header associated
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the compressed data from a KWAJ file.
|
||||
///
|
||||
/// 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="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;
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an KWAJ file to an output file in one step.
|
||||
///
|
||||
/// This opens an KWAJ file as input, reads the header, then decompresses
|
||||
/// the compressed data immediately to an output file, finally closing
|
||||
/// both the input and output file. It is more convenient to use than
|
||||
/// open() then extract() then close(), if you do not need to know the
|
||||
/// KWAJ output size or output filename.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the mskwaj_decompressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// the filename of the input KWAJ file. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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;
|
||||
|
||||
/// <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.
|
||||
/// </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;
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/KWAJ/DecompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/KWAJ/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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; }
|
||||
}
|
||||
}
|
||||
88
BurnOutSharp/External/libmspack/KWAJ/Enums.cs
vendored
Normal file
88
BurnOutSharp/External/libmspack/KWAJ/Enums.cs
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
public enum CompressionType
|
||||
{
|
||||
/// <summary>
|
||||
/// no compression.
|
||||
/// </summary>
|
||||
MSKWAJ_COMP_NONE = 0,
|
||||
|
||||
/// <summary>
|
||||
/// no compression, 0xFF XOR "encryption".
|
||||
/// </summary>
|
||||
MSKWAJ_COMP_XOR = 1,
|
||||
|
||||
/// <summary>
|
||||
/// LZSS (same method as SZDD)
|
||||
/// </summary>
|
||||
MSKWAJ_COMP_SZDD = 2,
|
||||
|
||||
/// <summary>
|
||||
/// LZ+Huffman compression
|
||||
/// </summary>
|
||||
MSKWAJ_COMP_LZH = 3,
|
||||
|
||||
/// <summary>
|
||||
/// MSZIP
|
||||
/// </summary>
|
||||
MSKWAJ_COMP_MSZIP = 4,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum OptionalHeaderFlag : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// decompressed file length is included
|
||||
/// </summary>
|
||||
MSKWAJ_HDR_HASLENGTH = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// unknown 2-byte structure is included
|
||||
/// </summary>
|
||||
MSKWAJ_HDR_HASUNKNOWN1 = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// unknown multi-sized structure is included
|
||||
/// </summary>
|
||||
MSKWAJ_HDR_HASUNKNOWN2 = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// file name (no extension) is included
|
||||
/// </summary>
|
||||
MSKWAJ_HDR_HASFILENAME = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// file extension is included
|
||||
/// </summary>
|
||||
MSKWAJ_HDR_HASFILEEXT = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// extra text is included
|
||||
/// </summary>
|
||||
MSKWAJ_HDR_HASEXTRATEXT = 0x20,
|
||||
}
|
||||
|
||||
public enum Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Compression type
|
||||
/// </summary>
|
||||
MSKWAJC_PARAM_COMP_TYPE = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Include the length of the uncompressed file in the header?
|
||||
/// </summary>
|
||||
MSKWAJC_PARAM_INCLUDE_LENGTH = 1,
|
||||
}
|
||||
}
|
||||
62
BurnOutSharp/External/libmspack/KWAJ/Header.cs
vendored
Normal file
62
BurnOutSharp/External/libmspack/KWAJ/Header.cs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents an KWAJ compressed file.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class Header
|
||||
{
|
||||
/// <summary>
|
||||
/// The compression type
|
||||
/// </summary>
|
||||
public CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The offset in the file where the compressed data stream begins
|
||||
/// </summary>
|
||||
public long DataOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags indicating which optional headers were included.
|
||||
/// </summary>
|
||||
public OptionalHeaderFlag Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of uncompressed data in the file, or 0 if not present.
|
||||
/// </summary>
|
||||
public long Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output filename, or NULL if not present
|
||||
/// </summary>
|
||||
public string Filename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra uncompressed data (usually text) in the header.
|
||||
/// This data can contain nulls so use extra_length to get the size.
|
||||
/// </summary>
|
||||
public string Extra { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of extra uncompressed data in the header
|
||||
/// </summary>
|
||||
public ushort ExtraLength { get; set; }
|
||||
}
|
||||
}
|
||||
16
BurnOutSharp/External/libmspack/KWAJ/HeaderImpl.cs
vendored
Normal file
16
BurnOutSharp/External/libmspack/KWAJ/HeaderImpl.cs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/* 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 HeaderImpl : Header
|
||||
{
|
||||
public object FileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
772
BurnOutSharp/External/libmspack/KWAJ/Implementation.cs
vendored
Normal file
772
BurnOutSharp/External/libmspack/KWAJ/Implementation.cs
vendored
Normal file
@@ -0,0 +1,772 @@
|
||||
/* 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;
|
||||
using System.Text;
|
||||
using LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
public class Implementation
|
||||
{
|
||||
#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 static int KWAJ_MATCHLEN1_TBLSIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if (KWAJ_TABLESIZE < (KWAJ_MATCHLEN1_SYMS * 2))
|
||||
return (KWAJ_MATCHLEN1_SYMS * 4);
|
||||
else
|
||||
return (KWAJ_TABLESIZE + (KWAJ_MATCHLEN1_SYMS * 2));
|
||||
}
|
||||
}
|
||||
|
||||
public static int KWAJ_MATCHLEN2_TBLSIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if (KWAJ_TABLESIZE < (KWAJ_MATCHLEN2_SYMS * 2))
|
||||
return (KWAJ_MATCHLEN2_SYMS * 4);
|
||||
else
|
||||
return (KWAJ_TABLESIZE + (KWAJ_MATCHLEN2_SYMS * 2));
|
||||
}
|
||||
}
|
||||
|
||||
public static int KWAJ_LITLEN_TBLSIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if (KWAJ_TABLESIZE < (KWAJ_LITLEN_SYMS * 2))
|
||||
return (KWAJ_LITLEN_SYMS * 4);
|
||||
else
|
||||
return (KWAJ_TABLESIZE + (KWAJ_LITLEN_SYMS * 2));
|
||||
}
|
||||
}
|
||||
|
||||
public static int KWAJ_OFFSET_TBLSIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if (KWAJ_TABLESIZE < (KWAJ_OFFSET_SYMS * 2))
|
||||
return (KWAJ_OFFSET_SYMS * 4);
|
||||
else
|
||||
return (KWAJ_TABLESIZE + (KWAJ_OFFSET_SYMS * 2));
|
||||
}
|
||||
}
|
||||
|
||||
public static int KWAJ_LITERAL_TBLSIZE
|
||||
{
|
||||
get
|
||||
{
|
||||
if (KWAJ_TABLESIZE < (KWAJ_LITERAL_SYMS * 2))
|
||||
return (KWAJ_LITERAL_SYMS * 4);
|
||||
else
|
||||
return (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 = (DecompressorImpl)d;
|
||||
if (self == null)
|
||||
return null;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
object fh = sys.Open(sys, 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);
|
||||
|
||||
sys.Free(hdr);
|
||||
hdr = null;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJD_CLOSE
|
||||
|
||||
/// <summary>
|
||||
/// Closes a KWAJ file
|
||||
/// </summary>
|
||||
public static void Close(Decompressor d, Header hdr)
|
||||
{
|
||||
DecompressorImpl self = (DecompressorImpl)d;
|
||||
HeaderImpl hdr_p = (HeaderImpl)hdr;
|
||||
|
||||
if (self == null || self.System == null)
|
||||
return;
|
||||
|
||||
// Close the file handle associated
|
||||
self.System.Close(hdr_p.FileHandle);
|
||||
|
||||
// Free the memory associated
|
||||
self.System.Free(hdr);
|
||||
|
||||
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, object 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 = (DecompressorImpl)d;
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
if (hdr == null)
|
||||
return self.Error = Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
object fh = ((HeaderImpl)hdr).FileHandle;
|
||||
|
||||
// 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
|
||||
object outfh;
|
||||
if ((outfh = sys.Open(sys, 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;
|
||||
|
||||
sys.Free(buf);
|
||||
}
|
||||
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)
|
||||
{
|
||||
InternalStream lzh = LZHInit(sys, fh, outfh);
|
||||
self.Error = (lzh != null) ? LZHDecompress(lzh) : Error.MSPACK_ERR_NOMEMORY;
|
||||
LZHFree(lzh);
|
||||
}
|
||||
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;
|
||||
MSZIP.Free(zip);
|
||||
}
|
||||
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 = (DecompressorImpl)d;
|
||||
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 = (DecompressorImpl)d;
|
||||
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 InternalStream LZHInit(SystemImpl sys, object input, object output)
|
||||
{
|
||||
if (sys == null || input == null || output == null)
|
||||
return null;
|
||||
|
||||
return new InternalStream()
|
||||
{
|
||||
Sys = sys,
|
||||
Input = input,
|
||||
Output = output,
|
||||
};
|
||||
}
|
||||
|
||||
private static Error LZHDecompress(InternalStream lzh)
|
||||
{
|
||||
uint bit_buffer = 0, bits_left = 0, len = 0, j = 0;
|
||||
int i;
|
||||
ushort sym = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
bool lit_run = false;
|
||||
int pos = 0, offset;
|
||||
int[] types = new int[6];
|
||||
|
||||
// Reset global state
|
||||
lzh.INIT_BITS();
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
for (i = 0; i < LZSS.LZSS_WINDOW_SIZE; i++)
|
||||
{
|
||||
lzh.Window[i] = LZSS.LZSS_WINDOW_FILL;
|
||||
}
|
||||
|
||||
// Read 6 encoding types (for byte alignment) but only 5 are needed
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref types[i], 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
// Read huffman table symbol lengths and build huffman trees
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
Error err = LZHReadLens(lzh, (uint)types[0], KWAJ_MATCHLEN1_SYMS, lzh.MATCHLEN1_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (InternalStream.MakeDecodeTable(KWAJ_MATCHLEN1_SYMS, (uint)KWAJ_MATCHLEN1_TBLSIZE, lzh.MATCHLEN1_len, lzh.MATCHLEN1_table) != 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
err = LZHReadLens(lzh, (uint)types[1], KWAJ_MATCHLEN2_SYMS, lzh.MATCHLEN2_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (InternalStream.MakeDecodeTable(KWAJ_MATCHLEN2_SYMS, (uint)KWAJ_MATCHLEN2_TBLSIZE, lzh.MATCHLEN2_len, lzh.MATCHLEN2_table) != 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
err = LZHReadLens(lzh, (uint)types[2], KWAJ_LITLEN_SYMS, lzh.LITLEN_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (InternalStream.MakeDecodeTable(KWAJ_LITLEN_SYMS, (uint)KWAJ_LITLEN_TBLSIZE, lzh.LITLEN_len, lzh.LITLEN_table) != 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
err = LZHReadLens(lzh, (uint)types[3], KWAJ_OFFSET_SYMS, lzh.OFFSET_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (InternalStream.MakeDecodeTable(KWAJ_OFFSET_SYMS, (uint)KWAJ_OFFSET_TBLSIZE, lzh.OFFSET_len, lzh.OFFSET_table) != 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
err = LZHReadLens(lzh, (uint)types[4], KWAJ_LITERAL_SYMS, lzh.LITERAL_len);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (InternalStream.MakeDecodeTable(KWAJ_LITERAL_SYMS, (uint)KWAJ_LITERAL_TBLSIZE, lzh.LITERAL_len, lzh.LITERAL_table) != 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
while (lzh.InputEnd == 0)
|
||||
{
|
||||
if (lit_run)
|
||||
{
|
||||
//READ_HUFFSYM_SAFE(tbl, val)
|
||||
lzh.READ_HUFFSYM(lzh.MATCHLEN2_table, ref len, KWAJ_MATCHLEN2_TBLSIZE, lzh.MATCHLEN2_len, KWAJ_MATCHLEN2_SYMS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
//READ_HUFFSYM_SAFE(tbl, val)
|
||||
lzh.READ_HUFFSYM(lzh.MATCHLEN1_table, ref len, KWAJ_MATCHLEN1_TBLSIZE, lzh.MATCHLEN1_len, KWAJ_MATCHLEN1_SYMS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
len += 2;
|
||||
lit_run = false; // Not the end of a literal run
|
||||
|
||||
//READ_HUFFSYM_SAFE(tbl, val)
|
||||
lzh.READ_HUFFSYM(lzh.OFFSET_table, ref j, KWAJ_OFFSET_TBLSIZE, lzh.OFFSET_len, KWAJ_OFFSET_SYMS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
offset = (int)(j << 6);
|
||||
|
||||
//READ_BITS_SAFE(val, n)
|
||||
int tempj = (int)j;
|
||||
lzh.READ_BITS(ref tempj, 6, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
j = (uint)tempj;
|
||||
offset |= tempj;
|
||||
|
||||
// Copy match as output and into the ring buffer
|
||||
while (len-- > 0)
|
||||
{
|
||||
lzh.Window[pos] = lzh.Window[(pos + 4096 - offset) & 4095];
|
||||
if (lzh.Sys.Write(lzh.Output, lzh.Window, pos, 1) != 1)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
|
||||
pos++; pos &= 4095;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//READ_HUFFSYM_SAFE(tbl, val)
|
||||
lzh.READ_HUFFSYM(lzh.LITLEN_table, ref len, KWAJ_LITLEN_TBLSIZE, lzh.LITLEN_len, KWAJ_LITLEN_SYMS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
len++;
|
||||
|
||||
lit_run = (len == 32) ? false : true; // End of a literal run?
|
||||
while (len-- > 0)
|
||||
{
|
||||
//READ_HUFFSYM_SAFE(tbl, val)
|
||||
lzh.READ_HUFFSYM(lzh.LITERAL_table, ref j, KWAJ_LITERAL_TBLSIZE, lzh.LITERAL_len, KWAJ_LITERAL_SYMS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
// Copy as output and into the ring buffer
|
||||
lzh.Window[pos] = (byte)j;
|
||||
if (lzh.Sys.Write(lzh.Output, lzh.Window, pos, 1) != 1)
|
||||
return Error.MSPACK_ERR_WRITE;
|
||||
|
||||
pos++;
|
||||
pos &= 4095;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private static void LZHFree(InternalStream lzh)
|
||||
{
|
||||
if (lzh == null || lzh.Sys == null)
|
||||
return;
|
||||
|
||||
SystemImpl sys = lzh.Sys;
|
||||
sys.Free(lzh);
|
||||
}
|
||||
|
||||
public static Error LZHReadLens(InternalStream lzh, uint type, uint numsyms, byte[] lens)
|
||||
{
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
uint i;
|
||||
int c = 0, sel = 0;
|
||||
|
||||
lzh.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
i = numsyms;
|
||||
c = (i == 16) ? 4 : (i == 32) ? 5 : (i == 64) ? 6 : (i == 256) ? 8 : 0;
|
||||
for (i = 0; i < numsyms; i++)
|
||||
{
|
||||
lens[i] = (byte)c;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
lens[0] = (byte)c;
|
||||
for (i = 1; i < numsyms; i++)
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
if (sel == 0)
|
||||
{
|
||||
lens[i] = (byte)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
if (sel == 0)
|
||||
{
|
||||
lens[i] = (byte)++c;
|
||||
}
|
||||
else
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
lens[i] = (byte)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
lens[0] = (byte)c;
|
||||
for (i = 1; i < numsyms; i++)
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref sel, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
if (sel == 3)
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
c += (char)sel - 1;
|
||||
}
|
||||
|
||||
lens[i] = (byte)c;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
for (i = 0; i < numsyms; i++)
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
lens[i] = (byte)c;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
lzh.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public static Error LZHReadInput(InternalStream lzh)
|
||||
{
|
||||
int read;
|
||||
if (lzh.InputEnd != 0)
|
||||
{
|
||||
lzh.InputEnd += 8;
|
||||
lzh.InputBuffer[0] = 0;
|
||||
read = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
read = lzh.Sys.Read(lzh.Input, lzh.InputBuffer, 0, KWAJ_INPUT_SIZE);
|
||||
if (read < 0)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (read == 0)
|
||||
{
|
||||
lzh.InputLength = 8;
|
||||
lzh.InputBuffer[0] = 0;
|
||||
read = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update InputPointer and InputLength
|
||||
lzh.InputPointer = 0;
|
||||
lzh.InputLength = read;
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
54
BurnOutSharp/External/libmspack/KWAJ/InternalStream.cs
vendored
Normal file
54
BurnOutSharp/External/libmspack/KWAJ/InternalStream.cs
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
public class InternalStream : 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];
|
||||
|
||||
// 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];
|
||||
|
||||
// History window
|
||||
|
||||
public byte[] Window { get; set; } = new byte[LZSS.LZSS_WINDOW_SIZE];
|
||||
|
||||
public override Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
{
|
||||
Error error = Error.MSPACK_ERR_OK;
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((error = Implementation.LZHReadInput(this)) != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
|
||||
i_ptr = InputPointer;
|
||||
i_end = InputLength;
|
||||
}
|
||||
|
||||
INJECT_BITS(InputBuffer[i_ptr++], 8, ref bitsLeft, ref bitBuffer);
|
||||
return error;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
}
|
||||
24
BurnOutSharp/External/libmspack/LIT/Compressor.cs
vendored
Normal file
24
BurnOutSharp/External/libmspack/LIT/Compressor.cs
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.LIT
|
||||
{
|
||||
// TODO
|
||||
public class Compressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/LIT/CompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/LIT/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
24
BurnOutSharp/External/libmspack/LIT/Decompressor.cs
vendored
Normal file
24
BurnOutSharp/External/libmspack/LIT/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.LIT
|
||||
{
|
||||
// TODO
|
||||
public class Decompressor
|
||||
{
|
||||
public int Dummy { get; set; }
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/LIT/DecompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/LIT/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
15
BurnOutSharp/External/libmspack/LIT/Implementation.cs
vendored
Normal file
15
BurnOutSharp/External/libmspack/LIT/Implementation.cs
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/* 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
|
||||
{
|
||||
}
|
||||
}
|
||||
564
BurnOutSharp/External/libmspack/Library.cs
vendored
Normal file
564
BurnOutSharp/External/libmspack/Library.cs
vendored
Normal file
@@ -0,0 +1,564 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/** \mainpage
|
||||
*
|
||||
* \section intro Introduction
|
||||
*
|
||||
* libmspack is a library which provides compressors and decompressors,
|
||||
* archivers and dearchivers for Microsoft compression formats.
|
||||
*
|
||||
* \section formats Formats supported
|
||||
*
|
||||
* The following file formats are supported:
|
||||
* - SZDD files, which use LZSS compression
|
||||
* - KWAJ files, which use LZSS, LZSS+Huffman or deflate compression
|
||||
* - .HLP (MS Help) files, which use LZSS compression
|
||||
* - .CAB (MS Cabinet) files, which use deflate, LZX or Quantum compression
|
||||
* - .CHM (HTML Help) files, which use LZX compression
|
||||
* - .LIT (MS EBook) files, which use LZX compression and DES encryption
|
||||
* - .LZX (Exchange Offline Addressbook) files, which use LZX compression
|
||||
*
|
||||
* To determine the capabilities of the library, and the binary
|
||||
* compatibility version of any particular compressor or decompressor, use
|
||||
* the mspack_version() function. The UNIX library interface version is
|
||||
* defined as the highest-versioned library component.
|
||||
*
|
||||
* \section starting Getting started
|
||||
*
|
||||
* The macro MSPACK_SYS_SELFTEST() should be used to ensure the library can
|
||||
* be used. In particular, it checks if the caller is using 32-bit file I/O
|
||||
* when the library is compiled for 64-bit file I/O and vice versa.
|
||||
*
|
||||
* If compiled normally, the library includes basic file I/O and memory
|
||||
* management functionality using the standard C library. This can be
|
||||
* customised and replaced entirely by creating a SystemImpl structure.
|
||||
*
|
||||
* A compressor or decompressor for the required format must be
|
||||
* instantiated before it can be used. Each construction function takes
|
||||
* one parameter, which is either a pointer to a custom SystemImpl
|
||||
* structure, or null to use the default. The instantiation returned, if
|
||||
* not null, contains function pointers (methods) to work with the given
|
||||
* file format.
|
||||
*
|
||||
* For compression:
|
||||
* - CreateCABCompressor() creates a mscab_compressor
|
||||
* - CreateCHMCompressor() creates a mschm_compressor
|
||||
* - CreateLITCompressor() creates a mslit_compressor
|
||||
* - CreateHLPCompressor() creates a mshlp_compressor
|
||||
* - CreateSZDDCompressor() creates a msszdd_compressor
|
||||
* - CreateKWAJCompressor() creates a mskwaj_compressor
|
||||
* - CreateOABCompressor() creates a msoab_compressor
|
||||
*
|
||||
* For decompression:
|
||||
* - mspack_create_cab_decompressor() creates a mscab_decompressor
|
||||
* - mspack_create_chm_decompressor() creates a mschm_decompressor
|
||||
* - mspack_create_lit_decompressor() creates a mslit_decompressor
|
||||
* - mspack_create_hlp_decompressor() creates a mshlp_decompressor
|
||||
* - mspack_create_szdd_decompressor() creates a msszdd_decompressor
|
||||
* - mspack_create_kwaj_decompressor() creates a mskwaj_decompressor
|
||||
* - mspack_create_oab_decompressor() creates a msoab_decompressor
|
||||
*
|
||||
* Once finished working with a format, each kind of
|
||||
* compressor/decompressor has its own specific destructor:
|
||||
* - mspack_destroy_cab_compressor()
|
||||
* - mspack_destroy_cab_decompressor()
|
||||
* - mspack_destroy_chm_compressor()
|
||||
* - mspack_destroy_chm_decompressor()
|
||||
* - mspack_destroy_lit_compressor()
|
||||
* - mspack_destroy_lit_decompressor()
|
||||
* - mspack_destroy_hlp_compressor()
|
||||
* - mspack_destroy_hlp_decompressor()
|
||||
* - mspack_destroy_szdd_compressor()
|
||||
* - mspack_destroy_szdd_decompressor()
|
||||
* - mspack_destroy_kwaj_compressor()
|
||||
* - mspack_destroy_kwaj_decompressor()
|
||||
* - mspack_destroy_oab_compressor()
|
||||
* - mspack_destroy_oab_decompressor()
|
||||
*
|
||||
* Destroying a compressor or decompressor does not destroy any objects,
|
||||
* structures or handles that have been created using that compressor or
|
||||
* decompressor. Ensure that everything created or opened is destroyed or
|
||||
* closed before compressor/decompressor is itself destroyed.
|
||||
*
|
||||
* \section threading Multi-threading
|
||||
*
|
||||
* libmspack methods are reentrant and multithreading-safe when each
|
||||
* thread has its own compressor or decompressor.
|
||||
* You should not call multiple methods simultaneously on a single
|
||||
* compressor or decompressor instance.
|
||||
*
|
||||
* If this may happen, you can either use one compressor or
|
||||
* decompressor per thread, or you can use your preferred lock,
|
||||
* semaphore or mutex library to ensure no more than one method on a
|
||||
* compressor/decompressor is called simultaneously. libmspack will
|
||||
* not do this locking for you.
|
||||
*
|
||||
* Example of incorrect behaviour:
|
||||
* - thread 1 calls mspack_create_cab_decompressor()
|
||||
* - thread 1 calls open()
|
||||
* - thread 1 calls extract() for one file
|
||||
* - thread 2 simultaneously calls extract() for another file
|
||||
*
|
||||
* Correct behaviour:
|
||||
* - thread 1 calls mspack_create_cab_decompressor()
|
||||
* - thread 2 calls mspack_create_cab_decompressor()
|
||||
* - thread 1 calls its own open() / extract()
|
||||
* - thread 2 simultaneously calls its own open() / extract()
|
||||
*
|
||||
* Also correct behaviour:
|
||||
* - thread 1 calls mspack_create_cab_decompressor()
|
||||
* - thread 1 locks a mutex for with the decompressor before
|
||||
* calling any methods on it, and unlocks the mutex after each
|
||||
* method returns.
|
||||
* - thread 1 can share the results of open() with thread 2, and both
|
||||
* can call extract(), provided they both guard against simultaneous
|
||||
* use of extract(), and any other methods, with the mutex
|
||||
*/
|
||||
|
||||
using LibMSPackSharp.Compression;
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
public partial class Library
|
||||
{
|
||||
#region CAB
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CAB compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="CAB.Compressor"/> or null</returns>
|
||||
public CAB.Compressor CreateCABCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CAB decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="CAB.Decompressor"/> or null</returns>
|
||||
public CAB.Decompressor CreateCABDecompressor(SystemImpl sys)
|
||||
{
|
||||
if (sys == null)
|
||||
sys = SystemImpl.DefaultSystem;
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new CAB.DecompressorImpl()
|
||||
{
|
||||
Open = CAB.Implementation.Open,
|
||||
Close = CAB.Implementation.Close,
|
||||
Search = CAB.Implementation.Search,
|
||||
Extract = CAB.Implementation.Extract,
|
||||
Prepend = CAB.Implementation.Prepend,
|
||||
Append = CAB.Implementation.Append,
|
||||
SetParam = CAB.Implementation.Param,
|
||||
LastError = CAB.Implementation.LastError,
|
||||
System = sys,
|
||||
State = null,
|
||||
Error = Error.MSPACK_ERR_OK,
|
||||
|
||||
SearchBufferSize = 32768,
|
||||
FixMSZip = false,
|
||||
BufferSize = 4096,
|
||||
Salvage = false,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing CAB compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="CAB.Compressor"/> to destroy</param>
|
||||
public void DestroyCABCompressor(CAB.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing CAB decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="CAB.Decompressor"/> to destroy</param>
|
||||
public void DestroyCABDecompressor(CAB.Decompressor d)
|
||||
{
|
||||
CAB.DecompressorImpl self = (CAB.DecompressorImpl)d;
|
||||
if (self != null)
|
||||
{
|
||||
SystemImpl sys = self.System;
|
||||
if (self.State != null)
|
||||
{
|
||||
if (self.State.InputFileHandle != null)
|
||||
sys.Close(self.State.InputFileHandle);
|
||||
|
||||
CAB.Implementation.FreeDecompressionState(self);
|
||||
sys.Free(self.State);
|
||||
}
|
||||
|
||||
sys.Free(self);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CHM
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CHM compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="CHM.Compressor"/> or null</returns>
|
||||
public CHM.Compressor CreateCHMCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CHM decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="CHM.Decompressor"/> or null</returns>
|
||||
public CHM.Decompressor CreateCHMDecompressor(SystemImpl sys)
|
||||
{
|
||||
if (sys == null)
|
||||
sys = SystemImpl.DefaultSystem;
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new CHM.DecompressorImpl()
|
||||
{
|
||||
Open = CHM.Implementation.Open,
|
||||
Close = CHM.Implementation.Close,
|
||||
Extract = CHM.Implementation.Extract,
|
||||
LastError = CHM.Implementation.LastError,
|
||||
FastOpen = CHM.Implementation.FastOpen,
|
||||
FastFind = CHM.Implementation.FastFind,
|
||||
System = sys,
|
||||
Error = Error.MSPACK_ERR_OK,
|
||||
State = null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing CHM compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="CHM.Compressor"/> to destroy</param>
|
||||
public void DestroyCHMCompressor(CHM.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing CHM decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="CHM.Decompressor"/> to destroy</param>
|
||||
public void DestroyCHMDecompressor(CHM.Decompressor d)
|
||||
{
|
||||
CHM.DecompressorImpl self = (CHM.DecompressorImpl)d;
|
||||
if (self != null)
|
||||
{
|
||||
SystemImpl sys = self.System;
|
||||
if (self.State != null)
|
||||
{
|
||||
if (self.State.InputFileHandle != null)
|
||||
sys.Close(self.State.InputFileHandle);
|
||||
|
||||
if (self.State.State != null)
|
||||
LZX.Free(self.State.State);
|
||||
|
||||
sys.Free(self.State);
|
||||
}
|
||||
sys.Free(self);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LIT
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LIT compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="LIT.Compressor"/> or null</returns>
|
||||
public LIT.Compressor CreateLITCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LIT decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="LIT.Decompressor"/> or null</returns>
|
||||
public LIT.Decompressor CreateLITDecompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing LIT compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="LIT.Compressor"/> to destroy</param>
|
||||
public void DestroyLITCompressor(LIT.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing LIT decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="LIT.Decompressor"/> to destroy</param>
|
||||
public void DestroyLITDecompressor(LIT.Decompressor d)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HLP
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new HLP compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="HLP.Compressor"/> or null</returns>
|
||||
public HLP.Compressor CreateHLPCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new HLP decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="HLP.Decompressor"/> or null</returns>
|
||||
public HLP.Decompressor CreateHLPDecompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing HLP compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="HLP.Compressor"/> to destroy</param>
|
||||
public void DestroyHLPCompressor(HLP.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing HLP decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="HLP.Decompressor"/> to destroy</param>
|
||||
public void DestroyHLPDecompressor(HLP.Decompressor d)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDD
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SZDD compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="SZDD.Compressor"/> or null</returns>
|
||||
public SZDD.Compressor CreateSZDDCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SZDD decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="SZDD.Decompressor"/> or null</returns>
|
||||
public SZDD.Decompressor CreateSZDDDecompressor(SystemImpl sys)
|
||||
{
|
||||
if (sys == null)
|
||||
sys = SystemImpl.DefaultSystem;
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new SZDD.DecompressorImpl()
|
||||
{
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing SZDD compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="SZDD.Compressor"/> to destroy</param>
|
||||
public void DestroySZDDCompressor(SZDD.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing SZDD decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="SZDD.Decompressor"/> to destroy</param>
|
||||
public void DestroySZDDDecompressor(SZDD.Decompressor d)
|
||||
{
|
||||
SZDD.DecompressorImpl self = (SZDD.DecompressorImpl)d;
|
||||
if (self != null)
|
||||
{
|
||||
SystemImpl sys = self.System;
|
||||
sys.Free(self);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region KWAJ
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new KWAJ compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="KWAJ.Compressor"/> or null</returns>
|
||||
public KWAJ.Compressor CreateKWAJCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new KWAJ decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="KWAJ.Decompressor"/> or null</returns>
|
||||
public KWAJ.Decompressor CreateKWAJDecompressor(SystemImpl sys)
|
||||
{
|
||||
if (sys == null)
|
||||
sys = SystemImpl.DefaultSystem;
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new KWAJ.DecompressorImpl()
|
||||
{
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing KWAJ compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="KWAJ.Compressor"/> to destroy</param>
|
||||
public void DestroyKWAJCompressor(KWAJ.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing KWAJ decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="KWAJ.Decompressor"/> to destroy</param>
|
||||
public void DestroyKWAJDecompressor(KWAJ.Decompressor d)
|
||||
{
|
||||
KWAJ.DecompressorImpl self = (KWAJ.DecompressorImpl)d;
|
||||
if (self != null)
|
||||
{
|
||||
SystemImpl sys = self.System;
|
||||
sys.Free(self);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OAB
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new OAB compressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="OAB.Compressor"/> or null</returns>
|
||||
public OAB.Compressor CreateOABCompressor(SystemImpl sys)
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new OAB decompressor.
|
||||
/// </summary>
|
||||
/// <param name="sys">a custom SystemImpl structure, or null to use the default</param>
|
||||
/// <returns>a <see cref="OAB.Decompressor"/> or null</returns>
|
||||
public OAB.Decompressor CreateOABDecompressor(SystemImpl sys)
|
||||
{
|
||||
if (sys == null)
|
||||
sys = SystemImpl.DefaultSystem;
|
||||
if (!SystemImpl.ValidSystem(sys))
|
||||
return null;
|
||||
|
||||
return new OAB.DecompressorImpl()
|
||||
{
|
||||
Decompress = OAB.Implementation.Decompress,
|
||||
DecompressIncremental = OAB.Implementation.DecompressIncremental,
|
||||
SetParam = OAB.Implementation.Param,
|
||||
System = sys,
|
||||
BufferSize = 4096,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing OAB compressor.
|
||||
/// </summary>
|
||||
/// <param name="c">the <see cref="OAB.Compressor"/> to destroy</param>
|
||||
public void DestroyOABCompressor(OAB.Compressor c)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an existing OAB decompressor.
|
||||
/// </summary>
|
||||
/// <param name="d">the <see cref="OAB.Decompressor"/> to destroy</param>
|
||||
public void DestroyOABDecompressor(OAB.Decompressor d)
|
||||
{
|
||||
OAB.DecompressorImpl self = (OAB.DecompressorImpl)d;
|
||||
if (self != null)
|
||||
{
|
||||
SystemImpl sys = self.System;
|
||||
sys.Free(self);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
80
BurnOutSharp/External/libmspack/OAB/Compressor.cs
vendored
Normal file
80
BurnOutSharp/External/libmspack/OAB/Compressor.cs
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
/// <summary>
|
||||
/// A compressor for the Offline Address Book (OAB) format.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateOABCompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyOABCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Compress a full OAB file.
|
||||
///
|
||||
/// The input file will be read and the compressed contents 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
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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<Compressor, string, string, Error> Compress;
|
||||
|
||||
/// <summary>
|
||||
/// Generate a compressed incremental OAB patch file.
|
||||
///
|
||||
/// The two uncompressed files "input" and "base" will be read, and an
|
||||
/// incremental patch to generate "input" from "base" 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 containing the new
|
||||
/// version of its contents. This is passed directly
|
||||
/// to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="base">
|
||||
/// the filename of the original base file containing
|
||||
/// the old version of its contents, against which the
|
||||
/// incremental patch shall generated. This is passed
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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<Compressor, string, string, string, Error> CompressIncremental;
|
||||
}
|
||||
}
|
||||
16
BurnOutSharp/External/libmspack/OAB/CompressorImpl.cs
vendored
Normal file
16
BurnOutSharp/External/libmspack/OAB/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/* 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; }
|
||||
}
|
||||
}
|
||||
106
BurnOutSharp/External/libmspack/OAB/Decompressor.cs
vendored
Normal file
106
BurnOutSharp/External/libmspack/OAB/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
/// <summary>
|
||||
/// A decompressor for .LZX (Offline Address Book) files
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateOABDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroyOABDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Decompresses a full Offline Address Book file.
|
||||
///
|
||||
/// If the input file is a valid compressed Offline Address Book file,
|
||||
/// 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
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an Offline Address Book with an incremental patch file.
|
||||
///
|
||||
/// This requires both a full UNCOMPRESSED Offline Address Book file to
|
||||
/// act as the "base", and a compressed incremental patch file as input.
|
||||
/// If the input file is valid, it will be decompressed with reference to
|
||||
/// the base file, and the decompressed contents will be written to the
|
||||
/// output file.
|
||||
///
|
||||
/// There is no way to tell what the right base file is for the given
|
||||
/// incremental patch, but if you get it wrong, this will usually result
|
||||
/// 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
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="base">
|
||||
/// 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
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Sets an OAB decompression engine parameter. Available only in OAB
|
||||
/// decompressor version 2 and above.
|
||||
///
|
||||
/// - #MSOABD_PARAM_DECOMPBUF: How many bytes should be used as an input
|
||||
/// 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>
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
20
BurnOutSharp/External/libmspack/OAB/DecompressorImpl.cs
vendored
Normal file
20
BurnOutSharp/External/libmspack/OAB/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
19
BurnOutSharp/External/libmspack/OAB/Enums.cs
vendored
Normal file
19
BurnOutSharp/External/libmspack/OAB/Enums.cs
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
public enum Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of decompression buffer
|
||||
/// </summary>
|
||||
MSOABD_PARAM_DECOMPBUF = 0,
|
||||
}
|
||||
}
|
||||
620
BurnOutSharp/External/libmspack/OAB/Implementation.cs
vendored
Normal file
620
BurnOutSharp/External/libmspack/OAB/Implementation.cs
vendored
Normal file
@@ -0,0 +1,620 @@
|
||||
/* 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 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 = (InternalFile)baseFile;
|
||||
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)
|
||||
{
|
||||
InternalFile file = (InternalFile)baseFile;
|
||||
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;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_DECOMPRESS
|
||||
|
||||
public static Error Decompress(Decompressor d, string input, string output)
|
||||
{
|
||||
DecompressorImpl self = (DecompressorImpl)d;
|
||||
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;
|
||||
|
||||
object infh = sys.Open(sys, input, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sys.Read(infh, hdrbuf, 0, oabhead_SIZEOF) != oabhead_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (BitConverter.ToUInt32(hdrbuf, oabhead_VersionHi) != 3 ||
|
||||
BitConverter.ToUInt32(hdrbuf, oabhead_VersionLo) != 1)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_SIGNATURE;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint block_max = BitConverter.ToUInt32(hdrbuf, oabhead_BlockMax);
|
||||
uint target_size = BitConverter.ToUInt32(hdrbuf, oabhead_TargetSize);
|
||||
|
||||
object outfh = sys.Open(sys, output, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
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;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
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;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (blk_flags == 0)
|
||||
{
|
||||
// Uncompressed block
|
||||
if (blk_dsize != blk_csize)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_DATAFORMAT;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = CopyFileHandle(sys, infh, outfh, (int)blk_dsize, buf, self.BufferSize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
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, out_ofh, window_bits, 0, self.BufferSize, blk_dsize, true);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_NOMEMORY;
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.Decompress(lzx, blk_dsize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LZX.Free(lzx);
|
||||
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)
|
||||
{
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_ofh.CRC != blk_crc)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_CHECKSUM;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
target_size -= blk_dsize;
|
||||
}
|
||||
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region OABD_DECOMPRESS_INCREMENTAL
|
||||
|
||||
public static Error DecompressIncremental(Decompressor d, string input, string basePath, string output)
|
||||
{
|
||||
DecompressorImpl self = (DecompressorImpl)d;
|
||||
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;
|
||||
|
||||
object infh = sys.Open(sys, input, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (infh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sys.Read(infh, hdrbuf, 0, patchhead_SIZEOF) != patchhead_SIZEOF)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_READ;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (BitConverter.ToUInt32(hdrbuf, patchhead_VersionHi) != 3 ||
|
||||
BitConverter.ToUInt32(hdrbuf, patchhead_VersionLo) != 2)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_SIGNATURE;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (infh != null)
|
||||
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;
|
||||
|
||||
object basefh = sys.Open(sys, basePath, OpenMode.MSPACK_SYS_OPEN_READ);
|
||||
if (basefh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
object outfh = sys.Open(sys, output, OpenMode.MSPACK_SYS_OPEN_WRITE);
|
||||
if (outfh == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_OPEN;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
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;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
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;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
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, out_ofh, window_bits, 0, 4096, blk_dsize, true);
|
||||
if (lzx == null)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_NOMEMORY;
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.SetReferenceData(lzx, sys, basefh, blk_ssize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = LZX.Decompress(lzx, blk_dsize);
|
||||
if (ret != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LZX.Free(lzx);
|
||||
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)
|
||||
{
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (out_ofh.CRC != blk_crc)
|
||||
{
|
||||
ret = Error.MSPACK_ERR_CHECKSUM;
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
target_size -= blk_dsize;
|
||||
}
|
||||
|
||||
if (lzx != null)
|
||||
LZX.Free(lzx);
|
||||
if (outfh != null)
|
||||
sys.Close(outfh);
|
||||
if (basefh != null)
|
||||
sys.Close(basefh);
|
||||
if (infh != null)
|
||||
sys.Close(infh);
|
||||
|
||||
sys.Free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Error CopyFileHandle(SystemImpl sys, object infh, object 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 = (DecompressorImpl)d;
|
||||
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
|
||||
}
|
||||
}
|
||||
29
BurnOutSharp/External/libmspack/OAB/InternalFile.cs
vendored
Normal file
29
BurnOutSharp/External/libmspack/OAB/InternalFile.cs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.OAB
|
||||
{
|
||||
public class InternalFile
|
||||
{
|
||||
public SystemImpl OrigSys { get; set; }
|
||||
|
||||
public object OrigFile { get; set; }
|
||||
|
||||
public uint CRC { get; set; }
|
||||
|
||||
public int Available { get; set; }
|
||||
}
|
||||
}
|
||||
110
BurnOutSharp/External/libmspack/SZDD/Compressor.cs
vendored
Normal file
110
BurnOutSharp/External/libmspack/SZDD/Compressor.cs
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
/// <summary>
|
||||
/// A compressor for the SZDD file format.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateSZDDCompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroySZDDCompressor(Compressor)"/>
|
||||
public class Compressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads an input file and creates a compressed output file in the
|
||||
/// SZDD compressed file format. The SZDD compression format is quick
|
||||
/// but gives poor compression. It is possible for the compressed output
|
||||
/// file to be larger than the input file.
|
||||
///
|
||||
/// Conventionally, SZDD compressed files have the final character in
|
||||
/// their filename replaced with an underscore, to show they are
|
||||
/// compressed. The missing character is stored in the compressed file
|
||||
/// itself. This is due to the restricted filename conventions of MS-DOS,
|
||||
/// most operating systems, such as UNIX, simply append another file
|
||||
/// extension to the existing filename. As mspack does not deal with
|
||||
/// filenames, this is left up to you. If you wish to set the missing
|
||||
/// character stored in the file header, use set_param() with the
|
||||
/// #MSSZDDC_PARAM_MISSINGCHAR parameter.
|
||||
///
|
||||
/// "Stream" compression (where the length of the input data is not
|
||||
/// known) is not possible. The length of the input data is stored in the
|
||||
/// header of the SZDD file and must therefore be known before any data
|
||||
/// is compressed. Due to technical limitations of the file format, the
|
||||
/// maximum size of uncompressed file that will be accepted is 2147483647
|
||||
/// bytes.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// the name of the file to compressed. This is passed
|
||||
/// passed directly to mspack_system::open()
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// the name of the file to write compressed data to.
|
||||
/// This is passed directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="length">
|
||||
/// the length of the uncompressed file, or -1 to indicate
|
||||
/// that this should be determined automatically by using
|
||||
/// mspack_system::seek() on the input file.
|
||||
/// </param>
|
||||
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
|
||||
/// <see cref="SetParam"/>
|
||||
public Func<Compressor, string, string, long, Error> Compress;
|
||||
|
||||
/// <summary>
|
||||
/// Sets an SZDD compression engine parameter.
|
||||
///
|
||||
/// The following parameters are defined:
|
||||
/// - #MSSZDDC_PARAM_CHARACTER: the "missing character", the last character
|
||||
/// in the uncompressed file's filename, which is traditionally replaced
|
||||
/// with an underscore to show the file is compressed. Traditionally,
|
||||
/// this can only be a character that is a valid part of an MS-DOS,
|
||||
/// filename, but libmspack permits any character between 0x00 and 0xFF
|
||||
/// to be stored. 0x00 is the default, and it represents "no character
|
||||
/// stored".
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_compressor
|
||||
/// instance being called
|
||||
/// </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>
|
||||
/// <see cref="Compress"/>
|
||||
public Func<Compressor, Parameters, int, Error> SetParam;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error code set by the most recently called method.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the msszdd_compressor
|
||||
/// instance being called
|
||||
/// </param>
|
||||
/// <returns>the most recent error code</returns>
|
||||
/// <see cref="Compress"/>
|
||||
public Func<Compressor, Error> LastError;
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/SZDD/CompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/SZDD/CompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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; }
|
||||
}
|
||||
}
|
||||
128
BurnOutSharp/External/libmspack/SZDD/Decompressor.cs
vendored
Normal file
128
BurnOutSharp/External/libmspack/SZDD/Decompressor.cs
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
/// <summary>
|
||||
/// A decompressor for SZDD compressed files.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
/// <see cref="Library.CreateSZDDDecompressor(SystemImpl)"/>
|
||||
/// <see cref="Library.DestroySZDDDecompressor(Decompressor)"/>
|
||||
public class Decompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a SZDD file and reads the header.
|
||||
///
|
||||
/// If the file opened is a valid SZDD file, all headers will be read and
|
||||
/// a msszddd_header structure will be returned.
|
||||
///
|
||||
/// In the case of an error occuring, NULL is returned and the error code
|
||||
/// is available from last_error().
|
||||
///
|
||||
/// 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
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened SZDD file.
|
||||
///
|
||||
/// This closes a SZDD file and frees the msszddd_header associated with
|
||||
/// it.
|
||||
///
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the compressed data from a SZDD file.
|
||||
///
|
||||
/// 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="filename">
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses an SZDD file to an output file in one step.
|
||||
///
|
||||
/// This opens an SZDD file as input, reads the header, then decompresses
|
||||
/// the compressed data immediately to an output file, finally closing
|
||||
/// both the input and output file. It is more convenient to use than
|
||||
/// 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
|
||||
/// directly to mspack_system::open().
|
||||
/// </param>
|
||||
/// <param name="output">
|
||||
/// 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;
|
||||
|
||||
/// <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.
|
||||
/// </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;
|
||||
}
|
||||
}
|
||||
18
BurnOutSharp/External/libmspack/SZDD/DecompressorImpl.cs
vendored
Normal file
18
BurnOutSharp/External/libmspack/SZDD/DecompressorImpl.cs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* 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; }
|
||||
}
|
||||
}
|
||||
32
BurnOutSharp/External/libmspack/SZDD/Enums.cs
vendored
Normal file
32
BurnOutSharp/External/libmspack/SZDD/Enums.cs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/* 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
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
public enum Format
|
||||
{
|
||||
/// <summary>
|
||||
/// a regular SZDD file
|
||||
/// </summary>
|
||||
MSSZDD_FMT_NORMAL = 0,
|
||||
|
||||
/// <summary>
|
||||
/// a special QBasic SZDD file
|
||||
/// </summary>
|
||||
MSSZDD_FMT_QBASIC = 1,
|
||||
}
|
||||
|
||||
public enum Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// The missing character
|
||||
/// </summary>
|
||||
MSSZDDC_PARAM_MISSINGCHAR = 0,
|
||||
}
|
||||
}
|
||||
45
BurnOutSharp/External/libmspack/SZDD/Header.cs
vendored
Normal file
45
BurnOutSharp/External/libmspack/SZDD/Header.cs
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.SZDD
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which represents an SZDD compressed file.
|
||||
///
|
||||
/// All fields are READ ONLY.
|
||||
/// </summary>
|
||||
public class Header
|
||||
{
|
||||
/// <summary>
|
||||
/// The file format
|
||||
/// </summary>
|
||||
public Format Format { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of data in the SZDD file once uncompressed.
|
||||
/// </summary>
|
||||
public long Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last character in the filename, traditionally replaced with an
|
||||
/// underscore to show the file is compressed. The null character is used
|
||||
/// to show that this character has not been stored (e.g. because the
|
||||
/// filename is not known). Generally, only characters that may appear in
|
||||
/// an MS-DOS filename (except ".") are valid.
|
||||
/// </summary>
|
||||
public char MissingChar { get; set; }
|
||||
}
|
||||
}
|
||||
16
BurnOutSharp/External/libmspack/SZDD/HeaderImpl.cs
vendored
Normal file
16
BurnOutSharp/External/libmspack/SZDD/HeaderImpl.cs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/* 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 HeaderImpl : Header
|
||||
{
|
||||
public object FileHandle { get; set; }
|
||||
}
|
||||
}
|
||||
226
BurnOutSharp/External/libmspack/SZDD/Implementation.cs
vendored
Normal file
226
BurnOutSharp/External/libmspack/SZDD/Implementation.cs
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
/* 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.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 = (DecompressorImpl)d;
|
||||
if (self == null)
|
||||
return null;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
object fh = sys.Open(sys, 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);
|
||||
|
||||
sys.Free(hdr);
|
||||
hdr = null;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SZDDD_CLOSE
|
||||
|
||||
/// <summary>
|
||||
/// Closes an SZDD file
|
||||
/// </summary>
|
||||
public static void Close(Decompressor d, Header hdr)
|
||||
{
|
||||
DecompressorImpl self = (DecompressorImpl)d;
|
||||
HeaderImpl hdr_p = (HeaderImpl)hdr;
|
||||
|
||||
if (self == null || self.System == null)
|
||||
return;
|
||||
|
||||
// Close the file handle associated
|
||||
self.System.Close(hdr_p.FileHandle);
|
||||
|
||||
// Free the memory associated
|
||||
self.System.Free(hdr);
|
||||
|
||||
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, object 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 = (DecompressorImpl)d;
|
||||
if (self == null)
|
||||
return Error.MSPACK_ERR_ARGS;
|
||||
if (hdr == null)
|
||||
return self.Error = Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
object fh = ((HeaderImpl)hdr).FileHandle;
|
||||
|
||||
// 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
|
||||
object outfh;
|
||||
if ((outfh = sys.Open(sys, 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 = (DecompressorImpl)d;
|
||||
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 = (DecompressorImpl)d;
|
||||
return (self != null) ? self.Error : Error.MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
375
BurnOutSharp/External/libmspack/SystemImpl.cs
vendored
Normal file
375
BurnOutSharp/External/libmspack/SystemImpl.cs
vendored
Normal file
@@ -0,0 +1,375 @@
|
||||
/* libmspack -- a library for working with Microsoft compression formats.
|
||||
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace LibMSPackSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure which abstracts file I/O and memory management.
|
||||
///
|
||||
/// The library always uses the SystemImpl structure for interaction
|
||||
/// with the file system and to allocate, free and copy all memory.It also
|
||||
/// uses it to send literal messages to the library user.
|
||||
///
|
||||
/// When the library is compiled normally, passing null to a compressor or
|
||||
/// decompressor constructor will result in a default SystemImpl being
|
||||
/// used, where all methods are implemented with the standard C library.
|
||||
/// However, all constructors support being given a custom created
|
||||
/// SystemImpl structure, with the library user's own methods. This
|
||||
/// allows for more abstract interaction, such as reading and writing files
|
||||
/// directly to memory, or from a network socket or pipe.
|
||||
///
|
||||
/// Implementors of an SystemImpl structure should read all
|
||||
/// documentation entries for every structure member, and write methods
|
||||
/// which conform to those standards.
|
||||
/// </summary>
|
||||
public class SystemImpl
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens a file for reading, writing, appending or updating.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the SystemImpl
|
||||
/// structure whose Open() method is being called. If
|
||||
/// this pointer is required by Close(), Read(), Write(),
|
||||
/// Seek() or Tell(), it should be stored in the result
|
||||
/// structure at this time.
|
||||
/// </param>
|
||||
/// <param name="filename">
|
||||
/// the file to be opened. It is passed directly from the
|
||||
/// library caller without being modified, so it is up to
|
||||
/// the caller what this parameter actually represents.
|
||||
/// </param>
|
||||
/// <param name="mode">One of the <see cref="OpenMode"/> values</param>
|
||||
/// <returns>
|
||||
/// a pointer to a mspack_file structure. This structure officially
|
||||
/// contains no members, its true contents are up to the
|
||||
/// SystemImpl implementor. It should contain whatever is needed
|
||||
/// for other SystemImpl methods to operate. Returning the null
|
||||
/// pointer indicates an error condition.
|
||||
/// </returns>
|
||||
public Func<SystemImpl, string, OpenMode, object> Open;
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened file. If any memory was allocated for this
|
||||
/// particular file handle, it should be freed at this time.
|
||||
/// </summary>
|
||||
/// <param name="file">the file to close</param>
|
||||
/// <see cref="Open"/>
|
||||
public Action<object> Close;
|
||||
|
||||
/// <summary>
|
||||
/// Reads a given number of bytes from an open file.
|
||||
/// </summary>
|
||||
/// <param name="file">the file to read from</param>
|
||||
/// <param name="buffer">the location where the read bytes should be stored</param>
|
||||
/// <param name="bytes">the number of bytes to read from the file.</param>
|
||||
/// <returns>
|
||||
/// the number of bytes successfully read (this can be less than
|
||||
/// the number requested), zero to mark the end of file, or less
|
||||
/// than zero to indicate an error. The library does not "retry"
|
||||
/// reads and assumes short reads are due to EOF, so you should
|
||||
/// avoid returning short reads because of transient errors.
|
||||
/// </returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Write"/>
|
||||
public Func<object, byte[], int, int, int> Read;
|
||||
|
||||
/// <summary>
|
||||
/// Writes a given number of bytes to an open file.
|
||||
/// </summary>
|
||||
/// <param name="file">the file to write to</param>
|
||||
/// <param name="buffer">the location where the written bytes should be read from</param>
|
||||
/// <param name="bytes">the number of bytes to write to the file.</param>
|
||||
/// <returns>
|
||||
/// the number of bytes successfully written, this can be less
|
||||
/// than the number requested. Zero or less can indicate an error
|
||||
/// where no bytes at all could be written. All cases where less
|
||||
/// bytes were written than requested are considered by the library
|
||||
/// to be an error.
|
||||
/// </returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Read"/>
|
||||
public Func<object, byte[], int, int, int> Write;
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to a specific file offset within an open file.
|
||||
///
|
||||
/// Sometimes the library needs to know the length of a file. It does
|
||||
/// this by seeking to the end of the file with seek(file, 0,
|
||||
/// MSPACK_SYS_SEEK_END), then calling Tell(). Implementations may want
|
||||
/// to make a special case for this.
|
||||
///
|
||||
/// Due to the potentially varying 32/64 bit datatype int on some
|
||||
/// architectures, the #MSPACK_SYS_SELFTEST macro MUST be used before
|
||||
/// using the library. If not, the error caused by the library passing an
|
||||
/// inappropriate stackframe to Seek() is subtle and hard to trace.
|
||||
/// </summary>
|
||||
/// <param name="file">the file to be seeked</param>
|
||||
/// <param name="offset">an offset to seek, measured in bytes</param>
|
||||
/// <param name="mode">One of the <see cref="SeekMode"/> values</param>
|
||||
/// <returns>zero for success, non-zero for an error</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Tell"/>
|
||||
public Func<object, long, SeekMode, bool> Seek;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current file position (in bytes) of the given file.
|
||||
/// </summary>
|
||||
/// <param name="file">the file whose file position is wanted</param>
|
||||
/// <returns>the current file position of the file</returns>
|
||||
/// <see cref="Open"/>
|
||||
/// <see cref="Seek"/>
|
||||
public Func<object, long> Tell;
|
||||
|
||||
/// <summary>
|
||||
/// Used to send messages from the library to the user.
|
||||
///
|
||||
/// Occasionally, the library generates warnings or other messages in
|
||||
/// plain english to inform the human user. These are informational only
|
||||
/// and can be ignored if not wanted.
|
||||
/// </summary>
|
||||
/// <param name="file">
|
||||
/// may be a file handle returned from Open() if this message
|
||||
/// pertains to a specific open file, or null if not related to
|
||||
/// a specific file.
|
||||
/// </param>
|
||||
/// <param name="format">a printf() style format string. It does NOT include a trailing newline.</param>
|
||||
/// <see cref="Open"/>
|
||||
public Action<object, string> Message;
|
||||
|
||||
/// <summary>
|
||||
/// Allocates memory.
|
||||
/// </summary>
|
||||
/// <param name="self">
|
||||
/// a self-referential pointer to the SystemImpl
|
||||
/// structure whose Alloc() method is being called.
|
||||
/// </param>
|
||||
/// <param name="bytes">the number of bytes to allocate</param>
|
||||
/// <returns>
|
||||
/// a pointer to the requested number of bytes, or null if
|
||||
/// not enough memory is available
|
||||
/// </returns>
|
||||
/// <see cref="Free"/>
|
||||
public Func<SystemImpl, int, byte[]> Alloc;
|
||||
|
||||
/// <summary>
|
||||
/// Frees memory.
|
||||
/// </summary>
|
||||
/// <param name="ptr">the memory to be freed. null is accepted and ignored.</param>
|
||||
/// <see cref="Alloc"/>
|
||||
public Action<object> Free;
|
||||
|
||||
/// <summary>
|
||||
/// Copies from one region of memory to another.
|
||||
///
|
||||
/// The regions of memory are guaranteed not to overlap, are usually less
|
||||
/// than 256 bytes, and may not be aligned. Please note that the source
|
||||
/// parameter comes before the destination parameter, unlike the standard
|
||||
/// C function memcpy().
|
||||
/// </summary>
|
||||
/// <param name="src">the region of memory to copy from</param>
|
||||
/// <param name="dest">the region of memory to copy to</param>
|
||||
/// <param name="bytes">the size of the memory region, in bytes</param>
|
||||
public Action<byte[], int, byte[], int, int> Copy;
|
||||
|
||||
/// <summary>
|
||||
/// A null pointer to mark the end of SystemImpl. It must equal null.
|
||||
///
|
||||
/// Should the SystemImpl structure extend in the future, this null
|
||||
/// will be seen, rather than have an invalid method pointer called.
|
||||
/// </summary>
|
||||
public readonly object NullPtr = null;
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of a file opened for reading
|
||||
/// </summary>
|
||||
public static Error GetFileLength(SystemImpl system, object file, out long length)
|
||||
{
|
||||
length = 0;
|
||||
long current;
|
||||
|
||||
if (system == null || file == null)
|
||||
return Error.MSPACK_ERR_OPEN;
|
||||
|
||||
// Get current offset
|
||||
current = system.Tell(file);
|
||||
|
||||
// Seek to end of file
|
||||
if (!system.Seek(file, 0, SeekMode.MSPACK_SYS_SEEK_END))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Get offset of end of file
|
||||
length = system.Tell(file);
|
||||
|
||||
// Seek back to original offset
|
||||
if (!system.Seek(file, current, SeekMode.MSPACK_SYS_SEEK_START))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates a system structure
|
||||
/// </summary>
|
||||
public static bool ValidSystem(SystemImpl sys)
|
||||
{
|
||||
return (sys != null) && (sys.Open != null) && (sys.Close != null) &&
|
||||
(sys.Read != null) && (sys.Write != null) && (sys.Seek != null) &&
|
||||
(sys.Tell != null) && (sys.Message != null) && (sys.Alloc != null) &&
|
||||
(sys.Free != null) && (sys.Copy != null) && (sys.NullPtr == null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Default Implementation
|
||||
|
||||
public static SystemImpl DefaultSystem => new SystemImpl()
|
||||
{
|
||||
Open = DefaultOpen,
|
||||
Close = DefaultClose,
|
||||
Read = DefaultRead,
|
||||
Write = DefaultWrite,
|
||||
Seek = DefaultSeek,
|
||||
Tell = DefaultTell,
|
||||
Message = DefaultMessage,
|
||||
Alloc = DefaultAlloc,
|
||||
Free = DefaultFree,
|
||||
Copy = DefaultCopy,
|
||||
};
|
||||
|
||||
private static object DefaultOpen(SystemImpl self, string filename, OpenMode mode)
|
||||
{
|
||||
DefaultFileImpl fileHandle = new DefaultFileImpl();
|
||||
switch (mode)
|
||||
{
|
||||
case OpenMode.MSPACK_SYS_OPEN_READ:
|
||||
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.Read);
|
||||
break;
|
||||
|
||||
case OpenMode.MSPACK_SYS_OPEN_WRITE:
|
||||
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.Write);
|
||||
break;
|
||||
|
||||
case OpenMode.MSPACK_SYS_OPEN_UPDATE:
|
||||
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.ReadWrite);
|
||||
break;
|
||||
|
||||
case OpenMode.MSPACK_SYS_OPEN_APPEND:
|
||||
fileHandle.FileHandle = File.Open(filename, FileMode.Append);
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return fileHandle;
|
||||
}
|
||||
|
||||
private static void DefaultClose(object file)
|
||||
{
|
||||
DefaultFileImpl self = (DefaultFileImpl)file;
|
||||
if (self != null)
|
||||
self.FileHandle.Close();
|
||||
}
|
||||
|
||||
private static int DefaultRead(object file, byte[] buffer, int pointer, int bytes)
|
||||
{
|
||||
DefaultFileImpl self = (DefaultFileImpl)file;
|
||||
if (self != null && buffer != null && bytes >= 0)
|
||||
{
|
||||
try { return self.FileHandle.Read(buffer, pointer, bytes); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int DefaultWrite(object file, byte[] buffer, int pointer, int bytes)
|
||||
{
|
||||
DefaultFileImpl self = (DefaultFileImpl)file;
|
||||
if (self != null && buffer != null && bytes >= 0)
|
||||
{
|
||||
try { self.FileHandle.Write(buffer, pointer, bytes); }
|
||||
catch { return -1; }
|
||||
return bytes;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static bool DefaultSeek(object file, long offset, SeekMode mode)
|
||||
{
|
||||
DefaultFileImpl self = (DefaultFileImpl)file;
|
||||
if (self != null)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case SeekMode.MSPACK_SYS_SEEK_START:
|
||||
try { self.FileHandle.Seek(offset, SeekOrigin.Begin); return true; }
|
||||
catch { return false; }
|
||||
|
||||
case SeekMode.MSPACK_SYS_SEEK_CUR:
|
||||
try { self.FileHandle.Seek(offset, SeekOrigin.Current); return true; }
|
||||
catch { return false; }
|
||||
|
||||
case SeekMode.MSPACK_SYS_SEEK_END:
|
||||
try { self.FileHandle.Seek(offset, SeekOrigin.End); return true; }
|
||||
catch { return false; }
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static long DefaultTell(object file)
|
||||
{
|
||||
DefaultFileImpl self = (DefaultFileImpl)file;
|
||||
return (self != null ? (int)self.FileHandle.Position : 0);
|
||||
}
|
||||
|
||||
private static void DefaultMessage(object file, string format)
|
||||
{
|
||||
if (file != null)
|
||||
Console.Error.Write($"{((DefaultFileImpl)file).Name}: ");
|
||||
|
||||
Console.Error.Write($"{format}\n");
|
||||
}
|
||||
|
||||
private static byte[] DefaultAlloc(SystemImpl self, int bytes)
|
||||
{
|
||||
return new byte[bytes];
|
||||
}
|
||||
|
||||
private static void DefaultFree(object buffer)
|
||||
{
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
private static void DefaultCopy(byte[] src, int srcPtr, byte[] dest, int destPtr, int bytes)
|
||||
{
|
||||
Array.Copy(src, srcPtr, dest, destPtr, bytes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user