btreeencode.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*
  2. ** Command & Conquer Generals(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 __BTRWRITE
  20. #define __BTRWRITE 1
  21. #include <string.h>
  22. #include "codex.h"
  23. #include "btreecodex.h"
  24. /****************************************************************/
  25. /* Internal Functions */
  26. /****************************************************************/
  27. #define BTREEWORD short
  28. #define BTREECODES 256
  29. #define BTREEBIGNUM 32000
  30. #define BTREESLOPAGE 16384
  31. struct BTREEMemStruct
  32. {
  33. char *ptr;
  34. int len;
  35. };
  36. struct BTreeEncodeContext
  37. {
  38. unsigned int packbits;
  39. unsigned int workpattern;
  40. unsigned char *bufptr;
  41. unsigned int ulen;
  42. unsigned int masks[17];
  43. unsigned char clueq[BTREECODES];
  44. unsigned char right[BTREECODES];
  45. unsigned char join[BTREECODES];
  46. unsigned int plen;
  47. unsigned char *bufbase;
  48. unsigned char *bufend;
  49. unsigned char *buffer;
  50. unsigned char *buf1;
  51. unsigned char *buf2;
  52. };
  53. static void BTREE_writebits(struct BTreeEncodeContext *EC,
  54. struct BTREEMemStruct *dest,
  55. unsigned int bitpattern,
  56. unsigned int len)
  57. {
  58. if (len > 16)
  59. {
  60. BTREE_writebits(EC,dest,(unsigned int) (bitpattern>>16), len-16);
  61. BTREE_writebits(EC,dest,(unsigned int) bitpattern, 16);
  62. }
  63. else
  64. {
  65. EC->packbits += len;
  66. EC->workpattern += (bitpattern & EC->masks[len]) << (24-EC->packbits);
  67. while (EC->packbits > 7)
  68. {
  69. *(dest->ptr+dest->len) = (unsigned char) (EC->workpattern >> 16);
  70. ++dest->len;
  71. EC->workpattern = EC->workpattern << 8;
  72. EC->packbits -= 8;
  73. ++EC->plen;
  74. }
  75. }
  76. }
  77. static void BTREE_adjcount(unsigned char *s, unsigned char *bend, BTREEWORD *count)
  78. {
  79. #ifdef __WATCOMC__
  80. union
  81. {
  82. unsigned char b[4];
  83. int w;
  84. } i;
  85. #define COUNTADJ(j) i.b[1] = i.b[0]; i.b[0] = *(s+j); ++count[i.w];
  86. i.w = 0;
  87. i.b[0] = (unsigned BTREEWORD) *s++;
  88. #else
  89. unsigned BTREEWORD i;
  90. #define COUNTADJ(j) i = (BTREEWORD)(((i<<8) | *(s+j))); ++*(count+(int)i);
  91. i = (unsigned BTREEWORD) *s++;
  92. #endif
  93. bend -= 16;
  94. if (s<bend)
  95. {
  96. do
  97. {
  98. COUNTADJ(0);
  99. COUNTADJ(1);
  100. COUNTADJ(2);
  101. COUNTADJ(3);
  102. COUNTADJ(4);
  103. COUNTADJ(5);
  104. COUNTADJ(6);
  105. COUNTADJ(7);
  106. COUNTADJ(8);
  107. COUNTADJ(9);
  108. COUNTADJ(10);
  109. COUNTADJ(11);
  110. COUNTADJ(12);
  111. COUNTADJ(13);
  112. COUNTADJ(14);
  113. COUNTADJ(15);
  114. s += 16;
  115. } while (s<bend);
  116. }
  117. bend += 16;
  118. if (s<bend)
  119. {
  120. do
  121. {
  122. COUNTADJ(0);
  123. ++s;
  124. } while (s<bend);
  125. }
  126. }
  127. /* Clear 128 ints (256 words). Done as ints for speed. */
  128. static void BTREE_clearcount(unsigned char *tryq,BTREEWORD *countbuf)
  129. {
  130. int zero=0;
  131. int i;
  132. int j;
  133. int *intptr;
  134. intptr = (int *) countbuf;
  135. j = 256;
  136. do
  137. {
  138. if (*tryq)
  139. {
  140. *tryq++ = 1;
  141. i = 8;
  142. do
  143. {
  144. *(intptr+0) = zero;
  145. *(intptr+1) = zero;
  146. *(intptr+2) = zero;
  147. *(intptr+3) = zero;
  148. *(intptr+4) = zero;
  149. *(intptr+5) = zero;
  150. *(intptr+6) = zero;
  151. *(intptr+7) = zero;
  152. *(intptr+8) = zero;
  153. *(intptr+9) = zero;
  154. *(intptr+10) = zero;
  155. *(intptr+11) = zero;
  156. *(intptr+12) = zero;
  157. *(intptr+13) = zero;
  158. *(intptr+14) = zero;
  159. *(intptr+15) = zero;
  160. intptr += 16;
  161. } while (--i);
  162. }
  163. else
  164. {
  165. ++tryq;
  166. intptr += 128;
  167. }
  168. } while (--j);
  169. }
  170. static void BTREE_joinnodes(struct BTreeEncodeContext *EC,
  171. unsigned char *cluep,
  172. unsigned char *rightp,
  173. unsigned char *joinp,
  174. unsigned int clue)
  175. {
  176. unsigned char *s;
  177. unsigned char *d;
  178. unsigned char *bend;
  179. unsigned int i;
  180. /* pack file */
  181. s = EC->bufbase;
  182. if (s==EC->buf1)
  183. {
  184. d = EC->buf2;
  185. }
  186. else
  187. {
  188. d = EC->buf1;
  189. }
  190. EC->bufbase = d;
  191. bend = EC->bufend;
  192. *bend = (unsigned char) clue;
  193. while (s<=bend)
  194. {
  195. while (!cluep[(unsigned int) (*d++ = *s++)])
  196. ;
  197. i = (unsigned int) *(s-1);
  198. if (cluep[i]==1)
  199. { if (*s==rightp[i])
  200. { *(d-1) = joinp[i];
  201. ++s;
  202. }
  203. }
  204. else
  205. { if (cluep[i]==3)
  206. { *(d-1) = (unsigned char) clue;
  207. *d++ = *(s-1);
  208. }
  209. else
  210. *d++ = *s++;
  211. }
  212. }
  213. EC->bufend = d-2;
  214. }
  215. /* find 48 most common nodes */
  216. static unsigned int BTREE_findbest(BTREEWORD *countptr,
  217. unsigned char *tryq,
  218. unsigned int *bestn,
  219. unsigned int *bestval,
  220. int ratio)
  221. {
  222. unsigned int i;
  223. unsigned int i1;
  224. unsigned int i2;
  225. unsigned int bestsize;
  226. unsigned int i3;
  227. unsigned int l;
  228. bestsize = 1;
  229. i = 3;
  230. l = 0;
  231. for (i2=0;i2<256;++i2)
  232. {
  233. if (tryq[i2])
  234. { for (i1=0;i1<256;++i1)
  235. {
  236. if (*countptr++>(BTREEWORD)i)
  237. {
  238. if (tryq[i1])
  239. { i = *(countptr-1);
  240. i3=bestsize;
  241. while (bestval[i3-1]<i)
  242. {
  243. bestn[i3] = bestn[i3-1];
  244. bestval[i3] = bestval[i3-1];
  245. --i3;
  246. }
  247. bestn[i3] = l+i1;
  248. bestval[i3] = i;
  249. if (bestsize<48)
  250. ++bestsize;
  251. while (bestval[bestsize-1]<(bestval[1]/ratio))
  252. --bestsize;
  253. if (bestsize<48)
  254. i = bestval[1]/ratio;
  255. else
  256. i = bestval[bestsize-1];
  257. }
  258. }
  259. }
  260. }
  261. else
  262. countptr += 256;
  263. l += 256;
  264. }
  265. return(bestsize);
  266. }
  267. static void BTREE_treepack(struct BTreeEncodeContext *EC,
  268. struct BTREEMemStruct *dest,
  269. unsigned int passes,
  270. unsigned int multimax,
  271. unsigned int quick,
  272. int zerosuppress)
  273. {
  274. unsigned char *bend;
  275. unsigned char *ptr1;
  276. unsigned char *treebuf;
  277. BTREEWORD *count;
  278. unsigned int i;
  279. unsigned int i1;
  280. int joinnode, leftnode, rightnode;
  281. int ratio;
  282. unsigned int hlen;
  283. unsigned int domore;
  284. unsigned int cost, save;
  285. unsigned int tcost, tsave;
  286. unsigned int clue;
  287. unsigned int freeptr;
  288. unsigned int count2[BTREECODES];
  289. unsigned char tryq[BTREECODES];
  290. unsigned char freeq[BTREECODES];
  291. unsigned int bestsize;
  292. unsigned char bestjoin[BTREECODES];
  293. unsigned int bestn[BTREECODES];
  294. unsigned int bestval[BTREECODES];
  295. unsigned int bt_size;
  296. unsigned int bt_node[BTREECODES];
  297. unsigned int bt_left[BTREECODES];
  298. unsigned int bt_right[BTREECODES];
  299. unsigned int sortptr[BTREECODES];
  300. int treebufsize;
  301. int buf1size;
  302. int buf2size;
  303. // 3/2 allows for worst case, where 2nd most popular
  304. treebufsize = 65536L*sizeof(BTREEWORD); /* 131K */
  305. buf1size = EC->ulen*3/2+(int)BTREESLOPAGE;
  306. buf2size = EC->ulen*3/2+(int)BTREESLOPAGE;
  307. treebuf = (unsigned char *) galloc(treebufsize);
  308. if (!treebuf)
  309. return; /* failure Insufficient memory for work buffer */
  310. EC->buf1 = (unsigned char *) galloc(buf1size);
  311. if (!EC->buf1)
  312. return; /* failure Insufficient memory for work buffer */
  313. EC->buf2 = (unsigned char *) galloc(buf2size);
  314. if (!EC->buf2)
  315. return; /* failure Insufficient memory for work buffer */
  316. memcpy(EC->buf1, EC->buffer, EC->ulen); /* copy to scratch buffer */
  317. EC->buffer = EC->buf1;
  318. EC->bufptr = EC->buf1+EC->ulen;
  319. EC->bufbase = EC->buffer;
  320. EC->bufend = EC->bufptr;
  321. count = (BTREEWORD *) treebuf;
  322. if (quick) ratio = quick;
  323. else ratio = 2;
  324. /*** count file ***/
  325. for (i=0; i<BTREECODES; ++i)
  326. count2[i] = 0;
  327. i1 = 0;
  328. bend = EC->bufptr;
  329. ptr1 = EC->buffer;
  330. while (ptr1<bend)
  331. { i = (unsigned int) *ptr1++;
  332. i1 = i1 + i;
  333. ++count2[i];
  334. }
  335. /* init clue array */
  336. for (i=0;i<BTREECODES;++i)
  337. EC->clueq[i] = 0;
  338. /* get a clue byte (forced) */
  339. for(i=0; i<BTREECODES; ++i)
  340. { freeq[i] = 1;
  341. if (count2[i]>3)
  342. tryq[i] = 1;
  343. else
  344. tryq[i] = 0;
  345. }
  346. /* don't use 0 for clue or node (so that [clue][0] is reserved for EOF) */
  347. count2[0] = BTREEBIGNUM; /* don't use for clue or node */
  348. /* asciiz btree suppress packing of 0..31 */
  349. if (zerosuppress)
  350. {
  351. for (i=0; i<32; ++i)
  352. {
  353. count2[i] = BTREEBIGNUM; /* don't use for nodes */
  354. tryq[i] = 0; /* don't try to pack */
  355. freeq[i] = 0; /* don't try to pack */
  356. }
  357. }
  358. /* sort codes with least used codes first */
  359. /* primary key is count, secondary key is higher code */
  360. /* registers vars usage
  361. i - code
  362. i1 - done flag/swap temp
  363. */
  364. for (i=0;i<BTREECODES;++i)
  365. sortptr[i] = i;
  366. i1=1;
  367. while (i1)
  368. {
  369. i1 = 0;
  370. for (i=1; i<BTREECODES; ++i)
  371. {
  372. if (count2[sortptr[i]]<count2[sortptr[i-1]] || ((count2[sortptr[i]]==count2[sortptr[i-1]]) && (sortptr[i]>sortptr[i-1])))
  373. {
  374. i1 = sortptr[i];
  375. sortptr[i] = sortptr[i-1];
  376. sortptr[i-1] = i1;
  377. i1 = 1;
  378. }
  379. }
  380. }
  381. freeptr = 0;
  382. i = sortptr[freeptr++];
  383. clue = (unsigned char) i;
  384. freeq[i] = 0;
  385. tryq[i] = 0;
  386. EC->clueq[i] = 3;
  387. if (count2[i])
  388. BTREE_joinnodes(EC,EC->clueq, EC->right, EC->join, clue);
  389. EC->clueq[i] = 2;
  390. /* init best array */
  391. bestval[0] = (unsigned int) -1;
  392. /* count file (pass 2) */
  393. bt_size = 0;
  394. domore = passes;
  395. while (domore)
  396. {
  397. /* clear count array */
  398. BTREE_clearcount(tryq,count);
  399. /* do an adjacency count */
  400. ptr1 = EC->bufbase;
  401. bend = EC->bufend;
  402. BTREE_adjcount(ptr1, bend, count);
  403. /* find most common nodes */
  404. bestsize = BTREE_findbest(count,tryq,bestn,bestval,ratio);
  405. /* decide which nodes should be joined to what */
  406. domore = 0;
  407. if (bestsize>1)
  408. {
  409. tcost = tsave = 0;
  410. i = i1 = domore = 1;
  411. while (domore)
  412. {
  413. leftnode = (bestn[i]>>8)&255;
  414. rightnode = bestn[i]&255;
  415. if ((tryq[leftnode]==1) && (tryq[rightnode]==1))
  416. {
  417. domore = 0;
  418. while ((freeptr<BTREECODES) && (!freeq[sortptr[freeptr]]))
  419. ++freeptr;
  420. if (freeptr<BTREECODES)
  421. {
  422. joinnode = sortptr[freeptr];
  423. cost = 3+count2[joinnode];
  424. save = bestval[i];
  425. if (cost<save)
  426. {
  427. tcost += cost;
  428. tsave += save;
  429. bestjoin[i1] = (unsigned char) joinnode;
  430. bestn[i1] = bestn[i];
  431. ++i1;
  432. freeq[joinnode] = 0;
  433. tryq[joinnode] = 2;
  434. EC->clueq[joinnode] = 3;
  435. freeq[leftnode] = 0;
  436. tryq[leftnode] = 2;
  437. EC->clueq[leftnode] = 1;
  438. EC->right[leftnode] = (unsigned char) rightnode;
  439. EC->join[leftnode] = (unsigned char) joinnode;
  440. freeq[rightnode] = 0;
  441. tryq[rightnode] = 2;
  442. bt_node[bt_size] = joinnode;
  443. bt_left[bt_size] = leftnode;
  444. bt_right[bt_size] = rightnode;
  445. ++bt_size;
  446. if (i1<=multimax)
  447. domore = 1;
  448. }
  449. }
  450. }
  451. ++i;
  452. if (i>=bestsize)
  453. domore = 0;
  454. }
  455. bestsize = i1;
  456. if (bestsize>1)
  457. {
  458. /* multijoin nodes */
  459. BTREE_joinnodes(EC,EC->clueq, EC->right, EC->join, clue);
  460. /* restore clue table */
  461. for(i=1;i<bestsize;++i)
  462. { leftnode = (bestn[i]>>8)&255;
  463. joinnode = bestjoin[i];
  464. EC->clueq[leftnode] = EC->clueq[joinnode] = 0;
  465. }
  466. domore = --passes;
  467. }
  468. }
  469. }
  470. EC->bufptr = EC->bufend;
  471. /* write header */
  472. BTREE_writebits(EC,dest,(unsigned int) clue, 8); /* clue byte */
  473. BTREE_writebits(EC,dest,(unsigned int) bt_size, 8); /* tree size */
  474. for (i=0; i<bt_size;++i)
  475. { BTREE_writebits(EC,dest,(unsigned int) bt_node[i], 8);
  476. BTREE_writebits(EC,dest,(unsigned int) bt_left[i], 8);
  477. BTREE_writebits(EC,dest,(unsigned int) bt_right[i], 8);
  478. }
  479. hlen = EC->plen;
  480. /*** write packed file ***/
  481. ptr1 = EC->bufbase;
  482. bend = EC->bufend;
  483. while (ptr1<bend)
  484. BTREE_writebits(EC,dest,(unsigned int) *ptr1++, 8);
  485. BTREE_writebits(EC,dest,(unsigned int) clue, 8);
  486. BTREE_writebits(EC,dest,(unsigned int) 0, 8);
  487. BTREE_writebits(EC,dest,0L,7); /* flush bits */
  488. gfree(EC->buf2);
  489. gfree(EC->buf1);
  490. gfree(treebuf);
  491. }
  492. static int BTREE_compressfile(struct BTreeEncodeContext *EC,
  493. struct BTREEMemStruct *infile,
  494. struct BTREEMemStruct *outfile,
  495. int ulen,
  496. int zerosuppress)
  497. {
  498. unsigned int i;
  499. unsigned int passes;
  500. unsigned int multimax;
  501. int flen;
  502. /* set defaults */
  503. EC->packbits = 0;
  504. EC->workpattern = 0L;
  505. passes = 256;
  506. multimax = 32;
  507. EC->masks[0] = 0;
  508. for (i=1;i<17;++i)
  509. EC->masks[i] = (EC->masks[i-1] << 1) + 1;
  510. /* read in a source file */
  511. EC->buffer = (unsigned char *) (infile->ptr);
  512. flen = infile->len;
  513. EC->ulen = flen;
  514. EC->bufptr = EC->buffer + flen;
  515. /* pack a file */
  516. outfile->ptr = outfile->ptr;
  517. outfile->len = 0L;
  518. EC->packbits = 0;
  519. EC->workpattern = 0L;
  520. EC->plen = 0L;
  521. /* write standard header stuff (type/signature/ulen/adjust) */
  522. /* simple fb6 header */
  523. if (ulen==infile->len)
  524. {
  525. BTREE_writebits(EC,outfile,(unsigned int) 0x46fb, 16);
  526. BTREE_writebits(EC,outfile,(unsigned int) infile->len, 24);
  527. }
  528. /* composite fb6 header */
  529. else
  530. {
  531. BTREE_writebits(EC,outfile,(unsigned int) 0x47fb, 16);
  532. BTREE_writebits(EC,outfile,(unsigned int) ulen, 24);
  533. BTREE_writebits(EC,outfile,(unsigned int) infile->len, 24);
  534. }
  535. BTREE_treepack(EC,outfile,passes, multimax, 0, zerosuppress);
  536. return(outfile->len);
  537. }
  538. /****************************************************************/
  539. /* Encode Function */
  540. /****************************************************************/
  541. int GCALL BTREE_encode(void *compresseddata, const void *source, int sourcesize, int *opts)
  542. {
  543. int plen;
  544. struct BTREEMemStruct infile;
  545. struct BTREEMemStruct outfile;
  546. struct BTreeEncodeContext EC;
  547. int opt=0;
  548. if (opts)
  549. opt = opts[0];
  550. infile.ptr = (char *)source;
  551. infile.len = sourcesize;
  552. outfile.ptr = (char *)compresseddata;
  553. outfile.len = sourcesize;
  554. plen = BTREE_compressfile(&EC,&infile, &outfile, sourcesize, opt);
  555. return(plen);
  556. }
  557. #endif