Subversion Repositories pentevo

Rev

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