diff --git a/libctru/include/3ds/util/decompress.h b/libctru/include/3ds/util/decompress.h index ffa145c..9538903 100644 --- a/libctru/include/3ds/util/decompress.h +++ b/libctru/include/3ds/util/decompress.h @@ -5,8 +5,28 @@ #pragma once #include +#include #include +/** @brief Compression types */ +typedef enum +{ + DECOMPRESS_DUMMY = 0x00, ///< Dummy compression + DECOMPRESS_LZSS = 0x10, ///< LZSS/LZ10 compression + DECOMPRESS_LZ10 = 0x10, ///< LZSS/LZ10 compression + DECOMPRESS_LZ11 = 0x11, ///< LZ11 compression + DECOMPRESS_HUFF1 = 0x21, ///< Huffman compression with 1-bit data + DECOMPRESS_HUFF2 = 0x22, ///< Huffman compression with 2-bit data + DECOMPRESS_HUFF3 = 0x23, ///< Huffman compression with 3-bit data + DECOMPRESS_HUFF4 = 0x24, ///< Huffman compression with 4-bit data + DECOMPRESS_HUFF5 = 0x25, ///< Huffman compression with 5-bit data + DECOMPRESS_HUFF6 = 0x26, ///< Huffman compression with 6-bit data + DECOMPRESS_HUFF7 = 0x27, ///< Huffman compression with 7-bit data + DECOMPRESS_HUFF8 = 0x28, ///< Huffman compression with 8-bit data + DECOMPRESS_HUFF = 0x28, ///< Huffman compression with 8-bit data + DECOMPRESS_RLE = 0x30, ///< Run-length encoding compression +} decompressType; + /** @brief I/O vector */ typedef struct { @@ -39,6 +59,19 @@ ssize_t decompressCallback_FD(void *userdata, void *buffer, size_t size); */ ssize_t decompressCallback_Stdio(void *userdata, void *buffer, size_t size); +/** @brief Decode decompression header + * @param[out] type Decompression type + * @param[out] size Decompressed size + * @param[in] callback Data callback (see decompressV()) + * @param[in] userdata User data passed to callback (see decompressV()) + * @param[in] insize Size of userdata (see decompressV()) + * @returns Bytes consumed + * @retval -1 error + */ +ssize_t decompressHeader(decompressType *type, size_t *size, + decompressCallback callback, void *userdata, + size_t insize); + /** @brief Decompress data * @param[in] iov Output vector * @param[in] iovcnt Number of buffers @@ -137,6 +170,7 @@ decompress_LZ11(void *output, size_t size, decompressCallback callback, } /** @brief Decompress Huffman + * @param[in] bits Data size in bits (usually 4 or 8) * @param[in] iov Output vector * @param[in] iovcnt Number of buffers * @param[in] callback Data callback (see decompressV()) @@ -144,11 +178,12 @@ decompress_LZ11(void *output, size_t size, decompressCallback callback, * @param[in] insize Size of userdata (see decompressV()) * @returns Whether succeeded */ -bool decompressV_Huff(const decompressIOVec *iov, size_t iovcnt, +bool decompressV_Huff(size_t bits, const decompressIOVec *iov, size_t iovcnt, decompressCallback callback, void *userdata, size_t insize); /** @brief Decompress Huffman + * @param[in] bits Data size in bits (usually 4 or 8) * @param[in] output Output buffer * @param[in] size Output size limit * @param[in] callback Data callback (see decompressV()) @@ -157,14 +192,14 @@ bool decompressV_Huff(const decompressIOVec *iov, size_t iovcnt, * @returns Whether succeeded */ static inline bool -decompress_Huff(void *output, size_t size, decompressCallback callback, - void *userdata, size_t insize) +decompress_Huff(size_t bits, void *output, size_t size, + decompressCallback callback, void *userdata, size_t insize) { decompressIOVec iov; iov.data = output; iov.size = size; - return decompressV_Huff(&iov, 1, callback, userdata, insize); + return decompressV_Huff(bits, &iov, 1, callback, userdata, insize); } /** @brief Decompress run-length encoding diff --git a/libctru/source/util/decompress/decompress.c b/libctru/source/util/decompress/decompress.c index 63a76f6..8cb54b1 100644 --- a/libctru/source/util/decompress/decompress.c +++ b/libctru/source/util/decompress/decompress.c @@ -31,24 +31,39 @@ typedef struct /** @brief Initialize buffer object from memory * @param[in] buffer Decompression buffer object - * @param[in] data Data to buffer + * @param[in] data Data to emulate buffering * @param[in] size Data size */ static inline void buffer_memory(buffer_t *buffer, const void *data, size_t size) { - buffer->data = (void*)data; - buffer->size = size; - buffer->pos = 0; + buffer->data = (void*)data; + buffer->limit = size; + buffer->size = size; + buffer->pos = 0; } -/** @brief Initialize buffer object +/** @brief Initialize buffer object with static memory + * @param[in] buffer Decompression buffer object + * @param[in] data Data buffer + * @param[in] size Data size + */ +static inline void +buffer_static(buffer_t *buffer, const void *data, size_t size) +{ + buffer->data = (void*)data; + buffer->limit = size; + buffer->size = 0; + buffer->pos = 0; +} + +/** @brief Initialize buffer object with dynamic memory * @param[in] buffer Decompression buffer object * @param[in] size Buffer size limit * @returns Whether succeeded */ static inline bool -buffer_init(buffer_t *buffer, size_t size) +buffer_dynamic(buffer_t *buffer, size_t size) { buffer->data = (uint8_t*)malloc(size); if(!buffer->data) @@ -498,6 +513,7 @@ decompress_lz11(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt, } /** @brief Decompress Huffman + * @param[in] bits Data size in bits (usually 4 or 8) * @param[in] buffer Decompression buffer object * @param[in] iov Output vector * @param[in] iovcnt Number of buffers @@ -507,9 +523,13 @@ decompress_lz11(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt, * @returns Whether succeeded */ static bool -decompress_huff(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt, - size_t size, decompressCallback callback, void *userdata) +decompress_huff(const size_t bits, buffer_t *buffer, const decompressIOVec *iov, + size_t iovcnt, size_t size, decompressCallback callback, + void *userdata) { + if(bits < 1 || bits > 8) + return false; + uint8_t *tree = (uint8_t*)malloc(512); if(!tree) return false; @@ -528,14 +548,13 @@ decompress_huff(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt, return false; } - iov_iter out = iov_begin(iov, iovcnt); - const size_t bits = 8; - uint32_t word = 0; // 32-bits of input bitstream - uint32_t mask = 0; // which bit we are reading - uint32_t dataMask = (1<