1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2 
3 /*
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (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 
19  /*
20  * LZHUF.C English version 1.0
21  * Based on Japanese version 29-NOV-1988
22  * LZSS coded by Haruhiko OKUMURA
23  * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
24  * Edited and translated to English by Kenji RIKITAKE
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include "lzh.h"
32 #include "libs/reslib.h"
33 
34 PLZHCODE_DESC _lpCurCodeDesc;
35 STREAM_TYPE _StreamType;
36 BYTE* _Stream;
37 UWORD _workbuf;
38 BYTE _workbuflen;
39 
40 /* get one bit */
41 static SWORD
GetBit(void)42 GetBit (void)
43 {
44 	SWORD i;
45 
46 	while (_workbuflen <= 8)
47 	{
48 		if ((i = InChar ()) < 0)
49 			i = 0;
50 		_workbuf |= i << (8 - _workbuflen);
51 		_workbuflen += 8;
52 	}
53 	i = (_workbuf & 0xFFFF) >> (16 - 1);
54 	_workbuf = (_workbuf << 1) & 0xFFFF;
55 	_workbuflen--;
56 
57 	return (i);
58 }
59 
60 static UWORD
GetBits(BYTE num_bits)61 GetBits (BYTE num_bits)
62 {
63 	SWORD i;
64 
65 	while (_workbuflen <= 8)
66 	{
67 		if ((i = InChar ()) < 0)
68 			i = 0;
69 		_workbuf |= i << (8 - _workbuflen);
70 		_workbuflen += 8;
71 	}
72 	i = (_workbuf & 0xFFFF) >> (16 - num_bits);
73 	_workbuf = (_workbuf << num_bits) & 0xFFFF;
74 	_workbuflen -= num_bits;
75 
76 	return (i);
77 }
78 
79 /* initialize freq tree */
80 
81 void
StartHuff(void)82 StartHuff (void)
83 {
84 	COUNT i, j;
85 
86 	for (i = 0; i < N_CHAR; i++)
87 	{
88 		_lpCurCodeDesc->freq[i] = 1;
89 		_lpCurCodeDesc->son[i] = i + T;
90 		_lpCurCodeDesc->prnt[i + T] = i;
91 	}
92 	i = 0; j = N_CHAR;
93 	while (j <= R)
94 	{
95 		_lpCurCodeDesc->freq[j] = _lpCurCodeDesc->freq[i] + _lpCurCodeDesc->freq[i + 1];
96 		_lpCurCodeDesc->son[j] = i;
97 		_lpCurCodeDesc->prnt[i] = _lpCurCodeDesc->prnt[i + 1] = j;
98 		i += 2; j++;
99 	}
100 	_lpCurCodeDesc->freq[T] = 0xffff;
101 	_lpCurCodeDesc->prnt[R] = 0;
102 }
103 
104 DECODE_REF
copen(void * InStream,STREAM_TYPE SType,STREAM_MODE SMode)105 copen (void *InStream, STREAM_TYPE SType, STREAM_MODE SMode)
106 {
107 	DWORD StreamLength;
108 
109 	_StreamType = SType;
110 	_Stream = InStream;
111 	if (SMode == STREAM_WRITE) /* writing */
112 	{
113 		OutChar (0); /* skip future StreamLength */
114 		OutChar (0);
115 		OutChar (0);
116 		OutChar (0);
117 
118 		StreamLength = 0;
119 	}
120 	else /* reading */
121 	{
122 		BYTE lobyte, hibyte;
123 		UWORD loword, hiword;
124 
125 		lobyte = (BYTE)InChar ();
126 		hibyte = (BYTE)InChar ();
127 		loword = MAKE_WORD (lobyte, hibyte);
128 		lobyte = (BYTE)InChar ();
129 		hibyte = (BYTE)InChar ();
130 		hiword = MAKE_WORD (lobyte, hibyte);
131 
132 		StreamLength = MAKE_DWORD (loword, hiword);
133 	}
134 
135 	if (StreamLength == 0xFFFFFFFF
136 			|| (_lpCurCodeDesc = AllocCodeDesc ()) == NULL)
137 	{
138 		FreeCodeDesc (_lpCurCodeDesc);
139 		_lpCurCodeDesc = NULL;
140 	}
141 	else
142 	{
143 		_lpCurCodeDesc->Stream = _Stream;
144 		_lpCurCodeDesc->StreamType = _StreamType;
145 		_lpCurCodeDesc->StreamMode = SMode;
146 		_lpCurCodeDesc->StreamLength = StreamLength;
147 		_lpCurCodeDesc->buf_index = N - F;
148 		memset (&_lpCurCodeDesc->text_buf[0], ' ', N - F);
149 
150 		StartHuff ();
151 	}
152 
153 	return ((DECODE_REF)_lpCurCodeDesc);
154 }
155 
156 DWORD
cclose(PLZHCODE_DESC lpCodeDesc)157 cclose (PLZHCODE_DESC lpCodeDesc)
158 {
159 	_lpCurCodeDesc = lpCodeDesc;
160 	if (_lpCurCodeDesc)
161 	{
162 		DWORD StreamIndex;
163 
164 		if (_lpCurCodeDesc->CleanupFunc)
165 			(*_lpCurCodeDesc->CleanupFunc) ();
166 
167 		StreamIndex = lpCodeDesc->StreamIndex;
168 		FreeCodeDesc (lpCodeDesc);
169 		_lpCurCodeDesc = NULL;
170 
171 		return (StreamIndex);
172 	}
173 
174 	return (0);
175 }
176 
177 void
cfilelength(PLZHCODE_DESC lpCodeDesc,DWORD * pfilelen)178 cfilelength (PLZHCODE_DESC lpCodeDesc, DWORD *pfilelen)
179 {
180 	if (lpCodeDesc == 0)
181 		*pfilelen = 0;
182 	else
183 		*pfilelen = lpCodeDesc->StreamLength;
184 }
185 
186 		/* decoder table */
187 static const BYTE d_code[256] =
188 {
189 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
194 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
195 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
196 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
197 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
198 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
199 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
200 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
201 	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
202 	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
203 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
204 	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
205 	0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
206 	0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
207 	0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
208 	0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
209 	0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
210 	0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
211 	0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
212 	0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
213 	0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
214 	0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
215 	0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
216 	0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
217 	0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
218 	0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
219 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
220 	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
221 };
222 static const BYTE d_len[256] =
223 {
224 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
225 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
226 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
227 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
228 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
229 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
230 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
231 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
232 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
233 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
234 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
235 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
236 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
237 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
238 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
239 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
240 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
241 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
242 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
243 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
244 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
245 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
246 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
247 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
248 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
249 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
250 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
251 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
252 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
253 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
254 	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
255 	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
256 };
257 
258 	/* decode upper 6 bits from given table */
259 #define DecodePosition(p) \
260 { \
261 	while (_workbuflen <= 8) \
262 	{ \
263 		*(p) = InChar (); \
264 		_workbuf |= *(p) << (8 - _workbuflen); \
265 		_workbuflen += 8; \
266 	} \
267 	*(p) = HIBYTE (_workbuf); \
268 	_workbuf = (_workbuf << 8) & 0xFFFF; \
269 	_workbuflen -= 8; \
270 	\
271 	/* input lower 6 bits directly */ \
272 	j = d_len[*(p)]; \
273 	*(p) = ((UWORD)d_code[*(p)] << 6) \
274 			| (((*(p) << j) | GetBits (j)) & 0x3f); \
275 }
276 
277 	/* start searching tree from the root to leaves.
278 	 * choose node #(son[]) if input bit == 0
279 	 * else choose #(son[]+1) (input bit == 1)
280 	 */
281 #define DecodeChar(c) \
282 { \
283 	for (*(c) = lpCodeDesc->son[R]; \
284 			*(c) < T; \
285 			*(c) = lpCodeDesc->son[*(c) + GetBit ()]) \
286 		; \
287 	_update (*(c)); \
288 	*(c) -= T; \
289 }
290 
291 COUNT
cread(void * buf,COUNT size,COUNT count,PLZHCODE_DESC lpCodeDesc)292 cread (void *buf, COUNT size, COUNT count, PLZHCODE_DESC lpCodeDesc)
293 {
294 	COUNT r, j, i;
295 	BYTE *lpStr;
296 
297 	if ((_lpCurCodeDesc = lpCodeDesc) == 0)
298 		return (0);
299 
300 	size *= count;
301 	if (lpCodeDesc->StreamIndex + size > lpCodeDesc->StreamLength)
302 	{
303 		size /= count;
304 		count = (COUNT)((lpCodeDesc->StreamLength
305 				- lpCodeDesc->StreamIndex) / size);
306 
307 		size *= count;
308 	}
309 
310 	if (size == 0)
311 		return (0);
312 
313 	lpStr = (BYTE*)buf;
314 	_StreamType = lpCodeDesc->StreamType;
315 
316 	_Stream = lpCodeDesc->Stream;
317 	_workbuf = lpCodeDesc->workbuf;
318 	_workbuflen = lpCodeDesc->workbuflen;
319 
320 	lpCodeDesc->StreamIndex += size;
321 	r = lpCodeDesc->buf_index;
322 	j = lpCodeDesc->bytes_left;
323 	if (j)
324 	{
325 		lpCodeDesc->bytes_left = 0;
326 		i = lpCodeDesc->restart_index;
327 
328 		goto ReenterRun;
329 	}
330 
331 	do
332 	{
333 		COUNT c;
334 
335 		DecodeChar (&c);
336 
337 		if (c < 256)
338 		{
339 			size--;
340 
341 			*lpStr++ = lpCodeDesc->text_buf[r++ & (N - 1)] = (BYTE)c;
342 		}
343 		else
344 		{
345 			COUNT copy_size;
346 
347 			//i is a COUNT;
348 				DecodePosition(&i);
349 			i = r - i - 1;
350 			j = c - 255 + THRESHOLD;
351 ReenterRun:
352 			if (j > size)
353 			{
354 				lpCodeDesc->bytes_left = j - size;
355 				lpCodeDesc->restart_index = i + size;
356 				j = size;
357 			}
358 
359 			size -= j;
360 			do
361 			{
362 				COUNT loc_size;
363 
364 				i &= (N - 1);
365 				r &= (N - 1);
366 				if ((i < r && i + j > r) || (i > r && i + j > r + N))
367 					copy_size = (r - i) & (N - 1);
368 				else if ((copy_size = j) > N)
369 					copy_size = N;
370 
371 				loc_size = copy_size;
372 				if (i + loc_size > N)
373 				{
374 					COUNT k;
375 
376 					k = N - i;
377 					memcpy (lpStr, &lpCodeDesc->text_buf[i], k);
378 					lpStr += k;
379 					loc_size -= k;
380 					i = 0;
381 				}
382 
383 				memcpy (lpStr, &lpCodeDesc->text_buf[i], loc_size);
384 				lpStr += loc_size;
385 				i += loc_size;
386 
387 				lpStr -= copy_size;
388 
389 				loc_size = copy_size;
390 				if (r + loc_size > N)
391 				{
392 					COUNT k;
393 
394 					k = N - r;
395 					memcpy (&lpCodeDesc->text_buf[r], lpStr, k);
396 					lpStr += k;
397 					loc_size -= k;
398 					r = 0;
399 				}
400 
401 				memcpy (&lpCodeDesc->text_buf[r], lpStr, loc_size);
402 				lpStr += loc_size;
403 				r += loc_size;
404 			} while (j -= copy_size);
405 		}
406 	} while (size);
407 
408 	lpCodeDesc->buf_index = r;
409 	lpCodeDesc->Stream = _Stream;
410 	lpCodeDesc->workbuf = _workbuf;
411 	lpCodeDesc->workbuflen = _workbuflen;
412 
413 	return (count);
414 }
415 
416