workaround a problem with the harmattan gcc
[drnoksnes] / cheats.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <string.h>
44 #include "snes9x.h"
45 #include "cheats.h"
46 #include "memmap.h"
47
48 static bool8 S9xAllHex (const char *code, int len)
49 {
50     for (int i = 0; i < len; i++)
51         if ((code [i] < '0' || code [i] > '9') &&
52             (code [i] < 'a' || code [i] > 'f') &&
53             (code [i] < 'A' || code [i] > 'F'))
54             return (FALSE);
55
56     return (TRUE);
57 }
58
59 const char *S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte)
60 {
61     uint32 data = 0;
62     if (strlen (code) != 8 || !S9xAllHex (code, 8) ||
63         sscanf (code, "%x", &data) != 1)
64         return ("Invalid Pro Action Replay code - should be 8 hex digits in length.");
65
66     address = data >> 8;
67     byte = (uint8) data;
68     return (NULL);
69 }
70
71 const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram,
72                                 uint8 &num_bytes, uint8 bytes[3])
73 {
74     char tmp [15];
75     if (strlen (code) != 14)
76         return ("Invalid Gold Finger code should be 14 hex digits in length.");
77
78     strncpy (tmp, code, 5);
79     tmp [5] = 0;
80     if (sscanf (tmp, "%x", &address) != 1)
81         return ("Invalid Gold Finger code.");
82
83     int i;
84     for (i = 0; i < 3; i++)
85     {
86         strncpy (tmp, code + 5 + i * 2, 2);
87         tmp [2] = 0;
88         int byte;
89         if (sscanf (tmp, "%x", &byte) != 1)
90             break;
91         bytes [i] = (uint8) byte;
92     }
93     num_bytes = i;
94     sram = code [13] == '1';
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) ||
103         !S9xAllHex (code + 5, 4))
104         return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'.");
105
106     strcpy (new_code, "0x");
107     strncpy (new_code + 2, code, 4);
108     strcpy (new_code + 6, code + 5);
109
110     static const char *real_hex  = "0123456789ABCDEF";
111     static const char *genie_hex = "DF4709156BC8A23E";
112
113     for (int i = 2; i < 10; i++)
114     {
115         if (islower (new_code [i]))
116             new_code [i] = toupper (new_code [i]);
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         if (j == 16)
127             return ("Invalid hex-character in Game Genie(tm) code");
128     }
129     uint32 data = 0;
130     sscanf (new_code, "%x", &data);
131     byte = (uint8)(data >> 24);
132     address = data & 0xffffff;
133     address = ((address & 0x003c00) << 10) +
134               ((address & 0x00003c) << 14) +
135               ((address & 0xf00000) >>  8) +
136               ((address & 0x000003) << 10) +
137               ((address & 0x00c000) >>  6) +
138               ((address & 0x0f0000) >> 12) +
139               ((address & 0x0003c0) >>  6);
140
141     return (NULL);
142 }
143
144 void S9xStartCheatSearch (SCheatData *d)
145 {
146     memmove (d->CWRAM, d->RAM, 0x20000);
147     memmove (d->CSRAM, d->SRAM, 0x10000);
148     memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000);
149     memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3);
150     memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3);
151     memset ((char *) d->IRAM_BITS, 0xff, 0x2000 >> 3);
152 }
153
154 #define BIT_CLEAR(a,v) \
155 (a)[(v) >> 5] &= ~(1 << ((v) & 31))
156
157 #define BIT_SET(a,v) \
158 (a)[(v) >> 5] |= 1 << ((v) & 31)
159
160 #define TEST_BIT(a,v) \
161 ((a)[(v) >> 5] & (1 << ((v) & 31)))
162
163 #define _C(c,a,b) \
164 ((c) == S9X_LESS_THAN ? (a) < (b) : \
165  (c) == S9X_GREATER_THAN ? (a) > (b) : \
166  (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \
167  (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \
168  (c) == S9X_EQUAL ? (a) == (b) : \
169  (a) != (b))
170
171 #define _D(s,m,o) \
172 ((s) == S9X_8_BITS ? (uint8) (*((m) + (o))) : \
173  (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \
174  (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \
175 ((uint32)  (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24))))
176
177 #define _DS(s,m,o) \
178 ((s) == S9X_8_BITS ? ((int8) *((m) + (o))) : \
179  (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \
180  (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \
181  ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24))))
182
183 void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, 
184                          S9xCheatDataSize size, bool8 is_signed, bool8 update)
185 {
186     int l;
187
188     switch (size)
189     {
190     case S9X_8_BITS: l = 0; break;
191     case S9X_16_BITS: l = 1; break;
192     case S9X_24_BITS: l = 2; break;
193     default:
194     case S9X_32_BITS: l = 3; break;
195     }
196
197     int i;
198     if (is_signed)
199     {
200         for (i = 0; i < 0x20000 - l; i++)
201         {
202             if (TEST_BIT (d->WRAM_BITS, i) &&
203                 _C(cmp, _DS(size, d->RAM, i), _DS(size, d->CWRAM, i)))
204             {
205                 if (update)
206                     d->CWRAM [i] = d->RAM [i];
207             }
208             else
209                 BIT_CLEAR (d->WRAM_BITS, i);
210         }
211         
212         for (i = 0; i < 0x10000 - l; i++)
213         {
214             if (TEST_BIT (d->SRAM_BITS, i) &&
215                 _C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i)))
216             {
217                 if (update)
218                     d->CSRAM [i] = d->SRAM [i];
219             }
220             else
221                 BIT_CLEAR (d->SRAM_BITS, i);
222         }
223         
224         for (i = 0; i < 0x2000 - l; i++)
225         {
226             if (TEST_BIT (d->IRAM_BITS, i) &&
227                 _C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i)))
228             {
229                 if (update)
230                     d->CIRAM [i] = d->FillRAM [i + 0x3000];
231             }
232             else
233                 BIT_CLEAR (d->IRAM_BITS, i);
234         }
235     }
236     else
237     {
238         for (i = 0; i < 0x20000 - l; i++)
239         {
240             if (TEST_BIT (d->WRAM_BITS, i) &&
241                 _C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i)))
242             {
243                 if (update)
244                     d->CWRAM [i] = d->RAM [i];
245             }
246             else
247                 BIT_CLEAR (d->WRAM_BITS, i);
248         }
249         
250         for (i = 0; i < 0x10000 - l; i++)
251         {
252             if (TEST_BIT (d->SRAM_BITS, i) &&
253                 _C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i)))
254             {
255                 if (update)
256                     d->CSRAM [i] = d->SRAM [i];
257             }
258             else
259                 BIT_CLEAR (d->SRAM_BITS, i);
260         }
261         
262         for (i = 0; i < 0x2000 - l; i++)
263         {
264             if (TEST_BIT (d->IRAM_BITS, i) &&
265                 _C(cmp, _D(size, d->FillRAM + 0x3000, i), _D(size, d->CIRAM, i)))
266             {
267                 if (update)
268                     d->CIRAM [i] = d->FillRAM [i + 0x3000];
269             }
270             else
271                 BIT_CLEAR (d->IRAM_BITS, i);
272         }
273     }
274 }
275
276 void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, 
277                         S9xCheatDataSize size, uint32 value, 
278                         bool8 is_signed, bool8 update)
279 {
280     int l;
281
282     switch (size)
283     {
284     case S9X_8_BITS: l = 0; break;
285     case S9X_16_BITS: l = 1; break;
286     case S9X_24_BITS: l = 2; break;
287     default:
288     case S9X_32_BITS: l = 3; break;
289     }
290
291     int i;
292
293     if (is_signed)
294     {
295         for (i = 0; i < 0x20000 - l; i++)
296         {
297             if (TEST_BIT (d->WRAM_BITS, i) &&
298                 _C(cmp, _DS(size, d->RAM, i), (int32) value))
299             {
300                 if (update)
301                     d->CWRAM [i] = d->RAM [i];
302             }
303             else
304                 BIT_CLEAR (d->WRAM_BITS, i);
305         }
306         
307         for (i = 0; i < 0x10000 - l; i++)
308         {
309             if (TEST_BIT (d->SRAM_BITS, i) &&
310                 _C(cmp, _DS(size, d->SRAM, i), (int32) value))
311             {
312                 if (update)
313                     d->CSRAM [i] = d->SRAM [i];
314             }
315             else
316                 BIT_CLEAR (d->SRAM_BITS, i);
317         }
318         
319         for (i = 0; i < 0x2000 - l; i++)
320         {
321             if (TEST_BIT (d->IRAM_BITS, i) &&
322                 _C(cmp, _DS(size, d->FillRAM + 0x3000, i), (int32) value))
323             {
324                 if (update)
325                     d->CIRAM [i] = d->FillRAM [i + 0x3000];
326             }
327             else
328                 BIT_CLEAR (d->IRAM_BITS, i);
329         }
330     }
331     else
332     {
333         for (i = 0; i < 0x20000 - l; i++)
334         {
335             if (TEST_BIT (d->WRAM_BITS, i) &&
336                 _C(cmp, _D(size, d->RAM, i), value))
337             {
338                 if (update)
339                     d->CWRAM [i] = d->RAM [i];
340             }
341             else
342                 BIT_CLEAR (d->WRAM_BITS, i);
343         }
344         
345         for (i = 0; i < 0x10000 - l; i++)
346         {
347             if (TEST_BIT (d->SRAM_BITS, i) &&
348                 _C(cmp, _D(size, d->SRAM, i), value))
349             {
350                 if (update)
351                     d->CSRAM [i] = d->SRAM [i];
352             }
353             else
354                 BIT_CLEAR (d->SRAM_BITS, i);
355         }
356         
357         for (i = 0; i < 0x2000 - l; i++)
358         {
359             if (TEST_BIT (d->IRAM_BITS, i) &&
360                 _C(cmp, _D(size, d->FillRAM + 0x3000, i), value))
361             {
362                 if (update)
363                     d->CIRAM [i] = d->FillRAM [i + 0x3000];
364             }
365             else
366                 BIT_CLEAR (d->IRAM_BITS, i);
367         }
368     }
369 }
370
371 void S9xOutputCheatSearchResults (SCheatData *d)
372 {
373     int i;
374     for (i = 0; i < 0x20000; i++)
375     {
376         if (TEST_BIT (d->WRAM_BITS, i))
377             printf ("WRAM: %05x: %02x\n", i, d->RAM [i]);
378     }
379
380     for (i = 0; i < 0x10000; i++)
381     {
382         if (TEST_BIT (d->SRAM_BITS, i))
383             printf ("SRAM: %04x: %02x\n", i, d->SRAM [i]);
384     }
385
386     for (i = 0; i < 0x2000; i++)
387     {
388         if (TEST_BIT (d->IRAM_BITS, i))
389             printf ("IRAM: %05x: %02x\n", i, d->FillRAM [i + 0x3000]);
390     }
391 }