Advertisement
Guest User

pkmncompress.c

a guest
Mar 23rd, 2014
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <stdint.h>
  20. #include <string.h>
  21.  
  22. uint8_t *compressed;
  23. int xrows;
  24. int xwidth;
  25. int curbit;
  26. int curbyte;
  27.  
  28. void writebit(int bit)
  29. {
  30.     if(++curbit == 8)
  31.     {
  32.         curbyte++;
  33.         curbit = 0;
  34.     }
  35.     compressed[curbyte] |= bit << (7 - curbit);
  36. }
  37.  
  38. void method_1(uint8_t *RAM)
  39. {
  40.     int i;
  41.     int j;
  42.     int nibble_1;
  43.     int nibble_2;
  44.     int code_1;
  45.     int code_2;
  46.     int table;
  47.     static int method_1[2][0x10] = {{0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, 0xC, 0xD, 0xF, 0xE, 0xA, 0xB, 0x9, 0x8}, {0x8, 0x9, 0xB, 0xA, 0xE, 0xF, 0xD, 0xC, 0x4, 0x5, 0x7, 0x6, 0x2, 0x3, 0x1, 0x0}};
  48.  
  49.     for(i = 0; i < xrows * xwidth * 8; i++)
  50.     {
  51.         j = i / xrows;
  52.         j += i % xrows * xwidth * 8;
  53.         if(!(i % xrows))
  54.         {
  55.             nibble_2 = 0;
  56.         }
  57.         nibble_1 = (RAM[j] >> 4) & 0x0F;
  58.         table = 0;
  59.         if(nibble_2 & 1)
  60.         {
  61.             table = 1;
  62.         }
  63.         code_1 = method_1[table][nibble_1];
  64.         nibble_2 = RAM[j] & 0x0F;
  65.         table = 0;
  66.         if(nibble_1 & 1)
  67.         {
  68.             table = 1;
  69.         }
  70.         code_2 = method_1[table][nibble_2];
  71.         RAM[j] = (code_1 << 4) | code_2;
  72.     }
  73. }
  74.  
  75. void RLE(int nums)
  76. {
  77.     int search;
  78.     int i;
  79.     int j;
  80.     int bitcount;
  81.     int number;
  82.     static unsigned int RLE[0x10] = {0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
  83.  
  84.     bitcount = -1;
  85.     search = ++nums;
  86.     while(search > 0)
  87.     {
  88.         for(i = 0; i < 0xF; i++)
  89.         {
  90.             if(RLE[i] == search)
  91.             {
  92.                 bitcount = i;
  93.                 break;
  94.             }
  95.         }
  96.         if(bitcount != -1)
  97.         {
  98.             break;
  99.         }
  100.         search--;
  101.     }
  102.     number = nums - RLE[bitcount];
  103.     for(j = 0; j < bitcount; j++)
  104.     {
  105.         writebit(1);
  106.     }
  107.     writebit(0);
  108.     for(j = bitcount; j >= 0; j--)
  109.     {
  110.         writebit((number >> j) & 1);
  111.     }
  112. }
  113.  
  114. void data_packet(uint8_t *bitgroups, int bgi)
  115. {
  116.     int i;
  117.     for(i = 0; i < bgi; i++)
  118.     {
  119.         writebit((bitgroups[i] >> 1) & 1);
  120.         writebit(bitgroups[i] & 1);
  121.     }
  122. }
  123.  
  124. int interpret_compress(uint8_t *RAM_1, uint8_t *RAM_2, int interpretation, int switchram)
  125. {
  126.     uint8_t *_1_RAM;
  127.     uint8_t *_2_RAM;
  128.     int i;
  129.     int ram;
  130.     int type;
  131.     int nums;
  132.     uint8_t *bitgroups;
  133.     int byte;
  134.     int bit;
  135.     int bitgroup;
  136.     int bgi = 0;
  137.  
  138.     _1_RAM = (uint8_t*) calloc(0x188, 1);
  139.     _2_RAM = (uint8_t*) calloc(0x188, 1);
  140.     if(switchram)
  141.     {
  142.         memcpy(_1_RAM, RAM_2, 0x188);
  143.         memcpy(_2_RAM, RAM_1, 0x188);
  144.     }
  145.     else
  146.     {
  147.         memcpy(_1_RAM, RAM_1, 0x188);
  148.         memcpy(_2_RAM, RAM_2, 0x188);
  149.     }
  150.  
  151.     switch(interpretation)
  152.     {
  153.         case 1:
  154.             method_1(_1_RAM);
  155.             method_1(_2_RAM);
  156.         break;
  157.         case 2:
  158.         case 3:
  159.             for(i = 0; i < xrows * xwidth * 8; i++)
  160.             {
  161.                 _2_RAM[i] ^= _1_RAM[i];
  162.             }
  163.             method_1(_1_RAM);
  164.         break;
  165.     }
  166.     if(interpretation == 3)
  167.     {
  168.         method_1(_2_RAM);
  169.     }
  170.  
  171.     curbit = 7;
  172.     curbyte = 0;
  173.     compressed = (uint8_t*) calloc(0x310, 1);
  174.     compressed[0] = (xrows << 4) | xwidth;
  175.     writebit(switchram);
  176.  
  177.     for(ram = 0; ram < 2; ram++)
  178.     {
  179.         type = 0;
  180.         nums = 0;
  181.         bitgroups = (uint8_t*) calloc(0x1000, 1);
  182.         for(i = 0; i < xrows * xwidth * 32; i++)
  183.         {
  184.             byte = i / (xwidth * 32);
  185.             byte = byte * xwidth * 8 + i % (xwidth * 8);
  186.             bit = i / (xwidth * 8);
  187.             bit = (bit * 2) % 8;
  188.             if(ram)
  189.             {
  190.                 bitgroup = (_2_RAM[byte] >> (6 - bit)) & 3;
  191.             }
  192.             else
  193.             {
  194.                 bitgroup = (_1_RAM[byte] >> (6 - bit)) & 3;
  195.             }
  196.             if(!bitgroup)
  197.             {
  198.                 if(!type)
  199.                 {
  200.                     writebit(0);
  201.                 }
  202.                 else if(type == 1)
  203.                 {
  204.                     nums++;
  205.                 }
  206.                 else
  207.                 {
  208.                     data_packet(bitgroups, bgi);
  209.                     writebit(0);
  210.                     writebit(0);
  211.                 }
  212.                 type = 1;
  213.                 free(bitgroups);
  214.                 bitgroups = (uint8_t*) calloc(0x1000, 1);
  215.                 bgi = 0;
  216.             }
  217.             else
  218.             {
  219.                 if(!type)
  220.                 {
  221.                     writebit(1);
  222.                 }
  223.                 else if(type == 1)
  224.                 {
  225.                     RLE(nums);
  226.                 }
  227.                 type = -1;
  228.                 bitgroups[bgi++] = bitgroup;
  229.                 nums = 0;
  230.             }
  231.         }
  232.         if(type == 1)
  233.         {
  234.             RLE(nums);
  235.         }
  236.         else
  237.         {
  238.             data_packet(bitgroups, bgi);
  239.         }
  240.         if(!ram)
  241.         {
  242.             if(interpretation < 2)
  243.             {
  244.                 writebit(0);
  245.             }
  246.             else
  247.             {
  248.                 writebit(1);
  249.                 writebit(interpretation - 2);
  250.             }
  251.         }
  252.     }
  253.     free(bitgroups);
  254.     free(_1_RAM);
  255.     free(_2_RAM);
  256.     return curbyte + 1;
  257. }
  258.  
  259. int compress(uint8_t *data, int width, int height)
  260. {
  261.     uint8_t *RAM_1;
  262.     uint8_t *RAM_2;
  263.     int i;
  264.     int newsize;
  265.     int size = -1;
  266.     uint8_t *current = NULL;
  267.  
  268.     xrows = height;
  269.     xwidth = width;
  270.  
  271.     RAM_1 = (uint8_t*) calloc(0x188, 1);
  272.     RAM_2 = (uint8_t*) calloc(0x188, 1);
  273.  
  274.     for(i = 0; i < xrows * xwidth * 8; i++)
  275.     {
  276.         RAM_1[i] = data[(i << 1)];
  277.         RAM_2[i] = data[(i << 1) | 1];
  278.     }
  279.  
  280.     for(i = 0; i < 6; i++)
  281.     {
  282.         newsize = interpret_compress(RAM_1, RAM_2, i / 2 + 1, i % 2);
  283.         if(size == -1 || newsize < size)
  284.         {
  285.             if(current != NULL)
  286.             {
  287.                 free(current);
  288.             }
  289.             current = (uint8_t*) calloc(0x310, 1);
  290.             memcpy(current, compressed, newsize);
  291.             free(compressed);
  292.             size = newsize;
  293.         }
  294.     }
  295.     compressed = (uint8_t*) calloc(0x310, 1);
  296.     memcpy(compressed, current, size);
  297.     free(current);
  298.  
  299.     free(RAM_1);
  300.     free(RAM_2);
  301.  
  302.     return size;
  303. }
  304.  
  305. int main(int argc, char *argv[])
  306. {
  307.     FILE *f;
  308.     int fz;
  309.     int size;
  310.     uint8_t *contents;
  311.     int tiles;
  312.     int *chloc;
  313.     char outfile[256];
  314.  
  315.     if(argc < 2)
  316.     {
  317.         fputs("Usage: pkmncompress infile.2bpp [outfile.bin]\n", stderr);
  318.         return EXIT_FAILURE;
  319.     }
  320.  
  321.     if(argc == 2)
  322.     {
  323.         strcpy(outfile, argv[1]);
  324.         if((chloc = (int *) strrchr(outfile, '.')) != NULL)
  325.         {
  326.             strcpy((char *) chloc, ".bin");
  327.         }
  328.         else
  329.         {
  330.             strcat(outfile, ".bin");
  331.         }
  332.     }
  333.     else
  334.     {
  335.         strcpy(outfile, argv[2]);
  336.     }
  337.  
  338.     f = fopen(argv[1], "rb");
  339.  
  340.     if(!f)
  341.     {
  342.         perror("Opening file failed");
  343.         return EXIT_FAILURE;
  344.     }
  345.  
  346.     fseek(f, 0, SEEK_END);
  347.     fz = ftell(f);
  348.     if(fz == 0x310)
  349.     {
  350.         tiles = 7;
  351.     }
  352.     else if(fz == 0x240)
  353.     {
  354.         tiles = 6;
  355.     }
  356.     else if(fz == 0x190)
  357.     {
  358.         tiles = 5;
  359.     }
  360.     else if(fz == 0x100)
  361.     {
  362.         tiles = 4;
  363.     }
  364.     else
  365.     {
  366.         fputs("Error: wrong file size.\n", stderr);
  367.         return EXIT_FAILURE;
  368.     }
  369.  
  370.     contents = (uint8_t*) calloc(0x310, 1);
  371.     fseek(f, 0, SEEK_SET);
  372.     fread(contents, 1, fz, f);
  373.     fclose(f);
  374.  
  375.     size = compress(contents, tiles, tiles);
  376.  
  377.     free(contents);
  378.  
  379.     f = fopen(outfile, "wb");
  380.     fwrite(compressed, 1, size, f);
  381.  
  382.     free(compressed);
  383.  
  384.     printf("Success! File size: %i bytes\n", size);
  385.  
  386.     return EXIT_SUCCESS;
  387. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement