From 54410bf59ed47617158fd37ab437e6d6bee42b25 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 2 Sep 2025 13:01:16 +0100 Subject: [PATCH] Add PAK methods 10 (crush) and 11 (distill). --- CMakeLists.txt | 19 +- library.h | 18 +- pak/bitstream.c | 166 ++++++++++++ pak/bitstream.h | 75 ++++++ pak/crush.c | 219 +++++++++++++++ pak/distill.c | 182 +++++++++++++ pak/lzw.c | 162 +++++++++++ pak/lzw.h | 83 ++++++ pak/prefixcode.c | 539 +++++++++++++++++++++++++++++++++++++ pak/prefixcode.h | 89 ++++++ tests/CMakeLists.txt | 10 +- tests/data/pak_crush.bin | Bin 0 -> 63282 bytes tests/data/pak_distill.bin | Bin 0 -> 60540 bytes tests/pak/crush.cpp | 81 ++++++ tests/pak/distill.cpp | 81 ++++++ 15 files changed, 1703 insertions(+), 21 deletions(-) create mode 100644 pak/bitstream.c create mode 100644 pak/bitstream.h create mode 100644 pak/crush.c create mode 100644 pak/distill.c create mode 100644 pak/lzw.c create mode 100644 pak/lzw.h create mode 100644 pak/prefixcode.c create mode 100644 pak/prefixcode.h create mode 100644 tests/data/pak_crush.bin create mode 100644 tests/data/pak_distill.bin create mode 100644 tests/pak/crush.cpp create mode 100644 tests/pak/distill.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a6d8a9..892de39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,21 +129,10 @@ endif() add_subdirectory(3rdparty) add_library("Aaru.Compression.Native" SHARED library.c apple_rle.c apple_rle.h adc.c adc.h lzip.c flac.c flac.h - zoo/lzd.c - zoo/lzd.h - zoo/lzh.c - zoo/decode.c - zoo/huf.c - zoo/io.c - zoo/lh5.h - zoo/lh5.c - zoo/lzh.h - zoo/ar.h - zoo/maketbl.c - arc/pack.c - arc/squeeze.c - arc/crunch.c - arc/lzw.c) + zoo/lzd.c zoo/lzd.h zoo/lzh.c zoo/decode.c zoo/huf.c zoo/io.c zoo/lh5.c zoo/lh5.h zoo/lzh.h zoo/ar.h zoo/maketbl.c + arc/pack.c arc/squeeze.c arc/crunch.c arc/lzw.c + pak/crush.c pak/distill.c pak/bitstream.c pak/bitstream.h pak/lzw.c pak/lzw.h pak/prefixcode.c + pak/prefixcode.h) include(3rdparty/bzip2.cmake) include(3rdparty/flac.cmake) diff --git a/library.h b/library.h index 0ab8dcd..5b2f375 100644 --- a/library.h +++ b/library.h @@ -124,22 +124,30 @@ AARU_EXPORT int AARU_CALL arc_decompress_pack(const unsigned char *in_buf, size_ // ARC method 4: Huffman squeezing AARU_EXPORT int AARU_CALL arc_decompress_squeeze(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len); -// Method 5: LZW (crunching) +// ARC Method 5: LZW (crunching) AARU_EXPORT int AARU_CALL arc_decompress_crunch(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len); -// Method 6: LZW with non-repeat packing (crunching) +// ARC Method 6: LZW with non-repeat packing (crunching) AARU_EXPORT int AARU_CALL arc_decompress_crunch_nrpack(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len); -// Method 7: LZW with non-repeat packing and new hash (Crunching) +// ARC Method 7: LZW with non-repeat packing and new hash (Crunching) AARU_EXPORT int AARU_CALL arc_decompress_crunch_nrpack_new(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len); -// Method 8: Dynamic LZW (crunching) +// ARC Method 8: Dynamic LZW (crunching) AARU_EXPORT int AARU_CALL arc_decompress_crunch_dynamic(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len); -// Method 9: Dynamic LZW with 13 bits (squashing) +// ARC Method 9: Dynamic LZW with 13 bits (squashing) AARU_EXPORT int AARU_CALL arc_decompress_squash(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len); +// ARC/PAK Method 10: LZW (crush) (unsure why it's different of the others but even XADMaster uses different codepaths) +AARU_EXPORT int AARU_CALL pak_decompress_crush(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, + size_t *out_len); + +// ARC/PAK Method 11: LZSS (distill) +AARU_EXPORT int AARU_CALL pak_decompress_distill(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, + size_t *out_len); + #endif // AARU_COMPRESSION_NATIVE_LIBRARY_H diff --git a/pak/bitstream.c b/pak/bitstream.c new file mode 100644 index 0000000..dd9ea69 --- /dev/null +++ b/pak/bitstream.c @@ -0,0 +1,166 @@ +/* + * bitstream.c - Bit stream input implementation + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "bitstream.h" + +void bitstream_init(BitStream *bs, const uint8_t *data, size_t length) +{ + bs->data = data; + bs->length = length; + bs->pos = 0; + bs->bitbuffer = 0; + bs->bitcount = 0; + bs->eof = false; +} + +static void bitstream_fill_buffer(BitStream *bs) +{ + while(bs->bitcount < 24 && bs->pos < bs->length) + { + bs->bitbuffer |= (uint32_t)bs->data[bs->pos] << (24 - bs->bitcount); + bs->bitcount += 8; + bs->pos++; + } + if(bs->pos >= bs->length && bs->bitcount == 0) { bs->eof = true; } +} + +uint32_t bitstream_read_bit(BitStream *bs) +{ + if(bs->eof) return 0; + + if(bs->bitcount == 0) { bitstream_fill_buffer(bs); } + + if(bs->bitcount == 0) + { + bs->eof = true; + return 0; + } + + uint32_t bit = (bs->bitbuffer >> 31) & 1; + bs->bitbuffer <<= 1; + bs->bitcount--; + + return bit; +} + +uint32_t bitstream_read_bit_le(BitStream *bs) +{ + if(bs->eof) return 0; + + if(bs->bitcount == 0) + { + if(bs->pos >= bs->length) + { + bs->eof = true; + return 0; + } + bs->bitbuffer = bs->data[bs->pos++]; + bs->bitcount = 8; + } + + uint32_t bit = bs->bitbuffer & 1; + bs->bitbuffer >>= 1; + bs->bitcount--; + + return bit; +} + +uint32_t bitstream_read_bits(BitStream *bs, int count) +{ + uint32_t result = 0; + for(int i = 0; i < count; i++) { result = (result << 1) | bitstream_read_bit(bs); } + return result; +} + +uint32_t bitstream_read_bits_le(BitStream *bs, int count) +{ + uint32_t result = 0; + for(int i = 0; i < count; i++) { result |= bitstream_read_bit_le(bs) << i; } + return result; +} + +uint32_t bitstream_peek_bits(BitStream *bs, int count) +{ + // Save current state + uint32_t saved_buffer = bs->bitbuffer; + int saved_bitcount = bs->bitcount; + size_t saved_pos = bs->pos; + bool saved_eof = bs->eof; + + // Read the bits + uint32_t result = bitstream_read_bits(bs, count); + + // Restore state + bs->bitbuffer = saved_buffer; + bs->bitcount = saved_bitcount; + bs->pos = saved_pos; + bs->eof = saved_eof; + + return result; +} + +uint32_t bitstream_peek_bits_le(BitStream *bs, int count) +{ + // Save current state + uint32_t saved_buffer = bs->bitbuffer; + int saved_bitcount = bs->bitcount; + size_t saved_pos = bs->pos; + bool saved_eof = bs->eof; + + // Read the bits + uint32_t result = bitstream_read_bits_le(bs, count); + + // Restore state + bs->bitbuffer = saved_buffer; + bs->bitcount = saved_bitcount; + bs->pos = saved_pos; + bs->eof = saved_eof; + + return result; +} + +void bitstream_skip_bits(BitStream *bs, int count) { bitstream_read_bits(bs, count); } + +void bitstream_skip_bits_le(BitStream *bs, int count) { bitstream_read_bits_le(bs, count); } + +uint8_t bitstream_read_byte(BitStream *bs) +{ + if(bs->pos >= bs->length) + { + bs->eof = true; + return 0; + } + return bs->data[bs->pos++]; +} + +uint16_t bitstream_read_uint16_le(BitStream *bs) +{ + if(bs->pos + 1 >= bs->length) + { + bs->eof = true; + return 0; + } + uint16_t result = bs->data[bs->pos] | (bs->data[bs->pos + 1] << 8); + bs->pos += 2; + return result; +} + +bool bitstream_eof(BitStream *bs) { return bs->eof; } diff --git a/pak/bitstream.h b/pak/bitstream.h new file mode 100644 index 0000000..08c77d5 --- /dev/null +++ b/pak/bitstream.h @@ -0,0 +1,75 @@ +/* + * bitstream.h - Bit stream input implementation + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef BITSTREAM_H +#define BITSTREAM_H + +#include +#include +#include + +typedef struct BitStream +{ + const uint8_t *data; + size_t length; + size_t pos; + uint32_t bitbuffer; + int bitcount; + bool eof; +} BitStream; + +// Initialize bit stream +void bitstream_init(BitStream *bs, const uint8_t *data, size_t length); + +// Read a single bit (MSB first) +uint32_t bitstream_read_bit(BitStream *bs); + +// Read a single bit (LSB first) +uint32_t bitstream_read_bit_le(BitStream *bs); + +// Read multiple bits (MSB first) +uint32_t bitstream_read_bits(BitStream *bs, int count); + +// Read multiple bits (LSB first) +uint32_t bitstream_read_bits_le(BitStream *bs, int count); + +// Peek at bits without consuming them (MSB first) +uint32_t bitstream_peek_bits(BitStream *bs, int count); + +// Peek at bits without consuming them (LSB first) +uint32_t bitstream_peek_bits_le(BitStream *bs, int count); + +// Skip previously peeked bits (MSB first) +void bitstream_skip_bits(BitStream *bs, int count); + +// Skip previously peeked bits (LSB first) +void bitstream_skip_bits_le(BitStream *bs, int count); + +// Read a byte +uint8_t bitstream_read_byte(BitStream *bs); + +// Read a 16-bit little endian integer +uint16_t bitstream_read_uint16_le(BitStream *bs); + +// Check if end of stream reached +bool bitstream_eof(BitStream *bs); + +#endif /* BITSTREAM_H */ diff --git a/pak/crush.c b/pak/crush.c new file mode 100644 index 0000000..125960b --- /dev/null +++ b/pak/crush.c @@ -0,0 +1,219 @@ +/* + * arc_crush.c - ARC Crush decompression algorithm + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include "../library.h" +#include "bitstream.h" +#include "lzw.h" + +int pak_decompress_crush_internal(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, size_t *out_len) +{ + if(!in_buf || !out_buf || !out_len || in_len == 0) { return -1; } + + BitStream bs; + bitstream_init(&bs, (const uint8_t *)in_buf, in_len); + + LZW *lzw = lzw_alloc(8192, 1); + if(!lzw) { return -1; } + + // Initialize state + int symbolsize = 1; + int nextsizebump = 2; + bool useliteralbit = true; + + int numrecentstrings = 0; + int ringindex = 0; + bool stringring[500]; + memset(stringring, 0, sizeof(stringring)); + + int usageindex = 0x101; + uint8_t usage[8192]; + memset(usage, 0, sizeof(usage)); + + int currbyte = 0; + uint8_t buffer[8192]; + size_t outpos = 0; + size_t max_output = *out_len; + + while(!bitstream_eof(&bs) && outpos < max_output) + { + if(!currbyte) + { + // Read the next symbol. How depends on the mode we are operating in. + int symbol; + if(useliteralbit) + { + // Use codes prefixed by a bit that selects literal or string codes. + // Literals are always 8 bits, strings vary. + if(bitstream_read_bit_le(&bs)) { symbol = bitstream_read_bits_le(&bs, symbolsize) + 256; } + else { symbol = bitstream_read_bits_le(&bs, 8); } + } + else + { + // Use same-length codes for both literals and strings. + // Due to an optimization quirk in the original decruncher, + // literals have their bits inverted. + symbol = bitstream_read_bits_le(&bs, symbolsize); + if(symbol < 0x100) symbol ^= 0xff; + } + + // Code 0x100 is the EOF code. + if(symbol == 0x100) { break; } + + // Walk through the LZW tree, and set the usage count of the current + // string and all its parents to 4. This is not necessary for literals, + // but we do it anyway for simplicity. + LZWTreeNode *nodes = lzw_symbols(lzw); + int marksymbol = symbol; + while(marksymbol >= 0) + { + if(marksymbol < 8192) { usage[marksymbol] = 4; } + marksymbol = nodes[marksymbol].parent; + } + + // Adjust the count of recent strings versus literals. + // Use a ring buffer of length 500 as a window to keep track + // of how many strings have been encountered lately. + + // First, decrease the count if a string leaves the window. + if(stringring[ringindex]) numrecentstrings--; + + // Then store the current type of symbol in the window, and + // increase the count if the current symbol is a string. + if(symbol < 0x100) { stringring[ringindex] = false; } + else + { + stringring[ringindex] = true; + numrecentstrings++; + } + + // Move the window forward. + ringindex = (ringindex + 1) % 500; + + // Check the number of strings. If there have been many literals + // lately, bit-prefixed codes should be used. If we need to change + // mode, re-calculate the point where we increase the code length. + bool manyliterals = numrecentstrings < 375; + if(manyliterals != useliteralbit) + { + useliteralbit = manyliterals; + nextsizebump = 1 << symbolsize; + if(!useliteralbit) nextsizebump -= 0x100; + } + + // Update the LZW tree. + if(!lzw_symbol_list_full(lzw)) + { + // If there is space in the tree, just add a new string as usual. + if(lzw_next_symbol(lzw, symbol) != LZW_NO_ERROR) + { + lzw_free(lzw); + return -1; + } + + // Set the usage count of the newly created entry. + int count = lzw_symbol_count(lzw); + if(count > 0 && count - 1 < 8192) { usage[count - 1] = 2; } + } + else + { + // If the tree is full, find a less-used symbol, and replace it. + int minindex = 0, minusage = INT_MAX; + int index = usageindex; + do { + index++; + if(index == 8192) index = 0x101; + + if(usage[index] < minusage) + { + minindex = index; + minusage = usage[index]; + } + + usage[index]--; + if(usage[index] == 0) break; + } while(index != usageindex); + + usageindex = index; + + if(lzw_replace_symbol(lzw, minindex, symbol) != LZW_NO_ERROR) + { + lzw_free(lzw); + return -1; + } + + // Set the usage count of the replaced entry. + if(minindex < 8192) { usage[minindex] = 2; } + } + + // Extract the data to output. + currbyte = lzw_reverse_output_to_buffer(lzw, buffer); + + // Check if we need to increase the code size. The point at which + // to increase varies depending on the coding mode. + if(lzw_symbol_count(lzw) - 257 >= nextsizebump) + { + symbolsize++; + nextsizebump = 1 << symbolsize; + if(!useliteralbit) nextsizebump -= 0x100; + } + } + + if(currbyte > 0 && outpos < max_output) { out_buf[outpos++] = (char)buffer[--currbyte]; } + else if(currbyte == 0) + { + // No more bytes in buffer, continue to next symbol + continue; + } + else + { + // Output buffer full + break; + } + } + + lzw_free(lzw); + *out_len = outpos; + return 0; +} + +AARU_EXPORT int AARU_CALL pak_decompress_crush(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, + size_t *out_len) +{ + // Allocate a temporary buffer. + size_t temp_len = *out_len * 2; // Heuristic. + unsigned char *temp_buf = malloc(temp_len); + if(!temp_buf) return -1; + + // Decompress crunched data. + int result = pak_decompress_crush_internal(in_buf, in_len, temp_buf, &temp_len); + if(result == 0) + { + // Decompress non-repeat packing. + result = arc_decompress_pack(temp_buf, temp_len, out_buf, out_len); + } + + free(temp_buf); + return result; +} \ No newline at end of file diff --git a/pak/distill.c b/pak/distill.c new file mode 100644 index 0000000..4196bb8 --- /dev/null +++ b/pak/distill.c @@ -0,0 +1,182 @@ +/* + * arc_distill.c - ARC Distill decompression algorithm + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include +#include +#include "../library.h" +#include "bitstream.h" +#include "prefixcode.h" + +static const int offset_lengths[0x40] = { + 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const int offset_codes[0x40] = { + 0x00, 0x02, 0x04, 0x0c, 0x01, 0x06, 0x0a, 0x0e, 0x11, 0x16, 0x1a, 0x1e, 0x05, 0x09, 0x0d, 0x15, + 0x19, 0x1d, 0x25, 0x29, 0x2d, 0x35, 0x39, 0x3d, 0x03, 0x07, 0x0b, 0x13, 0x17, 0x1b, 0x23, 0x27, + 0x2b, 0x33, 0x37, 0x3b, 0x43, 0x47, 0x4b, 0x53, 0x57, 0x5b, 0x63, 0x67, 0x6b, 0x73, 0x77, 0x7b, + 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff, +}; + +static void build_code_from_tree(PrefixCode *code, int *tree, int node, int numnodes, int depth) +{ + if(depth > 64) + { + // Too deep - error + return; + } + + if(node >= numnodes) { prefix_code_make_leaf_with_value(code, node - numnodes); } + else + { + prefix_code_start_zero_branch(code); + build_code_from_tree(code, tree, tree[node], numnodes, depth + 1); + prefix_code_start_one_branch(code); + build_code_from_tree(code, tree, tree[node + 1], numnodes, depth + 1); + prefix_code_finish_branches(code); + } +} + +AARU_EXPORT int AARU_CALL pak_decompress_distill(const unsigned char *in_buf, size_t in_len, unsigned char *out_buf, + size_t *out_len) +{ + if(!in_buf || !out_buf || !out_len || in_len == 0) { return -1; } + + BitStream bs; + bitstream_init(&bs, (const uint8_t *)in_buf, in_len); + + // Read header information + int numnodes = bitstream_read_uint16_le(&bs); + int codelength = bitstream_read_byte(&bs); + + if(numnodes < 2 || numnodes > 0x274) { return -1; } + + // Read tree nodes + int *nodes = malloc(numnodes * sizeof(int)); + if(!nodes) { return -1; } + + for(int i = 0; i < numnodes; i++) { nodes[i] = bitstream_read_bits_le(&bs, codelength); } + + // Build main code tree + PrefixCode *maincode = prefix_code_alloc(); + if(!maincode) + { + free(nodes); + return -1; + } + + prefix_code_start_building_tree(maincode); + build_code_from_tree(maincode, nodes, numnodes - 2, numnodes, 0); + + free(nodes); + + // Build offset code tree + PrefixCode *offsetcode = prefix_code_alloc(); + if(!offsetcode) + { + prefix_code_free(maincode); + return -1; + } + + for(int i = 0; i < 0x40; i++) + { + if(prefix_code_add_value_low_bit_first(offsetcode, i, offset_codes[i], offset_lengths[i]) != PREFIX_CODE_OK) + { + prefix_code_free(maincode); + prefix_code_free(offsetcode); + return -1; + } + } + + // LZSS decompression + uint8_t window[8192]; + memset(window, 0, sizeof(window)); + int windowpos = 0; + size_t outpos = 0; + size_t max_output = *out_len; + + while(!bitstream_eof(&bs) && outpos < max_output) + { + int symbol = prefix_code_read_symbol_le(&bs, maincode); + if(symbol < 0) break; + + if(symbol < 256) + { + // Literal byte + if(outpos < max_output) { out_buf[outpos++] = (char)symbol; } + window[windowpos] = symbol; + windowpos = (windowpos + 1) & 0x1fff; + } + else if(symbol == 256) + { + // End of stream + break; + } + else + { + // Match + int length = symbol - 0x101 + 3; + int offsetsymbol = prefix_code_read_symbol_le(&bs, offsetcode); + if(offsetsymbol < 0) break; + + int extralength; + if(outpos >= 0x1000 - 0x3c) + extralength = 7; + else if(outpos >= 0x800 - 0x3c) + extralength = 6; + else if(outpos >= 0x400 - 0x3c) + extralength = 5; + else if(outpos >= 0x200 - 0x3c) + extralength = 4; + else if(outpos >= 0x100 - 0x3c) + extralength = 3; + else if(outpos >= 0x80 - 0x3c) + extralength = 2; + else if(outpos >= 0x40 - 0x3c) + extralength = 1; + else + extralength = 0; + + int extrabits = bitstream_read_bits_le(&bs, extralength); + int offset = (offsetsymbol << extralength) + extrabits + 1; + + // Copy match + for(int i = 0; i < length; i++) + { + int sourcepos = (windowpos - offset) & 0x1fff; + uint8_t byte = window[sourcepos]; + + if(outpos < max_output) { out_buf[outpos++] = (char)byte; } + + window[windowpos] = byte; + windowpos = (windowpos + 1) & 0x1fff; + } + } + } + + prefix_code_free(maincode); + prefix_code_free(offsetcode); + + *out_len = outpos; + return 0; +} diff --git a/pak/lzw.c b/pak/lzw.c new file mode 100644 index 0000000..645ad76 --- /dev/null +++ b/pak/lzw.c @@ -0,0 +1,162 @@ +/* + * lzw.c - LZW decompression implementation + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "lzw.h" +#include + +LZW *lzw_alloc(int maxsymbols, int reservedsymbols) +{ + LZW *self = (LZW *)malloc(sizeof(LZW) + sizeof(LZWTreeNode) * maxsymbols); + if(!self) return NULL; + + if(maxsymbols < 256 + reservedsymbols) + { + free(self); + return NULL; + } + + self->maxsymbols = maxsymbols; + self->reservedsymbols = reservedsymbols; + + self->buffer = NULL; + self->buffersize = 0; + + for(int i = 0; i < 256; i++) + { + self->nodes[i].chr = i; + self->nodes[i].parent = -1; + } + + lzw_clear_table(self); + + return self; +} + +void lzw_free(LZW *self) +{ + if(self) + { + free(self->buffer); + free(self); + } +} + +void lzw_clear_table(LZW *self) +{ + self->numsymbols = 256 + self->reservedsymbols; + self->prevsymbol = -1; + self->symbolsize = 9; // TODO: technically this depends on reservedsymbols +} + +static uint8_t find_first_byte(LZWTreeNode *nodes, int symbol) +{ + while(nodes[symbol].parent >= 0) symbol = nodes[symbol].parent; + return nodes[symbol].chr; +} + +int lzw_next_symbol(LZW *self, int symbol) +{ + if(self->prevsymbol < 0) + { + if(symbol >= self->numsymbols) return LZW_INVALID_CODE_ERROR; + self->prevsymbol = symbol; + return LZW_NO_ERROR; + } + + int postfixbyte; + if(symbol < self->numsymbols) { postfixbyte = find_first_byte(self->nodes, symbol); } + else if(symbol == self->numsymbols) { postfixbyte = find_first_byte(self->nodes, self->prevsymbol); } + else { return LZW_INVALID_CODE_ERROR; } + + int parent = self->prevsymbol; + self->prevsymbol = symbol; + + if(!lzw_symbol_list_full(self)) + { + self->nodes[self->numsymbols].parent = parent; + self->nodes[self->numsymbols].chr = postfixbyte; + self->numsymbols++; + + if(!lzw_symbol_list_full(self)) + { + if((self->numsymbols & (self->numsymbols - 1)) == 0) { self->symbolsize++; } + } + + return LZW_NO_ERROR; + } + else { return LZW_TOO_MANY_CODES_ERROR; } +} + +int lzw_replace_symbol(LZW *self, int oldsymbol, int symbol) +{ + if(symbol >= self->numsymbols) return LZW_INVALID_CODE_ERROR; + + self->nodes[oldsymbol].parent = self->prevsymbol; + self->nodes[oldsymbol].chr = find_first_byte(self->nodes, symbol); + + self->prevsymbol = symbol; + + return LZW_NO_ERROR; +} + +int lzw_output_length(LZW *self) +{ + int symbol = self->prevsymbol; + int n = 0; + + while(symbol >= 0) + { + symbol = self->nodes[symbol].parent; + n++; + } + + return n; +} + +int lzw_output_to_buffer(LZW *self, uint8_t *buffer) +{ + int symbol = self->prevsymbol; + int n = lzw_output_length(self); + buffer += n; + + while(symbol >= 0) + { + *--buffer = self->nodes[symbol].chr; + symbol = self->nodes[symbol].parent; + } + + return n; +} + +int lzw_reverse_output_to_buffer(LZW *self, uint8_t *buffer) +{ + int symbol = self->prevsymbol; + int n = 0; + + while(symbol >= 0) + { + *buffer++ = self->nodes[symbol].chr; + symbol = self->nodes[symbol].parent; + n++; + } + + return n; +} diff --git a/pak/lzw.h b/pak/lzw.h new file mode 100644 index 0000000..3a22a76 --- /dev/null +++ b/pak/lzw.h @@ -0,0 +1,83 @@ +/* + * lzw.h - LZW decompression implementation + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef LZW_H +#define LZW_H + +#include +#include + +#define LZW_NO_ERROR 0 +#define LZW_INVALID_CODE_ERROR 1 +#define LZW_TOO_MANY_CODES_ERROR 2 + +typedef struct LZWTreeNode +{ + uint8_t chr; + int parent; +} LZWTreeNode; + +typedef struct LZW +{ + int numsymbols; + int maxsymbols; + int reservedsymbols; + int prevsymbol; + int symbolsize; + + uint8_t *buffer; + int buffersize; + + LZWTreeNode nodes[]; // Flexible array member (C99) +} LZW; + +// Allocate LZW structure +LZW *lzw_alloc(int maxsymbols, int reservedsymbols); + +// Free LZW structure +void lzw_free(LZW *self); + +// Clear/reset LZW table +void lzw_clear_table(LZW *self); + +// Process next symbol +int lzw_next_symbol(LZW *self, int symbol); + +// Replace a symbol +int lzw_replace_symbol(LZW *self, int oldsymbol, int symbol); + +// Get output length +int lzw_output_length(LZW *self); + +// Output to buffer (normal order) +int lzw_output_to_buffer(LZW *self, uint8_t *buffer); + +// Output to buffer (reverse order) +int lzw_reverse_output_to_buffer(LZW *self, uint8_t *buffer); + +// Inline helper functions +static inline int lzw_symbol_count(LZW *self) { return self->numsymbols; } + +static inline bool lzw_symbol_list_full(LZW *self) { return self->numsymbols == self->maxsymbols; } + +static inline LZWTreeNode *lzw_symbols(LZW *self) { return self->nodes; } + +#endif /* LZW_H */ diff --git a/pak/prefixcode.c b/pak/prefixcode.c new file mode 100644 index 0000000..67392d1 --- /dev/null +++ b/pak/prefixcode.c @@ -0,0 +1,539 @@ +/* + * prefixcode.c - Prefix code tree implementation + * + * Copyright (c) 2017-pstatic inline bool is_invalid_node(PrefixCode *self, int node) { + (void)self; // Suppress unused parameter warning + return (node < 0); +}ent, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include "prefixcode.h" +#include +#include +#include + +// Safe realloc that frees original pointer on failure +static void *safe_realloc(void *ptr, size_t newsize) +{ + void *newptr = realloc(ptr, newsize); + if(!newptr && newsize > 0) + { + free(ptr); + return NULL; + } + return newptr; +} + +// Inline helper functions +static inline CodeTreeNode *node_pointer(PrefixCode *self, int node) { return &self->tree[node]; } + +static inline int branch(PrefixCode *self, int node, int bit) { return node_pointer(self, node)->branches[bit]; } + +static inline void set_branch(PrefixCode *self, int node, int bit, int nextnode) +{ + node_pointer(self, node)->branches[bit] = nextnode; +} + +static inline int left_branch(PrefixCode *self, int node) { return branch(self, node, 0); } + +static inline int right_branch(PrefixCode *self, int node) { return branch(self, node, 1); } + +static inline void set_left_branch(PrefixCode *self, int node, int nextnode) { set_branch(self, node, 0, nextnode); } + +static inline void set_right_branch(PrefixCode *self, int node, int nextnode) { set_branch(self, node, 1, nextnode); } + +static inline int leaf_value(PrefixCode *self, int node) { return left_branch(self, node); } + +static inline void set_leaf_value(PrefixCode *self, int node, int value) +{ + set_left_branch(self, node, value); + set_right_branch(self, node, value); +} + +static inline void set_empty_node(PrefixCode *self, int node) +{ + set_left_branch(self, node, -1); + set_right_branch(self, node, -2); +} + +static inline bool is_invalid_node(PrefixCode *self, int node) { return node < 0; } + +static inline bool is_open_branch(PrefixCode *self, int node, int bit) +{ + return is_invalid_node(self, branch(self, node, bit)); +} + +static inline bool is_empty_node(PrefixCode *self, int node) +{ + return left_branch(self, node) == -1 && right_branch(self, node) == -2; +} + +static inline bool is_leaf_node(PrefixCode *self, int node) +{ + return left_branch(self, node) == right_branch(self, node); +} + +static int new_node(PrefixCode *self) +{ + CodeTreeNode *newtree = safe_realloc(self->tree, (self->numentries + 1) * sizeof(CodeTreeNode)); + if(!newtree) return -1; + + self->tree = newtree; + set_empty_node(self, self->numentries); + return self->numentries++; +} + +// Stack implementation for tree building +static PrefixCodeStack *prefix_code_stack_alloc(void) +{ + PrefixCodeStack *stack = malloc(sizeof(PrefixCodeStack)); + if(!stack) return NULL; + + stack->data = malloc(16 * sizeof(int)); + if(!stack->data) + { + free(stack); + return NULL; + } + + stack->count = 0; + stack->capacity = 16; + return stack; +} + +static void prefix_code_stack_free(PrefixCodeStack *stack) +{ + if(!stack) return; + free(stack->data); + free(stack); +} + +static int prefix_code_stack_push(PrefixCodeStack *stack, int value) +{ + if(stack->count >= stack->capacity) + { + int newcapacity = stack->capacity * 2; + int *newdata = safe_realloc(stack->data, newcapacity * sizeof(int)); + if(!newdata) return -1; + + stack->data = newdata; + stack->capacity = newcapacity; + } + + stack->data[stack->count++] = value; + return 0; +} + +static int prefix_code_stack_pop(PrefixCodeStack *stack) +{ + if(stack->count == 0) return -1; + return stack->data[--stack->count]; +} + +static void prefix_code_stack_clear(PrefixCodeStack *stack) { stack->count = 0; } + +// Bit reversal functions +static uint32_t reverse_32(uint32_t val) +{ + val = ((val >> 1) & 0x55555555) | ((val & 0x55555555) << 1); + val = ((val >> 2) & 0x33333333) | ((val & 0x33333333) << 2); + val = ((val >> 4) & 0x0F0F0F0F) | ((val & 0x0F0F0F0F) << 4); + val = ((val >> 8) & 0x00FF00FF) | ((val & 0x00FF00FF) << 8); + return (val >> 16) | (val << 16); +} + +static uint32_t reverse_n(uint32_t val, int length) { return reverse_32(val) >> (32 - length); } + +// Table construction functions +#define TABLE_MAX_SIZE 10 + +static void make_table(PrefixCode *code, int node, CodeTableEntry *table, int depth, int maxdepth) +{ + int currtablesize = 1 << (maxdepth - depth); + + if(is_invalid_node(code, node)) + { + for(int i = 0; i < currtablesize; i++) table[i].length = -1; + } + else if(is_leaf_node(code, node)) + { + for(int i = 0; i < currtablesize; i++) + { + table[i].length = depth; + table[i].value = leaf_value(code, node); + } + } + else + { + if(depth == maxdepth) + { + table[0].length = maxdepth + 1; + table[0].value = node; + } + else + { + make_table(code, left_branch(code, node), table, depth + 1, maxdepth); + make_table(code, right_branch(code, node), table + currtablesize / 2, depth + 1, maxdepth); + } + } +} + +static void make_table_le(PrefixCode *code, int node, CodeTableEntry *table, int depth, int maxdepth) +{ + int currtablesize = 1 << (maxdepth - depth); + int currstride = 1 << depth; + + if(is_invalid_node(code, node)) + { + for(int i = 0; i < currtablesize; i++) table[i * currstride].length = -1; + } + else if(is_leaf_node(code, node)) + { + for(int i = 0; i < currtablesize; i++) + { + table[i * currstride].length = depth; + table[i * currstride].value = leaf_value(code, node); + } + } + else + { + if(depth == maxdepth) + { + table[0].length = maxdepth + 1; + table[0].value = node; + } + else + { + make_table_le(code, left_branch(code, node), table, depth + 1, maxdepth); + make_table_le(code, right_branch(code, node), table + currstride, depth + 1, maxdepth); + } + } +} + +static int prefix_code_make_table(PrefixCode *self) +{ + if(self->table1) return PREFIX_CODE_OK; + + if(self->maxlength < self->minlength) + self->tablesize = TABLE_MAX_SIZE; // no code lengths recorded + else if(self->maxlength >= TABLE_MAX_SIZE) + self->tablesize = TABLE_MAX_SIZE; + else + self->tablesize = self->maxlength; + + self->table1 = malloc(sizeof(CodeTableEntry) * (1 << self->tablesize)); + if(!self->table1) return PREFIX_CODE_INVALID; + + make_table(self, 0, self->table1, 0, self->tablesize); + return PREFIX_CODE_OK; +} + +static int prefix_code_make_table_le(PrefixCode *self) +{ + if(self->table2) return PREFIX_CODE_OK; + + if(self->maxlength < self->minlength) + self->tablesize = TABLE_MAX_SIZE; // no code lengths recorded + else if(self->maxlength >= TABLE_MAX_SIZE) + self->tablesize = TABLE_MAX_SIZE; + else + self->tablesize = self->maxlength; + + self->table2 = malloc(sizeof(CodeTableEntry) * (1 << self->tablesize)); + if(!self->table2) return PREFIX_CODE_INVALID; + + make_table_le(self, 0, self->table2, 0, self->tablesize); + return PREFIX_CODE_OK; +} + +// Public functions + +PrefixCode *prefix_code_alloc(void) +{ + PrefixCode *self = malloc(sizeof(PrefixCode)); + if(!self) return NULL; + + self->tree = malloc(sizeof(CodeTreeNode)); + if(!self->tree) + { + free(self); + return NULL; + } + + set_empty_node(self, 0); + self->numentries = 1; + self->minlength = INT_MAX; + self->maxlength = INT_MIN; + self->isstatic = false; + + self->stack = NULL; + self->table1 = self->table2 = NULL; + self->tablesize = 0; + self->currnode = 0; + + return self; +} + +PrefixCode *prefix_code_alloc_with_static_table(int (*statictable)[2]) +{ + PrefixCode *self = malloc(sizeof(PrefixCode)); + if(!self) return NULL; + + self->tree = (CodeTreeNode *)statictable; // TODO: fix the ugly cast + self->isstatic = true; + + self->stack = NULL; + self->table1 = self->table2 = NULL; + self->tablesize = 0; + self->currnode = 0; + self->numentries = 0; + self->minlength = INT_MAX; + self->maxlength = INT_MIN; + + return self; +} + +PrefixCode *prefix_code_alloc_with_lengths(const int *lengths, int numsymbols, int maxcodelength, bool zeros) +{ + PrefixCode *self = prefix_code_alloc(); + if(!self) return NULL; + + int code = 0, symbolsleft = numsymbols; + + for(int length = 1; length <= maxcodelength; length++) + { + for(int i = 0; i < numsymbols; i++) + { + if(lengths[i] != length) continue; + // Instead of reversing to get a low-bit-first code, we shift and use high-bit-first. + int result; + if(zeros) { result = prefix_code_add_value_high_bit_first(self, i, code, length); } + else { result = prefix_code_add_value_high_bit_first(self, i, ~code, length); } + if(result != PREFIX_CODE_OK) + { + prefix_code_free(self); + return NULL; + } + code++; + if(--symbolsleft == 0) return self; // early exit if all codes have been handled + } + code <<= 1; + } + + return self; +} + +void prefix_code_free(PrefixCode *self) +{ + if(!self) return; + + if(!self->isstatic) free(self->tree); + free(self->table1); + free(self->table2); + if(self->stack) prefix_code_stack_free(self->stack); + free(self); +} + +int prefix_code_add_value_high_bit_first(PrefixCode *self, int value, uint32_t code, int length) +{ + return prefix_code_add_value_high_bit_first_repeat(self, value, code, length, length); +} + +int prefix_code_add_value_high_bit_first_repeat(PrefixCode *self, int value, uint32_t code, int length, int repeatpos) +{ + if(!self || self->isstatic) return PREFIX_CODE_INVALID; + + free(self->table1); + free(self->table2); + self->table1 = self->table2 = NULL; + + if(length > self->maxlength) self->maxlength = length; + if(length < self->minlength) self->minlength = length; + + repeatpos = length - 1 - repeatpos; + if(repeatpos == 0 || + (repeatpos >= 0 && (((code >> (repeatpos - 1)) & 3) == 0 || ((code >> (repeatpos - 1)) & 3) == 3))) + { + return PREFIX_CODE_INVALID; + } + + int lastnode = 0; + for(int bitpos = length - 1; bitpos >= 0; bitpos--) + { + int bit = (code >> bitpos) & 1; + + if(is_leaf_node(self, lastnode)) return PREFIX_CODE_INVALID; + + if(bitpos == repeatpos) + { + if(!is_open_branch(self, lastnode, bit)) return PREFIX_CODE_INVALID; + + int repeatnode = new_node(self); + int nextnode = new_node(self); + if(repeatnode < 0 || nextnode < 0) return PREFIX_CODE_INVALID; + + set_branch(self, lastnode, bit, repeatnode); + set_branch(self, repeatnode, bit, repeatnode); + set_branch(self, repeatnode, bit ^ 1, nextnode); + lastnode = nextnode; + + bitpos++; // terminating bit already handled, skip it + } + else + { + if(is_open_branch(self, lastnode, bit)) + { + int newnode = new_node(self); + if(newnode < 0) return PREFIX_CODE_INVALID; + set_branch(self, lastnode, bit, newnode); + } + lastnode = branch(self, lastnode, bit); + } + } + + if(!is_empty_node(self, lastnode)) return PREFIX_CODE_INVALID; + set_leaf_value(self, lastnode, value); + return PREFIX_CODE_OK; +} + +int prefix_code_add_value_low_bit_first(PrefixCode *self, int value, uint32_t code, int length) +{ + return prefix_code_add_value_high_bit_first(self, value, reverse_n(code, length), length); +} + +int prefix_code_add_value_low_bit_first_repeat(PrefixCode *self, int value, uint32_t code, int length, int repeatpos) +{ + return prefix_code_add_value_high_bit_first_repeat(self, value, reverse_n(code, length), length, repeatpos); +} + +void prefix_code_start_building_tree(PrefixCode *self) +{ + if(!self) return; + + self->currnode = 0; + if(!self->stack) { self->stack = prefix_code_stack_alloc(); } + else { prefix_code_stack_clear(self->stack); } +} + +void prefix_code_start_zero_branch(PrefixCode *self) +{ + if(!self) return; + + int new = new_node(self); + if(new < 0) return; + + set_branch(self, self->currnode, 0, new); + prefix_code_stack_push(self->stack, self->currnode); + self->currnode = new; +} + +void prefix_code_start_one_branch(PrefixCode *self) +{ + if(!self) return; + + int new = new_node(self); + if(new < 0) return; + + set_branch(self, self->currnode, 1, new); + prefix_code_stack_push(self->stack, self->currnode); + self->currnode = new; +} + +void prefix_code_finish_branches(PrefixCode *self) +{ + if(!self || !self->stack) return; + + int node = prefix_code_stack_pop(self->stack); + if(node >= 0) self->currnode = node; +} + +void prefix_code_make_leaf_with_value(PrefixCode *self, int value) +{ + if(!self) return; + + set_leaf_value(self, self->currnode, value); + prefix_code_finish_branches(self); +} + +// BitStream interface functions + +int prefix_code_read_symbol(BitStream *bs, PrefixCode *code) +{ + if(!code) return PREFIX_CODE_INVALID; + if(!code->table1) + { + if(prefix_code_make_table(code) != PREFIX_CODE_OK) return PREFIX_CODE_INVALID; + } + + int bits = bitstream_peek_bits(bs, code->tablesize); + + int length = code->table1[bits].length; + int value = code->table1[bits].value; + + if(length < 0) return PREFIX_CODE_INVALID; + + if(length <= code->tablesize) + { + bitstream_skip_bits(bs, length); + return value; + } + + bitstream_skip_bits(bs, code->tablesize); + + int node = value; + while(!is_leaf_node(code, node)) + { + int bit = bitstream_read_bit(bs); + if(is_open_branch(code, node, bit)) return PREFIX_CODE_INVALID; + node = branch(code, node, bit); + } + return leaf_value(code, node); +} + +int prefix_code_read_symbol_le(BitStream *bs, PrefixCode *code) +{ + if(!code) return PREFIX_CODE_INVALID; + if(!code->table2) + { + if(prefix_code_make_table_le(code) != PREFIX_CODE_OK) return PREFIX_CODE_INVALID; + } + + int bits = bitstream_peek_bits_le(bs, code->tablesize); + + int length = code->table2[bits].length; + int value = code->table2[bits].value; + + if(length < 0) return PREFIX_CODE_INVALID; + + if(length <= code->tablesize) + { + bitstream_skip_bits_le(bs, length); + return value; + } + + bitstream_skip_bits_le(bs, code->tablesize); + + int node = value; + while(!is_leaf_node(code, node)) + { + int bit = bitstream_read_bit_le(bs); + if(is_open_branch(code, node, bit)) return PREFIX_CODE_INVALID; + node = branch(code, node, bit); + } + return leaf_value(code, node); +} diff --git a/pak/prefixcode.h b/pak/prefixcode.h new file mode 100644 index 0000000..4a8b368 --- /dev/null +++ b/pak/prefixcode.h @@ -0,0 +1,89 @@ +/* + * prefixcode.h - Prefix code tree implementation + * + * Copyright (c) 2017-present, MacPaw Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#ifndef PREFIXCODE_H +#define PREFIXCODE_H + +#include +#include +#include "bitstream.h" + +// Error codes +#define PREFIX_CODE_OK 0 +#define PREFIX_CODE_INVALID -1 + +typedef struct CodeTreeNode +{ + int branches[2]; +} CodeTreeNode; + +typedef struct CodeTableEntry +{ + uint32_t length; + int32_t value; +} CodeTableEntry; + +// Simple stack implementation for tree building +typedef struct PrefixCodeStack +{ + int *data; + int count; + int capacity; +} PrefixCodeStack; + +typedef struct PrefixCode +{ + CodeTreeNode *tree; + int numentries; + int minlength; + int maxlength; + bool isstatic; + + int currnode; + PrefixCodeStack *stack; + + int tablesize; + CodeTableEntry *table1; + CodeTableEntry *table2; +} PrefixCode; + +// Function declarations +PrefixCode *prefix_code_alloc(void); +PrefixCode *prefix_code_alloc_with_lengths(const int *lengths, int numsymbols, int maxlength, bool shortestCodeIsZeros); +PrefixCode *prefix_code_alloc_with_static_table(int (*statictable)[2]); +void prefix_code_free(PrefixCode *self); + +int prefix_code_add_value_high_bit_first(PrefixCode *self, int value, uint32_t code, int length); +int prefix_code_add_value_high_bit_first_repeat(PrefixCode *self, int value, uint32_t code, int length, int repeatpos); +int prefix_code_add_value_low_bit_first(PrefixCode *self, int value, uint32_t code, int length); +int prefix_code_add_value_low_bit_first_repeat(PrefixCode *self, int value, uint32_t code, int length, int repeatpos); + +void prefix_code_start_building_tree(PrefixCode *self); +void prefix_code_start_zero_branch(PrefixCode *self); +void prefix_code_start_one_branch(PrefixCode *self); +void prefix_code_finish_branches(PrefixCode *self); +void prefix_code_make_leaf_with_value(PrefixCode *self, int value); + +// BitStream interface functions +int prefix_code_read_symbol(BitStream *bs, PrefixCode *code); +int prefix_code_read_symbol_le(BitStream *bs, PrefixCode *code); + +#endif /* PREFIXCODE_H */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 103394c..d6e5d5e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -60,9 +60,17 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arccrunch_dynamic.bin file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/arcsquash.bin DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/pak_crush.bin + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/pak_distill.bin + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) + # 'Google_Tests_run' is the target name # 'test1.cpp tests2.cpp' are source files with tests add_executable(tests_run apple_rle.cpp crc32.c crc32.h adc.cpp bzip2.cpp lzip.cpp lzfse.cpp zstd.cpp lzma.cpp flac.cpp zoo/lzd.cpp arc/pack.cpp lh5.cpp arc/squeeze.cpp arc/crunch.cpp - arc/squash.cpp) + arc/squash.cpp + pak/crush.cpp + pak/distill.cpp) target_link_libraries(tests_run gtest gtest_main "Aaru.Compression.Native") diff --git a/tests/data/pak_crush.bin b/tests/data/pak_crush.bin new file mode 100644 index 0000000000000000000000000000000000000000..0af589d3801d56ab81bc1e9fb2ee4953c6b02953 GIT binary patch literal 63282 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%0D+PBwTqb`2^wkxYM|Jep} zYWbY^tyJ6J(Z6UhzhKGR;Ke1jy}L_v9i_f%XK$C<{?gkgUT4FvK3{7)>wGz}VukZL zFTc+}#ZggkS;PM9n$DE7f1){cyXVz7#+xqdu+%&7uaw!sJ}#nY@>J*9>|doe6@J(d zx#)1V;@*4wdWU?rd#|dtkYBm1pjpyzP4Ti$|R?5BE69h>9%;>N@c?^6rC6 zN4~wiYHE4Q{^N1m-~JE049&gQUKIU&GV;Hr?ZNz7)0>ZZyw$W%i|=&O{x7k&Mc*-G zt=PF7;hSf@OQ%hF@o`Rr?S(&n)|YQBYPS@R7hmtLEY9|b`&!w$C!GBqtJfUWukd!4 zoSmxrn4f3&j3vI7HD{-cy#Hr@a!uHLZf0>%_?;WCL#HODysiBBp5fi{ z6zw>&sYb#j7L+`MtYxm1EX#8~hEB*Y|zT1{j9#U$4K=|Sbp~OLreQ- z+sB*bPhI;=bAI=RTe3Zq9#;L;GB2;ZWU=I%@3#BNia8VMgCjF#WUL@`LcPp zPyM+#`r7)P3G*!(Cn(RcJf@eVrowY;zG(iPMZx9`{~9i5Rr+>4wSIr)XYrY;*PR`; zs-F_(pH$F@+<9w3Sxh`e*+2qsa$T{RKC-Pvmv1P%IaF zB-)y^mUX>Vhj(#t)G70-54RdNC;n=dyJUKny!AKbMuYq|0hLc zHgr#wxW7@$Wy#0ualGG}m?Msy^}AB~O}(?_&HV4{oh`Qhxpn^S?n^tKUi$q*=3k4* z?{9r`yfc19c)T*qdHbPgf7{tcedBwNu9OD;xYo0L=Zse$_Ac<-e{b8&h|lr6b}wYI zPCsnqoa2--*{``|^7Ux@m)rkqoZ*r>!TsdtE3Z!ty!_p#c`OTy|4cu4P?;xI;PQt3 zw%>J`XM9QTDVU_G>&9?2Q+#?LTSm+R#_(qEoFCUX&m8z{VxOkh^i;{pXor|9leFm3 zGdJZHpL70_#FIVid;8V?sAYdkTsB0j-z?kwbal{yzZ)O3o&0KEJ##> zABAtsIMbY3WYT=n`P#kvcZ)vX{g85f!{N-PoV#~)8dWAcEuE%zzxwB;N{4IrL!X9S zzH6hr@5^iUJ9BPaQa-ysPE%ZN{*RiDIKHpkTC7!e=Vs1WzUu5#;pvNuzlHAgi}|}{ z|IBx{Uw#d=IdJ)%M^i87KHaV%#3j31{?zS_zpiw5&shC;{jK=K==r@* zGM#0%Ug~4kT*Pu-ObPGs zUTL38v5lKosUPSqCla{BJL7mMfYaNg>6_Qve=7fGRi@`HZXS04LZzoq`P zklLrMR=mmww%%JW#mb&C-7W3p>x9flIcr=#{;E8*C~mImn`Y}3Q|o3Y+hy)rF)xSj zzQcZZ`?O4P>Gh{h-<^2!LY2Uemdlk_PG=;DyB*U%lX;x)#_`|xm42SOb4cSZWBRIv z><0{9RqyRGw~t&jZP^c{8+U4>`CI?V>~_z-weIP&9Whsn&VG#+_KGY_z7+QCN~g)@ z%r9vsVf?8b^WOU#<}6?H@^f76t!0;8JO!l11H{B`eZHU4@#2x6_`ze#BSo`3n>ch* zWlyyByWaehpL_~JiGP7x|_|O`qLGX(zQ7cXm|J?lRfR}xuRwF=`&0Wxf|1d8XbB0yrAqdP=F2FoLCkQpxG z`@8u`W6=JBfSc!4O4H9N{wjNOOKWO$?&eoN7356MCw@}(y)W3~5?d#jtn^ny`g4-6 zgyS-a_cfEZ%~afEImy%B;N6OH`8dsG6DRD=`@i|?Kk<2I3|{}|(HE=u87nT5WOmU= zs?b2CXV>G;ub#*0-TV1y#tzPw%)at2pTnN(J-S1;YS-KI2mP@!v)s8$y~fE?|6Tr9 z%Uf&x+Fo?mr^F}vo!xGy5-{WHkNUp>zrOBx`__rE;fVSg##hOU&i|ZzY8LnYMH)}) z&-Yvp+o5!~?3M8Evs26K4=u8{dBxN|EsD!0@803~z60k4MH8P~dw79MssC)^(ogZv zl-Whu9zS|lX=HPM`}CYS>Q^SL_1*3Ech^#zf?w>&VGp%!uWkoh?C3yaC z>f=m(8rFVpOW&T*eO<={zt_Bky5K*$k!=%oO!HL)Z&fzU)`VoCEh1LviSUl zvl(@d)+--Aue()#YSnqR^?q`<+UFZeoXvRNtYgFTHID14!56M_%m2qOy*qi~6N>@I z)vZluGR6NqVk%>CcDl}D98~c+lge=Bu4ekP;KPwmJwNPve6-@(;u%M$Pyd{0 z_3q@H|I5DBy?pYHH%KNd)aOCc$zW4&#=eOwemw6N`y}?vdS(&NnJ{08E9b&K-m5B$ zJOBH%w&B}9nsIOA|E)Lw`D*szWx?x?p7pJkW8F66;)HUJ-}W_^g6f@l{=SY$+TYPU zVWzC>`}uFKt-K;6XLiOhT`YR{glFL?wtKA03wJxN2`G$ADQjYX7j>U^a^R7rYyw)_ zL;qiF<-R%lM$P$K_TR&_x8Kk4kX_$+H~tEjfY+A~v0IC8MNjaa`ytuo(6w7rwYU_n z?SFQwx`|Qg15*%Nm;Uvo|8oL-FRJk05{ul=!KMG@TGC_n(BB3syFM_kw(2kRUJ(3d z+B3}>-H$Jicselh39rySe356Sle`%<7O_G%PH64A(#GloOL_A(T{ep!Tf>-N9=&I4i}ba6*Knq7 z5DT`yJ2SE?cY_z>`Mdk?@AgP;$_)Fl=da+rbaT7gdlHHiB3}OV@cFd$EccUB>spFe z920+$`2Bm%|C#BVcKSAS*StK#Dv(k>ZSD6dUs()ynw;%>&^zrGdyjI??nL+LCZEo5T)t6=%K35f!Nid(bI%(=#{@8WWg12dHbtj*h*~UC^FEl*m$Lhg2^Xuvlfjychlp@n^yKK6DkE8j<|C6P% zl2x91rkfruamhHq!*^xAhMB%nQmT#ry4b(1xo*j`N`H8n{rM@;^EEl@={G&kBaYLL ze@Twr_u-%2;*N=R2|I1SZ@TiVzxKD~q24z&wKqT1{NLDG$mHhtvn+Y(C84z!qt4~? zoO!Q5-@*4sZ7XNSw9KV1`hL3|w=#)yc>C396^qmxsr|us-e24Q#OQz6{mx|pA0OF1 z+#DKw$l~4={_gj?t~q>GoyGKJf+$PvoEM)uxJ)*w6#bC-^Rs=bT}IaDnTKS|Y*h@E z<~2Q;_ltejoK*h>zbEvak|=*(YFxWvMfZkj3`b5azp$e6gwOh2K8~Wwn_cf5yKhnc zudug|*L1JBc;VI<|CCKnkAFQAFDAC$1+2o7jHzerX#pFJAw?Ek|m@<<#2cCJvI4D%H=AuHMb^^QR;S%gvUqI)l&G zJr>t7-U;P@oypne&08bre(dw(;0b4qWab~R+|$Xy+|Bd!dP@DY)UCIsye^cTVDeof z!@gpY#8!VP!R8ObmfV+0ZnJYRACi8b{(?u3=`~0E5k8s9MJ!TV&onKNtVp>Y`)HT@ z&YojGr%LpO-`U{oe2M-4%;J#0-43!l=igAZIP_N@6YH!K#=6*YfwJNJi&!2X;o0`t}~ z?v&p$MSZVv^~aT$?cO|a`e^-f`B!1}fZGh01HMS{Z2Y&mFN-5OPjA|SUKrl%k zjpLk8|9S4RzLJ}=Vb=Fs>vr6>yEv%Cbb(xdr>U*@GRA1dcr)AgEuX7ClO%D6qy83zN|9uk= zEnEE5^Q*~JBhS=@C$IGGzHhg;cuTz6%BS}tMX!DLyUg|^k}V_T`^S~u*Tmmmm@o6| zs9n`@$MPEX#pQkOHDR-`&vmp@LRC$=3nz|vIEW}U9s@zRk-83 zSs`vuT+`c&uQ+}G?fKoK7jEJrBblPGt@Nr_d^rE<>~E>>v>WcexW1(BrGAwhyMA4R zOzQjBjF*LsT=XYK@+DUs6nDNM^ZJFgR=xGe169sIx%CVb;CN#W##!%=aq(&hp9dijN%2g`UvOo{DFjlAeZ(J{Dx`>3nwY zNx+O}2Pb|t>7Mgp+No~yeMT>I4lwO<{^g=|*7Nq6bs6UWg8ubQc%T+sSF|Q?YR!(f zPd1ktb3SY7pJ@C*t+Z#;&B(G-|F-Q5XiKOxy&8Wbiq-z+)yXMtw_jfP>h|qDTl>M| z_kJ#Z_Woe-wl%A7Y*Clr&~mar#`4{#OAl(l1irgDRepx=j59{XFV(_21k#Up9MqIt z@jCY4ny37G{B<&Gzc2OK(cdi^VRAj$9lFkXxD5sk4fZ^bk&~g-xJ)q zutfG_>}mBc2Nf5J9QR`4x__2m|L)8E2EX;Key`{HDsISNq7$4EeRcm;ug$7@C%fFd z8Xbz(hLj$^ZRU99m|nQ$W{;c`Kev8(_*o@+f&ax*r~E!_KDoz~N4iSjTR~(+V*8Pl znID!kx0USrtTQQ<_im=rbI{q}T$$vTNI7Xp7L3mV22mDcI^%$rl)+J2%T=WzIy{tGj;tUmvfG%V)Sa$TLD za-`a8W3|EV|NL6JG)^BgeZ-xbZ8+bVXMyrWyWg|i3;(S8Uu7p!e|?+cYxbW@Zmt)w zmd)Ju_TK)jt1h@-OPJGUQlNO|t=r5-n@`)NlmE`lJ65O}ax7WjTTDl?@$K!^dVCia z{JynG|I_BW$1lqobeya_AD!6r=%B`_e>U^8`os4d_;2l5WO`}Ru4Qb0|M_X0-PSzw ztZ}*7x7}Cz3n!mw)!C!jKPm5U@&YZBO-E1YS133C`*@0B@!hN^589L@Umfv3Zz%J% z!Lu$yFlhR8x1Ntt`N99{YmN4w$#{KP z*rv?t%-Zb3(lu2%Gv`@6HI*uwmSe0OzD4j?cF~rZ7Pn_Te9ZS!_3-;j=NT+|{QEE7 zKmYP*h4$eElb*EQ{<81uzm)a^k2XX|Im)N?-En@Gy7-*&w}AEY?xG@Za=OfmNEQ>7PxHo}O%CsQq@WLT^)# zqv2leh@-EaqH^uT?r(c`S+HW)0=aKZlep|;bq=o+6Ti20iH6Rjf4jeCzfMlo+~gRo zJ*`uE)_Z@Y>wYOk+m`BV{~la8tFF$`=Gi;`vO|+^J^OC%c6F{r>VuCH4%&2m_&+EA z^9B`lH8}T(siu;^2Pf~Y$XT_1q~B#TZqRG=v(OcKpuVpSEQCeR)ncmi3{5jG7-# zmev01oc-qZ>UB?oC-(bs|La=CwkbaL!^>auZY@fke3^5K`a%)^x9eWsjybP3anYG8 z6GhDPQWo^(%-`tH&H3MS{Wrm#;Udo?)0Q8NVXuEz^?izDDfihDMOFSH`7RZYb1nD6 znx3&`{7^Vi^QHbv?dDyJ_^usG)SZ6e^^|u!%2y@QBp42K*Uov7W#P$xp=$S2hI2Y@ zPx{~ar}S^~*`{)C`lmTxz5lnlE)svQDLd(4;n|3!73E*2%eqWs-(kviu6S!?U94@X z+@sc8S;-qrnUI zcRpV&A1*xHINL?BRF7&Yf|06R}zp6fa%zyH5ru<}v&v&y{{*4nU6Yv+x{KI%i zEkXX(z1eEIA3AGu#C2*vmhF;S)%-10QeSny%RNo2)<%=Q(AnQQs$>6aq&MFSz9t>M zDl%T@Z*%k4nQe{#7wyi-^8bBpseap>=2bVt6hCfK-QIotokqAD&qKzO?;WCVpHAc| z*(}V#*1qH1#|r=5k!rHlpjGQfmRL`XH9owW<@BfBzT3RbEG8Y{e$}e~byse+p{NPV z>Sar1FFJXgQ?9#Le0h%gd>iJ}lsUI7l$k|~Rl$#S+%DqRhvapSco&*i7^-*#&y?iE$DS2cY3_3hXDgPS-|y}dfBHvsb@%=yMXoG= zCQrL|&g9O_JA4a;o^0OMXP&(;Cbi_0Z1EangBUlbZQ8Z(_51A1^FACs9Frm#ES)ER zW738N4W|Bk{{-*zOFj^B^Uwa(?Vi!IRW>aDz5Qi<#QwzVyqc?>T}k|1M(K^%S(Bh2`Zq>8sSKaGb z0KQy0Y$^NPeRqVXr>AtKS8n|&wtoGs>Gf$pJ!>V;y;_)fM%lRg(fW=0OiTGMaji0( zKiiG{(5f41`F%larm5-`zS&ZHc^TXM-!^q&78~r33O)98G4R>6->*l$t$xq>$w@I5 ztEWD=vC-njqILBQC0?u8?*}tAnb{ZV_A5V+3Mia>{dT~Ow-=w9ot#{|am&%@&ZsF$ zPwS?oMm+xd=Gl7LneQs~;y4)`X7t46w|3OboO^)D%HW(CkJ6{ipyz!)XU(DoAJqL+ z=3#kgHT%Cz?a%C`>z4g|)|kK;aOdA_bFMjSZGO7zh{dfgQO?;X#FohHWBz&fdjIF= zJ&OKDn$);lm4A`OqiRwczaz3mIc51rEw`f?n^$dk!(SU;?Cx-jU&PVYa(&qEsWo=H zF5QXzBjdEsLwHlS%&sz%N5^(dSm$}V=JTE9e3q^DpYPi&%z0yed&)0uOO|f?(&Oiy ze_!(9xO?j5yOtJP=8lv9e2P}JeA<6*R*IpXPft#VX0E^E-|&0sF&AFPPiuOs7#+gP zW@Pzio$m+viUVpA_D*|~>pTu;#joNPvtB+i_I_Q++J)K^ZP#y_`Pr>&!vBcVEVowN zpX;H!mobrX+B|o;zw2iy?(@qoirF9UblGOwr4q6H&8OEbwEk^t?ae*4w}kEgdJ~b) z3$-`qE5?_5c(xd?5a5iJsClY&@o3EwQ=&=BH1d zefg4ywGY;wjNS44uicNuH;%r4f2TnyLblsqnfGl&(6N^eZ_YRhPG9-luJT5p)qM*= z#)jT4C&kSd&kKDVw_$gk^!xos(^QVOJqr3fbAHpm^!1@_PuuRaNgTe4lYpQE=(5wLw`d-wGXB515`4k~k`6D|fMc z@-uC=(qOJP$Nt_jx*~glL#Fh|nSYtH=B&J(^2PsS`-A)+sUF+{chXZ7pW06`PBZWb zN~tf@@7cl4UR22t6kR{hTfVQ)=<;*(e+xSEpVY-2RPtZE!p)@AFK=r4IguAm+h{}myXqcy3d0@ki%USog z2p9;|$r$es5PY)X*+Ql0zE{a+w_n%<8=uaq+Yv2sxAObjzil1{I`_&m&z5|xQ`=)|PUp}91v08y?rw-Tst3Q=*FJIsM#_WXLDeuYtvYX&w^gH^u{v_>%8;*vSgfG;(QtWbb z>s^ihhpEMtss93IJgwlJs}`fYoc-2nW;V8t1<&0l|Friy-Z^Q`<|Q}O4{t5D5WBj3 zVFOFW6qd>NG!&-1$^6Ua+4(*9sm%VEtFl7PXODl{m^c6Wf4BE6n>#$Y)eAUf*)m(g z|6Lai5I1$c5VY#om*1~`3x-q|X@|+q;N0tT#AhSB`dRMg>e&BfLG{5Z)>9sx&bl-w z|K5Y&-^An=I~umvF`BUmoL~?5JnPE(+UnU)kEKW0E$T1&9Xz|?(^Rb`g7*8g#b4gm zD5_2S^Za@DipQ5YX70EV=4D}cJ@uDX((0uG;?LUtT|2VmczFDuoxT&L_-B8aIDOs% z;k^^mJ2J$s@3PdG-)75WZJ+vfW1oWU((m=xzxq5~V8Xd{%Bjyr?|;oR`R>e{y8e3O zy*IxP1pR-pFzBSl_FHG%oYJN*>|7(^f5{~};n#egTeqy`?%K+1tlEE4=K6fMjQ+{L z4q99;`tYX1+lBkq%dfAdZh5+OdE}j4OKkMQBAvp#*QT4x2AraUJfnH(qtIs@2RHZm zy4H*8Z!z8MzVots?9=yVZ+y}{#J~6C+w;GQ+-ILR&%ADb-BSls@0Q0Q%5uxg|4+%j zy&!kbd*LUY-{oV2{c6fKe`kvG{D1Ru{xgH8>%OsEm=KWh*nZ9X#3hfsKSr~EU-pGr z{`Ktz4==9_{N`0vuh@Q|qmp0URIVfQRguKnf(6GItx`ny+&g~Zpp|eT+pMX3H@7W( z`G@~e^TK0(yF#^1-pX!0?C0%n*R*+g&a7~*xPALPU)FQqXL`;Dl{iK0f1K%fbZedYhbwXpSHFuh zxi3fvo^k%%oPy7x6Yp=`#OJ(QNO4kg;_O!+D=pigJ85M;E8c^7 z*~Kr<7iqk8PLwj9DyaV}$8vsPPFU$o`}T5?CCe}U+q{$E+gsft;mG&@{3lKk*?Hbh z^<2f(`{uzJ`?zYdwLfhPixez6cq=YsenGyee9x3mqA&W^n>APP@6cUUY0>t}UB!LM znF}hCO0Ooms}>XS|9u1zz4H^0fhZ|gUP>58l~ zW6x!$*Pqu{J^v-&T4j%iG1p@AZ9UAM@-KT?CB2f4u)EFl_nDvbX7P;nbIb1=&VJE3 zN94>jGY&bIM;n%$lWv|P&~`3*8-K~xXRhbW&R)^3e8^l=JIhzo$zaY=Ex*IJOu4?A z{IA}$Sfr|5IsRtqf_#IkuikI$oaWb9)9xAihX3~2v)lLX>-zjx)xz`P+Z5&I=|96P zN_ie;2dKY_W2wJ;RWHf)&cSbrv$~HoE?Bbk)K2E-MVt-Ej*HSyYAS8J>J-`4Mb z&C>osdVvUHV|7j@=h4*?E6or5F)>uY+>?;Fc6;IT zIhVr?+MZY6eeAZPHo+>#I> zPoBEu`te!6c3ZPOTQT=Vl;~VL)zpZ%I?HMCn~Q_uiunS6tv{Mrw{HEVWCOe1p8L*S z59H9|JGT4I-@U&N{#c!QRmoV^|I{?kThcS`%xX-Xt0rT(F5*g=$=1rZF}%A}jS{bi zTbuuX)Lt84f2!6l<>-&5@Vd1@D#w0ycSuX$Uwc7h@2<%DwcnmU@0h@@rhVpH`)0{| zZ_FO*w=Pfc-}7qDjMZmfy<`+uXY_6?R58oA`S?xy=hdD!yO z*oVx&dF#XLzi~1K&dOh%8I_}h&am8O)b0?w^>ly1+28(OlrQ~X9wFNJ<4*75bL;QT znV55FOYLfXkPq}J;Q0VK#1AMFHiYLuxy>(yb`~7#p5mP&? zuAMFV@X~he!97Rc9Gx$y#{1;;lX#_lo+DWGWT?&%G|Gxf?Z}gTaD5uXKbrcet7VC@0G6d z8?H9CH;)TdowYu%)VMG|VQX>5n!_w^0>WDUY%!%@PYWJhuDD}GI>#VN={9l_7M{fO;ANe{*{>&sZ3&C~HhS%*oPfV4Wyk;Yl0TRCd zT+hqx@SpGTrZUptvRO^2*)os1g;RVCH|KnuW^nZ4=LgGba`e^K9+rRf>3Z1g*{^x7 zSc*Mp9im^Sl~lUssLBmY;=mygwI(u#EWWB&QS zW|-L4wqRzn{{O0uzKm>7_XGZZ^V+?$Pqajp2Il@b+;XG#(S9*)^K&nHA`TTSZugnF zPcF(jRy%Kl_>G+*M(=K&N}T>tf$O&6y(62vpYA@F|1#cj$5O-Cf-*)vk99e#-ygDe z%$pP9z4MfCrrDo&w`Vusf3|F1^3$JH8+UA+qY<=eU(By^R^x>mJ{|hk=sBxJU3^km z`|;+MW7>LdK23@rpGICyd-X$wd$zfGhPO_rwV-PJ|8Cno%InwO*>NSRW2)2ZX{*2G zp1;5UYgT>t>ePQ+YePh(-~HJ9Em85T@A+bdlg15qwA`8}e{?eWJGS_uRSj9;^NF6ug|@Zzeu)3z6TYM*M` zh^oE*#y@|S%zQidHjXBzZg%lf!OvBK(&`!p9)O+Ln4vmSi2E4p4UCsGBPqwXGxFS&R%<7uLk2b}*uAd6; zo>FR7w|SCfzu$cB)obA;7y88y8~W-r`7ga2qLypva8D)JJz(yB-|&8Kp6_B>(+#%g z995UT^!7*L;`7qh3wD-zDddG-xqEZoYF9z&cDtK(O}m{t-Fmsz5AQy*;X$a5h+>Jc zi&lQ~?uzg)@?xoB8lSIiKR#>m9of>$Su^L`bI&=jU#n2v^}iFJ`76f9$&S z=+>qxnFBM~g=b!tJNCFzkZIb1=Sy5?R_|W_H$6bu?6q8v0oTN1PHgk_%O9lst1e-^ z$lHCl-T(FkznKpc-#*H`Dz=!FQ)Jf9@4GygFglyI^ADsHRZQ5}y_8n_ybnAQMuYpcmyCYEVcUOs+f z^6VK-6ZWo7zfzFJZx!)tUi7&pyW`2HV%Ey+*;cYrjC<2J*5k+Rr=FDFqHG&G`SI<( zH%}*3Gxy}NXg(Z+|F z({3&o-)AYL?0ZUWVx+_a+g;P%2i6{b>i#m~fNE_)cXr1t^m$N3M7^JbOiot~Z^WWv?oYS$Pe#d4tWJ+HAqUb&M(~}QE8IBXaeXps`zht^-f9Eaf z#~1!K7wwhNQ(64)YW9!c5A!O1F<0yMcz;rob1TJzte;CLWiR z?f&phdPk06z?;hgCC1aAwH;2MGuigp;nj~=3r)6$cZ<6!)Wq(*vVW)h&ol`QpH+*! z*jJuV&i*G^RMs!~y?IHui}8{Le&0Xqc)#Dc-P4;T`iHDe^2cXpoIKqfvYb7-i|TBi zz1g(KR7mRdtC{{>seZT3FTJ$LpT(LzRm&xM(c^-K8zFY=hqk>CbbPtaVt1Xe^d$eU z-BRkCqzGA_g;7|zf@w|miN!DpW$+RWnVUB15<&n z#-Z;Xa%)QD_T5=877^gQi`nO|?x99GzX#v17fxVx`SW=K@4e|ht$M53&o5iCGNJ3i z_nWW0FFMI(zWele`$x92+4CjKXI)XZm znDb=PROQ(lN}FRh&tWmzm%cyY`n1{a7k*s*Q}hYPU-e1prnMpE1s{I&I^1*YeXp=B z@-%uP%1q&S zKci7ctE*GhBUaY%I_bTSuioDGcaOdJo=}_D9PzQM=KIaBes{;G+(f0)`iD)XXdt$3PN%OI6?ljqn2vxJbo`XzI|z07>J@b?|R zgpF?dt3Ui*wI>&r`oyu%Zq=1`02B|!AJV})st6#x-t~+Gr4xCLiPXTg8TO-fi9w+ z)OX-sMasJRZ%!N4YWX4$?7cC=rP@P$w(7Ks$yZE8Z>mh5w0zA9^CLF<%w}&$__o>p zy`oscj?54nf2PEZ>1q5+|8z;H?%Wl-b>ZTfsk5X)9Uo6Q^KZlZ!}Y#>i|^>X-?7O5 zh+sAEr#;>k0#8~lzMFIGX4yl_#FWzu_V5Mk|CUpo`BU@Zs$V8HUbhnevP@Hx2(K<% z%zHF%U--;jo}QIzdMV~|tRs%Zatf_^W>$RRKfN45B^(wH~Q;KiQ0Daiz^o; zYpy%*yRq*k^W)F81&m$En9oQtoov*Rti_(#*;=gZs{d+}g( zzWW|W=M~@F(0ac1Yt^^yMa$gh$4&fT6>Oy5^!U^&_WWnwX5F7xrtyATX3tu|yyc&* z=e<+QS6PSM`mprV*)6NI@2}i=&F=EoU%LO}iZ;f^>x4g9zGdq){TYT^zfWBLu8LpE z+v)1FWpC0pt(3oNe&xB@<~cQ6@)}Bo?Y_$B{d}0SDEIf>PuvSK&rV#&-qLN&shsoj z_|89Z`=)ZlTeROh&X&6Vh{@`H+W`LC(`Sd@zngn!zN3lKMTgC+mUOQ*vG{+}h!y^8UnMYaR(t>OXgBYFf$J9Y$t~$0XLji?#Vw9&eUeH^HCFZ}H}y z7>hFg#%Uk^8(jOV^!w6chq#g+*~9mDf08Wae42W$Siw;3e%bGDhq|Pr`Yu=BXI~ZN zx;W_=k3hRPKi8SuzdJS@Z8E-ey!sNut4C93Px=+$!F!f7gS}Pg@^Wu8jfkwiJuhp& zi)8R6nc1X$efQDUUj6gWdJVC{%7xkc568w!&N-mmCNr;kuh7AX=R5^YJ^7$4^q*~K z|K)=o-~8kFY}ppJzMOfo-RZLu4QrN5iA_U=BLqAfMPvAVK%rZ+A>&g_4+F*bhbyrs*s`f{Vg zWiMAw+nidg^+KSvJLTKW$xPX^8C^aUO^CEMZ7^{3wNqC(tG{xwq4|yN8@67qSlaPO zk^5(IrOnPwJFd^a$e<$;TI4#zb^pCL$^jnN3nm}`ASm>Zk@p|hid8kv(K{cvmVVtA zdTpNa<+9kN&qKCno78^@+_SyD>KA*}*U0BzOSk_5N}n7qjMx z)+T)Zo$FFMOp@;jsu;wXe^st)%k&fH-eo-1Ay|BE+nxsdf_LgCOn1Jy*}3l7*bt{1dJ4-a#l&+QLT>ooiU~ErShKdIh9VIHl6G)-ZoKr*Sf;I2d~~&M$Gp!efaxp z!S)@Y(QYy(264?+eewT9Z%){;k!A87R<;S#H+dTJ>-8<&(Zl*A;^QNYiRnycrcQ4> ztU81zTy+j{>4?7Hr`wP}>3!Ag17?|Pg*X4dpFUxAKhviR>TX85S&bbBUzTs&P_f)& zT3zJ&i5#!E8$Z;|fBnL83E!2<&(3P|(*GB2RG!GW^NLn-PHptrr+s{L7}U7;#~)HZ zapb-2)k`6H6Yp()ny~9{R_5CmE5B*)_@%h-#LvAVXV^;qDmt9r%lh|l>oSkS`5#)A z247Nl{;v6bYNYD)HUrjDyPN)7CY97mr%VhjKXT~YrdIpERtm#o+_})ZbjflhgrYwZ;!A3 z{w2TJH^q3v?e6(U|CBFS{E_2#!5mJrvgI>RwCRc8l%H;2BIVX#%Gcepuk%^b?32uY z=5?%8>YhZpW(*>r{RH>)4_yMI6Xy7$p(jXqYSvc>>S4r=*8G8;EHN0b}e`3mgp!e}#wf=>I|H@5H z-I{HqtRQf2Xl=ui-11=6sRo#0{G(g{|9P&3?VcF!_FS-llNfx2F@IX))#eJN6P3`Lc>vN0U+S@bD{AS-h{l}$LA>zQj*}EC;tkm_7Z{B-y$`{sT z`=3j~7EN{w=;EFpd0jdy?$ou;WkOuvpY^o-Q{K4l>bXl9?rRqRlFZ1;*L}rf{I%!P z+3Qh%_;2*y?P2-!RV!t8Yo960EMeg;d&%X=;m@~zIe%~KR7P&Cu%qGoIv>_nzcu$a zs1dQ8y7+#LQ~2pW(O=EOZFii}7OT3$6>#Wf;@9{M(RUC1u{)rm`ql9BR=JCjK4O<{ z`BX^wZu(`u<^Jes$3f4yT(iSBF< zuC68RGRhZ@aR0mKdbnx{_a8RR+gaDAG-=pR`pot7s7g`E!&#%j4ZWY&WofI#z=||*Rn_v2#tDoAQ);sod2QNqA z{iH|NZ08#tR+u~C2Yc?F{*N#CW`vZoUiY{?U)s7zxvYBsz0I{h^ukOHqOu-{9V`*L z%6-U5DmUz{&Examt?f5?ZCtT=P1?=vLYMWHro1c{jG62`%k$Ox4fEw3>z6L@>Mnk7 zw^Q170uZ}lsbHHQwCub(j-}Y97RbA%x3ELI+?e#5r@6t3Mb)PkqTpE(R<(5k73+77- zTVK9ewX3WAF3ZJ}-#8_$V^nMYr-j^n$6?{+r5l~G&E(;Si@j@;j_B8G1yAe!DCwHp zR(+txK>7B}b#7O`y}f(5sK<2zrkDNFm#ZoeN}aq&a@8No-Yt(wuQ920eZ$t~)i zyKn1>zJD@LLXMx3m#aT?_N=LVNM*6F=mKdyA(z`*4~O`f?hgOHv*&70cX8BFlUM5= ztomPA$>;P#`#_)F6bikgeW}k?@y-xspnqUOK6lh=i-mJWk z&}UzFJzF1l&fo^)=9nG%`Rffm6)ex3R9t50>A=6Ce&R&U<{2WX&*nW@;dA-h9oD6; z>;L3myeY~o?~=Cm+*HvIzPD;uoyysky=z{0deN;vO+P(Pma#34w%Yq-t?8lj>FHV!^^%^5oDpFg|e>Y|g) z-`0_Nv*yghKYW{h_FGPx%+JKi_jK})@N>uQmY<2VuqxT~)P946JXh%Vry0$RiOI8E zcI1{#GSChQlT4dC^_;w{!;9&4t4@oAwAZcrIAi{?utk^Vr;2$o{^Xx+^uKqph>m>T z!iitwE`5@JQ&Y`v-@~wMciObs$@8UbkG585?MrQsIotw|MmA!n=xvA8d+W7L~7J|FA{3{ZIV<&C{hWSi~e1U;f-< zR5$(B+#_WdE?XI6)ti(R;kF=lND+Oko6Qz$bzxh15Y1+R@zUvn2_vflAzhl3;{8}hl z?QZ3-hX${!9(}UB4-!d&{7pz_?%C_ z8fTtKzrZhk%K6x~H<8NrUpGHLb6Lr7tA(iB9rwV5CfoT>?QEnw_f*k*^uNBSO*$tphuhqlec?fGNxwspN6a5?+LHa`Qti#%nP>Fl_VIh} z=nj;topsA=S<`>XMalR7cAd|d-!iegVB56v#YbnKnD#9=U(X>$wc*7CzZ+im4c?1) ze*YS|X?|~Hhxu2oxcB4{?5vIM>DH*Y5JhZb!56L4BJUG(|klu0$>X212HNlaf9&0LIj`P1R#x=#bh*R1dHc7l;qxh-$|rp3{G(tI%}+5io^KIi(C;jtewV%9s3uS6 zvBu?n%l*E_%nLs^vo}ZoaP^BtXID2_D_+lkYG3}CvDV%qiajRU(@N{B|Gv7|{Xx#Z z7kxar!8+--HNzaHqwkk?9=vjAi|ps6jh^3jKk*U!Y?RmB!s5ckl~z!J6(2YAY%>O3*eRFjG(hD;zcbymhI=MqH z)Bo*$N0!|we@=r66JpmnZ-0; z@)T^`opk@N_mUl{$#b6lZTElwva_zzaDLPEl#;!E%0FdKw!eS#mTm2yDLVyt7dk!4 zHr_8aJGM4@I`_ky_uXG+967UYj>qM#QFh(2%~rO1ANz|a8yZE`vE^HL{+XHO?_ZO> zC#@rse`(r9wilWK+5H-Nb~@smpWjN{e0<#^+xgosKby5uQ=|^J?A*tA`ce3upH_cG z@A*ym%{njW#Wl@FRwq@qT^7Ddn|5ej{BHANLZS2KzLeLGH*M)+w2zz0w|BwCo3Tum zArA^)?icL-_S8Y}$c-l4EiP*@$F@DO`huIxxU)U$*bZLQ(Vg? zt4rG_7dOj=wcp|T|5-0h<80}~(+>o$uCBZHOz{64=GYhSzGjQHC;$KS{q4p_TlHe( zK68nD{>Spgu;O0Mj6HGlx~is^2^|Qoy(Tcv#9Yo|u^rc5iQjL&Kilf=q9_gpS zVisDn3%|5I|HfeM@~N@7=%@7pAJ>_weXrFE=GN~r&05RxdHKtN52G7bv(~e9Q+x+)L!tYm7>UY`xZD+cXYI$hi zB$Mamo7NZ3uIh4{7yHe%?)FJ8+nFT-OYa^vTkp0*he_4seQV-5^*hZCuOz3aU*gzb zzfaY5g>RMNnH$^7<9fNxr=|V1sE*b5z9~2BXI+WYlB*}#i*uWVUmV_iZmroh$G5h7 zD$oB_|L{igX`1bZ@+X_b*Ok2f_dDJuC$93T>ZPc2uS!$5yqSIIqn)wpk-+4L6NToh zSn4;WFfKhK{pI_e+5i8DOe#7O-G3w5Ed2Nv#R%iuMw{lXK9s-n!iV|apHGV-bNXRbd(_b+CiN-=(d6pWFTM>t(3QsH#vg#3)*EY)hWt{W7%YUi#4P9TY z(zo`F>*tBH`uD$|u`d4fM5T}4qL(%*Rpj|x+CF`UJpb-_FV{w4#C(=)5Vwko6S9gE~AtM8cCs=Sqz`sL%?Sod|a zX@2Ev?s%QJ1#$Yn)P5?)Se`dN&;8`6!DGt_3STD{mt^ic_WN7g8I=s{*%m@C+q&Iu z&pcs~xt`Zqff`C%JX9Z|%3a)}?mAcD|bK_R`fc_S!lLm%~2Yc=EXR zv_|DajoDAjZ6w7m89bVOLg>w616lr39o9ptM-|v7@r2bSZ%R@1Te9QKet}NY%{k%D zMU#zBMO|1m-y+8%dhpuBCeE7~^#9g_7LWeimAgXiHZ@;e)Oz9Qn>4?!@I@iBtuE%w z{Jc*oMr8Nq&v{S2?C!WG^I);@1HS`z-b}poh)+Fn*Rn6~9X9<}&zEzz{PvY^~FWpTra(D@Ba|@x$dL%$A7;kE3!XXswmEXX5!&+mT3zf z33ghu%ueche_3DmpZqP&ds)BhBsa5`mD~`Y{{Pe0l|S=ZtQ01>8#ryT4?c4@ul4AP z8X;kxt!~@_N>6P3eg%Kyd|oHGem?VgsjqX6CCz;(^<~wk{Z(aUoof<2tP_>^<}f}! zTw+-+>o{+&oS>5B?z;BU$qW^SRzKe4*nUQ-`Cx#{TO#mzN6H1($bHtQySmC`SwWIa>>KO^I=EOWW*(@J# z_*vdHA@b~^)*|O=MRBzvU$5Vvy5g!;_AId%&(3@~D=o86CqAsH?0jChr)h0>#)>PG zAN(}7HItX=J67Iy_H0kwWeu^UX}ur5*6QKNz3QB+ z@=vONbd!GL-knpTQ()3p%l%@G?X4R2Iji31mO0&@@J?j1Rb9Bj>^;`3Z}KzrqvyO( z>dKei_|D$R@;oDk6I?=e4Ha;tLwu}|4E z&RpSN|9AFBX6@+jES|Ghhfif%=H_45egEa$6;;81Cs{r`F>{&N)84z=R(+bWtMm5$ zpS6m|UOI`VuvY$`c+SJJMB>W7g)ihc&rjqxZkf{Xi|54|IX2@NiU|y9CntUKuQ^!r zR7A{av*i6%LKfjC=l`5h_cqy8aEiEo!%~OzxrOimE{`y z_BPjy%F}oIx2*oNlly?hmifQGZR=@`{r2Ha`t;Pj^F6l(lx?2j@LKTMGC$|P%V+RB z3Oy_^ZCR<^51FY4XYc+{x9RH@$B1~j69Q}R>}udLJhHaz?4zx&bJ@<@1zd^=xAHoz z_g+P$OTqa9tM(Z^oieN1g~CfL78S>D_npaNaq-X_Bk#sbY7ZxM9=LkN&A39Umb-Mz zccsLjjafY>Eo=l|JzFyK|DG%VkMo)}U(2iPe`zgAwf4vl4ebA^&$8qPh^kpTl zYPUb>p1AJh=HhERoMMHpux@c*`uE@KBL!vR7v}%?`}%QkX16uh5C4N4R7Pm9qQhGYn zlhw8Ewo}Dk#mc{BJ0Ggf(cchrN`HD}fUzIv=NX#!{}~>f$MN-o2k*b?l(juVVeXv^ zzoq7XXPu=JTPQY%$Nj{_i)kE{s`I|Sig^2_SMBYkWs|LRe*gO~(6;fmk@R7H=B?IS zAGHeKbX-5l#zUSf!g+pMvG6h*7oP5Aij^t(pMPC9*!cRE)>IR>km6$Zx_>1ctGL>4 zEU(@cwSM~3ZT*EV?!q>Plo?zg@A3H#*iYF>Csv-5uMl`;*pNEv=Ip zNB@C?|`T5B$Sy4il=$K>X@ zORs$ly8P(UJAJW?W|hM&Y)3j|SE$_&>b<$WTu!>GXRZ8|#QPtemPx+#TUEa@+b^xX z>c=fhe~(2rdVghuah(kcj zU$HHiH}y{U?2q%l=-qy3g;%X}vn zckKA2Ufg}*)Z7;pw=O;IZg7ZxeNja3z3uPMc_fs~{O?;d6>Hk%6 z7O~!+f1~r0l;XBFZ-<~wGwAmB47qFn-zMZ)PvpL~%jAuB z#?wXF=~vonJPqaR=f`ns%u|=W{?J}uaHW~f?6>bea~)oK>bvC4yOnmlA9!!ovOA=w z9sj#nkkk0N>bAH3Zx_i6AKkLke{FG%iHYZ>HG4kt>rd8@jy|04zGZH;+TustmswYw zoBi`;sLlEqx5wXSTxU*OQL_GDyjt+%|4;g+zu6fr)4XcNvqUE+l{*skhhNuQF5Thf zG2sCti^4S@#RGXM)fmQPgAR z#Perr{{3fk30!+wL}$Z?t;T=$+>?2)*Q+>hx!|R14}MwC=uQpbKCmY2zg}fSj4zX8 z!qV+wB{#zl^G$u!#}n18*PJHaay|R%}0`}Wv=<*l>c-(DTJ=bG=dE9=wN&5h9M+do6> zw4t)A&$b=%IXTz$O-?qcn$#XVyGn}rl(px(|Gj#>;@hSFA3wcc;NwD$ymK*j+|vyc zg8fR`mQ7rqAoT80{4d_#l>JZn>u#FZ`|8A9TfDSkA8T~wfhSy6-pb1gDmSi4%-+80 z+wGmE)(N1?-jXrHiJzQU1`&T^0J-)8Rx5{T}*uuK|)8^04Z(6t^Xd=M|s>o9COGwN%Z&yXj(?-A=je^vLxs_a9AexRw<9UG>PmiH9n- zZIV86*WM%I`;3k3AA9u9ulsMU?yolKSm*@v=NXj@dPXysFbduYP0On;GPjE4dwbx} z_u|#gYp%aCT)>i-tonPBL16qsrhDmgIrDx`U(zXPHO=zd+t|2;PwEX;*7$v$&&@57 zs<)^sMB>%nn}v5|uBb0Ay?Hb2VGZk=#O3!HD|Wo;suXnTy1=_Np~5(Jm5m3h*N+#v zA}bfH$e7Q3+Hqpq^NP1}lVuj~c$RMCb3lG&+BBJu5%wo;PG9ahJuhrdb7a$v`Q- zBM*HIW&HHr{fo$<&B;;sn~vn{|5#@(?Q)0Vz}~Hg_U)}-*Ybsbw%whzS}T$^h&-|} z;A@#Ls?^`x{UtOcWli+XZiWqa=4P0C9hDB!vyJNwtJvLnQQzRBWWu8}e@nxJVe49M(Mk(4{rIlbr<7hi@VWw_m60Z9Q@Ew`Si)*J&KP? z{MoYo0!95KmUWb`DRA9&=k=7&_kZbc-Tv6sUGa&JA+LOq;sM*k+J)WDpR$$JciMN| zm3?(TV?*U5@k-5dzO$a6eTsLA%?;RlDVv!6B~b2uGjNCy9U3zD+;3Ma9|u^XyHQis?EDrrY)PS{>dPEclIx{*TpT1N-Ctvm(G!$(y~jhb35aSNB+8Gr%~ZPWt@%jy^QYZEt}V*QKGJ{7WsmCj?a%kAN=;KUmR^767u)+Aj(5W{vM;;r z-2cQ$yr${?o_CI}GuN@sv5)xtP0ux8lF3r(PwaM{*IDB}iEjPK`{G#XgV*&H@e(Ny zu1wTl@oghlVmHI#egEG*Jah8DYHf`~;PQW#!d&|gzOPGVtn zk8FG)sGGjs$kk0ly#Fk>P?_ZPSdZFRsgEDhKJDIp<@viwuU0*+t9Pwy`nOu_+xzg) zGv(2Rk~2Q|==EH_d)05=<%D0mT35}TT`AV}7D5rGv}J7pXfe#%)f5ZVd)1|uP3_3O)QWU462>?o25PN;e|Vv`q3|Dtv~UfdFDCu zH~#lZpYnz1wE8FhlusxtS^h6rUo+gBH|MB$K<$~_nZ2KwJ8wNWxIr*@$-;~FIdfli z^P5e2m9Rqm%O?LxxnZJrBxcpG%Q_q^!uywb);4S3eHR;T<>wx5es=5p%U`yd>2C$h zE$5{1a$MNY{!3Be!AJA#k1G!!y!)fuIQ*}Q)*g;ozDwV&_NhI1J->5Z=#=G=3|H&b z7;VxdZi<#4-|+DAjlD5b`{m_gJLeO(MK|wyo&QZgwbe;P@H%T}u+O0Kyqk$oBB-`C}6-{4eD%N(rCzF@EccyEXeN=BNBE z{&-GJ#n5S8d9~=3^?vofd)WME`AlDGU&H7fXveT<{^!>9ORY~gH1HXO#JhC<(SF6g zk4K~8$efPXA?^G3%3Sw<|NcYwV$Z)#Eyv8Z{5&>YY>~vPa{|+q86KU|%zS%BzFBqZ z_6Y6t;^Nnp&&(%JUh>@T;txk-Ub&we1#7z%=eS>~JHERlYtkVe{eJd$3;t~UfAr%1 z@B2FXn>tfJt0p0F7=(y-tA{yQo1o}<7wr*_Aeam z@8>6L7sQ<0zu3$5+zo!;2cHwYs|;%&I3`H`STg5S`76EsbG5g8iho;ve^Ti(S5~8( z)uAUJ?Ub*CeQ{RXfB0Ti-RukM zN$&DepWKynj>=9g77O0GPqRvoH~N&D#%eC!km<|rW^SwZWcJB7Owibs@6Vwq616oa zc;WmEri|@5bvfKePh3`CCSS)RJ%3k|=W^zo;?k9~Ur*|p!E!9!e((IsUiEYGN-LP} zhY5<^KQd8m5BtyO8gjqVR-Ap5pd0^KE$-7?UE_4lBfE<0MQwijtv|i~VfOQPHFrM$ zyY<)kXJal`Macg>3wA75oieMI$;j>LGvB|?A#%$;{bs%@wc=SVpO^p5CL@6kcDq0S z?7v(L+M@A(evLN6i67I>?BR61{G@(ueqB@5;d7@8?%q-O;>j_!-h0E*wG0l5u1h*I zmp#tWtUgj#`udmlJ2tZ&HaDkiJjUodwZuJ`K{(4u=jWdqgIRJmm!JKRe_U|a?D_le zcT>3-cAUO?{Hj;^#IX18zb3!0SJ-%JAG>Wh!-ew+hxYvG*fRC_R%Om+E{XgJn#Ye< zct|D&{mwr+@BML+-^^=%cg=gI{HRqn+a>;HOQa)?|~>BFl$c|y(p=!qAe zl}uNSh^SuA>KZKJ%hfV=lzKiqAA+ira2dbG*UnXX9;=VxFs~;?H}3&75<5_nSFSW@$XlOs_ZQ zial%8xbgFiApP}UJ9pliv!0PV{ob}qLihh1H`%gbLe5;tV$iwHJvUcIPCoXo&rfpy z^uDz+-QBHSlFCYf>%&E-{YqwUjQJKJbKgSocY@KQl3qrIXZc%{D%Ko5%fBP|MUvX7 z+x+ZBO{$DO5`N|zUZ3BT9{VUK@zBW`EcWtuJh}H>nO0E6ba&zZZ(Hh`T#c*0L@3|9 z@9}99(`7U9C!(4!pMA9A4lX?H?6)@h-9Ed$_9YRTY}HI^(SNc7=l!#GU%dBx74(~{^qiry;tX*Sr-1kW!`&jh6!@a7m}SXgzwaCzN?uyKh{nhRLBHyQMKUH}%@!&KCS(dZ; zb%7EJGq>IPlQMJhDa~L}o4EY%-8P;t@3BAc7Mrv#yC&WsEZaYL<(J1-PKWNw78885 z{?*K1=~q`h{$^sKH)mebPNkU7<{vxX^W(oxIzPpYIu|DUhjHfy@ksvqLXYaMq^KlkDK`pRmJ?b6`^ z3r}5$*mh@?c>D2Be`l1~tm!xB-TL(8ZzFaE8Li#Zw!HkaAcuX=i`U_og$fiO(xGZUa@iEqc2a| zm;abyd&}WLNl;y>>1$)|9LMwpH|j)s6a4z_ep4=8)Seo(>%y6@j(a{$=dZbbx~_~p zG2iW-<dM9loh_DWeukGZW*7uM;_yxTg=%rmgC4p12grhjq4m zTK4J9HovcR7nXN%Ke&}-dG?>+k`+h)D}}Qj$&uf=;M+NQuD=qqCjF}77p*&GQhxAl zoyz(1ZozK~eqNa^y!L$h*V8Y*m2Uj2aKGxwy@(|%eV$cpzhn8-^D_6%go*qOKYx5( zTk>Q^ux-3e)6Z`wUL3dO_59pAck!d|D?h#C>A0_R`%Z)Vgk~A*32}?|eqKJCr?7%^ zdB=~EWeGZ5e~h|Byt00mcL#oEnS0+mf)}!e%jn0h;CWe2jHT)UDgS1-EIw7V(XBHp zz9`vn-t_;OZsD8DzPu}8zI18pxxHVb zfB(EOpWp7D>in(($32o;eqT?U{nYpG<@bcU zeLpMqYH$8tZ}iex{QuXVXTDcI+tk?^sO+~UbGey*np~xw`h#%3#T)j_zq0=qzue}e zXYVJxF$`h*{QCPF!N|(rcZ}zK?5;?h*522c(9i3>tz~1)oOzS|f`ui1__g*JCrnvt zG5zIqCxdzm;co86Hj~fZCv#_Q&|3KN)(M_@3v>Tnc(CQ#>Wn|1{uMEv_vtBYKc>4l z{OyhA1v0V!9=%ysr7Rch|8dvUf9ubrd`^{Zo>hN+x`S1sb+^HaQu31GJ^p2GniyQoG?_Y7X!{do0SJc~*f4X+p?YB)6ci5FPapfPQGc~z+ zM<><_m!68A|2aK_Nmc!9VyCF`-}e{JKKlP6Fqmz|##P>acMA8O>p#txV-eu$9MloK z?~;S3iD7sPYy6@LBNel+?GL`Z4HZ=PnCw4g37hyFE$;j8J|EG^6LZ|irn)R;-{y^X zLyONo%Rb0^t@nd3W8r`4qK@9l{}aFd%&q*{g$U)Q=U}cYtExr=eZ+JAWA#PgpX|{-bI17#=V_9OsVgT%N6)>x zY}b<|B8F3aWxLdQd6PQ3O}(|2uLP<6ZLaIOTuNy#6!c;JlKbiw|G8^5p2Dn{Gc&Xg+zTbvS)OzJ!0s zHSx{ryUwa#@{bmKak6xp$)~>TY4cC#9A5GH){~Qof0uCYEE5&`EADczxj3$IOx%XOcpEABU>62f6gW)&M zlS?nN|97%*Oi{5|aP#S9)1*3y7Q6lj>W-%Ot23r=lHOiq{`0Jgq@Dl6?2i`5XYiLy zKfH4Nw1zdAr{}D9KY!={DP>oo?D;k`5+dK_@2~x|p)>i_<@O!y3&jKW{11H|EfMlN z#i?si;@jKaKQ8b6boAERJ65U-ZfFTClvfMeYxe)*wmSEM9Q*e*2Oe)xlzO*YnCWlg z&wN=YtvyCR_NWM@i2nJVShK+1>WRBk#K+>~rYE^(+2w65hkhC!c{RP`=C<3bbuau` zP}jV-_oU?S|B_6BF(KYFwtcSLo~mzfC4bJeN9WwXo>IK_DADO{e(neb@?o& zm1holI6lf=we!cB4^OrGQa>y_JFP&HX zdHM0w7e>vf7axwLNxGEz)~yY`Q+fWx^}Cm{_dB!hk1&7Uq95GH&y!i+h1pI z_{u~r;K<%M@v^M_a<(#uZ-GBHe$UkZ$@iJ1vg)c?xxC0a-N{Fb^|G`-3jStKe|*Bw zn)7q&6z%QdFD17;<50i0aLU{x%dGEi_`gf`VBO`^rR%cY&ojsKPvT%`Wtnp2pC|Lg z=MAURJzrfq6M4VDsmDq{`YC8FP9dnFFB@IyYS8Ab4rbUpFgQ@IwJKb{tPRt=(mg0 z0Yv5l(UQI4yxi`SKdo-eSBf|I{`Rl2aE6b7zx-AMIop*k$}Ov(M{CP3kY|tI ztS!d1HuYz$`b_Q%Wzmn#{<90Waz9ZYW?sWVx2_`SpZZWa={P{2E>X$i1mWsWy@m$MOHq)z6XVsTSRr4lg7%?Vz zoMVZfAeg$a)gf=u%1Mi=V%A3wF`)2S* z>AE|EpW&z1YF}ne-56BU8mM)9efdcjyZoc-49`BD*>Kvk@lwA~#-+)hrt!t=Xq-*9 zcNO5;dP#-z>7~zmmvU@d>v|}@=K1c5;yvfq?w>PV;Na$xZGH>?+^>t8cKvt3^FzN1 zk9aJ7-)P7p;r}LCZ1*(HrHOBk?tAng=as+Y!JMGA>|1XND@u4be|@C!wfn-xw3}Za z3sr2Np{AG0IB%)R55uz;t_j}0AHIO~!bhcFU%&W=KJ1oWW^Fxfo&RUuqc0ejn;IIP zk4k@EB}XUlDN-Hm9l&9Z$FN{SlR2!K4+Uo;M>%> zJ=fQIR(+cB@WZ;^txqn;Zed#x8EmLnx@YE|zY5CQ75_7*`py5#c=*et_Ak=QI6ujy zaK|M1J(6Kuwq}lUZQQ?n@zrZCZF}16Y{U^Ld{UzF@|&%%4+%f6UvvM?@&m3bAL%cP zFy;O~wd;`GQjV@TR?&!zGsQQSPq`KI|M6kXPv7rxZ}vPn=@P)_;*dYdD)nA zyZmgs+mHTmuZ+8|vzE=gN+56PvLi}Nmy^Xy?q(Ftu)6nX+R^T$&%3iPUGP3LE%x-* zqY3vC{x_wbtZ3SzUv!j{TXWmu4{RUGoOjNhF1qjIxq0HI(vpV!otHNh3D`dLwfQfz zY5iII2{)(Roc~GVRVBx?Y?k@H>~)cs_Wqpv#Q2nOTSQJy`PmzOI+J7VvraGV=Lx&p zmbldAN5KEdFTXC{_hq3{G11pGJE)ht=hDnF*B8f zUHvg}eK(){8vPZ@hyQK(zl%*v)JWvKPv$-5^)q#_WCwA}gy|PC6 zV%VI8+AdGLubu4l6HvOQ^YMT6>FF#%1_2?R>yPc?l09lOuWr(}u$0GtkAHW5^jLr1 z&Ld$~^YmU>gs7(%-{AdN`epk}hV5^69#YFzt@Kzo*?ujGdsq3R+>S#Zqu!rdCY*of z!lVR$J@1U@+&uwu3O^^BT73@Qe*EyFSnu0&gXU*=eY1Bfod2D@q2|7cncw?OiZ5eT z)7ETTW_9!QvY)jDZZAs3Hvc-V8hXNxukyMPX-|lEeHOsK= zIYR4Rn|3X4_57A}#Y*wJ35n(H!oHirlan@`{OJB`(WlOXtFw#jOxJ}>*VQcZ<5(tm>TZxi z^&~F7rtskKxGl{~!=p8yHQoQlo%l*Qy)@)&+c8V4Xm;ngv@u!MDgp*em)-{5mfm zgR^B7KPqkCuI4$_a>%CXRne-(O5=wuCQsJ}6!e#>rd8M}9lu?~T{Y)@!_~L<{coHL z4dF_j{--9&SL-mi& zX)Exqj`5ezebN#+YkE%h8E@kpv#GCFM_38XeAwUadB`B8ukhqc7Ltdcagj31mW?CTrO&a_M` z-@L?8FZk7o-|ESUt2Z-S#kxi4l^xg|7P`Iq-@JtZxAec{IK@xOd^s;;@0N{IFZ^3& z{<~`X&ctH=`Io%y+AsE`d`R55Q~R9+i_vf2ZQgVZ>XUb#>pSUx(RBpn~>E|Zf-c~=C_EGPGaL{qy%%!TnllDIh zaI2c@p2DxiHSf)|$-FO`)+ZmGdwIqK|GR(wzt&?_h}{2X%}x%+DOY!C3B4)T{1g9k z%9YH+`@hR1%sG~6p`6oKr3Z@lH5zE!t%;OgIhd-!mDQCS+D~?+x zrhT&c`pWNr+4c4B9%|BPTEZk@FLe4d-AH4oAn!d?j z?Z>^a8K%lsht-ZBk=P)Zb3DB1K#OnXohKLLG=*XoeXE!#3vVc){Jz*gjcT?0tH(?e1X#mf|bR z%F~U*_CGpwU}Ek5MO=#JGwZk(Sl!lt_UFFM+pX)CF4||dIe6W}2~VGVvHZ#)Gjr1U z|NP-*7bnWEPb{z1xYy(HadX{5(d`;lT}%D%{j645dS%iI$Nx@$6t_BTzWw-qwe#+V zoZ^~0HLrKi=Dr?M zSy_>)amKLMT9D7-?}k;=n4NmvQ>7L^@JhJU{^;Q5Py77lUAO=C#9UjwDej+vX!1F~ z8>icOIN$uU;r#LIm+3Y0&FeP*$`JWmWpP$u-MZx)V}ldCmv%GG^N5J()a|m|@?PTp ziF`L(Wd_B2%O;l`vCYl+mvSp|i^b9HSGQN}y5D)Rm@o3zF45z>X{V!2FZ!tI_jg^t ztPyl2W5w!if1@?u<*(gQw0r+ld-YjPucsb5^>$KqecVTHC!Oe(@8WlU55Mr{!jJVP zZ}Qhq&H8TkfA;-lFO+morL8F2wUjMSf0Md5ON)Y8P>HnF$NuU~4FQ|eUt2Dn5K-_) zO+?}Cju(qtw>(*M#6N1=-)VNNTueKD3%>es_3p`I_b1-yJAcRhm#hl&ve!4ZojEv5 ze`orl;M#vOyHsv!W!QaHEX?LuxbNAavli1|r8c@>&N;ip<-@!4d+tn#DH7juarKK0 zO;P>ZS4Or4m%qrFko0rXxy?$JQ|tfu<_B)vU3C8a_iQey+x5q%@rgIx{u^-qx`W?= zh8Zp^K6M@Z_-2A8OZ*Y`+v~Uevwy99N+t4_#ZlHpEjQWqFU#-y=-=`E&V1)xa+BI8 zF4z(Jf7aE5U*2EL@yVZX_^NkqWBAINDwRFE{!Wz&b6m2fb%&bY(dND9Gw%PmV4O7R z{d;%M6-8U4SZ;h-xJOdSh}MW{{+sHdwXZ%bMsG;MO(Jt(Ans+CuU!zLX>P%^!;m-U6-A zoK5@v9%k2nHmT{q{P64Qpqp=w8Xe7=wrZ#9TV+Kd4wb^6v0PV!l74O5el5&sZu({W zw|$k(JWlm%`U;#{JYKv1KJBOK$j)C8r?;>ATg4GR#h33EhfU3W;`1+;Gjftt{!+uW z{|Xm1{k{5$>qq1S(=033`b&|kem@gBxIf+M`|V%%ua>R;JL{+RGKCM{R;*eXlJ)mk z->p&|rhQr83_bUK^a>L?`>>IN`$zv@=J}2r;;jw;OC;WR+BcWIV*ay}|I`+o+kAgQ z$84YW^XmIoUt|97X;r^->C0}H^$mx*SJyt=f4J0fd%>2f6{i>-Dj4R>eEB?JPG@-6 zkGlV_KPJ5w?w)yOhTLiG@ZU{uIg(!)YWObMzV+s-L%=v_JS>&TH`l}+nw)zvZVZ1 z>EmnZTcjB}o^8Eq5&uh~Al89BTe-h&D$9bolYX&qPnyT}-?Y(ImHrrP(`SnVULE!JDi*YC9_eDhB4!K;o za!ufxtU0*~vG)SC{yz;bX1%n|e$UyLGiy)pSmLrSOY&!S)9=l`CVh%4RUd~vy`$oC zR&7DmL5V9ed5Lw+wcZ^iQ=<7@vr`!~0$R(`^>W@!Vc>%kZ4xnWv7NJ3b3s z`;!=DzlUSC=JOlMFWq)}ul{{1#r(vHv)7m1_5U)V`0@QspL6zJ{qpib>!!cDTldEa zRCeSf_MQ>=FJ19~Wx~E)H=g|y3KG}9c{GhRGrK){-3hm={@Ttv*GW4a3xu_scJD z`0ytFp*s8ft&z+YFMcmh&HL24CVkE1zlUARCdON>X zX~&%S{mn1CQt&^Il)|^7IO-?wuUB7r_Lart+%s6Zl;guq*U9UO z0&k@K{pBB;==j^>$VTq)i?UH4Qm?#!^{4y(lFGCvYpy=ZnXRO7qGs`jrY|wGeJ-1MYuX;jgF!yJ{?b2@tS{X8c-RB5$* zzWIO7Tz1j7Zb9zWH~T_gMkX|Ea!UC3;pVCMt$V}P{*7K2m9zE!+k}1p@4qt>{gt`? z-p9*X;{Aec91s6rlg)!qiZeW9kuY9D+gnLu~6$&iP+^xAwrlvktd!wLW-o z@ZuV)Z2pNKouy}Od2s*H^v2_NjasKUY+14+tI+f7m99UhHGBM@spMrmO8zzT|Ipkz?7T3A!oHM6bmi4Z)@*eNwhTq<9Ro|FfU3}~|>(_~S z&mU$s_1*AZ(|Ud9=~b(=|DQ-a{Q7$8`NP-O-0JMS+S}77dGa|cOZ8&5)E94x%c@!2 zn*a5wWPaIN5Xb&)$-lz|eA-XS8}0tqhBY_m#Ivi%P3t*!M{>{VN3Qd3K4Y!l$k}fH zllRiC{pPm29(Z1Ibe{U|TD#pXR(tusf<~*4ueZ$zo6(S<5NMVhzxP7QQ*E>VJQLFl zwEx~wy)fBP(e-Jr&Fs%RvmduP|K9Ocw|xJKq!Wjx{r8OcDkAVr&u&V*_Ah?6&oyUq zzwSPMUGkylU+wzH9EmmI3`g^$&%fFkvNz7TW{<{vxtqMAw!TkGB82Q~t99=#*gt93 zveo?WZ5D6#{5RQr%0GvYW?lW}RQnKPPDibMk-V&-)kPb3CJU`yKJQrZ?vlwb{@bL8 z&ihv0^D$H8%g$?kD=zr!xP>`f-M;@?Wb}YziFh2O8 z;;Polf@r0$-!EGqtJ34V`R>eWvpFaBD>eQ)zFG8C>GGg@j-yL{w%WgDy6pFaN%v2z zJx7b@$%Ut0#ZS6%@aaXJdy!vdUEejGQq+mB&3?7jSvl>?>Bp`!UCcb$JT|FVKKo1*D;*XQV+#Xql_II4&o{GNVdaRmEvzYdr6DSFQAC$<<~-n0H|!&+A-alcI- z#XsiMKU%kXSKJwck5NA-yh{t{+%K)M`fGjdIWOzDoker+WKDkk`+V=>Uk^(hJC>x> zoUSSJ<9t{0?px=Y=~pcaIQqAymxo;xi2a{olAq)p`IV(T;Z^mD?F}xg9DWz4e={~d z`gwbTEopl6dQQ}xT&K{WWc}GQjyyT%#&=oW|Mmib zmG3ytR333Wu(SN6O=L}VxJa+7^qL*_)&4z|;jO>8WWg=v_sgo5G5h%*?7nQCd3c70 z%%aEjcilYnkJLJE-S9JagTSv}d)2I~Po&#;I`b$R^hSs!%;~Oo_Af}!Ip$y+(|L`< z!cyr@>1U%;GxM4LRAuHFKk{p>6FqHqH8pIr#KU+s;f8XFS(bYBGut*!zHC@L<%8|r z3vGHU=j|5UFLN(?k9^?idE5BU$oKC^b5weEr0mz7Ul*TqUHa&3fme;6 zCnS5ElKSqNVUnNVx%Tb6sH0vI4=>d+X}Z6vy|l8f#cM+E>viuES+|=m+!t_v#tXZL zx05z{c&2!}ypWIjx5o3mi*m^li|m4zVIR$P?Ru|mE|Qz8saL77<7ndjX^A=?Cw(c+ zuaw=STz&uECcYS#OpOSUqghAyJf2!tc4Jrf?d;jEUh8G+^5)7$ZSP^T?|l50b)ij) zVgSSoky!XK*&bHs}&gZ-~MKreWiN)wxW=& z@8_RYTJ5lBQoBcF`5un1_w!U;Hk+3lt;t`VS@);tkb8}#+;yM1vVL(sH7=1I-`|#M zUz!+l@}SY$hqaakpOQEDEL?j@GB(gw+VGxePWVdWr((Z#BxkR8Q@1r??2knKakjQFZQ-Ne*pd-~0s{cs)!s4ti6OXy?m~}CWbFM^) z$>M}_55iko%3TCMda3RV^qi2_BsL?rb+gL6<&z|>=D)jmdK1U)iQQ3kCq>h}cB=^) zwMK*qB|3zZ)~r7!`}0}UQ}gcgtD9z4?p^GZsl3^<{86U*w4NWrALREp?S8&eKW7JD zS&sO@`lAYmO!w{0U3b>tPH|*i$lfhoGVe0dZI-oHsK%BkWL#sAmoh`z zi;3Q|Hh-`Ead@K3B=I7)DQ*+polm_#c(iuY$=D|S55>Rk1yoN}b8vKIom<6fR~_+Q z!0ASysPL}q$LBXN_T)sD7MA?yPS7}SDLlb^PJv!#Wz@$Fmt3Sjl=-X7WcCj(+q^Wa za8_I|pYJN+sV~;GJKXe4Df(z}ziC3$(&m-VHU=CIJM}>`e0Q=@w%bk6zmY4gI;eOunI&70bNu8F6+ fCF1h)YR*MftL0ybGBX?u`?ogw-R;+UJ3a#dr=0mJ literal 0 HcmV?d00001 diff --git a/tests/pak/crush.cpp b/tests/pak/crush.cpp new file mode 100644 index 0000000..407c3b9 --- /dev/null +++ b/tests/pak/crush.cpp @@ -0,0 +1,81 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2025 Natalia Portillo. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library 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 library; if not, see . + */ + +#include +#include +#include + +#include "../../library.h" +#include "../crc32.h" +#include "gtest/gtest.h" + +#define EXPECTED_CRC32 0x66007dba + +static const uint8_t *buffer; + +class crushFixture : public ::testing::Test +{ +public: + crushFixture() + { + // initialization; + // can also be done in SetUp() + } + +protected: + void SetUp() + { + char path[PATH_MAX]; + char filename[PATH_MAX]; + + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/pak_crush.bin", path); + + FILE *file = fopen(filename, "rb"); + buffer = (const uint8_t *)malloc(63282); + fread((void *)buffer, 1, 63282, file); + fclose(file); + } + + void TearDown() { free((void *)buffer); } + + ~crushFixture() + { + // resources cleanup, no exceptions allowed + } + + // shared user data +}; + +TEST_F(crushFixture, crush) +{ + size_t destLen = 152089; + size_t srcLen = 63282; + auto *outBuf = (uint8_t *)malloc(152089); + + auto err = pak_decompress_crush(buffer, srcLen, outBuf, &destLen); + + EXPECT_EQ(err, 0); + EXPECT_EQ(destLen, 152089); + + auto crc = crc32_data(outBuf, 152089); + + free(outBuf); + + EXPECT_EQ(crc, EXPECTED_CRC32); +} \ No newline at end of file diff --git a/tests/pak/distill.cpp b/tests/pak/distill.cpp new file mode 100644 index 0000000..00d4882 --- /dev/null +++ b/tests/pak/distill.cpp @@ -0,0 +1,81 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2025 Natalia Portillo. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library 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 library; if not, see . + */ + +#include +#include +#include + +#include "../../library.h" +#include "../crc32.h" +#include "gtest/gtest.h" + +#define EXPECTED_CRC32 0x66007dba + +static const uint8_t *buffer; + +class distillFixture : public ::testing::Test +{ +public: + distillFixture() + { + // initialization; + // can also be done in SetUp() + } + +protected: + void SetUp() + { + char path[PATH_MAX]; + char filename[PATH_MAX]; + + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/pak_distill.bin", path); + + FILE *file = fopen(filename, "rb"); + buffer = (const uint8_t *)malloc(60540); + fread((void *)buffer, 1, 60540, file); + fclose(file); + } + + void TearDown() { free((void *)buffer); } + + ~distillFixture() + { + // resources cleanup, no exceptions allowed + } + + // shared user data +}; + +TEST_F(distillFixture, distill) +{ + size_t destLen = 152089; + size_t srcLen = 60540; + auto *outBuf = (uint8_t *)malloc(152089); + + auto err = pak_decompress_distill(buffer, srcLen, outBuf, &destLen); + + EXPECT_EQ(err, 0); + EXPECT_EQ(destLen, 152089); + + auto crc = crc32_data(outBuf, 152089); + + free(outBuf); + + EXPECT_EQ(crc, EXPECTED_CRC32); +} \ No newline at end of file