home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / System / XFD / Developer / Sources / C / LHA3.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-16  |  9.5 KB  |  418 lines

  1. char version[] = "$VER: LHA3 2.0 (11.07.1999) by SDI";
  2.  
  3. /* Objectheader
  4.  
  5.     Name:        LHA3.c
  6.     Description:    xfd external decruncher for =SB= files
  7.     Author:     SDI (stoecker@epost.de)
  8.     Distribution:    PD
  9.  
  10.  2.0   11.07.99 : first version
  11. */
  12.  
  13. #include <libraries/xfdmaster.h>
  14. #include <proto/exec.h>
  15. #include <exec/memory.h>
  16. #include <exec/execbase.h>
  17. #include "SDI_compiler.h"
  18.  
  19. #define MAXMATCH    256
  20. #define THRESHOLD    3
  21. #define UCHAR_MAX    ((1<<(sizeof(UBYTE)*8))-1)
  22. #define NT        (USHRT_BIT + 3)
  23. #define TBIT         5
  24. #define NC         (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
  25. #define NPT        0x80
  26. #define CHAR_BIT      8
  27. #define CBIT        9
  28. #define USHRT_BIT    16
  29.  
  30. struct LhData {
  31.   STRPTR     inbuf;
  32.   STRPTR     outbuf;
  33.   LONG        origsize;
  34.   LONG        compsize;
  35.   LONG        XFDerr;
  36.   UWORD        blocksize;
  37.   UWORD        bitbuf;
  38.   UWORD        left[2 * NC - 1];
  39.   UWORD        right[2 * NC - 1];
  40.   UWORD        c_table[4096];
  41.   UWORD        pt_table[256];
  42.   UBYTE     subbitbuf;
  43.   UBYTE        bitcount;
  44.   UBYTE        c_len[NC];
  45.   UBYTE        pt_len[NPT];
  46.   UBYTE        text[1 << 15];
  47. };
  48.  
  49. /************** Here starts xfd stuff - the xfdSlave structure **********/
  50.  
  51. #define MASTER_VERS    39
  52.  
  53. typedef BOOL (*xfdFunc) ();
  54.  
  55. ASM(LONG) RecogLHA3(REG(a0, ULONG * buf), REG(a1, struct xfdRecogResult *rr),
  56.  REG(d0, ULONG length));
  57. ASM(ULONG) DecrunchLHA3(REG(a0, struct xfdBufferInfo * xbi),
  58.  REG(a6, struct xfdMasterBase *xfdMasterBase));
  59. ASM(LONG) ScanLHA3(REG(a0, ULONG *buf), REG(d0, ULONG size));
  60. ASM(ULONG) VerifyLHA3(REG(a0, ULONG *buf), REG(d0, ULONG size));
  61. static void decode(struct LhData *lhd);
  62. static void read_pt_len(struct LhData *lhd, WORD nn, WORD nbit, WORD i_special);
  63. static void read_c_len(struct LhData *lhd);
  64. static UWORD decode_c_st1(struct LhData *lhd);
  65. static UWORD decode_p_st1(struct LhData *lhd);
  66. static void fillbuf(struct LhData *lhd, UBYTE n);            /* Shift bitbuf n bits left, read n bits */
  67. static UWORD getbits(struct LhData *lhd, UBYTE n);
  68. static void make_table(struct LhData *lhd, WORD nchar, UBYTE bitlen[], WORD tablebits, UWORD table[]);
  69.  
  70. struct xfdSlave FirstSlave = {
  71.   0, XFDS_VERSION, MASTER_VERS, "Stefan Boberg's LhA3 Converter", XFDPFF_DATA|XFDPFF_RECOGLEN|XFDPFF_USERTARGET,
  72.   0, (xfdFunc) RecogLHA3, (xfdFunc) DecrunchLHA3, (xfdFunc) ScanLHA3, (xfdFunc) VerifyLHA3, 0, 0, 12};
  73.  
  74. ASM(LONG) RecogLHA3(REG(a0, ULONG * buf), REG(a1, struct xfdRecogResult *rr),
  75. REG(d0, ULONG length))
  76. {
  77.   if(*buf == 0x3D53423D)
  78.   {
  79.     rr->xfdrr_FinalTargetLen = rr->xfdrr_MinTargetLen = buf[1];
  80.     rr->xfdrr_MinSourceLen = 12 + buf[2];
  81.     return 1;
  82.   }
  83.   else
  84.     return 0;
  85. }
  86.  
  87. ASM(LONG) ScanLHA3(REG(a0, ULONG *buf), REG(d0, ULONG size))
  88. {
  89.   if(*buf == 0x3D53423D)
  90.     return 1;
  91.   else
  92.     return 0;
  93. }
  94.  
  95. ASM(ULONG) VerifyLHA3(REG(a0, ULONG *buf), REG(d0, ULONG size))
  96. {
  97.   if((buf[1] >= buf[2]) && (buf[2] + 12 <= size))
  98.     return buf[2] + 12;
  99.   return 0;
  100. }
  101.  
  102. ASM(ULONG) DecrunchLHA3(REG(a0, struct xfdBufferInfo * xbi),
  103. REG(a6, struct xfdMasterBase *xfdMasterBase))
  104. {
  105.   ULONG res = 0;
  106.   struct ExecBase *SysBase;
  107.   struct LhData *lhd;
  108.  
  109.   SysBase = xfdMasterBase->xfdm_ExecBase;
  110.  
  111.   if((lhd = (struct LhData *) AllocMem(sizeof(struct LhData), MEMF_CLEAR)))
  112.   {
  113.     lhd->outbuf = xbi->xfdbi_UserTargetBuf;
  114.     lhd->inbuf = ((STRPTR) xbi->xfdbi_SourceBuffer)+12;
  115.     lhd->origsize = xbi->xfdbi_TargetBufSaveLen;
  116.     lhd->compsize = xbi->xfdbi_SourceBufLen-12;
  117.     decode(lhd);
  118.     if(!(xbi->xfdbi_Error = lhd->XFDerr))
  119.       res = 1;
  120.  
  121.     FreeMem(lhd, sizeof(struct LhData));
  122.   }
  123.   else
  124.     xbi->xfdbi_Error = XFDERR_NOMEMORY;
  125.  
  126.   return res;
  127. }
  128.  
  129. static void decode(struct LhData *lhd)
  130. {
  131.   LONG i, j, k, c, dicsiz1, offset, count, loc, dicsiz;
  132.  
  133.   dicsiz = 1 << 15;
  134.   for(i = 0; i < dicsiz; ++i)
  135.     lhd->text[i] = ' ';
  136. //  lhd->bitbuf = 0;
  137. //  lhd->subbitbuf = 0;
  138. //  lhd->bitcount = 0;
  139.   fillbuf(lhd, 2 * CHAR_BIT);
  140. //  lhd->blocksize = 0;
  141.   dicsiz1 = dicsiz - 1;
  142.   offset = 0x100 - 3;
  143.   count = 0;
  144.   loc = 0;
  145.   while((count < lhd->origsize) && (!lhd->XFDerr))
  146.   {
  147.     c = decode_c_st1(lhd);
  148.     if (c <= UCHAR_MAX)
  149.     {
  150.       *(lhd->outbuf++) = lhd->text[loc++] = c;
  151.       if (loc == dicsiz)
  152.         loc = 0;
  153.       count++;
  154.     }
  155.     else
  156.     {
  157.       j = c - offset;
  158.       i = (loc - decode_p_st1(lhd) - 1) & dicsiz1;
  159.       count += j;
  160.       for (k = 0; k < j; k++)
  161.       {
  162.         *(lhd->outbuf++) = c = lhd->text[(i + k) & dicsiz1];
  163.         lhd->text[loc++] = c;
  164.         if (loc == dicsiz)
  165.           loc = 0;
  166.       }
  167.     }
  168.   }
  169. }
  170.  
  171. static void read_pt_len(struct LhData *lhd, WORD nn, WORD nbit, WORD i_special)
  172. {
  173.   WORD i, c, n;
  174.  
  175.   n = getbits(lhd, nbit);
  176.   if (n == 0) {
  177.     c = getbits(lhd, nbit);
  178.     for (i = 0; i < nn; i++)
  179.       lhd->pt_len[i] = 0;
  180.     for (i = 0; i < 256; i++)
  181.       lhd->pt_table[i] = c;
  182.   }
  183.   else {
  184.     i = 0;
  185.     while (i < n) {
  186.       c = lhd->bitbuf >> (16 - 3);
  187.       if (c == 7) {
  188.         UWORD  mask = 1 << (16 - 4);
  189.         while (mask & lhd->bitbuf) {
  190.           mask >>= 1;
  191.           c++;
  192.         }
  193.       }
  194.       fillbuf(lhd, (c < 7) ? 3 : c - 3);
  195.       lhd->pt_len[i++] = c;
  196.       if (i == i_special) {
  197.         c = getbits(lhd, 2);
  198.         while (--c >= 0)
  199.           lhd->pt_len[i++] = 0;
  200.       }
  201.     }
  202.     while (i < nn)
  203.       lhd->pt_len[i++] = 0;
  204.     make_table(lhd, nn, lhd->pt_len, 8, lhd->pt_table);
  205.   }
  206. }
  207.  
  208. static void read_c_len(struct LhData *lhd)
  209. {
  210.   WORD i, c, n;
  211.  
  212.   n = getbits(lhd, CBIT);
  213.   if (n == 0) {
  214.     c = getbits(lhd, CBIT);
  215.     for (i = 0; i < NC; i++)
  216.       lhd->c_len[i] = 0;
  217.     for (i = 0; i < 4096; i++)
  218.       lhd->c_table[i] = c;
  219.   } else {
  220.     i = 0;
  221.     while (i < n) {
  222.       c = lhd->pt_table[lhd->bitbuf >> (16 - 8)];
  223.       if (c >= NT) {
  224.         UWORD  mask = 1 << (16 - 9);
  225.         do {
  226.           if (lhd->bitbuf & mask)
  227.             c = lhd->right[c];
  228.           else
  229.             c = lhd->left[c];
  230.           mask >>= 1;
  231.         } while (c >= NT);
  232.       }
  233.       fillbuf(lhd, lhd->pt_len[c]);
  234.       if (c <= 2) {
  235.         if (c == 0)
  236.           c = 1;
  237.         else if (c == 1)
  238.           c = getbits(lhd, 4) + 3;
  239.         else
  240.           c = getbits(lhd, CBIT) + 20;
  241.         while (--c >= 0)
  242.           lhd->c_len[i++] = 0;
  243.       }
  244.       else
  245.         lhd->c_len[i++] = c - 2;
  246.     }
  247.     while (i < NC)
  248.       lhd->c_len[i++] = 0;
  249.     make_table(lhd, NC, lhd->c_len, 12, lhd->c_table);
  250.   }
  251. }
  252.  
  253. static UWORD decode_c_st1(struct LhData *lhd)
  254. {
  255.   UWORD  j, mask;
  256.  
  257.   if (lhd->blocksize == 0) {
  258.     lhd->blocksize = getbits(lhd, 16);
  259.     read_pt_len(lhd, NT, TBIT, 3);
  260.     read_c_len(lhd);
  261.     read_pt_len(lhd, 16, 5, -1);
  262.   }
  263.   lhd->blocksize--;
  264.   j = lhd->c_table[lhd->bitbuf >> 4];
  265.   if (j < NC)
  266.     fillbuf(lhd, lhd->c_len[j]);
  267.   else {
  268.     fillbuf(lhd, 12);
  269.     mask = 1 << (16 - 1);
  270.     do {
  271.       if (lhd->bitbuf & mask)
  272.         j = lhd->right[j];
  273.       else
  274.         j = lhd->left[j];
  275.       mask >>= 1;
  276.     } while (j >= NC);
  277.     fillbuf(lhd, lhd->c_len[j] - 12);
  278.   }
  279.   return j;
  280. }
  281.  
  282. static UWORD decode_p_st1(struct LhData *lhd)
  283. {
  284.   UWORD  j, mask;
  285.  
  286.   j = lhd->pt_table[lhd->bitbuf >> (16 - 8)];
  287.   if (j < 16)
  288.     fillbuf(lhd, lhd->pt_len[j]);
  289.   else {
  290.     fillbuf(lhd, 8);
  291.     mask = 1 << (16 - 1);
  292.     do {
  293.       if (lhd->bitbuf & mask)
  294.         j = lhd->right[j];
  295.       else
  296.         j = lhd->left[j];
  297.       mask >>= 1;
  298.     } while (j >= 16);
  299.     fillbuf(lhd, lhd->pt_len[j] - 8);
  300.   }
  301.   if (j != 0)
  302.     j = (1 << (j - 1)) + getbits(lhd, j - 1);
  303.   return j;
  304. }
  305.  
  306. static void fillbuf(struct LhData *lhd, UBYTE n)     /* Shift lhd->bitbuf n bits lhd->left, read n bits */
  307. {
  308.   while (n > lhd->bitcount) {
  309.     n -= lhd->bitcount;
  310.     lhd->bitbuf = (lhd->bitbuf << lhd->bitcount) + (lhd->subbitbuf >> (CHAR_BIT - lhd->bitcount));
  311.     if (lhd->compsize != 0) {
  312.       lhd->compsize--;
  313.       lhd->subbitbuf = (UBYTE) *(lhd->inbuf++);
  314.     }
  315.     else
  316.       lhd->subbitbuf = 0;
  317.     lhd->bitcount = CHAR_BIT;
  318.   }
  319.   lhd->bitcount -= n;
  320.   lhd->bitbuf = (lhd->bitbuf << n) + (lhd->subbitbuf >> (CHAR_BIT - n));
  321.   lhd->subbitbuf <<= n;
  322. }
  323.  
  324. static UWORD getbits(struct LhData *lhd, UBYTE n)
  325. {
  326.   UWORD  x;
  327.  
  328.   x = lhd->bitbuf >> (2 * CHAR_BIT - n);
  329.   fillbuf(lhd, n);
  330.   return x;
  331. }
  332.  
  333. static void make_table(struct LhData *lhd, WORD nchar, UBYTE bitlen[], WORD tablebits, UWORD table[])
  334. {
  335.   UWORD  count[17]; /* count of bitlen */
  336.   UWORD  weight[17];  /* 0x10000ul >> bitlen */
  337.   UWORD  start[17]; /* first code of bitlen */
  338.   UWORD  total;
  339.   ULONG    i;
  340.   LONG             j, k, l, m, n, avail;
  341.   UWORD *p;
  342.  
  343.   if(lhd->XFDerr)
  344.     return;
  345.  
  346.   avail = nchar;
  347.  
  348.   /* initialize */
  349.   for (i = 1; i <= 16; i++) {
  350.     count[i] = 0;
  351.     weight[i] = 1 << (16 - i);
  352.   }
  353.  
  354.   /* count */
  355.   for (i = 0; i < nchar; i++)
  356.     count[bitlen[i]]++;
  357.  
  358.   /* calculate first code */
  359.   total = 0;
  360.   for (i = 1; i <= 16; i++) {
  361.     start[i] = total;
  362.     total += weight[i] * count[i];
  363.   }
  364.   if ((total & 0xffff) != 0)
  365.   {
  366.     lhd->XFDerr = XFDERR_CORRUPTEDDATA;
  367.     return;
  368.   }
  369.  
  370.   /* shift data for make table. */
  371.   m = 16 - tablebits;
  372.   for (i = 1; i <= tablebits; i++) {
  373.     start[i] >>= m;
  374.     weight[i] >>= m;
  375.   }
  376.  
  377.   /* initialize */
  378.   j = start[tablebits + 1] >> m;
  379.   k = 1 << tablebits;
  380.   if (j != 0)
  381.     for (i = j; i < k; i++)
  382.       table[i] = 0;
  383.  
  384.   /* create table and tree */
  385.   for (j = 0; j < nchar; j++) {
  386.     k = bitlen[j];
  387.     if (k == 0)
  388.       continue;
  389.     l = start[k] + weight[k];
  390.     if (k <= tablebits) {
  391.       /* code in table */
  392.       for (i = start[k]; i < l; i++)
  393.         table[i] = j;
  394.     }
  395.     else {
  396.       /* code not in table */
  397.       p = &table[(i = start[k]) >> m];
  398.       i <<= tablebits;
  399.       n = k - tablebits;
  400.       /* make tree (n length) */
  401.       while (--n >= 0) {
  402.         if (*p == 0) {
  403.           lhd->right[avail] = lhd->left[avail] = 0;
  404.           *p = avail++;
  405.         }
  406.         if (i & 0x8000)
  407.           p = &lhd->right[*p];
  408.         else
  409.           p = &lhd->left[*p];
  410.         i <<= 1;
  411.       }
  412.       *p = j;
  413.     }
  414.     start[k] = l;
  415.   }
  416. }
  417.  
  418.