1 /*
2 * Copyright (C) 2001, 2002, and 2003 Roy Keene
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * email: dact@rkeene.org
19 */
20
21
22 /*
23 Compress by gathering bytes that are most often placed near each other
24 and rearranging the ASCII Charectar Set to make those bytes have
25 similar values.
26
27 */
28
29
30 #include "dact.h"
31 #include "comp_mzlib2.h"
32 #ifndef comp_mzlib2_algo
33
34 #ifdef HAVE_LIBZ
35 #ifdef HAVE_ZLIB_H
36 #include <zlib.h>
37 #endif
38 #include <stdio.h>
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #ifdef HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45 #ifdef HAVE_STRING_H
46 #include <string.h>
47 #endif
48 #include "sort.h"
49 #define SQRD_256 65536
50
51
52 /*
53 mode - DACT_MODE_COMPR or DACT_MODE_DECMP
54 Determine whether to compress or decompress.
55 prev_block - Previous (uncompressed) block.
56 curr_block - The data to be compressed.
57 out_block - Where to put data after compression.
58 blk_size - Size of prev_block and curr_block.
59 */
60 #if defined(USE_MODULES) && defined(AS_MODULE)
61 #include "module.h"
62 uint32_t DC_NUM=8;
63 uint32_t DC_TYPE=DACT_MOD_TYPE_COMP;
64 void *DC_ALGO=comp_mzlib2_algo;
65 char *DC_NAME="Second Modified Zlib Compression (MOD)";
66 #endif
67
68 #ifdef DEBUG
69 #if DEBUG>=2
70 #define MAKE_MZLIB2 1
71 #endif
72 #endif
73
74 #ifdef MAKE_MZLIB2
comp_mzlib2_algo(int mode,unsigned char * prev_block,unsigned char * curr_block,unsigned char * out_block,int blk_size,int bufsize)75 int comp_mzlib2_algo(int mode, unsigned char *prev_block, unsigned char *curr_block, unsigned char *out_block, int blk_size, int bufsize) {
76 switch(mode) {
77 case DACT_MODE_COMPR:
78 return(comp_mzlib2_compress(prev_block, curr_block, out_block, blk_size, bufsize));
79 break; /* Heh */
80 case DACT_MODE_DECMP:
81 return(comp_mzlib2_decompress(prev_block, curr_block, out_block, blk_size, bufsize));
82 break;
83 default:
84 printf("Unsupported mode: %i\n", mode);
85 return(-1);
86 }
87 }
88 #else
comp_mzlib2_algo(int mode,unsigned char * prev_block,unsigned char * curr_block,unsigned char * out_block,int blk_size,int bufsize)89 int comp_mzlib2_algo(int mode, unsigned char *prev_block, unsigned char *curr_block, unsigned char *out_block, int blk_size, int bufsize) {
90 return(-1);
91 }
92 #endif
93
comp_mzlib2_compress(unsigned char * prev_block,unsigned char * curr_block,unsigned char * out_block,int blk_size,int bufsize)94 int comp_mzlib2_compress(unsigned char *prev_block, unsigned char *curr_block, unsigned char *out_block, int blk_size, int bufsize) {
95 unsigned long dest_size;
96 unsigned char *tmp_block;
97 uint32_t freq[SQRD_256];
98 uint16_t lookup_table[SQRD_256], curr_val, repl_val;
99 int i, cnt, m=2, retval, low_byte=0, x;
100
101 memset(freq,0,sizeof(freq));
102
103 for (i=0;i<blk_size;i+=2) {
104 x=(curr_block[i]<<8)|(curr_block[i+1]);
105 freq[x]++;
106 if (freq[x]==0xffff) return(-1);
107 }
108
109
110 int_sort_fast(freq, SQRD_256, 0);
111
112 for (i=0;i<(SQRD_256);i++) {
113 if ((freq[i]&0xffff)!=0) {
114 out_block[m++]=freq[i]>>24;
115 out_block[m++]=(freq[i]>>16)&0xff;
116 if (m>=(blk_size*2)) {
117 return(-1);
118 }
119 lookup_table[freq[i]>>16]=i;
120 PRINT_LINE; fprintf(stderr, "%04x: 0x%02x and 0x%02x are near each other %i times\n",i,(freq[i]>>24),(freq[i]>>16)&0xff,freq[i]&0xffff);
121 } else {
122 break;
123 }
124 }
125
126 cnt=(m-2);
127 out_block[0]=((m-2)>>8);
128 out_block[1]=((m-2)&0xff);
129 if ((m-2)<0x200) low_byte=1;
130
131 for (i=0;i<blk_size;i+=2) {
132 curr_val=((curr_block[i]<<8)| curr_block[i+1]);
133 repl_val=lookup_table[curr_val];
134 if (!low_byte)
135 out_block[m++]=repl_val>>8;
136 out_block[m++]=repl_val&0xff;
137 SPOTVAR_NUM(m);
138 if (m>=(blk_size*2)) return(-1);
139 }
140
141 dest_size=(int) ((float) ((m*1.02)+15));
142 SPOTVAR_NUM(dest_size);
143 if ((tmp_block=malloc(dest_size))==NULL) {
144 return(-1);
145 }
146 memcpy(tmp_block,out_block,m);
147 /*
148 for (i=0;i<m;i++) {
149 printf("%02x ", tmp_block[i]);
150 if (i==(cnt+2)) printf("-- ");
151 if (((i+1)%25)==0) printf("\n");
152 }
153 printf("\n\n");
154 */
155
156 /*
157 for (i=0;i<blk_size;i++) printf("%02x ", curr_block[i]);
158 printf("\n");
159 */
160
161 retval=compress(out_block, &dest_size, tmp_block, m);
162 if (retval!=Z_OK) {
163 return(blk_size*2);
164 }
165
166 free(tmp_block);
167 return(dest_size);
168 }
169
comp_mzlib2_decompress(unsigned char * prev_block,unsigned char * curr_block,unsigned char * out_block,int blk_size,int bufsize)170 int comp_mzlib2_decompress(unsigned char *prev_block, unsigned char *curr_block, unsigned char *out_block, int blk_size, int bufsize) {
171 uint16_t lookup_table[SQRD_256], curr_val, repl_val;
172 unsigned long dest_size=(blk_size*2);
173 unsigned char *tmp_block;
174 unsigned int m=0, hdrsize;
175 int retval, i, low_byte=0;
176
177 tmp_block=malloc(dest_size);
178 retval=uncompress(tmp_block,&dest_size,curr_block,blk_size);
179
180 if (retval!=Z_OK) return(0);
181
182 hdrsize=((unsigned int) (((tmp_block[0]<<8)|tmp_block[1])))+2;
183
184 if ((hdrsize-2)<0x200) low_byte=1;
185
186 for (i=2;i<hdrsize;i+=2) {
187 lookup_table[(i-2)/2]=((tmp_block[i]<<8)|tmp_block[i+1]);
188 }
189
190 for (i=hdrsize;i<(dest_size);i+=(2-low_byte)) {
191 if (low_byte) {
192 curr_val=tmp_block[i];
193 } else {
194 curr_val=((tmp_block[i]<<8)|tmp_block[i+1]);
195 }
196 repl_val=lookup_table[curr_val];
197 out_block[m++]=repl_val>>8;
198 out_block[m++]=repl_val&0xff;
199 }
200
201 /*
202 for (i=0;i<m;i++) printf("%02x ", out_block[i]);
203 printf("\n");
204 */
205
206 free(tmp_block);
207 return(m);
208 }
209 #endif
210
211 #endif
212