diff options
Diffstat (limited to 'libpsn00b/lzp')
| -rw-r--r-- | libpsn00b/lzp/bit.c | 65 | ||||
| -rw-r--r-- | libpsn00b/lzp/bit.h | 26 | ||||
| -rw-r--r-- | libpsn00b/lzp/compress.c | 488 | ||||
| -rw-r--r-- | libpsn00b/lzp/crc.c | 91 | ||||
| -rw-r--r-- | libpsn00b/lzp/lzp.c | 88 | ||||
| -rw-r--r-- | libpsn00b/lzp/lzp.h | 223 | ||||
| -rw-r--r-- | libpsn00b/lzp/lzqlp.h | 26 | ||||
| -rw-r--r-- | libpsn00b/lzp/makefile | 28 | ||||
| -rw-r--r-- | libpsn00b/lzp/qlp.c | 64 |
9 files changed, 1099 insertions, 0 deletions
diff --git a/libpsn00b/lzp/bit.c b/libpsn00b/lzp/bit.c new file mode 100644 index 0000000..aefa45d --- /dev/null +++ b/libpsn00b/lzp/bit.c @@ -0,0 +1,65 @@ +#include "bit.h" + +// Bit I/O +// + +unsigned char* inPtr = 0; +int inBytes = 0; +unsigned char* outPtr = 0; +int outBytes = 0; + +int bit_buf; +int bit_count; + +void init_bits() { + + bit_count = bit_buf=0; + +} + +void put_bits(int n, int x) { + + bit_buf |= x<<bit_count; + bit_count += n; + + while(bit_count >= 8) { + + *outPtr = bit_buf; + outPtr++; + outBytes++; + + bit_buf >>= 8; + bit_count -= 8; + + } + +} + +void flush_bits() { + + put_bits(7, 0); + bit_count = bit_buf = 0; + +} + +int get_bits(int n) { + + int x; + + while(bit_count < n) { + + bit_buf |= *inPtr<<bit_count; + inPtr++; + inBytes++; + + bit_count += 8; + + } + + x = bit_buf&((1<<n)-1); + bit_buf >>= n; + bit_count -= n; + + return(x); + +} diff --git a/libpsn00b/lzp/bit.h b/libpsn00b/lzp/bit.h new file mode 100644 index 0000000..ff71025 --- /dev/null +++ b/libpsn00b/lzp/bit.h @@ -0,0 +1,26 @@ +#ifndef _LZP_BIT_H +#define _LZP_BIT_H + +extern unsigned char* inPtr; +extern int inBytes; +extern unsigned char* outPtr; +extern int outBytes; + +extern int bit_buf; +extern int bit_count; + +#ifdef __cplusplus +extern "C" { +#endif + +void init_bits(); +void put_bits(int n, int x); +void flush_bits(); +int get_bits(int n); + +#ifdef __cplusplus +} +#endif + + +#endif // _LZP_BIT_H diff --git a/libpsn00b/lzp/compress.c b/libpsn00b/lzp/compress.c new file mode 100644 index 0000000..33af08d --- /dev/null +++ b/libpsn00b/lzp/compress.c @@ -0,0 +1,488 @@ +// Based on ilia muraviev's CRUSH compressor program which falls under public domain + +#include <string.h> +#if LZP_USE_MALLOC == TRUE +#include <stdlib.h> +#endif + +#include "lzconfig.h" +#include "bit.h" +#include "lzp.h" + + +// Internal structure for hash table allocation sizes +#if LZP_NO_COMPRESS == FALSE + +struct { + short WindowSize; // Window size (17 - 23) + short Hash1Size; // Hash 1 table size (10 - 21) + short Hash2Size; // Hash 2 table size (12 - 24) +} lzHashParam = { + LZP_WINDOW_SIZE, + LZP_HASH1_SIZE, + LZP_HASH2_SIZE +}; + +#endif + + +// Defines and macros for lz77 compression/decompression (don't touch) +#define W_BITS lzHashParam.WindowSize +#define HASH1_BITS lzHashParam.Hash1Size +#define HASH2_BITS lzHashParam.Hash2Size + +#define W_SIZE (1<<W_BITS) +#define W_MASK (W_SIZE-1) +#define SLOT_BITS 4 +#define NUM_SLOTS (1<<SLOT_BITS) + +#define A_BITS 2 // 1 xx +#define B_BITS 2 // 01 xx +#define C_BITS 2 // 001 xx +#define D_BITS 3 // 0001 xxx +#define E_BITS 5 // 00001 xxxxx +#define F_BITS 9 // 00000 xxxxxxxxx +#define A (1<<A_BITS) +#define B ((1<<B_BITS)+A) +#define C ((1<<C_BITS)+B) +#define D ((1<<D_BITS)+C) +#define E ((1<<E_BITS)+D) +#define F ((1<<F_BITS)+E) +#define MIN_MATCH 3 +#define MAX_MATCH ((F-1)+MIN_MATCH) + +#define BUF_SIZE (1<<26) +#define TOO_FAR (1<<16) + +#define HASH1_LEN MIN_MATCH +#define HASH2_LEN (MIN_MATCH+1) +#define HASH1_SIZE (1<<HASH1_BITS) +#define HASH2_SIZE (1<<HASH2_BITS) +#define HASH1_MASK (HASH1_SIZE-1) +#define HASH2_MASK (HASH2_SIZE-1) +#define HASH1_SHIFT ((HASH1_BITS+(HASH1_LEN-1))/HASH1_LEN) +#define HASH2_SHIFT ((HASH2_BITS+(HASH2_LEN-1))/HASH2_LEN) + + +// LZ77 +// + +#if LZP_NO_COMPRESS == FALSE + +int update_hash1(int h, int c) { + + return(((h<<HASH1_SHIFT)+c)&HASH1_MASK); + +} + +int update_hash2(int h, int c) { + + return(((h<<HASH2_SHIFT)+c)&HASH2_MASK); + +} + +int get_min(int a, int b) { + + return(a<b?a:b); + +} + +int get_max(int a, int b) { + + return(a>b?a:b); + +} + +int get_penalty(int a, int b) { + + int p=0; + + while(a > b) { + a >>= 3; + ++p; + } + + return(p); + +} + +int lzCompress(void* outBuff, void* inBuff, int inSize, int level) { + + #if LZP_USE_MALLOC == FALSE + int head[HASH1_SIZE+HASH2_SIZE]; + int prev[W_SIZE]; + #else + int* head = malloc(4*(HASH1_SIZE+HASH2_SIZE)); + int* prev = malloc(4*W_SIZE); + #endif + + + int max_chain[] = {4, 256, 1<<12}; + + int i,s; + int h1=0; + int h2=0; + int p=0; + + int len; + int offset; + + int max_match; + int limit; + + int chain_len; + int next_p; + int max_lazy; + int log; + + + inPtr = (unsigned char*)inBuff; + outPtr = (unsigned char*)outBuff; + outBytes = 0; + + + for (i=0; i<HASH1_SIZE+HASH2_SIZE; ++i) + head[i] = -1; + + for (i=0; i<HASH1_LEN; ++i) + h1=update_hash1(h1, inPtr[i]); + + for (i=0; i<HASH2_LEN; ++i) + h2=update_hash2(h2, inPtr[i]); + + init_bits(); + + // Put window size value so that the compressed data will be independent of the compression settings + put_bits(5, lzHashParam.WindowSize); + + while(p < inSize) { + + len = MIN_MATCH-1; + offset = W_SIZE; + + max_match = get_min(MAX_MATCH, inSize-p); + limit = get_max(p-W_SIZE, 0); + + if (head[h1] >= limit) { + + s = head[h1]; + + if (inPtr[s] == inPtr[p]) { + + i = 0; + + while(++i < max_match) { + if (inPtr[s+i] != inPtr[p+i]) + break; + } + + if (i > len) { + len = i; + offset = p-s; + } + + } + + } + + if (len < MAX_MATCH) { + + chain_len = max_chain[level]; + s = head[h2+HASH1_SIZE]; + + while((chain_len-- != 0) && (s >= limit)) { + + if ((inPtr[s+len] == inPtr[p+len]) && (inPtr[s] == inPtr[p])) { + + i = 0; + + while(++i < max_match) { + if (inPtr[s+i] != inPtr[p+i]) + break; + } + + if (i > len+get_penalty((p-s)>>4, offset)) { + len = i; + offset = p-s; + } + + if (i == max_match) + break; + + } + + s=prev[s&W_MASK]; + + } + + } + + if ((len == MIN_MATCH) && (offset > TOO_FAR)) + len=0; + + if ((level >= 2) && (len >= MIN_MATCH) && (len < max_match)) { + + next_p = p+1; + max_lazy = get_min(len+4, max_match); + + chain_len = max_chain[level]; + s = head[update_hash2(h2, inPtr[next_p+(HASH2_LEN-1)])+HASH1_SIZE]; + + while((chain_len-- != 0) && (s >= limit)) { + + if ((inPtr[s+len] == inPtr[next_p+len]) && (inPtr[s] == inPtr[next_p])) { + + i = 0; + + while(++i < max_lazy) { + if (inPtr[s+i] != inPtr[next_p+i]) + break; + } + + if (i > len+get_penalty(next_p-s, offset)) { + len = 0; + break; + } + + if (i == max_lazy) + break; + + } + + s = prev[s&W_MASK]; + + } + + } + + + if (len >= MIN_MATCH) { // Match + + put_bits(1, 1); + + i = len-MIN_MATCH; + + if (i < A) { + put_bits(1, 1); // 1 + put_bits(A_BITS, i); + } else if (i < B) { + put_bits(2, 1<<1); // 01 + put_bits(B_BITS, i-A); + } else if (i < C) { + put_bits(3, 1<<2); // 001 + put_bits(C_BITS, i-B); + } else if (i < D) { + put_bits(4, 1<<3); // 0001 + put_bits(D_BITS, i-C); + } else if (i < E) { + put_bits(5, 1<<4); // 00001 + put_bits(E_BITS, i-D); + } else { + put_bits(5, 0); // 00000 + put_bits(F_BITS, i-E); + } + + --offset; + log = W_BITS-NUM_SLOTS; + + while(offset >= (2<<log)) + ++log; + + put_bits(SLOT_BITS, log-(W_BITS-NUM_SLOTS)); + + if (log>(W_BITS-NUM_SLOTS)) + put_bits(log, offset-(1<<log)); + else + put_bits(W_BITS-(NUM_SLOTS-1), offset); + + } else { // Literal + + len = 1; + put_bits(9, inPtr[p]<<1); // 0 xxxxxxxx + + } + + while(len-- != 0) { // Insert new strings + + head[h1] = p; + prev[p&W_MASK] = head[h2+HASH1_SIZE]; + head[h2+HASH1_SIZE] = p; + + ++p; + + h1 = update_hash1(h1, inPtr[p+(HASH1_LEN-1)]); + h2 = update_hash2(h2, inPtr[p+(HASH2_LEN-1)]); + + } + + } + + flush_bits(); + + #if LZP_USE_MALLOC == TRUE + free(head); + free(prev); + #endif + + return(outBytes); + +} + +void lzSetHashSizes(int window, int hash1, int hash2) { + + lzHashParam.WindowSize = window; + lzHashParam.Hash1Size = hash1; + lzHashParam.Hash2Size = hash2; + +} + +void lzResetHashSizes() { + + lzHashParam.WindowSize = LZP_WINDOW_SIZE; + lzHashParam.Hash1Size = LZP_HASH1_SIZE; + lzHashParam.Hash2Size = LZP_HASH2_SIZE; + +} + +#endif // LZP_NO_COMPRESS + +int lzDecompress(void* outBuff, void* inBuff, int inSize) { + + int p=0; + int len; + int log; + int s; + int windowSize; + + inPtr = (unsigned char*)inBuff; + outPtr = (unsigned char*)outBuff; + inBytes = 0; + outBytes = 0; + + init_bits(); + + // Get window size value + windowSize = get_bits(5); + + while(inBytes < inSize) { + + if (get_bits(1)) { + + if (get_bits(1)) + len = get_bits(A_BITS); + else if (get_bits(1)) + len = get_bits(B_BITS)+A; + else if (get_bits(1)) + len = get_bits(C_BITS)+B; + else if (get_bits(1)) + len = get_bits(D_BITS)+C; + else if (get_bits(1)) + len = get_bits(E_BITS)+D; + else + len = get_bits(F_BITS)+E; + + log = get_bits(SLOT_BITS)+(windowSize-NUM_SLOTS); + + s =~ (log>(windowSize-NUM_SLOTS) ? get_bits(log)+(1<<log) : get_bits(windowSize-(NUM_SLOTS-1)))+p; + + if (s < 0) + return(LZP_ERR_DECOMPRESS); + + outPtr[p++] = outPtr[s++]; + outPtr[p++] = outPtr[s++]; + outPtr[p++] = outPtr[s++]; + + while(len-- != 0) + outPtr[p++] = outPtr[s++]; + + } else { + + outPtr[p++] = get_bits(8); + + } + + } + + return(p); + +} + +int lzDecompressLen(void* outBuff, int outSize, void* inBuff, int inSize) { + + int p=0; + int len; + int log; + int s; + int windowSize; + + inPtr = (unsigned char*)inBuff; + outPtr = (unsigned char*)outBuff; + inBytes = 0; + outBytes = 0; + + init_bits(); + + // Get window size value + windowSize = get_bits(5); + + while(inBytes < inSize) { + + if (get_bits(1)) { + + if (get_bits(1)) + len = get_bits(A_BITS); + else if (get_bits(1)) + len = get_bits(B_BITS)+A; + else if (get_bits(1)) + len = get_bits(C_BITS)+B; + else if (get_bits(1)) + len = get_bits(D_BITS)+C; + else if (get_bits(1)) + len = get_bits(E_BITS)+D; + else + len = get_bits(F_BITS)+E; + + log = get_bits(SLOT_BITS)+(windowSize-NUM_SLOTS); + + s =~ (log>(windowSize-NUM_SLOTS) ? get_bits(log)+(1<<log) : get_bits(windowSize-(NUM_SLOTS-1)))+p; + + if (s < 0) + return(LZP_ERR_DECOMPRESS); + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + while(len-- != 0) { + + outPtr[p++] = outPtr[s++]; + if (p >= outSize) + break; + + } + + if (p >= outSize) + break; + + } else { + + outPtr[p++] = get_bits(8); + + } + + if (p >= outSize) + break; + + } + + return(p); + +} diff --git a/libpsn00b/lzp/crc.c b/libpsn00b/lzp/crc.c new file mode 100644 index 0000000..c5ab702 --- /dev/null +++ b/libpsn00b/lzp/crc.c @@ -0,0 +1,91 @@ +#include "lzp.h" + +void initTable16(unsigned short* table) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) + crc = ( crc >> 1 ) ^ 0xA001; + else + crc = crc >> 1; + + c = c >> 1; + } + + table[i] = crc; + } + +} + +void initTable32(unsigned int* table) { + + int i,j; + unsigned int crcVal; + + for(i=0; i<256; i++) { + + crcVal = i; + + for(j=0; j<8; j++) { + + if (crcVal&0x00000001L) + crcVal = (crcVal>>1)^0xEDB88320L; + else + crcVal = crcVal>>1; + + } + + table[i] = crcVal; + + } + +} + +unsigned short lzCRC16(void* buff, int bytes, unsigned short crc) { + + int i; + unsigned short tmp, short_c; + unsigned short crcTable[256]; + + initTable16(crcTable); + + for(i=0; i<bytes; i++) { + + short_c = 0x00ff & (unsigned short)((unsigned char*)buff)[i]; + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crcTable[tmp&0xff]; + + } + + return(crc); + +} + +unsigned int lzCRC32(void* buff, int bytes, unsigned int crc) { + + int i; + unsigned char* byteBuff = (unsigned char*)buff; + unsigned int byte; + unsigned int crcTable[256]; + + initTable32(crcTable); + + for(i=0; i<bytes; i++) { + + byte = 0x000000ffL&(unsigned int)byteBuff[i]; + crc = (crc>>8)^crcTable[(crc^byte)&0xff]; + + } + + return(crc^0xFFFFFFFF); + +} diff --git a/libpsn00b/lzp/lzp.c b/libpsn00b/lzp/lzp.c new file mode 100644 index 0000000..1f4fea4 --- /dev/null +++ b/libpsn00b/lzp/lzp.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "lzp.h" + + +static char* lcase(char* text) { + + int i; + + for(i=0; text[i]!=0x00; i++) + text[i] = tolower(text[i]); + + return(text); + +} + + +int lzpSearchFile(const char* fileName, void* lzpack) { + + int i; + char searchName[16]; + char compareName[16]; + LZP_FILE* fileEntry; + + strcpy(searchName, fileName); + lcase(searchName); + + fileEntry = (LZP_FILE*)(lzpack+4); + for(i=0; i<((LZP_HEAD*)lzpack)->numFiles; i++) { + + strcpy(compareName, fileEntry[i].fileName); + lcase(compareName); + + if (strcmp(searchName, compareName) == 0) + return(i); + + } + + return(LZP_ERR_NOTFOUND); + +} + +LZP_FILE* lzpFileEntry(void* lzpack, int fileNum) { + + if (strncmp("LZP", ((LZP_HEAD*)lzpack)->id, 3) != 0) + return(NULL); + + if ((fileNum < 0) || (fileNum > (((LZP_HEAD*)lzpack)->numFiles-1))) + return(NULL); + + return(&((LZP_FILE*)(lzpack+4))[fileNum]); + +} + +int lzpFileSize(void* lzpack, int fileNum) { + + if (strncmp("LZP", ((LZP_HEAD*)lzpack)->id, 3) != 0) + return 0; + + if ((fileNum < 0) || (fileNum > (((LZP_HEAD*)lzpack)->numFiles-1))) + return 0; + + return ((LZP_FILE*)(lzpack+4))[fileNum].fileSize; +} + +int lzpUnpackFile(void* buff, void* lzpack, int fileNum) { + + LZP_FILE* fileEntry = &((LZP_FILE*)(lzpack+4))[fileNum]; + int unpackedSize; + + // Check ID header + if (strncmp("LZP", ((LZP_HEAD*)lzpack)->id, 3) != 0) + return(LZP_ERR_INVALID_PACK); + + // Do a CRC16 check of the compressed data's integrity + if (lzCRC32(lzpack+fileEntry->offset, fileEntry->packedSize, LZP_CRC32_REMAINDER) != fileEntry->crc) + return(LZP_ERR_CRC_MISMATCH); + + // Decompress data to the specified address + unpackedSize = lzDecompress(buff, lzpack+fileEntry->offset, fileEntry->packedSize); + if (unpackedSize < 0) + return(unpackedSize); + + return(unpackedSize); + +} diff --git a/libpsn00b/lzp/lzp.h b/libpsn00b/lzp/lzp.h new file mode 100644 index 0000000..ffd7933 --- /dev/null +++ b/libpsn00b/lzp/lzp.h @@ -0,0 +1,223 @@ +/*! \file lzp.h + * \brief Main library header + */ + +/*! \mainpage + * \version 0.20b + * \author John Wilbert 'Lameguy64' Villamor + * + * \section creditsSection Credits + * - LZ77 data compression/decompression routines based from Ilya Muravyov's + * crush.cpp released under public domain. Refined and ported to C by Lameguy64. + * - CRC calculation routines based from Lammert Bies' lib_crc routines. + * + */ + +#ifndef _LZPACK_H +#define _LZPACK_H + +#include <sys/types.h> +#ifdef _WIN32 +#include <windows.h> +#endif + +/*! \addtogroup crcBaseRemainders CRC Base Remainder Values + * @{ + */ +//! Initial remainder value for lzCRC16() +#define LZP_CRC16_REMAINDER 0x0000 +//! Initial remainder value for lzCRC32() +#define LZP_CRC32_REMAINDER 0xFFFFFFFF +/*! @} */ + + +/*! \addtogroup compLevels Compression Levels + * \brief Compression levels for the lzCompress() function. + * @{ + */ +//! Minimal (but fast) compression +#define LZP_COMPRESS_FAST 0 +//! Normal compression level +#define LZP_COMPRESS_NORMAL 1 +//! Maximum compression level +#define LZP_COMPRESS_MAX 2 +/*! @} */ + + +/*! \addtogroup libraryErrorCodes Library Error Codes + * @{ + */ +//! No error +#define LZP_ERR_NONE 0 +//! Decompression error +#define LZP_ERR_DECOMPRESS -1 +//! Not a valid LZP/QLP/PCK archive +#define LZP_ERR_INVALID_PACK -2 +//! File not found +#define LZP_ERR_NOTFOUND -3 +//! CRC check mismatch (data corruption) +#define LZP_ERR_CRC_MISMATCH -4 +/*! @} */ + + +//! Header structure of an LZP format archive file +typedef struct { + + //! File ID (must always be 'LZP') + char id[3]; + //! File count + u_char numFiles; + +} LZP_HEAD; + +//! File entry structure for an LZP format archive file +typedef struct { + + //! File name + char fileName[16]; + //! CRC32 checksum of file + u_int crc; + //! Original size of file in bytes + u_int fileSize; + //! Compressed size of file + u_int packedSize; + //! File data offset + u_int offset; + +} LZP_FILE; + + +// Function prototypes +#ifdef __cplusplus +extern "C" { +#endif + + +/*! \addtogroup compressFuncs Data Compression and Decompression Functions + * \brief Functions to compress and decompress data. + * @{ + */ + +/*! Compress a block of data. + * + * \details This function compresses a specified block of data in LZ77 encoding. + * Depending on the size of the input data and speed of the computer, compression + * may take a while to complete. + * + * \param[out] *outBuff Pointer to buffer to store compressed data. + * \param[in] *inBuff Pointer to data to compress. + * \param[in] inSize Size of data to compress in bytes. + * \param[in] level Compression level (see \ref compLevels). + * + * \returns The size of the compressed data in bytes. + */ +int lzCompress(void* outBuff, void* inBuff, int inSize, int level); + +/*! Decompress a compressed block of data. + * + * \details Decompressed a compressed block of data produced by lzCompress(). It cannot + * return the decompressed size of the data ahead of time so you must preserve the decompressed + * size of the data yourself. + * + * \note The decompression algorithm used in this function is completely independent + * of the compression settings set by lzSetHashSizes() before compressing the data with + * lzCompress(). + * + * \param[out] *outBuff Pointer to buffer to store decompressed data. + * \param[in] *inBuff Pointer to compressed data to decompress. + * \param[in] inSize Compressed data size in bytes. + * + * \returns Size of decompressed data in bytes or LZP_ERR_DECOMPRESS if a + * decompression error occurred. + */ +int lzDecompress(void* outBuff, void* inBuff, int inSize); + +int lzDecompressLen(void* outBuff, int outSize, void* inBuff, int inSize); + +/*! Sets the sizes of hash tables for data compression. + * + * \param[in] window Sliding window size. + * \param[in] hash1 Hash table 1 size. + * \param[in] hash2 Hash table 2 size. + */ +void lzSetHashSizes(int window, int hash1, int hash2); + +/*! Reset the sizes of hash tables to their defaults. + */ +void lzResetHashSizes(); + +/*! @} */ + + +/*! \addtogroup crcFuncs CRC Hashing Functions + * \brief Functions to calculate CRC hashes of data. + * @{ + */ + +/*! Calculates a CRC16 hash of the specified buffer. + * + * \param[in] *buff Pointer to buffer to calculate a hash of. + * \param[in] bytes Size of buffer in bytes. + * \param[in] crc CRC remainder (use LZP_CRC16_REMAINDER). + * + * \returns CRC16 hash of specified buffer. + */ +unsigned short lzCRC16(void* buff, int bytes, unsigned short crc); + +/*! Calculates a CRC32 hash of the specified buffer. + * + * \param[in] *buff Pointer to buffer to calculate a hash of. + * \param[in] bytes Size of buffer in bytes. + * \param[in] crc CRC remainder (use LZP_CRC16_REMAINDER). + * + * \returns CRC32 hash of specified buffer. + */ +unsigned int lzCRC32(void* buff, int bytes, unsigned int crc); + +/*! @} */ + + +/*! \addtogroup lzpFunctions LZP Archive Handling Routines + * \brief Functions to index and unpack files from LZP archives. + * @{ + */ + +/*! Searches for a file by name in an LZP archive and returns a file entry number. + * + * \param[in] *fileName String of file to search (must be less than 13 characters). + * \param[in] *lzpack Pointer to LZP archive file. + * + * \returns File index of found file or one of \ref libraryErrorCodes if an error occurred. + */ +int lzpSearchFile(const char* fileName, void* lzpack); + +int lzpFileSize(void* lzpack, int fileNum); + +/*! Get a pointer to a file entry inside of an LZP archive. + * + * \param[in] *lzpack Pointer to LZP archive file. + * \param[in] fileNum File number to get an entry of (you may use lzpSearchFile()). + * + * \returns A pointer to an LZP_FILE struct or NULL if an error occurred. + */ +LZP_FILE* lzpFileEntry(void* lzpack, int fileNum); + +/*! Unpacks a file from an LZP archive to the specified memory buffer. + * + * \param[in] *buff Pointer to buffer to store unpacked file. + * \param[in] *lzpack Pointer to LZP archive file. + * \param[in] fileNum File entry number of file to extract (you may use lzpSearchFile()). + * + * \returns Size of decompressed file in bytes or one of \ref libraryErrorCodes if an error occurred. + */ +int lzpUnpackFile(void* buff, void* lzpack, int fileNum); + +/*! @} */ + + +#ifdef __cplusplus +} +#endif + + +#endif // _LZPACK_H diff --git a/libpsn00b/lzp/lzqlp.h b/libpsn00b/lzp/lzqlp.h new file mode 100644 index 0000000..fae6438 --- /dev/null +++ b/libpsn00b/lzp/lzqlp.h @@ -0,0 +1,26 @@ +#ifndef _QLP_H +#define _QLP_H + +#define PACK_ERR_NONE 0 +#define PACK_ERR_INVALID -1 +#define PACK_ERR_NOTFOUND -2 +#define PACK_ERR_INCOMPLETE -3 +#define PACK_ERR_READ_FAULT -4 + +typedef struct { + char id[3]; + unsigned char numfiles; +} QLP_HEAD; + +typedef struct { + char name[16]; + unsigned int size; + unsigned int offs; +} QLP_FILE; + +int qlpFileCount(void* qlpfile); +QLP_FILE* qlpFileEntry(int index, void* qlpfile); +void* qlpFileAddr(int index, void* qlpfile); +int qlpFindFile(char* fileName, void* qlpfile); + +#endif // _QLP_H
\ No newline at end of file diff --git a/libpsn00b/lzp/makefile b/libpsn00b/lzp/makefile new file mode 100644 index 0000000..cf82872 --- /dev/null +++ b/libpsn00b/lzp/makefile @@ -0,0 +1,28 @@ +PREFIX = mipsel-unknown-elf- + +TARGET = liblzp.a + +CFILES = $(notdir $(wildcard ./*.c)) +OFILES = $(addprefix build/,$(CFILES:.c=.o)) + +INCLUDE = -I../include + +CFLAGS = -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute +AFLAGS = -msoft-float --strip-local-absolute + +CC = $(PREFIX)gcc +AR = $(PREFIX)ar +RANLIB = $(PREFIX)ranlib + +all: $(TARGET) + +$(TARGET): $(OFILES) + $(AR) cr $(TARGET) $(OFILES) + $(RANLIB) $(TARGET) + +build/%.o: %.c + @mkdir -p build + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -Rf build $(OFILES) $(TARGET) diff --git a/libpsn00b/lzp/qlp.c b/libpsn00b/lzp/qlp.c new file mode 100644 index 0000000..3be8356 --- /dev/null +++ b/libpsn00b/lzp/qlp.c @@ -0,0 +1,64 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "lzqlp.h" + +static char* lcase(char* str) { + + while(*str != 0x00) { + *str = tolower(*str); + str++; + } + + return(str); + +} + +int qlpFileCount(void* qlpfile) { + + if (strncmp(((QLP_HEAD*)qlpfile)->id, "QLP", 3) != 0) + return(PACK_ERR_INVALID); + + return(((QLP_HEAD*)qlpfile)->numfiles); + +} + +QLP_FILE* qlpFileEntry(int index, void* qlpfile) { + + if (strncmp(((QLP_HEAD*)qlpfile)->id, "QLP", 3) != 0) + return(NULL); + + if (index > ((QLP_HEAD*)qlpfile)->numfiles) + return(NULL); + + return(&((QLP_FILE*)(qlpfile+4))[index]); + +} + +void* qlpFileAddr(int index, void* qlpfile) { + + return( qlpfile+((QLP_FILE*)(qlpfile+4))[index].offs ); + +} + +int qlpFindFile(char* fileName, void* qlpfile) { + + int i; + char nameBuff[2][16]; + + strcpy(nameBuff[0], fileName); + lcase(nameBuff[0]); + + for(i=0; i<((QLP_HEAD*)qlpfile)->numfiles; i++) { + + strcpy(nameBuff[1], ((QLP_FILE*)(qlpfile+4))[i].name); + lcase(nameBuff[1]); + + if (strcmp(nameBuff[0], nameBuff[1]) == 0) + return(i); + + } + + return(PACK_ERR_NOTFOUND); + +}
\ No newline at end of file |
