ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / mupen64plus-core / src / main / cheat.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - cheat.c                                                 *
3  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
4  *   Copyright (C) 2009 Richard Goedeken                                   *
5  *   Copyright (C) 2008 Okaygo                                             *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
21  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22
23 // gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html 
24
25 #include <SDL.h>
26 #include <SDL_thread.h>
27
28 #include "api/m64p_types.h"
29 #include "api/callbacks.h"
30 #include "api/config.h"
31
32 #include "memory/memory.h"
33 #include "osal/preproc.h"
34 #include "cheat.h"
35 #include "main.h"
36 #include "rom.h"
37 #include "eventloop.h"
38 #include "list.h"
39
40 #include <stdio.h>
41 #include <string.h>
42
43 // local definitions
44 #define CHEAT_CODE_MAGIC_VALUE 0xDEAD0000
45
46 typedef struct cheat_code {
47     unsigned int address;
48     int value;
49     int old_value;
50     struct list_head list;
51 } cheat_code_t;
52
53 typedef struct cheat {
54     char *name;
55     int enabled;
56     int was_enabled;
57     struct list_head cheat_codes;
58     struct list_head list;
59 } cheat_t;
60
61 // local variables
62 static LIST_HEAD(active_cheats);
63 static SDL_mutex *cheat_mutex = NULL;
64
65 // private functions
66 static unsigned short read_address_16bit(unsigned int address)
67 {
68     return *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
69 }
70
71 static unsigned char read_address_8bit(unsigned int address)
72 {
73     return *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
74 }
75
76 static void update_address_16bit(unsigned int address, unsigned short new_value)
77 {
78     *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16))) = new_value;
79 }
80
81 static void update_address_8bit(unsigned int address, unsigned char new_value)
82 {
83     *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8))) = new_value;
84 }
85
86 static int address_equal_to_8bit(unsigned int address, unsigned char value)
87 {
88     unsigned char value_read;
89     value_read = *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
90     return value_read == value;
91 }
92
93 static int address_equal_to_16bit(unsigned int address, unsigned short value)
94 {
95     unsigned short value_read;
96     value_read = *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
97     return value_read == value;
98 }
99
100 // individual application - returns 0 if we are supposed to skip the next cheat
101 // (only really used on conditional codes)
102 static int execute_cheat(unsigned int address, unsigned short value, int *old_value)
103 {
104     switch (address & 0xFF000000)
105     {
106         case 0x80000000:
107         case 0x88000000:
108         case 0xA0000000:
109         case 0xA8000000:
110         case 0xF0000000:
111             // if pointer to old value is valid and uninitialized, write current value to it
112             if(old_value && (*old_value == CHEAT_CODE_MAGIC_VALUE))
113                 *old_value = (int) read_address_8bit(address);
114             update_address_8bit(address,(unsigned char) value);
115             return 1;
116         case 0x81000000:
117         case 0x89000000:
118         case 0xA1000000:
119         case 0xA9000000:
120         case 0xF1000000:
121             // if pointer to old value is valid and uninitialized, write current value to it
122             if(old_value && (*old_value == CHEAT_CODE_MAGIC_VALUE))
123                 *old_value = (int) read_address_16bit(address);
124             update_address_16bit(address,value);
125             return 1;
126         case 0xD0000000:
127         case 0xD8000000:
128             return address_equal_to_8bit(address,(unsigned char) value);
129         case 0xD1000000:
130         case 0xD9000000:
131             return address_equal_to_16bit(address,value);
132         case 0xD2000000:
133         case 0xDB000000:
134             return !(address_equal_to_8bit(address,(unsigned char) value));
135         case 0xD3000000:
136         case 0xDA000000:
137             return !(address_equal_to_16bit(address,value));
138         case 0xEE000000:
139             // most likely, this doesnt do anything.
140             execute_cheat(0xF1000318, 0x0040, NULL);
141             execute_cheat(0xF100031A, 0x0000, NULL);
142             return 1;
143         default:
144             return 1;
145     }
146 }
147
148 static cheat_t *find_or_create_cheat(const char *name)
149 {
150     cheat_t *cheat;
151     int found = 0;
152
153     list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
154         if (strcmp(cheat->name, name) == 0) {
155             found = 1;
156             break;
157         }
158     }
159
160     if (found)
161     {
162         /* delete any pre-existing cheat codes */
163         cheat_code_t *code, *safe;
164
165         list_for_each_entry_safe(code, safe, &cheat->cheat_codes, cheat_code_t, list) {
166              list_del(&code->list);
167              free(code);
168         }
169
170         cheat->enabled = 0;
171         cheat->was_enabled = 0;
172     }
173     else
174     {
175         cheat = malloc(sizeof(*cheat));
176         cheat->name = strdup(name);
177         cheat->enabled = 0;
178         cheat->was_enabled = 0;
179         INIT_LIST_HEAD(&cheat->cheat_codes);
180         list_add_tail(&cheat->list, &active_cheats);
181     }
182
183     return cheat;
184 }
185
186
187 // public functions
188 void cheat_init(void)
189 {
190     cheat_mutex = SDL_CreateMutex();
191 }
192
193 void cheat_uninit(void)
194 {
195     if (cheat_mutex != NULL)
196         SDL_DestroyMutex(cheat_mutex);
197     cheat_mutex = NULL;
198 }
199
200 void cheat_apply_cheats(int entry)
201 {
202     cheat_t *cheat;
203     cheat_code_t *code;
204     int skip;
205     int execute_next;
206
207     // If game is Zelda OOT, apply subscreen delay fix
208     if (entry == ENTRY_VI && strncmp((char *)ROM_HEADER.Name, "THE LEGEND OF ZELDA", 19) == 0) {
209         uint32_t subscreen_address = 0;
210         uint32_t credits_address[4];
211         credits_address[0] = 0;
212         if (sl(ROM_HEADER.CRC1) == 0xEC7011B7 && sl(ROM_HEADER.CRC2) == 0x7616D72B) {
213             // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.0)
214             subscreen_address = 0x801DA5CB;
215         } else if (sl(ROM_HEADER.CRC1) == 0xD43DA81F && sl(ROM_HEADER.CRC2) == 0x021E1E19) {
216             // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.1)
217             subscreen_address = 0x801DA78B;
218         } else if (sl(ROM_HEADER.CRC1) == 0x693BA2AE && sl(ROM_HEADER.CRC2) == 0xB7F14E9F) {
219             // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.2)
220             subscreen_address = 0x801DAE8B;
221         } else if (sl(ROM_HEADER.CRC1) == 0xB044B569 && sl(ROM_HEADER.CRC2) == 0x373C1985) {
222             // Legend of Zelda, The - Ocarina of Time (E) (V1.0)
223             subscreen_address = 0x801D860B;
224         } else if (sl(ROM_HEADER.CRC1) == 0xB2055FBD && sl(ROM_HEADER.CRC2) == 0x0BAB4E0C) {
225             // Legend of Zelda, The - Ocarina of Time (E) (V1.1)
226             subscreen_address = 0x801D864B;
227         // GC Versions such as Master Quest also require the End Credits Fix.
228         } else if (sl(ROM_HEADER.CRC1) == 0x1D4136F3 && sl(ROM_HEADER.CRC2) == 0xAF63EEA9) {
229             // Legend of Zelda, The - Ocarina of Time - Master Quest (E) (GC Version)
230             subscreen_address = 0x801D8F4B;
231             credits_address[0] = 0xD109A8C4;
232             credits_address[1] = 0x8109A8C4;
233             credits_address[2] = 0xD109A8C6;
234             credits_address[3] = 0x8109A8C6;
235         } else if (sl(ROM_HEADER.CRC1) == 0x09465AC3 && sl(ROM_HEADER.CRC2) == 0xF8CB501B) {
236             // Legend of Zelda, The - Ocarina of Time (E) (GC Version)
237             subscreen_address = 0x801D8F8B;
238             credits_address[0] = 0xD109A8E4;
239             credits_address[1] = 0x8109A8E4;
240             credits_address[2] = 0xD109A8E6;
241             credits_address[3] = 0x8109A8E6;
242         } else if (sl(ROM_HEADER.CRC1) == 0xF3DD35BA && sl(ROM_HEADER.CRC2) == 0x4152E075) {
243             // Legend of Zelda, The - Ocarina of Time (U) (GC Version)
244             subscreen_address = 0x801DB78B;
245             credits_address[0] = 0xD109A814;
246             credits_address[1] = 0x8109A814;
247             credits_address[2] = 0xD109A816;
248             credits_address[3] = 0x8109A816;
249         } else if (sl(ROM_HEADER.CRC1) == 0xF034001A && sl(ROM_HEADER.CRC2) == 0xAE47ED06) {
250             // Legend of Zelda, The - Ocarina of Time - Master Quest (U) (GC Version)
251             subscreen_address = 0x801DB74B;
252             credits_address[0] = 0xD109A7F4;
253             credits_address[1] = 0x8109A7F4;
254             credits_address[2] = 0xD109A7F6;
255             credits_address[3] = 0x8109A7F6;
256         } else if (sl(ROM_HEADER.CRC1) == 0xF7F52DB8 && sl(ROM_HEADER.CRC2) == 0x2195E636) {
257             // Zelda no Densetsu - Toki no Ocarina - Zelda Collection Version (J) (GC Version)
258             subscreen_address = 0x801DB78B;
259             credits_address[0] = 0xD109A814;
260             credits_address[1] = 0x8109A814;
261             credits_address[2] = 0xD109A816;
262             credits_address[3] = 0x8109A816;
263         } else if (sl(ROM_HEADER.CRC1) == 0xF611F4BA && sl(ROM_HEADER.CRC2) == 0xC584135C) {
264             // Zelda no Densetsu - Toki no Ocarina GC (J) (GC Version)
265             subscreen_address = 0x801DB78B;
266             credits_address[0] = 0xD109A834;
267             credits_address[1] = 0x8109A834;
268             credits_address[2] = 0xD109A836;
269             credits_address[3] = 0x8109A836;
270         } else if (sl(ROM_HEADER.CRC1) == 0xF43B45BA && sl(ROM_HEADER.CRC2) == 0x2F0E9B6F) {
271             // Zelda no Densetsu - Toki no Ocarina GC Ura (J) (GC Version)
272             subscreen_address = 0x801DB78B;
273             credits_address[0] = 0xD109A814;
274             credits_address[1] = 0x8109A814;
275             credits_address[2] = 0xD109A816;
276             credits_address[3] = 0x8109A816;
277         } else {
278             // UNKNOWN VERSION
279             DebugMessage(M64MSG_WARNING, "Warning: Ocarina of Time version could not be determined.  No fixes applied.");
280         }
281         if (subscreen_address) {
282             execute_cheat(subscreen_address, 0x0002, NULL);
283             if (credits_address[0]){
284                 if (execute_cheat(credits_address[0], 0x0320, NULL));
285                     execute_cheat(credits_address[1], 0x0000, NULL);
286                 if (execute_cheat(credits_address[2], 0xF809, NULL));
287                     execute_cheat(credits_address[3], 0x0000, NULL);
288             }
289         }
290     }
291     
292     if (list_empty(&active_cheats))
293         return;
294
295     if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
296     {
297         DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_apply_cheats()");
298         return;
299     }
300
301     list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
302         if (cheat->enabled)
303         {
304             cheat->was_enabled = 1;
305             switch(entry)
306             {
307                 case ENTRY_BOOT:
308                     list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
309                         // code should only be written once at boot time
310                         if((code->address & 0xF0000000) == 0xF0000000)
311                             execute_cheat(code->address, code->value, &code->old_value);
312                     }
313                     break;
314                 case ENTRY_VI:
315                     skip = 0;
316                     execute_next = 0;
317                     list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
318                         if (skip) {
319                             skip = 0;
320                             continue;
321                         }
322                         if (execute_next) {
323                             execute_next = 0;
324
325                             // if code needs GS button pressed, don't save old value
326                             if(((code->address & 0xFF000000) == 0xD8000000 ||
327                                 (code->address & 0xFF000000) == 0xD9000000 ||
328                                 (code->address & 0xFF000000) == 0xDA000000 ||
329                                 (code->address & 0xFF000000) == 0xDB000000))
330                                execute_cheat(code->address, code->value, NULL);
331                             else
332                                execute_cheat(code->address, code->value, &code->old_value);
333
334                             continue;
335                         }
336                         // conditional cheat codes
337                         if((code->address & 0xF0000000) == 0xD0000000)
338                         {
339                             // if code needs GS button pressed and it's not, skip it
340                             if(((code->address & 0xFF000000) == 0xD8000000 ||
341                                 (code->address & 0xFF000000) == 0xD9000000 ||
342                                 (code->address & 0xFF000000) == 0xDA000000 ||
343                                 (code->address & 0xFF000000) == 0xDB000000) &&
344                                !event_gameshark_active())
345                             {
346                                 // skip next code
347                                 skip = 1;
348                                 continue;
349                             }
350
351                             if (execute_cheat(code->address, code->value, NULL)) {
352                                 // if condition true, execute next cheat code
353                                 execute_next = 1;
354                             } else {
355                                 // if condition false, skip next code
356                                 skip = 1;
357                                 continue;
358                             }
359                         }
360                         // GS button triggers cheat code
361                         else if((code->address & 0xFF000000) == 0x88000000 ||
362                                 (code->address & 0xFF000000) == 0x89000000 ||
363                                 (code->address & 0xFF000000) == 0xA8000000 ||
364                                 (code->address & 0xFF000000) == 0xA9000000)
365                         {
366                             if(event_gameshark_active())
367                                 execute_cheat(code->address, code->value, NULL);
368                         }
369                         // normal cheat code
370                         else
371                         {
372                             // exclude boot-time cheat codes
373                             if((code->address & 0xF0000000) != 0xF0000000)
374                                 execute_cheat(code->address, code->value, &code->old_value);
375                         }
376                     }
377                     break;
378                 default:
379                     break;
380             }
381         }
382         // if cheat was enabled, but is now disabled, restore old memory values
383         else if (cheat->was_enabled)
384         {
385             cheat->was_enabled = 0;
386             switch(entry)
387             {
388                 case ENTRY_VI:
389                     list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
390                         // set memory back to old value and clear saved copy of old value
391                         if(code->old_value != CHEAT_CODE_MAGIC_VALUE)
392                         {
393                             execute_cheat(code->address, code->old_value, NULL);
394                             code->old_value = CHEAT_CODE_MAGIC_VALUE;
395                         }
396                     }
397                     break;
398                 default:
399                     break;
400             }
401         }
402     }
403
404     SDL_UnlockMutex(cheat_mutex);
405 }
406
407
408 void cheat_delete_all(void)
409 {
410     cheat_t *cheat, *safe_cheat;
411     cheat_code_t *code, *safe_code;
412
413     if (list_empty(&active_cheats))
414         return;
415
416     if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
417     {
418         DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_delete_all()");
419         return;
420     }
421
422     list_for_each_entry_safe(cheat, safe_cheat, &active_cheats, cheat_t, list) {
423         free(cheat->name);
424
425         list_for_each_entry_safe(code, safe_code, &cheat->cheat_codes, cheat_code_t, list) {
426             list_del(&code->list);
427             free(code);
428         }
429         list_del(&cheat->list);
430         free(cheat);
431     }
432
433     SDL_UnlockMutex(cheat_mutex);
434 }
435
436 int cheat_set_enabled(const char *name, int enabled)
437 {
438     cheat_t *cheat = NULL;
439
440     if (list_empty(&active_cheats))
441         return 0;
442
443     if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
444     {
445         DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_set_enabled()");
446         return 0;
447     }
448
449     list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
450         if (strcmp(name, cheat->name) == 0)
451         {
452             cheat->enabled = enabled;
453             SDL_UnlockMutex(cheat_mutex);
454             return 1;
455         }
456     }
457
458     SDL_UnlockMutex(cheat_mutex);
459     return 0;
460 }
461
462 int cheat_add_new(const char *name, m64p_cheat_code *code_list, int num_codes)
463 {
464     cheat_t *cheat;
465     int i, j;
466
467     if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
468     {
469         DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_add_new()");
470         return 0;
471     }
472
473     /* create a new cheat function or erase the codes in an existing cheat function */
474     cheat = find_or_create_cheat(name);
475     if (cheat == NULL)
476     {
477         SDL_UnlockMutex(cheat_mutex);
478         return 0;
479     }
480
481     cheat->enabled = 1; /* default for new cheats is enabled */
482
483     for (i = 0; i < num_codes; i++)
484     {
485         /* if this is a 'patch' code, convert it and dump out all of the individual codes */
486         if ((code_list[i].address & 0xFFFF0000) == 0x50000000 && i < num_codes - 1)
487         {
488             int code_count = ((code_list[i].address & 0xFF00) >> 8);
489             int incr_addr = code_list[i].address & 0xFF;
490             int incr_value = code_list[i].value;
491             int cur_addr = code_list[i+1].address;
492             int cur_value = code_list[i+1].value;
493             i += 1;
494             for (j = 0; j < code_count; j++)
495             {
496                 cheat_code_t *code = malloc(sizeof(*code));
497                 code->address = cur_addr;
498                 code->value = cur_value;
499                 code->old_value = CHEAT_CODE_MAGIC_VALUE;
500                 list_add_tail(&code->list, &cheat->cheat_codes);
501                 cur_addr += incr_addr;
502                 cur_value += incr_value;
503             }
504         }
505         else
506         { /* just a normal code */
507             cheat_code_t *code = malloc(sizeof(*code));
508             code->address = code_list[i].address;
509             code->value = code_list[i].value;
510             code->old_value = CHEAT_CODE_MAGIC_VALUE;
511             list_add_tail(&code->list, &cheat->cheat_codes);
512         }
513     }
514
515     SDL_UnlockMutex(cheat_mutex);
516     return 1;
517 }
518
519