1 | /*****************************************************************************\ |
2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. |
3 | This file is licensed under the Snes9x License. |
4 | For further information, consult the LICENSE file in the root directory. |
5 | \*****************************************************************************/ |
6 | |
7 | #include <ctype.h> |
8 | #include "snes9x.h" |
9 | #include "memmap.h" |
10 | #include "cheats.h" |
11 | |
12 | #define WRAM_BITS ALL_BITS |
13 | #define SRAM_BITS ALL_BITS + (0x20000 >> 5) |
14 | #define IRAM_BITS ALL_BITS + (0x30000 >> 5) |
15 | |
16 | #define BIT_CLEAR(a, v) (a)[(v) >> 5] &= ~(1 << ((v) & 31)) |
17 | |
18 | #define TEST_BIT(a, v) ((a)[(v) >> 5] & (1 << ((v) & 31))) |
19 | |
20 | #define _S9XCHTC(c, a, b) \ |
21 | ((c) == S9X_LESS_THAN ? (a) < (b) : \ |
22 | (c) == S9X_GREATER_THAN ? (a) > (b) : \ |
23 | (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ |
24 | (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ |
25 | (c) == S9X_EQUAL ? (a) == (b) : \ |
26 | (a) != (b)) |
27 | |
28 | #define _S9XCHTD(s, m, o) \ |
29 | ((s) == S9X_8_BITS ? ((uint8) (*((m) + (o)))) : \ |
30 | (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ |
31 | (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ |
32 | ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) |
33 | |
34 | #define _S9XCHTDS(s, m, o) \ |
35 | ((s) == S9X_8_BITS ? ((int8) (*((m) + (o)))) : \ |
36 | (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ |
37 | (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ |
38 | ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) |
39 | |
40 | static bool8 S9xAllHex (const char *, int); |
41 | |
42 | |
43 | static bool8 S9xAllHex (const char *code, int len) |
44 | { |
45 | for (int i = 0; i < len; i++) |
46 | if ((code[i] < '0' || code[i] > '9') && (code[i] < 'a' || code[i] > 'f') && (code[i] < 'A' || code[i] > 'F')) |
47 | return (FALSE); |
48 | |
49 | return (TRUE); |
50 | } |
51 | |
52 | const char * S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) |
53 | { |
54 | uint32 data = 0; |
55 | |
56 | if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x" , &data) != 1) |
57 | return ("Invalid Pro Action Replay code - should be 8 hex digits in length." ); |
58 | |
59 | address = data >> 8; |
60 | byte = (uint8) data; |
61 | |
62 | return (NULL); |
63 | } |
64 | |
65 | const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3]) |
66 | { |
67 | char tmp[15]; |
68 | int i; |
69 | |
70 | if (strlen(code) != 14) |
71 | return ("Invalid Gold Finger code - should be 14 hex digits in length." ); |
72 | |
73 | strncpy(tmp, code, 5); |
74 | tmp[5] = 0; |
75 | if (sscanf(tmp, "%x" , &address) != 1) |
76 | return ("Invalid Gold Finger code." ); |
77 | |
78 | // Correct GoldFinger Address |
79 | address = (address & 0x7FFF) | ((address & 0x7F8000) << 1) | 0x8000; |
80 | |
81 | for (i = 0; i < 3; i++) |
82 | { |
83 | unsigned int byte; |
84 | |
85 | strncpy(tmp, code + 5 + i * 2, 2); |
86 | tmp[2] = 0; |
87 | if (sscanf(tmp, "%x" , &byte) != 1) |
88 | break; |
89 | bytes[i] = (uint8) byte; |
90 | } |
91 | |
92 | num_bytes = i; |
93 | sram = code[13] == '1'; |
94 | |
95 | return (NULL); |
96 | } |
97 | |
98 | const char * S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) |
99 | { |
100 | char new_code[12]; |
101 | |
102 | if (strlen(code) != 9 || *(code + 4) != '-' || !S9xAllHex(code, 4) || !S9xAllHex(code + 5, 4)) |
103 | return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'." ); |
104 | |
105 | strcpy(new_code, "0x" ); |
106 | strncpy(new_code + 2, code, 4); |
107 | strcpy(new_code + 6, code + 5); |
108 | |
109 | static const char *real_hex = "0123456789ABCDEF" ; |
110 | static const char *genie_hex = "DF4709156BC8A23E" ; |
111 | |
112 | for (int i = 2; i < 10; i++) |
113 | { |
114 | if (islower(new_code[i])) |
115 | new_code[i] = toupper(new_code[i]); |
116 | |
117 | int j; |
118 | for (j = 0; j < 16; j++) |
119 | { |
120 | if (new_code[i] == genie_hex[j]) |
121 | { |
122 | new_code[i] = real_hex[j]; |
123 | break; |
124 | } |
125 | } |
126 | |
127 | if (j == 16) |
128 | return ("Invalid hex-character in Game Genie(tm) code." ); |
129 | } |
130 | |
131 | uint32 data = 0; |
132 | sscanf(new_code, "%x" , &data); |
133 | byte = (uint8) (data >> 24); |
134 | address = data & 0xffffff; |
135 | address = ((address & 0x003c00) << 10) + |
136 | ((address & 0x00003c) << 14) + |
137 | ((address & 0xf00000) >> 8) + |
138 | ((address & 0x000003) << 10) + |
139 | ((address & 0x00c000) >> 6) + |
140 | ((address & 0x0f0000) >> 12) + |
141 | ((address & 0x0003c0) >> 6); |
142 | |
143 | return (NULL); |
144 | } |
145 | |
146 | void S9xStartCheatSearch (SCheatData *d) |
147 | { |
148 | memmove(d->CWRAM, d->RAM, 0x20000); |
149 | memmove(d->CSRAM, d->SRAM, 0x10000); |
150 | memmove(d->CIRAM, &d->FillRAM[0x3000], 0x2000); |
151 | memset((char *) d->ALL_BITS, 0xff, 0x32000 >> 3); |
152 | } |
153 | |
154 | void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool8 is_signed, bool8 update) |
155 | { |
156 | int l, i; |
157 | |
158 | switch (size) |
159 | { |
160 | case S9X_8_BITS: l = 0; break; |
161 | case S9X_16_BITS: l = 1; break; |
162 | case S9X_24_BITS: l = 2; break; |
163 | default: |
164 | case S9X_32_BITS: l = 3; break; |
165 | } |
166 | |
167 | if (is_signed) |
168 | { |
169 | for (i = 0; i < 0x20000 - l; i++) |
170 | { |
171 | if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), _S9XCHTDS(size, d->CWRAM, i))) |
172 | { |
173 | if (update) |
174 | d->CWRAM[i] = d->RAM[i]; |
175 | } |
176 | else |
177 | BIT_CLEAR(d->WRAM_BITS, i); |
178 | } |
179 | |
180 | for (i = 0; i < 0x10000 - l; i++) |
181 | { |
182 | if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), _S9XCHTDS(size, d->CSRAM, i))) |
183 | { |
184 | if (update) |
185 | d->CSRAM[i] = d->SRAM[i]; |
186 | } |
187 | else |
188 | BIT_CLEAR(d->SRAM_BITS, i); |
189 | } |
190 | |
191 | for (i = 0; i < 0x2000 - l; i++) |
192 | { |
193 | if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), _S9XCHTDS(size, d->CIRAM, i))) |
194 | { |
195 | if (update) |
196 | d->CIRAM[i] = d->FillRAM[i + 0x3000]; |
197 | } |
198 | else |
199 | BIT_CLEAR(d->IRAM_BITS, i); |
200 | } |
201 | } |
202 | else |
203 | { |
204 | for (i = 0; i < 0x20000 - l; i++) |
205 | { |
206 | if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), _S9XCHTD(size, d->CWRAM, i))) |
207 | { |
208 | if (update) |
209 | d->CWRAM[i] = d->RAM[i]; |
210 | } |
211 | else |
212 | BIT_CLEAR(d->WRAM_BITS, i); |
213 | } |
214 | |
215 | for (i = 0; i < 0x10000 - l; i++) |
216 | { |
217 | if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), _S9XCHTD(size, d->CSRAM, i))) |
218 | { |
219 | if (update) |
220 | d->CSRAM[i] = d->SRAM[i]; |
221 | } |
222 | else |
223 | BIT_CLEAR(d->SRAM_BITS, i); |
224 | } |
225 | |
226 | for (i = 0; i < 0x2000 - l; i++) |
227 | { |
228 | if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), _S9XCHTD(size, d->CIRAM, i))) |
229 | { |
230 | if (update) |
231 | d->CIRAM[i] = d->FillRAM[i + 0x3000]; |
232 | } |
233 | else |
234 | BIT_CLEAR(d->IRAM_BITS, i); |
235 | } |
236 | } |
237 | |
238 | for (i = 0x20000 - l; i < 0x20000; i++) |
239 | BIT_CLEAR(d->WRAM_BITS, i); |
240 | |
241 | for (i = 0x10000 - l; i < 0x10000; i++) |
242 | BIT_CLEAR(d->SRAM_BITS, i); |
243 | } |
244 | |
245 | void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 is_signed, bool8 update) |
246 | { |
247 | int l, i; |
248 | |
249 | switch (size) |
250 | { |
251 | case S9X_8_BITS: l = 0; break; |
252 | case S9X_16_BITS: l = 1; break; |
253 | case S9X_24_BITS: l = 2; break; |
254 | default: |
255 | case S9X_32_BITS: l = 3; break; |
256 | } |
257 | |
258 | if (is_signed) |
259 | { |
260 | for (i = 0; i < 0x20000 - l; i++) |
261 | { |
262 | if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), (int32) value)) |
263 | { |
264 | if (update) |
265 | d->CWRAM[i] = d->RAM[i]; |
266 | } |
267 | else |
268 | BIT_CLEAR(d->WRAM_BITS, i); |
269 | } |
270 | |
271 | for (i = 0; i < 0x10000 - l; i++) |
272 | { |
273 | if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), (int32) value)) |
274 | { |
275 | if (update) |
276 | d->CSRAM[i] = d->SRAM[i]; |
277 | } |
278 | else |
279 | BIT_CLEAR(d->SRAM_BITS, i); |
280 | } |
281 | |
282 | for (i = 0; i < 0x2000 - l; i++) |
283 | { |
284 | if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), (int32) value)) |
285 | { |
286 | if (update) |
287 | d->CIRAM[i] = d->FillRAM[i + 0x3000]; |
288 | } |
289 | else |
290 | BIT_CLEAR(d->IRAM_BITS, i); |
291 | } |
292 | } |
293 | else |
294 | { |
295 | for (i = 0; i < 0x20000 - l; i++) |
296 | { |
297 | if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), value)) |
298 | { |
299 | if (update) |
300 | d->CWRAM[i] = d->RAM[i]; |
301 | } |
302 | else |
303 | BIT_CLEAR(d->WRAM_BITS, i); |
304 | } |
305 | |
306 | for (i = 0; i < 0x10000 - l; i++) |
307 | { |
308 | if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), value)) |
309 | { |
310 | if (update) |
311 | d->CSRAM[i] = d->SRAM[i]; |
312 | } |
313 | else |
314 | BIT_CLEAR(d->SRAM_BITS, i); |
315 | } |
316 | |
317 | for (i = 0; i < 0x2000 - l; i++) |
318 | { |
319 | if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), value)) |
320 | { |
321 | if (update) |
322 | d->CIRAM[i] = d->FillRAM[i + 0x3000]; |
323 | } |
324 | else |
325 | BIT_CLEAR(d->IRAM_BITS, i); |
326 | } |
327 | } |
328 | |
329 | for (i = 0x20000 - l; i < 0x20000; i++) |
330 | BIT_CLEAR(d->WRAM_BITS, i); |
331 | |
332 | for (i = 0x10000 - l; i < 0x10000; i++) |
333 | BIT_CLEAR(d->SRAM_BITS, i); |
334 | } |
335 | |
336 | void S9xSearchForAddress (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 update) |
337 | { |
338 | int l, i; |
339 | |
340 | switch (size) |
341 | { |
342 | case S9X_8_BITS: l = 0; break; |
343 | case S9X_16_BITS: l = 1; break; |
344 | case S9X_24_BITS: l = 2; break; |
345 | default: |
346 | case S9X_32_BITS: l = 3; break; |
347 | } |
348 | |
349 | for (i = 0; i < 0x20000 - l; i++) |
350 | { |
351 | if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, i, (int32) value)) |
352 | { |
353 | if (update) |
354 | d->CWRAM[i] = d->RAM[i]; |
355 | } |
356 | else |
357 | BIT_CLEAR(d->WRAM_BITS, i); |
358 | } |
359 | |
360 | for (i = 0; i < 0x10000 - l; i++) |
361 | { |
362 | if (TEST_BIT(d->SRAM_BITS, i) && _S9XCHTC(cmp, i + 0x20000, (int32) value)) |
363 | { |
364 | if (update) |
365 | d->CSRAM[i] = d->SRAM[i]; |
366 | } |
367 | else |
368 | BIT_CLEAR(d->SRAM_BITS, i); |
369 | } |
370 | |
371 | for (i = 0; i < 0x2000 - l; i++) |
372 | { |
373 | if (TEST_BIT(d->IRAM_BITS, i) && _S9XCHTC(cmp, i + 0x30000, (int32) value)) |
374 | { |
375 | if (update) |
376 | d->CIRAM[i] = d->FillRAM[i + 0x3000]; |
377 | } |
378 | else |
379 | BIT_CLEAR(d->IRAM_BITS, i); |
380 | } |
381 | |
382 | for (i = 0x20000 - l; i < 0x20000; i++) |
383 | BIT_CLEAR(d->WRAM_BITS, i); |
384 | |
385 | for (i = 0x10000 - l; i < 0x10000; i++) |
386 | BIT_CLEAR(d->SRAM_BITS, i); |
387 | } |
388 | |
389 | void S9xOutputCheatSearchResults (SCheatData *d) |
390 | { |
391 | int i; |
392 | |
393 | for (i = 0; i < 0x20000; i++) |
394 | { |
395 | if (TEST_BIT(d->WRAM_BITS, i)) |
396 | printf("WRAM: %05x: %02x\n" , i, d->RAM[i]); |
397 | } |
398 | |
399 | for (i = 0; i < 0x10000; i++) |
400 | { |
401 | if (TEST_BIT(d->SRAM_BITS, i)) |
402 | printf("SRAM: %04x: %02x\n" , i, d->SRAM[i]); |
403 | } |
404 | |
405 | for (i = 0; i < 0x2000; i++) |
406 | { |
407 | if (TEST_BIT(d->IRAM_BITS, i)) |
408 | printf("IRAM: %05x: %02x\n" , i, d->FillRAM[i + 0x3000]); |
409 | } |
410 | } |
411 | |