Advertisement
smiche

q3huff.h

Apr 13th, 2015
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.88 KB | None | 0 0
  1. /*
  2.  
  3. Quake 3 engine Huffman algorithm 0.3
  4.  
  5. ALL the code from the public GPL source code of the Quake 3 engine 1.32
  6.  
  7. some modifications by Luigi Auriemma
  8. e-mail: aluigi@autistici.org
  9. web:    aluigi.org
  10.  
  11. */
  12. /*
  13. ===========================================================================
  14. Copyright (C) 1999-2005 Id Software, Inc.
  15.  
  16. This file is part of Quake III Arena source code.
  17.  
  18. Quake III Arena source code is free software; you can redistribute it
  19. and/or modify it under the terms of the GNU General Public License as
  20. published by the Free Software Foundation; either version 2 of the License,
  21. or (at your option) any later version.
  22.  
  23. Quake III Arena source code is distributed in the hope that it will be
  24. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26. GNU General Public License for more details.
  27.  
  28. You should have received a copy of the GNU General Public License
  29. along with Foobar; if not, write to the Free Software
  30. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  31. ===========================================================================
  32. */
  33.  
  34. /* This is based on the Adaptive Huffman algorithm described in Sayood's Data
  35.  * Compression book.  The ranks are not actually stored, but implicitly defined
  36.  * by the location of a node within a doubly-linked list */
  37.  
  38.  
  39. #define Com_Memset  memset
  40. #define Com_Memcpy  memcpy
  41.  
  42. typedef unsigned char       byte;
  43.  
  44. typedef enum {qfalse, qtrue}    qboolean;
  45.  
  46. #define NYT HMAX                    /* NYT = Not Yet Transmitted */
  47. #define INTERNAL_NODE (HMAX+1)
  48.  
  49. typedef struct nodetype {
  50.     struct  nodetype *left, *right, *parent; /* tree structure */
  51.     struct  nodetype *next, *prev; /* doubly-linked list */
  52.     struct  nodetype **head; /* highest ranked node in block */
  53.     int     weight;
  54.     int     symbol;
  55. } node_t;
  56.  
  57. #define HMAX 256 /* Maximum symbol */
  58.  
  59. typedef struct {
  60.     int         blocNode;
  61.     int         blocPtrs;
  62.  
  63.     node_t*     tree;
  64.     node_t*     lhead;
  65.     node_t*     ltail;
  66.     node_t*     loc[HMAX+1];
  67.     node_t**    freelist;
  68.  
  69.     node_t      nodeList[768];
  70.     node_t*     nodePtrs[768];
  71. } huff_t;
  72.  
  73. static int          bloc = 0;
  74.  
  75. void    Huff_putBit( int bit, byte *fout, int *offset) {
  76.     bloc = *offset;
  77.     if ((bloc&7) == 0) {
  78.         fout[(bloc>>3)] = 0;
  79.     }
  80.     fout[(bloc>>3)] |= bit << (bloc&7);
  81.     bloc++;
  82.     *offset = bloc;
  83. }
  84.  
  85. int     Huff_getBit( byte *fin, int *offset) {
  86.     int t;
  87.     bloc = *offset;
  88.     t = (fin[(bloc>>3)] >> (bloc&7)) & 0x1;
  89.     bloc++;
  90.     *offset = bloc;
  91.     return t;
  92. }
  93.  
  94. /* Add a bit to the output file (buffered) */
  95. static void add_bit (char bit, byte *fout) {
  96.     if ((bloc&7) == 0) {
  97.         fout[(bloc>>3)] = 0;
  98.     }
  99.     fout[(bloc>>3)] |= bit << (bloc&7);
  100.     bloc++;
  101. }
  102.  
  103. /* Receive one bit from the input file (buffered) */
  104. static int get_bit (byte *fin) {
  105.     int t;
  106.     t = (fin[(bloc>>3)] >> (bloc&7)) & 0x1;
  107.     bloc++;
  108.     return t;
  109. }
  110.  
  111. static node_t **get_ppnode(huff_t* huff) {
  112.     node_t **tppnode;
  113.     if (!huff->freelist) {
  114.         return &(huff->nodePtrs[huff->blocPtrs++]);
  115.     } else {
  116.         tppnode = huff->freelist;
  117.         huff->freelist = (node_t **)*tppnode;
  118.         return tppnode;
  119.     }
  120. }
  121.  
  122. static void free_ppnode(huff_t* huff, node_t **ppnode) {
  123.     *ppnode = (node_t *)huff->freelist;
  124.     huff->freelist = ppnode;
  125. }
  126.  
  127. /* Swap the location of these two nodes in the tree */
  128. static void swap (huff_t* huff, node_t *node1, node_t *node2) {
  129.     node_t *par1, *par2;
  130.  
  131.     par1 = node1->parent;
  132.     par2 = node2->parent;
  133.  
  134.     if (par1) {
  135.         if (par1->left == node1) {
  136.             par1->left = node2;
  137.         } else {
  138.           par1->right = node2;
  139.         }
  140.     } else {
  141.         huff->tree = node2;
  142.     }
  143.  
  144.     if (par2) {
  145.         if (par2->left == node2) {
  146.             par2->left = node1;
  147.         } else {
  148.             par2->right = node1;
  149.         }
  150.     } else {
  151.         huff->tree = node1;
  152.     }
  153.  
  154.     node1->parent = par2;
  155.     node2->parent = par1;
  156. }
  157.  
  158. /* Swap these two nodes in the linked list (update ranks) */
  159. static void swaplist(node_t *node1, node_t *node2) {
  160.     node_t *par1;
  161.  
  162.     par1 = node1->next;
  163.     node1->next = node2->next;
  164.     node2->next = par1;
  165.  
  166.     par1 = node1->prev;
  167.     node1->prev = node2->prev;
  168.     node2->prev = par1;
  169.  
  170.     if (node1->next == node1) {
  171.         node1->next = node2;
  172.     }
  173.     if (node2->next == node2) {
  174.         node2->next = node1;
  175.     }
  176.     if (node1->next) {
  177.         node1->next->prev = node1;
  178.     }
  179.     if (node2->next) {
  180.         node2->next->prev = node2;
  181.     }
  182.     if (node1->prev) {
  183.         node1->prev->next = node1;
  184.     }
  185.     if (node2->prev) {
  186.         node2->prev->next = node2;
  187.     }
  188. }
  189.  
  190. /* Do the increments */
  191. static void increment(huff_t* huff, node_t *node) {
  192.     node_t *lnode;
  193.  
  194.     if (!node) {
  195.         return;
  196.     }
  197.  
  198.     if (node->next != NULL && node->next->weight == node->weight) {
  199.         lnode = *node->head;
  200.         if (lnode != node->parent) {
  201.             swap(huff, lnode, node);
  202.         }
  203.         swaplist(lnode, node);
  204.     }
  205.     if (node->prev && node->prev->weight == node->weight) {
  206.         *node->head = node->prev;
  207.     } else {
  208.         *node->head = NULL;
  209.         free_ppnode(huff, node->head);
  210.     }
  211.     node->weight++;
  212.     if (node->next && node->next->weight == node->weight) {
  213.         node->head = node->next->head;
  214.     } else {
  215.         node->head = get_ppnode(huff);
  216.         *node->head = node;
  217.     }
  218.     if (node->parent) {
  219.         increment(huff, node->parent);
  220.         if (node->prev == node->parent) {
  221.             swaplist(node, node->parent);
  222.             if (*node->head == node) {
  223.                 *node->head = node->parent;
  224.             }
  225.         }
  226.     }
  227. }
  228.  
  229. void Huff_addRef(huff_t* huff, byte ch) {
  230.     node_t *tnode, *tnode2;
  231.     if (huff->loc[ch] == NULL) { /* if this is the first transmission of this node */
  232.         tnode = &(huff->nodeList[huff->blocNode++]);
  233.         tnode2 = &(huff->nodeList[huff->blocNode++]);
  234.  
  235.         tnode2->symbol = INTERNAL_NODE;
  236.         tnode2->weight = 1;
  237.         tnode2->next = huff->lhead->next;
  238.         if (huff->lhead->next) {
  239.             huff->lhead->next->prev = tnode2;
  240.             if (huff->lhead->next->weight == 1) {
  241.                 tnode2->head = huff->lhead->next->head;
  242.             } else {
  243.                 tnode2->head = get_ppnode(huff);
  244.                 *tnode2->head = tnode2;
  245.             }
  246.         } else {
  247.             tnode2->head = get_ppnode(huff);
  248.             *tnode2->head = tnode2;
  249.         }
  250.         huff->lhead->next = tnode2;
  251.         tnode2->prev = huff->lhead;
  252.  
  253.         tnode->symbol = ch;
  254.         tnode->weight = 1;
  255.         tnode->next = huff->lhead->next;
  256.         if (huff->lhead->next) {
  257.             huff->lhead->next->prev = tnode;
  258.             if (huff->lhead->next->weight == 1) {
  259.                 tnode->head = huff->lhead->next->head;
  260.             } else {
  261.                 /* this should never happen */
  262.                 tnode->head = get_ppnode(huff);
  263.                 *tnode->head = tnode2;
  264.             }
  265.         } else {
  266.             /* this should never happen */
  267.             tnode->head = get_ppnode(huff);
  268.             *tnode->head = tnode;
  269.         }
  270.         huff->lhead->next = tnode;
  271.         tnode->prev = huff->lhead;
  272.         tnode->left = tnode->right = NULL;
  273.  
  274.         if (huff->lhead->parent) {
  275.             if (huff->lhead->parent->left == huff->lhead) { /* lhead is guaranteed to by the NYT */
  276.                 huff->lhead->parent->left = tnode2;
  277.             } else {
  278.                 huff->lhead->parent->right = tnode2;
  279.             }
  280.         } else {
  281.             huff->tree = tnode2;
  282.         }
  283.  
  284.         tnode2->right = tnode;
  285.         tnode2->left = huff->lhead;
  286.  
  287.         tnode2->parent = huff->lhead->parent;
  288.         huff->lhead->parent = tnode->parent = tnode2;
  289.  
  290.         huff->loc[ch] = tnode;
  291.  
  292.         increment(huff, tnode2->parent);
  293.     } else {
  294.         increment(huff, huff->loc[ch]);
  295.     }
  296. }
  297.  
  298. /* Get a symbol */
  299. int Huff_Receive (node_t *node, int *ch, byte *fin) {
  300.     while (node && node->symbol == INTERNAL_NODE) {
  301.         if (get_bit(fin)) {
  302.             node = node->right;
  303.         } else {
  304.             node = node->left;
  305.         }
  306.     }
  307.     if (!node) {
  308.         return 0;
  309. //      Com_Error(ERR_DROP, "Illegal tree!\n");
  310.     }
  311.     return (*ch = node->symbol);
  312. }
  313.  
  314. /* Get a symbol */
  315. void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
  316.     bloc = *offset;
  317.     while (node && node->symbol == INTERNAL_NODE) {
  318.         if (get_bit(fin)) {
  319.             node = node->right;
  320.         } else {
  321.             node = node->left;
  322.         }
  323.     }
  324.     if (!node) {
  325.         *ch = 0;
  326.         return;
  327. //      Com_Error(ERR_DROP, "Illegal tree!\n");
  328.     }
  329.     *ch = node->symbol;
  330.     *offset = bloc;
  331. }
  332.  
  333. /* Send the prefix code for this node */
  334. static void send_huff(node_t *node, node_t *child, byte *fout) {
  335.     if (node->parent) {
  336.         send_huff(node->parent, node, fout);
  337.     }
  338.     if (child) {
  339.         if (node->right == child) {
  340.             add_bit(1, fout);
  341.         } else {
  342.             add_bit(0, fout);
  343.         }
  344.     }
  345. }
  346.  
  347. /* Send a symbol */
  348. void Huff_transmit (huff_t *huff, int ch, byte *fout) {
  349.     int i;
  350.     if (huff->loc[ch] == NULL) {
  351.         /* node_t hasn't been transmitted, send a NYT, then the symbol */
  352.         Huff_transmit(huff, NYT, fout);
  353.         for (i = 7; i >= 0; i--) {
  354.             add_bit((char)((ch >> i) & 0x1), fout);
  355.         }
  356.     } else {
  357.         send_huff(huff->loc[ch], NULL, fout);
  358.     }
  359. }
  360.  
  361. void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset) {
  362.     bloc = *offset;
  363.     send_huff(huff->loc[ch], NULL, fout);
  364.     *offset = bloc;
  365. }
  366.  
  367. int Huff_DecompressPacket( unsigned char *msg, int offset, int cursize, int maxsize ) {
  368.     int         ch, cch, i, j, size;
  369.     byte        seq[65536];
  370.     byte*       buffer;
  371.     huff_t      huff;
  372.  
  373.     size = cursize - offset;
  374.     buffer = msg + offset;
  375.  
  376.     if ( size <= 0 ) {
  377.         return(cursize);
  378.     }
  379.  
  380.     Com_Memset(&huff, 0, sizeof(huff_t));
  381.     // Initialize the tree & list with the NYT node
  382.     huff.tree = huff.lhead = huff.ltail = huff.loc[NYT] = &(huff.nodeList[huff.blocNode++]);
  383.     huff.tree->symbol = NYT;
  384.     huff.tree->weight = 0;
  385.     huff.lhead->next = huff.lhead->prev = NULL;
  386.     huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
  387.  
  388.     cch = buffer[0]*256 + buffer[1];
  389.     // don't overflow with bad messages
  390.     if ( cch > maxsize - offset ) {
  391.         cch = maxsize - offset;
  392.     }
  393.     bloc = 16;
  394.  
  395.     for ( j = 0; j < cch; j++ ) {
  396.         ch = 0;
  397.         // don't overflow reading from the messages
  398.         // FIXME: would it be better to have a overflow check in get_bit ?
  399.         if ( (bloc >> 3) > size ) {
  400.             seq[j] = 0;
  401.             break;
  402.         }
  403.         Huff_Receive(huff.tree, &ch, buffer);               /* Get a character */
  404.         if ( ch == NYT ) {                              /* We got a NYT, get the symbol associated with it */
  405.             ch = 0;
  406.             for ( i = 0; i < 8; i++ ) {
  407.                 ch = (ch<<1) + get_bit(buffer);
  408.             }
  409.         }
  410.  
  411.         seq[j] = ch;                                    /* Write symbol */
  412.  
  413.         Huff_addRef(&huff, (byte)ch);                               /* Increment node */
  414.     }
  415.     cursize = cch + offset;
  416.     Com_Memcpy(buffer, seq, cch);
  417.     return(cursize);
  418. }
  419.  
  420. extern  int oldsize;
  421.  
  422. int Huff_CompressPacket( unsigned char *msg, int offset, int cursize ) {
  423.     int         i, ch, size;
  424.     byte        seq[65536];
  425.     byte*       buffer;
  426.     huff_t      huff;
  427.  
  428.     size = cursize - offset;
  429.     buffer = msg + offset;
  430.  
  431.     if (size<=0) {
  432.         return(cursize);
  433.     }
  434.  
  435.     Com_Memset(&huff, 0, sizeof(huff_t));
  436.     // Add the NYT (not yet transmitted) node into the tree/list */
  437.     huff.tree = huff.lhead = huff.loc[NYT] =  &(huff.nodeList[huff.blocNode++]);
  438.     huff.tree->symbol = NYT;
  439.     huff.tree->weight = 0;
  440.     huff.lhead->next = huff.lhead->prev = NULL;
  441.     huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
  442.     huff.loc[NYT] = huff.tree;
  443.  
  444.     seq[0] = (size>>8);
  445.     seq[1] = size&0xff;
  446.  
  447.     bloc = 16;
  448.  
  449.     for (i=0; i<size; i++ ) {
  450.         ch = buffer[i];
  451.         Huff_transmit(&huff, ch, seq);                      /* Transmit symbol */
  452.         Huff_addRef(&huff, (byte)ch);                               /* Do update */
  453.     }
  454.  
  455.     bloc += 8;                                              // next byte
  456.  
  457.     cursize = (bloc>>3) + offset;
  458.     Com_Memcpy(buffer, seq, (bloc>>3));
  459.     return(cursize);
  460. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement