/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ // Copyright (C) Electronic Arts Canada Inc. 1995-2002. All rights reserved. #ifndef __HUFREAD #define __HUFREAD 1 #include #include "codex.h" #include "huffcodex.h" #if defined(_MSC_VER) #pragma warning(push,1) #endif /****************************************************************/ /* Internal Functions */ /****************************************************************/ struct HuffDecodeContext { unsigned char *s; int bitsleft; unsigned int bits; }; /****************************************************************/ /* Huffman Unpacker */ /****************************************************************/ static int ZERO=0; #define GET16BITS() \ bitsunshifted = qs[0] | (bitsunshifted << 8);\ bitsunshifted = qs[1] | (bitsunshifted << 8);\ qs += 2; #define SQgetbits(v,n)\ if (n) \ { \ v = bits >> (32-(n));\ bits <<= (n);\ bitsleft -= (n);\ } \ \ if (bitsleft<0)\ {\ GET16BITS() \ \ bits = bitsunshifted<<(-bitsleft);\ bitsleft += 16;\ } #define SQgetnum(v) \ if ((int)bits<0)\ {\ SQgetbits(v,3);\ v -= 4;\ }\ else\ {\ int n;\ unsigned int v1;\ \ if (bits>>16)\ {\ n=2;\ do\ {\ bits <<= 1; \ ++n;\ }\ while ((int)bits>=0);\ bits <<= 1;\ bitsleft -= (n-1);\ SQgetbits(v,ZERO);\ }\ else\ {\ n=2;\ do\ {\ ++n;\ SQgetbits(v,1);\ }\ while (!v);\ }\ if (n>16)\ {\ SQgetbits(v,n-16);\ SQgetbits(v1,16);\ v = (v1|(v<<16))+(1<=9) break; numbitentries = 1<<(8-bits); while (bitnum--) { nextcode = *codeptr++; nextlen = bits; if (nextcode==clue) { cluelen = bits; nextlen = 96; /* will force out of main loop */ } for (i=0; i>24]; GET16BITS(); bits = bitsunshifted<<(16-bitsleft); /* quick 8 decode */ nextloop: numbits = quicklenptr[bits>>24]; bitsleft -= numbits; if (bitsleft>=0) { do { *qd++ = quickcodeptr[bits>>24]; bits <<= numbits; numbits = quicklenptr[bits>>24]; bitsleft -= numbits; if (bitsleft<0) break; *qd++ = quickcodeptr[bits>>24]; bits <<= numbits; numbits = quicklenptr[bits>>24]; bitsleft -= numbits; if (bitsleft<0) break; *qd++ = quickcodeptr[bits>>24]; bits <<= numbits; numbits = quicklenptr[bits>>24]; bitsleft -= numbits; if (bitsleft<0) break; *qd++ = quickcodeptr[bits>>24]; bits <<= numbits; numbits = quicklenptr[bits>>24]; bitsleft -= numbits; } while (bitsleft>=0); } bitsleft += 16; } while (bitsleft>=0); /* would fetching 16 bits do it? */ bitsleft = bitsleft-16+numbits; /* back to normal */ /****************************************************************/ /* 16 bit decoder */ /****************************************************************/ { unsigned char code; if (numbits!=96) { cmp = (unsigned int) (bits>>16); /* 16 bit left justified compare */ numbits = 8; do { ++numbits; } while (cmp>=cmptbl[numbits]); } else numbits = cluelen; cmp = bits >> (32-(numbits)); bits <<= (numbits); bitsleft -= (numbits); code = codetbl[cmp-deltatbl[numbits]]; /* the code */ if (code!=clue && bitsleft>=0) { *qd++ = code; goto nextloop; } if (bitsleft<0) { GET16BITS(); bits = bitsunshifted<<-bitsleft; bitsleft += 16; } if (code!=clue) { *qd++ = code; goto nextloop; } /* handle clue */ { int runlen=0; unsigned char *d=qd; unsigned char *dest; SQgetnum(runlen); if (runlen) /* runlength sequence */ { dest = d+runlen; code = *(d-1); do { *d++ = code; } while (d