yj1.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. //
  2. // PAL DOS compress format (YJ_1) library
  3. //
  4. // Author: Lou Yihua <louyihua@21cn.com>
  5. //
  6. // Copyright 2006 - 2007 Lou Yihua
  7. //
  8. // This file is part of PAL library.
  9. //
  10. // This library is free software; you can redistribute it and/or
  11. // modify it under the terms of the GNU Lesser General Public
  12. // License as published by the Free Software Foundation; either
  13. // version 2.1 of the License, or (at your option) any later version.
  14. //
  15. // This library is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. // Lesser General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU Lesser General Public
  21. // License along with this library; if not, write to the Free Software
  22. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. //
  24. // Ported to C from C++ and modified for compatibility with Big-Endian
  25. // by Wei Mingzhi <whistler@openoffice.org>.
  26. #include "common.h"
  27. typedef struct _YJ1_TreeNode
  28. {
  29. unsigned char value;
  30. unsigned char leaf;
  31. unsigned short level;
  32. unsigned int weight;
  33. struct _YJ1_TreeNode *parent;
  34. struct _YJ1_TreeNode *left;
  35. struct _YJ1_TreeNode *right;
  36. } YJ1_TreeNode;
  37. typedef struct _YJ1_TreeNodeList
  38. {
  39. YJ1_TreeNode *node;
  40. struct _YJ1_TreeNodeList *next;
  41. } YJ1_TreeNodeList;
  42. typedef struct _YJ_1_FILEHEADER
  43. {
  44. unsigned int Signature; // 'YJ_1'
  45. unsigned int UncompressedLength; // size before compression
  46. unsigned int CompressedLength; // size after compression
  47. unsigned short BlockCount; // number of blocks
  48. unsigned char Unknown;
  49. unsigned char HuffmanTreeLength; // length of huffman tree
  50. } YJ_1_FILEHEADER, *PYJ_1_FILEHEADER;
  51. typedef struct _YJ_1_BLOCKHEADER
  52. {
  53. unsigned short UncompressedLength; // maximum 0x4000
  54. unsigned short CompressedLength; // including the header
  55. unsigned short LZSSRepeatTable[4];
  56. unsigned char LZSSOffsetCodeLengthTable[4];
  57. unsigned char LZSSRepeatCodeLengthTable[3];
  58. unsigned char CodeCountCodeLengthTable[3];
  59. unsigned char CodeCountTable[2];
  60. } YJ_1_BLOCKHEADER, *PYJ_1_BLOCKHEADER;
  61. static unsigned int
  62. yj1_get_bits(
  63. const void *src,
  64. unsigned int *bitptr,
  65. unsigned int count
  66. )
  67. {
  68. unsigned char *temp = ((unsigned char *)src) + ((*bitptr >> 4) << 1);
  69. unsigned int bptr = *bitptr & 0xf;
  70. unsigned short mask;
  71. *bitptr += count;
  72. if (count > 16 - bptr)
  73. {
  74. count = count + bptr - 16;
  75. mask = 0xffff >> bptr;
  76. return (((temp[0] | (temp[1] << 8)) & mask) << count) | ((temp[2] | (temp[3] << 8)) >> (16 - count));
  77. }
  78. else
  79. return (((unsigned short)((temp[0] | (temp[1] << 8)) << bptr)) >> (16 - count));
  80. }
  81. static unsigned short
  82. yj1_get_loop(
  83. const void *src,
  84. unsigned int *bitptr,
  85. PYJ_1_BLOCKHEADER header
  86. )
  87. {
  88. if (yj1_get_bits(src, bitptr, 1))
  89. return header->CodeCountTable[0];
  90. else
  91. {
  92. unsigned int temp = yj1_get_bits(src, bitptr, 2);
  93. if (temp)
  94. return yj1_get_bits(src, bitptr, header->CodeCountCodeLengthTable[temp - 1]);
  95. else
  96. return header->CodeCountTable[1];
  97. }
  98. }
  99. static unsigned short
  100. yj1_get_count(
  101. const void *src,
  102. unsigned int *bitptr,
  103. PYJ_1_BLOCKHEADER header
  104. )
  105. {
  106. unsigned short temp;
  107. if ((temp = yj1_get_bits(src, bitptr, 2)) != 0)
  108. {
  109. if (yj1_get_bits(src, bitptr, 1))
  110. return yj1_get_bits(src, bitptr, header->LZSSRepeatCodeLengthTable[temp - 1]);
  111. else
  112. return SDL_SwapLE16(header->LZSSRepeatTable[temp]);
  113. }
  114. else
  115. return SDL_SwapLE16(header->LZSSRepeatTable[0]);
  116. }
  117. INT
  118. YJ1_Decompress(
  119. LPCVOID Source,
  120. LPVOID Destination,
  121. INT DestSize
  122. )
  123. {
  124. PYJ_1_FILEHEADER hdr = (PYJ_1_FILEHEADER)Source;
  125. unsigned char *src = (unsigned char *)Source;
  126. unsigned char *dest;
  127. unsigned int i;
  128. YJ1_TreeNode *root, *node;
  129. if (Source == NULL)
  130. return -1;
  131. if (SDL_SwapLE32(hdr->Signature) != 0x315f4a59)
  132. return -1;
  133. if (SDL_SwapLE32(hdr->UncompressedLength) > (unsigned int)DestSize)
  134. return -1;
  135. do
  136. {
  137. unsigned short tree_len = ((unsigned short)hdr->HuffmanTreeLength) * 2;
  138. unsigned int bitptr = 0;
  139. unsigned char *flag = (unsigned char *)src + 16 + tree_len;
  140. if ((node = root = (YJ1_TreeNode *)malloc(sizeof(YJ1_TreeNode) * (tree_len + 1))) == NULL)
  141. return -1;
  142. root[0].leaf = 0;
  143. root[0].value = 0;
  144. root[0].left = root + 1;
  145. root[0].right = root + 2;
  146. for (i = 1; i <= tree_len; i++)
  147. {
  148. root[i].leaf = !yj1_get_bits(flag, &bitptr, 1);
  149. root[i].value = src[15 + i];
  150. if (root[i].leaf)
  151. root[i].left = root[i].right = NULL;
  152. else
  153. {
  154. root[i].left = root + (root[i].value << 1) + 1;
  155. root[i].right = root[i].left + 1;
  156. }
  157. }
  158. src += 16 + tree_len + (((tree_len & 0xf) ? (tree_len >> 4) + 1 : (tree_len >> 4)) << 1);
  159. } while (0);
  160. dest = (unsigned char *)Destination;
  161. for (i = 0; i < SDL_SwapLE16(hdr->BlockCount); i++)
  162. {
  163. unsigned int bitptr;
  164. PYJ_1_BLOCKHEADER header;
  165. header = (PYJ_1_BLOCKHEADER)src;
  166. src += 4;
  167. if (!SDL_SwapLE16(header->CompressedLength))
  168. {
  169. unsigned short hul = SDL_SwapLE16(header->UncompressedLength);
  170. while (hul--)
  171. {
  172. *dest++ = *src++;
  173. }
  174. continue;
  175. }
  176. src += 20;
  177. bitptr = 0;
  178. for (;;)
  179. {
  180. unsigned short loop;
  181. if ((loop = yj1_get_loop(src, &bitptr, header)) == 0)
  182. break;
  183. while (loop--)
  184. {
  185. node = root;
  186. for (; !node->leaf;)
  187. {
  188. if (yj1_get_bits(src, &bitptr, 1))
  189. node = node->right;
  190. else
  191. node = node->left;
  192. }
  193. *dest++ = node->value;
  194. }
  195. if ((loop = yj1_get_loop(src, &bitptr, header)) == 0)
  196. break;
  197. while (loop--)
  198. {
  199. unsigned int pos, count;
  200. count = yj1_get_count(src, &bitptr, header);
  201. pos = yj1_get_bits(src, &bitptr, 2);
  202. pos = yj1_get_bits(src, &bitptr, header->LZSSOffsetCodeLengthTable[pos]);
  203. while (count--)
  204. {
  205. *dest = *(dest - pos);
  206. dest++;
  207. }
  208. }
  209. }
  210. src = ((unsigned char *)header) + SDL_SwapLE16(header->CompressedLength);
  211. }
  212. free(root);
  213. return SDL_SwapLE32(hdr->UncompressedLength);
  214. }
  215. /* ============================================================================================================================================= */
  216. typedef struct _YJ2_TreeNode
  217. {
  218. unsigned short weight;
  219. unsigned short value;
  220. struct _YJ2_TreeNode *parent;
  221. struct _YJ2_TreeNode *left;
  222. struct _YJ2_TreeNode *right;
  223. } YJ2_TreeNode;
  224. typedef struct _YJ2_Tree
  225. {
  226. YJ2_TreeNode *node;
  227. YJ2_TreeNode **list;
  228. } YJ2_Tree;
  229. static unsigned char yj2_data1[0x100] =
  230. {
  231. 0x3f, 0x0b, 0x17, 0x03, 0x2f, 0x0a, 0x16, 0x00, 0x2e, 0x09, 0x15, 0x02, 0x2d, 0x01, 0x08, 0x00,
  232. 0x3e, 0x07, 0x14, 0x03, 0x2c, 0x06, 0x13, 0x00, 0x2b, 0x05, 0x12, 0x02, 0x2a, 0x01, 0x04, 0x00,
  233. 0x3d, 0x0b, 0x11, 0x03, 0x29, 0x0a, 0x10, 0x00, 0x28, 0x09, 0x0f, 0x02, 0x27, 0x01, 0x08, 0x00,
  234. 0x3c, 0x07, 0x0e, 0x03, 0x26, 0x06, 0x0d, 0x00, 0x25, 0x05, 0x0c, 0x02, 0x24, 0x01, 0x04, 0x00,
  235. 0x3b, 0x0b, 0x17, 0x03, 0x23, 0x0a, 0x16, 0x00, 0x22, 0x09, 0x15, 0x02, 0x21, 0x01, 0x08, 0x00,
  236. 0x3a, 0x07, 0x14, 0x03, 0x20, 0x06, 0x13, 0x00, 0x1f, 0x05, 0x12, 0x02, 0x1e, 0x01, 0x04, 0x00,
  237. 0x39, 0x0b, 0x11, 0x03, 0x1d, 0x0a, 0x10, 0x00, 0x1c, 0x09, 0x0f, 0x02, 0x1b, 0x01, 0x08, 0x00,
  238. 0x38, 0x07, 0x0e, 0x03, 0x1a, 0x06, 0x0d, 0x00, 0x19, 0x05, 0x0c, 0x02, 0x18, 0x01, 0x04, 0x00,
  239. 0x37, 0x0b, 0x17, 0x03, 0x2f, 0x0a, 0x16, 0x00, 0x2e, 0x09, 0x15, 0x02, 0x2d, 0x01, 0x08, 0x00,
  240. 0x36, 0x07, 0x14, 0x03, 0x2c, 0x06, 0x13, 0x00, 0x2b, 0x05, 0x12, 0x02, 0x2a, 0x01, 0x04, 0x00,
  241. 0x35, 0x0b, 0x11, 0x03, 0x29, 0x0a, 0x10, 0x00, 0x28, 0x09, 0x0f, 0x02, 0x27, 0x01, 0x08, 0x00,
  242. 0x34, 0x07, 0x0e, 0x03, 0x26, 0x06, 0x0d, 0x00, 0x25, 0x05, 0x0c, 0x02, 0x24, 0x01, 0x04, 0x00,
  243. 0x33, 0x0b, 0x17, 0x03, 0x23, 0x0a, 0x16, 0x00, 0x22, 0x09, 0x15, 0x02, 0x21, 0x01, 0x08, 0x00,
  244. 0x32, 0x07, 0x14, 0x03, 0x20, 0x06, 0x13, 0x00, 0x1f, 0x05, 0x12, 0x02, 0x1e, 0x01, 0x04, 0x00,
  245. 0x31, 0x0b, 0x11, 0x03, 0x1d, 0x0a, 0x10, 0x00, 0x1c, 0x09, 0x0f, 0x02, 0x1b, 0x01, 0x08, 0x00,
  246. 0x30, 0x07, 0x0e, 0x03, 0x1a, 0x06, 0x0d, 0x00, 0x19, 0x05, 0x0c, 0x02, 0x18, 0x01, 0x04, 0x00
  247. };
  248. static unsigned char yj2_data2[0x10] =
  249. {
  250. 0x08, 0x05, 0x06, 0x04, 0x07, 0x05, 0x06, 0x03, 0x07, 0x05, 0x06, 0x04, 0x07, 0x04, 0x05, 0x03
  251. };
  252. static void yj2_adjust_tree(YJ2_Tree tree, unsigned short value)
  253. {
  254. YJ2_TreeNode* node = tree.list[value];
  255. YJ2_TreeNode tmp;
  256. YJ2_TreeNode* tmp1;
  257. YJ2_TreeNode* temp;
  258. while (node->value != 0x280)
  259. {
  260. temp = node + 1;
  261. while (node->weight == temp->weight)
  262. temp++;
  263. temp--;
  264. if (temp != node)
  265. {
  266. tmp1 = node->parent;
  267. node->parent = temp->parent;
  268. temp->parent = tmp1;
  269. if (node->value > 0x140)
  270. {
  271. node->left->parent = temp;
  272. node->right->parent = temp;
  273. }
  274. else
  275. tree.list[node->value] = temp;
  276. if (temp->value > 0x140)
  277. {
  278. temp->left->parent = node;
  279. temp->right->parent = node;
  280. }
  281. else
  282. tree.list[temp->value] = node;
  283. tmp = *node; *node = *temp; *temp = tmp;
  284. node = temp;
  285. }
  286. node->weight++;
  287. node = node->parent;
  288. }
  289. node->weight++;
  290. }
  291. static int yj2_build_tree(YJ2_Tree *tree)
  292. {
  293. int i, ptr;
  294. YJ2_TreeNode** list;
  295. YJ2_TreeNode* node;
  296. if ((tree->list = list = (YJ2_TreeNode **)malloc(sizeof(YJ2_TreeNode*) * 321)) == NULL)
  297. return 0;
  298. if ((tree->node = node = (YJ2_TreeNode *)malloc(sizeof(YJ2_TreeNode) * 641)) == NULL)
  299. {
  300. free(list);
  301. return 0;
  302. }
  303. memset(list, 0, 321 * sizeof(YJ2_TreeNode*));
  304. memset(node, 0, 641 * sizeof(YJ2_TreeNode));
  305. for (i = 0; i <= 0x140; i++)
  306. list[i] = node + i;
  307. for (i = 0; i <= 0x280; i++)
  308. {
  309. node[i].value = i;
  310. node[i].weight = 1;
  311. }
  312. tree->node[0x280].parent = tree->node + 0x280;
  313. for (i = 0, ptr = 0x141; ptr <= 0x280; i += 2, ptr++)
  314. {
  315. node[ptr].left = node + i;
  316. node[ptr].right = node + i + 1;
  317. node[i].parent = node[i + 1].parent = node + ptr;
  318. node[ptr].weight = node[i].weight + node[i + 1].weight;
  319. }
  320. return 1;
  321. }
  322. static int yj2_bt(const unsigned char* data, unsigned int pos)
  323. {
  324. return (data[pos >> 3] & (unsigned char)(1 << (pos & 0x7))) >> (pos & 0x7);
  325. }
  326. INT
  327. YJ2_Decompress(
  328. LPCVOID Source,
  329. LPVOID Destination,
  330. INT DestSize
  331. )
  332. {
  333. int Length;
  334. unsigned int len = 0, ptr = 0;
  335. unsigned char* src = (unsigned char*)Source + 4;
  336. unsigned char* dest;
  337. YJ2_Tree tree;
  338. YJ2_TreeNode* node;
  339. if (Source == NULL)
  340. return -1;
  341. if (!yj2_build_tree(&tree))
  342. return -1;
  343. Length = SDL_SwapLE32(*((unsigned int*)Source));
  344. if (Length > DestSize)
  345. return -1;
  346. dest = (unsigned char*)Destination;
  347. while (1)
  348. {
  349. unsigned short val;
  350. node = tree.node + 0x280;
  351. while (node->value > 0x140)
  352. {
  353. if (yj2_bt(src, ptr))
  354. node = node->right;
  355. else
  356. node = node->left;
  357. ptr++;
  358. }
  359. val = node->value;
  360. if (tree.node[0x280].weight == 0x8000)
  361. {
  362. int i;
  363. for (i = 0; i < 0x141; i++)
  364. if (tree.list[i]->weight & 0x1)
  365. yj2_adjust_tree(tree, i);
  366. for (i = 0; i <= 0x280; i++)
  367. tree.node[i].weight >>= 1;
  368. }
  369. yj2_adjust_tree(tree, val);
  370. if (val > 0xff)
  371. {
  372. int i;
  373. unsigned int temp, tmp, pos;
  374. unsigned char* pre;
  375. for (i = 0, temp = 0; i < 8; i++, ptr++)
  376. temp |= (unsigned int)yj2_bt(src, ptr) << i;
  377. tmp = temp & 0xff;
  378. for (; i < yj2_data2[tmp & 0xf] + 6; i++, ptr++)
  379. temp |= (unsigned int)yj2_bt(src, ptr) << i;
  380. temp >>= yj2_data2[tmp & 0xf];
  381. pos = (temp & 0x3f) | ((unsigned int)yj2_data1[tmp] << 6);
  382. if (pos == 0xfff)
  383. break;
  384. pre = dest - pos - 1;
  385. for (i = 0; i < val - 0xfd; i++)
  386. *dest++ = *pre++;
  387. len += val - 0xfd;
  388. }
  389. else
  390. {
  391. *dest++ = (unsigned char)val;
  392. len++;
  393. }
  394. }
  395. free(tree.list);
  396. free(tree.node);
  397. return Length;
  398. }
  399. INT (*Decompress)(LPCVOID, LPVOID, INT);