Add everything from szddd.c

This commit is contained in:
Matt Nadareski
2023-09-19 15:34:32 -04:00
parent 9d9f03c283
commit 3f4de3ee67
4 changed files with 203 additions and 15 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;
namespace SabreTools.Compression.libmspack
{
@@ -16,7 +17,25 @@ namespace SabreTools.Compression.libmspack
/// </summary>
/// <param name="sys">A custom mspack_system structure, or NULL to use the default</param>
/// <returns>A <see cref="mscab_decompressor"/> or NULL</returns>
public static mscab_decompressor mspack_create_cab_decompressor(mspack_system sys) => throw new NotImplementedException();
public static mscab_decompressor mspack_create_cab_decompressor(mspack_system sys)
{
if (sys == null)
return null;
var self = new mscab_decompressor
{
system = sys,
d = null,
error = MSPACK_ERR.MSPACK_ERR_OK,
searchbuf_size = 32768,
fix_mszip = 0,
buf_size = 4096,
salvage = 0,
};
return self;
}
/// <summary>
/// Destroys an existing CAB compressor.
@@ -28,7 +47,21 @@ namespace SabreTools.Compression.libmspack
/// Destroys an existing CAB decompressor.
/// </summary>
/// <param name="self">The <see cref="mscab_decompressor"/> to destroy</param>
public static void mspack_destroy_cab_decompressor(mscab_decompressor self) => throw new NotImplementedException();
public static void mspack_destroy_cab_decompressor(mscab_decompressor self)
{
if (self != null)
{
mspack_system sys = self.system;
if (self.d != null)
{
if (self.d.infh != null) sys.close(self.d.infh);
cabd_free_decomp(self);
//sys.free(self.d);
}
//sys.free(self);
}
}
/// <summary>
/// Creates a new CHM compressor.
@@ -120,7 +153,18 @@ namespace SabreTools.Compression.libmspack
/// </summary>
/// <param name="sys">A custom mspack_system structure, or NULL to use the default</param>
/// <returns>A <see cref="msszdd_decompressor"/> or NULL</returns>
public static msszdd_decompressor mspack_create_szdd_decompressor(mspack_system sys) => throw new NotImplementedException();
public static msszdd_decompressor mspack_create_szdd_decompressor(mspack_system sys)
{
msszdd_decompressor self = null;
if (sys == null) sys = new mspack_default_system();
self = new msszdd_decompressor();
self.system = sys;
self.error = MSPACK_ERR.MSPACK_ERR_OK;
return self;
}
/// <summary>
/// Destroys an existing SZDD compressor.
@@ -132,7 +176,14 @@ namespace SabreTools.Compression.libmspack
/// Destroys an existing SZDD decompressor.
/// </summary>
/// <param name="self">The <see cref="msszdd_decompressor"/> to destroy</param>
public static void mspack_destroy_szdd_decompressor(msszdd_decompressor self) => throw new NotImplementedException();
public static void mspack_destroy_szdd_decompressor(msszdd_decompressor self)
{
if (self != null)
{
mspack_system sys = self.system;
//sys.free(self);
}
}
/// <summary>
/// Creates a new KWAJ compressor.

View File

@@ -1,3 +1,6 @@
using System.Linq;
using static SabreTools.Compression.libmspack.szdd;
namespace SabreTools.Compression.libmspack
{
/// <summary>
@@ -7,7 +10,7 @@ namespace SabreTools.Compression.libmspack
/// </summary>
/// <see cref="mspack_create_szdd_decompressor()"/>
/// <see cref="mspack_destroy_szdd_decompressor()"/>
public abstract class msszdd_decompressor
public unsafe class msszdd_decompressor
{
public mspack_system system { get; set; }
@@ -19,7 +22,7 @@ namespace SabreTools.Compression.libmspack
/// If the file opened is a valid SZDD file, all headers will be read and
/// a msszddd_header structure will be returned.
///
/// In the case of an error occuring, NULL is returned and the error code
/// In the case of an error occuring, null is returned and the error code
/// is available from last_error().
///
/// The filename pointer should be considered "in use" until close() is
@@ -29,9 +32,26 @@ namespace SabreTools.Compression.libmspack
/// The filename of the SZDD compressed file. This is
/// passed directly to mspack_system::open().
/// </param>
/// <returns>A pointer to a msszddd_header structure, or NULL on failure</returns>
/// <returns>A pointer to a msszddd_header structure, or null on failure</returns>
/// <see cref="close(msszddd_header)"/>
public abstract msszddd_header open(in string filename);
public msszddd_header open(in string filename)
{
mspack_system sys = this.system;
mspack_file fh = sys.open(filename, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_READ);
msszddd_header hdr = new msszddd_header();
hdr.fh = fh;
this.error = szddd_read_headers(sys, fh, hdr);
if (this.error != MSPACK_ERR.MSPACK_ERR_OK)
{
if (fh != null) sys.close(fh);
//sys.free(hdr);
hdr = null;
}
return hdr;
}
/// <summary>
/// Closes a previously opened SZDD file.
@@ -42,7 +62,69 @@ namespace SabreTools.Compression.libmspack
/// The SZDD header pointer is now invalid and cannot be used again.
/// </summary>
/// <param name="szdd">The SZDD file to close</param>
public abstract void close(msszddd_header szdd);
public void close(msszddd_header szdd)
{
if (this.system == null) return;
// Close the file handle associated
this.system.close(szdd.fh);
// Free the memory associated
//this.system.free(hdr);
this.error = MSPACK_ERR.MSPACK_ERR_OK;
}
private static readonly byte[] szdd_signature_expand = new byte[8]
{
0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33
};
private static readonly byte[] szdd_signature_qbasic = new byte[8]
{
0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1
};
/// <summary>
/// Reads the headers of an SZDD format file
/// </summary>
/// <param name="sys"></param>
/// <param name="fh"></param>
/// <param name="hdr"></param>
/// <returns></returns>
private static MSPACK_ERR szddd_read_headers(mspack_system sys, mspack_file fh, msszddd_header hdr)
{
byte[] buf = new byte[8];
byte* bufPtr = libmspack.system.GetArrayPointer<byte>(buf);
// Read and check signature
if (sys.read(fh, buffer: bufPtr, 8) != 8) return MSPACK_ERR.MSPACK_ERR_READ;
if (buf.SequenceEqual(szdd_signature_expand))
{
// Common SZDD
hdr.format = MSSZDD_FMT.MSSZDD_FMT_NORMAL;
// Read the rest of the header
if (sys.read(fh, bufPtr, 6) != 6) return MSPACK_ERR.MSPACK_ERR_READ;
if (buf[0] != 0x41) return MSPACK_ERR.MSPACK_ERR_DATAFORMAT;
hdr.missing_char = (char)buf[1];
hdr.length = EndGetI32(&buf[2]);
}
else if (buf.SequenceEqual(szdd_signature_qbasic))
{
// Special QBasic SZDD
hdr.format = MSSZDD_FMT.MSSZDD_FMT_QBASIC;
if (sys.read(fh, bufPtr, 4) != 4) return MSPACK_ERR.MSPACK_ERR_READ;
hdr.missing_char = '\0';
hdr.length = EndGetI32(buf);
}
else
{
return MSPACK_ERR.MSPACK_ERR_SIGNATURE;
}
return MSPACK_ERR.MSPACK_ERR_OK;
}
/// <summary>
/// Extracts the compressed data from a SZDD file.
@@ -56,7 +138,38 @@ namespace SabreTools.Compression.libmspack
/// is passed directly to mspack_system::open().
/// </param>
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
public abstract MSPACK_ERR extract(msszddd_header szdd, in string filename);
public MSPACK_ERR extract(msszddd_header szdd, in string filename)
{
if (szdd == null) return this.error = MSPACK_ERR.MSPACK_ERR_ARGS;
mspack_system sys = this.system;
mspack_file fh = szdd.fh;
// Seek to the compressed data
long data_offset = (szdd.format == MSSZDD_FMT.MSSZDD_FMT_NORMAL) ? 14 : 12;
if (sys.seek(fh, data_offset, MSPACK_SYS_SEEK.MSPACK_SYS_SEEK_START) != 0)
{
return this.error = MSPACK_ERR.MSPACK_ERR_SEEK;
}
// Open file for output
mspack_file outfh;
if ((outfh = sys.open(filename, MSPACK_SYS_OPEN.MSPACK_SYS_OPEN_WRITE)) == null)
{
return this.error = MSPACK_ERR.MSPACK_ERR_OPEN;
}
// Decompress the data
this.error = lzss_decompress(sys, fh, outfh, SZDD_INPUT_SIZE,
szdd.format == MSSZDD_FMT.MSSZDD_FMT_NORMAL
? LZSS_MODE.LZSS_MODE_EXPAND
: LZSS_MODE.LZSS_MODE_QBASIC);
// Close output file
sys.close(outfh);
return this.error;
}
/// <summary>
/// Decompresses an SZDD file to an output file in one step.
@@ -76,7 +189,15 @@ namespace SabreTools.Compression.libmspack
/// is passed directly to mspack_system::open().
/// </param>
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
public abstract MSPACK_ERR decompress(in string input, in string output);
public MSPACK_ERR decompress(in string input, in string output)
{
msszddd_header hdr;
if ((hdr = open(input)) == null) return this.error;
MSPACK_ERR error = extract(hdr, output);
close(hdr);
return this.error = error;
}
/// <summary>
/// Returns the error code set by the most recently called method.
@@ -88,6 +209,9 @@ namespace SabreTools.Compression.libmspack
/// <see cref="open(in string)"/>
/// <see cref="extract(msszddd_header, in string)"/>
/// <see cref="decompress(in string, in string)"/>
public abstract MSPACK_ERR last_error();
public MSPACK_ERR last_error()
{
return this.error;
}
}
}

View File

@@ -9,12 +9,12 @@
namespace SabreTools.Compression.libmspack
{
public static class system
public unsafe static class system
{
/// <summary>
/// Returns the length of a file opened for reading
/// </summary>
public unsafe static MSPACK_ERR mspack_sys_filelen(mspack_system system, mspack_file file, long* length)
public static MSPACK_ERR mspack_sys_filelen(mspack_system system, mspack_file file, long* length)
{
if (system == null || file == null || length == null) return MSPACK_ERR.MSPACK_ERR_OPEN;
@@ -38,5 +38,18 @@ namespace SabreTools.Compression.libmspack
return MSPACK_ERR.MSPACK_ERR_OK;
}
public static T* CreateArray<T>(int length)
{
T[] buf = new T[length];
return GetArrayPointer(buf);
}
public static T* GetArrayPointer<T>(T[] arr)
{
var bufRef = __makeref(arr);
var bufPtr = **(System.IntPtr**)&bufRef;
return (T*)bufPtr.ToPointer();
}
}
}

View File

@@ -9,7 +9,7 @@
namespace SabreTools.Compression.libmspack
{
public static class SZDD
public static class szdd
{
/// <summary>
/// Input buffer size during decompression - not worth parameterising IMHO