/*
** 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