00001 /* {{{ 00002 * CalcRogue, a roguelike game for PCs, calculators and PDAs 00003 * Copyright (C) 2003 Jim Babcock 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 * }}} */ 00019 // huffman.c 00024 00025 #ifdef TARGET // Compiling CalcRogue (not a tool) 00026 #include "crogue.h" 00027 #endif 00028 00029 #include "hufftable.h" 00030 #include "huffman.h" 00031 #include "substdio.h" 00032 00033 #ifdef DISABLE_COMPRESSION 00034 #define DISABLE_HUFFMAN 00035 #endif 00036 00037 static unsigned long _hp_pending=0; 00038 static unsigned short _hp_pending_length=0; 00039 00040 void fhuffmaninit_write(void) 00041 { 00042 _hp_pending = 0; 00043 _hp_pending_length = 0; 00044 } 00045 00046 void fhuffmanputc(unsigned char c, FILE *f) 00047 { 00048 #ifdef DISABLE_HUFFMAN 00049 fputc(c, f); 00050 #else 00051 00052 _hp_pending_length += huff_compress.replen[c]; 00053 _hp_pending |= (long)huff_compress.rep[c] << (32L - _hp_pending_length); 00054 if(_hp_pending_length >= 16) 00055 fhuffmanflush(f); 00056 #endif 00057 } 00058 00059 void fhuffmanflush(FILE *f) 00060 { 00061 #ifndef DISABLE_HUFFMAN 00062 fputc((char)(_hp_pending>>24L), f); 00063 fputc((char)(_hp_pending>>16L), f); 00064 _hp_pending <<= 16; 00065 if(_hp_pending_length >= 16) 00066 _hp_pending_length -= 16; 00067 else 00068 _hp_pending_length = 0; 00069 #endif 00070 } 00071 00072 static unsigned long _hg_pending=0; 00073 static unsigned short _hg_pending_length=0; 00074 00075 void fhuffmaninit_read(void) 00076 { 00077 _hg_pending = 0; 00078 _hg_pending_length = 0; 00079 } 00080 00081 char fhuffmangetc(FILE *f) 00082 { 00083 #ifdef DISABLE_HUFFMAN 00084 return fgetc(f); 00085 #else 00086 short high, low, mid; 00087 unsigned short searchtarget; 00088 00089 while(_hg_pending_length < 24) 00090 { 00091 _hg_pending <<= 8; 00092 _hg_pending_length += 8; 00093 if(!feof(f)) 00094 _hg_pending |= fgetc(f); 00095 } 00096 searchtarget = _hg_pending >> (_hg_pending_length - 16UL); 00097 low = 0; 00098 high = 255; 00099 00100 do 00101 { 00102 mid = (low+high+1)/2; 00103 if(huff_decompress.entries[mid].binrep > searchtarget) 00104 high = mid-1; 00105 else 00106 low = mid; 00107 } while(high>low); 00108 00109 00110 _hg_pending <<= (32L + huff_decompress.entries[low].binreplen - _hg_pending_length); 00111 _hg_pending_length -= huff_decompress.entries[low].binreplen; 00112 _hg_pending >>= (32L - _hg_pending_length); 00113 00114 return huff_decompress.entries[low].byterep; 00115 #endif 00116 } 00117 00118
1.3.6