KWAJ objectification and cleanup

This commit is contained in:
Matt Nadareski
2022-05-23 21:13:55 -07:00
parent c3e0b99002
commit d37eac02d5
6 changed files with 139 additions and 101 deletions

View File

@@ -60,13 +60,6 @@ namespace LibMSPackSharp
#region KWAJ
public const byte kwajh_Signature1 = 0x00;
public const byte kwajh_Signature2 = 0x04;
public const byte kwajh_CompMethod = 0x08;
public const byte kwajh_DataOffset = 0x0a;
public const byte kwajh_Flags = 0x0c;
public const byte kwajh_SIZEOF = 0x0e;
// Input buffer size during decompression - not worth parameterising IMHO
public const int KWAJ_INPUT_SIZE = (2048);

View File

@@ -20,7 +20,5 @@ namespace LibMSPackSharp.HLP
public class Compressor
{
public SystemImpl System { get; set; }
public int Dummy { get; set; }
}
}

View File

@@ -46,10 +46,6 @@ namespace LibMSPackSharp.KWAJ
/// but gives poor compression.It is possible for the compressed output
/// file to be larger than the input file.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the Compressor
/// instance being called
/// </param>
/// <param name="input">
/// the name of the file to compressed. This is passed
/// passed directly to mspack_system::open()
@@ -63,9 +59,9 @@ namespace LibMSPackSharp.KWAJ
/// that this should be determined automatically by using
/// mspack_system::seek() on the input file.
/// </param>
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
/// <see cref="SetParam"/>
public Func<Compressor, string, string, long, Error> Compress;
/// <returns>An error code, or MSPACK_ERR_OK if successful</returns>
/// <see cref="SetParam(Parameters, int)"/>
public Error Compress(string input, string output, long length) => throw new NotImplementedException();
/// <summary>
/// Sets an KWAJ compression engine parameter.
@@ -82,17 +78,13 @@ namespace LibMSPackSharp.KWAJ
/// file. A value of zero says "no", non-zero says "yes". The default
/// is "no".
/// </summary>
/// <param name="self">
/// a self-referential pointer to the Compressor
/// instance being called
/// </param>
/// <param name="param">the parameter to set</param>
/// <param name="value">the value to set the parameter to</param>
/// <returns>MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there
/// is a problem with either parameter or value.
/// </returns>
/// <see cref="Generate"/>
public Func<Compressor, Parameters, int, Error> SetParam;
public Error SetParam(Parameters param, int value) => throw new NotImplementedException();
/// <summary>
/// Sets the original filename of the file before compression,
@@ -102,19 +94,12 @@ namespace LibMSPackSharp.KWAJ
/// MS-DOS "8.3" type filename (up to 8 bytes for the filename, then
/// optionally a "." and up to 3 bytes for a filename extension).
///
/// If NULL is passed as the filename, no filename is included in the
/// If null is passed as the filename, no filename is included in the
/// header. This is the default.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the Compressor
/// instance being called
/// </param>
/// <param name="filename">the original filename to use</param>
/// <returns>
/// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if the
/// filename is too long
/// </returns>
public Func<Compressor, string, Error> SetFilename;
/// <param name="filename">The original filename to use</param>
/// <returns>MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if the filename is too long</returns>
public Error SetFilename(string filename) => throw new NotImplementedException();
/// <summary>
/// Sets arbitrary data that will be stored in the header of the
@@ -122,31 +107,13 @@ namespace LibMSPackSharp.KWAJ
/// as the overall size of the header must not exceed 65535 bytes.
/// The data can contain null bytes if desired.
///
/// If NULL is passed as the data pointer, or zero is passed as the
/// If null is passed as the data pointer, or zero is passed as the
/// length, no extra data is included in the header. This is the
/// default.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the Compressor
/// instance being called
/// </param>
/// <param name="data">a pointer to the data to be stored in the header</param>
/// <param name="bytes">the length of the data in bytes</param>
/// <returns>
/// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS extra data
/// is too long
/// </returns>
public Func<Compressor, byte[], int, int, Error> SetExtraData;
/// <summary>
/// Returns the error code set by the most recently called method.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the Compressor
/// instance being called
/// </param>
/// <returns>the most recent error code</returns>
/// <see cref="Compress"/>
public Func<Compressor, Error> LastError;
/// <returns>MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS extra data is too long</returns>
public Error SetExtraData(byte[] data, int pointer, int bytes) => throw new NotImplementedException();
}
}

View File

@@ -54,20 +54,15 @@ namespace LibMSPackSharp.KWAJ
public Header Open(string filename)
{
FileStream fh = System.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
Header hdr = new Header();
if (fh != null && hdr != null)
if (fh == null)
{
hdr.FileHandle = fh;
Error = ReadHeaders(fh, hdr);
}
else
{
if (fh == null)
Error = Error.MSPACK_ERR_OPEN;
if (hdr == null)
Error = Error.MSPACK_ERR_NOMEMORY;
Error = Error.MSPACK_ERR_OPEN;
return null;
}
Header hdr = new Header() { FileHandle = fh };
Error = ReadHeaders(fh, hdr);
if (Error != Error.MSPACK_ERR_OK)
{
System.Close(fh);
@@ -116,7 +111,7 @@ namespace LibMSPackSharp.KWAJ
return Error.MSPACK_ERR_ARGS;
// Seek to the compressed data
if (System.Seek(fh, hdr.DataOffset, SeekMode.MSPACK_SYS_SEEK_START))
if (System.Seek(fh, hdr.KWAJHeader.DataOffset, SeekMode.MSPACK_SYS_SEEK_START))
return Error = Error.MSPACK_ERR_SEEK;
// Open file for output
@@ -127,8 +122,8 @@ namespace LibMSPackSharp.KWAJ
Error = Error.MSPACK_ERR_OK;
// Decompress based on format
if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_NONE ||
hdr.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
if (hdr.KWAJHeader.CompressionType == CompressionType.MSKWAJ_COMP_NONE ||
hdr.KWAJHeader.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
{
// NONE is a straight copy. XOR is a copy xored with 0xFF
byte[] buf = new byte[KWAJ_INPUT_SIZE];
@@ -136,7 +131,7 @@ namespace LibMSPackSharp.KWAJ
int read, i;
while ((read = System.Read(fh, buf, 0, KWAJ_INPUT_SIZE)) > 0)
{
if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
if (hdr.KWAJHeader.CompressionType == CompressionType.MSKWAJ_COMP_XOR)
{
for (i = 0; i < read; i++)
{
@@ -154,16 +149,16 @@ namespace LibMSPackSharp.KWAJ
if (read < 0)
Error = Error.MSPACK_ERR_READ;
}
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_SZDD)
else if (hdr.KWAJHeader.CompressionType == CompressionType.MSKWAJ_COMP_SZDD)
{
Error = LZSS.Decompress(System, fh, outfh, KWAJ_INPUT_SIZE, LZSSMode.LZSS_MODE_EXPAND);
}
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_LZH)
else if (hdr.KWAJHeader.CompressionType == CompressionType.MSKWAJ_COMP_LZH)
{
LZHKWAJStream lzh = LZHKWAJ.Init(System, fh, outfh);
Error = (lzh != null) ? LZHKWAJ.Decompress(lzh) : Error.MSPACK_ERR_NOMEMORY;
}
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_MSZIP)
else if (hdr.KWAJHeader.CompressionType == CompressionType.MSKWAJ_COMP_MSZIP)
{
MSZIPDStream zip = MSZIP.Init(System, fh, outfh, KWAJ_INPUT_SIZE, false);
Error = (zip != null) ? MSZIP.DecompressKWAJ(zip) : Error.MSPACK_ERR_NOMEMORY;
@@ -203,7 +198,7 @@ namespace LibMSPackSharp.KWAJ
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
public Error Decompress(string input, string output)
{
Header hdr = Open(input) as Header;
Header hdr = Open(input);
if (hdr == null)
return Error;
@@ -221,24 +216,20 @@ namespace LibMSPackSharp.KWAJ
/// </summary>
private Error ReadHeaders(FileStream fh, Header hdr)
{
int i;
// Read in the header
byte[] buf = new byte[16];
if (System.Read(fh, buf, 0, kwajh_SIZEOF) != kwajh_SIZEOF)
if (System.Read(fh, buf, 0, _KWAJHeader.Size) != _KWAJHeader.Size)
return Error.MSPACK_ERR_READ;
// Check for "KWAJ" signature
if ((BitConverter.ToUInt32(buf, kwajh_Signature1) != 0x4A41574B) ||
(BitConverter.ToUInt32(buf, kwajh_Signature2) != 0xD127F088))
{
return Error.MSPACK_ERR_SIGNATURE;
}
// Create a new header based on that
Error err = _KWAJHeader.Create(buf, out _KWAJHeader kwajHeader);
if (err != Error.MSPACK_ERR_OK)
return Error = err;
// Assign the header
hdr.KWAJHeader = kwajHeader;
// Basic header fields
hdr.CompressionType = (CompressionType)BitConverter.ToUInt16(buf, kwajh_CompMethod);
hdr.DataOffset = BitConverter.ToUInt16(buf, kwajh_DataOffset);
hdr.Headers = (OptionalHeaderFlag)BitConverter.ToUInt16(buf, kwajh_Flags);
hdr.Length = 0;
hdr.Filename = null;
hdr.Extra = null;
@@ -247,7 +238,7 @@ namespace LibMSPackSharp.KWAJ
// Optional headers
// 4 bytes: length of unpacked file
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASLENGTH))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASLENGTH))
{
if (System.Read(fh, buf, 0, 4) != 4)
return Error.MSPACK_ERR_READ;
@@ -256,25 +247,25 @@ namespace LibMSPackSharp.KWAJ
}
// 2 bytes: unknown purpose
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN1))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN1))
{
if (System.Read(fh, buf, 0, 2) != 2)
return Error.MSPACK_ERR_READ;
}
// 2 bytes: length of section, then [length] bytes: unknown purpose
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN2))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASUNKNOWN2))
{
if (System.Read(fh, buf, 0, 2) != 2)
return Error.MSPACK_ERR_READ;
i = BitConverter.ToUInt16(buf, 0);
int i = BitConverter.ToUInt16(buf, 0);
if (System.Seek(fh, i, SeekMode.MSPACK_SYS_SEEK_CUR))
return Error.MSPACK_ERR_SEEK;
}
// Filename and extension
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME) || hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME) || hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
{
int len;
@@ -283,13 +274,14 @@ namespace LibMSPackSharp.KWAJ
int fnPtr = 0;
// Copy filename if present
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILENAME))
{
// Read and copy up to 9 bytes of a null terminated string
if ((len = System.Read(fh, buf, 0, 9)) < 2)
return Error.MSPACK_ERR_READ;
for (i = 0; i < len; i++)
int i = 0;
for (; i < len; i++)
{
if ((fn[fnPtr++] = (char)buf[i]) == '\0')
break;
@@ -307,7 +299,7 @@ namespace LibMSPackSharp.KWAJ
}
// Copy extension if present
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASFILEEXT))
{
fn[fnPtr++] = '.';
@@ -315,7 +307,8 @@ namespace LibMSPackSharp.KWAJ
if ((len = System.Read(fh, buf, 0, 4)) < 2)
return Error.MSPACK_ERR_READ;
for (i = 0; i < len; i++)
int i = 0;
for (; i < len; i++)
{
if ((fn[fnPtr++] = (char)buf[i]) == '\0')
break;
@@ -336,12 +329,12 @@ namespace LibMSPackSharp.KWAJ
}
// 2 bytes: extra text length then [length] bytes of extra text data
if (hdr.Headers.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASEXTRATEXT))
if (hdr.KWAJHeader.Flags.HasFlag(OptionalHeaderFlag.MSKWAJ_HDR_HASEXTRATEXT))
{
if (System.Read(fh, buf, 0, 2) != 2)
return Error.MSPACK_ERR_READ;
i = BitConverter.ToUInt16(buf, 0);
int i = BitConverter.ToUInt16(buf, 0);
byte[] extra = new byte[i + 1];
if (System.Read(fh, extra, 0, i) != i)
return Error.MSPACK_ERR_READ;

View File

@@ -25,15 +25,14 @@ namespace LibMSPackSharp.KWAJ
/// </summary>
public class Header : BaseHeader
{
/// <summary>
/// The compression type
/// </summary>
public CompressionType CompressionType { get; set; }
#region Internal
/// <summary>
/// The offset in the file where the compressed data stream begins
/// KWAJ header information
/// </summary>
public long DataOffset { get; set; }
internal _KWAJHeader KWAJHeader { get; set; }
#endregion
/// <summary>
/// Flags indicating which optional headers were included.
@@ -61,6 +60,9 @@ namespace LibMSPackSharp.KWAJ
/// </summary>
public ushort ExtraLength { get; set; }
/// <summary>
/// Internal file handle
/// </summary>
public FileStream FileHandle { get; set; }
}
}

View File

@@ -0,0 +1,85 @@
/* This file is part of libmspack.
* (C) 2003-2018 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System;
namespace LibMSPackSharp.KWAJ
{
internal class _KWAJHeader
{
#region Fields
/// <summary>
/// "KWAA"
/// </summary>
/// <remarks>0x00</remarks>
public uint Signature1 { get; private set; }
/// <summary>
/// Signature extension
/// </summary>
/// <remarks>0x04</remarks>
public uint Signature2 { get; private set; }
/// <summary>
/// The compression type
/// </summary>
/// <remarks>0x08</remarks>
public CompressionType CompressionType { get; private set; }
/// <summary>
/// The offset in the file where the compressed data stream begins
/// </summary>
/// <remarks>0x0a</remarks>
public ushort DataOffset { get; private set; }
/// <summary>
///
/// </summary>
public OptionalHeaderFlag Flags { get; private set; }
/// <summary>
/// Total size of the KWAJ header in bytes
/// </summary>
public const int Size = 0x0e;
#endregion
/// <summary>
/// Private constructor
/// </summary>
private _KWAJHeader() { }
/// <summary>
/// Create a _KWAJHeader from a byte array, if possible
/// </summary>
public static Error Create(byte[] buffer, out _KWAJHeader header)
{
header = null;
if (buffer == null || buffer.Length < Size)
return Error.MSPACK_ERR_READ;
header = new _KWAJHeader();
header.Signature1 = BitConverter.ToUInt32(buffer, 0x00);
if (header.Signature1 != 0x4A41574B)
return Error.MSPACK_ERR_SIGNATURE;
header.Signature2 = BitConverter.ToUInt32(buffer, 0x04);
if (header.Signature1 != 0xD127F088)
return Error.MSPACK_ERR_SIGNATURE;
header.CompressionType = (CompressionType)BitConverter.ToUInt16(buffer, 0x08);
header.DataOffset = BitConverter.ToUInt16(buffer, 0x0a);
header.Flags = (OptionalHeaderFlag)BitConverter.ToUInt16(buffer, 0x0c);
return Error.MSPACK_ERR_OK;
}
}
}