Advertisement
Guest User

supaplex level compression

a guest
Apr 18th, 2010
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.91 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int bitcounter = 0, bytecounter = 0;
  5. char compressed[2000];      //aka stack
  6.  
  7. int max(int a, int b) {
  8.     return (a > b) ? a : b;
  9. }
  10.  
  11. void findnext(char c, FILE *ifp) {
  12.     int i;
  13.     do {
  14.     i = getc(ifp);
  15.     } while ( i != EOF && i != c);
  16. }
  17.  
  18. int chartohex(char c) {
  19.     c = (c >= 'a' && c <= 'f') ? c - 32 : c;        //converteert naar hoofdletters
  20.     if (c >= '0' && c <= '9')
  21.         return c - '0';
  22.     if (c >= 'A' && c <= 'F')
  23.         return c - 'A' + 10;
  24.     return 0;  
  25. }
  26.  
  27. void error(char str[]) {
  28.     printf("\n%s\npress any key to quit\n",str);
  29.     getchar();
  30.     exit(1);
  31. }
  32.  
  33. int *findstr(int *array, int start) {
  34.     //printf("atempting to find string at #%d\n",start);
  35.     int i;
  36.     static int value[2];   
  37.     for(int lengt = 32+4; lengt > 4; lengt--) {
  38.         //printf("lengt:%d\n",lengt);
  39.         for(int backtrack = -1; backtrack >= max(-255,-start) ; backtrack--){
  40.             //printf("\rcurrent lengt: %d\tcurrent backtrack: %d\t\n",lengt, backtrack);
  41.             value[0] = backtrack;
  42.             value[1] = lengt;
  43.             for(i = 0;(i < lengt) &&(array[start+i] == array[start+backtrack+i]); i++);
  44.             if ((i)>=lengt) {
  45.             return value;
  46.             }
  47.         }
  48.     }
  49.     return NULL;   
  50. }
  51.  
  52. void pushbit(int i) {
  53.     compressed[bytecounter] = compressed[bytecounter] << 1;
  54.     if (i != 0)
  55.         compressed[bytecounter]++;
  56.     bitcounter++;
  57.     if (bitcounter != 4)
  58.         return;
  59.     bitcounter = 0;
  60.     bytecounter++;
  61. }
  62.        
  63. void pushbyte(int byte, int bits) {
  64.     //printf(".%x%d",byte,bits);
  65.     for(; bits > 0; bits--)
  66.         pushbit((1 << (bits - 1)) & byte);
  67. }
  68.  
  69. char int2char(int i) {
  70.     return i + '0' + (('A'-'9'-1) * (i > 9));
  71. }
  72.  
  73. int main(int argc, char *argv[]) {
  74.  
  75.     for(int i = 0; i < 2000; i++)   //leeg compressed array
  76.         compressed[i] = 0;
  77.        
  78.     if (argc < 2)
  79.         error("too few args");
  80.        
  81.     printf("atempting to compress: %s....\n",argv[1]);
  82.    
  83.     FILE *ifp = fopen(argv[1], "r");
  84.     if (ifp == NULL)
  85.         error("unable to open file");
  86.  
  87.    
  88.    
  89.     int hex, hex2, c;
  90.     int tilemap[58*22];
  91.     int pointer = 0;
  92.     int tilemap_x = 0, tilemap_y = 0;
  93.     while (c != EOF) {          //load tilemap loop
  94.         c = getc(ifp);
  95.         if (';' == c)           //comment?
  96.             findnext('\n',ifp); //zoek eerstvolgende nieuwe regel
  97.         if ('.' == c) { //&& 'd' == getc(ifp) && ('b' == getc(ifp)))    {       //.db??
  98.             while (c != '\n' && c != ';' && c != EOF) {                 //zolang GEEN nieuwe regel of comment..
  99.                 c = getc(ifp);
  100.                 if (c == '$') {
  101.                     tilemap[pointer] = (chartohex(getc(ifp)) << 4) + (chartohex(getc(ifp)));        //haal eerste hex-char op
  102.                     //printf("%d\t%d\n", pointer, tilemap[pointer]);
  103.                     pointer++;
  104.                     if (pointer > 22*58)
  105.                         error("target is not a valid 58*22 tilemap: tilemap is too large");
  106.                                    
  107.                 }
  108.             }
  109.         }
  110.     }
  111.     if (pointer < 22*58)
  112.         error("no vailid 58*22 tilemap found");
  113.        
  114.     pointer = 0;
  115.     printf("valid tilemap found, starting LZ77 compression...\n");
  116.     while (pointer < 22*58) {
  117.         int *value = findstr(&tilemap[0], pointer);
  118.         //printf("pointer: %d\n",pointer);
  119.         if (value != 0) {   //als er een geldige string is gevonden, push 3 bytes op de stack
  120.            
  121.             //printf("pushing values on stack\n");
  122.             pushbyte(7,3);
  123.             pushbyte(-(value[0]),8);
  124.             pushbyte(value[1]-5,5);
  125.             //printf("backtrack: %d (%d)\tlengt:%d (%d)\n", value[0], -(value[0]), value[1], value[1]-5);
  126.             pointer += value[1];    //update pointer naar array
  127.         }
  128.         else {          //zoniet, bepaal de byte, en push die op de stack
  129.             int tile = tilemap[pointer];
  130.             //printf("no string was found\ncurrent tile is: %d\n",tile);   
  131.             if (tile <=5)   //als tile in 3 bits past
  132.                 pushbyte(tile, 3);
  133.             else {
  134.                 pushbyte(6, 3);
  135.                 tile = (tile >= 21) ? (tile - 1) : tile;
  136.                 tile = (tile >= 19) ? (tile - 1) : tile;
  137.                 tile -= 6;  //conversie naar tiles die daadwerkelijk worden gebruikt...
  138.                 pushbyte(tile, 4);     
  139.             }  
  140.         pointer++;
  141.         }
  142.     }
  143.     printf("compression finished, compressed data is %d bytes (%d, %d)\n",(bytecounter + 2 - (bitcounter == 0)) / 2, bytecounter, bitcounter);
  144.    
  145.     char *path = argv[1];
  146.     char filename[255];
  147.     int ptr, i;
  148.     for(ptr = 0; path[ptr] != '\0'; ptr++); //zoek ende van pad
  149.     for(; path[ptr] != '\\'; ptr--);    //zoek laatste \ in pad
  150.     ptr++;
  151.     for(i = 0; path[ptr + i - 1] != '\0'; filename[i] = path[ptr + i++]) {}         //kopieer filename
  152.     ptr -= 2;
  153.     for(; path[ptr] != '\\'; ptr--);    //zoek een-na laatste in pad
  154.     ptr++;
  155.     for(i = 0; path[ptr + i -1] != '\0'; path[ptr + i] = "compressed\\"[i++]) {}    //wijzig pad naar \compressed\.
  156.     ptr += i -1;
  157.     for(i = 0; path[ptr+i-1] != '\0'; path[ptr + i] = filename[i++]);       //plak filename
  158.     printf("now outputting to file %s\n",path);
  159.     FILE *ofp = fopen(path,"w");
  160.     if (ofp == NULL)
  161.         error("unable to open file");
  162.        
  163.     int counter = 0;
  164.     int chars = (bytecounter + 2 - (bitcounter == 0)) / 2;
  165.     while (counter < chars) {
  166.         fprintf(ofp,".db ");
  167.         for( int i = counter; i + 10 > counter; counter++) {
  168.             if (counter < chars)
  169.                 fprintf(ofp, "$%c%c,", int2char(compressed[2*counter]), int2char(compressed[2*counter+1]));
  170.         }
  171.         fprintf(ofp, "\n");
  172.     }
  173.     printf("sucess!\n");
  174.     getchar();
  175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement