mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-13 12:26:49 +00:00
Start cleanup on libmspack
This commit is contained in:
48
BurnOutSharp/External/libmspack/CAB/Cabinet.cs
vendored
48
BurnOutSharp/External/libmspack/CAB/Cabinet.cs
vendored
@@ -74,6 +74,15 @@ namespace LibMSPackSharp.CAB
|
||||
/// <see cref="Decompressor.Search"/>
|
||||
public class Cabinet
|
||||
{
|
||||
#region Internal
|
||||
|
||||
/// <summary>
|
||||
/// Cabinet header information
|
||||
/// </summary>
|
||||
internal _CabinetHeader Header { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <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
|
||||
@@ -93,11 +102,6 @@ namespace LibMSPackSharp.CAB
|
||||
/// </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>
|
||||
@@ -137,39 +141,5 @@ namespace LibMSPackSharp.CAB
|
||||
/// 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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/* This file is part of libmspack.
|
||||
* (C) 2003-2018 Stuart Caie.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
namespace LibMSPackSharp.CAB
|
||||
{
|
||||
public class CabinetImpl : Cabinet
|
||||
{
|
||||
public long BlocksOffset { get; set; }
|
||||
|
||||
public int BlockResverved { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -76,12 +76,12 @@ namespace LibMSPackSharp.CAB
|
||||
/// <summary>
|
||||
/// Input data consumed
|
||||
/// </summary>
|
||||
public int IPtr { get; set; }
|
||||
public int InputPointer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Input data end
|
||||
/// </summary>
|
||||
public int IEnd { get; set; }
|
||||
public int InputEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// One input block of data
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace LibMSPackSharp.CAB
|
||||
/// <see cref="Close"/>
|
||||
/// <see cref="Search"/>
|
||||
/// <see cref="LastError"/>
|
||||
public Func<Decompressor, string, CabinetImpl> Open;
|
||||
public Func<Decompressor, string, Cabinet> Open;
|
||||
|
||||
/// <summary>
|
||||
/// Closes a previously opened cabinet or cabinet set.
|
||||
|
||||
31
BurnOutSharp/External/libmspack/CAB/Folder.cs
vendored
31
BurnOutSharp/External/libmspack/CAB/Folder.cs
vendored
@@ -27,6 +27,15 @@ namespace LibMSPackSharp.CAB
|
||||
/// </summary>
|
||||
public class Folder
|
||||
{
|
||||
#region Internal
|
||||
|
||||
/// <summary>
|
||||
/// Folder header information
|
||||
/// </summary>
|
||||
internal _FolderHeader Header { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the next folder in this cabinet or cabinet set, or NULL
|
||||
/// if this is the final folder.
|
||||
@@ -34,28 +43,18 @@ namespace LibMSPackSharp.CAB
|
||||
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".
|
||||
/// Where are the data blocks?
|
||||
/// </summary>
|
||||
/// <see cref="MSCABD_COMP_METHOD()"/>
|
||||
/// <see cref="MSCABD_COMP_LEVEL()"/>
|
||||
public CompressionType CompressionType { get; set; }
|
||||
public FolderData Data { 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.
|
||||
/// First file needing backwards merge
|
||||
/// </summary>
|
||||
public ushort NumBlocks { get; set; }
|
||||
public InternalFile MergePrev { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the compression method used by a folder.
|
||||
/// First file needing forwards merge
|
||||
/// </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);
|
||||
public InternalFile MergeNext { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/* 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; }
|
||||
}
|
||||
}
|
||||
@@ -71,36 +71,6 @@ namespace LibMSPackSharp.CAB
|
||||
|
||||
#region Structure Offsets
|
||||
|
||||
private const int cfhead_Signature = (0x00);
|
||||
private const int cfhead_CabinetSize = (0x08);
|
||||
private const int cfhead_FileOffset = (0x10);
|
||||
private const int cfhead_MinorVersion = (0x18);
|
||||
private const int cfhead_MajorVersion = (0x19);
|
||||
private const int cfhead_NumFolders = (0x1A);
|
||||
private const int cfhead_NumFiles = (0x1C);
|
||||
private const int cfhead_Flags = (0x1E);
|
||||
private const int cfhead_SetID = (0x20);
|
||||
private const int cfhead_CabinetIndex = (0x22);
|
||||
private const int cfhead_SIZEOF = (0x24);
|
||||
|
||||
private const int cfheadext_HeaderReserved = (0x00);
|
||||
private const int cfheadext_FolderReserved = (0x02);
|
||||
private const int cfheadext_DataReserved = (0x03);
|
||||
private const int cfheadext_SIZEOF = (0x04);
|
||||
|
||||
private const int cffold_DataOffset = (0x00);
|
||||
private const int cffold_NumBlocks = (0x04);
|
||||
private const int cffold_CompType = (0x06);
|
||||
private const int cffold_SIZEOF = (0x08);
|
||||
|
||||
private const int cffile_UncompressedSize = (0x00);
|
||||
private const int cffile_FolderOffset = (0x04);
|
||||
private const int cffile_FolderIndex = (0x08);
|
||||
private const int cffile_Date = (0x0A);
|
||||
private const int cffile_Time = (0x0C);
|
||||
private const int cffile_Attribs = (0x0E);
|
||||
private const int cffile_SIZEOF = (0x10);
|
||||
|
||||
private const int cfdata_CheckSum = (0x00);
|
||||
private const int cfdata_CompressedSize = (0x04);
|
||||
private const int cfdata_UncompressedSize = (0x06);
|
||||
@@ -140,10 +110,10 @@ namespace LibMSPackSharp.CAB
|
||||
/// <summary>
|
||||
/// Opens a file and tries to read it as a cabinet file
|
||||
/// </summary>
|
||||
public static CabinetImpl Open(Decompressor d, string filename)
|
||||
public static Cabinet Open(Decompressor d, string filename)
|
||||
{
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
CabinetImpl cab = null;
|
||||
Cabinet cab = null;
|
||||
|
||||
if (self == null)
|
||||
return null;
|
||||
@@ -152,7 +122,7 @@ namespace LibMSPackSharp.CAB
|
||||
object fileHandle;
|
||||
if ((fileHandle = system.Open(system, filename, OpenMode.MSPACK_SYS_OPEN_READ)) != null)
|
||||
{
|
||||
cab = new CabinetImpl();
|
||||
cab = new Cabinet();
|
||||
cab.Filename = filename;
|
||||
Error error = ReadHeaders(system, fileHandle, cab, 0, self.Salvage, false);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
@@ -222,7 +192,7 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Free folder data segments
|
||||
for (dat = (fol as FolderImpl).Data.Next; dat != null; dat = ndat)
|
||||
for (dat = fol.Data.Next; dat != null; dat = ndat)
|
||||
{
|
||||
ndat = dat.Next;
|
||||
sys.Free(dat);
|
||||
@@ -272,18 +242,17 @@ namespace LibMSPackSharp.CAB
|
||||
/// Fills out a pre-existing Cabinet structure, allocates memory
|
||||
/// for folders and files as necessary
|
||||
/// </summary>
|
||||
public static Error ReadHeaders(SystemImpl sys, object fh, CabinetImpl cab, long offset, bool salvage, bool quiet)
|
||||
public static Error ReadHeaders(SystemImpl sys, object fh, Cabinet cab, long offset, bool salvage, bool quiet)
|
||||
{
|
||||
int num_folders, num_files, folder_resv, i, x;
|
||||
int i, x;
|
||||
Error err = Error.MSPACK_ERR_OK;
|
||||
FileFlags fidx;
|
||||
FolderImpl fol, linkfol = null;
|
||||
Folder fol, linkfol = null;
|
||||
InternalFile file, linkfile = null;
|
||||
byte[] buf = new byte[64];
|
||||
|
||||
// Initialise pointers
|
||||
if (cab == null)
|
||||
cab = new CabinetImpl();
|
||||
cab = new Cabinet();
|
||||
|
||||
cab.Next = null;
|
||||
cab.Files = null;
|
||||
@@ -299,73 +268,36 @@ namespace LibMSPackSharp.CAB
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Read in the CFHEADER
|
||||
if (sys.Read(fh, buf, 0, cfhead_SIZEOF) != cfhead_SIZEOF)
|
||||
if (sys.Read(fh, buf, 0, _CabinetHeader.Size) != _CabinetHeader.Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
// Check for "MSCF" signature
|
||||
if (BitConverter.ToUInt32(buf, cfhead_Signature) != 0x4643534D)
|
||||
return Error.MSPACK_ERR_SIGNATURE;
|
||||
// Create a new header based on that
|
||||
err = _CabinetHeader.Create(buf, out _CabinetHeader cabinetHeader);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
// Some basic header fields
|
||||
cab.Length = BitConverter.ToUInt32(buf, cfhead_CabinetSize);
|
||||
cab.SetID = BitConverter.ToUInt16(buf, cfhead_SetID);
|
||||
cab.SetIndex = BitConverter.ToUInt16(buf, cfhead_CabinetIndex);
|
||||
// Assign the header
|
||||
cab.Header = cabinetHeader;
|
||||
|
||||
// Get the number of folders
|
||||
num_folders = BitConverter.ToUInt16(buf, cfhead_NumFolders);
|
||||
if (num_folders == 0)
|
||||
// Check for the extended header
|
||||
if (cab.Header.Flags.HasFlag(HeaderFlags.MSCAB_HDR_RESV))
|
||||
{
|
||||
if (!quiet) sys.Message(fh, "no folders in cabinet.");
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Get the number of files
|
||||
num_files = BitConverter.ToUInt16(buf, cfhead_NumFiles);
|
||||
if (num_files == 0)
|
||||
{
|
||||
if (!quiet) sys.Message(fh, "no files in cabinet.");
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Check cabinet version
|
||||
if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3))
|
||||
{
|
||||
if (!quiet) sys.Message(fh, "WARNING; cabinet version is not 1.3");
|
||||
}
|
||||
|
||||
// Read the reserved-sizes part of header, if present
|
||||
cab.Flags = (HeaderFlags)BitConverter.ToUInt16(buf, cfhead_Flags);
|
||||
|
||||
if (cab.Flags.HasFlag(HeaderFlags.MSCAB_HDR_RESV))
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, cfheadext_SIZEOF) != cfheadext_SIZEOF)
|
||||
if (sys.Read(fh, buf, 0, _CabinetHeader.ExtendedSize) != _CabinetHeader.ExtendedSize)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
cab.HeaderResv = BitConverter.ToUInt16(buf, cfheadext_HeaderReserved);
|
||||
folder_resv = buf[cfheadext_FolderReserved];
|
||||
cab.BlockResverved = buf[cfheadext_DataReserved];
|
||||
|
||||
if (cab.HeaderResv > 60000)
|
||||
{
|
||||
if (!quiet) sys.Message(fh, "WARNING; reserved header > 60000.");
|
||||
}
|
||||
// Populate the extended header
|
||||
cabinetHeader.PopulateExtendedHeader(buf);
|
||||
|
||||
// Skip the reserved header
|
||||
if (cab.HeaderResv != 0)
|
||||
if (cab.Header.HeaderReserved != 0)
|
||||
{
|
||||
if (!sys.Seek(fh, cab.HeaderResv, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
if (!sys.Seek(fh, cab.Header.HeaderReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cab.HeaderResv = 0;
|
||||
folder_resv = 0;
|
||||
cab.BlockResverved = 0;
|
||||
}
|
||||
|
||||
// Read name and info of preceeding cabinet in set, if present
|
||||
if (cab.Flags.HasFlag(HeaderFlags.MSCAB_HDR_PREVCAB))
|
||||
if (cab.Header.Flags.HasFlag(HeaderFlags.MSCAB_HDR_PREVCAB))
|
||||
{
|
||||
cab.PreviousName = ReadString(sys, fh, false, ref err);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
@@ -377,7 +309,7 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Read name and info of next cabinet in set, if present
|
||||
if (cab.Flags.HasFlag(HeaderFlags.MSCAB_HDR_NEXTCAB))
|
||||
if (cab.Header.Flags.HasFlag(HeaderFlags.MSCAB_HDR_NEXTCAB))
|
||||
{
|
||||
cab.NextName = ReadString(sys, fh, false, ref err);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
@@ -389,29 +321,39 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Read folders
|
||||
for (i = 0; i < num_folders; i++)
|
||||
for (i = 0; i < cab.Header.NumFolders; i++)
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, cffold_SIZEOF) != cffold_SIZEOF)
|
||||
// Read in the FOHEADER
|
||||
if (sys.Read(fh, buf, 0, _FolderHeader.Size) != _FolderHeader.Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
if (folder_resv != 0)
|
||||
if (cab.Header.FolderReserved != 0)
|
||||
{
|
||||
if (!sys.Seek(fh, folder_resv, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
if (!sys.Seek(fh, cab.Header.FolderReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
fol = new FolderImpl();
|
||||
// Create an empty folder
|
||||
fol = new Folder()
|
||||
{
|
||||
Next = null,
|
||||
MergePrev = null,
|
||||
MergeNext = null,
|
||||
};
|
||||
|
||||
fol.Next = null;
|
||||
fol.CompressionType = (CompressionType)BitConverter.ToUInt16(buf, cffold_CompType);
|
||||
fol.NumBlocks = BitConverter.ToUInt16(buf, cffold_NumBlocks);
|
||||
fol.MergePrev = null;
|
||||
fol.MergeNext = null;
|
||||
// Create a new header based on that
|
||||
err = _FolderHeader.Create(buf, out _FolderHeader folderHeader);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
// Assign the header
|
||||
fol.Header = folderHeader;
|
||||
|
||||
// Set the folder data fields
|
||||
fol.Data = new FolderData();
|
||||
fol.Data.Next = null;
|
||||
fol.Data.Cab = cab;
|
||||
fol.Data.Offset = offset + (int)(BitConverter.ToUInt32(buf, cffold_DataOffset));
|
||||
fol.Data.Offset = offset + fol.Header.DataOffset;
|
||||
|
||||
// Link folder into list of folders
|
||||
if (linkfol == null)
|
||||
@@ -423,27 +365,30 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Read files
|
||||
for (i = 0; i < num_files; i++)
|
||||
for (i = 0; i < cab.Header.NumFiles; i++)
|
||||
{
|
||||
if (sys.Read(fh, buf, 0, cffile_SIZEOF) != cffile_SIZEOF)
|
||||
// Read in the FIHEADER
|
||||
if (sys.Read(fh, buf, 0, _FileHeader.Size) != _FileHeader.Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
file = new InternalFile();
|
||||
file = new InternalFile() { Next = null };
|
||||
|
||||
file.Next = null;
|
||||
file.Length = BitConverter.ToUInt32(buf, cffile_UncompressedSize);
|
||||
file.Attributes = (FileAttributes)BitConverter.ToUInt16(buf, cffile_Attribs);
|
||||
file.Offset = BitConverter.ToUInt32(buf, cffile_FolderOffset);
|
||||
// Create a new header based on that
|
||||
err = _FileHeader.Create(buf, out _FileHeader fileHeader);
|
||||
if (err != Error.MSPACK_ERR_OK)
|
||||
return err;
|
||||
|
||||
// Assign the header
|
||||
file.Header = fileHeader;
|
||||
|
||||
// Set folder pointer
|
||||
fidx = (FileFlags)BitConverter.ToUInt16(buf, cffile_FolderIndex);
|
||||
if (fidx < FileFlags.CONTINUED_FROM_PREV)
|
||||
if (file.Header.FolderIndex < FileFlags.CONTINUED_FROM_PREV)
|
||||
{
|
||||
// Normal folder index; count up to the correct folder
|
||||
if ((int)fidx < num_folders)
|
||||
if ((int)file.Header.FolderIndex < cab.Header.NumFolders)
|
||||
{
|
||||
Folder ifol = cab.Folders;
|
||||
while (fidx-- != 0)
|
||||
while (file.Header.FolderIndex-- != 0)
|
||||
{
|
||||
if (ifol != null)
|
||||
ifol = ifol.Next;
|
||||
@@ -460,7 +405,7 @@ namespace LibMSPackSharp.CAB
|
||||
else
|
||||
{
|
||||
// Either CONTINUED_TO_NEXT, CONTINUED_FROM_PREV or CONTINUED_PREV_AND_NEXT
|
||||
if (fidx == FileFlags.CONTINUED_TO_NEXT || fidx == FileFlags.CONTINUED_PREV_AND_NEXT)
|
||||
if (file.Header.FolderIndex == FileFlags.CONTINUED_TO_NEXT || file.Header.FolderIndex == FileFlags.CONTINUED_PREV_AND_NEXT)
|
||||
{
|
||||
// Get last folder
|
||||
Folder ifol = cab.Folders;
|
||||
@@ -472,35 +417,23 @@ namespace LibMSPackSharp.CAB
|
||||
file.Folder = ifol;
|
||||
|
||||
// Set "merge next" pointer
|
||||
fol = ifol as FolderImpl;
|
||||
fol = ifol;
|
||||
if (fol.MergeNext == null)
|
||||
fol.MergeNext = file;
|
||||
}
|
||||
|
||||
if (fidx == FileFlags.CONTINUED_FROM_PREV || fidx == FileFlags.CONTINUED_PREV_AND_NEXT)
|
||||
if (file.Header.FolderIndex == FileFlags.CONTINUED_FROM_PREV || file.Header.FolderIndex == FileFlags.CONTINUED_PREV_AND_NEXT)
|
||||
{
|
||||
// Get first folder
|
||||
file.Folder = cab.Folders;
|
||||
|
||||
// Set "merge prev" pointer
|
||||
fol = file.Folder as FolderImpl;
|
||||
fol = file.Folder;
|
||||
if (fol.MergePrev == null)
|
||||
fol.MergePrev = file;
|
||||
}
|
||||
}
|
||||
|
||||
// Get time
|
||||
x = BitConverter.ToUInt16(buf, cffile_Time);
|
||||
file.LastModifiedTimeHour = (byte)(x >> 11);
|
||||
file.LastModifiedTimeMinute = (byte)((x >> 5) & 0x3F);
|
||||
file.LastModifiedTimeSecond = (byte)((x << 1) & 0x3E);
|
||||
|
||||
// Get date
|
||||
x = BitConverter.ToUInt16(buf, cffile_Date);
|
||||
file.LastModifiedDateDay = (byte)(x & 0x1F);
|
||||
file.LastModifiedDateMonth = (byte)((x >> 5) & 0xF);
|
||||
file.LastModifiedDateYear = (x >> 9) + 1980;
|
||||
|
||||
// Get filename
|
||||
file.Filename = ReadString(sys, fh, false, ref err);
|
||||
|
||||
@@ -528,7 +461,7 @@ namespace LibMSPackSharp.CAB
|
||||
{
|
||||
// We never actually added any files to the file list. Something went wrong.
|
||||
// The file header may have been invalid */
|
||||
Console.WriteLine($"No files found, even though header claimed to have {num_files} files");
|
||||
Console.WriteLine($"No files found, even though header claimed to have {cab.Header.NumFiles} files");
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
@@ -610,7 +543,7 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Open file and get its full file length
|
||||
object fh; CabinetImpl cab = null;
|
||||
object fh; Cabinet cab = null;
|
||||
if ((fh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_READ)) != null)
|
||||
{
|
||||
long firstlen = 0;
|
||||
@@ -643,10 +576,10 @@ namespace LibMSPackSharp.CAB
|
||||
/// The inner loop of <see cref="Search(Decompressor, string)"/>, to make it easier to
|
||||
/// break out of the loop and be sure that all resources are freed
|
||||
/// </summary>
|
||||
public static Error Find(DecompressorImpl self, byte[] buf, object fh, string filename, long flen, ref long firstlen, out CabinetImpl firstcab)
|
||||
public static Error Find(DecompressorImpl self, byte[] buf, object fh, string filename, long flen, ref long firstlen, out Cabinet firstcab)
|
||||
{
|
||||
firstcab = null;
|
||||
CabinetImpl cab, link = null;
|
||||
Cabinet cab, link = null;
|
||||
long caboff, offset, length;
|
||||
SystemImpl sys = self.System;
|
||||
long p, pend;
|
||||
@@ -762,8 +695,7 @@ namespace LibMSPackSharp.CAB
|
||||
(((caboff + cablen_u32) < (flen + 32)) || self.Salvage))
|
||||
{
|
||||
// Likely cabinet found -- try reading it
|
||||
cab = new CabinetImpl();
|
||||
cab.Filename = filename;
|
||||
cab = new Cabinet() { Filename = filename };
|
||||
|
||||
if (ReadHeaders(sys, fh, cab, caboff, self.Salvage, quiet: true) != Error.MSPACK_ERR_OK)
|
||||
{
|
||||
@@ -842,7 +774,7 @@ namespace LibMSPackSharp.CAB
|
||||
DecompressorImpl self = d as DecompressorImpl;
|
||||
|
||||
FolderData data, ndata;
|
||||
FolderImpl lfol, rfol;
|
||||
Folder lfol, rfol;
|
||||
InternalFile fi, rfi, lfi;
|
||||
|
||||
if (self == null)
|
||||
@@ -884,18 +816,18 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Warn about odd set IDs or indices
|
||||
if (lcab.SetID != rcab.SetID)
|
||||
if (lcab.Header.SetID != rcab.Header.SetID)
|
||||
sys.Message(null, "WARNING; merged cabinets with differing Set IDs.");
|
||||
|
||||
if (lcab.SetIndex > rcab.SetIndex)
|
||||
if (lcab.Header.CabinetIndex > rcab.Header.CabinetIndex)
|
||||
sys.Message(null, "WARNING; merged cabinets with odd order.");
|
||||
|
||||
// Merging the last folder in lcab with the first folder in rcab
|
||||
lfol = lcab.Folders as FolderImpl;
|
||||
rfol = rcab.Folders as FolderImpl;
|
||||
lfol = lcab.Folders;
|
||||
rfol = rcab.Folders;
|
||||
while (lfol.Next != null)
|
||||
{
|
||||
lfol = lfol.Next as FolderImpl;
|
||||
lfol = lfol.Next;
|
||||
}
|
||||
|
||||
// Do we need to merge folders?
|
||||
@@ -947,14 +879,14 @@ namespace LibMSPackSharp.CAB
|
||||
// NOTE: special case, don't merge if rfol is merge prev and next,
|
||||
// rfol.MergeNext is going to be deleted, so keep lfol's version
|
||||
// instead
|
||||
lfol.NumBlocks += (ushort)(rfol.NumBlocks - 1);
|
||||
lfol.Header.NumBlocks += (ushort)(rfol.Header.NumBlocks - 1);
|
||||
if ((rfol.MergeNext == null) || (rfol.MergeNext.Folder != rfol))
|
||||
lfol.MergeNext = rfol.MergeNext;
|
||||
|
||||
// Attach the rfol's folder (except the merge folder)
|
||||
while (lfol.Next != null)
|
||||
{
|
||||
lfol = (FolderImpl)lfol.Next;
|
||||
lfol = lfol.Next;
|
||||
}
|
||||
|
||||
lfol.Next = rfol.Next;
|
||||
@@ -1015,20 +947,20 @@ namespace LibMSPackSharp.CAB
|
||||
/// <summary>
|
||||
/// Decides if two folders are OK to merge
|
||||
/// </summary>
|
||||
private static bool CanMergeFolders(SystemImpl sys, FolderImpl lfol, FolderImpl rfol)
|
||||
private static bool CanMergeFolders(SystemImpl sys, Folder lfol, Folder rfol)
|
||||
{
|
||||
InternalFile lfi, rfi, l, r;
|
||||
bool matching = true;
|
||||
|
||||
// Check that both folders use the same compression method/settings
|
||||
if (lfol.CompressionType != rfol.CompressionType)
|
||||
if (lfol.Header.CompType != rfol.Header.CompType)
|
||||
{
|
||||
Console.WriteLine("folder merge: compression type mismatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check there are not too many data blocks after merging
|
||||
if ((lfol.NumBlocks + rfol.NumBlocks) > CAB_FOLDERMAX)
|
||||
if ((lfol.Header.NumBlocks + rfol.Header.NumBlocks) > CAB_FOLDERMAX)
|
||||
{
|
||||
Console.WriteLine("folder merge: too many data blocks in merged folders");
|
||||
return false;
|
||||
@@ -1046,7 +978,7 @@ namespace LibMSPackSharp.CAB
|
||||
// offset and length of each file.
|
||||
for (l = lfi, r = rfi; l != null; l = l.Next, r = r.Next)
|
||||
{
|
||||
if (r == null || (l.Offset != r.Offset) || (l.Length != r.Length))
|
||||
if (r == null || (l.Header.FolderOffset != r.Header.FolderOffset) || (l.Header.UncompressedSize != r.Header.UncompressedSize))
|
||||
{
|
||||
matching = false;
|
||||
break;
|
||||
@@ -1064,7 +996,7 @@ namespace LibMSPackSharp.CAB
|
||||
{
|
||||
for (r = rfi; r != null; r = r.Next)
|
||||
{
|
||||
if (l.Offset == r.Offset && l.Length == r.Length)
|
||||
if (l.Header.FolderOffset == r.Header.FolderOffset && l.Header.UncompressedSize == r.Header.UncompressedSize)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1095,19 +1027,19 @@ namespace LibMSPackSharp.CAB
|
||||
return self.Error = Error.MSPACK_ERR_ARGS;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
FolderImpl fol = file.Folder as FolderImpl;
|
||||
Folder fol = file.Folder;
|
||||
|
||||
// If offset is beyond 2GB, nothing can be extracted
|
||||
if (file.Offset > CAB_LENGTHMAX)
|
||||
if (file.Header.FolderOffset > CAB_LENGTHMAX)
|
||||
return self.Error = Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
// If file claims to go beyond 2GB either error out,
|
||||
// or in salvage mode reduce file length so it fits 2GB limit
|
||||
long filelen = file.Length;
|
||||
if (filelen > CAB_LENGTHMAX || (file.Offset + filelen) > CAB_LENGTHMAX)
|
||||
long filelen = file.Header.UncompressedSize;
|
||||
if (filelen > CAB_LENGTHMAX || (file.Header.FolderOffset + filelen) > CAB_LENGTHMAX)
|
||||
{
|
||||
if (self.Salvage)
|
||||
filelen = CAB_LENGTHMAX - file.Offset;
|
||||
filelen = CAB_LENGTHMAX - file.Header.FolderOffset;
|
||||
else
|
||||
return self.Error = Error.MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
@@ -1123,8 +1055,8 @@ namespace LibMSPackSharp.CAB
|
||||
// In salvage mode, don't assume block sizes, just try decoding
|
||||
if (!self.Salvage)
|
||||
{
|
||||
long maxlen = fol.NumBlocks * CAB_BLOCKMAX;
|
||||
if ((file.Offset + filelen) > maxlen)
|
||||
long maxlen = fol.Header.NumBlocks * CAB_BLOCKMAX;
|
||||
if ((file.Header.FolderOffset + filelen) > maxlen)
|
||||
{
|
||||
sys.Message(null, $"ERROR; file \"{file.Filename}\" cannot be extracted, cabinet set is incomplete");
|
||||
return self.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
@@ -1146,7 +1078,7 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Do we need to change folder or reset the current folder?
|
||||
if ((self.State.Folder != fol) || (self.State.Offset > file.Offset) || self.State.DecompressorState == null)
|
||||
if ((self.State.Folder != fol) || (self.State.Offset > file.Header.FolderOffset) || self.State.DecompressorState == null)
|
||||
{
|
||||
// Free any existing decompressor
|
||||
FreeDecompressionState(self);
|
||||
@@ -1169,7 +1101,7 @@ namespace LibMSPackSharp.CAB
|
||||
return self.Error = Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Set up decompressor
|
||||
if (InitDecompressionState(self, fol.CompressionType) != Error.MSPACK_ERR_OK)
|
||||
if (InitDecompressionState(self, fol.Header.CompType) != Error.MSPACK_ERR_OK)
|
||||
return self.Error;
|
||||
|
||||
// Initialise new folder state
|
||||
@@ -1178,7 +1110,7 @@ namespace LibMSPackSharp.CAB
|
||||
self.State.Offset = 0;
|
||||
self.State.Block = 0;
|
||||
self.State.Outlen = 0;
|
||||
self.State.IPtr = self.State.IEnd = 0;
|
||||
self.State.InputPointer = self.State.InputEnd = 0;
|
||||
|
||||
// read_error lasts for the lifetime of a decompressor
|
||||
self.ReadError = Error.MSPACK_ERR_OK;
|
||||
@@ -1200,7 +1132,7 @@ namespace LibMSPackSharp.CAB
|
||||
// - if cabd_sys_read() has an error, it will set self.ReadError
|
||||
// and pass back MSPACK_ERR_READ
|
||||
self.State.OutputFileHandle = null;
|
||||
if ((bytes = file.Offset - self.State.Offset) != 0)
|
||||
if ((bytes = file.Header.FolderOffset - self.State.Offset) != 0)
|
||||
{
|
||||
error = self.State.Decompress(self.State.DecompressorState, bytes);
|
||||
self.Error = (error == Error.MSPACK_ERR_READ) ? self.ReadError : error;
|
||||
@@ -1310,7 +1242,11 @@ namespace LibMSPackSharp.CAB
|
||||
private static int SysRead(object file, byte[] buffer, int pointer, int bytes)
|
||||
{
|
||||
DecompressorImpl self = file as DecompressorImpl;
|
||||
if (self == null)
|
||||
return 0;
|
||||
|
||||
SystemImpl sys = self.System;
|
||||
|
||||
int avail, todo, outlen = 0;
|
||||
|
||||
bool ignore_cksum = self.Salvage ||
|
||||
@@ -1321,7 +1257,7 @@ namespace LibMSPackSharp.CAB
|
||||
todo = bytes;
|
||||
while (todo > 0)
|
||||
{
|
||||
avail = self.State.IEnd - self.State.IPtr;
|
||||
avail = self.State.InputEnd - self.State.InputPointer;
|
||||
|
||||
// If out of input data, read a new block
|
||||
if (avail != 0)
|
||||
@@ -1330,8 +1266,8 @@ namespace LibMSPackSharp.CAB
|
||||
if (avail > todo)
|
||||
avail = todo;
|
||||
|
||||
sys.Copy(self.State.Input, self.State.IPtr, buffer, pointer, avail);
|
||||
self.State.IPtr += avail;
|
||||
sys.Copy(self.State.Input, self.State.InputPointer, buffer, pointer, avail);
|
||||
self.State.InputPointer += avail;
|
||||
pointer += avail;
|
||||
todo -= avail;
|
||||
}
|
||||
@@ -1340,7 +1276,7 @@ namespace LibMSPackSharp.CAB
|
||||
// Out of data, read a new block
|
||||
|
||||
// Check if we're out of input blocks, advance block counter
|
||||
if (self.State.Block++ >= self.State.Folder.NumBlocks)
|
||||
if (self.State.Block++ >= self.State.Folder.Header.NumBlocks)
|
||||
{
|
||||
if (!self.Salvage)
|
||||
self.ReadError = Error.MSPACK_ERR_DATAFORMAT;
|
||||
@@ -1361,10 +1297,10 @@ namespace LibMSPackSharp.CAB
|
||||
// to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
|
||||
// anything from 0 to 4 trailing null bytes.
|
||||
if ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_QUANTUM)
|
||||
self.State.Input[self.State.IEnd++] = 0xFF;
|
||||
self.State.Input[self.State.InputEnd++] = 0xFF;
|
||||
|
||||
// Is this the last block?
|
||||
if (self.State.Block >= self.State.Folder.NumBlocks)
|
||||
if (self.State.Block >= self.State.Folder.Header.NumBlocks)
|
||||
{
|
||||
if ((self.State.CompressionType & CompressionType.COMPTYPE_MASK) == CompressionType.COMPTYPE_LZX)
|
||||
{
|
||||
@@ -1387,12 +1323,21 @@ namespace LibMSPackSharp.CAB
|
||||
/// </summary>
|
||||
private static int SysWrite(object file, byte[] buffer, int pointer, int bytes)
|
||||
{
|
||||
DecompressorImpl self = file as DecompressorImpl;
|
||||
self.State.Offset += (uint)bytes;
|
||||
if (self.State.OutputFileHandle != null)
|
||||
return self.System.Write(self.State.OutputFileHandle, buffer, pointer, bytes);
|
||||
if (file is DecompressorImpl self)
|
||||
{
|
||||
self.State.Offset += (uint)bytes;
|
||||
if (self.State.OutputFileHandle != null)
|
||||
return self.System.Write(self.State.OutputFileHandle, buffer, pointer, bytes);
|
||||
|
||||
return bytes;
|
||||
return bytes;
|
||||
}
|
||||
else if (file is DefaultFileImpl impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Write(file, buffer, pointer, bytes);
|
||||
}
|
||||
|
||||
// Unknown file to write to
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1410,21 +1355,21 @@ namespace LibMSPackSharp.CAB
|
||||
int len, full_len;
|
||||
|
||||
// Reset the input block pointer and end of block pointer
|
||||
d.IPtr = d.IEnd = 0;
|
||||
d.InputPointer = d.InputEnd = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Read the block header
|
||||
if (sys.Read(d.InputFileHandle, hdr, 0, cfdata_SIZEOF) != cfdata_SIZEOF)
|
||||
if (SystemImpl.DefaultSystem.Read(d.InputFileHandle, hdr, 0, cfdata_SIZEOF) != cfdata_SIZEOF)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
// Skip any reserved block headers
|
||||
if (d.Data.Cab.HeaderResv != 0 && !sys.Seek(d.InputFileHandle, d.Data.Cab.HeaderResv, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
if (d.Data.Cab.Header.HeaderReserved != 0 && !sys.Seek(d.InputFileHandle, d.Data.Cab.Header.HeaderReserved, SeekMode.MSPACK_SYS_SEEK_CUR))
|
||||
return Error.MSPACK_ERR_SEEK;
|
||||
|
||||
// Blocks must not be over CAB_INPUTMAX in size
|
||||
len = BitConverter.ToUInt16(hdr, cfdata_CompressedSize);
|
||||
full_len = (d.IEnd - d.IPtr) + len; // Include cab-spanning blocks
|
||||
full_len = (d.InputEnd - d.InputPointer) + len; // Include cab-spanning blocks
|
||||
if (full_len > CAB_INPUTMAX)
|
||||
{
|
||||
Console.WriteLine($"block size {full_len} > CAB_INPUTMAX");
|
||||
@@ -1443,13 +1388,13 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Read the block data
|
||||
if (sys.Read(d.InputFileHandle, d.Input, d.IEnd, len) != len)
|
||||
if (SystemImpl.DefaultSystem.Read(d.InputFileHandle, d.Input, d.InputEnd, len) != len)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
// Perform checksum test on the block (if one is stored)
|
||||
if ((cksum = BitConverter.ToUInt32(hdr, cfdata_CheckSum)) != 0)
|
||||
{
|
||||
uint sum2 = Checksum(d.Input, d.IEnd, (uint)len, 0);
|
||||
uint sum2 = Checksum(d.Input, d.InputEnd, (uint)len, 0);
|
||||
if (Checksum(hdr, 4, 4, sum2) != cksum)
|
||||
{
|
||||
if (!ignore_cksum)
|
||||
@@ -1460,7 +1405,7 @@ namespace LibMSPackSharp.CAB
|
||||
}
|
||||
|
||||
// Advance end of block pointer to include newly read data
|
||||
d.IEnd += len;
|
||||
d.InputEnd += len;
|
||||
|
||||
// Uncompressed size == 0 means this block was part of a split block
|
||||
// and it continues as the first block of the next cabinet in the set.
|
||||
|
||||
@@ -23,6 +23,15 @@ namespace LibMSPackSharp.CAB
|
||||
/// </summary>
|
||||
public class InternalFile
|
||||
{
|
||||
#region Internal
|
||||
|
||||
/// <summary>
|
||||
/// File header information
|
||||
/// </summary>
|
||||
internal _FileHeader Header { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The next file in the cabinet or cabinet set, or NULL if this is the final file.
|
||||
/// </summary>
|
||||
@@ -34,57 +43,12 @@ namespace LibMSPackSharp.CAB
|
||||
/// 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"/>
|
||||
/// <see cref="_FileHeader.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; }
|
||||
}
|
||||
}
|
||||
|
||||
204
BurnOutSharp/External/libmspack/CAB/_CabinetHeader.cs
vendored
Normal file
204
BurnOutSharp/External/libmspack/CAB/_CabinetHeader.cs
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/* 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
|
||||
{
|
||||
internal class _CabinetHeader
|
||||
{
|
||||
#region Normal Header
|
||||
|
||||
/// <summary>
|
||||
/// "MSCF"
|
||||
/// </summary>
|
||||
/// <remarks>0x00</remarks>
|
||||
public uint Signature { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// UNKNOWN
|
||||
/// </summary>
|
||||
/// <remarks>0x04</remarks>
|
||||
public uint Reserved0 { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The length of the cabinet file in bytes.
|
||||
/// </summary>
|
||||
/// <remarks>0x08</remarks>
|
||||
public uint CabinetSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// UNKNOWN
|
||||
/// </summary>
|
||||
/// <remarks>0x0C</remarks>
|
||||
public uint Reserved1 { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// UNKNOWN
|
||||
/// </summary>
|
||||
/// <remarks>0x10</remarks>
|
||||
public uint FileOffset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// UNKNOWN
|
||||
/// </summary>
|
||||
/// <remarks>0x14</remarks>
|
||||
public uint Reserved2 { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minor cabinet version
|
||||
/// </summary>
|
||||
/// <remarks>0x18</remarks>
|
||||
public byte MinorVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Major cabinet version
|
||||
/// </summary>
|
||||
/// <remarks>0x19</remarks>
|
||||
public byte MajorVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of internal folders
|
||||
/// </summary>
|
||||
/// <remarks>0x1A</remarks>
|
||||
public ushort NumFolders { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of internal files
|
||||
/// </summary>
|
||||
/// <remarks>0x1C</remarks>
|
||||
public ushort NumFiles { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Header flags.
|
||||
/// </summary>
|
||||
/// <remarks>0x1E</remarks>
|
||||
/// <see cref="Cabinet.PreviousName"/>
|
||||
/// <see cref="Cabinet.PreviousInfo"/>
|
||||
/// <see cref="Cabinet.NextName"/>
|
||||
/// <see cref="Cabinet.NextInfo"/>
|
||||
/// <see cref="Cabinet.HeaderResv"/>
|
||||
public HeaderFlags Flags { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set ID of the cabinet. All cabinets in the same set should have
|
||||
/// the same set ID.
|
||||
/// </summary>
|
||||
/// <remarks>0x20</remarks>
|
||||
public ushort SetID { get; private 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>
|
||||
/// <remarks>0x22</remarks>
|
||||
public ushort CabinetIndex { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total size of the normal Cabinet header in bytes
|
||||
/// </summary>
|
||||
public const int Size = 0x24;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Extended Header
|
||||
|
||||
/// <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>
|
||||
/// <remarks>0x24</remarks>
|
||||
/// <see cref="Flags"/>
|
||||
public ushort HeaderReserved { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes reserved in the folder area of the cabinet
|
||||
/// </summary>
|
||||
/// <remarks>0x26</remarks>
|
||||
public byte FolderReserved { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes reserved in the data area of the cabinet
|
||||
/// </summary>
|
||||
/// <remarks>0x27</remarks>
|
||||
public byte DataReserved { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total size of the extended Cabinet header in bytes
|
||||
/// </summary>
|
||||
public const int ExtendedSize = 0x04;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
private _CabinetHeader() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a _CabinetHeader from a byte array, if possible
|
||||
/// </summary>
|
||||
public static Error Create(byte[] buffer, out _CabinetHeader header)
|
||||
{
|
||||
header = null;
|
||||
if (buffer == null || buffer.Length < Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
header = new _CabinetHeader();
|
||||
|
||||
header.Signature = BitConverter.ToUInt32(buffer, 0x00);
|
||||
if (header.Signature != 0x4643534D)
|
||||
return Error.MSPACK_ERR_SIGNATURE;
|
||||
|
||||
header.Reserved0 = BitConverter.ToUInt32(buffer, 0x04);
|
||||
header.CabinetSize = BitConverter.ToUInt32(buffer, 0x08);
|
||||
header.Reserved1 = BitConverter.ToUInt32(buffer, 0x0C);
|
||||
header.FileOffset = BitConverter.ToUInt32(buffer, 0x10);
|
||||
header.Reserved2 = BitConverter.ToUInt32(buffer, 0x14);
|
||||
|
||||
// Expect version 1.3, but don't validate
|
||||
header.MinorVersion = buffer[0x18];
|
||||
header.MajorVersion = buffer[0x19];
|
||||
|
||||
header.NumFolders = BitConverter.ToUInt16(buffer, 0x1A);
|
||||
if (header.NumFolders == 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
header.NumFiles = BitConverter.ToUInt16(buffer, 0x1C);
|
||||
if (header.NumFiles == 0)
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
header.Flags = (HeaderFlags)BitConverter.ToUInt16(buffer, 0x1E);
|
||||
header.SetID = BitConverter.ToUInt16(buffer, 0x20);
|
||||
header.CabinetIndex = BitConverter.ToUInt16(buffer, 0x20);
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate the extended header fields from buffer
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
public void PopulateExtendedHeader(byte[] buffer)
|
||||
{
|
||||
if (buffer.Length < ExtendedSize)
|
||||
return;
|
||||
|
||||
// Expect less than 60,000, but don't validate
|
||||
HeaderReserved = BitConverter.ToUInt16(buffer, 0x24);
|
||||
FolderReserved = buffer[0x26];
|
||||
DataReserved = buffer[0x27];
|
||||
}
|
||||
}
|
||||
}
|
||||
122
BurnOutSharp/External/libmspack/CAB/_FileHeader.cs
vendored
Normal file
122
BurnOutSharp/External/libmspack/CAB/_FileHeader.cs
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/* 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
|
||||
{
|
||||
internal class _FileHeader
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// The uncompressed length of the file, in bytes.
|
||||
/// </summary>
|
||||
/// <remarks>0x00</remarks>
|
||||
public uint UncompressedSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The uncompressed offset of this file in its folder.
|
||||
/// </summary>
|
||||
/// <remarks>0x04</remarks>
|
||||
public uint FolderOffset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal index of the folder
|
||||
/// </summary>
|
||||
/// <remarks>0x08</remarks>
|
||||
public FileFlags FolderIndex { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified date, day field.
|
||||
/// </summary>
|
||||
/// <remarks>0x0A</remarks>
|
||||
public byte LastModifiedDateDay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified date, month field.
|
||||
/// </summary>
|
||||
/// <remarks>0x0A</remarks>
|
||||
public byte LastModifiedDateMonth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified date, year field.
|
||||
/// </summary>
|
||||
/// <remarks>0x0A</remarks>
|
||||
public int LastModifiedDateYear { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified time, hour field.
|
||||
/// </summary>
|
||||
/// <remarks>0x0C</remarks>
|
||||
public byte LastModifiedTimeHour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified time, minute field.
|
||||
/// </summary>
|
||||
/// <remarks>0x0C</remarks>
|
||||
public byte LastModifiedTimeMinute { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File's last modified time, second field.
|
||||
/// </summary>
|
||||
/// <remarks>0x0C</remarks>
|
||||
public byte LastModifiedTimeSecond { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File attributes.
|
||||
/// </summary>
|
||||
/// <remarks>0x0E</remarks>
|
||||
public FileAttributes Attributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the File header in bytes
|
||||
/// </summary>
|
||||
public const int Size = 0x10;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
private _FileHeader() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a _Folder from a byte array, if possible
|
||||
/// </summary>
|
||||
public static Error Create(byte[] buffer, out _FileHeader header)
|
||||
{
|
||||
header = null;
|
||||
if (buffer == null || buffer.Length < Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
header = new _FileHeader();
|
||||
|
||||
header.UncompressedSize = BitConverter.ToUInt32(buffer, 0x00);
|
||||
header.FolderOffset = BitConverter.ToUInt32(buffer, 0x04);
|
||||
header.FolderIndex = (FileFlags)BitConverter.ToUInt16(buffer, 0x08);
|
||||
|
||||
// Get date
|
||||
ushort x = BitConverter.ToUInt16(buffer, 0x0A);
|
||||
header.LastModifiedDateDay = (byte)(x & 0x1F);
|
||||
header.LastModifiedDateMonth = (byte)((x >> 5) & 0xF);
|
||||
header.LastModifiedDateYear = (x >> 9) + 1980;
|
||||
|
||||
// Get time
|
||||
x = BitConverter.ToUInt16(buffer, 0x0C);
|
||||
header.LastModifiedTimeHour = (byte)(x >> 11);
|
||||
header.LastModifiedTimeMinute = (byte)((x >> 5) & 0x3F);
|
||||
header.LastModifiedTimeSecond = (byte)((x << 1) & 0x3E);
|
||||
|
||||
header.Attributes = (FileAttributes)BitConverter.ToUInt16(buffer, 0x0E);
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
BurnOutSharp/External/libmspack/CAB/_FolderHeader.cs
vendored
Normal file
72
BurnOutSharp/External/libmspack/CAB/_FolderHeader.cs
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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
|
||||
{
|
||||
internal class _FolderHeader
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Cabinet offset of first datablock
|
||||
/// </summary>
|
||||
/// <remarks>0x00</remarks>
|
||||
public uint DataOffset { get; internal 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>
|
||||
/// <remarks>0x04</remarks>
|
||||
public ushort NumBlocks { get; internal 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>
|
||||
/// <remarks>0x06</remarks>
|
||||
public CompressionType CompType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the Folder header in bytes
|
||||
/// </summary>
|
||||
public const int Size = 0x08;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
private _FolderHeader() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a _Folder from a byte array, if possible
|
||||
/// </summary>
|
||||
public static Error Create(byte[] buffer, out _FolderHeader header)
|
||||
{
|
||||
header = null;
|
||||
if (buffer == null || buffer.Length < Size)
|
||||
return Error.MSPACK_ERR_READ;
|
||||
|
||||
header = new _FolderHeader();
|
||||
|
||||
header.DataOffset = BitConverter.ToUInt32(buffer, 0x00);
|
||||
header.NumBlocks = BitConverter.ToUInt16(buffer, 0x04);
|
||||
header.CompType = (CompressionType)BitConverter.ToUInt16(buffer, 0x06);
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1154,12 +1154,21 @@ namespace LibMSPackSharp.CHM
|
||||
/// </summary>
|
||||
private static int SysWrite(object file, byte[] buffer, int offset, int bytes)
|
||||
{
|
||||
DecompressorImpl self = file as DecompressorImpl;
|
||||
self.State.Offset += bytes;
|
||||
if (self.State.OutputFileHandle != null)
|
||||
return self.System.Write(self.State.OutputFileHandle, buffer, offset, bytes);
|
||||
if (file is DecompressorImpl self)
|
||||
{
|
||||
self.State.Offset += (uint)bytes;
|
||||
if (self.State.OutputFileHandle != null)
|
||||
return self.System.Write(self.State.OutputFileHandle, buffer, offset, bytes);
|
||||
|
||||
return bytes;
|
||||
return bytes;
|
||||
}
|
||||
else if (file is DefaultFileImpl impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Write(file, buffer, offset, bytes);
|
||||
}
|
||||
|
||||
// Unknown file to write to
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -140,77 +140,104 @@ namespace LibMSPackSharp.Compression
|
||||
InputEnd = 0;
|
||||
}
|
||||
|
||||
public void STORE_BITS(int inputPointer, int inputLength, uint bitBuffer, uint bitsLeft)
|
||||
public void STORE_BITS(int inputPointer, int inputLength, uint bit_buffer, uint bits_left)
|
||||
{
|
||||
InputPointer = inputPointer;
|
||||
InputLength = inputLength;
|
||||
BitBuffer = bitBuffer;
|
||||
BitsLeft = bitsLeft;
|
||||
BitBuffer = bit_buffer;
|
||||
BitsLeft = bits_left;
|
||||
}
|
||||
|
||||
public void RESTORE_BITS(ref int inputPointer, ref int inputLength, ref uint bitBuffer, ref uint bitsLeft)
|
||||
public void RESTORE_BITS(ref int inputPointer, ref int inputLength, ref uint bit_buffer, ref uint bits_left)
|
||||
{
|
||||
inputPointer = InputPointer;
|
||||
inputLength = InputLength;
|
||||
bitBuffer = BitBuffer;
|
||||
bitsLeft = BitsLeft;
|
||||
bit_buffer = BitBuffer;
|
||||
bits_left = BitsLeft;
|
||||
}
|
||||
|
||||
public void ENSURE_BITS(int nbits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
public void ENSURE_BITS(int nbits, ref int i_ptr, ref int i_end, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
while (bitsLeft < nbits)
|
||||
while (bits_left < nbits)
|
||||
{
|
||||
READ_BYTES(ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
READ_BYTES(ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public void READ_BITS(ref int val, int nbits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
public void READ_BITS(ref int val, int nbits, ref int i_ptr, ref int i_end, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
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);
|
||||
ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
val = PEEK_BITS(nbits, bit_buffer, msb);
|
||||
REMOVE_BITS(nbits, ref bits_left, ref bit_buffer, msb);
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public Error READ_MANY_BITS(ref uint val, byte bits, ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
public void READ_MANY_BITS(ref uint val, byte bits, ref int i_ptr, ref int i_end, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
byte needed = bits, bitrun;
|
||||
val = 0;
|
||||
while (needed > 0)
|
||||
{
|
||||
if (bitsLeft <= (BITBUF_WIDTH - 16))
|
||||
if (bits_left <= (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;
|
||||
READ_BYTES(ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
bitrun = (byte)((bitsLeft < needed) ? bitsLeft : needed);
|
||||
val = (uint)((val << bitrun) | PEEK_BITS(bitrun, bitBuffer));
|
||||
REMOVE_BITS(bitrun, ref bitsLeft, ref bitBuffer);
|
||||
bitrun = (byte)((bits_left < needed) ? bits_left : needed);
|
||||
val = (uint)((val << bitrun) | PEEK_BITS(bitrun, bit_buffer, msb));
|
||||
REMOVE_BITS(bitrun, ref bits_left, ref bit_buffer, msb);
|
||||
needed -= bitrun;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public int PEEK_BITS(int nbits, uint bitBuffer)
|
||||
public int PEEK_BITS(int nbits, uint bit_buffer, bool msb)
|
||||
{
|
||||
return (int)(bitBuffer & ((1 << (nbits)) - 1));
|
||||
if (msb)
|
||||
return (int)(bit_buffer >> (BITBUF_WIDTH - (nbits)));
|
||||
else
|
||||
return (int)(bit_buffer & ((1 << (nbits)) - 1));
|
||||
}
|
||||
|
||||
public void REMOVE_BITS(int nbits, ref uint bitsLeft, ref uint bitBuffer)
|
||||
public void REMOVE_BITS(int nbits, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
bitBuffer >>= nbits;
|
||||
bitsLeft -= (uint)nbits;
|
||||
if (msb)
|
||||
{
|
||||
bit_buffer <<= nbits;
|
||||
bits_left -= (uint)nbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit_buffer >>= nbits;
|
||||
bits_left -= (uint)nbits;
|
||||
}
|
||||
}
|
||||
|
||||
public void INJECT_BITS(uint bitdata, int nbits, ref uint bitsLeft, ref uint bitBuffer)
|
||||
public void INJECT_BITS(uint bitdata, int nbits, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
bitBuffer |= bitdata << (int)bitsLeft;
|
||||
bitsLeft += (uint)nbits;
|
||||
if (msb)
|
||||
{
|
||||
bit_buffer |= bitdata << (int)bits_left;
|
||||
bits_left += (uint)nbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit_buffer |= bitdata << (int)bits_left;
|
||||
bits_left += (uint)nbits;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer);
|
||||
public abstract void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bits_left, ref uint bit_buffer, bool msb);
|
||||
|
||||
// lsb_bit_mask[n] = (1 << n) - 1 */
|
||||
private static readonly ushort[] lsb_bit_mask = new ushort[17]
|
||||
@@ -224,54 +251,63 @@ namespace LibMSPackSharp.Compression
|
||||
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)
|
||||
public void READ_BITS_T(ref int val, int nbits, ref int i_ptr, ref int i_end, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
ENSURE_BITS(nbits, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
val = PEEK_BITS_T(nbits);
|
||||
REMOVE_BITS(nbits, ref bitsLeft, ref bitBuffer);
|
||||
REMOVE_BITS(nbits, ref bits_left, ref bit_buffer, msb);
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public Error READ_IF_NEEDED(ref int iPtr, ref int iEnd)
|
||||
public void READ_IF_NEEDED(ref int i_ptr, ref int i_end)
|
||||
{
|
||||
if (iPtr >= iEnd)
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if (ReadInput(this) != Error.MSPACK_ERR_OK)
|
||||
return Error;
|
||||
ReadInput();
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
iPtr = InputPointer;
|
||||
iEnd = InputLength;
|
||||
i_ptr = InputPointer;
|
||||
i_end = InputLength;
|
||||
}
|
||||
|
||||
return Error.MSPACK_ERR_OK;
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
private static Error ReadInput(CompressionStream p)
|
||||
private void ReadInput()
|
||||
{
|
||||
int read = p.Sys.Read(p.Input, p.InputBuffer, 0, (int)p.InputBufferSize);
|
||||
int read = Sys.Read(Input, InputBuffer, 0, (int)InputBufferSize);
|
||||
if (read < 0)
|
||||
return p.Error = Error.MSPACK_ERR_READ;
|
||||
{
|
||||
Error = Error.MSPACK_ERR_READ;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)
|
||||
if (InputEnd != 0)
|
||||
{
|
||||
Console.WriteLine("out of input bytes");
|
||||
return p.Error = Error.MSPACK_ERR_READ;
|
||||
Error = Error.MSPACK_ERR_READ;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
read = 2;
|
||||
p.InputBuffer[0] = p.InputBuffer[1] = 0;
|
||||
p.InputEnd = 1;
|
||||
InputBuffer[0] = InputBuffer[1] = 0;
|
||||
InputEnd = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update i_ptr and i_end
|
||||
p.InputPointer = 0;
|
||||
p.InputLength = read;
|
||||
return Error.MSPACK_ERR_OK;
|
||||
InputPointer = 0;
|
||||
InputLength = read;
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -284,33 +320,50 @@ namespace LibMSPackSharp.Compression
|
||||
/// 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)
|
||||
public int READ_HUFFSYM(ushort[] decodingTable, ref uint var, int tablebits, byte[] lengthTable, int maxsymbols, ref int i, ref int i_ptr, ref int i_end, ref uint bits_left, ref uint bit_buffer, bool msb)
|
||||
{
|
||||
ENSURE_BITS(HUFF_MAXBITS, ref i_ptr, ref i_end, ref bitsLeft, ref bitBuffer);
|
||||
sym = decodingTable[PEEK_BITS(tablebits, bitBuffer)];
|
||||
ENSURE_BITS(HUFF_MAXBITS, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return (int)Error;
|
||||
|
||||
ushort sym = decodingTable[PEEK_BITS(tablebits, bit_buffer, msb)];
|
||||
if (sym >= maxsymbols)
|
||||
{
|
||||
int ret = HUFF_TRAVERSE(decodingTable, tablebits, maxsymbols, ref i, ref sym, bitBuffer);
|
||||
int ret = HUFF_TRAVERSE(decodingTable, tablebits, maxsymbols, ref i, ref sym, bit_buffer, msb);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
var = sym;
|
||||
i = lengthTable[sym];
|
||||
REMOVE_BITS(i, ref bitsLeft, ref bitBuffer);
|
||||
REMOVE_BITS(i, ref bits_left, ref bit_buffer, msb);
|
||||
return (int)Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public int HUFF_TRAVERSE(ushort[] decodingTable, int tablebits, int maxsymbols, ref int i, ref ushort sym, uint bitBuffer)
|
||||
public int HUFF_TRAVERSE(ushort[] decodingTable, int tablebits, int maxsymbols, ref int i, ref ushort sym, uint bit_buffer, bool msb)
|
||||
{
|
||||
i = tablebits - 1;
|
||||
do
|
||||
if (msb)
|
||||
{
|
||||
if (i++ > HUFF_MAXBITS)
|
||||
return HUFF_ERROR();
|
||||
i = 1 << (BITBUF_WIDTH - tablebits);
|
||||
do
|
||||
{
|
||||
if ((i >>= 1) == 0)
|
||||
return HUFF_ERROR();
|
||||
|
||||
sym = decodingTable[(sym << 1) | ((bitBuffer >> i) & 1)];
|
||||
} while (sym >= maxsymbols);
|
||||
sym = decodingTable[(sym << 1) | ((bit_buffer & i) != 0 ? 1 : 0)];
|
||||
} while (sym >= maxsymbols);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = tablebits - 1;
|
||||
do
|
||||
{
|
||||
if (i++ > HUFF_MAXBITS)
|
||||
return HUFF_ERROR();
|
||||
|
||||
try { sym = decodingTable[(sym << 1) | ((bit_buffer >> i) & 1)]; } catch { }
|
||||
} while (sym >= maxsymbols);
|
||||
}
|
||||
|
||||
return (int)Error.MSPACK_ERR_OK;
|
||||
}
|
||||
@@ -330,94 +383,84 @@ namespace LibMSPackSharp.Compression
|
||||
/// 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)
|
||||
/// <returns>true for OK or false for error</returns>
|
||||
public static bool MakeDecodeTable(int nsyms, int nbits, byte[] length, ushort[] table, bool msb)
|
||||
{
|
||||
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
|
||||
int next_symbol;
|
||||
long leaf, fill;
|
||||
long reverse; // Only used when !msb
|
||||
long pos = 0; // The current position in the decode table
|
||||
int table_mask = 1 << nbits;
|
||||
long 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 (byte bit_num = 1; bit_num <= nbits; bit_num++)
|
||||
{
|
||||
for (sym = 0; sym < nsyms; sym++)
|
||||
for (ushort 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
|
||||
if (msb)
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
leaf = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reverse the significant bits
|
||||
fill = length[sym];
|
||||
reverse = pos >> (nbits - (byte)fill);
|
||||
leaf = 0;
|
||||
|
||||
do
|
||||
{
|
||||
leaf <<= 1;
|
||||
leaf |= reverse & 1;
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
}
|
||||
|
||||
if ((pos += bit_mask) > table_mask)
|
||||
return 1; // Table overrun
|
||||
return false; // Table overrun
|
||||
|
||||
// Fill all possible lookups of this symbol with the symbol itself
|
||||
fill = bit_mask;
|
||||
next_symbol = (ushort)(1 << bit_num);
|
||||
|
||||
do
|
||||
if (msb)
|
||||
{
|
||||
table[leaf] = sym;
|
||||
leaf += next_symbol;
|
||||
} while (--fill != 0);
|
||||
for (fill = bit_mask; fill-- > 0;)
|
||||
{
|
||||
table[leaf++] = sym;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fill = bit_mask;
|
||||
next_symbol = 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;
|
||||
return true;
|
||||
|
||||
// Mark all remaining table entries as unused
|
||||
for (sym = (ushort)pos; sym < table_mask; sym++)
|
||||
for (long sym = pos; sym < table_mask; sym++)
|
||||
{
|
||||
reverse = sym;
|
||||
leaf = 0;
|
||||
fill = nbits;
|
||||
|
||||
do
|
||||
if (msb)
|
||||
{
|
||||
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++)
|
||||
table[sym] = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
reverse = sym;
|
||||
leaf = 0;
|
||||
fill = nbits;
|
||||
|
||||
@@ -428,19 +471,60 @@ namespace LibMSPackSharp.Compression
|
||||
reverse >>= 1;
|
||||
} while (--fill != 0);
|
||||
|
||||
table[leaf] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
// next_symbol = base of allocation for long codes
|
||||
next_symbol = ((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 (int bit_num = nbits + 1; bit_num <= HUFF_MAXBITS; bit_num++)
|
||||
{
|
||||
for (ushort sym = 0; sym < nsyms; sym++)
|
||||
{
|
||||
if (length[sym] != bit_num)
|
||||
continue;
|
||||
if (pos >= table_mask)
|
||||
return false; // Table overflow
|
||||
|
||||
if (msb)
|
||||
{
|
||||
leaf = pos >> 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 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++;
|
||||
table[leaf] = (ushort)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] << 1;
|
||||
if (((pos >> (15 - (int)fill)) & 1) != 0)
|
||||
leaf++;
|
||||
}
|
||||
|
||||
@@ -452,7 +536,7 @@ namespace LibMSPackSharp.Compression
|
||||
}
|
||||
|
||||
// Full table?
|
||||
return (pos == table_mask) ? 0 : 1;
|
||||
return pos == table_mask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
178
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
178
BurnOutSharp/External/libmspack/Compression/LZX.cs
vendored
@@ -95,13 +95,13 @@ namespace LibMSPackSharp.Compression
|
||||
// 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 byte LZX_PRETREE_TABLEBITS = 6;
|
||||
public const int LZX_MAINTREE_MAXSYMBOLS = LZX_NUM_CHARS + 290 * 8;
|
||||
public const int LZX_MAINTREE_TABLEBITS = 12;
|
||||
public const byte LZX_MAINTREE_TABLEBITS = 12;
|
||||
public const int LZX_LENGTH_MAXSYMBOLS = LZX_NUM_SECONDARY_LENGTHS + 1;
|
||||
public const int LZX_LENGTH_TABLEBITS = 12;
|
||||
public const byte LZX_LENGTH_TABLEBITS = 12;
|
||||
public const int LZX_ALIGNED_MAXSYMBOLS = LZX_ALIGNED_NUM_ELEMENTS;
|
||||
public const int LZX_ALIGNED_TABLEBITS = 7;
|
||||
public const byte 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
|
||||
@@ -433,7 +433,6 @@ namespace LibMSPackSharp.Compression
|
||||
// Bitstream and huffman reading variables
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
ushort sym = 0;
|
||||
|
||||
int match_length, extra, verbatim_bits = 0, bytes_todo;
|
||||
int this_run, j = 0, warned = 0;
|
||||
@@ -502,8 +501,11 @@ namespace LibMSPackSharp.Compression
|
||||
// LZX DELTA format has chunk_size, not present in LZX format
|
||||
if (lzx.IsDelta)
|
||||
{
|
||||
lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.REMOVE_BITS(16, ref bits_left, ref bit_buffer);
|
||||
lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.REMOVE_BITS(16, ref bits_left, ref bit_buffer, msb: true);
|
||||
}
|
||||
|
||||
// Read header if necessary
|
||||
@@ -512,11 +514,19 @@ namespace LibMSPackSharp.Compression
|
||||
/* read 1 bit. if bit=0, intel filesize = 0.
|
||||
* if bit=1, read intel filesize (32 bits) */
|
||||
j = 0;
|
||||
lzx.READ_BITS(ref i, 1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref i, 1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
lzx.READ_BITS(ref i, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref j, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref i, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.READ_BITS(ref j, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
}
|
||||
|
||||
lzx.IntelFileSize = (i << 16) | j;
|
||||
@@ -549,10 +559,19 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Read block type (3 bits) and block length (24 bits)
|
||||
int blockType = 0;
|
||||
lzx.READ_BITS(ref blockType, 3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref blockType, 3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.BlockType = (LZXBlockType)blockType;
|
||||
lzx.READ_BITS(ref i, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref j, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref i, 16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.READ_BITS(ref j, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.BlockRemaining = lzx.BlockLength = (uint)((i << 8) | j);
|
||||
// Console.WriteLine("new block t%d len %u", lzx.BlockType, lzx.BlockLength);
|
||||
|
||||
@@ -563,12 +582,15 @@ namespace LibMSPackSharp.Compression
|
||||
case LZXBlockType.LZX_BLOCKTYPE_ALIGNED:
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
lzx.READ_BITS(ref j, 3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref j, 3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.ALIGNED_len[i] = (byte)j;
|
||||
}
|
||||
|
||||
//BUILD_TABLE(ALIGNED)
|
||||
if (LZXDStream.MakeDecodeTable(LZX_ALIGNED_MAXSYMBOLS, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, lzx.ALIGNED_table) != 0)
|
||||
if (!LZXDStream.MakeDecodeTable(LZX_ALIGNED_MAXSYMBOLS, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, lzx.ALIGNED_table, msb: true))
|
||||
{
|
||||
Console.WriteLine("failed to build ALIGNED table");
|
||||
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
@@ -589,7 +611,7 @@ namespace LibMSPackSharp.Compression
|
||||
lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
//BUILD_TABLE(MAINTREE)
|
||||
if (LZXDStream.MakeDecodeTable(LZX_MAINTREE_MAXSYMBOLS, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, lzx.MAINTREE_table) != 0)
|
||||
if (!LZXDStream.MakeDecodeTable(LZX_MAINTREE_MAXSYMBOLS, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, lzx.MAINTREE_table, msb: true))
|
||||
{
|
||||
Console.WriteLine("failed to build MAINTREE table");
|
||||
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
@@ -609,7 +631,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
//BUILD_TABLE_MAYBE_EMPTY(LENGTH)
|
||||
lzx.LENGTH_empty = 0;
|
||||
if (LZXDStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table) != 0)
|
||||
if (!LZXDStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true))
|
||||
{
|
||||
for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
@@ -642,7 +664,7 @@ namespace LibMSPackSharp.Compression
|
||||
lzx.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
|
||||
//BUILD_TABLE(MAINTREE)
|
||||
if (LZXDStream.MakeDecodeTable(LZX_MAINTREE_MAXSYMBOLS, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, lzx.MAINTREE_table) != 0)
|
||||
if (!LZXDStream.MakeDecodeTable(LZX_MAINTREE_MAXSYMBOLS, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, lzx.MAINTREE_table, msb: true))
|
||||
{
|
||||
Console.WriteLine("failed to build MAINTREE table");
|
||||
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
@@ -662,7 +684,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
//BUILD_TABLE_MAYBE_EMPTY(LENGTH)
|
||||
lzx.LENGTH_empty = 0;
|
||||
if (LZXDStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table) != 0)
|
||||
if (!LZXDStream.MakeDecodeTable(LZX_LENGTH_MAXSYMBOLS, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, lzx.LENGTH_table, msb: true))
|
||||
{
|
||||
for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)
|
||||
{
|
||||
@@ -685,7 +707,11 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Read 1-16 (not 0-15) bits to align to bytes
|
||||
if (bits_left == 0)
|
||||
lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
{
|
||||
lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
}
|
||||
|
||||
bits_left = 0; bit_buffer = 0;
|
||||
|
||||
@@ -728,7 +754,9 @@ namespace LibMSPackSharp.Compression
|
||||
case LZXBlockType.LZX_BLOCKTYPE_VERBATIM:
|
||||
while (this_run > 0)
|
||||
{
|
||||
lzx.READ_HUFFSYM(lzx.MAINTREE_table, ref main_element, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, LZX_MAINTREE_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzx.READ_HUFFSYM(lzx.MAINTREE_table, ref main_element, LZX_MAINTREE_TABLEBITS, lzx.MAINTREE_len, LZX_MAINTREE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
if (main_element < LZX_NUM_CHARS)
|
||||
{
|
||||
// Literal: 0 to LZX_NUM_CHARS-1
|
||||
@@ -750,7 +778,9 @@ namespace LibMSPackSharp.Compression
|
||||
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
lzx.READ_HUFFSYM(lzx.LENGTH_table, ref length_footer, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, LZX_LENGTH_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzx.READ_HUFFSYM(lzx.LENGTH_table, ref length_footer, LZX_LENGTH_TABLEBITS, lzx.LENGTH_len, LZX_LENGTH_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
match_length += (int)length_footer;
|
||||
}
|
||||
|
||||
@@ -772,7 +802,10 @@ namespace LibMSPackSharp.Compression
|
||||
else
|
||||
{
|
||||
extra = (match_offset >= 36) ? 17 : extra_bits[match_offset];
|
||||
lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
match_offset = (uint)(position_base[match_offset] - 2 + verbatim_bits);
|
||||
}
|
||||
}
|
||||
@@ -786,21 +819,31 @@ namespace LibMSPackSharp.Compression
|
||||
{
|
||||
// >3: verbatim and aligned bits
|
||||
extra -= 3;
|
||||
lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
match_offset += (uint)(verbatim_bits << 3);
|
||||
lzx.READ_HUFFSYM(lzx.ALIGNED_table, ref aligned_bits, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, LZX_ALIGNED_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzx.READ_HUFFSYM(lzx.ALIGNED_table, ref aligned_bits, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, LZX_ALIGNED_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
match_offset += aligned_bits;
|
||||
}
|
||||
else if (extra == 3)
|
||||
{
|
||||
// 3: aligned bits only
|
||||
lzx.READ_HUFFSYM(lzx.ALIGNED_table, ref aligned_bits, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, LZX_ALIGNED_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzx.READ_HUFFSYM(lzx.ALIGNED_table, ref aligned_bits, LZX_ALIGNED_TABLEBITS, lzx.ALIGNED_len, LZX_ALIGNED_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
match_offset += aligned_bits;
|
||||
}
|
||||
else if (extra > 0)
|
||||
{
|
||||
// 1-2: verbatim bits only
|
||||
lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref verbatim_bits, extra, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
match_offset += (uint)verbatim_bits;
|
||||
}
|
||||
else
|
||||
@@ -819,28 +862,43 @@ namespace LibMSPackSharp.Compression
|
||||
if (match_length == LZX_MAX_MATCH && lzx.IsDelta)
|
||||
{
|
||||
int extra_len = 0;
|
||||
lzx.ENSURE_BITS(3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer); /* 4 entry huffman tree */
|
||||
if (lzx.PEEK_BITS(1, bit_buffer) == 0)
|
||||
|
||||
/* 4 entry huffman tree */
|
||||
lzx.ENSURE_BITS(3, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
if (lzx.PEEK_BITS(1, bit_buffer, msb: true) == 0)
|
||||
{
|
||||
lzx.REMOVE_BITS(1, ref bits_left, ref bit_buffer); /* '0' . 8 extra length bits */
|
||||
lzx.READ_BITS(ref extra_len, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.REMOVE_BITS(1, ref bits_left, ref bit_buffer, msb: true); /* '0' . 8 extra length bits */
|
||||
lzx.READ_BITS(ref extra_len, 8, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
}
|
||||
else if (lzx.PEEK_BITS(2, bit_buffer) == 2)
|
||||
else if (lzx.PEEK_BITS(2, bit_buffer, msb: true) == 2)
|
||||
{
|
||||
lzx.REMOVE_BITS(2, ref bits_left, ref bit_buffer); /* '10' . 10 extra length bits + 0x100 */
|
||||
lzx.READ_BITS(ref extra_len, 10, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.REMOVE_BITS(2, ref bits_left, ref bit_buffer, msb: true); /* '10' . 10 extra length bits + 0x100 */
|
||||
lzx.READ_BITS(ref extra_len, 10, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
extra_len += 0x100;
|
||||
}
|
||||
else if (lzx.PEEK_BITS(3, bit_buffer) == 6)
|
||||
else if (lzx.PEEK_BITS(3, bit_buffer, msb: true) == 6)
|
||||
{
|
||||
lzx.REMOVE_BITS(3, ref bits_left, ref bit_buffer); /* '110' . 12 extra length bits + 0x500 */
|
||||
lzx.READ_BITS(ref extra_len, 12, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.REMOVE_BITS(3, ref bits_left, ref bit_buffer, msb: true); /* '110' . 12 extra length bits + 0x500 */
|
||||
lzx.READ_BITS(ref extra_len, 12, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
extra_len += 0x500;
|
||||
}
|
||||
else
|
||||
{
|
||||
lzx.REMOVE_BITS(3, ref bits_left, ref bit_buffer); /* '111' . 15 extra length bits */
|
||||
lzx.READ_BITS(ref extra_len, 15, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.REMOVE_BITS(3, ref bits_left, ref bit_buffer, msb: true); /* '111' . 15 extra length bits */
|
||||
lzx.READ_BITS(ref extra_len, 15, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
}
|
||||
|
||||
match_length += extra_len;
|
||||
@@ -960,10 +1018,14 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Re-align input bitstream
|
||||
if (bits_left > 0)
|
||||
lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
{
|
||||
lzx.ENSURE_BITS(16, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
}
|
||||
|
||||
if ((bits_left & 15) != 0)
|
||||
lzx.REMOVE_BITS((int)(bits_left & 15), ref bits_left, ref bit_buffer);
|
||||
lzx.REMOVE_BITS((int)(bits_left & 15), ref bits_left, ref bit_buffer, msb: true);
|
||||
|
||||
// Check that we've used all of the previous frame first
|
||||
if (lzx.OutputPointer != lzx.OutputLength)
|
||||
@@ -1072,7 +1134,6 @@ namespace LibMSPackSharp.Compression
|
||||
// Bit buffer and huffman symbol decode variables
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
int i = 0;
|
||||
ushort sym = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
|
||||
int x, y = 0;
|
||||
@@ -1083,12 +1144,15 @@ namespace LibMSPackSharp.Compression
|
||||
// Read lengths for pretree (20 symbols, lengths stored in fixed 4 bits)
|
||||
for (x = 0; x < 20; x++)
|
||||
{
|
||||
lzx.READ_BITS(ref y, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
lzx.READ_BITS(ref y, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
lzx.PRETREE_len[x] = (byte)y;
|
||||
}
|
||||
|
||||
//BUILD_TABLE(PRETREE)
|
||||
if (LZXDStream.MakeDecodeTable(LZX_PRETREE_MAXSYMBOLS, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, lzx.PRETREE_table) != 0)
|
||||
if (!LZXDStream.MakeDecodeTable(LZX_PRETREE_MAXSYMBOLS, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, lzx.PRETREE_table, msb: true))
|
||||
{
|
||||
Console.WriteLine("failed to build PRETREE table");
|
||||
return lzx.Error = Error.MSPACK_ERR_DECRUNCH;
|
||||
@@ -1096,11 +1160,17 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
for (x = (int)first; x < last;)
|
||||
{
|
||||
lzx.READ_HUFFSYM(lzx.PRETREE_table, ref z, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, LZX_PRETREE_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
if (lzx.READ_HUFFSYM(lzx.PRETREE_table, ref z, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, LZX_PRETREE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
if (z == 17)
|
||||
{
|
||||
// Code = 17, run of ([read 4 bits]+4) zeros
|
||||
lzx.READ_BITS(ref y, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); y += 4;
|
||||
lzx.READ_BITS(ref y, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
y += 4;
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = 0;
|
||||
@@ -1109,7 +1179,11 @@ namespace LibMSPackSharp.Compression
|
||||
else if (z == 18)
|
||||
{
|
||||
// Code = 18, run of ([read 5 bits]+20) zeros
|
||||
lzx.READ_BITS(ref y, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); y += 20;
|
||||
lzx.READ_BITS(ref y, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
y += 20;
|
||||
while (y-- != 0)
|
||||
{
|
||||
lens[x++] = 0;
|
||||
@@ -1118,8 +1192,14 @@ namespace LibMSPackSharp.Compression
|
||||
else if (z == 19)
|
||||
{
|
||||
// Code = 19, run of ([read 1 bit]+4) [read huffman symbol]
|
||||
lzx.READ_BITS(ref y, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left); y += 4;
|
||||
lzx.READ_HUFFSYM(lzx.PRETREE_table, ref z, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, LZX_PRETREE_MAXSYMBOLS, ref i, ref sym, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer);
|
||||
lzx.READ_BITS(ref y, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzx.Error != Error.MSPACK_ERR_OK)
|
||||
return lzx.Error;
|
||||
|
||||
y += 4;
|
||||
if (lzx.READ_HUFFSYM(lzx.PRETREE_table, ref z, LZX_PRETREE_TABLEBITS, lzx.PRETREE_len, LZX_PRETREE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
|
||||
z = lens[x] - z;
|
||||
if (z < 0)
|
||||
z += 17;
|
||||
|
||||
@@ -137,21 +137,21 @@ namespace LibMSPackSharp.Compression
|
||||
// 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)
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer, bool msb)
|
||||
{
|
||||
Error error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
byte b0 = InputBuffer[i_ptr++];
|
||||
|
||||
error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
byte b1 = InputBuffer[i_ptr++];
|
||||
INJECT_BITS((uint)((b1 << 8) | b0), 16, ref bitsLeft, ref bitBuffer);
|
||||
return Error.MSPACK_ERR_OK;
|
||||
INJECT_BITS((uint)((b1 << 8) | b0), 16, ref bitsLeft, ref bitBuffer, msb);
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)(Error = Error.MSPACK_ERR_DECRUNCH);
|
||||
|
||||
182
BurnOutSharp/External/libmspack/Compression/MSZIP.cs
vendored
182
BurnOutSharp/External/libmspack/Compression/MSZIP.cs
vendored
@@ -27,27 +27,12 @@ namespace LibMSPackSharp.Compression
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
//public const int MSZIP_LITERAL_TABLESIZE = (MSZIP_LITERAL_MAXSYMBOLS * 4);
|
||||
public const int MSZIP_LITERAL_TABLESIZE = ((1 << MSZIP_LITERAL_TABLEBITS) + (MSZIP_LITERAL_MAXSYMBOLS * 2));
|
||||
|
||||
//public const int MSZIP_DISTANCE_TABLESIZE = (MSZIP_DISTANCE_MAXSYMBOLS * 4);
|
||||
public const int MSZIP_DISTANCE_TABLESIZE = ((1 << MSZIP_DISTANCE_TABLEBITS) + (MSZIP_DISTANCE_MAXSYMBOLS * 2));
|
||||
|
||||
/// <summary>
|
||||
/// Match lengths for literal codes 257.. 285
|
||||
@@ -203,12 +188,15 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Skip to next read 'CK' header
|
||||
i = (int)(bits_left & 7);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer); // Align to bytestream
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer, msb: false); // Align to bytestream
|
||||
state = 0;
|
||||
|
||||
do
|
||||
{
|
||||
zip.READ_BITS(ref i, 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, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return zip.Error;
|
||||
|
||||
if (i == 'C')
|
||||
state = 1;
|
||||
else if ((state == 1) && (i == 'K'))
|
||||
@@ -224,7 +212,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
if ((error = (int)Inflate(zip)) != 0)
|
||||
{
|
||||
Console.WriteLine($"inflate error {error}");
|
||||
Console.WriteLine($"inflate error {(InflateErrorCode)error}");
|
||||
if (zip.RepairMode)
|
||||
{
|
||||
// Recover partially-inflated buffers
|
||||
@@ -249,8 +237,16 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Write a frame
|
||||
i = (out_bytes < zip.BytesOutput) ? (int)out_bytes : zip.BytesOutput;
|
||||
if (zip.Sys.Write(zip.Output, zip.Window, zip.OutputPointer, i) != i)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
if (zip.Output is DefaultFileImpl)
|
||||
{
|
||||
if (SystemImpl.DefaultSystem.Write(zip.Output, zip.Window, zip.OutputPointer, i) != i)
|
||||
return zip.Error = Error.MSPACK_ERR_WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
@@ -288,20 +284,30 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// 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);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer, msb: false);
|
||||
zip.READ_BITS(ref block_len, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return zip.Error;
|
||||
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return zip.Error;
|
||||
|
||||
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);
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return zip.Error;
|
||||
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);
|
||||
zip.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return zip.Error;
|
||||
if (i != 'K')
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
@@ -311,7 +317,7 @@ namespace LibMSPackSharp.Compression
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
if ((error = (int)Inflate(zip)) != 0)
|
||||
{
|
||||
Console.WriteLine($"inflate error {error}");
|
||||
Console.WriteLine($"inflate error {(InflateErrorCode)error}");
|
||||
return zip.Error = (error > 0) ? (Error)error : Error.MSPACK_ERR_DECRUNCH;
|
||||
}
|
||||
|
||||
@@ -339,7 +345,7 @@ namespace LibMSPackSharp.Compression
|
||||
}
|
||||
}
|
||||
|
||||
private static InflateErrorCode ZipReadLens(MSZIPDStream zip)
|
||||
private static InflateErrorCode ReadLens(MSZIPDStream zip)
|
||||
{
|
||||
// For the bit buffer and huffman decoding
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
@@ -355,11 +361,20 @@ namespace LibMSPackSharp.Compression
|
||||
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);
|
||||
zip.READ_BITS(ref lit_codes, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
lit_codes += 257;
|
||||
zip.READ_BITS(ref dist_codes, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
zip.READ_BITS(ref dist_codes, 5, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
dist_codes += 1;
|
||||
zip.READ_BITS(ref bitlen_codes, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
zip.READ_BITS(ref bitlen_codes, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
bitlen_codes += 4;
|
||||
|
||||
if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS)
|
||||
@@ -371,7 +386,10 @@ namespace LibMSPackSharp.Compression
|
||||
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);
|
||||
zip.READ_BITS(ref blLenTemp, 3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
bl_len[bitlen_order[i]] = (byte)blLenTemp;
|
||||
}
|
||||
|
||||
@@ -380,17 +398,20 @@ namespace LibMSPackSharp.Compression
|
||||
bl_len[bitlen_order[i++]] = 0;
|
||||
}
|
||||
|
||||
// Create decoding table with an immediate lookup */
|
||||
if (MSZIPDStream.MakeDecodeTable(19, 7, bl_len, bl_table) != 0)
|
||||
// Create decoding table with an immediate lookup
|
||||
if (!MSZIPDStream.MakeDecodeTable(19, 7, bl_len, bl_table, msb: false))
|
||||
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);
|
||||
zip.ENSURE_BITS(7, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITBUF;
|
||||
|
||||
code = bl_table[zip.PEEK_BITS(7, bit_buffer, msb: false)];
|
||||
zip.REMOVE_BITS(bl_len[code], ref bits_left, ref bit_buffer, msb: false);
|
||||
|
||||
if (code < 16)
|
||||
{
|
||||
@@ -401,19 +422,28 @@ namespace LibMSPackSharp.Compression
|
||||
switch (code)
|
||||
{
|
||||
case 16:
|
||||
zip.READ_BITS(ref run, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
zip.READ_BITS(ref run, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
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);
|
||||
zip.READ_BITS(ref run, 3, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
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);
|
||||
zip.READ_BITS(ref run, 7, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
run += 11;
|
||||
code = 0;
|
||||
break;
|
||||
@@ -463,18 +493,22 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// For the bit buffer and huffman decoding
|
||||
uint bit_buffer = 0, bits_left = 0;
|
||||
ushort sym = 0;
|
||||
int i_ptr = 0, i_end = 0;
|
||||
InflateErrorCode err;
|
||||
|
||||
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);
|
||||
zip.READ_BITS(ref last_block, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
// Read in block type
|
||||
zip.READ_BITS(ref block_type, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
zip.READ_BITS(ref block_type, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITOVERRUN;
|
||||
|
||||
if (block_type == 0)
|
||||
{
|
||||
@@ -483,7 +517,7 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// Go to byte boundary
|
||||
i = (int)(bits_left & 7);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer);
|
||||
zip.REMOVE_BITS(i, ref bits_left, ref bit_buffer, msb: false);
|
||||
|
||||
// Read 4 bytes of data, emptying the bit-buffer if necessary
|
||||
for (i = 0; (bits_left >= 8); i++)
|
||||
@@ -491,13 +525,19 @@ namespace LibMSPackSharp.Compression
|
||||
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);
|
||||
lens_buf[i] = (byte)zip.PEEK_BITS(8, bit_buffer, msb: false);
|
||||
zip.REMOVE_BITS(8, ref bits_left, ref bit_buffer, msb: false);
|
||||
}
|
||||
if (bits_left != 0) return InflateErrorCode.INF_ERR_BITBUF;
|
||||
|
||||
if (bits_left != 0)
|
||||
return InflateErrorCode.INF_ERR_BITBUF;
|
||||
|
||||
while (i < 4)
|
||||
{
|
||||
zip.READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITBUF;
|
||||
|
||||
lens_buf[i++] = zip.InputBuffer[i_ptr++];
|
||||
}
|
||||
|
||||
@@ -511,9 +551,13 @@ namespace LibMSPackSharp.Compression
|
||||
while (length > 0)
|
||||
{
|
||||
zip.READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_BITBUF;
|
||||
|
||||
this_run = length;
|
||||
if (this_run > (uint)(i_end - i_ptr)) this_run = i_end - i_ptr;
|
||||
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);
|
||||
|
||||
@@ -571,7 +615,7 @@ namespace LibMSPackSharp.Compression
|
||||
// Block with dynamic Huffman codes
|
||||
zip.STORE_BITS(i_ptr, i_end, bit_buffer, bits_left);
|
||||
|
||||
if ((i = (int)ZipReadLens(zip)) != 0)
|
||||
if ((i = (int)ReadLens(zip)) != 0)
|
||||
return (InflateErrorCode)i;
|
||||
|
||||
zip.RESTORE_BITS(ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
@@ -579,16 +623,24 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
// 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_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, zip.LITERAL_table, msb: false))
|
||||
{
|
||||
// TODO: Figure out why this always gets hit
|
||||
//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;
|
||||
if (!MSZIPDStream.MakeDecodeTable(MSZIP_DISTANCE_MAXSYMBOLS, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, zip.DISTANCE_table, msb: false))
|
||||
{
|
||||
// TODO: Figure out why this always gets hit
|
||||
//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 ((err = (InflateErrorCode)zip.READ_HUFFSYM(zip.LITERAL_table, ref code, MSZIP_LITERAL_TABLEBITS, zip.LITERAL_len, MSZIP_LITERAL_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: false)) != InflateErrorCode.INF_ERR_OK)
|
||||
return err;
|
||||
|
||||
if (code < 256)
|
||||
{
|
||||
zip.Window[zip.WindowPosition++] = (byte)code;
|
||||
@@ -613,14 +665,22 @@ namespace LibMSPackSharp.Compression
|
||||
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);
|
||||
zip.READ_BITS_T(ref length, lit_extrabits[code], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_LITCODE;
|
||||
|
||||
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 ((err = (InflateErrorCode)zip.READ_HUFFSYM(zip.DISTANCE_table, ref code, MSZIP_DISTANCE_TABLEBITS, zip.DISTANCE_len, MSZIP_DISTANCE_MAXSYMBOLS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: false)) != 0)
|
||||
return err;
|
||||
|
||||
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);
|
||||
zip.READ_BITS_T(ref distance, dist_extrabits[code], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: false);
|
||||
if (zip.Error != Error.MSPACK_ERR_OK)
|
||||
return InflateErrorCode.INF_ERR_DISTCODE;
|
||||
|
||||
distance += dist_offsets[code];
|
||||
|
||||
// Match position is window position minus distance. If distance
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
#endregion
|
||||
|
||||
public override Error READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer)
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer, bool msb)
|
||||
{
|
||||
Error error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
INJECT_BITS(InputBuffer[i_ptr++], 8, ref bitsLeft, ref bitBuffer);
|
||||
return Error.MSPACK_ERR_OK;
|
||||
INJECT_BITS(InputBuffer[i_ptr++], 8, ref bitsLeft, ref bitBuffer, msb);
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)InflateErrorCode.INF_ERR_HUFFSYM;
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace LibMSPackSharp.Compression
|
||||
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);
|
||||
qtm.READ_BITS(ref tempCurrent, 16, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
current = (ushort)tempCurrent;
|
||||
qtm.HeaderRead = 1;
|
||||
}
|
||||
@@ -266,7 +266,10 @@ namespace LibMSPackSharp.Compression
|
||||
// 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);
|
||||
qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (qtm.Error != Error.MSPACK_ERR_OK)
|
||||
return qtm.Error;
|
||||
|
||||
match_offset = position_base[sym] + extra + 1;
|
||||
match_length = 3;
|
||||
break;
|
||||
@@ -274,7 +277,10 @@ namespace LibMSPackSharp.Compression
|
||||
// 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);
|
||||
qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (qtm.Error != Error.MSPACK_ERR_OK)
|
||||
return qtm.Error;
|
||||
|
||||
match_offset = position_base[sym] + extra + 1;
|
||||
match_length = 4;
|
||||
break;
|
||||
@@ -282,11 +288,17 @@ namespace LibMSPackSharp.Compression
|
||||
// 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);
|
||||
qtm.READ_MANY_BITS(ref extra, length_extra[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (qtm.Error != Error.MSPACK_ERR_OK)
|
||||
return qtm.Error;
|
||||
|
||||
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);
|
||||
qtm.READ_MANY_BITS(ref extra, extra_bits[sym], ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (qtm.Error != Error.MSPACK_ERR_OK)
|
||||
return qtm.Error;
|
||||
|
||||
match_offset = position_base[sym] + extra + 1;
|
||||
break;
|
||||
|
||||
@@ -407,14 +419,14 @@ namespace LibMSPackSharp.Compression
|
||||
{
|
||||
// Re-align input
|
||||
if ((bits_left & 7) != 0)
|
||||
qtm.REMOVE_BITS((int)bits_left & 7, ref bits_left, ref bit_buffer);
|
||||
qtm.REMOVE_BITS((int)bits_left & 7, ref bits_left, ref bit_buffer, msb: true);
|
||||
|
||||
// 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);
|
||||
qtm.READ_BITS(ref i, 8, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
} while (i != 0xFF);
|
||||
|
||||
qtm.HeaderRead = 0;
|
||||
@@ -533,9 +545,13 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
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);
|
||||
|
||||
qtm.ENSURE_BITS(1, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true);
|
||||
if (qtm.Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
current = (ushort)((current << 1) | qtm.PEEK_BITS(1, bit_buffer, msb: true));
|
||||
qtm.REMOVE_BITS(1, ref bits_left, ref bit_buffer, msb: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,21 +120,21 @@ namespace LibMSPackSharp.Compression
|
||||
|
||||
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)
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer, bool msb)
|
||||
{
|
||||
Error error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
byte b0 = InputBuffer[i_ptr++];
|
||||
|
||||
error = READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (error != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
READ_IF_NEEDED(ref i_ptr, ref i_end);
|
||||
if (Error != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
byte b1 = InputBuffer[i_ptr++];
|
||||
INJECT_BITS((uint)((b0 << 8) | b1), 16, ref bitsLeft, ref bitBuffer);
|
||||
return Error.MSPACK_ERR_OK;
|
||||
INJECT_BITS((uint)((b0 << 8) | b1), 16, ref bitsLeft, ref bitBuffer, msb);
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -45,60 +45,21 @@ namespace LibMSPackSharp.KWAJ
|
||||
// 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 const int KWAJ_MATCHLEN1_TBLSIZE = (KWAJ_MATCHLEN1_SYMS * 4);
|
||||
public const int KWAJ_MATCHLEN1_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_MATCHLEN1_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 const int KWAJ_MATCHLEN2_TBLSIZE = (KWAJ_MATCHLEN2_SYMS * 4);
|
||||
public const int KWAJ_MATCHLEN2_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_MATCHLEN2_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 const int KWAJ_LITLEN_TBLSIZE = (KWAJ_LITLEN_SYMS * 4);
|
||||
public const int KWAJ_LITLEN_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_LITLEN_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));
|
||||
}
|
||||
}
|
||||
//public const int KWAJ_OFFSET_TBLSIZE = (KWAJ_OFFSET_SYMS * 4);
|
||||
public const int KWAJ_OFFSET_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_OFFSET_SYMS * 2));
|
||||
|
||||
//public const int KWAJ_LITERAL_TBLSIZE = (KWAJ_LITERAL_SYMS * 4);
|
||||
public const int KWAJ_LITERAL_TBLSIZE = (KWAJ_TABLESIZE + (KWAJ_LITERAL_SYMS * 2));
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -465,7 +426,6 @@ namespace LibMSPackSharp.KWAJ
|
||||
{
|
||||
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;
|
||||
@@ -483,7 +443,9 @@ namespace LibMSPackSharp.KWAJ
|
||||
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);
|
||||
lzh.READ_BITS(ref types[i], 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.Error != Error.MSPACK_ERR_OK)
|
||||
return lzh.Error;
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
@@ -497,7 +459,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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)
|
||||
if (!InternalStream.MakeDecodeTable(KWAJ_MATCHLEN1_SYMS, KWAJ_MATCHLEN1_TBLSIZE, lzh.MATCHLEN1_len, lzh.MATCHLEN1_table, msb: true))
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
@@ -507,7 +469,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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)
|
||||
if (!InternalStream.MakeDecodeTable(KWAJ_MATCHLEN2_SYMS, KWAJ_MATCHLEN2_TBLSIZE, lzh.MATCHLEN2_len, lzh.MATCHLEN2_table, msb: true))
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
@@ -517,7 +479,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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)
|
||||
if (!InternalStream.MakeDecodeTable(KWAJ_LITLEN_SYMS, KWAJ_LITLEN_TBLSIZE, lzh.LITLEN_len, lzh.LITLEN_table, msb: true))
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
@@ -527,7 +489,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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)
|
||||
if (!InternalStream.MakeDecodeTable(KWAJ_OFFSET_SYMS, KWAJ_OFFSET_TBLSIZE, lzh.OFFSET_len, lzh.OFFSET_table, msb: true))
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
//BUILD_TREE(tbl, type)
|
||||
@@ -537,7 +499,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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)
|
||||
if (!InternalStream.MakeDecodeTable(KWAJ_LITERAL_SYMS, KWAJ_LITERAL_TBLSIZE, lzh.LITERAL_len, lzh.LITERAL_table, msb: true))
|
||||
return Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
while (lzh.InputEnd == 0)
|
||||
@@ -545,14 +507,16 @@ namespace LibMSPackSharp.KWAJ
|
||||
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.READ_HUFFSYM(lzh.MATCHLEN2_table, ref len, KWAJ_MATCHLEN2_TBLSIZE, lzh.MATCHLEN2_len, KWAJ_MATCHLEN2_SYMS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
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.READ_HUFFSYM(lzh.MATCHLEN1_table, ref len, KWAJ_MATCHLEN1_TBLSIZE, lzh.MATCHLEN1_len, KWAJ_MATCHLEN1_SYMS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
@@ -563,7 +527,8 @@ namespace LibMSPackSharp.KWAJ
|
||||
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.READ_HUFFSYM(lzh.OFFSET_table, ref j, KWAJ_OFFSET_TBLSIZE, lzh.OFFSET_len, KWAJ_OFFSET_SYMS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -571,7 +536,9 @@ namespace LibMSPackSharp.KWAJ
|
||||
|
||||
//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);
|
||||
lzh.READ_BITS(ref tempj, 6, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.Error != Error.MSPACK_ERR_OK)
|
||||
return lzh.Error;
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -591,7 +558,8 @@ namespace LibMSPackSharp.KWAJ
|
||||
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.READ_HUFFSYM(lzh.LITLEN_table, ref len, KWAJ_LITLEN_TBLSIZE, lzh.LITLEN_len, KWAJ_LITLEN_SYMS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -601,7 +569,8 @@ namespace LibMSPackSharp.KWAJ
|
||||
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.READ_HUFFSYM(lzh.LITERAL_table, ref j, KWAJ_LITERAL_TBLSIZE, lzh.LITERAL_len, KWAJ_LITERAL_SYMS, ref i, ref i_ptr, ref i_end, ref bits_left, ref bit_buffer, msb: true) != 0)
|
||||
return Error.MSPACK_ERR_DECRUNCH;
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -650,7 +619,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
|
||||
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);
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -658,7 +627,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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);
|
||||
lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -669,7 +638,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
else
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
lzh.READ_BITS(ref sel, 1, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -680,7 +649,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
else
|
||||
{
|
||||
//READ_BITS_SAFE(val, n)
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left);
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -692,7 +661,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
|
||||
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);
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
@@ -700,14 +669,14 @@ namespace LibMSPackSharp.KWAJ
|
||||
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);
|
||||
lzh.READ_BITS(ref sel, 2, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
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);
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
}
|
||||
@@ -725,7 +694,7 @@ namespace LibMSPackSharp.KWAJ
|
||||
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);
|
||||
lzh.READ_BITS(ref c, 4, ref i_ptr, ref i_end, ref bit_buffer, ref bits_left, msb: true);
|
||||
if (lzh.InputEnd != 0 && bits_left < lzh.InputEnd)
|
||||
return Error.MSPACK_ERR_OK;
|
||||
|
||||
|
||||
@@ -33,20 +33,19 @@ namespace LibMSPackSharp.KWAJ
|
||||
|
||||
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)
|
||||
public override void READ_BYTES(ref int i_ptr, ref int i_end, ref uint bitsLeft, ref uint bitBuffer, bool msb)
|
||||
{
|
||||
Error error = Error.MSPACK_ERR_OK;
|
||||
if (i_ptr >= i_end)
|
||||
{
|
||||
if ((error = Implementation.LZHReadInput(this)) != Error.MSPACK_ERR_OK)
|
||||
return error;
|
||||
if ((Error = Implementation.LZHReadInput(this)) != Error.MSPACK_ERR_OK)
|
||||
return;
|
||||
|
||||
i_ptr = InputPointer;
|
||||
i_end = InputLength;
|
||||
}
|
||||
|
||||
INJECT_BITS(InputBuffer[i_ptr++], 8, ref bitsLeft, ref bitBuffer);
|
||||
return error;
|
||||
INJECT_BITS(InputBuffer[i_ptr++], 8, ref bitsLeft, ref bitBuffer, msb);
|
||||
Error = Error.MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
public override int HUFF_ERROR() => (int)Error.MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
@@ -85,16 +85,21 @@ namespace LibMSPackSharp.OAB
|
||||
|
||||
private static int SysWrite(object baseFile, byte[] buf, int pointer, int size)
|
||||
{
|
||||
InternalFile file = baseFile as InternalFile;
|
||||
if (file == null)
|
||||
return 0;
|
||||
if (baseFile is InternalFile file)
|
||||
{
|
||||
int bytes_written = file.OrigSys.Write(file.OrigFile, buf, pointer, size);
|
||||
if (bytes_written > 0)
|
||||
file.CRC = Checksum.CRC32(buf, 0, bytes_written, file.CRC);
|
||||
|
||||
int bytes_written = file.OrigSys.Write(file.OrigFile, buf, pointer, size);
|
||||
return bytes_written;
|
||||
}
|
||||
else if (baseFile is DefaultFileImpl impl)
|
||||
{
|
||||
return SystemImpl.DefaultSystem.Write(impl, buf, pointer, size);
|
||||
}
|
||||
|
||||
if (bytes_written > 0)
|
||||
file.CRC = Checksum.CRC32(buf, 0, bytes_written, file.CRC);
|
||||
|
||||
return bytes_written;
|
||||
// Unknown file to write to
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user