Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #include "std.h" |
2 | |||
3 | #include "emul.h" |
||
4 | #include "vars.h" |
||
5 | #include "wd93crc.h" |
||
6 | |||
7 | #include "util.h" |
||
8 | |||
9 | int FDD::write_td0(FILE *ff) |
||
10 | { |
||
11 | unsigned char zerosec[256] = { 0 }; |
||
12 | unsigned char td0hdr[12] = { 0 }; |
||
13 | |||
14 | *(unsigned short*)td0hdr = WORD2('T','D'); |
||
15 | td0hdr[4] = 21; td0hdr[6] = 2; td0hdr[9] = (unsigned char)sides; |
||
16 | if (*dsc) td0hdr[7] = 0x80; |
||
17 | *(unsigned short*)(td0hdr + 10) = crc16(td0hdr, 10); |
||
18 | fwrite(td0hdr, 1, 12, ff); |
||
19 | if (*dsc) { |
||
20 | unsigned char inf[0x200] = { 0 }; |
||
21 | strcpy((char*)inf+10, dsc); |
||
22 | unsigned len = strlen(dsc)+1; |
||
23 | *(unsigned*)(inf+2) = len; |
||
24 | *(unsigned short*)inf = crc16(inf+2, len+8); |
||
25 | fwrite(inf, 1, len+10, ff); |
||
26 | } |
||
27 | |||
28 | unsigned c; //Alone Coder 0.36.7 |
||
29 | for (/*unsigned*/ c = 0; c < cyls; c++) |
||
30 | for (unsigned s = 0; s < sides; s++) { |
||
31 | t.seek(this,c,s,LOAD_SECTORS); |
||
32 | unsigned char bf[16]; |
||
33 | *bf = t.s; |
||
34 | bf[1] = c, bf[2] = s; |
||
35 | bf[3] = (unsigned char)crc16(bf, 3); |
||
36 | fwrite(bf, 1, 4, ff); |
||
37 | for (unsigned sec = 0; sec < t.s; sec++) { |
||
38 | if (!t.hdr[sec].data) { t.hdr[sec].data = zerosec, t.hdr[sec].datlen = 256, t.hdr[sec].l = 1; } |
||
39 | *(unsigned*)bf = *(unsigned*)&t.hdr[sec]; |
||
40 | bf[4] = 0; // flags |
||
41 | bf[5] = (unsigned char)crc16(t.hdr[sec].data, t.hdr[sec].datlen); |
||
42 | *(unsigned short*)(bf+6) = t.hdr[sec].datlen + 1; |
||
43 | bf[8] = 0; // compression type = none |
||
44 | fwrite(bf, 1, 9, ff); |
||
45 | if (fwrite(t.hdr[sec].data, 1, t.hdr[sec].datlen, ff) != t.hdr[sec].datlen) return 0; |
||
46 | } |
||
47 | } |
||
48 | c = WORD4(0xFF,0,0,0); |
||
49 | if (fwrite(&c, 1, 4, ff) != 4) return 0; |
||
50 | return 1; |
||
51 | } |
||
52 | |||
53 | |||
54 | unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf); |
||
55 | |||
56 | // No ID address field was present for this sector, |
||
57 | // but there is a data field. The sector information in |
||
58 | // the header represents fabricated information. |
||
59 | const ULONG TD0_SEC_NO_ID = 0x40; |
||
60 | |||
61 | // This sector's data field is missing; no sector data follows this header. |
||
62 | const ULONG TD0_SEC_NO_DATA = 0x20; |
||
63 | |||
64 | // A DOS sector copy was requested; this sector was not allocated. |
||
65 | // In this case, no sector data follows this header. |
||
66 | const ULONG TD0_SEC_NO_DATA2 = 0x10; |
||
67 | |||
68 | #pragma pack(push, 1) |
||
69 | struct TTd0Sec |
||
70 | { |
||
71 | u8 c; |
||
72 | u8 h; |
||
73 | u8 s; |
||
74 | u8 n; |
||
75 | u8 flags; |
||
76 | u8 crc; |
||
77 | }; |
||
78 | #pragma pack(pop) |
||
79 | |||
80 | int FDD::read_td0() |
||
81 | { |
||
82 | if (*(short*)snbuf == WORD2('t','d')) |
||
83 | { // packed disk |
||
84 | unsigned char *tmp = (unsigned char*)malloc(snapsize); |
||
85 | memcpy(tmp, snbuf+12, snapsize-12); |
||
86 | snapsize = 12+unpack_lzh(tmp, snapsize-12, snbuf+12); |
||
87 | ::free(tmp); |
||
88 | //*(short*)snbuf = WORD2('T','D'); |
||
89 | } |
||
90 | |||
91 | char dscbuffer[sizeof(dsc)]; |
||
92 | *dscbuffer = 0; |
||
93 | |||
94 | unsigned char *start = snbuf+12; |
||
95 | if (snbuf[7] & 0x80) // coment record |
||
96 | { |
||
97 | start += 10; |
||
98 | unsigned len = *(unsigned short*)(snbuf+14); |
||
99 | start += len; |
||
100 | if (len >= sizeof dsc) |
||
101 | len = sizeof(dsc)-1; |
||
102 | memcpy(dscbuffer, snbuf+12+10, len); |
||
103 | dscbuffer[len] = 0; |
||
104 | } |
||
105 | unsigned char *td0_src = start; |
||
106 | |||
107 | unsigned sides = (snbuf[9] == 1 ? 1 : 2); |
||
108 | unsigned max_cyl = 0; |
||
109 | |||
110 | for (;;) |
||
111 | { |
||
112 | unsigned char s = *td0_src; // Sectors |
||
113 | if (s == 0xFF) |
||
114 | break; |
||
115 | max_cyl = max(max_cyl, unsigned(td0_src[1])); // PhysTrack |
||
116 | td0_src += 4; // sizeof(track_rec) |
||
117 | for (; s; s--) |
||
118 | { |
||
119 | unsigned char flags = td0_src[4]; |
||
120 | td0_src += 6; // sizeof(sec_rec) |
||
121 | |||
122 | assert(td0_src <= snbuf + snapsize); |
||
123 | |||
124 | if (td0_src > snbuf + snapsize) |
||
125 | return 0; |
||
126 | td0_src += *(unsigned short*)td0_src + 2; // data_len |
||
127 | } |
||
128 | } |
||
129 | |||
130 | if(max_cyl+1 > MAX_CYLS) |
||
131 | { |
||
132 | err_printf("cylinders (%d) > MAX_CYLS(%d)", max_cyl, MAX_CYLS); |
||
133 | return 0; |
||
134 | } |
||
135 | |||
136 | newdisk(max_cyl+1, sides); |
||
137 | memcpy(dsc, dscbuffer, sizeof dsc); |
||
138 | |||
139 | td0_src = start; |
||
140 | for (;;) |
||
141 | { |
||
142 | unsigned char t0[16384]; |
||
143 | unsigned char *dst = t0; |
||
144 | unsigned char *trkh = td0_src; |
||
145 | td0_src += 4; // sizeof(track_rec) |
||
146 | |||
147 | if(*trkh == 0xFF) |
||
148 | break; |
||
149 | |||
150 | t.seek(this, trkh[1], trkh[2], JUST_SEEK); |
||
151 | |||
152 | unsigned s = 0; |
||
153 | for (unsigned se = 0; se < trkh[0]; se++) |
||
154 | { |
||
155 | TTd0Sec *SecHdr = (TTd0Sec *)td0_src; |
||
156 | unsigned sec_size = 128U << (SecHdr->n & 3); // [vv] |
||
157 | unsigned char flags = SecHdr->flags; |
||
158 | // printf("fl=%x\n", flags); |
||
159 | // printf("c=%d, h=%d, s=%d, n=%d\n", SecHdr->c, SecHdr->h, SecHdr->s, SecHdr->n); |
||
160 | if(flags & (TD0_SEC_NO_ID | TD0_SEC_NO_DATA | TD0_SEC_NO_DATA2)) // skip sectors with no data & sectors without headers |
||
161 | { |
||
162 | td0_src += sizeof(TTd0Sec); // sizeof(sec_rec) |
||
163 | |||
164 | unsigned src_size = *(unsigned short*)td0_src; |
||
165 | // printf("sz=%d\n", src_size); |
||
166 | td0_src += 2; // data_len |
||
167 | unsigned char *end_packed_data = td0_src + src_size; |
||
168 | /* |
||
169 | u8 method = *td0_src++; |
||
170 | printf("m=%d\n", method); |
||
171 | switch(method) |
||
172 | { |
||
173 | case 0: |
||
174 | { |
||
175 | char name[MAX_PATH]; |
||
176 | sprintf(name, "%02d-%d-%03d-%d.trk", SecHdr->c, SecHdr->h, SecHdr->s, SecHdr->n); |
||
177 | FILE *f = fopen(name, "wb"); |
||
178 | fwrite(td0_src, 1, src_size - 1, f); |
||
179 | fclose(f); |
||
180 | break; |
||
181 | } |
||
182 | case 1: |
||
183 | { |
||
184 | unsigned n = *(unsigned short*)td0_src; |
||
185 | td0_src += 2; |
||
186 | unsigned short data = *(unsigned short*)td0_src; |
||
187 | printf("len=%d, data=%04X\n", n, data); |
||
188 | break; |
||
189 | } |
||
190 | } |
||
191 | */ |
||
192 | td0_src = end_packed_data; |
||
193 | continue; |
||
194 | } |
||
195 | |||
196 | // c, h, s, n |
||
197 | t.hdr[s].c = SecHdr->c; |
||
198 | t.hdr[s].s = SecHdr->h; |
||
199 | t.hdr[s].n = SecHdr->s; |
||
200 | t.hdr[s].l = SecHdr->n; |
||
201 | t.hdr[s].c1 = t.hdr[s].c2 = 0; |
||
202 | t.hdr[s].data = dst; |
||
203 | |||
204 | td0_src += sizeof(TTd0Sec); // sizeof(sec_rec) |
||
205 | |||
206 | unsigned src_size = *(unsigned short*)td0_src; |
||
207 | td0_src += 2; // data_len |
||
208 | unsigned char *end_packed_data = td0_src + src_size; |
||
209 | |||
210 | memset(dst, 0, sec_size); |
||
211 | |||
212 | switch (*td0_src++) // Method |
||
213 | { |
||
214 | case 0: // raw sector |
||
215 | memcpy(dst, td0_src, src_size-1); |
||
216 | break; |
||
217 | case 1: // repeated 2-byte pattern |
||
218 | { |
||
219 | unsigned n = *(unsigned short*)td0_src; |
||
220 | td0_src += 2; |
||
221 | unsigned short data = *(unsigned short*)td0_src; |
||
222 | for (unsigned i = 0; i < n; i++) |
||
223 | *(unsigned short*)(dst+2*i) = data; |
||
224 | break; |
||
225 | } |
||
226 | case 2: // RLE block |
||
227 | { |
||
228 | unsigned short data; |
||
229 | unsigned char s; |
||
230 | unsigned char *d0 = dst; |
||
231 | do |
||
232 | { |
||
233 | switch (*td0_src++) |
||
234 | { |
||
235 | case 0: // Zero count means a literal data block |
||
236 | for (s = *td0_src++; s; s--) |
||
237 | *dst++ = *td0_src++; |
||
238 | break; |
||
239 | case 1: // repeated fragment |
||
240 | s = *td0_src++; |
||
241 | data = *(unsigned short*)td0_src; |
||
242 | td0_src += 2; |
||
243 | for ( ; s; s--) |
||
244 | { |
||
245 | *(unsigned short*)dst = data; |
||
246 | dst += 2; |
||
247 | } |
||
248 | break; |
||
249 | default: |
||
250 | errmsg("unknown RLE block type"); |
||
251 | goto shit; |
||
252 | } |
||
253 | } while (td0_src < end_packed_data); |
||
254 | dst = d0; |
||
255 | break; |
||
256 | } |
||
257 | default: // error! |
||
258 | errmsg("unknown block type"); |
||
259 | |||
260 | shit: |
||
261 | errmsg("bad TD0 file"); |
||
262 | return 0; |
||
263 | } |
||
264 | dst += sec_size; |
||
265 | td0_src = end_packed_data; |
||
266 | s++; |
||
267 | } |
||
268 | t.s = s; |
||
269 | t.format(); |
||
270 | } |
||
271 | return 1; |
||
272 | } |
||
273 | |||
274 | // ------------------------------------------------------ LZH unpacker |
||
275 | |||
276 | |||
277 | unsigned char *packed_ptr, *packed_end; |
||
278 | |||
279 | int readChar(void) |
||
280 | { |
||
281 | if (packed_ptr < packed_end) return *packed_ptr++; |
||
282 | else return -1; |
||
283 | } |
||
284 | |||
285 | unsigned char d_code[256] = |
||
286 | { |
||
287 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||
288 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||
289 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||
290 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||
291 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
||
292 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
||
293 | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, |
||
294 | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, |
||
295 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
||
296 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
||
297 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
298 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
299 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
300 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
301 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, |
||
302 | 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, |
||
303 | 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, |
||
304 | 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, |
||
305 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, |
||
306 | 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, |
||
307 | 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, |
||
308 | 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, |
||
309 | 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, |
||
310 | 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, |
||
311 | 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, |
||
312 | 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, |
||
313 | 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, |
||
314 | 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, |
||
315 | 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, |
||
316 | 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, |
||
317 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
||
318 | 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, |
||
319 | }; |
||
320 | |||
321 | unsigned char d_len[256] = |
||
322 | { |
||
323 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
||
324 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
||
325 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
||
326 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, |
||
327 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
328 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
329 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
330 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
331 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
332 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, |
||
333 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
334 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
335 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
336 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
337 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
338 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
339 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
340 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, |
||
341 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
342 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
343 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
344 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
345 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
346 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, |
||
347 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
348 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
349 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
350 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
351 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
352 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, |
||
353 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, |
||
354 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, |
||
355 | }; |
||
356 | |||
357 | |||
358 | const int N = 4096; // buffer size |
||
359 | const int F = 60; // lookahead buffer size |
||
360 | const int THRESHOLD = 2; |
||
361 | const int NIL = N; // leaf of tree |
||
362 | |||
363 | unsigned char text_buf[N + F - 1]; |
||
364 | |||
365 | const int N_CHAR = (256 - THRESHOLD + F); // kinds of characters (character code = 0..N_CHAR-1) |
||
366 | const int T = (N_CHAR * 2 - 1); // size of table |
||
367 | const int R = (T - 1); // position of root |
||
368 | const int MAX_FREQ = 0x8000; // updates tree when the |
||
369 | // root frequency comes to this value. |
||
370 | |||
371 | unsigned short freq[T + 1]; // frequency table |
||
372 | |||
373 | short prnt[T + N_CHAR]; // pointers to parent nodes, except for the |
||
374 | // elements [T..T + N_CHAR - 1] which are used to get |
||
375 | // the positions of leaves corresponding to the codes. |
||
376 | short son[T]; // pointers to child nodes (son[], son[] + 1) |
||
377 | |||
378 | |||
379 | int r; |
||
380 | |||
381 | unsigned getbuf; |
||
382 | unsigned char getlen; |
||
383 | |||
384 | int GetBit(void) /* get one bit */ |
||
385 | { |
||
386 | int i; |
||
387 | |||
388 | while (getlen <= 8) |
||
389 | { |
||
390 | if((i = readChar()) == -1) i = 0; |
||
391 | getbuf |= i << (8 - getlen); |
||
392 | getlen += 8; |
||
393 | } |
||
394 | i = getbuf; |
||
395 | getbuf <<= 1; |
||
396 | getlen--; |
||
397 | return ((i>>15) & 1); |
||
398 | } |
||
399 | |||
400 | int GetByte(void) /* get one byte */ |
||
401 | { |
||
402 | unsigned i; |
||
403 | |||
404 | while (getlen <= 8) |
||
405 | { |
||
406 | if((i = readChar()) == -1) i = 0; |
||
407 | getbuf |= i << (8 - getlen); |
||
408 | getlen += 8; |
||
409 | } |
||
410 | i = getbuf; |
||
411 | getbuf <<= 8; |
||
412 | getlen -= 8; |
||
413 | return (i >> 8) & 0xFF; |
||
414 | } |
||
415 | |||
416 | void StartHuff(void) |
||
417 | { |
||
418 | int i, j; |
||
419 | |||
420 | getbuf = 0, getlen = 0; |
||
421 | for (i = 0; i < N_CHAR; i++) { |
||
422 | freq[i] = 1; |
||
423 | son[i] = i + T; |
||
424 | prnt[i + T] = i; |
||
425 | } |
||
426 | i = 0; j = N_CHAR; |
||
427 | while (j <= R) { |
||
428 | freq[j] = freq[i] + freq[i + 1]; |
||
429 | son[j] = i; |
||
430 | prnt[i] = prnt[i + 1] = j; |
||
431 | i += 2; j++; |
||
432 | } |
||
433 | freq[T] = 0xffff; |
||
434 | prnt[R] = 0; |
||
435 | |||
436 | for (i = 0; i < N - F; i++) text_buf[i] = ' '; |
||
437 | r = N - F; |
||
438 | } |
||
439 | |||
440 | /* reconstruction of tree */ |
||
441 | void reconst(void) |
||
442 | { |
||
443 | int i, j, k; |
||
444 | int f, l; |
||
445 | |||
446 | /* collect leaf nodes in the first half of the table */ |
||
447 | /* and replace the freq by (freq + 1) / 2. */ |
||
448 | j = 0; |
||
449 | for(i = 0; i < T; i++) |
||
450 | { |
||
451 | if(son[i] >= T) |
||
452 | { |
||
453 | freq[j] = (freq[i] + 1) / 2; |
||
454 | son[j] = son[i]; |
||
455 | j++; |
||
456 | } |
||
457 | } |
||
458 | /* begin constructing tree by connecting sons */ |
||
459 | for(i = 0, j = N_CHAR; j < T; i += 2, j++) |
||
460 | { |
||
461 | k = i + 1; |
||
462 | f = freq[j] = freq[i] + freq[k]; |
||
463 | for(k = j - 1; f < freq[k]; k--); |
||
464 | k++; |
||
465 | l = (j - k) * sizeof(*freq); |
||
466 | MoveMemory(&freq[k + 1], &freq[k], l); |
||
467 | freq[k] = f; |
||
468 | MoveMemory(&son[k + 1], &son[k], l); |
||
469 | son[k] = i; |
||
470 | } |
||
471 | /* connect prnt */ |
||
472 | for (i = 0; i < T; i++) |
||
473 | if ((k = son[i]) >= T) prnt[k] = i; |
||
474 | else prnt[k] = prnt[k + 1] = i; |
||
475 | } |
||
476 | |||
477 | |||
478 | /* increment frequency of given code by one, and update tree */ |
||
479 | |||
480 | void update(int c) |
||
481 | { |
||
482 | int i, j, k, l; |
||
483 | |||
484 | if(freq[R] == MAX_FREQ) reconst(); |
||
485 | |||
486 | c = prnt[c + T]; |
||
487 | do { |
||
488 | k = ++freq[c]; |
||
489 | |||
490 | /* if the order is disturbed, exchange nodes */ |
||
491 | if (k > freq[l = c + 1]) |
||
492 | { |
||
493 | while (k > freq[++l]); |
||
494 | l--; |
||
495 | freq[c] = freq[l]; |
||
496 | freq[l] = k; |
||
497 | |||
498 | i = son[c]; |
||
499 | prnt[i] = l; |
||
500 | if (i < T) prnt[i + 1] = l; |
||
501 | |||
502 | j = son[l]; |
||
503 | son[l] = i; |
||
504 | |||
505 | prnt[j] = c; |
||
506 | if (j < T) prnt[j + 1] = c; |
||
507 | son[c] = j; |
||
508 | |||
509 | c = l; |
||
510 | } |
||
511 | } while ((c = prnt[c]) != 0); /* repeat up to root */ |
||
512 | } |
||
513 | |||
514 | int DecodeChar(void) |
||
515 | { |
||
516 | int c; |
||
517 | |||
518 | c = son[R]; |
||
519 | |||
520 | /* travel from root to leaf, */ |
||
521 | /* choosing the smaller child node (son[]) if the read bit is 0, */ |
||
522 | /* the bigger (son[]+1} if 1 */ |
||
523 | while(c < T) c = son[c + GetBit()]; |
||
524 | c -= T; |
||
525 | update(c); |
||
526 | return c; |
||
527 | } |
||
528 | |||
529 | int DecodePosition(void) |
||
530 | { |
||
531 | int i, j, c; |
||
532 | |||
533 | /* recover upper 6 bits from table */ |
||
534 | i = GetByte(); |
||
535 | c = (int)d_code[i] << 6; |
||
536 | j = d_len[i]; |
||
537 | /* read lower 6 bits verbatim */ |
||
538 | j -= 2; |
||
539 | while (j--) i = (i << 1) + GetBit(); |
||
540 | return c | (i & 0x3f); |
||
541 | } |
||
542 | |||
543 | unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf) |
||
544 | { |
||
545 | packed_ptr = src; packed_end = src+size; |
||
546 | int i, j, k, c; |
||
547 | unsigned count = 0; |
||
548 | StartHuff(); |
||
549 | |||
550 | // while (count < textsize) // textsize - sizeof unpacked data |
||
551 | while (packed_ptr < packed_end) |
||
552 | { |
||
553 | c = DecodeChar(); |
||
554 | if(c < 256) |
||
555 | { |
||
556 | *buf++ = c; |
||
557 | text_buf[r++] = c; |
||
558 | r &= (N - 1); |
||
559 | count++; |
||
560 | } else { |
||
561 | i = (r - DecodePosition() - 1) & (N - 1); |
||
562 | j = c - 255 + THRESHOLD; |
||
563 | for (k = 0; k < j; k++) |
||
564 | { |
||
565 | c = text_buf[(i + k) & (N - 1)]; |
||
566 | *buf++ = c; |
||
567 | text_buf[r++] = c; |
||
568 | r &= (N - 1); |
||
569 | count++; |
||
570 | } |
||
571 | } |
||
572 | } |
||
573 | return count; |
||
574 | } |