/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996, 1997, 1998 Gary Henderson (gary@daniver.demon.co.uk) and * Jerremy Koot (jkoot@euronet.nl) * * Super FX C emulator code * (c) Copyright 1997, 1998 Lestat (lstat@hotmail.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Lestat and Gary Henderson. * DOS port code contains the works of other authors. See headers in * individual files. * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */ #include #include #include #include "snes9x.h" #include "cheats.h" #include "memmap.h" extern SCheats Cheats [10]; extern int num_cheats; const char *S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) { uint32 data = 0; if (strlen (code) != 8 || sscanf (code, "%x", &data) != 1) return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); address = data >> 8; byte = (uint8) address; return (NULL); } const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3]) { char tmp [15]; uint32 data = 0; if (strlen (code) != 14) return ("Invalid Gold Finger code should be 14 hex digits in length."); strncpy (tmp, code, 5); tmp [5] = 0; if (sscanf (tmp, "%x", &address) != 1) return ("Invalid Gold Finger code."); int i; for (i = 0; i < 3; i++) { strncpy (tmp, code + 5 + i * 2, 2); tmp [2] = 0; int byte; if (sscanf (tmp, "%x", &byte) != 1) break; bytes [i] = (uint8) byte; } num_bytes = i; sram = code [13] == '1'; return (NULL); } const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) { char new_code [12]; if (strlen (code) != 9 || *(code + 4) != '-') return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); strcpy (new_code, "0x"); strncpy (new_code + 2, code, 4); strcpy (new_code + 6, code + 5); static char *real_hex = "0123456789ABCDEF"; static char *genie_hex = "DF4709156BC8A23E"; for (int i = 2; i < 10; i++) { if (islower (new_code [i])) new_code [i] = toupper (new_code [i]); int j; for (j = 0; j < 16; j++) { if (new_code [i] == genie_hex [j]) { new_code [i] = real_hex [j]; break; } } if (j == 16) return ("Invalid hex-character in Game Genie(tm) code"); } uint32 data = 0; sscanf (new_code, "%x", &data); byte = (uint8)(data >> 24); address = data & 0xffffff; address = ((address & 0x003C00) * 0x0400) + // {abcd} ((address & 0x00003C) * 0x4000) + // {efgh} ((address & 0xF00000) / 0x0100) + // {ijkl} ((address & 0x000003) * 0x0400) + // {mn} ((address & 0x00C000) / 0x0040) + // {op} ((address & 0x0F0000) / 0x1000) + // {qrst} ((address & 0x0003C0) / 0x0040); // {uvwx} return (NULL); } void S9xAddCheat (uint32 address, bool8 cpu_address, bool8 sram, uint8 num_bytes, uint8 byte1, uint8 byte2, uint8 byte3) { if (num_cheats < sizeof (Cheats) / sizeof (Cheats [0])) { Cheats [num_cheats].address = address; Cheats [num_cheats].cpu_address = cpu_address; Cheats [num_cheats].sram = sram; Cheats [num_cheats].num_bytes = num_bytes; Cheats [num_cheats].bytes [0] = byte1; Cheats [num_cheats].bytes [1] = byte2; Cheats [num_cheats].bytes [2] = byte3; num_cheats++; } } void S9xDeleteCheats () { RemoveCheats (); num_cheats = 0; } void RemoveCheats () { S9xApplyCheats (FALSE); } void S9xApplyCheats (bool8 apply) { for (int i = 0; i < num_cheats; i++) { for (int j = 0; j < Cheats [i].num_bytes; j++) { uint32 address = Cheats [i].address + j; if (Cheats [i].cpu_address) { uint32 block = (address >> 13) & 0x7ff; if (Memory.BlockIsROM [block]) address = Memory.Map [block] - Memory.ROM + (address & 0xffff); else continue; } address %= CMemory::MAX_ROM_SIZE; if (Cheats [i].sram) { if (!apply) Memory.SRAM [address & Memory.SRAMMask] = Cheats [i].saved_bytes [j]; else { Cheats [i].saved_bytes [j] = Memory.SRAM [address & Memory.SRAMMask]; Memory.SRAM [address & Memory.SRAMMask] = Cheats [i].bytes[j]; } } else { if (!apply) Memory.ROM [address] = Cheats [i].saved_bytes [j]; else { Cheats [i].saved_bytes [j] = Memory.ROM [address]; Memory.ROM [address] = Cheats [i].bytes[j]; } } } } }