Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  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. }
  575.