1
2 /*
3 * xDMS v1.3 - Portable DMS archive unpacker - Public Domain
4 * Written by Andre Rodrigues de la Rocha <adlroc@usa.net>
5 *
6 * Lempel-Ziv-Huffman decompression functions used in Heavy 1 & 2
7 * compression modes. Based on LZH decompression functions from
8 * UNIX LHA made by Masaru Oki
9 *
10 */
11
12
13 #include "cdata.h"
14 #include "u_heavy.h"
15 #include "getbits.h"
16 #include "maketbl.h"
17
18
19 #define NC 510
20 #define NPT 20
21 #define N1 510
22 #define OFFSET 253
23
24 USHORT dms_left[2 * NC - 1], dms_right[2 * NC - 1 + 9];
25 static UCHAR c_len[NC], pt_len[NPT];
26 static USHORT c_table[4096], pt_table[256];
27 USHORT dms_lastlen, dms_np;
28 USHORT dms_heavy_text_loc;
29
30
31 static USHORT read_tree_c(void);
32 static USHORT read_tree_p(void);
33 USHORT decode_c(void);
34 USHORT decode_p(void);
35
36
37
Unpack_HEAVY(UCHAR * in,UCHAR * out,UCHAR flags,USHORT origsize)38 USHORT Unpack_HEAVY(UCHAR *in, UCHAR *out, UCHAR flags, USHORT origsize){
39 USHORT j, i, c, bitmask;
40 UCHAR *outend;
41
42 /* Heavy 1 uses a 4Kb dictionary, Heavy 2 uses 8Kb */
43
44 if (flags & 8) {
45 dms_np = 15;
46 bitmask = 0x1fff;
47 } else {
48 dms_np = 14;
49 bitmask = 0x0fff;
50 }
51
52 initbitbuf(in);
53
54 if (flags & 2) {
55 if (read_tree_c()) return 1;
56 if (read_tree_p()) return 2;
57 }
58
59 outend = out+origsize;
60
61 while (out<outend) {
62 c = decode_c();
63 if (c < 256) {
64 *out++ = dms_text[dms_heavy_text_loc++ & bitmask] = (UCHAR)c;
65 } else {
66 j = (USHORT) (c - OFFSET);
67 i = (USHORT) (dms_heavy_text_loc - decode_p() - 1);
68 while(j--) *out++ = dms_text[dms_heavy_text_loc++ & bitmask] = dms_text[i++ & bitmask];
69 }
70 }
71
72 return 0;
73 }
74
75
76
decode_c(void)77 INLINE USHORT decode_c(void){
78 USHORT i, j, m;
79
80 j = c_table[GETBITS(12)];
81 if (j < N1) {
82 DROPBITS(c_len[j]);
83 } else {
84 DROPBITS(12);
85 i = GETBITS(16);
86 m = 0x8000;
87 do {
88 if (i & m) j = dms_right[j];
89 else j = dms_left [j];
90 m >>= 1;
91 } while (j >= N1);
92 DROPBITS(c_len[j] - 12);
93 }
94 return j;
95 }
96
97
98
decode_p(void)99 INLINE USHORT decode_p(void){
100 USHORT i, j, m;
101
102 j = pt_table[GETBITS(8)];
103 if (j < dms_np) {
104 DROPBITS(pt_len[j]);
105 } else {
106 DROPBITS(8);
107 i = GETBITS(16);
108 m = 0x8000;
109 do {
110 if (i & m) j = dms_right[j];
111 else j = dms_left [j];
112 m >>= 1;
113 } while (j >= dms_np);
114 DROPBITS(pt_len[j] - 8);
115 }
116
117 if (j != dms_np-1) {
118 if (j > 0) {
119 j = (USHORT)(GETBITS(i=(USHORT)(j-1)) | (1U << (j-1)));
120 DROPBITS(i);
121 }
122 dms_lastlen=j;
123 }
124
125 return dms_lastlen;
126
127 }
128
129
130
read_tree_c(void)131 static USHORT read_tree_c(void){
132 USHORT i,n;
133
134 n = GETBITS(9);
135 DROPBITS(9);
136 if (n>0){
137 for (i=0; i<n; i++) {
138 c_len[i] = (UCHAR)GETBITS(5);
139 DROPBITS(5);
140 }
141 for (i=n; i<510; i++) c_len[i] = 0;
142 if (dms_make_table(510,c_len,12,c_table)) return 1;
143 } else {
144 n = GETBITS(9);
145 DROPBITS(9);
146 for (i=0; i<510; i++) c_len[i] = 0;
147 for (i=0; i<4096; i++) c_table[i] = n;
148 }
149 return 0;
150 }
151
152
153
read_tree_p(void)154 static USHORT read_tree_p(void){
155 USHORT i,n;
156
157 n = GETBITS(5);
158 DROPBITS(5);
159 if (n>0){
160 for (i=0; i<n; i++) {
161 pt_len[i] = (UCHAR)GETBITS(4);
162 DROPBITS(4);
163 }
164 for (i=n; i<dms_np; i++) pt_len[i] = 0;
165 if (dms_make_table(dms_np,pt_len,8,pt_table)) return 1;
166 } else {
167 n = GETBITS(5);
168 DROPBITS(5);
169 for (i=0; i<dms_np; i++) pt_len[i] = 0;
170 for (i=0; i<256; i++) pt_table[i] = n;
171 }
172 return 0;
173 }
174
175
176