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