Subversion Repositories pentevo

Rev

Rev 798 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  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 = unsigned(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 = u8(t.s);
  34.          bf[1] = u8(c); bf[2] = u8(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)
  39.              {
  40.                  t.hdr[sec].data = zerosec;
  41.                  t.hdr[sec].datlen = 256;
  42.                  t.hdr[sec].l = 1;
  43.              }
  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);
  47.             *(unsigned short*)(bf+6) = u16(t.hdr[sec].datlen + 1);
  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;
  208.          t.hdr[s].datlen = 0;
  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.  
  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.  
  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.             {
  246.                u8 n;
  247.                unsigned char *d0 = dst;
  248.                do
  249.                {
  250.                   u8 RleData[510];
  251.                   u8 l = 2 * (*td0_src++);
  252.                   if(l == 0) // Zero count means a literal data block
  253.                   {
  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;
  264.                   }
  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.                   }
  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.  
  306. static unsigned char *packed_ptr, *packed_end;
  307.  
  308. static unsigned readChar()
  309. {
  310.     if(packed_ptr < packed_end)
  311.     {
  312.         return *packed_ptr++;
  313.     }
  314.     else
  315.     {
  316.         return -1U;
  317.     }
  318. }
  319.  
  320. static unsigned char d_code[256] =
  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.  
  356. static unsigned char d_len[256] =
  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.  
  398. static unsigned char text_buf[N + F - 1];
  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.  
  406. static unsigned short freq[T + 1];        // frequency table
  407.  
  408. static short prnt[T + N_CHAR]; // pointers to parent nodes, except for the
  409.                         // elements [T..T + N_CHAR - 1] which are used to get
  410.                         // the positions of leaves corresponding to the codes.
  411. static short son[T];           // pointers to child nodes (son[], son[] + 1)
  412.  
  413.  
  414. static int r;
  415.  
  416. static unsigned getbuf;
  417. static unsigned char getlen;
  418.  
  419. static int GetBit()      /* get one bit */
  420. {
  421.   unsigned i;
  422.  
  423.   while (getlen <= 8)
  424.   {
  425.       if((i = readChar()) == -1U)
  426.       {
  427.           i = 0;
  428.       }
  429.       getbuf |= unsigned(i << (8 - getlen));
  430.       getlen += 8;
  431.   }
  432.   i = getbuf;
  433.   getbuf <<= 1;
  434.   getlen--;
  435.   return ((i>>15) & 1);
  436. }
  437.  
  438. static int GetByte()     /* get one byte */
  439. {
  440.   unsigned i;
  441.  
  442.   while (getlen <= 8)
  443.   {
  444.       if((i = readChar()) == -1U)
  445.       {
  446.           i = 0;
  447.       }
  448.       getbuf |= unsigned(i << (8 - getlen));
  449.       getlen += 8;
  450.   }
  451.   i = getbuf;
  452.   getbuf <<= 8;
  453.   getlen -= 8;
  454.   return (i >> 8) & 0xFF;
  455. }
  456.  
  457. static void StartHuff()
  458. {
  459.   int i, j;
  460.  
  461.   getbuf = 0; getlen = 0;
  462.   for (i = 0; i < N_CHAR; i++) {
  463.     freq[i] = 1;
  464.     son[i] = i16(i + T);
  465.     prnt[i + T] = i16(i);
  466.   }
  467.   i = 0; j = N_CHAR;
  468.   while (j <= R) {
  469.     freq[j] = freq[i] + freq[i + 1];
  470.     son[j] = i16(i);
  471.     prnt[i] = prnt[i + 1] = i16(j);
  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 */
  482. static void reconst()
  483. {
  484.   int i, j, k;
  485.   int f;
  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++;
  506.     size_t l = unsigned(j - k) * sizeof(*freq);
  507.     MoveMemory(&freq[k + 1], &freq[k], l);
  508.     freq[k] = u16(f);
  509.     MoveMemory(&son[k + 1], &son[k], l);
  510.     son[k] = i16(i);
  511.   }
  512.   /* connect prnt */
  513.   for (i = 0; i < T; i++)
  514.     if ((k = son[i]) >= T) prnt[k] = i16(i);
  515.     else prnt[k] = prnt[k + 1] = i16(i);
  516. }
  517.  
  518.  
  519. /* increment frequency of given code by one, and update tree */
  520.  
  521. static void update(int c)
  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];
  537.       freq[l] = u16(k);
  538.  
  539.       i = son[c];
  540.       prnt[i] = i16(l);
  541.       if (i < T) prnt[i + 1] = i16(l);
  542.  
  543.       j = son[l];
  544.       son[l] = i16(i);
  545.  
  546.       prnt[j] = i16(c);
  547.       if (j < T) prnt[j + 1] = i16(c);
  548.       son[c] = i16(j);
  549.  
  550.       c = l;
  551.     }
  552.   } while ((c = prnt[c]) != 0);  /* repeat up to root */
  553. }
  554.  
  555. static int DecodeChar()
  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.  
  570. static int DecodePosition()
  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.     {
  597.       *buf++ = u8(c);
  598.       text_buf[r++] = u8(c);
  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)];
  607.         *buf++ = u8(c);
  608.         text_buf[r++] = u8(c);
  609.         r &= (N - 1);
  610.         count++;
  611.       }
  612.     }
  613.   }
  614.   return count;
  615. }
  616.