Subversion Repositories Games.Carmageddon

Rev

Rev 1 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1 Rev 11
Line 4... Line 4...
4
 
4
 
-
 
5
void DecodeLine2(char* pS) {
-
 
6
        const char *gLong_key       = "\x6c\x1b\x99\x5f\xb9\xcd\x5f\x13\xcb\x04\x20\x0e\x5e\x1c\xa1\x0e";
-
 
7
        const char *gOther_long_key = "\x67\xa8\xd6\x26\xb6\xdd\x45\x1b\x32\x7e\x22\x13\x15\xc2\x94\x37";
-
 
8
        const int gEncryption_method = 2;
-
 
9
 
-
 
10
    int len;
-
 
11
    int seed;
-
 
12
    int i;
-
 
13
    unsigned char c;
-
 
14
    char* key;
-
 
15
 
-
 
16
    len = strlen(pS);
-
 
17
    key = (char*)gLong_key;
-
 
18
    while (len > 0 && (pS[len - 1] == '\r' || pS[len - 1] == '\n')) {
-
 
19
        len--;
-
 
20
        pS[len] = '\0';
-
 
21
    }
-
 
22
    seed = len % 16;
-
 
23
    for (i = 0; i < len; i++) {
-
 
24
        c = pS[i];
-
 
25
        if (i >= 2) {
-
 
26
            if (pS[i - 1] == '/' && pS[i - 2] == '/') {
-
 
27
                key = (char*)gOther_long_key;
-
 
28
            }
-
 
29
        }
-
 
30
        if (gEncryption_method == 1) {
-
 
31
            if (c == '\t') {
-
 
32
                c = 0x9f;
-
 
33
            }
-
 
34
 
-
 
35
            c -= 0x20;
-
 
36
            c ^= key[seed];
-
 
37
            c &= 0x7f;
-
 
38
            c += 0x20;
-
 
39
 
-
 
40
            seed += 7;
-
 
41
            seed %= 16;
-
 
42
 
-
 
43
            if (c == 0x9f) {
-
 
44
                c = '\t';
-
 
45
            }
-
 
46
        } else {
-
 
47
            if (c == '\t') {
-
 
48
                c = 0x80;
-
 
49
            }
-
 
50
            c -= 0x20;
-
 
51
            if ((c & 0x80) == 0) {
-
 
52
                c ^= key[seed] & 0x7f;
-
 
53
            }
-
 
54
            c += 0x20;
-
 
55
 
-
 
56
            seed += 7;
-
 
57
            seed %= 16;
-
 
58
 
-
 
59
            if (c == 0x80) {
-
 
60
                c = '\t';
-
 
61
            }
-
 
62
        }
-
 
63
        pS[i] = c;
-
 
64
    }
-
 
65
}
5
 
66
 
6
int main (int argc, char **argv)
67
int main (int argc, char **argv)
7
{
68
{
8
        // Carmageddon data file decryption utility
69
        // Carmageddon data file decryption utility
9
 
70
 
10
        #define DECODE_CHAR_WITH_KEY(c,key,should_bump_seed) do { \
71
        #define DECODE_CHAR_WITH_KEY(c,key) do { \
11
                if (c == '\t') \
72
                if (c == '\t') \
12
                        c = 0x80; \
73
                        c = 128; \
13
                c -= 32; \
74
                c -= 32; \
14
                if ((c & 0x80) == 0) \
75
                if (c < 128) \
15
                        c ^= (key)[seed] & 0x7f; \
76
                        c ^= (key)[seed] & 0x7f; \
16
                c += 32; \
77
                c += 32; \
17
                if (c == 0x80) \
78
                if (c == 128) \
18
                        c = '\t'; \
79
                        c = '\t'; \
19
                if (should_bump_seed) \
-
 
20
                        seed = (seed + 7) % 16; \
80
                seed = (seed + 7) % 16; \
21
        } while (0)
81
        } while (0)
22
 
82
 
23
        const char *key1 = "\x6c\x1b\x99\x5f\xb9\xcd\x5f\x13\xcb\x04\x20\x0e\x5e\x1c\xa1\x0e";
83
        const char *key1 = "\x6c\x1b\x99\x5f\xb9\xcd\x5f\x13\xcb\x04\x20\x0e\x5e\x1c\xa1\x0e";
24
        const char *key2 = "\x67\xa8\xd6\x26\xb6\xdd\x45\x1b\x32\x7e\x22\x13\x15\xc2\x94\x37";
84
        const char *key2 = "\x67\xa8\xd6\x26\xb6\xdd\x45\x1b\x32\x7e\x22\x13\x15\xc2\x94\x37";
25
        const char *key_to_use;
85
        const char *key_to_use;
26
        char line_buffer[1024];
86
        char line_buffer[1024];
-
 
87
        char other_buffer[1024];
27
        char *file_pathname = NULL;
88
        char *file_pathname = NULL;
28
        int should_fix_b0rken_crypto = 1;
89
        int should_fix_b0rken_crypto = 1;
29
        unsigned char c;
90
        unsigned char c;
-
 
91
        int weird_count;
-
 
92
        int seed_backup;
30
        int seed;
93
        int seed;
31
        int len;
94
        int len;
32
        int i;
95
        int i;
-
 
96
        int j;
33
        FILE *fp;
97
        FILE *fp;
34
 
98
 
35
        // process command-line arguments
99
        // process command-line arguments
36
        for (i = 1; i < argc; i++)
100
        for (i = 1; i < argc; i++)
37
        {
101
        {
Line 43... Line 107...
43
 
107
 
44
        // consistency check
108
        // consistency check
45
        if (file_pathname == NULL)
109
        if (file_pathname == NULL)
46
        {
110
        {
47
                fprintf (stderr, "usage: %s [--dont-fix-b0rken-carmageddon-crypto] <FILE.TXT>\n", argv[0]);
111
                fprintf (stderr, "usage: %s [--dont-fix-b0rken-carmageddon-crypto] <FILE.TXT>\n", argv[0]);
48
                exit (1);
112
                exit (1);
49
        }
113
        }
50
 
114
 
51
        // open the Carmageddon data file to decrypt
115
        // open the Carmageddon data file to decrypt
52
        fp = fopen (file_pathname, "rb");
116
        fp = fopen (file_pathname, "rb");
53
        if (fp == NULL)
117
        if (fp == NULL)
54
        {
118
        {
55
                fprintf (stderr, "error: couldn't open '%s'\n", argv[1]);
119
                fprintf (stderr, "error: couldn't open '%s'\n", argv[1]);
56
                exit (1);
120
                exit (1);
57
        }
121
        }
58
 
122
 
59
        // read it line per line
123
        // read it line per line
60
        while (fgets (line_buffer, sizeof (line_buffer), fp) != NULL)
124
        while (fgets (line_buffer, sizeof (line_buffer), fp) != NULL)
61
        {
125
        {
62
                len = (int) strlen (line_buffer); // measure line length
126
                len = (int) strlen (line_buffer); // measure line length
63
 
127
 
Line 66... Line 130...
66
                {
130
                {
67
                        // chop off all trailing CR and LFs from the input data
131
                        // chop off all trailing CR and LFs from the input data
68
                        while ((len > 0) && ((line_buffer[len - 1] == '\r') || (line_buffer[len - 1] == '\n')))
132
                        while ((len > 0) && ((line_buffer[len - 1] == '\r') || (line_buffer[len - 1] == '\n')))
69
                                line_buffer[--len] = 0;
133
                                line_buffer[--len] = 0;
70
 
134
 
-
 
135
#if 1
71
                        // start with the first key and initialize the algorithm seed to the remainder of the length of data / 16
136
                        // start with the first key and initialize the algorithm seed to the remainder of the length of data / 16
72
                        key_to_use = key1;
137
                        key_to_use = key1;
73
                        seed = (len - 1) % 16;
138
                        seed = (len - 1) % 16;
74
 
139
 
75
                        // for each encrypted character...
140
                        // for each encrypted character...
76
                        for (i = 1; i < len; i++)
141
                        for (i = 1; i < len; i++)
77
                        {
142
                        {
78
                                c = line_buffer[i]; // quick access to character
143
                                c = line_buffer[i]; // quick access to character
79
 
144
 
80
                                // when loading game data, Carmageddon does not switch the XOR cypher when the comments start
145
                                // when loading game data, Carmageddon does not switch the XOR cypher when the comments start
81
                                if (should_fix_b0rken_crypto && (i >= 3) && (line_buffer[i - 2] == '/') && (line_buffer[i - 3] == '/'))
146
                                if ((key_to_use == key1) && should_fix_b0rken_crypto)
82
                                {
147
                                {
-
 
148
                                        if ((i >= 3) && (line_buffer[i - 2] == '/') && (line_buffer[i - 3] == '/')) // pattern: "//?"
-
 
149
                                        {
-
 
150
                                                seed_backup = seed;
-
 
151
/*
-
 
152
                                                weird_count = 0;
-
 
153
                                                for (j = i; j < len; j++)
-
 
154
                                                {
-
 
155
                                                        c = line_buffer[j];
-
 
156
                                                        DECODE_CHAR_WITH_KEY (c, key2); // decode character with the alternate key, but don't advance the seed
-
 
157
                                                        if (c > 0x7f)
-
 
158
                                                                weird_count++;
-
 
159
                                                        else if (c == ' ')
-
 
160
                                                                break;
-
 
161
                                                }
-
 
162
                                                if ((j < len) || (weird_count > (len - i) / 10))
-
 
163
                                                {
-
 
164
//                                                      fprintf (stderr, "===> Switching keys at char %d\n", i);
-
 
165
                                                        key_to_use = key2;
-
 
166
                                                }
-
 
167
/*/
83
                                        DECODE_CHAR_WITH_KEY (c, key2, 0); // decode character with the alternate key, but don't advance the seed
168
                                                DECODE_CHAR_WITH_KEY (c, key2); // decode character with the alternate key, but don't advance the seed
84
                                        if ((i > 4) || (c == ' ') || (c == '\t') || (c == '/'))
169
                                                if ((i > 4) || (c == ' ') || (c == '\t') || (c == '/'))
-
 
170
                                                {
-
 
171
//                                                      fprintf (stderr, "===> Switching keys at char %d\n", i);
85
                                                key_to_use = key2; // if this character looks sensible enough, it's time to swap keys
172
                                                        key_to_use = key2; // if this character looks sensible enough, it's time to swap keys
-
 
173
                                                }
-
 
174
 
-
 
175
 
86
                                        c = line_buffer[i]; // reload character after decryption attempt with alternate key
176
                                                c = line_buffer[i]; // reload character after decryption attempt with alternate key
-
 
177
                                                seed = seed_backup; // and restore seed
-
 
178
                                        }
87
                                }
179
                                }
88
 
180
 
89
                                DECODE_CHAR_WITH_KEY (c, key_to_use, 1); // decode character and advance the seed
181
                                DECODE_CHAR_WITH_KEY (c, key_to_use); // decode character and advance the seed
90
                                line_buffer[i - 1] = c; // write decoded character one position backwards to erase the '@' prefix
182
                                line_buffer[i - 1] = c; // write decoded character one position backwards to erase the '@' prefix
91
                        }
183
                        }
92
 
184
#else
-
 
185
i = len;
-
 
186
DecodeLine2 (&line_buffer[1]);
-
 
187
memmove (line_buffer, &line_buffer[1], len);
-
 
188
#endif
93
                        line_buffer[i - 1] = 0; // terminate the decrypted string properly
189
                        line_buffer[i - 1] = 0; // terminate the decrypted string properly
94
                }
190
                }
95
 
191
 
96
                // chop off all trailing CR and LFs from the decrypted data once again
192
                // chop off all trailing CR and LFs from the decrypted data once again
97
                while ((len > 0) && ((line_buffer[len - 1] == '\r') || (line_buffer[len - 1] == '\n')))
193
                while ((len > 0) && ((line_buffer[len - 1] == '\r') || (line_buffer[len - 1] == '\n')))