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 *
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. *
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. *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23 // gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html
26 #include <SDL_thread.h>
28 #include "api/m64p_types.h"
29 #include "api/callbacks.h"
30 #include "api/config.h"
32 #include "memory/memory.h"
33 #include "osal/preproc.h"
37 #include "eventloop.h"
44 #define CHEAT_CODE_MAGIC_VALUE 0xDEAD0000
46 typedef struct cheat_code {
50 struct list_head list;
53 typedef struct cheat {
57 struct list_head cheat_codes;
58 struct list_head list;
62 static LIST_HEAD(active_cheats);
63 static SDL_mutex *cheat_mutex = NULL;
66 static unsigned short read_address_16bit(unsigned int address)
68 return *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
71 static unsigned char read_address_8bit(unsigned int address)
73 return *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
76 static void update_address_16bit(unsigned int address, unsigned short new_value)
78 *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16))) = new_value;
81 static void update_address_8bit(unsigned int address, unsigned char new_value)
83 *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8))) = new_value;
86 static int address_equal_to_8bit(unsigned int address, unsigned char value)
88 unsigned char value_read;
89 value_read = *(unsigned char *)((rdramb + ((address & 0xFFFFFF)^S8)));
90 return value_read == value;
93 static int address_equal_to_16bit(unsigned int address, unsigned short value)
95 unsigned short value_read;
96 value_read = *(unsigned short *)((rdramb + ((address & 0xFFFFFF)^S16)));
97 return value_read == value;
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)
104 switch (address & 0xFF000000)
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);
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);
128 return address_equal_to_8bit(address,(unsigned char) value);
131 return address_equal_to_16bit(address,value);
134 return !(address_equal_to_8bit(address,(unsigned char) value));
137 return !(address_equal_to_16bit(address,value));
139 // most likely, this doesnt do anything.
140 execute_cheat(0xF1000318, 0x0040, NULL);
141 execute_cheat(0xF100031A, 0x0000, NULL);
148 static cheat_t *find_or_create_cheat(const char *name)
153 list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
154 if (strcmp(cheat->name, name) == 0) {
162 /* delete any pre-existing cheat codes */
163 cheat_code_t *code, *safe;
165 list_for_each_entry_safe(code, safe, &cheat->cheat_codes, cheat_code_t, list) {
166 list_del(&code->list);
171 cheat->was_enabled = 0;
175 cheat = malloc(sizeof(*cheat));
176 cheat->name = strdup(name);
178 cheat->was_enabled = 0;
179 INIT_LIST_HEAD(&cheat->cheat_codes);
180 list_add_tail(&cheat->list, &active_cheats);
188 void cheat_init(void)
190 cheat_mutex = SDL_CreateMutex();
193 void cheat_uninit(void)
195 if (cheat_mutex != NULL)
196 SDL_DestroyMutex(cheat_mutex);
200 void cheat_apply_cheats(int entry)
207 // If game is Zelda OOT, apply subscreen delay fix
208 if (strncmp((char *)ROM_HEADER.Name, "THE LEGEND OF ZELDA", 19) == 0 && entry == ENTRY_VI) {
209 if (sl(ROM_HEADER.CRC1) == 0xEC7011B7 && sl(ROM_HEADER.CRC2) == 0x7616D72B) {
210 // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.0)
211 execute_cheat(0x801DA5CB, 0x0002, NULL);
212 } else if (sl(ROM_HEADER.CRC1) == 0xD43DA81F && sl(ROM_HEADER.CRC2) == 0x021E1E19) {
213 // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.1)
214 execute_cheat(0x801DA78B, 0x0002, NULL);
215 } else if (sl(ROM_HEADER.CRC1) == 0x693BA2AE && sl(ROM_HEADER.CRC2) == 0xB7F14E9F) {
216 // Legend of Zelda, The - Ocarina of Time (U) + (J) (V1.2)
217 execute_cheat(0x801DAE8B, 0x0002, NULL);
218 } else if (sl(ROM_HEADER.CRC1) == 0xB044B569 && sl(ROM_HEADER.CRC2) == 0x373C1985) {
219 // Legend of Zelda, The - Ocarina of Time (E) (V1.0)
220 execute_cheat(0x801D860B, 0x0002, NULL);
221 } else if (sl(ROM_HEADER.CRC1) == 0xB2055FBD && sl(ROM_HEADER.CRC2) == 0x0BAB4E0C) {
222 // Legend of Zelda, The - Ocarina of Time (E) (V1.1)
223 execute_cheat(0x801D864B, 0x0002, NULL);
225 // Legend of Zelda, The - Ocarina of Time Master Quest
226 execute_cheat(0x801D8F4B, 0x0002, NULL);
230 if (list_empty(&active_cheats))
233 if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
235 DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_apply_cheats()");
239 list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
242 cheat->was_enabled = 1;
246 list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
247 // code should only be written once at boot time
248 if((code->address & 0xF0000000) == 0xF0000000)
249 execute_cheat(code->address, code->value, &code->old_value);
255 list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
263 // if code needs GS button pressed, don't save old value
264 if(((code->address & 0xFF000000) == 0xD8000000 ||
265 (code->address & 0xFF000000) == 0xD9000000 ||
266 (code->address & 0xFF000000) == 0xDA000000 ||
267 (code->address & 0xFF000000) == 0xDB000000))
268 execute_cheat(code->address, code->value, NULL);
270 execute_cheat(code->address, code->value, &code->old_value);
274 // conditional cheat codes
275 if((code->address & 0xF0000000) == 0xD0000000)
277 // if code needs GS button pressed and it's not, skip it
278 if(((code->address & 0xFF000000) == 0xD8000000 ||
279 (code->address & 0xFF000000) == 0xD9000000 ||
280 (code->address & 0xFF000000) == 0xDA000000 ||
281 (code->address & 0xFF000000) == 0xDB000000) &&
282 !event_gameshark_active())
289 if (execute_cheat(code->address, code->value, NULL)) {
290 // if condition true, execute next cheat code
293 // if condition false, skip next code
298 // GS button triggers cheat code
299 else if((code->address & 0xFF000000) == 0x88000000 ||
300 (code->address & 0xFF000000) == 0x89000000 ||
301 (code->address & 0xFF000000) == 0xA8000000 ||
302 (code->address & 0xFF000000) == 0xA9000000)
304 if(event_gameshark_active())
305 execute_cheat(code->address, code->value, NULL);
310 // exclude boot-time cheat codes
311 if((code->address & 0xF0000000) != 0xF0000000)
312 execute_cheat(code->address, code->value, &code->old_value);
320 // if cheat was enabled, but is now disabled, restore old memory values
321 else if (cheat->was_enabled)
323 cheat->was_enabled = 0;
327 list_for_each_entry(code, &cheat->cheat_codes, cheat_code_t, list) {
328 // set memory back to old value and clear saved copy of old value
329 if(code->old_value != CHEAT_CODE_MAGIC_VALUE)
331 execute_cheat(code->address, code->old_value, NULL);
332 code->old_value = CHEAT_CODE_MAGIC_VALUE;
342 SDL_UnlockMutex(cheat_mutex);
346 void cheat_delete_all(void)
348 cheat_t *cheat, *safe_cheat;
349 cheat_code_t *code, *safe_code;
351 if (list_empty(&active_cheats))
354 if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
356 DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_delete_all()");
360 list_for_each_entry_safe(cheat, safe_cheat, &active_cheats, cheat_t, list) {
363 list_for_each_entry_safe(code, safe_code, &cheat->cheat_codes, cheat_code_t, list) {
364 list_del(&code->list);
367 list_del(&cheat->list);
371 SDL_UnlockMutex(cheat_mutex);
374 int cheat_set_enabled(const char *name, int enabled)
376 cheat_t *cheat = NULL;
378 if (list_empty(&active_cheats))
381 if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
383 DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_set_enabled()");
387 list_for_each_entry(cheat, &active_cheats, cheat_t, list) {
388 if (strcmp(name, cheat->name) == 0)
390 cheat->enabled = enabled;
391 SDL_UnlockMutex(cheat_mutex);
396 SDL_UnlockMutex(cheat_mutex);
400 int cheat_add_new(const char *name, m64p_cheat_code *code_list, int num_codes)
405 if (cheat_mutex == NULL || SDL_LockMutex(cheat_mutex) != 0)
407 DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_add_new()");
411 /* create a new cheat function or erase the codes in an existing cheat function */
412 cheat = find_or_create_cheat(name);
415 SDL_UnlockMutex(cheat_mutex);
419 cheat->enabled = 1; /* default for new cheats is enabled */
421 for (i = 0; i < num_codes; i++)
423 /* if this is a 'patch' code, convert it and dump out all of the individual codes */
424 if ((code_list[i].address & 0xFFFF0000) == 0x50000000 && i < num_codes - 1)
426 int code_count = ((code_list[i].address & 0xFF00) >> 8);
427 int incr_addr = code_list[i].address & 0xFF;
428 int incr_value = code_list[i].value;
429 int cur_addr = code_list[i+1].address;
430 int cur_value = code_list[i+1].value;
432 for (j = 0; j < code_count; j++)
434 cheat_code_t *code = malloc(sizeof(*code));
435 code->address = cur_addr;
436 code->value = cur_value;
437 code->old_value = CHEAT_CODE_MAGIC_VALUE;
438 list_add_tail(&code->list, &cheat->cheat_codes);
439 cur_addr += incr_addr;
440 cur_value += incr_value;
444 { /* just a normal code */
445 cheat_code_t *code = malloc(sizeof(*code));
446 code->address = code_list[i].address;
447 code->value = code_list[i].value;
448 code->old_value = CHEAT_CODE_MAGIC_VALUE;
449 list_add_tail(&code->list, &cheat->cheat_codes);
453 SDL_UnlockMutex(cheat_mutex);