From f3e040230772f978540a71aea43dfde200992922 Mon Sep 17 00:00:00 2001 From: "John Wilbert M. Villamor" Date: Sat, 6 Apr 2019 10:11:07 +0800 Subject: First commit --- libpsn00b/lzp/compress.c | 488 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 488 insertions(+) create mode 100644 libpsn00b/lzp/compress.c (limited to 'libpsn00b/lzp/compress.c') 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 +#if LZP_USE_MALLOC == TRUE +#include +#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<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= 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<(W_BITS-NUM_SLOTS)) + put_bits(log, offset-(1<(windowSize-NUM_SLOTS) ? get_bits(log)+(1<(windowSize-NUM_SLOTS) ? get_bits(log)+(1<= 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); + +} -- cgit v1.2.3