huffdecode.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // Copyright (C) Electronic Arts Canada Inc. 1995-2002. All rights reserved.
  19. #ifndef __HUFREAD
  20. #define __HUFREAD 1
  21. #include <string.h>
  22. #include "codex.h"
  23. #include "huffcodex.h"
  24. #if defined(_MSC_VER)
  25. #pragma warning(push,1)
  26. #endif
  27. /****************************************************************/
  28. /* Internal Functions */
  29. /****************************************************************/
  30. struct HuffDecodeContext
  31. {
  32. unsigned char *s;
  33. int bitsleft;
  34. unsigned int bits;
  35. };
  36. /****************************************************************/
  37. /* Huffman Unpacker */
  38. /****************************************************************/
  39. static int ZERO=0;
  40. #define GET16BITS() \
  41. bitsunshifted = qs[0] | (bitsunshifted << 8);\
  42. bitsunshifted = qs[1] | (bitsunshifted << 8);\
  43. qs += 2;
  44. #define SQgetbits(v,n)\
  45. if (n) \
  46. { \
  47. v = bits >> (32-(n));\
  48. bits <<= (n);\
  49. bitsleft -= (n);\
  50. } \
  51. \
  52. if (bitsleft<0)\
  53. {\
  54. GET16BITS() \
  55. \
  56. bits = bitsunshifted<<(-bitsleft);\
  57. bitsleft += 16;\
  58. }
  59. #define SQgetnum(v) \
  60. if ((int)bits<0)\
  61. {\
  62. SQgetbits(v,3);\
  63. v -= 4;\
  64. }\
  65. else\
  66. {\
  67. int n;\
  68. unsigned int v1;\
  69. \
  70. if (bits>>16)\
  71. {\
  72. n=2;\
  73. do\
  74. {\
  75. bits <<= 1; \
  76. ++n;\
  77. }\
  78. while ((int)bits>=0);\
  79. bits <<= 1;\
  80. bitsleft -= (n-1);\
  81. SQgetbits(v,ZERO);\
  82. }\
  83. else\
  84. {\
  85. n=2;\
  86. do\
  87. {\
  88. ++n;\
  89. SQgetbits(v,1);\
  90. }\
  91. while (!v);\
  92. }\
  93. if (n>16)\
  94. {\
  95. SQgetbits(v,n-16);\
  96. SQgetbits(v1,16);\
  97. v = (v1|(v<<16))+(1<<n)-4;\
  98. }\
  99. else\
  100. {\
  101. SQgetbits(v,n);\
  102. v = (v+(1<<n)-4);\
  103. }\
  104. }
  105. /* note: requires 'amt' be a multiple of 16 */
  106. #define SQmemset(ptr, val, amt) \
  107. {\
  108. int i = amt/16;\
  109. int intval = (val<<24)|(val<<16)|(val<<8)|val;\
  110. int* lptr = (int*)ptr;\
  111. \
  112. while (i)\
  113. {\
  114. lptr[0] = intval;\
  115. lptr[1] = intval;\
  116. lptr[2] = intval;\
  117. lptr[3] = intval;\
  118. lptr += 4;\
  119. --i;\
  120. }\
  121. }\
  122. static int HUFF_decompress(unsigned char *packbuf, unsigned char *unpackbuf)
  123. {
  124. unsigned int type;
  125. unsigned char clue;
  126. int ulen;
  127. unsigned int cmp;
  128. int bitnum=0;
  129. int cluelen=0;
  130. unsigned char *qs;
  131. unsigned char *qd;
  132. unsigned int bits;
  133. unsigned int bitsunshifted=0;
  134. int numbits;
  135. int bitsleft;
  136. unsigned int v;
  137. qs = packbuf;
  138. qd = unpackbuf;
  139. ulen = 0L;
  140. if (qs)
  141. {
  142. {
  143. int mostbits;
  144. int i;
  145. int bitnumtbl[16];
  146. unsigned int deltatbl[16];
  147. unsigned int cmptbl[16];
  148. unsigned char codetbl[256];
  149. unsigned char quickcodetbl[256];
  150. unsigned char quicklentbl[256];
  151. bitsleft = -16; /* init bit stream */
  152. bits = 0;
  153. SQgetbits(v,ZERO);
  154. SQgetbits(type,16);
  155. if (type&0x8000) /* 4 byte size field */
  156. {
  157. /* (skip nothing for 0x30fb) */
  158. if (type&0x100) /* skip ulen */
  159. {
  160. SQgetbits(v,16);
  161. SQgetbits(v,16);
  162. }
  163. type &= ~0x100;
  164. SQgetbits(v,16); /* unpack len */
  165. SQgetbits(ulen,16);
  166. ulen |= (v<<16);
  167. }
  168. else
  169. {
  170. /* (skip nothing for 0x30fb) */
  171. if (type&0x100) /* skip ulen */
  172. {
  173. SQgetbits(v,8);
  174. SQgetbits(v,16);
  175. }
  176. type &= ~0x100;
  177. SQgetbits(v,8); /* unpack len */
  178. SQgetbits(ulen,16);
  179. ulen |= (v<<16);
  180. }
  181. {
  182. {
  183. int numchars;
  184. {
  185. unsigned int basecmp;
  186. {
  187. unsigned int t;
  188. SQgetbits(t,8); /* clue byte */
  189. clue = (unsigned char)t;
  190. }
  191. numchars = 0;
  192. numbits = 1;
  193. basecmp = (unsigned int) 0;
  194. /* decode bitnums */
  195. do
  196. {
  197. basecmp <<= 1;
  198. deltatbl[numbits] = basecmp-numchars;
  199. SQgetnum(bitnum); /* # of codes of n bits */
  200. bitnumtbl[numbits] = bitnum;
  201. numchars += bitnum;
  202. basecmp += bitnum;
  203. cmp = 0;
  204. if (bitnum) /* left justify cmp */
  205. cmp = (basecmp << (16-numbits) & 0xffff);
  206. cmptbl[numbits++] = cmp;
  207. }
  208. while (!bitnum || cmp); /* n+1 bits in cmp? */
  209. }
  210. cmptbl[numbits-1] = 0xffffffff; /* force match on most bits */
  211. mostbits = numbits-1;
  212. /* decode leapfrog code table */
  213. {
  214. signed char leap[256];
  215. unsigned char nextchar;
  216. SQmemset(leap,0,256);
  217. nextchar = (unsigned char) -1;
  218. for (i=0;i<numchars;++i)
  219. {
  220. int leapdelta=0;
  221. SQgetnum(leapdelta);
  222. ++leapdelta;
  223. do
  224. {
  225. ++nextchar;
  226. if (!leap[nextchar])
  227. --leapdelta;
  228. } while (leapdelta);
  229. leap[nextchar] = 1;
  230. codetbl[i] = nextchar;
  231. }
  232. }
  233. }
  234. /****************************************************************/
  235. /* Make fast 8 tables */
  236. /****************************************************************/
  237. SQmemset(quicklentbl,64,256);
  238. {
  239. int bits;
  240. int bitnum;
  241. int numbitentries;
  242. int nextcode;
  243. int nextlen;
  244. int i;
  245. unsigned char *codeptr;
  246. unsigned char *quickcodeptr;
  247. unsigned char *quicklenptr;
  248. codeptr = codetbl;
  249. quickcodeptr = quickcodetbl;
  250. quicklenptr = quicklentbl;
  251. for (bits=1; bits<=mostbits; ++bits)
  252. {
  253. bitnum = bitnumtbl[bits];
  254. if (bits>=9)
  255. break;
  256. numbitentries = 1<<(8-bits);
  257. while (bitnum--)
  258. {
  259. nextcode = *codeptr++;
  260. nextlen = bits;
  261. if (nextcode==clue)
  262. {
  263. cluelen = bits;
  264. nextlen = 96; /* will force out of main loop */
  265. }
  266. for (i=0; i<numbitentries; ++i)
  267. {
  268. *quickcodeptr++ = (unsigned char) nextcode;
  269. *quicklenptr++ = (unsigned char) nextlen;
  270. }
  271. }
  272. }
  273. }
  274. }
  275. /****************************************************************/
  276. /* Main decoder */
  277. /****************************************************************/
  278. for (;;)
  279. {
  280. unsigned char *quickcodeptr = quickcodetbl;
  281. unsigned char *quicklenptr = quicklentbl;
  282. goto nextloop;
  283. /* quick 8 fetch */
  284. do
  285. {
  286. *qd++ = quickcodeptr[bits>>24];
  287. GET16BITS();
  288. bits = bitsunshifted<<(16-bitsleft);
  289. /* quick 8 decode */
  290. nextloop:
  291. numbits = quicklenptr[bits>>24];
  292. bitsleft -= numbits;
  293. if (bitsleft>=0)
  294. {
  295. do
  296. {
  297. *qd++ = quickcodeptr[bits>>24];
  298. bits <<= numbits;
  299. numbits = quicklenptr[bits>>24];
  300. bitsleft -= numbits;
  301. if (bitsleft<0) break;
  302. *qd++ = quickcodeptr[bits>>24];
  303. bits <<= numbits;
  304. numbits = quicklenptr[bits>>24];
  305. bitsleft -= numbits;
  306. if (bitsleft<0) break;
  307. *qd++ = quickcodeptr[bits>>24];
  308. bits <<= numbits;
  309. numbits = quicklenptr[bits>>24];
  310. bitsleft -= numbits;
  311. if (bitsleft<0) break;
  312. *qd++ = quickcodeptr[bits>>24];
  313. bits <<= numbits;
  314. numbits = quicklenptr[bits>>24];
  315. bitsleft -= numbits;
  316. } while (bitsleft>=0);
  317. }
  318. bitsleft += 16;
  319. } while (bitsleft>=0); /* would fetching 16 bits do it? */
  320. bitsleft = bitsleft-16+numbits; /* back to normal */
  321. /****************************************************************/
  322. /* 16 bit decoder */
  323. /****************************************************************/
  324. {
  325. unsigned char code;
  326. if (numbits!=96)
  327. {
  328. cmp = (unsigned int) (bits>>16); /* 16 bit left justified compare */
  329. numbits = 8;
  330. do
  331. {
  332. ++numbits;
  333. }
  334. while (cmp>=cmptbl[numbits]);
  335. }
  336. else
  337. numbits = cluelen;
  338. cmp = bits >> (32-(numbits));
  339. bits <<= (numbits);
  340. bitsleft -= (numbits);
  341. code = codetbl[cmp-deltatbl[numbits]]; /* the code */
  342. if (code!=clue && bitsleft>=0)
  343. {
  344. *qd++ = code;
  345. goto nextloop;
  346. }
  347. if (bitsleft<0)
  348. {
  349. GET16BITS();
  350. bits = bitsunshifted<<-bitsleft;
  351. bitsleft += 16;
  352. }
  353. if (code!=clue)
  354. {
  355. *qd++ = code;
  356. goto nextloop;
  357. }
  358. /* handle clue */
  359. {
  360. int runlen=0;
  361. unsigned char *d=qd;
  362. unsigned char *dest;
  363. SQgetnum(runlen);
  364. if (runlen) /* runlength sequence */
  365. {
  366. dest = d+runlen;
  367. code = *(d-1);
  368. do
  369. {
  370. *d++ = code;
  371. } while (d<dest);
  372. qd = d;
  373. goto nextloop;
  374. }
  375. }
  376. SQgetbits(v,1); /* End Of File */
  377. if (v)
  378. break;
  379. {
  380. unsigned int t;
  381. SQgetbits(t,8); /* explicite byte */
  382. code = (unsigned char)t;
  383. }
  384. *qd++ = code;
  385. goto nextloop;
  386. }
  387. }
  388. /****************************************************************/
  389. /* Undelta */
  390. /****************************************************************/
  391. {
  392. int i;
  393. int nextchar;
  394. if (type==0x32fb || type==0xb2fb) /* deltaed? */
  395. {
  396. i = 0;
  397. qd = unpackbuf;
  398. while (qd<unpackbuf+ulen)
  399. {
  400. i += (int) *qd;
  401. *qd++ = (unsigned char) i;
  402. }
  403. }
  404. else if (type==0x34fb || type==0xb4fb) /* accelerated? */
  405. {
  406. i = 0;
  407. nextchar = 0;
  408. qd = unpackbuf;
  409. while (qd<unpackbuf+ulen)
  410. {
  411. i += (int) *qd;
  412. nextchar += i;
  413. *qd++ = (unsigned char) nextchar;
  414. }
  415. }
  416. }
  417. }
  418. }
  419. return(ulen);
  420. }
  421. #if defined(_MSC_VER)
  422. #pragma warning(pop)
  423. #endif
  424. /****************************************************************/
  425. /* Information Functions */
  426. /****************************************************************/
  427. /* check for reasonable header: */
  428. /* 30fb..35fb header */
  429. bool GCALL HUFF_is(const void *compresseddata)
  430. {
  431. bool ok=false;
  432. int packtype=ggetm(compresseddata,2);
  433. if (packtype==0x30fb
  434. || packtype==0x31fb
  435. || packtype==0x32fb
  436. || packtype==0x33fb
  437. || packtype==0x34fb
  438. || packtype==0x35fb
  439. || packtype==0xb0fb
  440. || packtype==0xb1fb
  441. || packtype==0xb2fb
  442. || packtype==0xb3fb
  443. || packtype==0xb4fb
  444. || packtype==0xb5fb)
  445. ok = true;
  446. return(ok);
  447. }
  448. /****************************************************************/
  449. /* Decode Functions */
  450. /****************************************************************/
  451. int GCALL HUFF_size(const void *compresseddata)
  452. {
  453. int len=0;
  454. int packtype=ggetm(compresseddata,2);
  455. int ssize=(packtype&0x8000)?4:3;
  456. if (packtype&0x100) /* 31fb 33fb 35fb */
  457. {
  458. len = ggetm((char *)compresseddata+2+ssize,ssize);
  459. }
  460. else /* 30fb 32fb 34fb */
  461. {
  462. len = ggetm((char *)compresseddata+2,ssize);
  463. }
  464. return(len);
  465. }
  466. int GCALL HUFF_decode(void *dest, const void *compresseddata, int *compressedsize)
  467. {
  468. return(HUFF_decompress((unsigned char *)compresseddata, (unsigned char *)dest));
  469. }
  470. #endif