ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / mupen64plus-core / src / main / cheat.c
CommitLineData
451ab91e 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
46typedef struct cheat_code {
47 unsigned int address;
48 int value;
49 int old_value;
50 struct list_head list;
51} cheat_code_t;
52
53typedef 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
62static LIST_HEAD(active_cheats);
63static SDL_mutex *cheat_mutex = NULL;
64
65// private functions
66static unsigned short read_address_16bit(unsigned int address)
67{
68 return *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
69}
70
71static unsigned char read_address_8bit(unsigned int address)
72{
73 return *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
74}
75
76static void update_address_16bit(unsigned int address, unsigned short new_value)
77{
78 *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16))) = new_value;
79}
80
81static void update_address_8bit(unsigned int address, unsigned char new_value)
82{
83 *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8))) = new_value;
84}
85
86static 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
93static 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)
102static 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
148static 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
188void cheat_init(void)
189{
190 cheat_mutex = SDL_CreateMutex();
191}
192
193void cheat_uninit(void)
194{
195 if (cheat_mutex != NULL)
196 SDL_DestroyMutex(cheat_mutex);
197 cheat_mutex = NULL;
198}
199
200void 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
2d262872 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;
451ab91e 212 if (sl(ROM_HEADER.CRC1) == 0xEC7011B7 && sl(ROM_HEADER.CRC2) == 0x7616D72B) {
213 // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.0)
2d262872 214 subscreen_address = 0x801DA5CB;
451ab91e 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)
2d262872 217 subscreen_address = 0x801DA78B;
451ab91e 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)
2d262872 220 subscreen_address = 0x801DAE8B;
451ab91e 221 } else if (sl(ROM_HEADER.CRC1) == 0xB044B569 && sl(ROM_HEADER.CRC2) == 0x373C1985) {
222 // Legend of Zelda, The - Ocarina of Time (E) (V1.0)
2d262872 223 subscreen_address = 0x801D860B;
451ab91e 224 } else if (sl(ROM_HEADER.CRC1) == 0xB2055FBD && sl(ROM_HEADER.CRC2) == 0x0BAB4E0C) {
225 // Legend of Zelda, The - Ocarina of Time (E) (V1.1)
2d262872 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;
451ab91e 277 } else {
2d262872 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 }
451ab91e 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
408void 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
436int 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
462int 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