pkmncompress.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /*
  2. * Copyright © 2013 stag019 <stag019@gmail.com>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <stdint.h>
  19. #include <string.h>
  20. typedef uint8_t u8;
  21. u8 *compressed = NULL;
  22. int xrows = 0;
  23. int xwidth = 0;
  24. int curbit = 0;
  25. int curbyte = 0;
  26. void writebit(int bit)
  27. {
  28. if (++curbit == 8)
  29. {
  30. curbyte++;
  31. curbit = 0;
  32. }
  33. compressed[curbyte] |= bit << (7 - curbit);
  34. }
  35. void method_1(u8 *RAM)
  36. {
  37. int i;
  38. int j;
  39. int nibble_1;
  40. int nibble_2 = 0;
  41. int code_1;
  42. int code_2;
  43. int table;
  44. static int method_1[2][0x10] = {
  45. {0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, 0xC, 0xD, 0xF, 0xE, 0xA, 0xB, 0x9, 0x8},
  46. {0x8, 0x9, 0xB, 0xA, 0xE, 0xF, 0xD, 0xC, 0x4, 0x5, 0x7, 0x6, 0x2, 0x3, 0x1, 0x0}
  47. };
  48. for (i = 0; i < xrows * xwidth * 8; i++)
  49. {
  50. j = i / xrows;
  51. j += i % xrows * xwidth * 8;
  52. if (!(i % xrows))
  53. {
  54. nibble_2 = 0;
  55. }
  56. nibble_1 = (RAM[j] >> 4) & 0x0F;
  57. table = 0;
  58. if (nibble_2 & 1)
  59. {
  60. table = 1;
  61. }
  62. code_1 = method_1[table][nibble_1];
  63. nibble_2 = RAM[j] & 0x0F;
  64. table = 0;
  65. if (nibble_1 & 1)
  66. {
  67. table = 1;
  68. }
  69. code_2 = method_1[table][nibble_2];
  70. RAM[j] = (code_1 << 4) | code_2;
  71. }
  72. }
  73. // "Get the previous power of 2. Deriving the bitcount from that seems to be faster on average than using the lookup table."
  74. void RLE(int nums)
  75. {
  76. int v;
  77. int j;
  78. int bitcount;
  79. int number;
  80. bitcount = -1;
  81. v = ++nums;
  82. v++;
  83. v |= v >> 1;
  84. v |= v >> 2;
  85. v |= v >> 4;
  86. v |= v >> 8;
  87. v |= v >> 16;
  88. v -= v >> 1;
  89. v--;
  90. number = nums - v;
  91. while(v) {
  92. v >>= 1;
  93. bitcount++;
  94. }
  95. for(j = 0; j < bitcount; j++) {
  96. writebit(1);
  97. }
  98. writebit(0);
  99. for(j = bitcount; j >= 0; j--) {
  100. writebit((number >> j) & 1);
  101. }
  102. }
  103. void RLE_old(int nums)
  104. {
  105. int search;
  106. int i;
  107. int j;
  108. int bitcount;
  109. int number;
  110. static int RLE[0x10] = {0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
  111. bitcount = -1;
  112. search = ++nums;
  113. while (search > 0)
  114. {
  115. for (i = 0; i < 0xF; i++)
  116. {
  117. if (RLE[i] == search)
  118. {
  119. bitcount = i;
  120. break;
  121. }
  122. }
  123. if (bitcount != -1)
  124. {
  125. break;
  126. }
  127. search--;
  128. }
  129. number = nums - RLE[bitcount];
  130. for (j = 0; j < bitcount; j++)
  131. {
  132. writebit(1);
  133. }
  134. writebit(0);
  135. for (j = bitcount; j >= 0; j--)
  136. {
  137. writebit((number >> j) & 1);
  138. }
  139. }
  140. void data_packet(u8 *bitgroups, int bgi)
  141. {
  142. int i;
  143. for (i = 0; i < bgi; i++)
  144. {
  145. writebit((bitgroups[i] >> 1) & 1);
  146. writebit(bitgroups[i] & 1);
  147. }
  148. }
  149. int interpret_compress(u8 *RAM_1, u8 *RAM_2, int interpretation, int switchram)
  150. {
  151. u8 *_1_RAM;
  152. u8 *_2_RAM;
  153. int i;
  154. int ram;
  155. int type;
  156. int nums;
  157. u8 *bitgroups;
  158. int x;
  159. int y;
  160. int byte;
  161. int bit;
  162. int bitgroup;
  163. int bgi = 0;
  164. int ram_size = xrows * xwidth * 8;
  165. _1_RAM = (u8 *)calloc(ram_size, 1);
  166. _2_RAM = (u8 *)calloc(ram_size, 1);
  167. if (switchram)
  168. {
  169. memcpy(_1_RAM, RAM_2, ram_size);
  170. memcpy(_2_RAM, RAM_1, ram_size);
  171. }
  172. else
  173. {
  174. memcpy(_1_RAM, RAM_1, ram_size);
  175. memcpy(_2_RAM, RAM_2, ram_size);
  176. }
  177. switch(interpretation)
  178. {
  179. case 1:
  180. method_1(_1_RAM);
  181. method_1(_2_RAM);
  182. break;
  183. case 2:
  184. case 3:
  185. for (i = 0; i < xrows * xwidth * 8; i++)
  186. {
  187. _2_RAM[i] ^= _1_RAM[i];
  188. }
  189. method_1(_1_RAM);
  190. break;
  191. }
  192. if (interpretation == 3)
  193. {
  194. method_1(_2_RAM);
  195. }
  196. curbit = 7;
  197. curbyte = 0;
  198. compressed = (u8 *)calloc(0x310, 1);
  199. compressed[0] = (xrows << 4) | xwidth;
  200. writebit(switchram);
  201. for (ram = 0; ram < 2; ram++)
  202. {
  203. type = 0;
  204. nums = 0;
  205. bitgroups = (u8 *)calloc(0x1000, 1);
  206. for (x = 0; x < xwidth; x++)
  207. {
  208. for (bit = 0; bit < 8; bit += 2)
  209. {
  210. byte = x * xrows * 8;
  211. for (y=0; y < xrows * 8; y++)
  212. {
  213. if (ram)
  214. {
  215. bitgroup = (_2_RAM[byte] >> (6 - bit)) & 3;
  216. }
  217. else
  218. {
  219. bitgroup = (_1_RAM[byte] >> (6 - bit)) & 3;
  220. }
  221. if (!bitgroup)
  222. {
  223. if (!type)
  224. {
  225. writebit(0);
  226. }
  227. else if (type == 1)
  228. {
  229. nums++;
  230. }
  231. else
  232. {
  233. data_packet(bitgroups, bgi);
  234. writebit(0);
  235. writebit(0);
  236. }
  237. type = 1;
  238. free(bitgroups);
  239. bitgroups = (u8 *)calloc(0x1000, 1);
  240. bgi = 0;
  241. }
  242. else
  243. {
  244. if (!type)
  245. {
  246. writebit(1);
  247. }
  248. else if (type == 1)
  249. {
  250. RLE(nums);
  251. }
  252. type = -1;
  253. bitgroups[bgi++] = bitgroup;
  254. nums = 0;
  255. }
  256. byte++;
  257. }
  258. }
  259. }
  260. if (type == 1)
  261. {
  262. RLE(nums);
  263. }
  264. else
  265. {
  266. data_packet(bitgroups, bgi);
  267. }
  268. if (!ram)
  269. {
  270. if (interpretation < 2)
  271. {
  272. writebit(0);
  273. }
  274. else
  275. {
  276. writebit(1);
  277. writebit(interpretation - 2);
  278. }
  279. }
  280. }
  281. free(bitgroups);
  282. free(_1_RAM);
  283. free(_2_RAM);
  284. return (curbyte + 1) * 8 + curbit;
  285. }
  286. int compress(u8 *data, int width, int height)
  287. {
  288. u8 *RAM_1;
  289. u8 *RAM_2;
  290. int i;
  291. int mode;
  292. int order;
  293. int newsize;
  294. int compressedsize;
  295. int size = -1;
  296. u8 *current = NULL;
  297. int ram_size;
  298. xrows = height;
  299. xwidth = width;
  300. ram_size = xrows * xwidth * 8;
  301. RAM_1 = (u8 *)calloc(ram_size, 1);
  302. RAM_2 = (u8 *)calloc(ram_size, 1);
  303. for (i = 0; i < xrows * xwidth * 8; i++)
  304. {
  305. RAM_1[i] = data[(i << 1)];
  306. RAM_2[i] = data[(i << 1) | 1];
  307. }
  308. for (mode = 1; mode < 4; mode++)
  309. {
  310. for (order = 0; order < 2; order++)
  311. {
  312. if (!(mode == 1 && order == 0))
  313. {
  314. newsize = interpret_compress(RAM_1, RAM_2, mode, order);
  315. if (size == -1 || newsize < size)
  316. {
  317. if (current != NULL)
  318. {
  319. free(current);
  320. }
  321. current = (u8 *)calloc(0x310, 1);
  322. memcpy(current, compressed, newsize / 8);
  323. free(compressed);
  324. size = newsize;
  325. }
  326. }
  327. }
  328. }
  329. compressed = (u8 *)calloc(0x310, 1);
  330. compressedsize = size / 8;
  331. memcpy(compressed, current, compressedsize);
  332. free(current);
  333. free(RAM_1);
  334. free(RAM_2);
  335. return compressedsize;
  336. }
  337. uint8_t *transpose_tiles(uint8_t *data, int width, int height)
  338. {
  339. int i;
  340. int j;
  341. int tile_size = 0x10;
  342. int size = width * height * tile_size;
  343. u8 *transposed = calloc(size, 1);
  344. for (i = 0; i < size; i++)
  345. {
  346. j = (i / 0x10) * width * 0x10;
  347. j = (j % size) + 0x10 * (j / size) + (i % 0x10);
  348. transposed[j] = data[i];
  349. }
  350. free(data);
  351. return transposed;
  352. }
  353. int main(int argc, char *argv[])
  354. {
  355. int width = 0;
  356. int height = 0;
  357. int transpose = 1;
  358. if (argc != 3)
  359. {
  360. fputs("Usage: pkmncompress infile.2bpp outfile.pic\n", stderr);
  361. return EXIT_FAILURE;
  362. }
  363. char *infile = argv[1];
  364. char *outfile = argv[2];
  365. FILE *f = fopen(infile, "rb");
  366. if (!f) {
  367. fprintf(stderr, "failed to open for reading: '%s'\n", infile);
  368. return EXIT_FAILURE;
  369. }
  370. fseek(f, 0, SEEK_END);
  371. int filesize = ftell(f);
  372. for (int i = 0; i < 32; i++) {
  373. width = i;
  374. height = i;
  375. if (width * height * 16 >= filesize) {
  376. break;
  377. }
  378. }
  379. if (width * height * 16 < filesize) {
  380. fprintf(stderr, "file too big: '%s' (%x)\n", infile, filesize);
  381. return EXIT_FAILURE;
  382. }
  383. if (width * height * 16 > filesize) {
  384. fprintf(stderr, "wrong filesize for '%s' (%x). must be a square image of 16-byte tiles\n", infile, filesize);
  385. return EXIT_FAILURE;
  386. }
  387. u8 *data = (u8 *)calloc(filesize, 1);
  388. fseek(f, 0, SEEK_SET);
  389. int size = fread(data, 1, filesize, f);
  390. fclose(f);
  391. if (size != filesize) {
  392. fprintf(stderr, "failed to read: '%s'\n", infile);
  393. return EXIT_FAILURE;
  394. }
  395. if (transpose) {
  396. data = transpose_tiles(data, width, height);
  397. }
  398. int compressed_size = compress(data, width, height);
  399. free(data);
  400. f = fopen(outfile, "wb");
  401. if (!f) {
  402. fprintf(stderr, "failed to open for writing: '%s'\n", outfile);
  403. return EXIT_FAILURE;
  404. }
  405. fwrite(compressed, 1, compressed_size, f);
  406. fclose(f);
  407. free(compressed);
  408. return EXIT_SUCCESS;
  409. }