rlm@1
|
1 #include <cstdio>
|
rlm@1
|
2 #include <cctype>
|
rlm@1
|
3 #include <cstring>
|
rlm@1
|
4
|
rlm@1
|
5 #include "../common/System.h"
|
rlm@1
|
6 #include "../common/Util.h"
|
rlm@1
|
7 #include "../NLS.h"
|
rlm@1
|
8 #include "GBACheats.h"
|
rlm@1
|
9 #include "GBA.h"
|
rlm@1
|
10 #include "GBAinline.h"
|
rlm@1
|
11 #include "GBAGlobals.h"
|
rlm@1
|
12
|
rlm@1
|
13 /**
|
rlm@1
|
14 * Gameshark code types:
|
rlm@1
|
15 *
|
rlm@1
|
16 * NNNNNNNN 001DC0DE - ID code for the game (game 4 character name) from ROM
|
rlm@1
|
17 * DEADFACE XXXXXXXX - changes decryption seeds
|
rlm@1
|
18 * 0AAAAAAA 000000YY - 8-bit constant write
|
rlm@1
|
19 * 1AAAAAAA 0000YYYY - 16-bit constant write
|
rlm@1
|
20 * 2AAAAAAA YYYYYYYY - 32-bit constant write
|
rlm@1
|
21 * 3AAAAAAA YYYYYYYY - ??
|
rlm@1
|
22 * 6AAAAAAA 0000YYYY - 16-bit ROM Patch (address >> 1)
|
rlm@1
|
23 * 6AAAAAAA 1000YYYY - 16-bit ROM Patch ? (address >> 1)
|
rlm@1
|
24 * 6AAAAAAA 2000YYYY - 16-bit ROM Patch ? (address >> 1)
|
rlm@1
|
25 * 8A1AAAAA 000000YY - 8-bit button write
|
rlm@1
|
26 * 8A2AAAAA 0000YYYY - 16-bit button write
|
rlm@1
|
27 * 8A3AAAAA YYYYYYYY - 32-bit button write
|
rlm@1
|
28 * 80F00000 0000YYYY - button slow motion
|
rlm@1
|
29 * DAAAAAAA 0000YYYY - if address contains 16-bit value enable next code
|
rlm@1
|
30 * FAAAAAAA 0000YYYY - Master code function
|
rlm@1
|
31 *
|
rlm@1
|
32 * CodeBreaker codes types:
|
rlm@1
|
33 *
|
rlm@1
|
34 * 0000AAAA 000Y - Game CRC (Y are flags: 8 - CRC, 2 - DI)
|
rlm@1
|
35 * 1AAAAAAA YYYY - Master Code function (store address at ((YYYY << 0x16)
|
rlm@1
|
36 * + 0x08000100))
|
rlm@1
|
37 * 2AAAAAAA YYYY - 16-bit or
|
rlm@1
|
38 * 3AAAAAAA YYYY - 8-bit constant write
|
rlm@1
|
39 * 4AAAAAAA YYYY - Slide code
|
rlm@1
|
40 * XXXXCCCC IIII (C is count and I is address increment, X is value incr.)
|
rlm@1
|
41 * 5AAAAAAA CCCC - Super code (Write bytes to address, CCCC is count)
|
rlm@1
|
42 * BBBBBBBB BBBB
|
rlm@1
|
43 * 6AAAAAAA YYYY - 16-bit and
|
rlm@1
|
44 * 7AAAAAAA YYYY - if address contains 16-bit value enable next code
|
rlm@1
|
45 * 8AAAAAAA YYYY - 16-bit constant write
|
rlm@1
|
46 * 9AAAAAAA YYYY - change decryption (when first code only?)
|
rlm@1
|
47 * AAAAAAAA YYYY - if address does not contain 16-bit value enable next code
|
rlm@1
|
48 * BAAAAAAA YYYY - if 16-bit < YYYY
|
rlm@1
|
49 * CAAAAAAA YYYY - if 16-bit > YYYY
|
rlm@1
|
50 * D0000020 YYYY - if button keys equal value enable next code
|
rlm@1
|
51 * EAAAAAAA YYYY - increase value stored in address
|
rlm@1
|
52 */
|
rlm@1
|
53 #define UNKNOWN_CODE -1
|
rlm@1
|
54 #define INT_8_BIT_WRITE 0
|
rlm@1
|
55 #define INT_16_BIT_WRITE 1
|
rlm@1
|
56 #define INT_32_BIT_WRITE 2
|
rlm@1
|
57 #define GSA_16_BIT_ROM_PATCH 3
|
rlm@1
|
58 #define GSA_8_BIT_GS_WRITE 4
|
rlm@1
|
59 #define GSA_16_BIT_GS_WRITE 5
|
rlm@1
|
60 #define GSA_32_BIT_GS_WRITE 6
|
rlm@1
|
61 #define CBA_IF_KEYS_PRESSED 7
|
rlm@1
|
62 #define CBA_IF_TRUE 8
|
rlm@1
|
63 #define CBA_SLIDE_CODE 9
|
rlm@1
|
64 #define CBA_IF_FALSE 10
|
rlm@1
|
65 #define CBA_AND 11
|
rlm@1
|
66 #define GSA_8_BIT_GS_WRITE2 12
|
rlm@1
|
67 #define GSA_16_BIT_GS_WRITE2 13
|
rlm@1
|
68 #define GSA_32_BIT_GS_WRITE2 14
|
rlm@1
|
69 #define GSA_16_BIT_ROM_PATCH2 15
|
rlm@1
|
70 #define GSA_8_BIT_SLIDE 16
|
rlm@1
|
71 #define GSA_16_BIT_SLIDE 17
|
rlm@1
|
72 #define GSA_32_BIT_SLIDE 18
|
rlm@1
|
73 #define GSA_8_BIT_IF_TRUE 19
|
rlm@1
|
74 #define GSA_32_BIT_IF_TRUE 20
|
rlm@1
|
75 #define GSA_8_BIT_IF_FALSE 21
|
rlm@1
|
76 #define GSA_32_BIT_IF_FALSE 22
|
rlm@1
|
77 #define GSA_8_BIT_FILL 23
|
rlm@1
|
78 #define GSA_16_BIT_FILL 24
|
rlm@1
|
79 #define GSA_8_BIT_IF_TRUE2 25
|
rlm@1
|
80 #define GSA_16_BIT_IF_TRUE2 26
|
rlm@1
|
81 #define GSA_32_BIT_IF_TRUE2 27
|
rlm@1
|
82 #define GSA_8_BIT_IF_FALSE2 28
|
rlm@1
|
83 #define GSA_16_BIT_IF_FALSE2 29
|
rlm@1
|
84 #define GSA_32_BIT_IF_FALSE2 30
|
rlm@1
|
85 #define GSA_SLOWDOWN 31
|
rlm@1
|
86 #define CBA_ADD 32
|
rlm@1
|
87 #define CBA_OR 33
|
rlm@1
|
88 #define CBA_LT 34
|
rlm@1
|
89 #define CBA_GT 35
|
rlm@1
|
90 #define CBA_SUPER 36
|
rlm@1
|
91
|
rlm@1
|
92 CheatsData cheatsList[100];
|
rlm@1
|
93 int cheatsNumber = 0;
|
rlm@1
|
94
|
rlm@1
|
95 u8 cheatsCBASeedBuffer[0x30];
|
rlm@1
|
96 u32 cheatsCBASeed[4];
|
rlm@1
|
97 u32 cheatsCBATemporaryValue = 0;
|
rlm@1
|
98 u16 cheatsCBATable[256];
|
rlm@1
|
99 bool cheatsCBATableGenerated = false;
|
rlm@1
|
100
|
rlm@1
|
101 u8 cheatsCBACurrentSeed[12] = {
|
rlm@1
|
102 0x00, 0x00, 0x00, 0x00,
|
rlm@1
|
103 0x00, 0x00, 0x00, 0x00,
|
rlm@1
|
104 0x00, 0x00, 0x00, 0x00
|
rlm@1
|
105 };
|
rlm@1
|
106
|
rlm@1
|
107 #define CHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9'))
|
rlm@1
|
108
|
rlm@1
|
109 #define CHEAT_PATCH_ROM_16BIT(a, v) \
|
rlm@1
|
110 WRITE16LE(((u16 *)&rom[(a) & 0x1ffffff]), v);
|
rlm@1
|
111
|
rlm@1
|
112 static bool isMultilineWithData(int i)
|
rlm@1
|
113 {
|
rlm@1
|
114 // we consider it a multiline code if it has more than one line of data
|
rlm@1
|
115 // otherwise, it can still be considered a single code
|
rlm@1
|
116 if (i < cheatsNumber && i >= 0)
|
rlm@1
|
117 switch (cheatsList[i].size)
|
rlm@1
|
118 {
|
rlm@1
|
119 case INT_8_BIT_WRITE:
|
rlm@1
|
120 case INT_16_BIT_WRITE:
|
rlm@1
|
121 case INT_32_BIT_WRITE:
|
rlm@1
|
122 case GSA_16_BIT_ROM_PATCH:
|
rlm@1
|
123 case GSA_8_BIT_GS_WRITE:
|
rlm@1
|
124 case GSA_16_BIT_GS_WRITE:
|
rlm@1
|
125 case GSA_32_BIT_GS_WRITE:
|
rlm@1
|
126 case CBA_AND:
|
rlm@1
|
127 case CBA_IF_KEYS_PRESSED:
|
rlm@1
|
128 case CBA_IF_TRUE:
|
rlm@1
|
129 case CBA_IF_FALSE:
|
rlm@1
|
130 case GSA_8_BIT_IF_TRUE:
|
rlm@1
|
131 case GSA_32_BIT_IF_TRUE:
|
rlm@1
|
132 case GSA_8_BIT_IF_FALSE:
|
rlm@1
|
133 case GSA_32_BIT_IF_FALSE:
|
rlm@1
|
134 case GSA_8_BIT_FILL:
|
rlm@1
|
135 case GSA_16_BIT_FILL:
|
rlm@1
|
136 case GSA_8_BIT_IF_TRUE2:
|
rlm@1
|
137 case GSA_16_BIT_IF_TRUE2:
|
rlm@1
|
138 case GSA_32_BIT_IF_TRUE2:
|
rlm@1
|
139 case GSA_8_BIT_IF_FALSE2:
|
rlm@1
|
140 case GSA_16_BIT_IF_FALSE2:
|
rlm@1
|
141 case GSA_32_BIT_IF_FALSE2:
|
rlm@1
|
142 case GSA_SLOWDOWN:
|
rlm@1
|
143 case CBA_ADD:
|
rlm@1
|
144 case CBA_OR:
|
rlm@1
|
145 return false;
|
rlm@1
|
146 // the codes below have two lines of data
|
rlm@1
|
147 case CBA_SLIDE_CODE:
|
rlm@1
|
148 case GSA_8_BIT_GS_WRITE2:
|
rlm@1
|
149 case GSA_16_BIT_GS_WRITE2:
|
rlm@1
|
150 case GSA_32_BIT_GS_WRITE2:
|
rlm@1
|
151 case GSA_16_BIT_ROM_PATCH2:
|
rlm@1
|
152 case GSA_8_BIT_SLIDE:
|
rlm@1
|
153 case GSA_16_BIT_SLIDE:
|
rlm@1
|
154 case GSA_32_BIT_SLIDE:
|
rlm@1
|
155 case CBA_LT:
|
rlm@1
|
156 case CBA_GT:
|
rlm@1
|
157 case CBA_SUPER:
|
rlm@1
|
158 return true;
|
rlm@1
|
159 }
|
rlm@1
|
160 return false;
|
rlm@1
|
161 }
|
rlm@1
|
162
|
rlm@1
|
163 static int getCodeLength(int num)
|
rlm@1
|
164 {
|
rlm@1
|
165 if (num >= cheatsNumber || num < 0)
|
rlm@1
|
166 return 1;
|
rlm@1
|
167
|
rlm@1
|
168 // this is for all the codes that are true multiline
|
rlm@1
|
169 switch (cheatsList[num].size)
|
rlm@1
|
170 {
|
rlm@1
|
171 case INT_8_BIT_WRITE:
|
rlm@1
|
172 case INT_16_BIT_WRITE:
|
rlm@1
|
173 case INT_32_BIT_WRITE:
|
rlm@1
|
174 case GSA_16_BIT_ROM_PATCH:
|
rlm@1
|
175 case GSA_8_BIT_GS_WRITE:
|
rlm@1
|
176 case GSA_16_BIT_GS_WRITE:
|
rlm@1
|
177 case GSA_32_BIT_GS_WRITE:
|
rlm@1
|
178 case CBA_AND:
|
rlm@1
|
179 case GSA_8_BIT_FILL:
|
rlm@1
|
180 case GSA_16_BIT_FILL:
|
rlm@1
|
181 case GSA_SLOWDOWN:
|
rlm@1
|
182 case CBA_ADD:
|
rlm@1
|
183 case CBA_OR:
|
rlm@1
|
184 return 1;
|
rlm@1
|
185 case CBA_IF_KEYS_PRESSED:
|
rlm@1
|
186 case CBA_IF_TRUE:
|
rlm@1
|
187 case CBA_IF_FALSE:
|
rlm@1
|
188 case CBA_SLIDE_CODE:
|
rlm@1
|
189 case GSA_8_BIT_GS_WRITE2:
|
rlm@1
|
190 case GSA_16_BIT_GS_WRITE2:
|
rlm@1
|
191 case GSA_32_BIT_GS_WRITE2:
|
rlm@1
|
192 case GSA_16_BIT_ROM_PATCH2:
|
rlm@1
|
193 case GSA_8_BIT_SLIDE:
|
rlm@1
|
194 case GSA_16_BIT_SLIDE:
|
rlm@1
|
195 case GSA_32_BIT_SLIDE:
|
rlm@1
|
196 case GSA_8_BIT_IF_TRUE:
|
rlm@1
|
197 case GSA_32_BIT_IF_TRUE:
|
rlm@1
|
198 case GSA_8_BIT_IF_FALSE:
|
rlm@1
|
199 case GSA_32_BIT_IF_FALSE:
|
rlm@1
|
200 case CBA_LT:
|
rlm@1
|
201 case CBA_GT:
|
rlm@1
|
202 return 2;
|
rlm@1
|
203 case GSA_8_BIT_IF_TRUE2:
|
rlm@1
|
204 case GSA_16_BIT_IF_TRUE2:
|
rlm@1
|
205 case GSA_32_BIT_IF_TRUE2:
|
rlm@1
|
206 case GSA_8_BIT_IF_FALSE2:
|
rlm@1
|
207 case GSA_16_BIT_IF_FALSE2:
|
rlm@1
|
208 case GSA_32_BIT_IF_FALSE2:
|
rlm@1
|
209 return 3;
|
rlm@1
|
210 case CBA_SUPER:
|
rlm@1
|
211 return (cheatsList[num].value+5)/6;
|
rlm@1
|
212 }
|
rlm@1
|
213 return 1;
|
rlm@1
|
214 }
|
rlm@1
|
215
|
rlm@1
|
216 int cheatsCheckKeys(u32 keys, u32 extended)
|
rlm@1
|
217 {
|
rlm@1
|
218 int ticks = 0;
|
rlm@1
|
219 for (int i = 0; i < cheatsNumber; i++)
|
rlm@1
|
220 {
|
rlm@1
|
221 if (!cheatsList[i].enabled)
|
rlm@1
|
222 {
|
rlm@1
|
223 // make sure we skip other lines in this code
|
rlm@1
|
224 i += getCodeLength(i)-1;
|
rlm@1
|
225 continue;
|
rlm@1
|
226 }
|
rlm@1
|
227 switch (cheatsList[i].size)
|
rlm@1
|
228 {
|
rlm@1
|
229 case INT_8_BIT_WRITE:
|
rlm@1
|
230 CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
231 break;
|
rlm@1
|
232 case INT_16_BIT_WRITE:
|
rlm@1
|
233 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
234 break;
|
rlm@1
|
235 case INT_32_BIT_WRITE:
|
rlm@1
|
236 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
237 break;
|
rlm@1
|
238 case GSA_16_BIT_ROM_PATCH:
|
rlm@1
|
239 if ((cheatsList[i].status & 1) == 0)
|
rlm@1
|
240 {
|
rlm@1
|
241 if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
242 {
|
rlm@1
|
243 cheatsList[i].oldValue = CPUReadHalfWord(cheatsList[i].address);
|
rlm@1
|
244 cheatsList[i].status |= 1;
|
rlm@1
|
245 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
246 }
|
rlm@1
|
247 }
|
rlm@1
|
248 break;
|
rlm@1
|
249 case GSA_8_BIT_GS_WRITE:
|
rlm@1
|
250 if (extended & 4)
|
rlm@1
|
251 {
|
rlm@1
|
252 CPUWriteByte(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
253 }
|
rlm@1
|
254 break;
|
rlm@1
|
255 case GSA_16_BIT_GS_WRITE:
|
rlm@1
|
256 if (extended & 4)
|
rlm@1
|
257 {
|
rlm@1
|
258 CPUWriteHalfWord(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
259 }
|
rlm@1
|
260 break;
|
rlm@1
|
261 case GSA_32_BIT_GS_WRITE:
|
rlm@1
|
262 if (extended & 4)
|
rlm@1
|
263 {
|
rlm@1
|
264 CPUWriteMemory(cheatsList[i].address, cheatsList[i].value);
|
rlm@1
|
265 }
|
rlm@1
|
266 break;
|
rlm@1
|
267 case CBA_IF_KEYS_PRESSED:
|
rlm@1
|
268 {
|
rlm@1
|
269 u16 value = cheatsList[i].value;
|
rlm@1
|
270 u32 addr = cheatsList[i].address;
|
rlm@1
|
271 if ((addr & 0x30) == 0x20)
|
rlm@1
|
272 {
|
rlm@1
|
273 if ((keys & value) != value)
|
rlm@1
|
274 {
|
rlm@1
|
275 i++;
|
rlm@1
|
276 }
|
rlm@1
|
277 }
|
rlm@1
|
278 else if ((addr & 0x30) == 0x10)
|
rlm@1
|
279 {
|
rlm@1
|
280 if ((keys & value) == value)
|
rlm@1
|
281 {
|
rlm@1
|
282 i++;
|
rlm@1
|
283 }
|
rlm@1
|
284 }
|
rlm@1
|
285 break;
|
rlm@1
|
286 }
|
rlm@1
|
287 case CBA_IF_TRUE:
|
rlm@1
|
288 if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
289 {
|
rlm@1
|
290 i++;
|
rlm@1
|
291 }
|
rlm@1
|
292 break;
|
rlm@1
|
293 case CBA_SLIDE_CODE:
|
rlm@1
|
294 {
|
rlm@1
|
295 u32 address = cheatsList[i].address;
|
rlm@1
|
296 u16 value = cheatsList[i].value;
|
rlm@1
|
297 i++;
|
rlm@1
|
298 if (i < cheatsNumber)
|
rlm@1
|
299 {
|
rlm@1
|
300 int count = (cheatsList[i].address & 0xFFFF);
|
rlm@1
|
301 u16 vinc = (cheatsList[i].address >> 16) & 0xFFFF;
|
rlm@1
|
302 int inc = cheatsList[i].value;
|
rlm@1
|
303
|
rlm@1
|
304 for (int x = 0; x < count; x++)
|
rlm@1
|
305 {
|
rlm@1
|
306 CPUWriteHalfWord(address, value);
|
rlm@1
|
307 address += inc;
|
rlm@1
|
308 value += vinc;
|
rlm@1
|
309 }
|
rlm@1
|
310 }
|
rlm@1
|
311 break;
|
rlm@1
|
312 }
|
rlm@1
|
313 case CBA_IF_FALSE:
|
rlm@1
|
314 if (CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value)
|
rlm@1
|
315 {
|
rlm@1
|
316 i++;
|
rlm@1
|
317 }
|
rlm@1
|
318 break;
|
rlm@1
|
319 case CBA_AND:
|
rlm@1
|
320 CPUWriteHalfWord(cheatsList[i].address,
|
rlm@1
|
321 CPUReadHalfWord(cheatsList[i].address) &
|
rlm@1
|
322 cheatsList[i].value);
|
rlm@1
|
323 break;
|
rlm@1
|
324 case GSA_8_BIT_GS_WRITE2:
|
rlm@1
|
325 i++;
|
rlm@1
|
326 if (i < cheatsNumber)
|
rlm@1
|
327 {
|
rlm@1
|
328 if (extended & 4)
|
rlm@1
|
329 {
|
rlm@1
|
330 CPUWriteByte(cheatsList[i-1].value, cheatsList[i].address);
|
rlm@1
|
331 }
|
rlm@1
|
332 }
|
rlm@1
|
333 break;
|
rlm@1
|
334 case GSA_16_BIT_GS_WRITE2:
|
rlm@1
|
335 i++;
|
rlm@1
|
336 if (i < cheatsNumber)
|
rlm@1
|
337 {
|
rlm@1
|
338 if (extended & 4)
|
rlm@1
|
339 {
|
rlm@1
|
340 CPUWriteHalfWord(cheatsList[i-1].value, cheatsList[i].address);
|
rlm@1
|
341 }
|
rlm@1
|
342 }
|
rlm@1
|
343 break;
|
rlm@1
|
344 case GSA_32_BIT_GS_WRITE2:
|
rlm@1
|
345 i++;
|
rlm@1
|
346 if (i < cheatsNumber)
|
rlm@1
|
347 {
|
rlm@1
|
348 if (extended & 4)
|
rlm@1
|
349 {
|
rlm@1
|
350 CPUWriteMemory(cheatsList[i-1].value, cheatsList[i].address);
|
rlm@1
|
351 }
|
rlm@1
|
352 }
|
rlm@1
|
353 break;
|
rlm@1
|
354 case GSA_16_BIT_ROM_PATCH2:
|
rlm@1
|
355 i++;
|
rlm@1
|
356 if (i < cheatsNumber)
|
rlm@1
|
357 {
|
rlm@1
|
358 if ((cheatsList[i-1].status & 1) == 0)
|
rlm@1
|
359 {
|
rlm@1
|
360 u32 addr = ((cheatsList[i-1].value & 0x00FFFFFF) << 1) + 0x8000000;
|
rlm@1
|
361 if (CPUReadHalfWord(addr) != (cheatsList[i].address & 0xFFFF))
|
rlm@1
|
362 {
|
rlm@1
|
363 cheatsList[i-1].oldValue = CPUReadHalfWord(addr);
|
rlm@1
|
364 cheatsList[i-1].status |= 1;
|
rlm@1
|
365 CHEAT_PATCH_ROM_16BIT(addr, cheatsList[i].address & 0xFFFF);
|
rlm@1
|
366 }
|
rlm@1
|
367 }
|
rlm@1
|
368 }
|
rlm@1
|
369 break;
|
rlm@1
|
370 case GSA_8_BIT_SLIDE:
|
rlm@1
|
371 i++;
|
rlm@1
|
372 if (i < cheatsNumber)
|
rlm@1
|
373 {
|
rlm@1
|
374 u32 addr = cheatsList[i-1].value;
|
rlm@1
|
375 u8 value = cheatsList[i].address;
|
rlm@1
|
376 int vinc = (cheatsList[i].value >> 24) & 255;
|
rlm@1
|
377 int count = (cheatsList[i].value >> 16) & 255;
|
rlm@1
|
378 int ainc = (cheatsList[i].value & 0xffff);
|
rlm@1
|
379 while (count > 0)
|
rlm@1
|
380 {
|
rlm@1
|
381 CPUWriteByte(addr, value);
|
rlm@1
|
382 value += vinc;
|
rlm@1
|
383 addr += ainc;
|
rlm@1
|
384 count--;
|
rlm@1
|
385 }
|
rlm@1
|
386 }
|
rlm@1
|
387 break;
|
rlm@1
|
388 case GSA_16_BIT_SLIDE:
|
rlm@1
|
389 i++;
|
rlm@1
|
390 if (i < cheatsNumber)
|
rlm@1
|
391 {
|
rlm@1
|
392 u32 addr = cheatsList[i-1].value;
|
rlm@1
|
393 u16 value = cheatsList[i].address;
|
rlm@1
|
394 int vinc = (cheatsList[i].value >> 24) & 255;
|
rlm@1
|
395 int count = (cheatsList[i].value >> 16) & 255;
|
rlm@1
|
396 int ainc = (cheatsList[i].value & 0xffff)*2;
|
rlm@1
|
397 while (count > 0)
|
rlm@1
|
398 {
|
rlm@1
|
399 CPUWriteHalfWord(addr, value);
|
rlm@1
|
400 value += vinc;
|
rlm@1
|
401 addr += ainc;
|
rlm@1
|
402 count--;
|
rlm@1
|
403 }
|
rlm@1
|
404 }
|
rlm@1
|
405 break;
|
rlm@1
|
406 case GSA_32_BIT_SLIDE:
|
rlm@1
|
407 i++;
|
rlm@1
|
408 if (i < cheatsNumber)
|
rlm@1
|
409 {
|
rlm@1
|
410 u32 addr = cheatsList[i-1].value;
|
rlm@1
|
411 u32 value = cheatsList[i].address;
|
rlm@1
|
412 int vinc = (cheatsList[i].value >> 24) & 255;
|
rlm@1
|
413 int count = (cheatsList[i].value >> 16) & 255;
|
rlm@1
|
414 int ainc = (cheatsList[i].value & 0xffff)*4;
|
rlm@1
|
415 while (count > 0)
|
rlm@1
|
416 {
|
rlm@1
|
417 CPUWriteMemory(addr, value);
|
rlm@1
|
418 value += vinc;
|
rlm@1
|
419 addr += ainc;
|
rlm@1
|
420 count--;
|
rlm@1
|
421 }
|
rlm@1
|
422 }
|
rlm@1
|
423 break;
|
rlm@1
|
424 case GSA_8_BIT_IF_TRUE:
|
rlm@1
|
425 if (CPUReadByte(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
426 {
|
rlm@1
|
427 i++;
|
rlm@1
|
428 }
|
rlm@1
|
429 break;
|
rlm@1
|
430 case GSA_32_BIT_IF_TRUE:
|
rlm@1
|
431 if (CPUReadMemory(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
432 {
|
rlm@1
|
433 i++;
|
rlm@1
|
434 }
|
rlm@1
|
435 break;
|
rlm@1
|
436 case GSA_8_BIT_IF_FALSE:
|
rlm@1
|
437 if (CPUReadByte(cheatsList[i].address) == cheatsList[i].value)
|
rlm@1
|
438 {
|
rlm@1
|
439 i++;
|
rlm@1
|
440 }
|
rlm@1
|
441 break;
|
rlm@1
|
442 case GSA_32_BIT_IF_FALSE:
|
rlm@1
|
443 if (CPUReadMemory(cheatsList[i].address) == cheatsList[i].value)
|
rlm@1
|
444 {
|
rlm@1
|
445 i++;
|
rlm@1
|
446 }
|
rlm@1
|
447 break;
|
rlm@1
|
448 case GSA_8_BIT_FILL:
|
rlm@1
|
449 {
|
rlm@1
|
450 u32 addr = cheatsList[i].address;
|
rlm@1
|
451 u8 v = cheatsList[i].value & 0xff;
|
rlm@1
|
452 u32 end = addr + (cheatsList[i].value >> 8);
|
rlm@1
|
453 do
|
rlm@1
|
454 {
|
rlm@1
|
455 CPUWriteByte(addr, v);
|
rlm@1
|
456 addr++;
|
rlm@1
|
457 }
|
rlm@1
|
458 while (addr <= end);
|
rlm@1
|
459 break;
|
rlm@1
|
460 }
|
rlm@1
|
461 case GSA_16_BIT_FILL:
|
rlm@1
|
462 {
|
rlm@1
|
463 u32 addr = cheatsList[i].address;
|
rlm@1
|
464 u16 v = cheatsList[i].value & 0xffff;
|
rlm@1
|
465 u32 end = addr + ((cheatsList[i].value >> 16) << 1);
|
rlm@1
|
466 do
|
rlm@1
|
467 {
|
rlm@1
|
468 CPUWriteHalfWord(addr, v);
|
rlm@1
|
469 addr += 2;
|
rlm@1
|
470 }
|
rlm@1
|
471 while (addr <= end);
|
rlm@1
|
472 break;
|
rlm@1
|
473 }
|
rlm@1
|
474 case GSA_8_BIT_IF_TRUE2:
|
rlm@1
|
475 if (CPUReadByte(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
476 {
|
rlm@1
|
477 i += 2;
|
rlm@1
|
478 }
|
rlm@1
|
479 break;
|
rlm@1
|
480 case GSA_16_BIT_IF_TRUE2:
|
rlm@1
|
481 if (CPUReadHalfWord(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
482 {
|
rlm@1
|
483 i += 2;
|
rlm@1
|
484 }
|
rlm@1
|
485 break;
|
rlm@1
|
486 case GSA_32_BIT_IF_TRUE2:
|
rlm@1
|
487 if (CPUReadMemory(cheatsList[i].address) != cheatsList[i].value)
|
rlm@1
|
488 {
|
rlm@1
|
489 i += 2;
|
rlm@1
|
490 }
|
rlm@1
|
491 break;
|
rlm@1
|
492 case GSA_8_BIT_IF_FALSE2:
|
rlm@1
|
493 if (CPUReadByte(cheatsList[i].address) == cheatsList[i].value)
|
rlm@1
|
494 {
|
rlm@1
|
495 i += 2;
|
rlm@1
|
496 }
|
rlm@1
|
497 break;
|
rlm@1
|
498 case GSA_16_BIT_IF_FALSE2:
|
rlm@1
|
499 if (CPUReadHalfWord(cheatsList[i].address) == cheatsList[i].value)
|
rlm@1
|
500 {
|
rlm@1
|
501 i += 2;
|
rlm@1
|
502 }
|
rlm@1
|
503 break;
|
rlm@1
|
504 case GSA_32_BIT_IF_FALSE2:
|
rlm@1
|
505 if (CPUReadMemory(cheatsList[i].address) == cheatsList[i].value)
|
rlm@1
|
506 {
|
rlm@1
|
507 i += 2;
|
rlm@1
|
508 }
|
rlm@1
|
509 break;
|
rlm@1
|
510 case GSA_SLOWDOWN:
|
rlm@1
|
511 // check if button was pressed and released, if so toggle our state
|
rlm@1
|
512 if ((cheatsList[i].status & 4) && !(extended & 4))
|
rlm@1
|
513 cheatsList[i].status ^= 1;
|
rlm@1
|
514 if (extended & 4)
|
rlm@1
|
515 cheatsList[i].status |= 4;
|
rlm@1
|
516 else
|
rlm@1
|
517 cheatsList[i].status &= ~4;
|
rlm@1
|
518
|
rlm@1
|
519 if (cheatsList[i].status & 1)
|
rlm@1
|
520 ticks += 2*256*((cheatsList[i].value >> 8) & 255);
|
rlm@1
|
521 break;
|
rlm@1
|
522 case CBA_ADD:
|
rlm@1
|
523 CPUWriteHalfWord(cheatsList[i].address,
|
rlm@1
|
524 CPUReadHalfWord(cheatsList[i].address) +
|
rlm@1
|
525 (u16)cheatsList[i].value);
|
rlm@1
|
526 break;
|
rlm@1
|
527 case CBA_OR:
|
rlm@1
|
528 CPUWriteHalfWord(cheatsList[i].address,
|
rlm@1
|
529 CPUReadHalfWord(cheatsList[i].address) |
|
rlm@1
|
530 cheatsList[i].value);
|
rlm@1
|
531 break;
|
rlm@1
|
532 case CBA_LT:
|
rlm@1
|
533 if (CPUReadHalfWord(cheatsList[i].address) >= cheatsList[i].value)
|
rlm@1
|
534 i++;
|
rlm@1
|
535 break;
|
rlm@1
|
536 case CBA_GT:
|
rlm@1
|
537 if (CPUReadHalfWord(cheatsList[i].address) <= cheatsList[i].value)
|
rlm@1
|
538 i++;
|
rlm@1
|
539 break;
|
rlm@1
|
540 case CBA_SUPER:
|
rlm@1
|
541 {
|
rlm@1
|
542 int count = 2*cheatsList[i].value;
|
rlm@1
|
543 u32 address = cheatsList[i].address;
|
rlm@1
|
544 for (int x = 0; x < count; x++)
|
rlm@1
|
545 {
|
rlm@1
|
546 u8 b;
|
rlm@1
|
547 int res = x % 6;
|
rlm@1
|
548 if (res < 4)
|
rlm@1
|
549 b = (cheatsList[i].address >> (24-8*res)) & 0xFF;
|
rlm@1
|
550 else
|
rlm@1
|
551 b = (cheatsList[i].value >> (8 - 8*(res-4))) & 0x0FF;
|
rlm@1
|
552 CPUWriteByte(address, b);
|
rlm@1
|
553 address++;
|
rlm@1
|
554 if (x && !res)
|
rlm@1
|
555 i++;
|
rlm@1
|
556 }
|
rlm@1
|
557 if (count % 6)
|
rlm@1
|
558 i++;
|
rlm@1
|
559 break;
|
rlm@1
|
560 }
|
rlm@1
|
561 }
|
rlm@1
|
562 }
|
rlm@1
|
563 return ticks;
|
rlm@1
|
564 }
|
rlm@1
|
565
|
rlm@1
|
566 void cheatsAdd(const char *codeStr,
|
rlm@1
|
567 const char *desc,
|
rlm@1
|
568 u32 address,
|
rlm@1
|
569 u32 value,
|
rlm@1
|
570 int code,
|
rlm@1
|
571 int size)
|
rlm@1
|
572 {
|
rlm@1
|
573 if (cheatsNumber < 100)
|
rlm@1
|
574 {
|
rlm@1
|
575 int x = cheatsNumber;
|
rlm@1
|
576 cheatsList[x].code = code;
|
rlm@1
|
577 cheatsList[x].size = size;
|
rlm@1
|
578 cheatsList[x].address = address;
|
rlm@1
|
579 cheatsList[x].value = value;
|
rlm@1
|
580 strcpy(cheatsList[x].codestring, codeStr);
|
rlm@1
|
581 strcpy(cheatsList[x].desc, desc);
|
rlm@1
|
582 cheatsList[x].enabled = true;
|
rlm@1
|
583 cheatsList[x].status = 0;
|
rlm@1
|
584
|
rlm@1
|
585 // we only store the old value for this simple codes. ROM patching
|
rlm@1
|
586 // is taken care when it actually patches the ROM
|
rlm@1
|
587 switch (cheatsList[x].size)
|
rlm@1
|
588 {
|
rlm@1
|
589 case INT_8_BIT_WRITE:
|
rlm@1
|
590 cheatsList[x].oldValue = CPUReadByte(address);
|
rlm@1
|
591 break;
|
rlm@1
|
592 case INT_16_BIT_WRITE:
|
rlm@1
|
593 cheatsList[x].oldValue = CPUReadHalfWord(address);
|
rlm@1
|
594 break;
|
rlm@1
|
595 case INT_32_BIT_WRITE:
|
rlm@1
|
596 cheatsList[x].oldValue = CPUReadMemory(address);
|
rlm@1
|
597 break;
|
rlm@1
|
598 }
|
rlm@1
|
599 cheatsNumber++;
|
rlm@1
|
600 }
|
rlm@1
|
601 }
|
rlm@1
|
602
|
rlm@1
|
603 void cheatsDelete(int number, bool restore)
|
rlm@1
|
604 {
|
rlm@1
|
605 if (number < cheatsNumber && number >= 0)
|
rlm@1
|
606 {
|
rlm@1
|
607 int x = number;
|
rlm@1
|
608
|
rlm@1
|
609 if (restore)
|
rlm@1
|
610 {
|
rlm@1
|
611 switch (cheatsList[x].size)
|
rlm@1
|
612 {
|
rlm@1
|
613 case INT_8_BIT_WRITE:
|
rlm@1
|
614 CPUWriteByte(cheatsList[x].address, (u8)cheatsList[x].oldValue);
|
rlm@1
|
615 break;
|
rlm@1
|
616 case INT_16_BIT_WRITE:
|
rlm@1
|
617 CPUWriteHalfWord(cheatsList[x].address, (u16)cheatsList[x].oldValue);
|
rlm@1
|
618 break;
|
rlm@1
|
619 case INT_32_BIT_WRITE:
|
rlm@1
|
620 CPUWriteMemory(cheatsList[x].address, cheatsList[x].oldValue);
|
rlm@1
|
621 break;
|
rlm@1
|
622 case GSA_16_BIT_ROM_PATCH:
|
rlm@1
|
623 if (cheatsList[x].status & 1)
|
rlm@1
|
624 {
|
rlm@1
|
625 cheatsList[x].status &= ~1;
|
rlm@1
|
626 CHEAT_PATCH_ROM_16BIT(cheatsList[x].address,
|
rlm@1
|
627 cheatsList[x].oldValue);
|
rlm@1
|
628 }
|
rlm@1
|
629 break;
|
rlm@1
|
630 case GSA_16_BIT_ROM_PATCH2:
|
rlm@1
|
631 if (cheatsList[x].status & 1)
|
rlm@1
|
632 {
|
rlm@1
|
633 cheatsList[x].status &= ~1;
|
rlm@1
|
634 CHEAT_PATCH_ROM_16BIT(((cheatsList[x].value & 0x00FFFFFF) << 1)+
|
rlm@1
|
635 0x8000000,
|
rlm@1
|
636 cheatsList[x].oldValue);
|
rlm@1
|
637 }
|
rlm@1
|
638 break;
|
rlm@1
|
639 }
|
rlm@1
|
640 }
|
rlm@1
|
641 if ((x+1) < cheatsNumber)
|
rlm@1
|
642 {
|
rlm@1
|
643 memcpy(&cheatsList[x], &cheatsList[x+1], sizeof(CheatsData)*
|
rlm@1
|
644 (cheatsNumber-x-1));
|
rlm@1
|
645 }
|
rlm@1
|
646 cheatsNumber--;
|
rlm@1
|
647 }
|
rlm@1
|
648 }
|
rlm@1
|
649
|
rlm@1
|
650 void cheatsDeleteAll(bool restore)
|
rlm@1
|
651 {
|
rlm@1
|
652 for (int i = cheatsNumber-1; i >= 0; i--)
|
rlm@1
|
653 {
|
rlm@1
|
654 cheatsDelete(i, restore);
|
rlm@1
|
655 }
|
rlm@1
|
656 }
|
rlm@1
|
657
|
rlm@1
|
658 void cheatsEnable(int i)
|
rlm@1
|
659 {
|
rlm@1
|
660 if (i >= 0 && i < cheatsNumber)
|
rlm@1
|
661 {
|
rlm@1
|
662 cheatsList[i].enabled = true;
|
rlm@1
|
663 }
|
rlm@1
|
664 }
|
rlm@1
|
665
|
rlm@1
|
666 void cheatsDisable(int i)
|
rlm@1
|
667 {
|
rlm@1
|
668 if (i >= 0 && i < cheatsNumber)
|
rlm@1
|
669 {
|
rlm@1
|
670 switch (cheatsList[i].size)
|
rlm@1
|
671 {
|
rlm@1
|
672 case GSA_16_BIT_ROM_PATCH:
|
rlm@1
|
673 if (cheatsList[i].status & 1)
|
rlm@1
|
674 {
|
rlm@1
|
675 cheatsList[i].status &= ~1;
|
rlm@1
|
676 CHEAT_PATCH_ROM_16BIT(cheatsList[i].address,
|
rlm@1
|
677 cheatsList[i].oldValue);
|
rlm@1
|
678 }
|
rlm@1
|
679 break;
|
rlm@1
|
680 case GSA_16_BIT_ROM_PATCH2:
|
rlm@1
|
681 if (cheatsList[i].status & 1)
|
rlm@1
|
682 {
|
rlm@1
|
683 cheatsList[i].status &= ~1;
|
rlm@1
|
684 CHEAT_PATCH_ROM_16BIT(((cheatsList[i].value & 0x00FFFFFF) << 1)+
|
rlm@1
|
685 0x8000000,
|
rlm@1
|
686 cheatsList[i].oldValue);
|
rlm@1
|
687 }
|
rlm@1
|
688 break;
|
rlm@1
|
689 }
|
rlm@1
|
690 cheatsList[i].enabled = false;
|
rlm@1
|
691 }
|
rlm@1
|
692 }
|
rlm@1
|
693
|
rlm@1
|
694 bool cheatsVerifyCheatCode(const char *code, const char *desc)
|
rlm@1
|
695 {
|
rlm@1
|
696 int len = strlen(code);
|
rlm@1
|
697 if (len != 11 && len != 13 && len != 17)
|
rlm@1
|
698 {
|
rlm@1
|
699 systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
|
rlm@1
|
700 return false;
|
rlm@1
|
701 }
|
rlm@1
|
702
|
rlm@1
|
703 if (code[8] != ':')
|
rlm@1
|
704 {
|
rlm@1
|
705 systemMessage(MSG_INVALID_CHEAT_CODE, N_("Invalid cheat code '%s'"), code);
|
rlm@1
|
706 return false;
|
rlm@1
|
707 }
|
rlm@1
|
708
|
rlm@1
|
709 int i;
|
rlm@1
|
710 for (i = 0; i < 8; i++)
|
rlm@1
|
711 {
|
rlm@1
|
712 if (!CHEAT_IS_HEX(code[i]))
|
rlm@1
|
713 {
|
rlm@1
|
714 // wrong cheat
|
rlm@1
|
715 systemMessage(MSG_INVALID_CHEAT_CODE,
|
rlm@1
|
716 N_("Invalid cheat code '%s'"), code);
|
rlm@1
|
717 return false;
|
rlm@1
|
718 }
|
rlm@1
|
719 }
|
rlm@1
|
720 for (i = 9; i < len; i++)
|
rlm@1
|
721 {
|
rlm@1
|
722 if (!CHEAT_IS_HEX(code[i]))
|
rlm@1
|
723 {
|
rlm@1
|
724 // wrong cheat
|
rlm@1
|
725 systemMessage(MSG_INVALID_CHEAT_CODE,
|
rlm@1
|
726 N_("Invalid cheat code '%s'"), code);
|
rlm@1
|
727 return false;
|
rlm@1
|
728 }
|
rlm@1
|
729 }
|
rlm@1
|
730
|
rlm@1
|
731 u32 address = 0;
|
rlm@1
|
732 u32 value = 0;
|
rlm@1
|
733
|
rlm@1
|
734 char buffer[10];
|
rlm@1
|
735 strncpy(buffer, code, 8);
|
rlm@1
|
736 buffer[8] = 0;
|
rlm@1
|
737 sscanf(buffer, "%x", &address);
|
rlm@1
|
738
|
rlm@1
|
739 switch (address >> 24)
|
rlm@1
|
740 {
|
rlm@1
|
741 case 2:
|
rlm@1
|
742 case 3:
|
rlm@1
|
743 break;
|
rlm@1
|
744 default:
|
rlm@1
|
745 systemMessage(MSG_INVALID_CHEAT_CODE_ADDRESS,
|
rlm@1
|
746 N_("Invalid cheat code address: %08x"),
|
rlm@1
|
747 address);
|
rlm@1
|
748 return false;
|
rlm@1
|
749 }
|
rlm@1
|
750
|
rlm@1
|
751 strncpy(buffer, &code[9], 8);
|
rlm@1
|
752 sscanf(buffer, "%x", &value);
|
rlm@1
|
753 int type = 0;
|
rlm@1
|
754 if (len == 13)
|
rlm@1
|
755 type = 1;
|
rlm@1
|
756 if (len == 17)
|
rlm@1
|
757 type = 2;
|
rlm@1
|
758 cheatsAdd(code, desc, address, value, type, type);
|
rlm@1
|
759 return true;
|
rlm@1
|
760 }
|
rlm@1
|
761
|
rlm@1
|
762 void cheatsAddCheatCode(const char *code, const char *desc)
|
rlm@1
|
763 {
|
rlm@1
|
764 cheatsVerifyCheatCode(code, desc);
|
rlm@1
|
765 }
|
rlm@1
|
766
|
rlm@1
|
767 void cheatsDecryptGSACode(u32& address, u32& value, bool v3)
|
rlm@1
|
768 {
|
rlm@1
|
769 u32 rollingseed = 0xC6EF3720;
|
rlm@1
|
770 u32 seeds_v1[] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 };
|
rlm@1
|
771 u32 seeds_v3[] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 };
|
rlm@1
|
772 u32 *seeds = v3 ? seeds_v3 : seeds_v1;
|
rlm@1
|
773
|
rlm@1
|
774 int bitsleft = 32;
|
rlm@1
|
775 while (bitsleft > 0)
|
rlm@1
|
776 {
|
rlm@1
|
777 value -= ((((address << 4) + seeds[2]) ^ (address + rollingseed)) ^
|
rlm@1
|
778 ((address >> 5) + seeds[3]));
|
rlm@1
|
779 address -= ((((value << 4) + seeds[0]) ^ (value + rollingseed)) ^
|
rlm@1
|
780 ((value >> 5) + seeds[1]));
|
rlm@1
|
781 rollingseed -= 0x9E3779B9;
|
rlm@1
|
782 bitsleft--;
|
rlm@1
|
783 }
|
rlm@1
|
784 }
|
rlm@1
|
785
|
rlm@1
|
786 void cheatsAddGSACode(const char *code, const char *desc, bool v3)
|
rlm@1
|
787 {
|
rlm@1
|
788 if (strlen(code) != 16)
|
rlm@1
|
789 {
|
rlm@1
|
790 // wrong cheat
|
rlm@1
|
791 systemMessage(MSG_INVALID_GSA_CODE,
|
rlm@1
|
792 N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
|
rlm@1
|
793 return;
|
rlm@1
|
794 }
|
rlm@1
|
795
|
rlm@1
|
796 int i;
|
rlm@1
|
797 for (i = 0; i < 16; i++)
|
rlm@1
|
798 {
|
rlm@1
|
799 if (!CHEAT_IS_HEX(code[i]))
|
rlm@1
|
800 {
|
rlm@1
|
801 // wrong cheat
|
rlm@1
|
802 systemMessage(MSG_INVALID_GSA_CODE,
|
rlm@1
|
803 N_("Invalid GSA code. Format is XXXXXXXXYYYYYYYY"));
|
rlm@1
|
804 return;
|
rlm@1
|
805 }
|
rlm@1
|
806 }
|
rlm@1
|
807
|
rlm@1
|
808 char buffer[10];
|
rlm@1
|
809 strncpy(buffer, code, 8);
|
rlm@1
|
810 buffer[8] = 0;
|
rlm@1
|
811 u32 address;
|
rlm@1
|
812 sscanf(buffer, "%x", &address);
|
rlm@1
|
813 strncpy(buffer, &code[8], 8);
|
rlm@1
|
814 buffer[8] = 0;
|
rlm@1
|
815 u32 value;
|
rlm@1
|
816 sscanf(buffer, "%x", &value);
|
rlm@1
|
817
|
rlm@1
|
818 cheatsDecryptGSACode(address, value, v3);
|
rlm@1
|
819
|
rlm@1
|
820 if (value == 0x1DC0DE)
|
rlm@1
|
821 {
|
rlm@1
|
822 u32 gamecode = READ32LE(((u32 *)&rom[0xac]));
|
rlm@1
|
823 if (gamecode != address)
|
rlm@1
|
824 {
|
rlm@1
|
825 char buffer[5];
|
rlm@1
|
826 *((u32 *)buffer) = address;
|
rlm@1
|
827 buffer[4] = 0;
|
rlm@1
|
828 char buffer2[5];
|
rlm@1
|
829 *((u32 *)buffer2) = READ32LE(((u32 *)&rom[0xac]));
|
rlm@1
|
830 buffer2[4] = 0;
|
rlm@1
|
831 systemMessage(MSG_GBA_CODE_WARNING,
|
rlm@1
|
832 N_("Warning: cheats are for game %s. Current game is %s.\nCodes may not work correctly."),
|
rlm@1
|
833 buffer, buffer2);
|
rlm@1
|
834 }
|
rlm@1
|
835 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, v3 ? 257 : 256,
|
rlm@1
|
836 UNKNOWN_CODE);
|
rlm@1
|
837 return;
|
rlm@1
|
838 }
|
rlm@1
|
839 if (isMultilineWithData(cheatsNumber-1))
|
rlm@1
|
840 {
|
rlm@1
|
841 cheatsAdd(code, desc, address, value, v3 ? 257 : 256, UNKNOWN_CODE);
|
rlm@1
|
842 return;
|
rlm@1
|
843 }
|
rlm@1
|
844 if (v3)
|
rlm@1
|
845 {
|
rlm@1
|
846 int type = (address >> 25) & 127;
|
rlm@1
|
847 u32 addr = (address & 0x00F00000) << 4 | (address & 0x0003FFFF);
|
rlm@1
|
848 switch (type)
|
rlm@1
|
849 {
|
rlm@1
|
850 case 0x00:
|
rlm@1
|
851 if (address == 0)
|
rlm@1
|
852 {
|
rlm@1
|
853 type = (value >> 25) & 127;
|
rlm@1
|
854 addr = (value & 0x00F00000) << 4 | (value & 0x0003FFFF);
|
rlm@1
|
855 switch (type)
|
rlm@1
|
856 {
|
rlm@1
|
857 case 0x04:
|
rlm@1
|
858 cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_SLOWDOWN);
|
rlm@1
|
859 break;
|
rlm@1
|
860 case 0x08:
|
rlm@1
|
861 cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_GS_WRITE2);
|
rlm@1
|
862 break;
|
rlm@1
|
863 case 0x09:
|
rlm@1
|
864 cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_GS_WRITE2);
|
rlm@1
|
865 break;
|
rlm@1
|
866 case 0x0a:
|
rlm@1
|
867 cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_GS_WRITE2);
|
rlm@1
|
868 break;
|
rlm@1
|
869 case 0x0c:
|
rlm@1
|
870 case 0x0d:
|
rlm@1
|
871 case 0x0e:
|
rlm@1
|
872 case 0x0f:
|
rlm@1
|
873 cheatsAdd(code, desc, 0, value & 0x00FFFFFF, 257, GSA_16_BIT_ROM_PATCH2);
|
rlm@1
|
874 break;
|
rlm@1
|
875 case 0x40:
|
rlm@1
|
876 cheatsAdd(code, desc, 0, addr, 257, GSA_8_BIT_SLIDE);
|
rlm@1
|
877 break;
|
rlm@1
|
878 case 0x41:
|
rlm@1
|
879 cheatsAdd(code, desc, 0, addr, 257, GSA_16_BIT_SLIDE);
|
rlm@1
|
880 break;
|
rlm@1
|
881 case 0x42:
|
rlm@1
|
882 cheatsAdd(code, desc, 0, addr, 257, GSA_32_BIT_SLIDE);
|
rlm@1
|
883 break;
|
rlm@1
|
884 default:
|
rlm@1
|
885 cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE);
|
rlm@1
|
886 break;
|
rlm@1
|
887 }
|
rlm@1
|
888 }
|
rlm@1
|
889 else
|
rlm@1
|
890 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_FILL);
|
rlm@1
|
891 break;
|
rlm@1
|
892 case 0x01:
|
rlm@1
|
893 cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_FILL);
|
rlm@1
|
894 break;
|
rlm@1
|
895 case 0x02:
|
rlm@1
|
896 cheatsAdd(code, desc, addr, value, 257, INT_32_BIT_WRITE);
|
rlm@1
|
897 break;
|
rlm@1
|
898 case 0x04:
|
rlm@1
|
899 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE);
|
rlm@1
|
900 break;
|
rlm@1
|
901 case 0x05:
|
rlm@1
|
902 cheatsAdd(code, desc, addr, value, 257, CBA_IF_TRUE);
|
rlm@1
|
903 break;
|
rlm@1
|
904 case 0x06:
|
rlm@1
|
905 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE);
|
rlm@1
|
906 break;
|
rlm@1
|
907 case 0x08:
|
rlm@1
|
908 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE);
|
rlm@1
|
909 break;
|
rlm@1
|
910 case 0x09:
|
rlm@1
|
911 cheatsAdd(code, desc, addr, value, 257, CBA_IF_FALSE);
|
rlm@1
|
912 break;
|
rlm@1
|
913 case 0x0a:
|
rlm@1
|
914 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE);
|
rlm@1
|
915 break;
|
rlm@1
|
916 case 0x24:
|
rlm@1
|
917 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_TRUE2);
|
rlm@1
|
918 break;
|
rlm@1
|
919 case 0x25:
|
rlm@1
|
920 cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_TRUE2);
|
rlm@1
|
921 break;
|
rlm@1
|
922 case 0x26:
|
rlm@1
|
923 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_TRUE2);
|
rlm@1
|
924 break;
|
rlm@1
|
925 case 0x28:
|
rlm@1
|
926 cheatsAdd(code, desc, addr, value, 257, GSA_8_BIT_IF_FALSE2);
|
rlm@1
|
927 break;
|
rlm@1
|
928 case 0x29:
|
rlm@1
|
929 cheatsAdd(code, desc, addr, value, 257, GSA_16_BIT_IF_FALSE2);
|
rlm@1
|
930 break;
|
rlm@1
|
931 case 0x2a:
|
rlm@1
|
932 cheatsAdd(code, desc, addr, value, 257, GSA_32_BIT_IF_FALSE2);
|
rlm@1
|
933 break;
|
rlm@1
|
934 default:
|
rlm@1
|
935 cheatsAdd(code, desc, address, value, 257, UNKNOWN_CODE);
|
rlm@1
|
936 break;
|
rlm@1
|
937 }
|
rlm@1
|
938 }
|
rlm@1
|
939 else
|
rlm@1
|
940 {
|
rlm@1
|
941 int type = (address >> 28) & 15;
|
rlm@1
|
942 switch (type)
|
rlm@1
|
943 {
|
rlm@1
|
944 case 0:
|
rlm@1
|
945 case 1:
|
rlm@1
|
946 case 2:
|
rlm@1
|
947 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256, type);
|
rlm@1
|
948 break;
|
rlm@1
|
949 case 6:
|
rlm@1
|
950 address <<= 1;
|
rlm@1
|
951 type = (address >> 28) & 15;
|
rlm@1
|
952 if (type == 0x0c)
|
rlm@1
|
953 {
|
rlm@1
|
954 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256,
|
rlm@1
|
955 GSA_16_BIT_ROM_PATCH);
|
rlm@1
|
956 break;
|
rlm@1
|
957 }
|
rlm@1
|
958 // unsupported code
|
rlm@1
|
959 cheatsAdd(code, desc, address, value, 256,
|
rlm@1
|
960 UNKNOWN_CODE);
|
rlm@1
|
961 break;
|
rlm@1
|
962 case 8:
|
rlm@1
|
963 switch ((address >> 20) & 15)
|
rlm@1
|
964 {
|
rlm@1
|
965 case 1:
|
rlm@1
|
966 cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256,
|
rlm@1
|
967 GSA_8_BIT_GS_WRITE);
|
rlm@1
|
968 break;
|
rlm@1
|
969 case 2:
|
rlm@1
|
970 cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256,
|
rlm@1
|
971 GSA_16_BIT_GS_WRITE);
|
rlm@1
|
972 break;
|
rlm@1
|
973 case 3:
|
rlm@1
|
974 cheatsAdd(code, desc, address & 0x0F0FFFFF, value, 256,
|
rlm@1
|
975 GSA_32_BIT_GS_WRITE);
|
rlm@1
|
976 case 15:
|
rlm@1
|
977 cheatsAdd(code, desc, 0, value & 0xFF00, 256, GSA_SLOWDOWN);
|
rlm@1
|
978 break;
|
rlm@1
|
979 default:
|
rlm@1
|
980 // unsupported code
|
rlm@1
|
981 cheatsAdd(code, desc, address, value, 256,
|
rlm@1
|
982 UNKNOWN_CODE);
|
rlm@1
|
983 break;
|
rlm@1
|
984 }
|
rlm@1
|
985 break;
|
rlm@1
|
986 case 0x0d:
|
rlm@1
|
987 if (address != 0xDEADFACE)
|
rlm@1
|
988 {
|
rlm@1
|
989 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 256,
|
rlm@1
|
990 CBA_IF_TRUE);
|
rlm@1
|
991 }
|
rlm@1
|
992 else
|
rlm@1
|
993 cheatsAdd(code, desc, address, value, 256,
|
rlm@1
|
994 UNKNOWN_CODE);
|
rlm@1
|
995 break;
|
rlm@1
|
996 default:
|
rlm@1
|
997 // unsupported code
|
rlm@1
|
998 cheatsAdd(code, desc, address, value, 256,
|
rlm@1
|
999 UNKNOWN_CODE);
|
rlm@1
|
1000 break;
|
rlm@1
|
1001 }
|
rlm@1
|
1002 }
|
rlm@1
|
1003 }
|
rlm@1
|
1004
|
rlm@1
|
1005 bool cheatsImportGSACodeFile(const char *name, int game, bool v3)
|
rlm@1
|
1006 {
|
rlm@1
|
1007 FILE *f = fopen(name, "rb");
|
rlm@1
|
1008 if (!f)
|
rlm@1
|
1009 return false;
|
rlm@1
|
1010
|
rlm@1
|
1011 int games = 0;
|
rlm@1
|
1012 int len = 0;
|
rlm@1
|
1013 fseek(f, 0x1e, SEEK_CUR);
|
rlm@1
|
1014 fread(&games, 1, 4, f);
|
rlm@1
|
1015 bool found = false;
|
rlm@1
|
1016 int g = 0;
|
rlm@1
|
1017 while (games > 0)
|
rlm@1
|
1018 {
|
rlm@1
|
1019 if (g == game)
|
rlm@1
|
1020 {
|
rlm@1
|
1021 found = true;
|
rlm@1
|
1022 break;
|
rlm@1
|
1023 }
|
rlm@1
|
1024 fread(&len, 1, 4, f);
|
rlm@1
|
1025 fseek(f, len, SEEK_CUR);
|
rlm@1
|
1026 int codes = 0;
|
rlm@1
|
1027 fread(&codes, 1, 4, f);
|
rlm@1
|
1028 while (codes > 0)
|
rlm@1
|
1029 {
|
rlm@1
|
1030 fread(&len, 1, 4, f);
|
rlm@1
|
1031 fseek(f, len, SEEK_CUR);
|
rlm@1
|
1032 fseek(f, 8, SEEK_CUR);
|
rlm@1
|
1033 fread(&len, 1, 4, f);
|
rlm@1
|
1034 fseek(f, len*12, SEEK_CUR);
|
rlm@1
|
1035 codes--;
|
rlm@1
|
1036 }
|
rlm@1
|
1037 games--;
|
rlm@1
|
1038 g++;
|
rlm@1
|
1039 }
|
rlm@1
|
1040 if (found)
|
rlm@1
|
1041 {
|
rlm@1
|
1042 char desc[256];
|
rlm@1
|
1043 char code[17];
|
rlm@1
|
1044 fread(&len, 1, 4, f);
|
rlm@1
|
1045 fseek(f, len, SEEK_CUR);
|
rlm@1
|
1046 int codes = 0;
|
rlm@1
|
1047 fread(&codes, 1, 4, f);
|
rlm@1
|
1048 while (codes > 0)
|
rlm@1
|
1049 {
|
rlm@1
|
1050 fread(&len, 1, 4, f);
|
rlm@1
|
1051 fread(desc, 1, len, f);
|
rlm@1
|
1052 desc[len] = 0;
|
rlm@1
|
1053 desc[31] = 0;
|
rlm@1
|
1054 fread(&len, 1, 4, f);
|
rlm@1
|
1055 fseek(f, len, SEEK_CUR);
|
rlm@1
|
1056 fseek(f, 4, SEEK_CUR);
|
rlm@1
|
1057 fread(&len, 1, 4, f);
|
rlm@1
|
1058 while (len)
|
rlm@1
|
1059 {
|
rlm@1
|
1060 fseek(f, 4, SEEK_CUR);
|
rlm@1
|
1061 fread(code, 1, 8, f);
|
rlm@1
|
1062 fseek(f, 4, SEEK_CUR);
|
rlm@1
|
1063 fread(&code[8], 1, 8, f);
|
rlm@1
|
1064 code[16] = 0;
|
rlm@1
|
1065 cheatsAddGSACode(code, desc, v3);
|
rlm@1
|
1066 len -= 2;
|
rlm@1
|
1067 }
|
rlm@1
|
1068 codes--;
|
rlm@1
|
1069 }
|
rlm@1
|
1070 }
|
rlm@1
|
1071 fclose(f);
|
rlm@1
|
1072 return false;
|
rlm@1
|
1073 }
|
rlm@1
|
1074
|
rlm@1
|
1075 void cheatsCBAReverseArray(u8 *array, u8 *dest)
|
rlm@1
|
1076 {
|
rlm@1
|
1077 dest[0] = array[3];
|
rlm@1
|
1078 dest[1] = array[2];
|
rlm@1
|
1079 dest[2] = array[1];
|
rlm@1
|
1080 dest[3] = array[0];
|
rlm@1
|
1081 dest[4] = array[5];
|
rlm@1
|
1082 dest[5] = array[4];
|
rlm@1
|
1083 }
|
rlm@1
|
1084
|
rlm@1
|
1085 void chatsCBAScramble(u8 *array, int count, u8 b)
|
rlm@1
|
1086 {
|
rlm@1
|
1087 u8 *x = array + (count >> 3);
|
rlm@1
|
1088 u8 *y = array + (b >> 3);
|
rlm@1
|
1089 u32 z = *x & (1 << (count & 7));
|
rlm@1
|
1090 u32 x0 = (*x & (~(1 << (count & 7))));
|
rlm@1
|
1091 if (z != 0)
|
rlm@1
|
1092 z = 1;
|
rlm@1
|
1093 if ((*y & (1 << (b & 7))) != 0)
|
rlm@1
|
1094 x0 |= (1 << (count & 7));
|
rlm@1
|
1095 *x = x0;
|
rlm@1
|
1096 u32 temp = *y & (~(1 << (b & 7)));
|
rlm@1
|
1097 if (z != 0)
|
rlm@1
|
1098 temp |= (1 << (b & 7));
|
rlm@1
|
1099 *y = temp;
|
rlm@1
|
1100 }
|
rlm@1
|
1101
|
rlm@1
|
1102 u32 cheatsCBAGetValue(u8 *array)
|
rlm@1
|
1103 {
|
rlm@1
|
1104 return array[0] | array[1]<<8 | array[2] << 16 | array[3]<<24;
|
rlm@1
|
1105 }
|
rlm@1
|
1106
|
rlm@1
|
1107 u16 cheatsCBAGetData(u8 *array)
|
rlm@1
|
1108 {
|
rlm@1
|
1109 return array[4] | array[5]<<8;
|
rlm@1
|
1110 }
|
rlm@1
|
1111
|
rlm@1
|
1112 void cheatsCBAArrayToValue(u8 *array, u8 *dest)
|
rlm@1
|
1113 {
|
rlm@1
|
1114 dest[0] = array[3];
|
rlm@1
|
1115 dest[1] = array[2];
|
rlm@1
|
1116 dest[2] = array[1];
|
rlm@1
|
1117 dest[3] = array[0];
|
rlm@1
|
1118 dest[4] = array[5];
|
rlm@1
|
1119 dest[5] = array[4];
|
rlm@1
|
1120 }
|
rlm@1
|
1121
|
rlm@1
|
1122 void cheatsCBAParseSeedCode(u32 address, u32 value, u32 *array)
|
rlm@1
|
1123 {
|
rlm@1
|
1124 array[0] = 1;
|
rlm@1
|
1125 array[1] = value & 0xFF;
|
rlm@1
|
1126 array[2] = (address >> 0x10) & 0xFF;
|
rlm@1
|
1127 array[3] = (value >> 8) & 0xFF;
|
rlm@1
|
1128 array[4] = (address >> 0x18) & 0x0F;
|
rlm@1
|
1129 array[5] = address & 0xFFFF;
|
rlm@1
|
1130 array[6] = address;
|
rlm@1
|
1131 array[7] = value;
|
rlm@1
|
1132 }
|
rlm@1
|
1133
|
rlm@1
|
1134 u32 cheatsCBAEncWorker()
|
rlm@1
|
1135 {
|
rlm@1
|
1136 u32 x = (cheatsCBATemporaryValue * 0x41c64e6d) + 0x3039;
|
rlm@1
|
1137 u32 y = (x * 0x41c64e6d) + 0x3039;
|
rlm@1
|
1138 u32 z = x >> 0x10;
|
rlm@1
|
1139 x = ((y >> 0x10) & 0x7fff) << 0x0f;
|
rlm@1
|
1140 z = (z << 0x1e) | x;
|
rlm@1
|
1141 x = (y * 0x41c64e6d) + 0x3039;
|
rlm@1
|
1142 cheatsCBATemporaryValue = x;
|
rlm@1
|
1143 return z | ((x >> 0x10) & 0x7fff);
|
rlm@1
|
1144 }
|
rlm@1
|
1145
|
rlm@1
|
1146 #define ROR(v, s) \
|
rlm@1
|
1147 (((v) >> (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
|
rlm@1
|
1148
|
rlm@1
|
1149 u32 cheatsCBACalcIndex(u32 x, u32 y)
|
rlm@1
|
1150 {
|
rlm@1
|
1151 if (y != 0)
|
rlm@1
|
1152 {
|
rlm@1
|
1153 if (y == 1)
|
rlm@1
|
1154 x = 0;
|
rlm@1
|
1155 else if (x == y)
|
rlm@1
|
1156 x = 0;
|
rlm@1
|
1157 if (y < 1)
|
rlm@1
|
1158 return x;
|
rlm@1
|
1159 else if (x < y)
|
rlm@1
|
1160 return x;
|
rlm@1
|
1161 u32 x0 = 1;
|
rlm@1
|
1162
|
rlm@1
|
1163 while (y < 0x10000000)
|
rlm@1
|
1164 {
|
rlm@1
|
1165 if (y < x)
|
rlm@1
|
1166 {
|
rlm@1
|
1167 y = y << 4;
|
rlm@1
|
1168 x0 = x0 << 4;
|
rlm@1
|
1169 }
|
rlm@1
|
1170 else
|
rlm@1
|
1171 break;
|
rlm@1
|
1172 }
|
rlm@1
|
1173
|
rlm@1
|
1174 while (y < 0x80000000)
|
rlm@1
|
1175 {
|
rlm@1
|
1176 if (y < x)
|
rlm@1
|
1177 {
|
rlm@1
|
1178 y = y << 1;
|
rlm@1
|
1179 x0 = x0 << 1;
|
rlm@1
|
1180 }
|
rlm@1
|
1181 else
|
rlm@1
|
1182 break;
|
rlm@1
|
1183 }
|
rlm@1
|
1184
|
rlm@1
|
1185 loop:
|
rlm@1
|
1186 u32 z = 0;
|
rlm@1
|
1187 if (x >= y)
|
rlm@1
|
1188 x -= y;
|
rlm@1
|
1189 if (x >= (y >> 1))
|
rlm@1
|
1190 {
|
rlm@1
|
1191 x -= (y >> 1);
|
rlm@1
|
1192 z |= ROR(x0, 1);
|
rlm@1
|
1193 }
|
rlm@1
|
1194 if (x >= (y >> 2))
|
rlm@1
|
1195 {
|
rlm@1
|
1196 x -= (y >> 2);
|
rlm@1
|
1197 z |= ROR(x0, 2);
|
rlm@1
|
1198 }
|
rlm@1
|
1199 if (x >= (y >> 3))
|
rlm@1
|
1200 {
|
rlm@1
|
1201 x -= (y >> 3);
|
rlm@1
|
1202 z |= ROR(x0, 3);
|
rlm@1
|
1203 }
|
rlm@1
|
1204
|
rlm@1
|
1205 u32 temp = x0;
|
rlm@1
|
1206
|
rlm@1
|
1207 if (x != 0)
|
rlm@1
|
1208 {
|
rlm@1
|
1209 x0 = x0 >> 4;
|
rlm@1
|
1210 if (x0 != 0)
|
rlm@1
|
1211 {
|
rlm@1
|
1212 y = y >> 4;
|
rlm@1
|
1213 goto loop;
|
rlm@1
|
1214 }
|
rlm@1
|
1215 }
|
rlm@1
|
1216
|
rlm@1
|
1217 z = z & 0xe0000000;
|
rlm@1
|
1218
|
rlm@1
|
1219 if (z != 0)
|
rlm@1
|
1220 {
|
rlm@1
|
1221 if ((temp & 7) == 0)
|
rlm@1
|
1222 return x;
|
rlm@1
|
1223 }
|
rlm@1
|
1224 else
|
rlm@1
|
1225 return x;
|
rlm@1
|
1226
|
rlm@1
|
1227 if ((z & ROR(temp, 3)) != 0)
|
rlm@1
|
1228 x += y >> 3;
|
rlm@1
|
1229 if ((z & ROR(temp, 2)) != 0)
|
rlm@1
|
1230 x += y >> 2;
|
rlm@1
|
1231 if ((z & ROR(temp, 1)) != 0)
|
rlm@1
|
1232 x += y >> 1;
|
rlm@1
|
1233 return x;
|
rlm@1
|
1234 }
|
rlm@1
|
1235 else
|
rlm@1
|
1236 {}
|
rlm@1
|
1237 // should not happen in the current code
|
rlm@1
|
1238 return 0;
|
rlm@1
|
1239 }
|
rlm@1
|
1240
|
rlm@1
|
1241 void cheatsCBAUpdateSeedBuffer(u32 a, u8 *buffer, int count)
|
rlm@1
|
1242 {
|
rlm@1
|
1243 int i;
|
rlm@1
|
1244 for (i = 0; i < count; i++)
|
rlm@1
|
1245 buffer[i] = i;
|
rlm@1
|
1246 for (i = 0; (u32)i < a; i++)
|
rlm@1
|
1247 {
|
rlm@1
|
1248 u32 a = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
|
rlm@1
|
1249 u32 b = cheatsCBACalcIndex(cheatsCBAEncWorker(), count);
|
rlm@1
|
1250 u32 t = buffer[a];
|
rlm@1
|
1251 buffer[a] = buffer[b];
|
rlm@1
|
1252 buffer[b] = t;
|
rlm@1
|
1253 }
|
rlm@1
|
1254 }
|
rlm@1
|
1255
|
rlm@1
|
1256 void cheatsCBAChangeEncryption(u32 *seed)
|
rlm@1
|
1257 {
|
rlm@1
|
1258 int i;
|
rlm@1
|
1259
|
rlm@1
|
1260 cheatsCBATemporaryValue = (seed[1] ^ 0x1111);
|
rlm@1
|
1261 cheatsCBAUpdateSeedBuffer(0x50, cheatsCBASeedBuffer, 0x30);
|
rlm@1
|
1262 cheatsCBATemporaryValue = 0x4efad1c3;
|
rlm@1
|
1263
|
rlm@1
|
1264 for (i = 0; (u32)i < seed[4]; i++)
|
rlm@1
|
1265 {
|
rlm@1
|
1266 cheatsCBATemporaryValue = cheatsCBAEncWorker();
|
rlm@1
|
1267 }
|
rlm@1
|
1268 cheatsCBASeed[2] = cheatsCBAEncWorker();
|
rlm@1
|
1269 cheatsCBASeed[3] = cheatsCBAEncWorker();
|
rlm@1
|
1270
|
rlm@1
|
1271 cheatsCBATemporaryValue = seed[3] ^ 0xf254;
|
rlm@1
|
1272
|
rlm@1
|
1273 for (i = 0; (u32)i < seed[3]; i++)
|
rlm@1
|
1274 {
|
rlm@1
|
1275 cheatsCBATemporaryValue = cheatsCBAEncWorker();
|
rlm@1
|
1276 }
|
rlm@1
|
1277
|
rlm@1
|
1278 cheatsCBASeed[0] = cheatsCBAEncWorker();
|
rlm@1
|
1279 cheatsCBASeed[1] = cheatsCBAEncWorker();
|
rlm@1
|
1280
|
rlm@1
|
1281 *((u32 *)&cheatsCBACurrentSeed[0]) = seed[6];
|
rlm@1
|
1282 *((u32 *)&cheatsCBACurrentSeed[4]) = seed[7];
|
rlm@1
|
1283 *((u32 *)&cheatsCBACurrentSeed[8]) = 0;
|
rlm@1
|
1284 }
|
rlm@1
|
1285
|
rlm@1
|
1286 u16 cheatsCBAGenValue(u32 x, u32 y, u32 z)
|
rlm@1
|
1287 {
|
rlm@1
|
1288 y <<= 0x10;
|
rlm@1
|
1289 z <<= 0x10;
|
rlm@1
|
1290 x <<= 0x18;
|
rlm@1
|
1291 u32 x0 = (int)y >> 0x10;
|
rlm@1
|
1292 z = (int)z >> 0x10;
|
rlm@1
|
1293 x = (int)x >> 0x10;
|
rlm@1
|
1294 for (int i = 0; i < 8; i++)
|
rlm@1
|
1295 {
|
rlm@1
|
1296 u32 temp = z ^ x;
|
rlm@1
|
1297 if ((int)temp >= 0)
|
rlm@1
|
1298 {
|
rlm@1
|
1299 temp = z << 0x11;
|
rlm@1
|
1300 }
|
rlm@1
|
1301 else
|
rlm@1
|
1302 {
|
rlm@1
|
1303 temp = z << 0x01;
|
rlm@1
|
1304 temp ^= x0;
|
rlm@1
|
1305 temp = temp << 0x10;
|
rlm@1
|
1306 }
|
rlm@1
|
1307 z = (int)temp >> 0x10;
|
rlm@1
|
1308 temp = x << 0x11;
|
rlm@1
|
1309 x = (int)temp >> 0x10;
|
rlm@1
|
1310 }
|
rlm@1
|
1311 return z & 0xffff;
|
rlm@1
|
1312 }
|
rlm@1
|
1313
|
rlm@1
|
1314 void cheatsCBAGenTable()
|
rlm@1
|
1315 {
|
rlm@1
|
1316 for (int i = 0; i < 0x100; i++)
|
rlm@1
|
1317 {
|
rlm@1
|
1318 cheatsCBATable[i] = cheatsCBAGenValue(i, 0x1021, 0);
|
rlm@1
|
1319 }
|
rlm@1
|
1320 cheatsCBATableGenerated = true;
|
rlm@1
|
1321 }
|
rlm@1
|
1322
|
rlm@1
|
1323 u16 cheatsCBACalcCRC(u8 *rom, int count)
|
rlm@1
|
1324 {
|
rlm@1
|
1325 u32 crc = 0xffffffff;
|
rlm@1
|
1326
|
rlm@1
|
1327 if (count & 3)
|
rlm@1
|
1328 {
|
rlm@1
|
1329 // 0x08000EAE
|
rlm@1
|
1330 }
|
rlm@1
|
1331 else
|
rlm@1
|
1332 {
|
rlm@1
|
1333 count = (count >> 2) - 1;
|
rlm@1
|
1334 if (count != -1)
|
rlm@1
|
1335 {
|
rlm@1
|
1336 while (count != -1)
|
rlm@1
|
1337 {
|
rlm@1
|
1338 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
|
rlm@1
|
1339 ^ *rom++]) << 0x10) >> 0x10;
|
rlm@1
|
1340 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
|
rlm@1
|
1341 ^ *rom++]) << 0x10) >> 0x10;
|
rlm@1
|
1342 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
|
rlm@1
|
1343 ^ *rom++]) << 0x10) >> 0x10;
|
rlm@1
|
1344 crc = (((crc << 0x08) ^ cheatsCBATable[(((u32)crc << 0x10) >> 0x18)
|
rlm@1
|
1345 ^ *rom++]) << 0x10) >> 0x10;
|
rlm@1
|
1346 count--;
|
rlm@1
|
1347 }
|
rlm@1
|
1348 }
|
rlm@1
|
1349 }
|
rlm@1
|
1350 return crc & 0xffff;
|
rlm@1
|
1351 }
|
rlm@1
|
1352
|
rlm@1
|
1353 void cheatsCBADecrypt(u8 *decrypt)
|
rlm@1
|
1354 {
|
rlm@1
|
1355 u8 buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
rlm@1
|
1356 u8 *array = &buffer[1];
|
rlm@1
|
1357
|
rlm@1
|
1358 cheatsCBAReverseArray(decrypt, array);
|
rlm@1
|
1359
|
rlm@1
|
1360 for (int count = 0x2f; count >= 0; count--)
|
rlm@1
|
1361 {
|
rlm@1
|
1362 chatsCBAScramble(array, count, cheatsCBASeedBuffer[count]);
|
rlm@1
|
1363 }
|
rlm@1
|
1364 cheatsCBAArrayToValue(array, decrypt);
|
rlm@1
|
1365 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt) ^
|
rlm@1
|
1366 cheatsCBASeed[0];
|
rlm@1
|
1367 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt) ^
|
rlm@1
|
1368 cheatsCBASeed[1]) & 0xffff;
|
rlm@1
|
1369
|
rlm@1
|
1370 cheatsCBAReverseArray(decrypt, array);
|
rlm@1
|
1371
|
rlm@1
|
1372 u32 cs = cheatsCBAGetValue(cheatsCBACurrentSeed);
|
rlm@1
|
1373 for (int i = 0; i <= 4; i++)
|
rlm@1
|
1374 {
|
rlm@1
|
1375 array[i] = ((cs >> 8) ^ array[i+1]) ^ array[i] ;
|
rlm@1
|
1376 }
|
rlm@1
|
1377
|
rlm@1
|
1378 array[5] = (cs >> 8) ^ array[5];
|
rlm@1
|
1379
|
rlm@1
|
1380 for (int j = 5; j >= 0; j--)
|
rlm@1
|
1381 {
|
rlm@1
|
1382 array[j] = (cs ^ array[j-1]) ^ array[j];
|
rlm@1
|
1383 }
|
rlm@1
|
1384
|
rlm@1
|
1385 cheatsCBAArrayToValue(array, decrypt);
|
rlm@1
|
1386
|
rlm@1
|
1387 *((u32 *)decrypt) = cheatsCBAGetValue(decrypt)
|
rlm@1
|
1388 ^ cheatsCBASeed[2];
|
rlm@1
|
1389 *((u16 *)(decrypt+4)) = (cheatsCBAGetData(decrypt)
|
rlm@1
|
1390 ^ cheatsCBASeed[3]) & 0xffff;
|
rlm@1
|
1391 }
|
rlm@1
|
1392
|
rlm@1
|
1393 int cheatsCBAGetCount()
|
rlm@1
|
1394 {
|
rlm@1
|
1395 int count = 0;
|
rlm@1
|
1396 for (int i = 0; i < cheatsNumber; i++)
|
rlm@1
|
1397 {
|
rlm@1
|
1398 if (cheatsList[i].code == 512)
|
rlm@1
|
1399 count++;
|
rlm@1
|
1400 }
|
rlm@1
|
1401 return count;
|
rlm@1
|
1402 }
|
rlm@1
|
1403
|
rlm@1
|
1404 bool cheatsCBAShouldDecrypt()
|
rlm@1
|
1405 {
|
rlm@1
|
1406 for (int i = 0; i < cheatsNumber; i++)
|
rlm@1
|
1407 {
|
rlm@1
|
1408 if (cheatsList[i].code == 512)
|
rlm@1
|
1409 {
|
rlm@1
|
1410 return (cheatsList[i].codestring[0] == '9');
|
rlm@1
|
1411 }
|
rlm@1
|
1412 }
|
rlm@1
|
1413 return false;
|
rlm@1
|
1414 }
|
rlm@1
|
1415
|
rlm@1
|
1416 void cheatsAddCBACode(const char *code, const char *desc)
|
rlm@1
|
1417 {
|
rlm@1
|
1418 if (strlen(code) != 13)
|
rlm@1
|
1419 {
|
rlm@1
|
1420 // wrong cheat
|
rlm@1
|
1421 systemMessage(MSG_INVALID_CBA_CODE,
|
rlm@1
|
1422 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
|
rlm@1
|
1423 return;
|
rlm@1
|
1424 }
|
rlm@1
|
1425
|
rlm@1
|
1426 int i;
|
rlm@1
|
1427 for (i = 0; i < 8; i++)
|
rlm@1
|
1428 {
|
rlm@1
|
1429 if (!CHEAT_IS_HEX(code[i]))
|
rlm@1
|
1430 {
|
rlm@1
|
1431 // wrong cheat
|
rlm@1
|
1432 systemMessage(MSG_INVALID_CBA_CODE,
|
rlm@1
|
1433 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
|
rlm@1
|
1434 return;
|
rlm@1
|
1435 }
|
rlm@1
|
1436 }
|
rlm@1
|
1437
|
rlm@1
|
1438 if (code[8] != ' ')
|
rlm@1
|
1439 {
|
rlm@1
|
1440 systemMessage(MSG_INVALID_CBA_CODE,
|
rlm@1
|
1441 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
|
rlm@1
|
1442 return;
|
rlm@1
|
1443 }
|
rlm@1
|
1444
|
rlm@1
|
1445 for (i = 9; i < 13; i++)
|
rlm@1
|
1446 {
|
rlm@1
|
1447 if (!CHEAT_IS_HEX(code[i]))
|
rlm@1
|
1448 {
|
rlm@1
|
1449 // wrong cheat
|
rlm@1
|
1450 systemMessage(MSG_INVALID_CBA_CODE,
|
rlm@1
|
1451 N_("Invalid CBA code. Format is XXXXXXXX YYYY."));
|
rlm@1
|
1452 return;
|
rlm@1
|
1453 }
|
rlm@1
|
1454 }
|
rlm@1
|
1455
|
rlm@1
|
1456 char buffer[10];
|
rlm@1
|
1457 strncpy(buffer, code, 8);
|
rlm@1
|
1458 buffer[8] = 0;
|
rlm@1
|
1459 u32 address;
|
rlm@1
|
1460 sscanf(buffer, "%x", &address);
|
rlm@1
|
1461 strncpy(buffer, &code[9], 4);
|
rlm@1
|
1462 buffer[4] = 0;
|
rlm@1
|
1463 u32 value;
|
rlm@1
|
1464 sscanf(buffer, "%x", &value);
|
rlm@1
|
1465
|
rlm@1
|
1466 u8 array[8] = {
|
rlm@1
|
1467 address &255,
|
rlm@1
|
1468 (address >> 8) & 255,
|
rlm@1
|
1469 (address >> 16) & 255,
|
rlm@1
|
1470 (address >> 24) & 255,
|
rlm@1
|
1471 (value & 255),
|
rlm@1
|
1472 (value >> 8) & 255,
|
rlm@1
|
1473 0,
|
rlm@1
|
1474 0
|
rlm@1
|
1475 };
|
rlm@1
|
1476
|
rlm@1
|
1477 if (cheatsCBAGetCount() == 0 &&
|
rlm@1
|
1478 (address >> 28) == 9)
|
rlm@1
|
1479 {
|
rlm@1
|
1480 u32 seed[8];
|
rlm@1
|
1481 cheatsCBAParseSeedCode(address, value, seed);
|
rlm@1
|
1482 cheatsCBAChangeEncryption(seed);
|
rlm@1
|
1483 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512, UNKNOWN_CODE);
|
rlm@1
|
1484 }
|
rlm@1
|
1485 else
|
rlm@1
|
1486 {
|
rlm@1
|
1487 if (cheatsCBAShouldDecrypt())
|
rlm@1
|
1488 cheatsCBADecrypt(array);
|
rlm@1
|
1489
|
rlm@1
|
1490 address = READ32LE(((u32 *)array));
|
rlm@1
|
1491 value = READ16LE(((u16 *)&array[4]));
|
rlm@1
|
1492
|
rlm@1
|
1493 int type = (address >> 28) & 15;
|
rlm@1
|
1494
|
rlm@1
|
1495 if (isMultilineWithData(cheatsNumber-1))
|
rlm@1
|
1496 {
|
rlm@1
|
1497 cheatsAdd(code, desc, address, value, 512, UNKNOWN_CODE);
|
rlm@1
|
1498 return;
|
rlm@1
|
1499 }
|
rlm@1
|
1500
|
rlm@1
|
1501 switch (type)
|
rlm@1
|
1502 {
|
rlm@1
|
1503 case 0x00:
|
rlm@1
|
1504 {
|
rlm@1
|
1505 if (!cheatsCBATableGenerated)
|
rlm@1
|
1506 cheatsCBAGenTable();
|
rlm@1
|
1507 u32 crc = cheatsCBACalcCRC(rom, 0x10000);
|
rlm@1
|
1508 if (crc != address)
|
rlm@1
|
1509 {
|
rlm@1
|
1510 systemMessage(MSG_CBA_CODE_WARNING,
|
rlm@1
|
1511 N_("Warning: Codes seem to be for a different game.\nCodes may not work correctly."));
|
rlm@1
|
1512 }
|
rlm@1
|
1513 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1514 UNKNOWN_CODE);
|
rlm@1
|
1515 break;
|
rlm@1
|
1516 }
|
rlm@1
|
1517 case 0x02:
|
rlm@1
|
1518 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1519 CBA_OR);
|
rlm@1
|
1520 break;
|
rlm@1
|
1521 case 0x03:
|
rlm@1
|
1522 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1523 INT_8_BIT_WRITE);
|
rlm@1
|
1524 break;
|
rlm@1
|
1525 case 0x04:
|
rlm@1
|
1526 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1527 CBA_SLIDE_CODE);
|
rlm@1
|
1528 break;
|
rlm@1
|
1529 case 0x05:
|
rlm@1
|
1530 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1531 CBA_SUPER);
|
rlm@1
|
1532 break;
|
rlm@1
|
1533 case 0x06:
|
rlm@1
|
1534 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1535 CBA_AND);
|
rlm@1
|
1536 break;
|
rlm@1
|
1537 case 0x07:
|
rlm@1
|
1538 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1539 CBA_IF_TRUE);
|
rlm@1
|
1540 break;
|
rlm@1
|
1541 case 0x08:
|
rlm@1
|
1542 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1543 INT_16_BIT_WRITE);
|
rlm@1
|
1544 break;
|
rlm@1
|
1545 case 0x0a:
|
rlm@1
|
1546 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1547 CBA_IF_FALSE);
|
rlm@1
|
1548 break;
|
rlm@1
|
1549 case 0x0b:
|
rlm@1
|
1550 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1551 CBA_LT);
|
rlm@1
|
1552 break;
|
rlm@1
|
1553 case 0x0c:
|
rlm@1
|
1554 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1555 CBA_GT);
|
rlm@1
|
1556 break;
|
rlm@1
|
1557 case 0x0d:
|
rlm@1
|
1558 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1559 CBA_IF_KEYS_PRESSED);
|
rlm@1
|
1560 break;
|
rlm@1
|
1561 case 0x0e:
|
rlm@1
|
1562 cheatsAdd(code, desc, address & 0x0FFFFFFF, value, 512,
|
rlm@1
|
1563 CBA_ADD);
|
rlm@1
|
1564 break;
|
rlm@1
|
1565 default:
|
rlm@1
|
1566 // unsupported code
|
rlm@1
|
1567 cheatsAdd(code, desc, address & 0xFFFFFFFF, value, 512,
|
rlm@1
|
1568 UNKNOWN_CODE);
|
rlm@1
|
1569 break;
|
rlm@1
|
1570 }
|
rlm@1
|
1571 }
|
rlm@1
|
1572 }
|
rlm@1
|
1573
|
rlm@1
|
1574 void cheatsSaveGame(gzFile file)
|
rlm@1
|
1575 {
|
rlm@1
|
1576 utilWriteInt(file, cheatsNumber);
|
rlm@1
|
1577
|
rlm@1
|
1578 utilGzWrite(file, cheatsList, sizeof(cheatsList));
|
rlm@1
|
1579 }
|
rlm@1
|
1580
|
rlm@1
|
1581 void cheatsReadGame(gzFile file)
|
rlm@1
|
1582 {
|
rlm@1
|
1583 cheatsNumber = 0;
|
rlm@1
|
1584
|
rlm@1
|
1585 cheatsNumber = utilReadInt(file);
|
rlm@1
|
1586
|
rlm@1
|
1587 utilGzRead(file, cheatsList, sizeof(cheatsList));
|
rlm@1
|
1588
|
rlm@1
|
1589 bool firstCodeBreaker = true;
|
rlm@1
|
1590
|
rlm@1
|
1591 for (int i = 0; i < cheatsNumber; i++)
|
rlm@1
|
1592 {
|
rlm@1
|
1593 cheatsList[i].status = 0;
|
rlm@1
|
1594 if (!cheatsList[i].codestring[0])
|
rlm@1
|
1595 {
|
rlm@1
|
1596 switch (cheatsList[i].size)
|
rlm@1
|
1597 {
|
rlm@1
|
1598 case 0:
|
rlm@1
|
1599 sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
|
rlm@1
|
1600 cheatsList[i].value);
|
rlm@1
|
1601 break;
|
rlm@1
|
1602 case 1:
|
rlm@1
|
1603 sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
|
rlm@1
|
1604 cheatsList[i].value);
|
rlm@1
|
1605 break;
|
rlm@1
|
1606 case 2:
|
rlm@1
|
1607 sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
|
rlm@1
|
1608 cheatsList[i].value);
|
rlm@1
|
1609 break;
|
rlm@1
|
1610 }
|
rlm@1
|
1611 }
|
rlm@1
|
1612
|
rlm@1
|
1613 if (cheatsList[i].enabled)
|
rlm@1
|
1614 {
|
rlm@1
|
1615 cheatsEnable(i);
|
rlm@1
|
1616 }
|
rlm@1
|
1617
|
rlm@1
|
1618 if (cheatsList[i].code == 512 && firstCodeBreaker)
|
rlm@1
|
1619 {
|
rlm@1
|
1620 firstCodeBreaker = false;
|
rlm@1
|
1621 char buffer[10];
|
rlm@1
|
1622 strncpy(buffer, cheatsList[i].codestring, 8);
|
rlm@1
|
1623 buffer[8] = 0;
|
rlm@1
|
1624 u32 address;
|
rlm@1
|
1625 sscanf(buffer, "%x", &address);
|
rlm@1
|
1626 if ((address >> 28) == 9)
|
rlm@1
|
1627 {
|
rlm@1
|
1628 strncpy(buffer, &cheatsList[i].codestring[9], 4);
|
rlm@1
|
1629 buffer[4] = 0;
|
rlm@1
|
1630 u32 value;
|
rlm@1
|
1631 sscanf(buffer, "%x", &value);
|
rlm@1
|
1632
|
rlm@1
|
1633 u32 seed[8];
|
rlm@1
|
1634 cheatsCBAParseSeedCode(address, value, seed);
|
rlm@1
|
1635 cheatsCBAChangeEncryption(seed);
|
rlm@1
|
1636 }
|
rlm@1
|
1637 }
|
rlm@1
|
1638 }
|
rlm@1
|
1639 }
|
rlm@1
|
1640
|
rlm@1
|
1641 void cheatsSaveCheatList(const char *file)
|
rlm@1
|
1642 {
|
rlm@1
|
1643 if (cheatsNumber == 0)
|
rlm@1
|
1644 return;
|
rlm@1
|
1645 FILE *f = fopen(file, "wb");
|
rlm@1
|
1646 if (f == NULL)
|
rlm@1
|
1647 return;
|
rlm@1
|
1648 int version = 1;
|
rlm@1
|
1649 fwrite(&version, 1, sizeof(version), f);
|
rlm@1
|
1650 int type = 0;
|
rlm@1
|
1651 fwrite(&type, 1, sizeof(type), f);
|
rlm@1
|
1652 fwrite(&cheatsNumber, 1, sizeof(cheatsNumber), f);
|
rlm@1
|
1653 fwrite(cheatsList, 1, sizeof(cheatsList), f);
|
rlm@1
|
1654 fclose(f);
|
rlm@1
|
1655 }
|
rlm@1
|
1656
|
rlm@1
|
1657 bool cheatsLoadCheatList(const char *file)
|
rlm@1
|
1658 {
|
rlm@1
|
1659 cheatsNumber = 0;
|
rlm@1
|
1660
|
rlm@1
|
1661 int count = 0;
|
rlm@1
|
1662
|
rlm@1
|
1663 FILE *f = fopen(file, "rb");
|
rlm@1
|
1664
|
rlm@1
|
1665 if (f == NULL)
|
rlm@1
|
1666 return false;
|
rlm@1
|
1667
|
rlm@1
|
1668 int version = 0;
|
rlm@1
|
1669
|
rlm@1
|
1670 if (fread(&version, 1, sizeof(version), f) != sizeof(version))
|
rlm@1
|
1671 {
|
rlm@1
|
1672 fclose(f);
|
rlm@1
|
1673 return false;
|
rlm@1
|
1674 }
|
rlm@1
|
1675
|
rlm@1
|
1676 if (version != 1)
|
rlm@1
|
1677 {
|
rlm@1
|
1678 systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
|
rlm@1
|
1679 N_("Unsupported cheat list version %d"), version);
|
rlm@1
|
1680 fclose(f);
|
rlm@1
|
1681 return false;
|
rlm@1
|
1682 }
|
rlm@1
|
1683
|
rlm@1
|
1684 int type = 0;
|
rlm@1
|
1685 if (fread(&type, 1, sizeof(type), f) != sizeof(type))
|
rlm@1
|
1686 {
|
rlm@1
|
1687 fclose(f);
|
rlm@1
|
1688 return false;
|
rlm@1
|
1689 }
|
rlm@1
|
1690
|
rlm@1
|
1691 if (type != 0)
|
rlm@1
|
1692 {
|
rlm@1
|
1693 systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
|
rlm@1
|
1694 N_("Unsupported cheat list type %d"), type);
|
rlm@1
|
1695 fclose(f);
|
rlm@1
|
1696 return false;
|
rlm@1
|
1697 }
|
rlm@1
|
1698
|
rlm@1
|
1699 if (fread(&count, 1, sizeof(count), f) != sizeof(count))
|
rlm@1
|
1700 {
|
rlm@1
|
1701 fclose(f);
|
rlm@1
|
1702 return false;
|
rlm@1
|
1703 }
|
rlm@1
|
1704
|
rlm@1
|
1705 if (fread(cheatsList, 1, sizeof(cheatsList), f) != sizeof(cheatsList))
|
rlm@1
|
1706 {
|
rlm@1
|
1707 fclose(f);
|
rlm@1
|
1708 return false;
|
rlm@1
|
1709 }
|
rlm@1
|
1710
|
rlm@1
|
1711 bool firstCodeBreaker = true;
|
rlm@1
|
1712
|
rlm@1
|
1713 for (int i = 0; i < count; i++)
|
rlm@1
|
1714 {
|
rlm@1
|
1715 cheatsList[i].status = 0; // remove old status as it is not used
|
rlm@1
|
1716 if (!cheatsList[i].codestring[0])
|
rlm@1
|
1717 {
|
rlm@1
|
1718 switch (cheatsList[i].size)
|
rlm@1
|
1719 {
|
rlm@1
|
1720 case 0:
|
rlm@1
|
1721 sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
|
rlm@1
|
1722 cheatsList[i].value);
|
rlm@1
|
1723 break;
|
rlm@1
|
1724 case 1:
|
rlm@1
|
1725 sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
|
rlm@1
|
1726 cheatsList[i].value);
|
rlm@1
|
1727 break;
|
rlm@1
|
1728 case 2:
|
rlm@1
|
1729 sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
|
rlm@1
|
1730 cheatsList[i].value);
|
rlm@1
|
1731 break;
|
rlm@1
|
1732 }
|
rlm@1
|
1733 }
|
rlm@1
|
1734
|
rlm@1
|
1735 if (cheatsList[i].code == 512 && firstCodeBreaker)
|
rlm@1
|
1736 {
|
rlm@1
|
1737 firstCodeBreaker = false;
|
rlm@1
|
1738 char buffer[10];
|
rlm@1
|
1739 strncpy(buffer, cheatsList[i].codestring, 8);
|
rlm@1
|
1740 buffer[8] = 0;
|
rlm@1
|
1741 u32 address;
|
rlm@1
|
1742 sscanf(buffer, "%x", &address);
|
rlm@1
|
1743 if ((address >> 28) == 9)
|
rlm@1
|
1744 {
|
rlm@1
|
1745 strncpy(buffer, &cheatsList[i].codestring[9], 4);
|
rlm@1
|
1746 buffer[4] = 0;
|
rlm@1
|
1747 u32 value;
|
rlm@1
|
1748 sscanf(buffer, "%x", &value);
|
rlm@1
|
1749
|
rlm@1
|
1750 u32 seed[8];
|
rlm@1
|
1751 cheatsCBAParseSeedCode(address, value, seed);
|
rlm@1
|
1752 cheatsCBAChangeEncryption(seed);
|
rlm@1
|
1753 }
|
rlm@1
|
1754 }
|
rlm@1
|
1755 }
|
rlm@1
|
1756 cheatsNumber = count;
|
rlm@1
|
1757 fclose(f);
|
rlm@1
|
1758 return true;
|
rlm@1
|
1759 }
|
rlm@1
|
1760
|
rlm@1
|
1761 extern int *extCpuLoopTicks;
|
rlm@1
|
1762 extern int *extClockTicks;
|
rlm@1
|
1763 extern int *extTicks;
|
rlm@1
|
1764 extern int cpuSavedTicks;
|
rlm@1
|
1765
|
rlm@1
|
1766 extern void debuggerBreakOnWrite(u32 *, u32, u32, int);
|
rlm@1
|
1767
|
rlm@1
|
1768 #define CPU_BREAK_LOOP2 \
|
rlm@1
|
1769 cpuSavedTicks = cpuSavedTicks - *extCpuLoopTicks; \
|
rlm@1
|
1770 *extCpuLoopTicks = *extClockTicks; \
|
rlm@1
|
1771 *extTicks = *extClockTicks;
|
rlm@1
|
1772
|
rlm@1
|
1773 void cheatsWriteMemory(u32 *address, u32 value, u32 mask)
|
rlm@1
|
1774 {
|
rlm@1
|
1775 #ifdef BKPT_SUPPORT
|
rlm@1
|
1776 #ifdef SDL
|
rlm@1
|
1777 if (cheatsNumber == 0)
|
rlm@1
|
1778 {
|
rlm@1
|
1779 debuggerBreakOnWrite(address, *address, value, 2);
|
rlm@1
|
1780 CPU_BREAK_LOOP2;
|
rlm@1
|
1781 *address = value;
|
rlm@1
|
1782 return;
|
rlm@1
|
1783 }
|
rlm@1
|
1784 #endif
|
rlm@1
|
1785 #endif
|
rlm@1
|
1786 }
|
rlm@1
|
1787
|
rlm@1
|
1788 void cheatsWriteHalfWord(u16 *address, u16 value, u16 mask)
|
rlm@1
|
1789 {
|
rlm@1
|
1790 #ifdef BKPT_SUPPORT
|
rlm@1
|
1791 #ifdef SDL
|
rlm@1
|
1792 if (cheatsNumber == 0)
|
rlm@1
|
1793 {
|
rlm@1
|
1794 debuggerBreakOnWrite((u32 *)address, *address, value, 1);
|
rlm@1
|
1795 CPU_BREAK_LOOP2;
|
rlm@1
|
1796 *address = value;
|
rlm@1
|
1797 return;
|
rlm@1
|
1798 }
|
rlm@1
|
1799 #endif
|
rlm@1
|
1800 #endif
|
rlm@1
|
1801 }
|
rlm@1
|
1802
|
rlm@1
|
1803 #if defined BKPT_SUPPORT && defined SDL
|
rlm@1
|
1804 void cheatsWriteByte(u8 *address, u8 value)
|
rlm@1
|
1805 #else
|
rlm@1
|
1806 void cheatsWriteByte(u8 *, u8)
|
rlm@1
|
1807 #endif
|
rlm@1
|
1808 {
|
rlm@1
|
1809 #ifdef BKPT_SUPPORT
|
rlm@1
|
1810 #ifdef SDL
|
rlm@1
|
1811 if (cheatsNumber == 0)
|
rlm@1
|
1812 {
|
rlm@1
|
1813 debuggerBreakOnWrite((u32 *)address, *address, value, 0);
|
rlm@1
|
1814 CPU_BREAK_LOOP2;
|
rlm@1
|
1815 *address = value;
|
rlm@1
|
1816 return;
|
rlm@1
|
1817 }
|
rlm@1
|
1818 #endif
|
rlm@1
|
1819 #endif
|
rlm@1
|
1820 }
|
rlm@1
|
1821
|
rlm@1
|
1822 #undef CPU_BREAK_LOOP2
|