diff --git a/libmspack/cab.cs b/libmspack/cab.cs new file mode 100644 index 0000000..a71792f --- /dev/null +++ b/libmspack/cab.cs @@ -0,0 +1,75 @@ +namespace SabreTools.Compression.libmspack +{ + public static class cab + { + /* structure offsets */ + public const byte cfhead_Signature = 0x00; + public const byte cfhead_CabinetSize = 0x08; + public const byte cfhead_FileOffset = 0x10; + public const byte cfhead_MinorVersion = 0x18; + public const byte cfhead_MajorVersion = 0x19; + public const byte cfhead_NumFolders = 0x1A; + public const byte cfhead_NumFiles = 0x1C; + public const byte cfhead_Flags = 0x1E; + public const byte cfhead_SetID = 0x20; + public const byte cfhead_CabinetIndex = 0x22; + public const byte cfhead_SIZEOF = 0x24; + public const byte cfheadext_HeaderReserved = 0x00; + public const byte cfheadext_FolderReserved = 0x02; + public const byte cfheadext_DataReserved = 0x03; + public const byte cfheadext_SIZEOF = 0x04; + public const byte cffold_DataOffset = 0x00; + public const byte cffold_NumBlocks = 0x04; + public const byte cffold_CompType = 0x06; + public const byte cffold_SIZEOF = 0x08; + public const byte cffile_UncompressedSize = 0x00; + public const byte cffile_FolderOffset = 0x04; + public const byte cffile_FolderIndex = 0x08; + public const byte cffile_Date = 0x0A; + public const byte cffile_Time = 0x0C; + public const byte cffile_Attribs = 0x0E; + public const byte cffile_SIZEOF = 0x10; + public const byte cfdata_CheckSum = 0x00; + public const byte cfdata_CompressedSize = 0x04; + public const byte cfdata_UncompressedSize = 0x06; + public const byte cfdata_SIZEOF = 0x08; + + /* flags */ + public const ushort cffoldCOMPTYPE_MASK = 0x000f; + public const ushort cffoldCOMPTYPE_NONE = 0x0000; + public const ushort cffoldCOMPTYPE_MSZIP = 0x0001; + public const ushort cffoldCOMPTYPE_QUANTUM = 0x0002; + public const ushort cffoldCOMPTYPE_LZX = 0x0003; + public const ushort cfheadPREV_CABINET = 0x0001; + public const ushort cfheadNEXT_CABINET = 0x0002; + public const ushort cfheadRESERVE_PRESENT = 0x0004; + public const ushort cffileCONTINUED_FROM_PREV = 0xFFFD; + public const ushort cffileCONTINUED_TO_NEXT = 0xFFFE; + public const ushort cffileCONTINUED_PREV_AND_NEXT = 0xFFFF; + + /* CAB data blocks are <= 32768 bytes in uncompressed form. Uncompressed + * blocks have zero growth. MSZIP guarantees that it won't grow above + * uncompressed size by more than 12 bytes. LZX guarantees it won't grow + * more than 6144 bytes. Quantum has no documentation, but the largest + * block seen in the wild is 337 bytes above uncompressed size. + */ + public const int CAB_BLOCKMAX = 32768; + public const int CAB_INPUTMAX = CAB_BLOCKMAX + 6144; + + /* input buffer needs to be CAB_INPUTMAX + 1 byte to allow for max-sized block + * plus 1 trailer byte added by cabd_sys_read_block() for Quantum alignment. + * + * When MSCABD_PARAM_SALVAGE is set, block size is not checked so can be + * up to 65535 bytes, so max input buffer size needed is 65535 + 1 + */ + public const int CAB_INPUTMAX_SALVAGE = 65535; + public const int CAB_INPUTBUF = CAB_INPUTMAX_SALVAGE + 1; + + /* There are no more than 65535 data blocks per folder, so a folder cannot + * be more than 32768*65535 bytes in length. As files cannot span more than + * one folder, this is also their max offset, length and offset+length limit. + */ + public const int CAB_FOLDERMAX = 65535; + public const int CAB_LENGTHMAX = CAB_BLOCKMAX * CAB_FOLDERMAX; + } +} \ No newline at end of file diff --git a/libmspack/mscab_compressor.cs b/libmspack/mscab_compressor.cs index 3b58868..f6429a6 100644 --- a/libmspack/mscab_compressor.cs +++ b/libmspack/mscab_compressor.cs @@ -6,5 +6,7 @@ namespace SabreTools.Compression.libmspack public class mscab_compressor { public int dummy { get; set; } + + public mspack_system system { get; set; } } } \ No newline at end of file diff --git a/libmspack/mscab_decompressor.cs b/libmspack/mscab_decompressor.cs index 1e4462a..00d380e 100644 --- a/libmspack/mscab_decompressor.cs +++ b/libmspack/mscab_decompressor.cs @@ -9,6 +9,22 @@ namespace SabreTools.Compression.libmspack /// public abstract class mscab_decompressor { + public mscabd_decompress_state d { get; set; } + + public mspack_system system { get; set; } + + public int buf_size { get; set; } + + public int searchbuf_size { get; set; } + + public int fix_mszip { get; set; } + + public int salvage { get; set; } + + public MSPACK_ERR error { get; set; } + + public MSPACK_ERR read_error { get; set; } + /// /// Opens a cabinet file and reads its contents. /// diff --git a/libmspack/mscabd_cabinet.cs b/libmspack/mscabd_cabinet.cs index 01954dc..5806e92 100644 --- a/libmspack/mscabd_cabinet.cs +++ b/libmspack/mscabd_cabinet.cs @@ -111,5 +111,15 @@ namespace SabreTools.Compression.libmspack /// /// public MSCAB_HDR flags { get; set; } + + /// + /// Offset to data blocks + /// + public long blocks_off { get; set; } + + /// + /// Reserved space in data blocks + /// + public int block_resv { get; set; } } } \ No newline at end of file diff --git a/libmspack/mscabd_decompress_state.cs b/libmspack/mscabd_decompress_state.cs new file mode 100644 index 0000000..39e27bf --- /dev/null +++ b/libmspack/mscabd_decompress_state.cs @@ -0,0 +1,85 @@ +using static SabreTools.Compression.libmspack.cab; + +namespace SabreTools.Compression.libmspack +{ + public abstract unsafe class mscabd_decompress_state + { + /// + /// Current folder we're extracting from + /// + public mscabd_folder folder { get; set; } + + /// + /// Current folder split we're in + /// + public mscabd_folder_data data { get; set; } + + /// + /// Uncompressed offset within folder + /// + public uint offset { get; set; } + + /// + /// Which block are we decompressing? + /// + public uint block { get; set; } + + /// + /// Cumulative sum of block output sizes + /// + public long outlen { get; set; } + + /// + /// Special I/O code for decompressor + /// + public mspack_system sys { get; set; } + + /// + /// Type of compression used by folder + /// + public MSCAB_COMP comp_type { get; set; } + + /// + /// Decompressor code + /// + /// + /// + /// + public abstract int decompress(void* data, long offset); + + /// + /// Decompressor state + /// + public void* state { get; set; } + + /// + /// Cabinet where input data comes from + /// + public mscabd_cabinet incab { get; set; } + + /// + /// Input file handle + /// + public mspack_file infh { get; set; } + + /// + /// Output file handle + /// + public mspack_file outfh { get; set; } + + /// + /// Input data consumed + /// + public byte* i_ptr { get; set; } + + /// + /// Input data end + /// + public byte* i_end { get; set; } + + /// + /// One input block of data + /// + public byte[] input { get; set; } = new byte[CAB_INPUTBUF]; + } +} \ No newline at end of file diff --git a/libmspack/mscabd_folder.cs b/libmspack/mscabd_folder.cs index 3ee9ac4..33ccdaf 100644 --- a/libmspack/mscabd_folder.cs +++ b/libmspack/mscabd_folder.cs @@ -34,5 +34,20 @@ namespace SabreTools.Compression.libmspack /// one cabinet. /// public uint num_blocks { get; set; } + + /// + /// Where are the data blocks? + /// + public mscabd_folder_data data { get; set; } + + /// + /// First file needing backwards merge + /// + public mscabd_file merge_prev { get; set; } + + /// + /// First file needing forwards merge + /// + public mscabd_file merge_next { get; set; } } } \ No newline at end of file diff --git a/libmspack/mscabd_folder_data.cs b/libmspack/mscabd_folder_data.cs new file mode 100644 index 0000000..91a2442 --- /dev/null +++ b/libmspack/mscabd_folder_data.cs @@ -0,0 +1,20 @@ +namespace SabreTools.Compression.libmspack +{ + /// + /// There is one of these for every cabinet a folder spans + /// + public class mscabd_folder_data + { + public mscabd_folder_data next { get; set; } + + /// + /// Cabinet file of this folder span + /// + public mscabd_cabinet cab { get; set; } + + /// + /// Cabinet offset of first datablock + /// + public long offset { get; set; } + } +} \ No newline at end of file