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
40static bool8 S9xAllHex (const char *, int);
41
42
43static 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
52const 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
65const 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
98const 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
146void 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
154void 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
245void 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
336void 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
389void 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