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