- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
-   
- int main (int argc, char **argv) 
- { 
-         // Carmageddon data file decryption utility 
-   
-         #define DECODE_CHAR_WITH_KEY(c,key,should_bump_seed) do { \ 
-                 if (c == '\t') \ 
-                         c = 0x80; \ 
-                 c -= 32; \ 
-                 if ((c & 0x80) == 0) \ 
-                         c ^= (key)[seed] & 0x7f; \ 
-                 c += 32; \ 
-                 if (c == 0x80) \ 
-                         c = '\t'; \ 
-                 if (should_bump_seed) \ 
-                         seed = (seed + 7) % 16; \ 
-         } while (0) 
-   
-         const char *key1 = "\x6c\x1b\x99\x5f\xb9\xcd\x5f\x13\xcb\x04\x20\x0e\x5e\x1c\xa1\x0e"; 
-         const char *key2 = "\x67\xa8\xd6\x26\xb6\xdd\x45\x1b\x32\x7e\x22\x13\x15\xc2\x94\x37"; 
-         const char *key_to_use; 
-         char line_buffer[1024]; 
-         char *file_pathname = NULL; 
-         int should_fix_b0rken_crypto = 1; 
-         unsigned char c; 
-         int seed; 
-         int len; 
-         int i; 
-         FILE *fp; 
-   
-         // process command-line arguments 
-         for (i = 1; i < argc; i++) 
-         { 
-                 if (strcmp (- argv [- i ], "--dont-fix-b0rken-carmageddon-crypto") == 0)
 
-                         should_fix_b0rken_crypto = 0; 
-                 else if (file_pathname == NULL) 
-                         file_pathname = argv[i]; 
-         } 
-   
-         // consistency check 
-         if (file_pathname == NULL) 
-         { 
-                 fprintf (- stderr , "usage: %s [--dont-fix-b0rken-carmageddon-crypto] <FILE.TXT>\n",-  argv [0]);
 
-         } 
-   
-         // open the Carmageddon data file to decrypt 
-         fp  = fopen (- file_pathname , "rb");
-         if (fp == NULL) 
-         { 
-                 fprintf (- stderr , "error: couldn't open '%s'\n",-  argv [1]);
 
-         } 
-   
-         // read it line per line 
-         while (fgets (- line_buffer , sizeof (- line_buffer ),-  fp ) !=-  NULL )
 
-         { 
-                 len  = (int) strlen (- line_buffer ); // measure line length
-   
-                 // is this line encrypted ? 
-                 if (line_buffer[0] == '@') 
-                 { 
-                         // chop off all trailing CR and LFs from the input data 
-                         while ((len > 0) && ((line_buffer[len - 1] == '\r') || (line_buffer[len - 1] == '\n'))) 
-                                 line_buffer[--len] = 0; 
-   
-                         // start with the first key and initialize the algorithm seed to the remainder of the length of data / 16 
-                         key_to_use = key1; 
-                         seed = (len - 1) % 16; 
-   
-                         // for each encrypted character... 
-                         for (i = 1; i < len; i++) 
-                         { 
-                                 c = line_buffer[i]; // quick access to character 
-   
-                                 // when loading game data, Carmageddon does not switch the XOR cypher when the comments start 
-                                 if (should_fix_b0rken_crypto && (i >= 3) && (line_buffer[i - 2] == '/') && (line_buffer[i - 3] == '/')) 
-                                 { 
-                                         DECODE_CHAR_WITH_KEY (c, key2, 0); // decode character with the alternate key, but don't advance the seed 
-                                         if ((i > 4) || (c == ' ') || (c == '\t') || (c == '/')) 
-                                                 key_to_use = key2; // if this character looks sensible enough, it's time to swap keys 
-                                         c = line_buffer[i]; // reload character after decryption attempt with alternate key 
-                                 } 
-   
-                                 DECODE_CHAR_WITH_KEY (c, key_to_use, 1); // decode character and advance the seed 
-                                 line_buffer[i - 1] = c; // write decoded character one position backwards to erase the '@' prefix 
-                         } 
-   
-                         line_buffer[i - 1] = 0; // terminate the decrypted string properly 
-                 } 
-   
-                 // chop off all trailing CR and LFs from the decrypted data once again 
-                 while ((len > 0) && ((line_buffer[len - 1] == '\r') || (line_buffer[len - 1] == '\n'))) 
-                    line_buffer[--len] = 0; 
-   
-                 fprintf (- stdout , "%s\n",-  line_buffer ); // dump decrypted line to the standard output, with a proper newline at the end
 
-         } 
-   
-         fclose (- fp ); // close the input file
 
-         exit (0); // and exit with a success code 
- } 
-