~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Source/Core/Core/Src/ARDecrypt.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Dolphin Emulator Project
 
2
// Licensed under GPLv2
 
3
// Refer to the license.txt file included.
 
4
 
 
5
// Most of the code in this file is from:
 
6
// GCNcrypt - Gamecube AR Crypto Program
 
7
// Copyright (C) 2003-2004 Parasyte
 
8
 
 
9
 
 
10
#include "ARDecrypt.h"
 
11
#include <algorithm>
 
12
 
 
13
#ifdef _WIN32
 
14
#include <windows.h>
 
15
#endif
 
16
 
 
17
namespace ActionReplay
 
18
{
 
19
 
 
20
// Alphanumeric filter for text<->bin conversion
 
21
const char *filter = "0123456789ABCDEFGHJKMNPQRTUVWXYZILOS";
 
22
 
 
23
u32 genseeds[0x20];
 
24
 
 
25
 
 
26
const u8 bitstringlen[0x08] = {
 
27
        0x06, 0x0A, 0x0C, 0x11, 0x11, 0x08, 0x07, 0x20,
 
28
};
 
29
 
 
30
const u8 gentable0[0x38] = {
 
31
        0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01,
 
32
        0x3A, 0x32, 0x2A, 0x22, 0x1A, 0x12, 0x0A, 0x02,
 
33
        0x3B, 0x33, 0x2B, 0x23, 0x1B, 0x13, 0x0B, 0x03,
 
34
        0x3C, 0x34, 0x2C, 0x24, 0x3F, 0x37, 0x2F, 0x27,
 
35
        0x1F, 0x17, 0x0F, 0x07, 0x3E, 0x36, 0x2E, 0x26,
 
36
        0x1E, 0x16, 0x0E, 0x06, 0x3D, 0x35, 0x2D, 0x25,
 
37
        0x1D, 0x15, 0x0D, 0x05, 0x1C, 0x14, 0x0C, 0x04,
 
38
};
 
39
const u8 gentable1[0x08] = {
 
40
        0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
 
41
};
 
42
const u8 gentable2[0x10] = {
 
43
        0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
 
44
        0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1C,
 
45
};
 
46
const u8 gentable3[0x30] = {
 
47
        0x0E, 0x11, 0x0B, 0x18, 0x01, 0x05, 0x03, 0x1C,
 
48
        0x0F, 0x06, 0x15, 0x0A, 0x17, 0x13, 0x0C, 0x04,
 
49
        0x1A, 0x08, 0x10, 0x07, 0x1B, 0x14, 0x0D, 0x02,
 
50
        0x29, 0x34, 0x1F, 0x25, 0x2F, 0x37, 0x1E, 0x28,
 
51
        0x33, 0x2D, 0x21, 0x30, 0x2C, 0x31, 0x27, 0x38,
 
52
        0x22, 0x35, 0x2E, 0x2A, 0x32, 0x24, 0x1D, 0x20,
 
53
};
 
54
 
 
55
const u16 crctable0[0x10] = {
 
56
        0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
 
57
        0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F,
 
58
};
 
59
const u16 crctable1[0x10] = {
 
60
        0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
 
61
        0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
 
62
};
 
63
 
 
64
const u8 gensubtable[0x08] = {
 
65
        0x34, 0x1C, 0x84, 0x9E, 0xFD, 0xA4, 0xB6, 0x7B,
 
66
};
 
67
 
 
68
 
 
69
const u32 table0[0x40] = {
 
70
        0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
 
71
        0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
 
72
        0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
 
73
        0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
 
74
        0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
 
75
        0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
 
76
        0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
 
77
        0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004,
 
78
};
 
79
const u32 table1[0x40] = {
 
80
        0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
 
81
        0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
 
82
        0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
 
83
        0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
 
84
        0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
 
85
        0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
 
86
        0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
 
87
        0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000,
 
88
};
 
89
const u32 table2[0x40] = {
 
90
        0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
 
91
        0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
 
92
        0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
 
93
        0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
 
94
        0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
 
95
        0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
 
96
        0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
 
97
        0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200,
 
98
};
 
99
const u32 table3[0x40] = {
 
100
        0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
 
101
        0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
 
102
        0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
 
103
        0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
 
104
        0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
 
105
        0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
 
106
        0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
 
107
        0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080,
 
108
};
 
109
const u32 table4[0x40] = {
 
110
        0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
 
111
        0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
 
112
        0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
 
113
        0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
 
114
        0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
 
115
        0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
 
116
        0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
 
117
        0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100,
 
118
};
 
119
const u32 table5[0x40] = {
 
120
        0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
 
121
        0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
 
122
        0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
 
123
        0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
 
124
        0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
 
125
        0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
 
126
        0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
 
127
        0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010,
 
128
};
 
129
const u32 table6[0x40] = {
 
130
        0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
 
131
        0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
 
132
        0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
 
133
        0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
 
134
        0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
 
135
        0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
 
136
        0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
 
137
        0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002,
 
138
};
 
139
const u32 table7[0x40] = {
 
140
        0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
 
141
        0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
 
142
        0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
 
143
        0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
 
144
        0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
 
145
        0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
 
146
        0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
 
147
        0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000,
 
148
};
 
149
 
 
150
 
 
151
void generateseeds(u32 *seeds, const u8 *seedtable, u8 doreverse)
 
152
{
 
153
        int i,j;
 
154
        u32 tmp3;
 
155
        u8 array0[0x38],array1[0x38],array2[0x08];
 
156
        u8 tmp,tmp2;
 
157
 
 
158
        i = 0;
 
159
        while (i < 0x38)
 
160
        {
 
161
                tmp = (gentable0[i] - 1);
 
162
                array0[i++] = ((u32)(0-(seedtable[tmp>>3] & gentable1[tmp&7])) >> 31);
 
163
        }
 
164
 
 
165
        i = 0;
 
166
        while (i < 0x10)
 
167
        {
 
168
                memset(array2,0,8);
 
169
                tmp2 = gentable2[i];
 
170
 
 
171
                for (j = 0; j < 0x38; j++)
 
172
                {
 
173
                        tmp = (tmp2+j);
 
174
 
 
175
                        if (j > 0x1B)
 
176
                        {
 
177
                                if (tmp > 0x37) tmp-=0x1C;
 
178
                        }
 
179
                        else if (tmp > 0x1B) tmp-=0x1C;
 
180
 
 
181
                        array1[j] = array0[tmp];
 
182
                }
 
183
                for (j = 0; j < 0x30; j++)
 
184
                {
 
185
                        if (!array1[gentable3[j]-1]) continue;
 
186
                        tmp = (((j*0x2AAB)>>16) - (j>>0x1F));
 
187
                        array2[tmp] |= (gentable1[j-(tmp*6)]>>2);
 
188
                }
 
189
                seeds[i<<1] = ((array2[0]<<24)|(array2[2]<<16)|(array2[4]<<8)|array2[6]);
 
190
                seeds[(i<<1)+1] = ((array2[1]<<24)|(array2[3]<<16)|(array2[5]<<8)|array2[7]);
 
191
                i++;
 
192
        }
 
193
 
 
194
        if (!doreverse)
 
195
        {
 
196
                j = 0x1F;
 
197
                for (i = 0; i < 16; i+=2)
 
198
                {
 
199
                        tmp3 = seeds[i];
 
200
                        seeds[i] = seeds[j-1];
 
201
                        seeds[j-1] = tmp3;
 
202
 
 
203
                        tmp3 = seeds[i+1];
 
204
                        seeds[i+1] = seeds[j];
 
205
                        seeds[j] = tmp3;
 
206
                        j-=2;
 
207
                }
 
208
        }
 
209
}
 
210
 
 
211
void buildseeds()
 
212
{
 
213
        generateseeds(genseeds,gensubtable,0);
 
214
}
 
215
 
 
216
void getcode(u32 *src, u32 *addr, u32 *val)
 
217
{
 
218
        *addr = Common::swap32(src[0]);
 
219
        *val = Common::swap32(src[1]);
 
220
}
 
221
 
 
222
void setcode(u32 *dst, u32 addr, u32 val)
 
223
{
 
224
        dst[0] = Common::swap32(addr);
 
225
        dst[1] = Common::swap32(val);
 
226
}
 
227
 
 
228
u16 gencrc16(u32 *codes, u16 size)
 
229
{
 
230
        u16 ret=0;
 
231
        u8 tmp=0,tmp2;
 
232
        int i;
 
233
 
 
234
        if (size > 0)
 
235
        {
 
236
                while (tmp < size)
 
237
                {
 
238
                        for (i = 0; i < 4; i++)
 
239
                        {
 
240
                                tmp2 = ((codes[tmp] >> (i<<3))^ret);
 
241
                                ret = ((crctable0[(tmp2>>4)&0x0F]^crctable1[tmp2&0x0F])^(ret>>8));
 
242
                        }
 
243
                        tmp++;
 
244
                }
 
245
        }
 
246
        return ret;
 
247
}
 
248
 
 
249
u8 verifycode(u32 *codes, u16 size)
 
250
{
 
251
        u16 tmp;
 
252
 
 
253
        tmp = gencrc16(codes,size);
 
254
        return (((tmp>>12)^(tmp>>8)^(tmp>>4)^tmp)&0x0F);
 
255
}
 
256
 
 
257
void unscramble1(u32 *addr, u32 *val)
 
258
{
 
259
        u32 tmp;
 
260
 
 
261
        *val = _rotl(*val,4);
 
262
 
 
263
        tmp = ((*addr^*val)&0xF0F0F0F0);
 
264
        *addr ^= tmp;
 
265
        *val = _rotr((*val^tmp),0x14);
 
266
 
 
267
        tmp = ((*addr^*val)&0xFFFF0000);
 
268
        *addr ^= tmp;
 
269
        *val = _rotr((*val^tmp),0x12);
 
270
 
 
271
        tmp = ((*addr^*val)&0x33333333);
 
272
        *addr ^= tmp;
 
273
        *val = _rotr((*val^tmp),6);
 
274
 
 
275
        tmp = ((*addr^*val)&0x00FF00FF);
 
276
        *addr ^= tmp;
 
277
        *val = _rotl((*val^tmp),9);
 
278
 
 
279
        tmp = ((*addr^*val)&0xAAAAAAAA);
 
280
        *addr = _rotl((*addr^tmp),1);
 
281
        *val ^= tmp;
 
282
}
 
283
 
 
284
void unscramble2(u32 *addr, u32 *val)
 
285
{
 
286
        u32 tmp;
 
287
 
 
288
        *val = _rotr(*val,1);
 
289
 
 
290
        tmp = ((*addr^*val)&0xAAAAAAAA);
 
291
        *val ^= tmp;
 
292
        *addr = _rotr((*addr^tmp),9);
 
293
 
 
294
        tmp = ((*addr^*val)&0x00FF00FF);
 
295
        *val ^= tmp;
 
296
        *addr = _rotl((*addr^tmp),6);
 
297
 
 
298
        tmp = ((*addr^*val)&0x33333333);
 
299
        *val ^= tmp;
 
300
        *addr = _rotl((*addr^tmp),0x12);
 
301
 
 
302
        tmp = ((*addr^*val)&0xFFFF0000);
 
303
        *val ^= tmp;
 
304
        *addr = _rotl((*addr^tmp),0x14);
 
305
 
 
306
        tmp = ((*addr^*val)&0xF0F0F0F0);
 
307
        *val ^= tmp;
 
308
        *addr = _rotr((*addr^tmp),4);
 
309
}
 
310
 
 
311
void decryptcode(u32 *seeds, u32 *code)
 
312
{
 
313
        u32 addr,val;
 
314
        u32 tmp,tmp2;
 
315
        int i=0;
 
316
 
 
317
        getcode(code,&addr,&val);
 
318
        unscramble1(&addr,&val);
 
319
        while (i < 32)
 
320
        {
 
321
                tmp = (_rotr(val,4)^seeds[i++]);
 
322
                tmp2 = (val^seeds[i++]);
 
323
                addr ^= (table6[tmp&0x3F]^table4[(tmp>>8)&0x3F]^table2[(tmp>>16)&0x3F]^table0[(tmp>>24)&0x3F]^table7[tmp2&0x3F]^table5[(tmp2>>8)&0x3F]^table3[(tmp2>>16)&0x3F]^table1[(tmp2>>24)&0x3F]);
 
324
 
 
325
                tmp = (_rotr(addr,4)^seeds[i++]);
 
326
                tmp2 = (addr^seeds[i++]);
 
327
                val ^= (table6[tmp&0x3F]^table4[(tmp>>8)&0x3F]^table2[(tmp>>16)&0x3F]^table0[(tmp>>24)&0x3F]^table7[tmp2&0x3F]^table5[(tmp2>>8)&0x3F]^table3[(tmp2>>16)&0x3F]^table1[(tmp2>>24)&0x3F]);
 
328
        }
 
329
        unscramble2(&addr,&val);
 
330
        setcode(code,val,addr);
 
331
}
 
332
 
 
333
bool getbitstring(u32 *ctrl, u32 *out, u8 len)
 
334
{
 
335
        u32 tmp=(ctrl[0]+(ctrl[1]<<2));
 
336
 
 
337
        *out = 0;
 
338
        while (len--)
 
339
        {
 
340
                if (ctrl[2] > 0x1F)
 
341
                {
 
342
                        ctrl[2] = 0;
 
343
                        ctrl[1]++;
 
344
                        tmp = (ctrl[0]+(ctrl[1]<<2));
 
345
                }
 
346
                if (ctrl[1] >= ctrl[3]) return false;
 
347
                *out = ((*out<<1) | ((tmp >> (0x1F-ctrl[2])) & 1));
 
348
                ctrl[2]++;
 
349
        }
 
350
        return true;
 
351
}
 
352
 
 
353
bool batchdecrypt(u32 *codes, u16 size)
 
354
{
 
355
        u32 tmp,*ptr=codes;
 
356
        u32 tmparray[4] = { 0 },tmparray2[8] = { 0 };
 
357
 
 
358
        // Not required
 
359
        //if (size & 1) return 0;
 
360
        //if (!size) return 0;
 
361
 
 
362
        tmp = (size >> 1);
 
363
        while (tmp--)
 
364
        {
 
365
                decryptcode(genseeds,ptr);
 
366
                ptr+=2;
 
367
        }
 
368
 
 
369
        tmparray[0] = *codes;
 
370
        tmparray[1] = 0;
 
371
        tmparray[2] = 4; // Skip crc
 
372
        tmparray[3] = size;
 
373
        getbitstring(tmparray,tmparray2+1,11);  // Game id
 
374
        getbitstring(tmparray,tmparray2+2,17);  // Code id
 
375
        getbitstring(tmparray,tmparray2+3,1);   // Master code
 
376
        getbitstring(tmparray,tmparray2+4,1);   // Unknown
 
377
        getbitstring(tmparray,tmparray2+5,2);   // Region
 
378
 
 
379
        // Grab gameid and region from the last decrypted code
 
380
        // Maybe check this against dolphin's GameID? - "code is for wrong game" type msg
 
381
        //gameid = tmparray2[1];
 
382
        //region = tmparray2[5];
 
383
 
 
384
        tmp = codes[0];
 
385
        codes[0] &= 0x0FFFFFFF;
 
386
        if ((tmp>>28) != verifycode(codes,size)) return false;
 
387
 
 
388
        return true;
 
389
 
 
390
        // Unfinished (so says Parasyte :p )
 
391
}
 
392
 
 
393
int GetVal(const char *flt, char chr)
 
394
{
 
395
        int ret = (int)(strchr(flt,chr) - flt);
 
396
        switch (ret)
 
397
        {
 
398
        case 32: // 'I'
 
399
        case 33: // 'L'
 
400
                ret = 1;
 
401
                break;
 
402
        case 34: // 'O'
 
403
                ret = 0;
 
404
                break;
 
405
        case 35: // 'S'
 
406
                ret = 5;
 
407
                break;
 
408
        }
 
409
        return ret;
 
410
}
 
411
 
 
412
int alphatobin(u32 *dst, std::vector<std::string> alpha, int size)
 
413
{
 
414
        int i,j=0,k;
 
415
        int ret=0,org=(size+1);
 
416
        u32 bin[2];
 
417
        u8 parity;
 
418
 
 
419
        while (size)
 
420
        {
 
421
                bin[0]=0;
 
422
                for (i = 0; i < 6; i++)
 
423
                {
 
424
                        bin[0] |= (GetVal(filter,alpha[j>>1][i]) << (((5-i)*5)+2));
 
425
                }
 
426
                bin[0] |= (GetVal(filter,alpha[j>>1][6]) >> 3);
 
427
                dst[j++] = bin[0];
 
428
 
 
429
                bin[1]=0;
 
430
                for (i = 0; i < 6; i++)
 
431
                {
 
432
                        bin[1] |= (GetVal(filter,alpha[j>>1][i+6]) << (((5-i)*5)+4));
 
433
                }
 
434
                bin[1] |= (GetVal(filter,alpha[j>>1][12]) >> 1);
 
435
                dst[j++] = bin[1];
 
436
 
 
437
                //verify parity bit
 
438
                k=0;
 
439
                parity=0;
 
440
                for (i = 0; i < 64; i++)
 
441
                {
 
442
                        if (i == 32) k++;
 
443
                        parity ^= (bin[k] >> (i-(k<<5)));
 
444
                }
 
445
                if ((parity&1) != (GetVal(filter,alpha[(j-2)>>1][12])&1)) ret=(org-size);
 
446
 
 
447
                size--;
 
448
        }
 
449
 
 
450
        return ret;
 
451
}
 
452
 
 
453
void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry> &ops)
 
454
{
 
455
        // The almighty buildseeds() function!! without this, the crypto routines are useless
 
456
        buildseeds();
 
457
 
 
458
        u32 uCodes[1200];
 
459
        u32 i,ret;
 
460
 
 
461
        for(i = 0; i < vCodes.size(); ++i)
 
462
        {
 
463
                transform(vCodes[i].begin(), vCodes[i].end(), vCodes[i].begin(), toupper);
 
464
                //PanicAlert("Encrypted AR Code\n%s", vCodes[i].c_str());
 
465
        }
 
466
 
 
467
        if ((ret=alphatobin(uCodes, vCodes, (int)vCodes.size())))
 
468
        {
 
469
                PanicAlertT("Action Replay Code Decryption Error:\nParity Check Failed\n\nCulprit Code:\n%s", vCodes[ret].c_str());
 
470
                batchdecrypt(uCodes, (u16)vCodes.size()<<1);
 
471
        }
 
472
        else if (!batchdecrypt(uCodes, (u16)vCodes.size()<<1))
 
473
        {
 
474
                // Commented out since we just send the code anyways and hope for the best XD
 
475
                //PanicAlert("Action Replay Code Decryption Error:\nCRC Check Failed\n\n"
 
476
                //      "First Code in Block(should be verification code):\n%s", vCodes[0].c_str());
 
477
 
 
478
                for (i = 0; i < (vCodes.size()<<1); i+=2)
 
479
                {
 
480
                        AREntry op;
 
481
                        op.cmd_addr = uCodes[i];
 
482
                        op.value = uCodes[i+1];
 
483
                        ops.push_back(op);
 
484
                        //PanicAlert("Decrypted AR Code without verification code:\n%08X %08X", uCodes[i], uCodes[i+1]);
 
485
                }
 
486
        }
 
487
        else
 
488
        {
 
489
                // Skip passing the verification code back
 
490
                for (i = 2; i < (vCodes.size()<<1); i+=2)
 
491
                {
 
492
                        AREntry op;
 
493
                        op.cmd_addr = uCodes[i];
 
494
                        op.value = uCodes[i+1];
 
495
                        ops.push_back(op);
 
496
                        //PanicAlert("Decrypted AR Code:\n%08X %08X", uCodes[i], uCodes[i+1]);
 
497
                }
 
498
        }
 
499
}
 
500
 
 
501
} //namespace ActionReplay