- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
- void DecodeLine2(char* pS) { 
-         const char *gLong_key       = "\x6c\x1b\x99\x5f\xb9\xcd\x5f\x13\xcb\x04\x20\x0e\x5e\x1c\xa1\x0e"; 
-         const char *gOther_long_key = "\x67\xa8\xd6\x26\xb6\xdd\x45\x1b\x32\x7e\x22\x13\x15\xc2\x94\x37"; 
-         const int gEncryption_method = 2; 
-   
-     int len; 
-     int seed; 
-     int i; 
-     unsigned char c; 
-     char* key; 
-   
-     key = (char*)gLong_key; 
-     while (len > 0 && (pS[len - 1] == '\r' || pS[len - 1] == '\n')) { 
-         len--; 
-         pS[len] = '\0'; 
-     } 
-     seed = len % 16; 
-     for (i = 0; i < len; i++) { 
-         c = pS[i]; 
-         if (i >= 2) { 
-             if (pS[i - 1] == '/' && pS[i - 2] == '/') { 
-                 key = (char*)gOther_long_key; 
-             } 
-         } 
-         if (gEncryption_method == 1) { 
-             if (c == '\t') { 
-                 c = 0x9f; 
-             } 
-   
-             c -= 0x20; 
-             c ^= key[seed]; 
-             c &= 0x7f; 
-             c += 0x20; 
-   
-             seed += 7; 
-             seed %= 16; 
-   
-             if (c == 0x9f) { 
-                 c = '\t'; 
-             } 
-         } else { 
-             if (c == '\t') { 
-                 c = 0x80; 
-             } 
-             c -= 0x20; 
-             if ((c & 0x80) == 0) { 
-                 c ^= key[seed] & 0x7f; 
-             } 
-             c += 0x20; 
-   
-             seed += 7; 
-             seed %= 16; 
-   
-             if (c == 0x80) { 
-                 c = '\t'; 
-             } 
-         } 
-         pS[i] = c; 
-     } 
- } 
-   
- int main (int argc, char **argv) 
- { 
-         // Carmageddon data file decryption utility 
-   
-         #define DECODE_CHAR_WITH_KEY(c,key) do { \ 
-                 if (c == '\t') \ 
-                         c = 128; \ 
-                 c -= 32; \ 
-                 if (c < 128) \ 
-                         c ^= (key)[seed] & 0x7f; \ 
-                 c += 32; \ 
-                 if (c == 128) \ 
-                         c = '\t'; \ 
-                 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 other_buffer[1024]; 
-         char *file_pathname = NULL; 
-         int should_fix_b0rken_crypto = 1; 
-         unsigned char c; 
-         int weird_count; 
-         int seed_backup; 
-         int seed; 
-         int len; 
-         int i; 
-         int j; 
-         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; 
-   
- #if 1 
-                         // 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 ((key_to_use == key1) && should_fix_b0rken_crypto) 
-                                 { 
-                                         if ((i >= 3) && (line_buffer[i - 2] == '/') && (line_buffer[i - 3] == '/')) // pattern: "//?" 
-                                         { 
-                                                 seed_backup = seed; 
- /* 
-                                                 weird_count = 0; 
-                                                 for (j = i; j < len; j++) 
-                                                 { 
-                                                         c = line_buffer[j]; 
-                                                         DECODE_CHAR_WITH_KEY (c, key2); // decode character with the alternate key, but don't advance the seed 
-                                                         if (c > 0x7f) 
-                                                                 weird_count++; 
-                                                         else if (c == ' ') 
-                                                                 break; 
-                                                 } 
-                                                 if ((j < len) || (weird_count > (len - i) / 10)) 
-                                                 { 
- //                                                      fprintf (stderr, "===> Switching keys at char %d\n", i); 
-                                                         key_to_use = key2; 
-                                                 } 
- /*/ 
-                                                 DECODE_CHAR_WITH_KEY (c, key2); // decode character with the alternate key, but don't advance the seed 
-                                                 if ((i > 4) || (c == ' ') || (c == '\t') || (c == '/')) 
-                                                 { 
- //                                                      fprintf (stderr, "===> Switching keys at char %d\n", i); 
-                                                         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 
-                                                 seed = seed_backup; // and restore seed 
-                                         } 
-                                 } 
-   
-                                 DECODE_CHAR_WITH_KEY (c, key_to_use); // decode character and advance the seed 
-                                 line_buffer[i - 1] = c; // write decoded character one position backwards to erase the '@' prefix 
-                         } 
- #else 
- i = len; 
- DecodeLine2 (&line_buffer[1]); 
- memmove (- line_buffer , &- line_buffer [1],-  len );
 
- #endif 
-                         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 
- } 
-