mirror of
https://github.com/SabreTools/SabreTools.Compression.git
synced 2026-09-21 22:35:00 +00:00
Add everything from lzx.h
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using static SabreTools.Compression.libmspack.kwaj;
|
||||
using static SabreTools.Compression.libmspack.lzss;
|
||||
|
||||
namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
|
||||
147
libmspack/lzx.cs
Normal file
147
libmspack/lzx.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
public static class lzx
|
||||
{
|
||||
// Some constants defined by the LZX specification
|
||||
public const int LZX_MIN_MATCH = 2;
|
||||
public const int LZX_MAX_MATCH = 257;
|
||||
public const int LZX_NUM_CHARS = 256;
|
||||
public const int LZX_BLOCKTYPE_INVALID = 0; /* also blocktypes 4-7 invalid */
|
||||
public const int LZX_BLOCKTYPE_VERBATIM = 1;
|
||||
public const int LZX_BLOCKTYPE_ALIGNED = 2;
|
||||
public const int LZX_BLOCKTYPE_UNCOMPRESSED = 3;
|
||||
public const int LZX_PRETREE_NUM_ELEMENTS = 20;
|
||||
public const int LZX_ALIGNED_NUM_ELEMENTS = 8; /* aligned offset tree #elements */
|
||||
public const int LZX_NUM_PRIMARY_LENGTHS = 7; /* this one missing from spec! */
|
||||
public const int LZX_NUM_SECONDARY_LENGTHS = 249; /* length tree #elements */
|
||||
|
||||
// LZX huffman defines: tweak tablebits as desired
|
||||
public const int LZX_PRETREE_MAXSYMBOLS = LZX_PRETREE_NUM_ELEMENTS;
|
||||
public const int LZX_PRETREE_TABLEBITS = 6;
|
||||
public const int LZX_MAINTREE_MAXSYMBOLS = LZX_NUM_CHARS + 290 * 8;
|
||||
public const int LZX_MAINTREE_TABLEBITS = 12;
|
||||
public const int LZX_LENGTH_MAXSYMBOLS = LZX_NUM_SECONDARY_LENGTHS + 1;
|
||||
public const int LZX_LENGTH_TABLEBITS = 12;
|
||||
public const int LZX_ALIGNED_MAXSYMBOLS = LZX_ALIGNED_NUM_ELEMENTS;
|
||||
public const int LZX_ALIGNED_TABLEBITS = 7;
|
||||
public const int LZX_LENTABLE_SAFETY = 64; /* table decoding overruns are allowed */
|
||||
|
||||
public const int LZX_FRAME_SIZE = 32768; /* the size of a frame in LZX */
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initialises LZX decompression state for decoding an LZX
|
||||
/// stream.
|
||||
///
|
||||
/// This routine uses system->alloc() to allocate memory. If memory
|
||||
/// allocation fails, or the parameters to this function are invalid,
|
||||
/// NULL is returned.
|
||||
/// </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 LZX data.</param>
|
||||
/// <param name="output">An output stream to write the decoded data to.</param>
|
||||
/// <param name="window_bits">
|
||||
/// The size of the decoding window, which must be
|
||||
/// between 15 and 21 inclusive for regular LZX
|
||||
/// data, or between 17 and 25 inclusive for
|
||||
/// LZX DELTA data.
|
||||
/// </param>
|
||||
/// <param name="reset_interval">
|
||||
/// The interval at which the LZX bitstream is
|
||||
/// reset, in multiples of LZX frames (32678
|
||||
/// bytes), e.g. a value of 2 indicates the input
|
||||
/// stream resets after every 65536 output bytes.
|
||||
/// A value of 0 indicates that the bitstream never
|
||||
/// resets, such as in CAB LZX streams.
|
||||
/// </param>
|
||||
/// <param name="input_buffer_size">The number of bytes to use as an input bitstream buffer.</param>
|
||||
/// <param name="output_length">
|
||||
/// The length in bytes of the entirely
|
||||
/// decompressed output stream, if known in
|
||||
/// advance. It is used to correctly perform the
|
||||
/// Intel E8 transformation, which must stop 6
|
||||
/// bytes before the very end of the
|
||||
/// decompressed stream. It is not otherwise used
|
||||
/// or adhered to. If the full decompressed
|
||||
/// length is known in advance, set it here.
|
||||
/// If it is NOT known, use the value 0, and call
|
||||
/// lzxd_set_output_length() once it is
|
||||
/// known. If never set, 4 of the final 6 bytes
|
||||
/// of the output stream may be incorrect.
|
||||
/// </param>
|
||||
/// <param name="is_delta">
|
||||
/// Should be zero for all regular LZX data,
|
||||
/// non-zero for LZX DELTA encoded data.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A pointer to an initialised lzxd_stream structure, or NULL if
|
||||
/// there was not enough memory or parameters to the function were wrong.
|
||||
/// </returns>
|
||||
public static lzxd_stream lzxd_init(mspack_system system, mspack_file input, mspack_file output, int window_bits, int reset_interval, int input_buffer_size, long output_length, char is_delta) => null;
|
||||
|
||||
/// <summary>
|
||||
/// See description of output_length in lzxd_init()
|
||||
/// </summary>
|
||||
public static void lzxd_set_output_length(lzxd_stream lzx, long output_length) { }
|
||||
|
||||
/// <summary>
|
||||
/// Reads LZX DELTA reference data into the window and allows
|
||||
/// lzxd_decompress() to reference it.
|
||||
///
|
||||
/// Call this before the first call to lzxd_decompress().
|
||||
/// </summary>
|
||||
/// <param name="lzx">The LZX stream to apply this reference data to</param>
|
||||
/// <param name="system">
|
||||
/// An mspack_system implementation to use with the
|
||||
/// input param. Only read() will be called.
|
||||
/// </param>
|
||||
/// <param name="input">
|
||||
/// An input file handle to read reference data using
|
||||
/// system->read().
|
||||
/// </param>
|
||||
/// <param name="length">
|
||||
/// The length of the reference data. Cannot be longer
|
||||
/// than the LZX window size.
|
||||
/// </param>
|
||||
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public static MSPACK_ERR lzxd_set_reference_data(lzxd_stream lzx, mspack_system system, mspack_file input, uint length) => MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
/// <summary>
|
||||
/// Decompresses entire or partial LZX streams.
|
||||
///
|
||||
/// The number of bytes of data that should be decompressed is given as the
|
||||
/// out_bytes parameter. If more bytes are decoded than are needed, they
|
||||
/// will be kept over for a later invocation.
|
||||
///
|
||||
/// The output bytes will be passed to the system->write() function given in
|
||||
/// lzxd_init(), using the output file handle given in lzxd_init(). More than
|
||||
/// one call may be made to system->write().
|
||||
///
|
||||
/// Input bytes will be read in as necessary using the system->read()
|
||||
/// function given in lzxd_init(), using the input file handle given in
|
||||
/// lzxd_init(). 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 LZX asks for when they
|
||||
/// reach the end of the stream, rather than return an error code.
|
||||
///
|
||||
/// If any error code other than MSPACK_ERR_OK is returned, the stream
|
||||
/// should be considered unusable and lzxd_decompress() should not be
|
||||
/// called again on this stream.
|
||||
/// </summary>
|
||||
/// <param name="lzx">LZX decompression state, as allocated by lzxd_init().</param>
|
||||
/// <param name="out_bytes">The number of bytes of data to decompress.</param>
|
||||
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
|
||||
public static MSPACK_ERR lzxd_decompress(lzxd_stream lzx, long out_bytes) => MSPACK_ERR.MSPACK_ERR_OK;
|
||||
|
||||
/// <summary>
|
||||
/// Frees all state associated with an LZX data stream. This will call
|
||||
/// system->free() using the system pointer given in lzxd_init().
|
||||
/// </summary>
|
||||
/// <param name="lzx">LZX decompression state to free.</param>
|
||||
public static void lzxd_free(lzxd_stream lzx) { }
|
||||
}
|
||||
}
|
||||
180
libmspack/lzxd_stream.cs
Normal file
180
libmspack/lzxd_stream.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using static SabreTools.Compression.libmspack.lzx;
|
||||
|
||||
namespace SabreTools.Compression.libmspack
|
||||
{
|
||||
public unsafe class lzxd_stream
|
||||
{
|
||||
/// <summary>
|
||||
/// I/O routines
|
||||
/// </summary>
|
||||
public mspack_system sys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input file handle
|
||||
/// </summary>
|
||||
public mspack_file input { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Output file handle
|
||||
/// </summary>
|
||||
public mspack_file output { get; set; }
|
||||
|
||||
/// <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 window_size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// LZX DELTA reference data size
|
||||
/// </summary>
|
||||
public uint ref_data_size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of match_offset entries in table
|
||||
/// </summary>
|
||||
public uint num_offsets { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decompression offset within window
|
||||
/// </summary>
|
||||
public uint window_posn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current frame offset within in window
|
||||
/// </summary>
|
||||
public uint frame_posn { 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 reset_interval { 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 block_length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Uncompressed bytes still left to decode
|
||||
/// </summary>
|
||||
public uint block_remaining { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Magic header value used for transform
|
||||
/// </summary>
|
||||
public int intel_filesize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has intel E8 decoding started?
|
||||
/// </summary>
|
||||
public byte intel_started { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of the current block
|
||||
/// </summary>
|
||||
public byte block_type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Have we started decoding at all yet?
|
||||
/// </summary>
|
||||
public byte header_read { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Have we reached the end of input?
|
||||
/// </summary>
|
||||
public byte input_end { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Does stream follow LZX DELTA spec?
|
||||
/// </summary>
|
||||
public byte is_delta { get; set; }
|
||||
|
||||
public MSPACK_ERR error { get; set; }
|
||||
|
||||
#region I/O buffering
|
||||
|
||||
public byte* inbuf { get; set; }
|
||||
|
||||
public byte* i_ptr { get; set; }
|
||||
|
||||
public byte* i_end { get; set; }
|
||||
|
||||
public byte* o_ptr { get; set; }
|
||||
|
||||
public byte* o_end { get; set; }
|
||||
|
||||
public uint bit_buffer { get; set; }
|
||||
|
||||
public uint bits_left { get; set; }
|
||||
|
||||
public uint inbuf_size { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Huffman code lengths
|
||||
|
||||
public byte[] PRETREE_len { get; set; } = new byte[LZX_PRETREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
|
||||
|
||||
public byte[] MAINTREE_len { get; set; } = new byte[LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
|
||||
|
||||
public byte[] LENGTH_len { get; set; } = new byte[LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
|
||||
|
||||
public byte[] ALIGNED_len { get; set; } = new byte[LZX_ALIGNED_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Huffman decoding tables
|
||||
|
||||
public ushort[] PRETREE_table { get; set; } = new ushort[(1 << LZX_PRETREE_TABLEBITS) + (LZX_PRETREE_MAXSYMBOLS * 2)];
|
||||
|
||||
public ushort[] MAINTREE_table { get; set; } = new ushort[(1 << LZX_MAINTREE_TABLEBITS) + (LZX_MAINTREE_MAXSYMBOLS * 2)];
|
||||
|
||||
public ushort[] LENGTH_table { get; set; } = new ushort[(1 << LZX_LENGTH_TABLEBITS) + (LZX_LENGTH_MAXSYMBOLS * 2)];
|
||||
|
||||
public ushort[] ALIGNED_table { get; set; } = new ushort[(1 << LZX_ALIGNED_TABLEBITS) + (LZX_ALIGNED_MAXSYMBOLS * 2)];
|
||||
|
||||
public byte LENGTH_empty { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// This is used purely for doing the intel E8 transform
|
||||
/// </summary>
|
||||
public byte[] e8_buf { get; set; } = new byte[LZX_FRAME_SIZE];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user