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 | |
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 |
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 | |
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 | |