Revamping cheats support.

This commit is contained in:
Brandon Wright 2018-04-25 19:29:26 -05:00
parent c727189d3e
commit 0d102b72ff
12 changed files with 451 additions and 290 deletions

59
bml.cpp
View File

@ -12,6 +12,8 @@ static inline bml_node *bml_node_new(void)
node->data = NULL;
node->name = NULL;
node->depth = -1;
return node;
}
static char *strndup_trim (char *str, int len)
@ -45,14 +47,14 @@ static inline unsigned int bml_read_depth (char *data)
return depth;
}
static unsigned int bml_parse_depth (bml_node *node, char **data)
static void bml_parse_depth (bml_node *node, char **data)
{
unsigned int depth = bml_read_depth (*data);
*data += depth;
node->depth = depth;
}
static char *bml_parse_name (bml_node *node, char **data)
static void bml_parse_name (bml_node *node, char **data)
{
int len;
@ -70,7 +72,7 @@ static void bml_parse_data (bml_node *node, char **data)
if (p[0] == '=' && p[1] == '\"')
{
len = 2;
while (p[len] && !islf (p[len]))
while (p[len] && p[len] != '\"' && !islf (p[len]))
len++;
if (p[len] != '\"')
return;
@ -177,7 +179,8 @@ static void bml_parse_attr (bml_node *node, char **data)
n->name = strndup_trim (p, len);
p += len;
bml_parse_data (n, &p);
node->attr.push_back (n);
n->depth = bml_attr_type;
node->child.push_back (n);
}
*data = p;
@ -196,10 +199,12 @@ static int contains_space (char *str)
static void bml_print_node (bml_node *node, int depth)
{
int i;
if (!node)
return;
for (int i = 0; i < depth * 2; i++)
for (i = 0; i < depth * 2; i++)
{
printf (" ");
}
@ -210,22 +215,21 @@ static void bml_print_node (bml_node *node, int depth)
if (node->data)
{
if (contains_space (node->data))
printf (": \"%s\"", node->data);
printf ("=\"%s\"", node->data);
else
printf (": %s", node->data);
}
for (int i = 0; i < node->attr.size(); i++)
for (i = 0; i < (int) node->child.size () && node->child[i]->depth == bml_attr_type; i++)
{
if (node->attr[i]->name)
if (node->child[i]->name)
{
printf (" %s", node->attr[i]->name);
if (node->attr[i]->data)
printf (" %s", node->child[i]->name);
if (node->child[i]->data)
{
if (contains_space (node->attr[i]->data))
printf ("=\"%s\"", node->attr[i]->data);
if (contains_space (node->child[i]->data))
printf ("=\"%s\"", node->child[i]->data);
else
printf ("=%s", node->attr[i]->data);
printf ("=%s", node->child[i]->data);
}
}
}
@ -233,7 +237,7 @@ static void bml_print_node (bml_node *node, int depth)
if (depth >= 0)
printf ("\n");
for (int i = 0; i < node->child.size(); i++)
for (; i < (int) node->child.size(); i++)
{
bml_print_node (node->child[i], depth + 1);
}
@ -265,7 +269,7 @@ static bml_node *bml_parse_node (char **doc)
return NULL;
bml_skip_empty (doc);
while (*doc && bml_read_depth (*doc) > node->depth)
while (*doc && (int) bml_read_depth (*doc) > node->depth)
{
bml_node *child = bml_parse_node (doc);
@ -283,18 +287,12 @@ void bml_free_node (bml_node *node)
delete[] (node->name);
delete[] (node->data);
for (int i = 0; i < node->child.size(); i++)
for (unsigned int i = 0; i < node->child.size(); i++)
{
bml_free_node (node->child[i]);
delete node->child[i];
}
for (int i = 0; i < node->attr.size(); i++)
{
bml_free_node (node->attr[i]);
delete node->attr[i];
}
return;
}
@ -320,7 +318,20 @@ bml_node *bml_parse (char **doc)
return root;
}
bml_node *bml_parse_file (char *filename)
bml_node *bml_find_sub (bml_node *n, const char *name)
{
unsigned int i;
for (i = 0; i < n->child.size (); i++)
{
if (!strcasecmp (n->child[i]->name, name))
return n->child[i];
}
return NULL;
}
bml_node *bml_parse_file (const char *filename)
{
FILE *file = NULL;
char *buffer = NULL;

7
bml.h
View File

@ -2,6 +2,8 @@
#define __BML_H
#include <vector>
const int bml_attr_type = -2;
typedef struct bml_node
{
char *name;
@ -9,12 +11,13 @@ typedef struct bml_node
int depth;
std::vector<bml_node *> attr;
std::vector<bml_node *> child;
} bml_node;
bml_node *bml_parse_file (char *filename);
bml_node *bml_find_sub (bml_node *node, const char *name);
bml_node *bml_parse_file (const char *filename);
/* Parse character array into BML tree. Destructive to input. */
bml_node *bml_parse (char **buffer);

View File

@ -193,22 +193,30 @@
#ifndef _CHEATS_H_
#define _CHEATS_H_
#define MAX_CHEATS 150
#include "port.h"
#include <vector>
struct SCheat
{
uint32 address;
uint8 byte;
uint8 saved_byte;
bool8 conditional;
bool8 cond_true;
uint8 cond_byte;
bool8 enabled;
bool8 saved;
char name[22];
};
struct SCheatGroup
{
char *name;
bool8 enabled;
std::vector<struct SCheat> c;
};
struct SCheatData
{
struct SCheat c[MAX_CHEATS];
uint32 num_cheats;
std::vector<struct SCheatGroup> g;
uint8 CWRAM[0x20000];
uint8 CSRAM[0x10000];
uint8 CIRAM[0x2000];
@ -250,20 +258,20 @@ typedef enum
extern SCheatData Cheat;
extern Watch watches[16];
void S9xApplyCheat (uint32);
void S9xApplyCheats (void);
void S9xRemoveCheat (uint32);
void S9xRemoveCheats (void);
void S9xDeleteCheat (uint32);
int S9xAddCheatGroup (const char *name, const char *cheat);
int S9xModifyCheatGroup (uint32 index, const char *name, const char *cheat);
void S9xEnableCheatGroup (uint32 index);
void S9xDisableCheatGroup (uint32 index);
void S9xDeleteCheats (void);
void S9xEnableCheat (uint32);
void S9xDisableCheat (uint32);
void S9xAddCheat (bool8, bool8, uint32, uint8);
char *S9xCheatGroupToText (uint32 index);
void S9xDeleteCheatGroup (uint32 index);
bool8 S9xLoadCheatFile (const char *filename);
bool8 S9xSaveCheatFile (const char *filename);
void S9xUpdateCheatsInMemory (void);
bool8 S9xImportCheatsFromDatabase (const char *filename);
void S9xInitCheatData (void);
void S9xInitWatchedAddress (void);
bool8 S9xLoadCheatFile (const char *);
bool8 S9xSaveCheatFile (const char *);
void S9xStartCheatSearch (SCheatData *);
void S9xSearchForChange (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, bool8, bool8);
void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8, bool8);

View File

@ -189,10 +189,10 @@
Nintendo Co., Limited and its subsidiary companies.
***********************************************************************************/
#include "snes9x.h"
#include "memmap.h"
#include "cheats.h"
#include "bml.h"
static inline uint8 S9xGetByteFree (uint32 Address)
{
@ -283,7 +283,7 @@ static inline uint8 S9xGetByteFree (uint32 Address)
static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.WriteMap[block];
uint8 *SetAddress = Memory.Map[block];
if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
{
@ -328,7 +328,6 @@ static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte;
CPU.SRAMModified = TRUE;
}
return;
case CMemory::MAP_BWRAM:
@ -374,7 +373,6 @@ void S9xInitWatchedAddress (void)
{
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
watches[i].on = false;
}
void S9xInitCheatData (void)
@ -384,185 +382,414 @@ void S9xInitCheatData (void)
Cheat.FillRAM = Memory.FillRAM;
}
void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte)
{
if (Cheat.num_cheats < sizeof(Cheat.c) / sizeof(Cheat.c[0]))
{
Cheat.c[Cheat.num_cheats].address = address;
Cheat.c[Cheat.num_cheats].byte = byte;
Cheat.c[Cheat.num_cheats].enabled = enable;
if (save_current_value)
void S9xUpdateCheatInMemory (SCheat *c)
{
Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(address);
Cheat.c[Cheat.num_cheats].saved = TRUE;
uint8 byte;
if (!c->enabled)
return;
byte = S9xGetByteFree (c->address);
if (byte != c->byte)
{
/* The game wrote a different byte to the address, update saved_byte */
c->saved_byte = byte;
if (c->conditional)
{
if (c->saved_byte != c->cond_byte && c->cond_true)
{
/* Condition is now false, let the byte stand */
c->cond_true = false;
}
else if (c->saved_byte == c->cond_byte && !c->cond_true)
{
c->cond_true = true;
S9xSetByteFree (c->byte, c->address);
}
}
else
S9xSetByteFree (c->byte, c->address);
}
else if (c->conditional)
{
if (byte == c->cond_byte)
{
c->cond_true = true;
c->saved_byte = byte;
S9xSetByteFree (c->byte, c->address);
}
Cheat.num_cheats++;
}
}
void S9xDeleteCheat (uint32 which1)
void S9xDisableCheat (SCheat *c)
{
if (which1 < Cheat.num_cheats)
{
if (Cheat.c[which1].enabled)
S9xRemoveCheat(which1);
if (!c->enabled)
return;
memmove(&Cheat.c[which1], &Cheat.c[which1 + 1], sizeof(Cheat.c[0]) * (Cheat.num_cheats - which1 - 1));
S9xUpdateCheatInMemory (c);
c->enabled = false;
Cheat.num_cheats--;
if (c->conditional && !c->cond_true)
return;
S9xSetByteFree (c->saved_byte, c->address);
c->cond_true = false;
}
void S9xDeleteCheatGroup (uint32 g)
{
unsigned int i;
if (g >= Cheat.g.size ())
return;
for (i = 0; i < Cheat.g[g].c.size (); i++)
{
S9xDisableCheat (&Cheat.g[g].c[i]);
}
delete[] Cheat.g[g].name;
Cheat.g.erase (Cheat.g.begin () + g);
}
void S9xDeleteCheats (void)
{
S9xRemoveCheats();
Cheat.num_cheats = 0;
unsigned int i;
for (i = 0; i < Cheat.g.size (); i++)
{
S9xDisableCheatGroup (i);
delete[] Cheat.g[i].name;
}
void S9xRemoveCheat (uint32 which1)
{
if (Cheat.c[which1].saved)
{
uint32 address = Cheat.c[which1].address;
Cheat.g.clear ();
}
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *ptr = Memory.Map[block];
void S9xEnableCheat (SCheat *c)
{
uint8 byte;
if (c->enabled)
return;
c->enabled = true;
byte = S9xGetByteFree(c->address);
if (c->conditional)
{
if (byte != c->cond_byte)
return;
c->cond_true = true;
}
c->saved_byte = byte;
S9xSetByteFree (c->byte, c->address);
}
void S9xEnableCheatGroup (uint32 num)
{
unsigned int i;
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xEnableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = true;
}
void S9xDisableCheatGroup (uint32 num)
{
unsigned int i;
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xDisableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = false;
}
SCheat S9xTextToCheat (char *text)
{
SCheat c;
unsigned int byte = 0;
unsigned int cond_byte = 0;
c.enabled = false;
c.conditional = false;
if (!S9xGameGenieToRaw (text, c.address, c.byte))
{
byte = c.byte;
}
else if (!S9xProActionReplayToRaw (text, c.address, c.byte))
{
byte = c.byte;
}
else if (sscanf (text, "%x=%x?%x", &c.address, &cond_byte, &byte) == 3)
{
c.conditional = true;
}
else if (sscanf (text, "%x=%x", &c.address, &byte) == 2)
{
}
else if (sscanf (text, "%x/%x/%x", &c.address, &cond_byte, &byte) == 3)
{
c.conditional = true;
}
else if (sscanf (text, "%x/%x", &c.address, &byte) == 2)
{
}
if (ptr >= (uint8 *) CMemory::MAP_LAST)
*(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte;
else
S9xSetByteFree(Cheat.c[which1].saved_byte, address);
{
c.address = 0;
byte = 0;
}
c.byte = byte;
c.cond_byte = cond_byte;
return c;
}
SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat)
{
SCheatGroup g;
char *code;
char *code_string = strdup (cheat);
g.name = strdup (name);
g.enabled = false;
for (code = strtok (code_string, "+"); code; code = strtok (NULL, "+"))
{
if (code)
{
SCheat c = S9xTextToCheat (code);
if (c.address)
g.c.push_back (c);
}
}
void S9xRemoveCheats (void)
{
for (uint32 i = 0; i < Cheat.num_cheats; i++)
if (Cheat.c[i].enabled)
S9xRemoveCheat(i);
delete[] code_string;
return g;
}
void S9xEnableCheat (uint32 which1)
int S9xAddCheatGroup (const char *name, const char *cheat)
{
if (which1 < Cheat.num_cheats && !Cheat.c[which1].enabled)
{
Cheat.c[which1].enabled = TRUE;
S9xApplyCheat(which1);
}
SCheatGroup g = S9xCreateCheatGroup (name, cheat);
if (g.c.size () == 0)
return -1;
Cheat.g.push_back (S9xCreateCheatGroup (name, cheat));
return Cheat.g.size () - 1;
}
void S9xDisableCheat (uint32 which1)
int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat)
{
if (which1 < Cheat.num_cheats && Cheat.c[which1].enabled)
{
S9xRemoveCheat(which1);
Cheat.c[which1].enabled = FALSE;
}
S9xDisableCheatGroup (num);
delete[] Cheat.g[num].name;
Cheat.g[num] = S9xCreateCheatGroup (name, cheat);
return num;
}
void S9xApplyCheat (uint32 which1)
char *S9xCheatToText (SCheat *c)
{
uint32 address = Cheat.c[which1].address;
int size = 10; /* 6 address, 1 =, 2 byte, 1 NUL */
char *text;
if (!Cheat.c[which1].saved)
{
Cheat.c[which1].saved_byte = S9xGetByteFree(address);
Cheat.c[which1].saved = TRUE;
}
if (c->conditional)
size += 3; /* additional 2 byte, 1 ? */
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *ptr = Memory.Map[block];
text = new char[size];
if (ptr >= (uint8 *) CMemory::MAP_LAST)
*(ptr + (address & 0xffff)) = Cheat.c[which1].byte;
if (c->conditional)
snprintf (text, size, "%x=%x?%x", c->address, c->cond_byte, c->byte);
else
S9xSetByteFree(Cheat.c[which1].byte, address);
snprintf (text, size, "%x=%x", c->address, c->byte);
return text;
}
void S9xApplyCheats (void)
char *S9xCheatGroupToText (uint32 num)
{
if (Settings.ApplyCheats)
std::string text = "";
unsigned int i;
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
for (uint32 i = 0; i < Cheat.num_cheats; i++)
if (Cheat.c[i].enabled)
S9xApplyCheat(i);
char *tmp = S9xCheatToText (&Cheat.g[num].c[i]);
if (i != 0)
text += '+';
text += tmp;
delete[] tmp;
}
return strdup (text.c_str ());
}
void S9xUpdateCheatsInMemory (void)
{
unsigned int i;
unsigned int j;
for (i = 0; i < Cheat.g.size (); i++)
{
for (j = 0; j < Cheat.g[i].c.size (); j++)
{
S9xUpdateCheatInMemory (&Cheat.g[i].c[j]);
}
}
}
static void S9xLoadCheatsFromBMLNode (bml_node *n)
{
unsigned int i;
for (i = 0; i < n->child.size (); i++)
{
if (!strcasecmp (n->child[i]->name, "cheat"))
{
char *desc = NULL;
char *code = NULL;
bool8 enabled = false;
bml_node *c = n->child[i];
bml_node *tmp = NULL;
tmp = bml_find_sub(c, "description");
desc = tmp->data;
tmp = bml_find_sub(c, "code");
code = tmp->data;
if (bml_find_sub(c, "enabled"))
enabled = true;
if (desc && code)
{
int index = S9xAddCheatGroup (desc, code);
if (enabled)
S9xEnableCheatGroup (index);
}
}
}
return;
}
bool8 S9xLoadCheatFile (const char *filename)
{
FILE *fs;
uint8 data[28];
bml_node *bml = NULL;
bml_node *n = NULL;
Cheat.num_cheats = 0;
bml = bml_parse_file (filename);
if (!bml)
return FALSE;
fs = fopen(filename, "rb");
if (!fs)
return (FALSE);
S9xDeleteCheats ();
while (fread((void *) data, 1, 28, fs) == 28)
n = bml_find_sub (bml, "cartridge");
if (n)
{
Cheat.c[Cheat.num_cheats].enabled = (data[0] & 4) == 0;
Cheat.c[Cheat.num_cheats].byte = data[1];
Cheat.c[Cheat.num_cheats].address = data[2] | (data[3] << 8) | (data[4] << 16);
Cheat.c[Cheat.num_cheats].saved_byte = data[5];
Cheat.c[Cheat.num_cheats].saved = (data[0] & 8) != 0;
memmove(Cheat.c[Cheat.num_cheats].name, &data[8], 20);
Cheat.c[Cheat.num_cheats++].name[20] = 0;
S9xLoadCheatsFromBMLNode (n);
}
fclose(fs);
bml_free_node (bml);
return (TRUE);
}
bool8 S9xSaveCheatFile (const char *filename)
{
if (Cheat.num_cheats == 0)
unsigned int i;
FILE *file = NULL;
if (Cheat.g.size () == 0)
return TRUE;
file = fopen (filename, "w");
if (!file)
return FALSE;
fprintf (file, "cartridge sha256=");
for (i = 0; i < 32; i++)
fprintf (file, "%02x", Memory.ROMSHA256[i]);
fprintf (file, "\n");
for (i = 0; i < Cheat.g.size (); i++)
{
remove(filename);
return (TRUE);
fprintf (file,
" cheat%s\n"
" description: %s\n"
" code: %s\n\n",
(Cheat.g[i].enabled ? " enabled" : ""),
Cheat.g[i].name,
S9xCheatGroupToText (i));
}
FILE *fs;
uint8 data[28];
fclose (file);
fs = fopen(filename, "wb");
if (!fs)
return (FALSE);
return TRUE;
}
for (uint32 i = 0; i < Cheat.num_cheats; i++)
bool8 S9xImportCheatsFromDatabase (const char *filename)
{
memset(data, 0, 28);
bml_node *bml;
char sha256_txt[65];
char hextable[] = "0123456789abcdef";
unsigned int i;
if (i == 0)
bml = bml_parse_file (filename);
if (!bml)
return FALSE;
for (i = 0; i < 32; i++)
{
data[6] = 254;
data[7] = 252;
sha256_txt[i * 2] = hextable[Memory.ROMSHA256[i] >> 4];
sha256_txt[i * 2 + 1] = hextable[Memory.ROMSHA256[i] & 0xf];
}
sha256_txt[64] = '\0';
if (!Cheat.c[i].enabled)
data[0] |= 4;
if (Cheat.c[i].saved)
data[0] |= 8;
data[1] = Cheat.c[i].byte;
data[2] = (uint8) (Cheat.c[i].address >> 0);
data[3] = (uint8) (Cheat.c[i].address >> 8);
data[4] = (uint8) (Cheat.c[i].address >> 16);
data[5] = Cheat.c[i].saved_byte;
memmove(&data[8], Cheat.c[i].name, 19);
if (fwrite(data, 28, 1, fs) != 1)
for (i = 0; i < bml->child.size (); i++)
{
fclose(fs);
return (FALSE);
if (!strcasecmp (bml->child[i]->name, "cartridge"))
{
bml_node *n;
if ((n = bml_find_sub (bml->child[i], "sha256")))
{
if (!strcasecmp (n->data, sha256_txt))
{
S9xLoadCheatsFromBMLNode (bml->child[i]);
bml_free_node (bml);
return TRUE;
}
}
}
}
return (fclose(fs) == 0);
bml_free_node (bml);
return FALSE;
}

View File

@ -452,7 +452,7 @@ void S9xEndScreenRefresh (void)
else
S9xControlEOF();
S9xApplyCheats();
S9xUpdateCheatsInMemory ();
#ifdef DEBUGGER
if (CPU.Flags & FRAME_ADVANCE_FLAG)

View File

@ -180,7 +180,8 @@ snes9x_gtk_SOURCES += \
../screenshot.cpp \
../movie.cpp \
../statemanager.cpp \
../sha256.cpp
../sha256.cpp \
../bml.cpp
# ASMCPU Doesn't exist anymore.
snes9x_gtk_SOURCES += \

View File

@ -13,14 +13,6 @@ enum
extern SCheatData Cheat;
static void
add_cheat (uint32 address, uint8 byte, const char *description)
{
S9xAddCheat (FALSE, TRUE, address, byte);
S9xEnableCheat (Cheat.num_cheats - 1);
strncpy (Cheat.c[Cheat.num_cheats - 1].name, description, 22);
}
static void
display_errorbox (const char *error)
{
@ -190,27 +182,22 @@ void
Snes9xCheats::refresh_tree_view (void)
{
GtkTreeIter iter;
char str [1024];
gtk_list_store_clear (store);
for (unsigned int i = 0; i < Cheat.num_cheats; i++)
for (unsigned int i = 0; i < Cheat.g.size (); i++)
{
snprintf (str,
1024,
"%06x:%02x/%02x",
Cheat.c [i].address,
Cheat.c [i].byte,
Cheat.c [i].saved_byte);
char *str = S9xCheatGroupToText (i);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_DESCRIPTION,
!strcmp (Cheat.c [i].name, "") ? _("No description")
: Cheat.c [i].name,
!strcmp (Cheat.g [i].name, "") ? _("No description")
: Cheat.g [i].name,
COLUMN_CHEAT, str,
COLUMN_ENABLED, Cheat.c [i].enabled,
COLUMN_ENABLED, Cheat.g [i].enabled,
-1);
delete[] str;
}
@ -220,32 +207,15 @@ Snes9xCheats::refresh_tree_view (void)
void
Snes9xCheats::add_code (void)
{
uint32 address;
uint8 byte;
uint8 bytes [3];
bool8 sram;
uint8 num_bytes;
const char *description;
const gchar *code = get_entry_text ("code_entry");
description = get_entry_text ("description_entry");
if (description[0] == '\0')
description = _("No description");
if (!S9xGameGenieToRaw (code, address, byte))
add_cheat (address, byte, description);
else if (!S9xProActionReplayToRaw (code, address, byte))
add_cheat (address, byte, description);
else if (!S9xGoldFingerToRaw (code, address, sram, num_bytes, bytes))
{
for (int c = 0; c < num_bytes; c++)
add_cheat (address + c, bytes[c], description);
}
else
{
display_errorbox (_("Code does not match Game Genie, ProAction Replay, or GoldFinger format."));
}
if (S9xAddCheatGroup (description, code) < 0)
display_errorbox (_("Couldn't find any cheat codes in input."));
gtk_widget_grab_focus (get_widget ("code_entry"));
@ -262,7 +232,7 @@ Snes9xCheats::remove_code (void)
if (index < 0)
return;
S9xDeleteCheat (index);
S9xDeleteCheatGroup (index);
refresh_tree_view ();
@ -277,10 +247,10 @@ Snes9xCheats::toggle_code (const gchar *path)
if (index < 0)
return;
if (Cheat.c[index].enabled)
S9xDisableCheat (index);
if (Cheat.g[index].enabled)
S9xDisableCheatGroup (index);
else
S9xEnableCheat (index);
S9xEnableCheatGroup (index);
refresh_tree_view ();

View File

@ -256,7 +256,6 @@ Snes9xConfig::load_defaults (void)
Settings.DynamicRateControl = 1;
Settings.DynamicRateLimit = 5;
Settings.HDMATimingHack = 100;
Settings.ApplyCheats = 1;
#ifdef NETPLAY_SUPPORT
Settings.NetPlay = FALSE;

View File

@ -196,16 +196,6 @@ S9xOpenROM (const char *rom_filename)
{
Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR));
S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
for (unsigned int i = 0; i < Cheat.num_cheats; i++)
{
if (Cheat.c[i].enabled)
{
/* RAM is fresh, so we need to clean out old saved values */
Cheat.c[i].saved = FALSE;
S9xApplyCheat (i);
}
}
}
else
{

View File

@ -316,7 +316,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="hscrollbar_policy">never</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkTreeView" id="cheat_treeview">
@ -391,7 +391,7 @@
<object class="GtkEntry" id="description_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="max_length">21</property>
<property name="max_length">1024</property>
<property name="activates_default">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>

View File

@ -1783,15 +1783,12 @@ bool8 CMemory::LoadROMInt (int32 ROMfillSize)
memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
SNESGameFixes.SRAMInitialValue = 0x60;
S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
InitROM();
S9xInitCheatData();
S9xApplyCheats();
S9xReset();
S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
return (TRUE);
}
@ -1951,15 +1948,13 @@ bool8 CMemory::LoadMultiCartInt ()
memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
SNESGameFixes.SRAMInitialValue = 0x60;
S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
InitROM();
S9xInitCheatData();
S9xApplyCheats();
S9xReset();
S9xInitCheatData();
S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
return (TRUE);
}

View File

@ -777,57 +777,14 @@ char * S9xParseArgs (char **argv, int argc)
if (!strcasecmp(argv[i], "-cheat"))
Settings.ApplyCheats = TRUE;
else
if (!strcasecmp(argv[i], "-gamegenie"))
if (!strcasecmp(argv[i], "-gamegenie") || !strcasecmp(argv[i], "-actionreplay"))
{
if (i + 1 < argc)
{
uint32 address;
uint8 byte;
const char *error;
if ((error = S9xGameGenieToRaw(argv[++i], address, byte)) == NULL)
S9xAddCheat(TRUE, FALSE, address, byte);
else
S9xMessage(S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, error);
}
else
S9xUsage();
}
else
if (!strcasecmp(argv[i], "-actionreplay"))
if (S9xAddCheatGroup ("Unknown", argv[++i]) < 0)
{
if (i + 1 < argc)
{
uint32 address;
uint8 byte;
const char *error;
if ((error = S9xProActionReplayToRaw(argv[++i], address, byte)) == NULL)
S9xAddCheat(TRUE, FALSE, address, byte);
else
S9xMessage(S9X_ERROR, S9X_ACTION_REPLY_CODE_ERROR, error);
S9xMessage(S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, "Code format invalid");
}
else
S9xUsage();
}
else
if (!strcasecmp(argv[i], "-goldfinger"))
{
if (i + 1 < argc)
{
uint32 address;
uint8 bytes[3];
bool8 sram;
uint8 num_bytes;
const char *error;
if ((error = S9xGoldFingerToRaw(argv[++i], address, sram, num_bytes, bytes)) == NULL)
{
for (int c = 0; c < num_bytes; c++)
S9xAddCheat(TRUE, FALSE, address + c, bytes[c]);
}
else
S9xMessage(S9X_ERROR, S9X_GOLD_FINGER_CODE_ERROR, error);
}
else
S9xUsage();