/* Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant 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 General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "q3data.h" #if 0 /* ================== MTF ================== */ cblock_t MTF (cblock_t in) { int i, j, b, code; byte *out_p; int index[256]; cblock_t out; out_p = out.data = malloc(in.count + 4); // write count *out_p++ = in.count&255; *out_p++ = (in.count>>8)&255; *out_p++ = (in.count>>16)&255; *out_p++ = (in.count>>24)&255; for (i=0 ; i<256 ; i++) index[i] = i; for (i=0 ; i b2) return 1; if (++i1 == bwt_size) i1 = 0; if (++i2 == bwt_size) i2 = 0; } return 0; } /* ================== BWT ================== */ cblock_t BWT (cblock_t in) { int *sorted; int i; byte *out_p; cblock_t out; bwt_size = in.count; bwt_data = in.data; sorted = malloc(in.count*sizeof(*sorted)); for (i=0 ; i>8)&255; *out_p++ = (in.count>>16)&255; *out_p++ = (in.count>>24)&255; // write head index for (i=0 ; i>8)&255; *out_p++ = (i>>16)&255; *out_p++ = (i>>24)&255; // write the L column for (i=0 ; i 32) Error ("bitcount > 32"); charbits[nodenum] = bits; charbitscount[nodenum] = bitcount; return; } node = &hnodes[nodenum]; bits <<= 1; BuildChars (node->children[0], bits, bitcount+1); bits |= 1; BuildChars (node->children[1], bits, bitcount+1); } /* ================== Huffman ================== */ cblock_t Huffman (cblock_t in) { int i; hnode_t *node; int outbits, c; unsigned bits; byte *out_p; cblock_t out; int max, maxchar; // count memset (hnodes, 0, sizeof(hnodes)); for (i=0 ; i max) { max = hnodes[i].count; maxchar = i; } } if (max == 0) Error ("Huffman: max == 0"); for (i=0 ; i<256 ; i++) { hnodes[i].count = (hnodes[i].count*255+max-1) / max; } // build the nodes numhnodes = 256; while (numhnodes != 511) { node = &hnodes[numhnodes]; // pick two lowest counts node->children[0] = SmallestNode (); if (node->children[0] == -1) break; // no more node->children[1] = SmallestNode (); if (node->children[1] == -1) { if (node->children[0] != numhnodes-1) Error ("Bad smallestnode"); break; } node->count = hnodes[node->children[0]].count + hnodes[node->children[1]].count; numhnodes++; } BuildChars (numhnodes-1, 0, 0); out_p = out.data = malloc(in.count*2 + 1024); memset (out_p, 0, in.count*2+1024); // write count *out_p++ = in.count&255; *out_p++ = (in.count>>8)&255; *out_p++ = (in.count>>16)&255; *out_p++ = (in.count>>24)&255; // save out the 256 normalized counts so the tree can be recreated for (i=0 ; i<256 ; i++) *out_p++ = hnodes[i].count; // write bits outbits = 0; for (i=0 ; i>3] |= 1<<(outbits&7); outbits++; } } out_p += (outbits+7)>>3; out.count = out_p - out.data; return out; } //========================================================================== /* ================== RLE ================== */ #define RLE_CODE 0xe8 #define RLE_TRIPPLE 0xe9 int rle_counts[256]; int rle_bytes[256]; cblock_t RLE (cblock_t in) { int i; byte *out_p; int val; int repeat; cblock_t out; out_p = out.data = malloc (in.count*2); // write count *out_p++ = in.count&255; *out_p++ = (in.count>>8)&255; *out_p++ = (in.count>>16)&255; *out_p++ = (in.count>>24)&255; for (i=0 ; i 3 || val == RLE_CODE) { *out_p++ = RLE_CODE; *out_p++ = val; *out_p++ = repeat; } else { while (repeat--) *out_p++ = val; } } out.count = out_p - out.data; return out; } //========================================================================== unsigned lzss_head[256]; unsigned lzss_next[0x20000]; /* ================== LZSS ================== */ #define BACK_WINDOW 0x10000 #define BACK_BITS 16 #define FRONT_WINDOW 16 #define FRONT_BITS 4 cblock_t LZSS (cblock_t in) { int i; byte *out_p; cblock_t out; int val; int j, start, max; int bestlength, beststart; int outbits; if (in.count >= sizeof(lzss_next)/4) Error ("LZSS: too big"); memset (lzss_head, -1, sizeof(lzss_head)); out_p = out.data = malloc (in.count*2); memset (out.data, 0, in.count*2); // write count *out_p++ = in.count&255; *out_p++ = (in.count>>8)&255; *out_p++ = (in.count>>16)&255; *out_p++ = (in.count>>24)&255; outbits = 0; for (i=0 ; i in.count) max = in.count - i; start = lzss_head[val]; while (start != -1 && start >= i-BACK_WINDOW) { // count match length for (j=0 ; j bestlength) { bestlength = j; beststart = start; } start = lzss_next[start]; } #else // slow simple search // search for a match max = FRONT_WINDOW; if (i + max > in.count) max = in.count - i; start = i - BACK_WINDOW; if (start < 0) start = 0; bestlength = 0; beststart = 0; for ( ; start < i ; start++) { if (in.data[start] != val) continue; // count match length for (j=0 ; j bestlength) { bestlength = j; beststart = start; } } #endif beststart = BACK_WINDOW - (i-beststart); if (bestlength < 3) { // output a single char bestlength = 1; out_p[outbits>>3] |= 1<<(outbits&7); // set bit to mark char outbits++; for (j=0 ; j<8 ; j++, outbits++) if (val & (1<>3] |= 1<<(outbits&7); } else { // output a phrase outbits++; // leave a 0 bit to mark phrase for (j=0 ; j>3] |= 1<<(outbits&7); for (j=0 ; j>3] |= 1<<(outbits&7); } while (bestlength--) { val = in.data[i]; lzss_next[i] = lzss_head[val]; lzss_head[val] = i; i++; } } out_p += (outbits+7)>>3; out.count = out_p - out.data; return out; } //========================================================================== #define MIN_REPT 15 #define MAX_REPT 0 #define HUF_TOKENS (256+MAX_REPT) unsigned charbits1[256][HUF_TOKENS]; int charbitscount1[256][HUF_TOKENS]; hnode_t hnodes1[256][HUF_TOKENS*2]; int numhnodes1[256]; int order0counts[256]; /* ================== SmallestNode1 ================== */ int SmallestNode1 (hnode_t *hnodes, int numhnodes) { int i; int best, bestnode; best = 99999999; bestnode = -1; for (i=0 ; i 32) Error ("bitcount > 32"); charbits1[prev][nodenum] = bits; charbitscount1[prev][nodenum] = bitcount; return; } node = &hnodes1[prev][nodenum]; bits <<= 1; BuildChars1 (prev, node->children[0], bits, bitcount+1); bits |= 1; BuildChars1 (prev, node->children[1], bits, bitcount+1); } /* ================== BuildTree1 ================== */ void BuildTree1 (int prev) { hnode_t *node, *nodebase; int numhnodes; // build the nodes numhnodes = HUF_TOKENS; nodebase = hnodes1[prev]; while (1) { node = &nodebase[numhnodes]; // pick two lowest counts node->children[0] = SmallestNode1 (nodebase, numhnodes); if (node->children[0] == -1) break; // no more node->children[1] = SmallestNode1 (nodebase, numhnodes); if (node->children[1] == -1) break; node->count = nodebase[node->children[0]].count + nodebase[node->children[1]].count; numhnodes++; } numhnodes1[prev] = numhnodes-1; BuildChars1 (prev, numhnodes-1, 0, 0); } /* ================== Huffman1_Count ================== */ void Huffman1_Count (cblock_t in) { int i; int prev; int v; int rept; prev = 0; for (i=0 ; i MIN_REPT) { hnodes1[prev][255+rept].count++; i += rept-1; } #endif } } /* ================== Huffman1_Build ================== */ byte scaled[256][HUF_TOKENS]; void Huffman1_Build (FILE *f) { int i, j, v; int max; int total; for (i=0 ; i<256 ; i++) { // normalize and save the counts max = 0; for (j=0 ; j max) max = hnodes1[i][j].count; } if (max == 0) max = 1; total = 0; for (j=0 ; j 255) Error ("v > 255"); scaled[i][j] = hnodes1[i][j].count = v; if (v) total++; } if (total == 1) { // must have two tokens if (!scaled[i][0]) scaled[i][0] = hnodes1[i][0].count = 1; else scaled[i][1] = hnodes1[i][1].count = 1; } BuildTree1 (i); } #if 0 // count up the total bits total = 0; for (i=0 ; i<256 ; i++) for (j=0 ; j<256 ; j++) total += charbitscount1[i][j] * hnodes1[i][j].count; total = (total+7)/8; printf ("%i bytes huffman1 compressed\n", total); #endif fwrite (scaled, 1, sizeof(scaled), f); } /* ================== Huffman1 Order 1 compression with pre-built table ================== */ cblock_t Huffman1 (cblock_t in) { int i; int outbits, c; unsigned bits; byte *out_p; cblock_t out; int prev; int v; int rept; out_p = out.data = malloc(in.count*2 + 1024); memset (out_p, 0, in.count*2+1024); // write count *out_p++ = in.count&255; *out_p++ = (in.count>>8)&255; *out_p++ = (in.count>>16)&255; *out_p++ = (in.count>>24)&255; // write bits outbits = 0; prev = 0; for (i=0 ; i>3] |= 1<<(outbits&7); outbits++; } prev = v; #if 1 // check for repeat encodes for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++) if (in.data[i+rept] != v) break; if (rept > MIN_REPT) { c = charbitscount1[prev][255+rept]; bits = charbits1[prev][255+rept]; if (!c) Error ("!bits"); while (c) { c--; if (bits & (1<>3] |= 1<<(outbits&7); outbits++; } i += rept-1; } #endif } out_p += (outbits+7)>>3; out.count = out_p - out.data; return out; } #endif