From d37eac02d5cec3e15ccd0610ecfd9686886075a9 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 23 May 2022 21:13:55 -0700 Subject: [PATCH] KWAJ objectification and cleanup --- BurnOutSharp/External/libmspack/Constants.cs | 7 -- .../External/libmspack/HLP/Compressor.cs | 2 - .../External/libmspack/KWAJ/Compressor.cs | 55 +++--------- .../External/libmspack/KWAJ/Decompressor.cs | 77 ++++++++--------- .../External/libmspack/KWAJ/Header.cs | 14 +-- .../External/libmspack/KWAJ/_KWAJHeader.cs | 85 +++++++++++++++++++ 6 files changed, 139 insertions(+), 101 deletions(-) create mode 100644 BurnOutSharp/External/libmspack/KWAJ/_KWAJHeader.cs diff --git a/BurnOutSharp/External/libmspack/Constants.cs b/BurnOutSharp/External/libmspack/Constants.cs index 3a83377a..82871f2c 100644 --- a/BurnOutSharp/External/libmspack/Constants.cs +++ b/BurnOutSharp/External/libmspack/Constants.cs @@ -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); diff --git a/BurnOutSharp/External/libmspack/HLP/Compressor.cs b/BurnOutSharp/External/libmspack/HLP/Compressor.cs index 0f5efbb5..5017a0d9 100644 --- a/BurnOutSharp/External/libmspack/HLP/Compressor.cs +++ b/BurnOutSharp/External/libmspack/HLP/Compressor.cs @@ -20,7 +20,5 @@ namespace LibMSPackSharp.HLP public class Compressor { public SystemImpl System { get; set; } - - public int Dummy { get; set; } } } diff --git a/BurnOutSharp/External/libmspack/KWAJ/Compressor.cs b/BurnOutSharp/External/libmspack/KWAJ/Compressor.cs index 16389d3d..c246a4c3 100644 --- a/BurnOutSharp/External/libmspack/KWAJ/Compressor.cs +++ b/BurnOutSharp/External/libmspack/KWAJ/Compressor.cs @@ -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. /// - /// - /// a self-referential pointer to the Compressor - /// instance being called - /// /// /// 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. /// - /// an error code, or MSPACK_ERR_OK if successful - /// - public Func Compress; + /// An error code, or MSPACK_ERR_OK if successful + /// + public Error Compress(string input, string output, long length) => throw new NotImplementedException(); /// /// 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". /// - /// - /// a self-referential pointer to the Compressor - /// instance being called - /// /// the parameter to set /// the value to set the parameter to /// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there /// is a problem with either parameter or value. /// /// - public Func SetParam; + public Error SetParam(Parameters param, int value) => throw new NotImplementedException(); /// /// 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. /// - /// - /// a self-referential pointer to the Compressor - /// instance being called - /// - /// the original filename to use - /// - /// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if the - /// filename is too long - /// - public Func SetFilename; + /// The original filename to use + /// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if the filename is too long + public Error SetFilename(string filename) => throw new NotImplementedException(); /// /// 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. /// - /// - /// a self-referential pointer to the Compressor - /// instance being called - /// /// a pointer to the data to be stored in the header /// the length of the data in bytes - /// - /// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS extra data - /// is too long - /// - public Func SetExtraData; - - /// - /// Returns the error code set by the most recently called method. - /// - /// - /// a self-referential pointer to the Compressor - /// instance being called - /// - /// the most recent error code - /// - public Func LastError; + /// MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS extra data is too long + public Error SetExtraData(byte[] data, int pointer, int bytes) => throw new NotImplementedException(); } } diff --git a/BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs b/BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs index 7cd37b67..b1e7a95a 100644 --- a/BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs +++ b/BurnOutSharp/External/libmspack/KWAJ/Decompressor.cs @@ -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 /// an error code, or MSPACK_ERR_OK if successful 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 /// 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; diff --git a/BurnOutSharp/External/libmspack/KWAJ/Header.cs b/BurnOutSharp/External/libmspack/KWAJ/Header.cs index ea43c0fe..9d9dd4a7 100644 --- a/BurnOutSharp/External/libmspack/KWAJ/Header.cs +++ b/BurnOutSharp/External/libmspack/KWAJ/Header.cs @@ -25,15 +25,14 @@ namespace LibMSPackSharp.KWAJ /// public class Header : BaseHeader { - /// - /// The compression type - /// - public CompressionType CompressionType { get; set; } + #region Internal /// - /// The offset in the file where the compressed data stream begins + /// KWAJ header information /// - public long DataOffset { get; set; } + internal _KWAJHeader KWAJHeader { get; set; } + + #endregion /// /// Flags indicating which optional headers were included. @@ -61,6 +60,9 @@ namespace LibMSPackSharp.KWAJ /// public ushort ExtraLength { get; set; } + /// + /// Internal file handle + /// public FileStream FileHandle { get; set; } } } diff --git a/BurnOutSharp/External/libmspack/KWAJ/_KWAJHeader.cs b/BurnOutSharp/External/libmspack/KWAJ/_KWAJHeader.cs new file mode 100644 index 00000000..d6bd2d4c --- /dev/null +++ b/BurnOutSharp/External/libmspack/KWAJ/_KWAJHeader.cs @@ -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 + + /// + /// "KWAA" + /// + /// 0x00 + public uint Signature1 { get; private set; } + + /// + /// Signature extension + /// + /// 0x04 + public uint Signature2 { get; private set; } + + /// + /// The compression type + /// + /// 0x08 + public CompressionType CompressionType { get; private set; } + + /// + /// The offset in the file where the compressed data stream begins + /// + /// 0x0a + public ushort DataOffset { get; private set; } + + /// + /// + /// + public OptionalHeaderFlag Flags { get; private set; } + + /// + /// Total size of the KWAJ header in bytes + /// + public const int Size = 0x0e; + + #endregion + + /// + /// Private constructor + /// + private _KWAJHeader() { } + + /// + /// Create a _KWAJHeader from a byte array, if possible + /// + 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; + } + } +}