Merge pull request #283 from snes9xgit/newcheats

Cheats Restructure
This commit is contained in:
bearoso 2018-05-03 13:28:33 -05:00 committed by GitHub
commit 448d7e6660
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 89155 additions and 1327 deletions

115
bml.cpp
View File

@ -1,17 +1,57 @@
#include <ctype.h>
#include <vector>
#include <string.h>
#include <stdio.h>
#include "port.h"
#include "bml.h"
static inline bml_node *bml_node_new(void)
static char *strndup_p(char *str, int len)
{
char *buffer;
int n;
buffer = (char *) malloc (len + 1);
if (buffer)
{
for (n = 0; ((n < len) && (str[n] != 0)); n++) buffer[n] = str[n];
buffer[n] = '\0';
}
return buffer;
}
static inline bml_node *bml_node_new (void)
{
bml_node *node = new bml_node;
node->data = NULL;
node->name = NULL;
node->depth = -1;
return node;
}
static inline int islf(char c)
{
return (c == '\r' || c == '\n');
}
static inline int isblank(char c)
{
return (c == ' ' || c == '\t');
}
static inline int isalnum(char c)
{
return ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9'));
}
static inline int bml_valid (char c)
{
return (isalnum (c) || c == '-');
}
static char *strndup_trim (char *str, int len)
@ -25,17 +65,7 @@ static char *strndup_trim (char *str, int len)
for (end = len - 1; isblank (str[end]) || str[end] == '\n' || str[end] == '\r'; end--) {}
return strndup (str + start, end - start + 1);
}
static inline int bml_valid (char c)
{
return (isalnum (c) || c == '-');
}
static inline int islf(char c)
{
return (c == '\r' || c == '\n');
return strndup_p (str + start, end - start + 1);
}
static inline unsigned int bml_read_depth (char *data)
@ -45,14 +75,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,12 +100,12 @@ 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;
node->data = strndup (p + 2, len - 2);
node->data = strndup_p (p + 2, len - 2);
*data += len + 1;
}
else if (*p == '=')
@ -177,7 +207,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 +227,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 +243,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 +265,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 +297,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 +315,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 +346,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,31 @@
#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;
bool8 enabled;
uint8 CWRAM[0x20000];
uint8 CSRAM[0x10000];
uint8 CIRAM[0x2000];
@ -250,20 +259,23 @@ 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);
int S9xImportCheatsFromDatabase(const char *filename);
void S9xCheatsDisable (void);
void S9xCheatsEnable (void);
char *S9xCheatValidate (char *cheat);
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,16 +189,16 @@
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)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block];
uint8 byte;
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block];
uint8 byte;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{
@ -282,8 +282,8 @@ 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];
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
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:
@ -372,197 +371,577 @@ static inline void S9xSetByteFree (uint8 Byte, uint32 Address)
void S9xInitWatchedAddress (void)
{
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
watches[i].on = false;
for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++)
watches[i].on = false;
}
void S9xInitCheatData (void)
{
Cheat.RAM = Memory.RAM;
Cheat.SRAM = Memory.SRAM;
Cheat.FillRAM = Memory.FillRAM;
Cheat.RAM = Memory.RAM;
Cheat.SRAM = Memory.SRAM;
Cheat.FillRAM = Memory.FillRAM;
}
void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte)
void S9xUpdateCheatInMemory (SCheat *c)
{
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;
uint8 byte;
if (save_current_value)
{
Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(address);
Cheat.c[Cheat.num_cheats].saved = TRUE;
}
if (!c->enabled)
return;
Cheat.num_cheats++;
}
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);
}
}
}
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));
if (!Cheat.enabled)
{
c->enabled = false;
return;
}
Cheat.num_cheats--;
}
/* Make sure we restore the up-to-date written byte */
S9xUpdateCheatInMemory (c);
c->enabled = false;
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;
}
Cheat.g.clear ();
}
void S9xRemoveCheat (uint32 which1)
void S9xEnableCheat (SCheat *c)
{
if (Cheat.c[which1].saved)
{
uint32 address = Cheat.c[which1].address;
uint8 byte;
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *ptr = Memory.Map[block];
if (c->enabled)
return;
if (ptr >= (uint8 *) CMemory::MAP_LAST)
*(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte;
else
S9xSetByteFree(Cheat.c[which1].saved_byte, address);
}
c->enabled = true;
if (!Cheat.enabled)
return;
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 S9xRemoveCheats (void)
void S9xEnableCheatGroup (uint32 num)
{
for (uint32 i = 0; i < Cheat.num_cheats; i++)
if (Cheat.c[i].enabled)
S9xRemoveCheat(i);
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 S9xEnableCheat (uint32 which1)
void S9xDisableCheatGroup (uint32 num)
{
if (which1 < Cheat.num_cheats && !Cheat.c[which1].enabled)
{
Cheat.c[which1].enabled = TRUE;
S9xApplyCheat(which1);
}
unsigned int i;
for (i = 0; i < Cheat.g[num].c.size (); i++)
{
S9xDisableCheat (&Cheat.g[num].c[i]);
}
Cheat.g[num].enabled = false;
}
void S9xDisableCheat (uint32 which1)
SCheat S9xTextToCheat (char *text)
{
if (which1 < Cheat.num_cheats && Cheat.c[which1].enabled)
{
S9xRemoveCheat(which1);
Cheat.c[which1].enabled = FALSE;
}
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)
{
}
else
{
c.address = 0;
byte = 0;
}
c.byte = byte;
c.cond_byte = cond_byte;
return c;
}
void S9xApplyCheat (uint32 which1)
SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat)
{
uint32 address = Cheat.c[which1].address;
SCheatGroup g;
char *code;
char *code_string = strdup (cheat);
if (!Cheat.c[which1].saved)
{
Cheat.c[which1].saved_byte = S9xGetByteFree(address);
Cheat.c[which1].saved = TRUE;
}
g.name = strdup (name);
g.enabled = false;
int block = (address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *ptr = Memory.Map[block];
for (code = strtok (code_string, "+"); code; code = strtok (NULL, "+"))
{
if (code)
{
SCheat c = S9xTextToCheat (code);
if (c.address)
g.c.push_back (c);
}
}
if (ptr >= (uint8 *) CMemory::MAP_LAST)
*(ptr + (address & 0xffff)) = Cheat.c[which1].byte;
else
S9xSetByteFree(Cheat.c[which1].byte, address);
delete[] code_string;
return g;
}
void S9xApplyCheats (void)
int S9xAddCheatGroup (const char *name, const char *cheat)
{
if (Settings.ApplyCheats)
{
for (uint32 i = 0; i < Cheat.num_cheats; i++)
if (Cheat.c[i].enabled)
S9xApplyCheat(i);
}
SCheatGroup g = S9xCreateCheatGroup (name, cheat);
if (g.c.size () == 0)
return -1;
Cheat.g.push_back (g);
return Cheat.g.size () - 1;
}
int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat)
{
if (num >= Cheat.g.size())
return -1;
S9xDisableCheatGroup (num);
delete[] Cheat.g[num].name;
Cheat.g[num] = S9xCreateCheatGroup (name, cheat);
return num;
}
char *S9xCheatToText (SCheat *c)
{
int size = 10; /* 6 address, 1 =, 2 byte, 1 NUL */
char *text;
if (c->conditional)
size += 3; /* additional 2 byte, 1 ? */
text = new char[size];
if (c->conditional)
snprintf (text, size, "%x=%x?%x", c->address, c->cond_byte, c->byte);
else
snprintf (text, size, "%x=%x", c->address, c->byte);
return text;
}
char *S9xCheatGroupToText (SCheatGroup *g)
{
std::string text = "";
unsigned int i;
if (g->c.size () == 0)
return NULL;
for (i = 0; i < g->c.size (); i++)
{
char *tmp = S9xCheatToText (&g->c[i]);
if (i != 0)
text += '+';
text += tmp;
delete[] tmp;
}
return strdup (text.c_str ());
}
char *S9xCheatValidate (char *code_string)
{
SCheatGroup g = S9xCreateCheatGroup ("temp", code_string);
delete[] g.name;
if (g.c.size() > 0)
{
return S9xCheatGroupToText (&g);
}
return NULL;
}
char *S9xCheatGroupToText (uint32 num)
{
if (num >= Cheat.g.size ())
return NULL;
return S9xCheatGroupToText (&Cheat.g[num]);
}
void S9xUpdateCheatsInMemory (void)
{
unsigned int i;
unsigned int j;
if (!Cheat.enabled)
return;
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 int S9xCheatIsDuplicate (char *name, char *code)
{
unsigned int i;
for (i = 0; i < Cheat.g.size(); i++)
{
if (!strcmp (name, Cheat.g[i].name))
{
char *code_string = S9xCheatGroupToText (i);
char *validated = S9xCheatValidate (code);
if (validated && !strcmp (code_string, validated))
{
free (code_string);
free (validated);
return TRUE;
}
free (code_string);
free (validated);
}
}
return FALSE;
}
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;
if (!desc)
desc = (char *) "";
tmp = bml_find_sub(c, "code");
code = tmp->data;
if (bml_find_sub(c, "enabled"))
enabled = true;
if (code && !S9xCheatIsDuplicate (desc, code))
{
int index = S9xAddCheatGroup (desc, code);
if (enabled)
S9xEnableCheatGroup (index);
}
}
}
return;
}
static bool8 S9xLoadCheatFileClassic (const char *filename)
{
FILE *fs;
uint8 data[28];
fs = fopen(filename, "rb");
if (!fs)
return (FALSE);
while (fread ((void *) data, 1, 28, fs) == 28)
{
SCheat c;
char name[21];
char cheat[10];
c.enabled = (data[0] & 4) == 0;
c.byte = data[1];
c.address = data[2] | (data[3] << 8) | (data[4] << 16);
memcpy (name, &data[8], 20);
name[20] = 0;
snprintf (cheat, 21, "%x=%x", c.address, c.byte);
S9xAddCheatGroup (name, cheat);
if (c.enabled)
S9xEnableCheatGroup (Cheat.g.size () - 1);
}
fclose(fs);
return (TRUE);
}
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 S9xLoadCheatFileClassic (filename);
}
fs = fopen(filename, "rb");
if (!fs)
return (FALSE);
n = bml_find_sub (bml, "cartridge");
if (n)
{
S9xLoadCheatsFromBMLNode (n);
}
while (fread((void *) data, 1, 28, fs) == 28)
{
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;
}
bml_free_node (bml);
fclose(fs);
if (!n)
{
return S9xLoadCheatFileClassic (filename);
}
return (TRUE);
return (TRUE);
}
bool8 S9xSaveCheatFile (const char *filename)
{
if (Cheat.num_cheats == 0)
{
remove(filename);
return (TRUE);
}
unsigned int i;
FILE *file = NULL;
FILE *fs;
uint8 data[28];
if (Cheat.g.size () == 0)
{
remove (filename);
return TRUE;
}
fs = fopen(filename, "wb");
if (!fs)
return (FALSE);
file = fopen (filename, "w");
for (uint32 i = 0; i < Cheat.num_cheats; i++)
{
memset(data, 0, 28);
if (!file)
return FALSE;
if (i == 0)
{
data[6] = 254;
data[7] = 252;
}
fprintf (file, "cartridge sha256=");
for (i = 0; i < 32; i++)
fprintf (file, "%02x", Memory.ROMSHA256[i]);
fprintf (file, "\n");
if (!Cheat.c[i].enabled)
data[0] |= 4;
for (i = 0; i < Cheat.g.size (); i++)
{
char *txt = S9xCheatGroupToText (i);
if (Cheat.c[i].saved)
data[0] |= 8;
fprintf (file,
" cheat%s\n"
" description: %s\n"
" code: %s\n",
(Cheat.g[i].enabled ? " enabled" : ""),
(Cheat.g[i].name ? Cheat.g[i].name : ""),
txt);
delete[] txt;
}
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;
fclose (file);
memmove(&data[8], Cheat.c[i].name, 19);
if (fwrite(data, 28, 1, fs) != 1)
{
fclose(fs);
return (FALSE);
}
}
return (fclose(fs) == 0);
return TRUE;
}
void S9xCheatsDisable (void)
{
unsigned int i;
if (!Cheat.enabled)
return;
for (i = 0; i < Cheat.g.size (); i++)
{
if (Cheat.g[i].enabled)
{
S9xDisableCheatGroup (i);
Cheat.g[i].enabled = TRUE;
}
}
Cheat.enabled = FALSE;
}
void S9xCheatsEnable (void)
{
unsigned int i;
if (Cheat.enabled)
return;
Cheat.enabled = TRUE;
for (i = 0; i < Cheat.g.size (); i++)
{
if (Cheat.g[i].enabled)
{
Cheat.g[i].enabled = FALSE;
S9xEnableCheatGroup (i);
}
}
}
int S9xImportCheatsFromDatabase (const char *filename)
{
bml_node *bml;
char sha256_txt[65];
char hextable[] = "0123456789abcdef";
unsigned int i;
bml = bml_parse_file (filename);
if (!bml)
return -1; /* No file */
for (i = 0; i < 32; i++)
{
sha256_txt[i * 2] = hextable[Memory.ROMSHA256[i] >> 4];
sha256_txt[i * 2 + 1] = hextable[Memory.ROMSHA256[i] & 0xf];
}
sha256_txt[64] = '\0';
for (i = 0; i < bml->child.size (); i++)
{
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 0;
}
}
}
}
bml_free_node (bml);
return -2; /* No codes */
}

View File

@ -227,7 +227,7 @@ static void S9xSoftResetCPU (void)
CPU.V_Counter = 0;
CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG);
CPU.PCBase = NULL;
CPU.NMILine = FALSE;
CPU.NMIPending = FALSE;
CPU.IRQLine = FALSE;
CPU.IRQTransition = FALSE;
CPU.IRQLastState = FALSE;

View File

@ -209,11 +209,11 @@ void S9xMainLoop (void)
{
for (;;)
{
if (CPU.NMILine)
if (CPU.NMIPending)
{
if (Timings.NMITriggerPos <= CPU.Cycles)
{
CPU.NMILine = FALSE;
CPU.NMIPending = FALSE;
Timings.NMITriggerPos = 0xffff;
if (CPU.WaitingForInterrupt)
{
@ -439,8 +439,6 @@ void S9xDoHEventProcessing (void)
// FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles.
Memory.FillRAM[0x4210] = Model->_5A22;
CPU.NMILine = FALSE;
Timings.NMITriggerPos = 0xffff;
ICPU.Frame++;
PPU.HVBeamCounterLatched = 0;
@ -507,7 +505,7 @@ void S9xDoHEventProcessing (void)
{
// FIXME: triggered at HC=6, checked just before the final CPU cycle,
// then, when to call S9xOpcode_NMI()?
CPU.NMILine = TRUE;
CPU.NMIPending = TRUE;
Timings.NMITriggerPos = 6 + 6;
}

87497
data/cheats.bml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -215,6 +215,7 @@ enum s9x_getdirtype
void S9xUsage (void);
char * S9xParseArgs (char **, int);
void S9xParseArgsForCheats (char **, int);
void S9xLoadConfigFiles (char **, int);
void S9xSetInfoString (const char *);

View File

@ -1288,7 +1288,7 @@ bool8 S9xDoDMA (uint8 Channel)
}
}
if (CPU.NMILine && (Timings.NMITriggerPos != 0xffff))
if (CPU.NMIPending && (Timings.NMITriggerPos != 0xffff))
{
Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay;
if (Timings.NMITriggerPos >= Timings.H_Max)

48
gfx.cpp
View File

@ -452,7 +452,7 @@ void S9xEndScreenRefresh (void)
else
S9xControlEOF();
S9xApplyCheats();
S9xUpdateCheatsInMemory ();
#ifdef DEBUGGER
if (CPU.Flags & FRAME_ADVANCE_FLAG)
@ -899,8 +899,14 @@ static void SetupOBJ (void)
else // evil FirstSprite+Y case
{
// First, find out which sprites are on which lines
uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128];
memset(OBJOnLine, 0, sizeof(OBJOnLine));
uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128];
// memset(OBJOnLine, 0, sizeof(OBJOnLine));
/* Hold on here, that's a lot of bytes to initialise at once!
* So we only initialise them per line, as needed. [Neb]
* Bonus: We can quickly avoid looping if a line has no OBJs.
*/
bool8 AnyOBJOnLine[SNES_HEIGHT_EXTENDED];
memset(AnyOBJOnLine, FALSE, sizeof(AnyOBJOnLine)); // better
for (S = 0; S < 128; S++)
{
@ -934,6 +940,11 @@ static void SetupOBJ (void)
if (Y >= SNES_HEIGHT_EXTENDED)
continue;
if (!AnyOBJOnLine[Y]) {
memset(OBJOnLine[Y], 0, sizeof(OBJOnLine[Y]));
AnyOBJOnLine[Y] = TRUE;
}
if (PPU.OBJ[S].VFlip)
// Yes, Width not Height. It so happens that the
// sprites with H=2*W flip as two WxW sprites.
@ -955,25 +966,28 @@ static void SetupOBJ (void)
S = FirstSprite;
j = 0;
do
if (AnyOBJOnLine[Y])
{
if (OBJOnLine[Y][S])
do
{
if (j >= 32)
if (OBJOnLine[Y][S])
{
GFX.OBJLines[Y].RTOFlags |= 0x40;
break;
if (j >= 32)
{
GFX.OBJLines[Y].RTOFlags |= 0x40;
break;
}
GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S];
if (GFX.OBJLines[Y].Tiles < 0)
GFX.OBJLines[Y].RTOFlags |= 0x80;
GFX.OBJLines[Y].OBJ[j].Sprite = S;
GFX.OBJLines[Y].OBJ[j++].Line = OBJOnLine[Y][S] & ~0x80;
}
GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S];
if (GFX.OBJLines[Y].Tiles < 0)
GFX.OBJLines[Y].RTOFlags |= 0x80;
GFX.OBJLines[Y].OBJ[j].Sprite = S;
GFX.OBJLines[Y].OBJ[j++].Line = OBJOnLine[Y][S] & ~0x80;
}
S = (S + 1) & 0x7f;
} while (S != FirstSprite);
S = (S + 1) & 0x7f;
} while (S != FirstSprite);
}
if (j < 32)
GFX.OBJLines[Y].OBJ[j].Sprite = -1;

View File

@ -8,7 +8,7 @@ snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti
endif
noinst_LIBRARIES =
AM_CPPFLAGS = -I../apu/bapu -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\"
AM_CPPFLAGS = -I../apu/bapu -I$(top_srcdir) -I.. -DDATADIR=\""$(snes9xdatadir)"\" -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\"
CLEANFILES = \
src/gtk_snes9x_ui.cpp \
@ -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

@ -34,7 +34,10 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE")
AM_GLIB_GNU_GETTEXT
snes9xlocaledir='${prefix}/${DATADIRNAME}/locale'
snes9xdatadir='${prefix}/${DATADIRNAME}/snes9x'
AC_SUBST(snes9xlocaledir)
AC_SUBST(snes9xdatadir)
AC_ARG_WITH(debug,
[AS_HELP_STRING([--with(out)-debug],
@ -60,12 +63,6 @@ AC_ARG_WITH(xv,
[],
[with_xv=yes])
AC_ARG_WITH(xrandr,
[AS_HELP_STRING([--with(out)-xrandr],
[Enable XRandR support on GTK (default: with)])],
[],
[with_xrandr=yes])
AC_ARG_WITH(portaudio,
[AS_HELP_STRING([--with(out)-portaudio],
[Enable PortAudio sound driver support (default: with)])],
@ -152,9 +149,15 @@ AC_ARG_WITH(screenshot,
AC_ARG_WITH(gtk3,
[AS_HELP_STRING([--with(out)-gtk3],
[Build with GTK+ 3 if available (default: with)])],
[],
[with_gtk3=yes])
AC_ARG_WITH(gtk2,
[AS_HELP_STRING([--with(out)-gtk2],
[Build with GTK+ 3 if available (default: without)])],
[],
[with_gtk3=no])
[with_gtk2=no])
if test yes = "$with_debug" ; then
CFLAGS="$CFLAGS -g"
@ -187,10 +190,9 @@ GTK=yes
snes9x_info_display="GTK"
GTK3_WARNING=no
if test yes = "$with_gtk3" ; then
if test yes = "$with_gtk3" -a no = "$with_gtk2"; then
GTK_VERSION="gtk+-3.0"
GTK3_WARNING=yes
CFLAGS="$CFLAGS -DUSE_GTK3"
else
GTK_VERSION="gtk+-2.0 >= 2.16"
fi
@ -198,6 +200,7 @@ fi
PKG_CHECK_MODULES([GTK], ["$GTK_VERSION"])
PKG_CHECK_MODULES([GLIB], [gthread-2.0 >= 2.6 gobject-2.0 >= 2.6])
PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.0])
PKG_CHECK_MODULES([XRANDR], [xrandr])
if test yes = "$with_opengl" ; then
@ -295,19 +298,6 @@ if test yes = "$with_pulseaudio" ; then
])
fi
XRANDR=0
XRANDR_CFLAGS=""
XRANDR_LIBS=""
if test yes = "$with_xrandr" ; then
PKG_CHECK_MODULES([XRANDR],[xrandr],[
XRANDR=yes
CFLAGS="$CFLAGS -DUSE_XRANDR"
],[
echo "Cannot find libXrandr. Make sure the X11 development headers are installed."
echo "--> Disabling Xrandr support."
])
fi
LIBPNG_CFLAGS=""
LIBPNG_LIBS=""
if test yes = "$with_screenshot"; then
@ -499,7 +489,7 @@ echo "Snes9x will build with support for the following:"
echo ""
if test yes = "$GTK3_WARNING" ; then
echo " GTK+ 3.0 (experimental)"
echo " GTK+ 3.0"
else
echo " GTK+ 2.0"
fi

View File

@ -13,6 +13,9 @@ icon32x32_DATA = snes9x_32x32.png
iconscalabledir = $(datadir)/icons/hicolor/scalable/apps
iconscalable_DATA = snes9x.svg
cheatsdir = $(datadir)/snes9x
cheats_DATA = ../../data/cheats.bml
install-data-hook:
mv -f $(DESTDIR)$(datadir)/icons/hicolor/16x16/apps/snes9x_16x16.png \
$(DESTDIR)$(datadir)/icons/hicolor/16x16/apps/snes9x.png

View File

@ -1,9 +1,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#ifdef USE_GTK3
#if GTK_MAJOR_VERSION >= 3
#include <gdk/gdkkeysyms-compat.h>
#endif

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)
{
@ -49,12 +41,37 @@ event_remove_code (GtkButton *button, gpointer data)
((Snes9xCheats *) data)->remove_code ();
}
static void
event_search_database (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->search_database ();
}
static void
event_delete_all_cheats (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->delete_all_cheats ();
}
static void
event_code_toggled (GtkCellRendererToggle *cell_renderer,
gchar *path,
gpointer data)
{
((Snes9xCheats *) data)->toggle_code (path);
int enabled = !gtk_cell_renderer_toggle_get_active (cell_renderer);
((Snes9xCheats *) data)->toggle_code (path, enabled);
return;
}
void
event_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer data)
{
((Snes9xCheats *) data)->row_activated (path);
return;
}
@ -68,13 +85,17 @@ Snes9xCheats::Snes9xCheats (void)
{
{ "add_code", G_CALLBACK (event_add_code) },
{ "remove_code", G_CALLBACK (event_remove_code) },
{ "search_database", G_CALLBACK (event_search_database) },
{ "delete_all_cheats", G_CALLBACK (event_delete_all_cheats) },
{ NULL, NULL}
};
view = GTK_TREE_VIEW (get_widget ("cheat_treeview"));
g_signal_connect (view, "row-activated", G_CALLBACK (event_row_activated), (gpointer) this);
renderer = gtk_cell_renderer_toggle_new ();
gtk_cell_renderer_toggle_set_activatable (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
gtk_tree_view_insert_column_with_attributes (view,
-1,
"",
@ -94,6 +115,8 @@ Snes9xCheats::Snes9xCheats (void)
renderer,
"text", COLUMN_DESCRIPTION,
NULL);
GtkTreeViewColumn *column = gtk_tree_view_get_column (view, 1);
gtk_tree_view_column_set_resizable (column, TRUE);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (view,
@ -102,6 +125,9 @@ Snes9xCheats::Snes9xCheats (void)
renderer,
"text", COLUMN_CHEAT,
NULL);
column = gtk_tree_view_get_column (view, 2);
gtk_tree_view_column_set_resizable (column, TRUE);
store = gtk_list_store_new (NUM_COLS,
G_TYPE_BOOLEAN,
@ -190,62 +216,50 @@ void
Snes9xCheats::refresh_tree_view (void)
{
GtkTreeIter iter;
char str [1024];
unsigned int list_size;
gtk_list_store_clear (store);
list_size = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL);
for (unsigned int i = 0; i < Cheat.num_cheats; i++)
{
snprintf (str,
1024,
"%06x:%02x/%02x",
Cheat.c [i].address,
Cheat.c [i].byte,
Cheat.c [i].saved_byte);
if (Cheat.g.size () == 0)
return;
for (unsigned int i = 0; i < Cheat.g.size() - list_size; i++)
gtk_list_store_append (store, &iter);
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
for (unsigned int i = 0; i < Cheat.g.size (); i++)
{
char *str = S9xCheatGroupToText (i);
if (i > 0)
gtk_tree_model_iter_next (GTK_TREE_MODEL (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;
}
return;
}
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"));
@ -258,31 +272,129 @@ void
Snes9xCheats::remove_code (void)
{
int index = get_selected_index ();
GtkTreeIter iter;
if (index < 0)
return;
S9xDeleteCheat (index);
gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, NULL, index);
gtk_list_store_remove (store, &iter);
refresh_tree_view ();
S9xDeleteCheatGroup (index);
return;
}
void
Snes9xCheats::toggle_code (const gchar *path)
Snes9xCheats::delete_all_cheats (void)
{
int index = get_index_from_path (path);
if (index < 0)
return;
if (Cheat.c[index].enabled)
S9xDisableCheat (index);
else
S9xEnableCheat (index);
refresh_tree_view ();
S9xDeleteCheats ();
gtk_list_store_clear (store);
return;
}
void
Snes9xCheats::search_database (void)
{
std::string filename;
int result;
int reason = 0;
filename = S9xGetDirectory (CHEAT_DIR);
filename += "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ())))
{
refresh_tree_view ();
return;
}
if (result < reason)
reason = result;
char *config_dir = get_config_dir ();
filename = std::string (config_dir) + "/cheats.bml";
free (config_dir);
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ())))
{
refresh_tree_view ();
return;
}
if (result < reason)
reason = result;
filename = std::string (DATADIR) + "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ())))
{
refresh_tree_view ();
return;
}
if (result < reason)
reason = result;
filename = S9xGetDirectory (ROM_DIR);
filename += "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ())))
{
refresh_tree_view ();
return;
}
if (result < reason)
reason = result;
GtkMessageDialog *dialog;
GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new (get_window (),
flags,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
reason == -1 ? _("Couldn't Find Cheats Database") :
_("No Matching Game Found")));
gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG (dialog),
reason == -1 ?
_("The database file <b>cheats.bml</b> was not found. It is normally installed with "
"Snes9x, but you may also place a custom copy in your configuration or cheats directory.") :
_("No matching game was found in the databases. If you are using a non-official "
"translation or modified copy, you may be able to find and manually enter the codes."));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
return;
}
void
Snes9xCheats::row_activated (GtkTreePath *path)
{
gint *indices = gtk_tree_path_get_indices (path);
char *cheat_text;
cheat_text = S9xCheatGroupToText (indices[0]);
set_entry_text ("code_entry", cheat_text);
delete[] cheat_text;
set_entry_text ("description_entry", Cheat.g[indices[0]].name);
return;
}
void
Snes9xCheats::toggle_code (const gchar *path, int enabled)
{
GtkTreeIter iter;
int index = get_index_from_path (path);
GtkTreePath *treepath = gtk_tree_path_new_from_string (path);
gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, treepath);
gtk_list_store_set (store, &iter, COLUMN_ENABLED, enabled, -1);
if (enabled)
S9xEnableCheatGroup (index);
else
S9xDisableCheatGroup (index);
return;
}

View File

@ -15,7 +15,10 @@ class Snes9xCheats : public GtkBuilderWindow
void show (void);
void add_code (void);
void remove_code (void);
void toggle_code (const gchar *path);
void search_database (void);
void delete_all_cheats (void);
void toggle_code (const gchar *path, int enabled);
void row_activated (GtkTreePath *path);
private:
void refresh_tree_view (void);

View File

@ -162,8 +162,6 @@ Snes9xConfig::load_defaults (void)
full_screen_on_open = 0;
change_display_resolution = 0;
xrr_index = 0;
xrr_width = 0;
xrr_height = 0;
scale_to_fit = 1;
maintain_aspect_ratio = 0;
aspect_ratio = 0;
@ -191,6 +189,7 @@ Snes9xConfig::load_defaults (void)
sound_buffer_size = 32;
sound_playback_rate = 5;
sound_input_rate = 31950;
auto_input_rate = TRUE;
last_directory[0] = '\0';
window_width = -1;
window_height = -1;
@ -217,6 +216,7 @@ Snes9xConfig::load_defaults (void)
netplay_last_host [0] = '\0';
netplay_last_port = 6096;
modal_dialogs = 1;
S9xCheatsEnable ();
rewind_granularity = 5;
rewind_buffer_size = 0;
@ -253,10 +253,9 @@ Snes9xConfig::load_defaults (void)
Settings.FrameTime = Settings.FrameTimeNTSC;
Settings.BlockInvalidVRAMAccessMaster = TRUE;
Settings.SoundSync = 1;
Settings.DynamicRateControl = 1;
Settings.DynamicRateControl = FALSE;
Settings.DynamicRateLimit = 5;
Settings.HDMATimingHack = 100;
Settings.ApplyCheats = 1;
#ifdef NETPLAY_SUPPORT
Settings.NetPlay = FALSE;
@ -324,8 +323,6 @@ Snes9xConfig::save_config_file (void)
xml_out_int (xml, "full_screen_on_open", full_screen_on_open);
xml_out_int (xml, "change_display_resolution", change_display_resolution);
xml_out_int (xml, "video_mode", xrr_index);
xml_out_int (xml, "video_mode_width", xrr_width);
xml_out_int (xml, "video_mode_height", xrr_height);
xml_out_int (xml, "scale_to_fit", scale_to_fit);
xml_out_int (xml, "maintain_aspect_ratio", maintain_aspect_ratio);
xml_out_int (xml, "aspect_ratio", aspect_ratio);
@ -406,6 +403,7 @@ Snes9xConfig::save_config_file (void)
xml_out_int (xml, "sound_sync", Settings.SoundSync);
xml_out_int (xml, "dynamic_rate_control", Settings.DynamicRateControl);
xml_out_int (xml, "dynamic_rate_limit", Settings.DynamicRateLimit);
xml_out_int (xml, "auto_input_rate", auto_input_rate);
/* Snes9X core-stored variables */
xml_out_int (xml, "transparency", Settings.Transparency);
@ -498,14 +496,7 @@ Snes9xConfig::set_option (const char *name, const char *value)
}
else if (!strcasecmp (name, "video_mode"))
{
}
else if (!strcasecmp (name, "video_mode_width"))
{
xrr_width = atoi (value);
}
else if (!strcasecmp (name, "video_mode_height"))
{
xrr_height = atoi (value);
xrr_index = atoi (value);
}
else if (!strcasecmp (name, "scale_to_fit"))
{
@ -677,6 +668,10 @@ Snes9xConfig::set_option (const char *name, const char *value)
Settings.DynamicRateLimit = atoi (value);
Settings.DynamicRateLimit = CLAMP (Settings.DynamicRateLimit, 1, 1000);
}
else if (!strcasecmp (name, "auto_input_rate"))
{
auto_input_rate = atoi (value);
}
else if (!strcasecmp (name, "gaussian_interpolation"))
{
}

View File

@ -4,9 +4,7 @@
#include <sys/time.h>
#include <libxml/parser.h>
#include <X11/Xlib.h>
#ifdef USE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
#include "gtk_control.h"
#include "snes_ntsc.h"
@ -58,9 +56,7 @@ class Snes9xConfig
unsigned char statusbar_visible;
unsigned char default_esc_behavior;
unsigned char prevent_screensaver;
unsigned int xrr_index;
int xrr_width;
int xrr_height;
int xrr_index;
unsigned char scale_to_fit;
unsigned char maintain_aspect_ratio;
int aspect_ratio;
@ -122,6 +118,7 @@ class Snes9xConfig
int mute_sound_turbo;
int sound_buffer_size;
int sound_playback_rate;
int auto_input_rate;
int sound_input_rate;
int rom_loaded;
int window_width, window_height;
@ -137,14 +134,10 @@ class Snes9xConfig
unsigned int rewind_granularity;
unsigned int rewind_buffer_size;
#ifdef USE_XRANDR
XRRScreenConfiguration *xrr_config;
XRRScreenSize *xrr_sizes;
int xrr_num_sizes;
Rotation xrr_rotation;
SizeID xrr_original_size;
#endif
XRRScreenResources *xrr_screen_resources;
XRROutputInfo *xrr_output_info;
XRRCrtcInfo *xrr_crtc_info;
RROutput xrr_output;
#ifdef USE_OPENGL
unsigned char sync_to_vblank;

View File

@ -1703,31 +1703,34 @@ S9xQueryDrivers (void)
gui_config->allow_opengl = 0;
#endif
#ifdef USE_XRANDR
gui_config->allow_xrandr = 0;
int error_base_p, event_base_p;
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
int major_version, minor_version;
Display *dpy = gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (top_level->get_window())));
Window xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (top_level->get_window())));
if (!XRRQueryExtension (dpy, &event_base_p, &error_base_p))
{
gui_config->change_display_resolution = FALSE;
return;
}
if (!XRRQueryVersion (dpy, &major_version, &minor_version))
{
gui_config->change_display_resolution = FALSE;
return;
}
if (minor_version < 3)
{
gui_config->change_display_resolution = FALSE;
return;
}
gui_config->allow_xrandr = 1;
if (!XRRQueryExtension (display, &event_base_p, &error_base_p))
{
gui_config->allow_xrandr = 0;
gui_config->change_display_resolution = FALSE;
}
if (gui_config->allow_xrandr)
{
gui_config->xrr_config = XRRGetScreenInfo (display,
DefaultRootWindow (display));
gui_config->xrr_original_size =
XRRConfigCurrentConfiguration (gui_config->xrr_config,
&(gui_config->xrr_rotation));
gui_config->xrr_sizes = XRRConfigSizes (gui_config->xrr_config,
&(gui_config->xrr_num_sizes));
}
#else
gui_config->allow_xrandr = 0;
#endif
gui_config->xrr_screen_resources = XRRGetScreenResources (dpy, xid);
gui_config->xrr_output = XRRGetOutputPrimary (dpy, xid);
gui_config->xrr_output_info = XRRGetOutputInfo (dpy, gui_config->xrr_screen_resources, gui_config->xrr_output);
gui_config->xrr_crtc_info = XRRGetCrtcInfo (dpy, gui_config->xrr_screen_resources, gui_config->xrr_output_info->crtc);
return;
}

View File

@ -770,7 +770,7 @@ S9xOpenGLDisplayDriver::create_window (int width, int height)
XMapWindow (display, xwindow);
XSync (display, False);
#if USE_GTK3
#if GTK_MAJOR_VERSION >= 3
gdk_window = gdk_x11_window_foreign_new_for_display (gtk_widget_get_display (drawing_area), xwindow);
#else
gdk_window = gdk_window_foreign_new (xwindow);

View File

@ -76,7 +76,7 @@ S9xXVDisplayDriver::create_window (int width, int height)
XMapWindow (display, xwindow);
XSync (display, False);
#if USE_GTK3
#if GTK_MAJOR_VERSION >= 3
gdk_window = gdk_x11_window_foreign_new_for_display (gtk_widget_get_display (drawing_area), xwindow);
#else
gdk_window = gdk_window_foreign_new (xwindow);

View File

@ -375,7 +375,7 @@ void
S9xAutoSaveSRAM (void)
{
Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR));
S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
S9xSaveCheatFile (S9xGetFilename (".bml", CHEAT_DIR));
return;
}

View File

@ -2,9 +2,6 @@
#include <stdlib.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkx.h>
#ifdef USE_GTK3
#include <gdk/gdkkeysyms-compat.h>
#endif
#include "gtk_preferences.h"
#include "gtk_config.h"
@ -14,6 +11,10 @@
#include "gtk_display.h"
#include "gtk_binding.h"
#if GTK_MAJOR_VERSION >= 3
#include <gdk/gdkkeysyms-compat.h>
#endif
#define SAME_GAME _("Same location as current game")
gboolean
@ -464,66 +465,22 @@ event_input_rate_changed (GtkRange *range, gpointer data)
return;
}
#ifdef USE_XRANDR
static double XRRGetExactRefreshRate (Display *dpy, Window window)
void
event_auto_input_rate_toggled (GtkToggleButton *togglebutton, gpointer data)
{
XRRScreenResources *resources = NULL;
XRROutputInfo *output_info = NULL;
XRRCrtcInfo *crtc_info = NULL;
RROutput output;
int event_base;
int error_base;
int version_major;
int version_minor;
double refresh_rate = 0.0;
int i;
if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
!XRRQueryVersion (dpy, &version_major, &version_minor))
{
return refresh_rate;
}
resources = XRRGetScreenResources (dpy, window);
output = XRRGetOutputPrimary (dpy, window);
output_info = XRRGetOutputInfo (dpy, resources, output);
crtc_info = XRRGetCrtcInfo (dpy, resources, output_info->crtc);
for (i = 0; i < resources->nmode; i++)
{
if (resources->modes[i].id == crtc_info->mode)
{
XRRModeInfo *m = &resources->modes[i];
refresh_rate = (double) m->dotClock / m->hTotal / m->vTotal;
break;
}
}
XRRFreeCrtcInfo (crtc_info);
XRRFreeOutputInfo (output_info);
XRRFreeScreenResources (resources);
return refresh_rate;
}
#endif
static void
event_set_input_rate (GtkButton *widget, gpointer data)
{
#ifdef USE_XRANDR
Snes9xPreferences *preferences = (Snes9xPreferences *) data;
GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET(top_level->get_window()));
Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdk_window));
Window window = GDK_COMPAT_WINDOW_XID (gdk_window);
double rate = XRRGetExactRefreshRate(dpy, window);
if (rate != 0.0)
preferences->set_slider("sound_input_rate", (int) (rate * 32040 / 60.09881389744051 + 0.5));
#endif
if (gtk_toggle_button_get_active (togglebutton))
{
preferences->set_slider("sound_input_rate", top_level->get_auto_input_rate ());
gtk_widget_set_sensitive (preferences->get_widget("sound_input_rate"), FALSE);
}
else
{
gtk_widget_set_sensitive (preferences->get_widget("sound_input_rate"), TRUE);
}
}
static void
event_about_clicked (GtkButton *widget, gpointer data)
{
@ -548,9 +505,6 @@ event_about_clicked (GtkButton *widget, gpointer data)
#ifdef USE_XV
version_string += _(" XVideo");
#endif
#ifdef USE_XRANDR
version_string += _(" XRandR");
#endif
#ifdef USE_JOYSTICK
version_string += _(" Joystick");
#endif
@ -565,7 +519,7 @@ event_about_clicked (GtkButton *widget, gpointer data)
gtk_widget_hide (about_dialog->get_widget ("preferences_splash"));
#ifdef USE_GTK3
#if GTK_MAJOR_VERSION >= 3
GtkCssProvider *provider;
GtkStyleContext *context;
@ -622,7 +576,7 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
{ "game_data_browse", G_CALLBACK (event_game_data_browse) },
{ "game_data_clear", G_CALLBACK (event_game_data_clear) },
{ "about_clicked", G_CALLBACK (event_about_clicked) },
{ "set_input_rate", G_CALLBACK (event_set_input_rate) },
{ "auto_input_rate_toggled", G_CALLBACK (event_auto_input_rate_toggled) },
#ifdef USE_JOYSTICK
{ "calibrate", G_CALLBACK (event_calibrate) },
#endif
@ -632,6 +586,8 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
last_toggled = NULL;
this->config = config;
mode_indices = NULL;
gtk_widget_realize (window);
signal_connect (callbacks);
@ -648,6 +604,8 @@ Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) :
Snes9xPreferences::~Snes9xPreferences (void)
{
delete[] mode_indices;
return;
}
@ -735,6 +693,9 @@ Snes9xPreferences::move_settings_to_dialog (void)
set_spin ("num_threads", config->num_threads);
set_check ("mute_sound_check", config->mute_sound);
set_check ("mute_sound_turbo_check", config->mute_sound_turbo);
set_check ("auto_input_rate", config->auto_input_rate);
gtk_widget_set_sensitive (get_widget("sound_input_rate"),
config->auto_input_rate ? FALSE : TRUE);
set_spin ("sound_buffer_size", config->sound_buffer_size);
set_slider ("sound_input_rate", config->sound_input_rate);
set_check ("sync_sound", Settings.SoundSync);
@ -824,21 +785,19 @@ Snes9xPreferences::get_settings_from_dialog (void)
int sound_needs_restart = 0;
int gfx_needs_restart = 0;
if ((config->sound_driver != get_combo ("sound_driver")) ||
(config->mute_sound != get_check ("mute_sound_check")) ||
(config->sound_buffer_size != (int) get_spin ("sound_buffer_size"))||
(Settings.Stereo != get_check ("stereo_check")) ||
(config->sound_playback_rate !=
(7 - (get_combo ("playback_combo")))) ||
(config->sound_input_rate != get_slider ("sound_input_rate")) ||
(Settings.SoundSync != get_check ("sync_sound")) ||
(Settings.DynamicRateControl != get_check ("dynamic_rate_control"))
)
if ((config->sound_driver != get_combo ("sound_driver")) ||
(config->mute_sound != get_check ("mute_sound_check")) ||
(config->sound_buffer_size != (int) get_spin ("sound_buffer_size")) ||
(Settings.Stereo != get_check ("stereo_check")) ||
(config->sound_playback_rate != (7 - (get_combo ("playback_combo")))) ||
(config->sound_input_rate != get_slider ("sound_input_rate")) ||
(config->auto_input_rate != get_check ("auto_input_rate")) ||
(Settings.SoundSync != get_check ("sync_sound")) ||
(Settings.DynamicRateControl != get_check ("dynamic_rate_control")))
{
sound_needs_restart = 1;
}
#ifdef USE_XRANDR
if ((config->change_display_resolution != get_check ("change_display_resolution") ||
(config->change_display_resolution &&
(config->xrr_index != get_combo ("resolution_combo")))) &&
@ -846,18 +805,13 @@ Snes9xPreferences::get_settings_from_dialog (void)
{
top_level->leave_fullscreen_mode ();
config->xrr_index = get_combo ("resolution_combo");
config->xrr_width = config->xrr_sizes[config->xrr_index].width;
config->xrr_height = config->xrr_sizes[config->xrr_index].height;
config->change_display_resolution = get_check ("change_display_resolution");
top_level->enter_fullscreen_mode ();
}
else
{
config->xrr_index = get_combo ("resolution_combo");
config->xrr_width = config->xrr_sizes[config->xrr_index].width;
config->xrr_height = config->xrr_sizes[config->xrr_index].height;
}
#endif
config->change_display_resolution = get_check ("change_display_resolution");
@ -893,6 +847,7 @@ Snes9xPreferences::get_settings_from_dialog (void)
config->sound_playback_rate = 7 - (get_combo ("playback_combo"));
config->sound_buffer_size = get_spin ("sound_buffer_size");
config->sound_input_rate = get_slider ("sound_input_rate");
config->auto_input_rate = get_check ("auto_input_rate");
Settings.SoundSync = get_check ("sync_sound");
config->mute_sound = get_check ("mute_sound_check");
config->mute_sound_turbo = get_check ("mute_sound_turbo_check");
@ -1096,28 +1051,42 @@ Snes9xPreferences::show (void)
if (config->allow_xrandr)
{
#ifdef USE_XRANDR
char size_string[256];
combo = get_widget ("resolution_combo");
config->xrr_index = 0;
for (int i = 0; i < config->xrr_num_sizes; i++)
mode_indices = new unsigned int[config->xrr_output_info->nmode];
for (int i = 0; i < config->xrr_output_info->nmode; i++)
{
if (config->xrr_width == config->xrr_sizes[i].width &&
config->xrr_height == config->xrr_sizes[i].height)
config->xrr_index = i;
for (int j = 0; j < config->xrr_screen_resources->nmode; j++)
{
if (config->xrr_screen_resources->modes[j].id == config->xrr_output_info->modes[i])
{
mode_indices[i] = j;
}
}
XRRModeInfo *m = &config->xrr_screen_resources->modes[mode_indices[i]];
unsigned long dotClock = m->dotClock;
if (m->modeFlags & RR_ClockDivideBy2)
dotClock /= 2;
if (m->modeFlags & RR_DoubleScan)
dotClock /= 2;
if (m->modeFlags & RR_DoubleClock)
dotClock *= 2;
snprintf (size_string,
256,
"%dx%d",
config->xrr_sizes[i].width,
config->xrr_sizes[i].height);
"%dx%d @ %.3fHz",
m->width,
m->height,
(double) dotClock / m->hTotal / m->vTotal);
combo_box_append (GTK_COMBO_BOX (combo), size_string);
}
#endif
if (config->xrr_index > config->xrr_output_info->nmode)
config->xrr_index = 0;
}
else
{

View File

@ -40,6 +40,8 @@ class Snes9xPreferences : public GtkBuilderWindow
private:
void get_settings_from_dialog (void);
void move_settings_to_dialog (void);
unsigned int *mode_indices;
};
#endif /* __GTK_PREFERENCES_H */

View File

@ -195,17 +195,6 @@ S9xOpenROM (const char *rom_filename)
if (loaded)
{
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

@ -36,7 +36,7 @@
extern Snes9xWindow *top_level;
extern Snes9xConfig *gui_config;
#ifdef USE_GTK3
#if GTK_MAJOR_VERSION >= 3
#define GDK_COMPAT_WINDOW_XID(window) (gdk_x11_window_get_xid (window))
#else
#define GDK_COMPAT_WINDOW_XID(window) (GDK_WINDOW_XWINDOW (window))

View File

@ -1,10 +1,8 @@
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#ifdef USE_GTK3
#include <gdk/gdkkeysyms-compat.h>
#endif
#include <cairo.h>
#include <X11/Xatom.h>
#ifdef USE_XV
#include <X11/extensions/XShm.h>
@ -24,6 +22,10 @@
#include "gtk_netplay.h"
#endif
#if GTK_MAJOR_VERSION >= 3
#include <gdk/gdkkeysyms-compat.h>
#endif
static gboolean
event_main_window_delete (GtkWidget *widget,
GdkEvent *event,
@ -133,7 +135,7 @@ event_open_netplay (GtkWidget *widget, gpointer data)
return TRUE;
}
#ifdef USE_GTK3
#if GTK_MAJOR_VERSION >= 3
static gboolean
event_drawingarea_draw (GtkWidget *widget,
cairo_t *cr,
@ -147,9 +149,9 @@ event_drawingarea_draw (GtkWidget *widget,
return FALSE;
}
#endif
#ifndef USE_GTK3
#else
static gboolean
event_drawingarea_expose (GtkWidget *widget,
GdkEventExpose *event,
@ -623,13 +625,13 @@ Snes9xWindow::Snes9xWindow (Snes9xConfig *config) :
}
drawing_area = GTK_DRAWING_AREA (get_widget ("drawingarea"));
#ifndef USE_GTK3
#if GTK_MAJOR_VERSION < 3
gtk_widget_set_double_buffered (GTK_WIDGET (drawing_area), FALSE);
#endif
gtk_widget_realize (window);
gtk_widget_realize (GTK_WIDGET (drawing_area));
#ifndef USE_GTK3
#if GTK_MAJOR_VERSION < 3
gdk_window_set_back_pixmap (gtk_widget_get_window (window), NULL, FALSE);
gdk_window_set_back_pixmap (gtk_widget_get_window (GTK_WIDGET (drawing_area)), NULL, FALSE);
#endif
@ -646,7 +648,7 @@ Snes9xWindow::Snes9xWindow (Snes9xConfig *config) :
gtk_widget_hide (get_widget ("sync_clients_separator"));
#endif
#ifdef USE_GTK3
#if GTK_MAJOR_VERSION >= 3
g_signal_connect_data (drawing_area,
"draw",
G_CALLBACK (event_drawingarea_draw),
@ -1527,6 +1529,80 @@ Snes9xWindow::toggle_fullscreen_mode (void)
enter_fullscreen_mode ();
}
static double XRRGetExactRefreshRate (Display *dpy, Window window)
{
XRRScreenResources *resources = NULL;
XRROutputInfo *output_info = NULL;
XRRCrtcInfo *crtc_info = NULL;
RROutput output;
int event_base;
int error_base;
int version_major;
int version_minor;
double refresh_rate = 0.0;
int i;
if (!XRRQueryExtension (dpy, &event_base, &error_base) ||
!XRRQueryVersion (dpy, &version_major, &version_minor))
{
return refresh_rate;
}
resources = XRRGetScreenResources (dpy, window);
output = XRRGetOutputPrimary (dpy, window);
output_info = XRRGetOutputInfo (dpy, resources, output);
crtc_info = XRRGetCrtcInfo (dpy, resources, output_info->crtc);
for (i = 0; i < resources->nmode; i++)
{
if (resources->modes[i].id == crtc_info->mode)
{
XRRModeInfo *m = &resources->modes[i];
refresh_rate = (double) m->dotClock / m->hTotal / m->vTotal;
refresh_rate /= m->modeFlags & RR_DoubleScan ? 2 : 1;
refresh_rate /= m->modeFlags & RR_ClockDivideBy2 ? 2 : 1;
refresh_rate *= m->modeFlags & RR_DoubleClock ? 2 : 1;
break;
}
}
XRRFreeCrtcInfo (crtc_info);
XRRFreeOutputInfo (output_info);
XRRFreeScreenResources (resources);
return refresh_rate;
}
double
Snes9xWindow::get_refresh_rate (void)
{
Window xid = gdk_x11_window_get_xid(gtk_widget_get_window (window));
Display *dpy = gdk_x11_display_get_xdisplay(gtk_widget_get_display (window));
double refresh_rate = XRRGetExactRefreshRate (dpy, xid);
if (refresh_rate < 10.0)
{
printf ("Warning: Couldn't read refresh rate.\n");
refresh_rate = 60.0;
}
return refresh_rate;
}
int
Snes9xWindow::get_auto_input_rate (void)
{
return (int) (get_refresh_rate () * 32040.0 / 60.09881389744051 + 0.5);
}
static void set_bypass_compositor (Display *dpy, Window window, unsigned char bypass)
{
Atom net_wm_bypass_compositor = XInternAtom (dpy, "_NET_WM_BYPASS_COMPOSITOR", False);
XChangeProperty (dpy, window, net_wm_bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) &bypass, 1);
}
void
Snes9xWindow::enter_fullscreen_mode (void)
{
@ -1542,49 +1618,44 @@ Snes9xWindow::enter_fullscreen_mode (void)
gtk_window_get_position (GTK_WINDOW (window), &nfs_x, &nfs_y);
if (config->change_display_resolution)
{
GdkDisplay *gdk_display = gtk_widget_get_display (window);
Display *dpy = gdk_x11_display_get_xdisplay (gdk_display);
gdk_display_sync (gdk_display);
if (XRRSetCrtcConfig (dpy,
config->xrr_screen_resources,
config->xrr_output_info->crtc,
CurrentTime,
config->xrr_crtc_info->x,
config->xrr_crtc_info->y,
config->xrr_output_info->modes[config->xrr_index],
config->xrr_crtc_info->rotation,
&config->xrr_output,
1) != 0)
{
config->change_display_resolution = 0;
}
if (gui_config->auto_input_rate)
{
Settings.SoundInputRate = top_level->get_auto_input_rate ();
S9xUpdateDynamicRate (1, 2);
}
}
/* Make sure everything is done synchronously */
gdk_display_sync (gdk_display_get_default ());
gtk_window_fullscreen (GTK_WINDOW (window));
#ifdef USE_XRANDR
if (config->change_display_resolution)
{
int mode = -1;
for (int i = 0; i < config->xrr_num_sizes; i++)
{
if (config->xrr_sizes[i].width == config->xrr_width &&
config->xrr_sizes[i].height == config->xrr_height)
{
mode = i;
}
}
if (mode < 0)
{
config->change_display_resolution = 0;
}
else
{
GdkDisplay *gdk_display = gtk_widget_get_display (window);
Display *display = gdk_x11_display_get_xdisplay (gdk_display);
GdkScreen *screen = gtk_widget_get_screen (window);
GdkWindow *root = gdk_screen_get_root_window (screen);
gdk_display_sync (gdk_display_get_default ());
XRRSetScreenConfig (display,
config->xrr_config,
GDK_COMPAT_WINDOW_XID (root),
(SizeID) mode,
config->xrr_rotation,
CurrentTime);
}
}
#endif
gdk_display_sync (gdk_display_get_default ());
gtk_window_present (GTK_WINDOW (window));
set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (drawing_area))),
gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (drawing_area))),
1);
config->fullscreen = 1;
config->rom_loaded = rom_loaded;
@ -1607,33 +1678,38 @@ Snes9xWindow::leave_fullscreen_mode (void)
config->rom_loaded = 0;
#ifdef USE_XRANDR
if (config->change_display_resolution)
{
gtk_widget_hide (window);
GdkDisplay *gdk_display = gtk_widget_get_display (window);
Display *display = gdk_x11_display_get_xdisplay (gdk_display);
GdkScreen *screen = gtk_widget_get_screen (window);
GdkWindow *root = gdk_screen_get_root_window (screen);
Display *dpy = gdk_x11_display_get_xdisplay (gdk_display);
XRRSetScreenConfig (display,
config->xrr_config,
GDK_COMPAT_WINDOW_XID (root),
(SizeID) config->xrr_original_size,
config->xrr_rotation,
CurrentTime);
if (config->xrr_index > config->xrr_output_info->nmode)
config->xrr_index = 0;
gdk_display_sync (gdk_display);
XRRSetCrtcConfig (dpy,
config->xrr_screen_resources,
config->xrr_output_info->crtc,
CurrentTime,
config->xrr_crtc_info->x,
config->xrr_crtc_info->y,
config->xrr_crtc_info->mode,
config->xrr_crtc_info->rotation,
&config->xrr_output,
1);
if (gui_config->auto_input_rate)
{
Settings.SoundInputRate = top_level->get_auto_input_rate ();
S9xUpdateDynamicRate (1, 2);
}
}
#endif
gtk_window_unfullscreen (GTK_WINDOW (window));
#ifdef USE_XRANDR
if (config->change_display_resolution)
{
gtk_widget_show (window);
}
#endif
set_bypass_compositor (gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (drawing_area))),
gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (drawing_area))),
0);
resize (nfs_width, nfs_height);
gtk_window_move (GTK_WINDOW (window), nfs_x, nfs_y);
@ -1966,7 +2042,7 @@ Snes9xWindow::get_cairo (void)
GtkWidget *drawing_area = GTK_WIDGET (this->drawing_area);
#ifndef USE_GTK3
#if GTK_MAJOR_VERSION < 3
cr = gdk_cairo_create (gtk_widget_get_window (drawing_area));
#else
GtkAllocation allocation;
@ -1988,7 +2064,7 @@ Snes9xWindow::release_cairo (void)
{
if (cairo_owned)
{
#ifndef USE_GTK3
#if GTK_MAJOR_VERSION < 3
cairo_destroy (cr);
#else
gdk_window_end_draw_frame (gtk_widget_get_window (GTK_WIDGET (drawing_area)), gdk_drawing_context);

View File

@ -61,6 +61,8 @@ class Snes9xWindow : public GtkBuilderWindow
void resize_to_multiple (int factor);
void resize_viewport (int width, int height);
void expose (void);
double get_refresh_rate (void);
int get_auto_input_rate (void);
cairo_t *get_cairo (void);
void release_cairo (void);
@ -83,7 +85,7 @@ class Snes9xWindow : public GtkBuilderWindow
GtkWidget *recent_menu;
cairo_t *cr;
int cairo_owned;
#ifdef USE_GTK3
#if GTK_MAJOR_VERSION >= 3
GdkDrawingContext *gdk_drawing_context;
cairo_region_t *cairo_region;
#endif

View File

@ -127,7 +127,14 @@ S9xPortSoundInit (void)
{
driver->init ();
Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 8000, 48000);
if (gui_config->auto_input_rate)
{
Settings.SoundInputRate = top_level->get_auto_input_rate ();
}
else
{
Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 8000, 48000);
}
Settings.SoundPlaybackRate = playback_rates[gui_config->sound_playback_rate];

View File

@ -256,8 +256,8 @@
<property name="page_increment">0.10000000000000001</property>
</object>
<object class="GtkDialog" id="cheat_window">
<property name="width_request">512</property>
<property name="height_request">350</property>
<property name="width_request">720</property>
<property name="height_request">480</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">5</property>
@ -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>
@ -438,6 +438,36 @@
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkButton" id="delete_all_cheats_button">
<property name="label" translatable="yes">Delete All Cheats</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<signal name="clicked" handler="delete_all_cheats" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cheat_search_button">
<property name="label" translatable="yes">Search Cheat Database</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<signal name="clicked" handler="search_database" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">7</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -4017,7 +4047,22 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="auto_input_rate">
<property name="label" translatable="yes">Automatically adjust input rate to display</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Sets the correct input rate based on the display's refresh rate</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="auto_input_rate_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="dynamic_rate_control">
<property name="label" translatable="yes">Dynamic rate control</property>
@ -4030,7 +4075,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
@ -4047,7 +4092,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
<child>
@ -4063,7 +4108,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
<child>
@ -4079,7 +4124,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
<property name="position">6</property>
</packing>
</child>
<child>
@ -4141,8 +4186,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4155,8 +4200,8 @@
<property name="label" translatable="yes">Buffer size:</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4169,8 +4214,8 @@
<property name="label" translatable="yes">Dynamic rate limit:</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4199,8 +4244,8 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options">GTK_FILL</property>
<property name="x_options">GTK_FILL</property>
</packing>
@ -4213,8 +4258,8 @@
<property name="label" translatable="yes">Input rate:</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4232,8 +4277,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
@ -4267,23 +4312,6 @@
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkButton" id="set_input_rate_button">
<property name="label" translatable="yes">Automatically Set Input Rate</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="set_input_rate" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label139">
<property name="visible">True</property>
@ -4292,8 +4320,8 @@
<property name="label" translatable="yes">Video rate:</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
@ -4307,8 +4335,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
@ -4316,7 +4344,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
<property name="position">7</property>
</packing>
</child>
</object>

View File

@ -6,6 +6,7 @@ SOURCES_CXX := $(CORE_DIR)/apu/apu.cpp \
$(CORE_DIR)/apu/bapu/dsp/SPC_DSP.cpp \
$(CORE_DIR)/apu/bapu/smp/smp.cpp \
$(CORE_DIR)/apu/bapu/smp/smp_state.cpp \
$(CORE_DIR)/bml.cpp \
$(CORE_DIR)/bsx.cpp \
$(CORE_DIR)/c4.cpp \
$(CORE_DIR)/c4emu.cpp \

View File

@ -395,16 +395,10 @@ void retro_set_controller_port_device(unsigned port, unsigned device)
void retro_cheat_reset()
{
S9xDeleteCheats();
S9xApplyCheats();
}
void retro_cheat_set(unsigned index, bool enabled, const char *codeline)
{
uint32 address;
uint8 val;
bool8 sram;
uint8 bytes[3];//used only by GoldFinger, ignored for now
char codeCopy[256];
char* code;
@ -421,36 +415,21 @@ void retro_cheat_set(unsigned index, bool enabled, const char *codeline)
code[8]='\0';
}
if (S9xGameGenieToRaw(code, address, val)==NULL ||
S9xProActionReplayToRaw(code, address, val)==NULL)
/* Goldfinger was broken and nobody noticed. Removed */
if (S9xAddCheatGroup ("retro", code) >= 0)
{
Cheat.c[Cheat.num_cheats].address = address;
Cheat.c[Cheat.num_cheats].byte = val;
Cheat.c[Cheat.num_cheats].enabled = enabled;
Cheat.c[Cheat.num_cheats].saved = FALSE; // it'll be saved next time cheats run anyways
Cheat.num_cheats++;
}
else if (S9xGoldFingerToRaw(code, address, sram, val, bytes)==NULL)
{
if (!sram)
{
for (int i=0;i<val;i++){
Cheat.c[Cheat.num_cheats].address = address;
Cheat.c[Cheat.num_cheats].byte = bytes[i];
Cheat.c[Cheat.num_cheats].enabled = enabled;
Cheat.c[Cheat.num_cheats].saved = FALSE; // it'll be saved next time cheats run anyways
Cheat.num_cheats++;
}
}
if (enabled)
S9xEnableCheatGroup (Cheat.g.size () - 1);
}
else
{
printf("CHEAT: Failed to recognize %s\n",code);
}
code=strtok(NULL,"+,.; "); // bad code, ignore
}
Settings.ApplyCheats=true;
S9xApplyCheats();
S9xCheatsEnable();
}
static void init_descriptors(void)

View File

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

View File

@ -1513,7 +1513,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
{
// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
// then, when to call S9xOpcode_NMI()?
CPU.NMILine = TRUE;
CPU.NMIPending = TRUE;
Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
}

View File

@ -384,7 +384,7 @@ static FreezeData SnapCPU[] =
DELETED_INT_ENTRY(6, 7, WaitAddress, 4),
DELETED_INT_ENTRY(6, 7, WaitCounter, 4),
DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4),
INT_ENTRY(7, NMILine),
INT_ENTRY(7, NMIPending),
INT_ENTRY(7, IRQLine),
INT_ENTRY(7, IRQTransition),
INT_ENTRY(7, IRQLastState),
@ -1745,7 +1745,7 @@ int S9xUnfreezeFromStream (STREAM stream)
{
printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION);
CPU.NMILine = (CPU.Flags & (1 << 7)) ? TRUE : FALSE;
CPU.NMIPending = (CPU.Flags & (1 << 7)) ? TRUE : FALSE;
CPU.IRQLine = (CPU.Flags & (1 << 11)) ? TRUE : FALSE;
CPU.IRQTransition = FALSE;
CPU.IRQLastState = FALSE;

View File

@ -386,6 +386,7 @@ void S9xLoadConfigFiles (char **argv, int argc)
Settings.ForceInterleaved2 = conf.GetBool("ROM::Interleaved2", false);
Settings.ForceInterleaveGD24 = conf.GetBool("ROM::InterleaveGD24", false);
Settings.ApplyCheats = conf.GetBool("ROM::Cheat", false);
Cheat.enabled = false;
Settings.NoPatch = !conf.GetBool("ROM::Patch", true);
Settings.IgnorePatchChecksum = conf.GetBool("ROM::IgnorePatchChecksum", false);
@ -583,9 +584,8 @@ void S9xUsage (void)
// PATCH/CHEAT OPTIONS
S9xMessage(S9X_INFO, S9X_USAGE, "-nopatch Do not apply any available IPS/UPS patches");
S9xMessage(S9X_INFO, S9X_USAGE, "-cheat Apply saved cheats");
S9xMessage(S9X_INFO, S9X_USAGE, "-gamegenie <code> Supply a Game Genie code");
S9xMessage(S9X_INFO, S9X_USAGE, "-actionreplay <code> Supply a Pro-Action Reply code");
S9xMessage(S9X_INFO, S9X_USAGE, "-goldfinger <code> Supply a Gold Finger code");
S9xMessage(S9X_INFO, S9X_USAGE, "-cheatcode <code> Supply a cheat code in Game Genie,");
S9xMessage(S9X_INFO, S9X_USAGE, " Pro-Action Replay, or Raw format (address=byte)");
S9xMessage(S9X_INFO, S9X_USAGE, "");
#ifdef NETPLAY_SUPPORT
@ -624,6 +624,31 @@ void S9xUsage (void)
exit(1);
}
void S9xParseArgsForCheats (char **argv, int argc)
{
for (int i = 1; i < argc; i++)
{
if (!strcasecmp(argv[i], "-gamegenie") ||
!strcasecmp(argv[i], "-actionreplay") ||
!strcasecmp(argv[i], "-cheatcode"))
{
if (i + 1 < argc)
{
if (S9xAddCheatGroup ("Unknown", argv[++i]) < 0)
{
S9xMessage(S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, "Code format invalid");
}
else
{
S9xEnableCheatGroup (Cheat.g.size() - 1);
}
}
else
S9xUsage();
}
}
}
char * S9xParseArgs (char **argv, int argc)
{
for (int i = 1; i < argc; i++)
@ -777,63 +802,25 @@ 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") ||
!strcasecmp(argv[i], "-cheatcode"))
{
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 (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);
}
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)
if (S9xAddCheatGroup ("Unknown", argv[++i]) < 0)
{
for (int c = 0; c < num_bytes; c++)
S9xAddCheat(TRUE, FALSE, address + c, bytes[c]);
S9xMessage(S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, "Code format invalid");
}
else
S9xMessage(S9X_ERROR, S9X_GOLD_FINGER_CODE_ERROR, error);
{
S9xEnableCheatGroup (Cheat.g.size() - 1);
}
}
else
S9xUsage();
}
else
// NETPLAY OPTIONS
#ifdef NETPLAY_SUPPORT

View File

@ -303,7 +303,7 @@ struct SCPUState
int32 PrevCycles;
int32 V_Counter;
uint8 *PCBase;
bool8 NMILine;
bool8 NMIPending;
bool8 IRQLine;
bool8 IRQTransition;
bool8 IRQLastState;

View File

@ -8,7 +8,7 @@
OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"`
BUILDDIR = .
OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../msu1.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o ../sha256.o unix.o x11.o
OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../msu1.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o ../sha256.o ../bml.o unix.o x11.o
DEFS = -DMITSHM
ifdef S9XDEBUGGER

View File

@ -1619,9 +1619,8 @@ void S9xExit (void)
#endif
Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR));
S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
S9xResetSaveTimer(FALSE);
S9xSaveCheatFile(S9xGetFilename(".bml", CHEAT_DIR));
S9xUnmapAllControls();
S9xDeinitDisplay();
Memory.Deinit();
@ -1698,6 +1697,7 @@ int main (int argc, char **argv)
S9xLoadConfigFiles(argv, argc);
rom_filename = S9xParseArgs(argv, argc);
S9xDeleteCheats();
make_snes9x_dirs();
@ -1785,9 +1785,18 @@ int main (int argc, char **argv)
exit(1);
}
S9xDeleteCheats();
S9xCheatsEnable();
NSRTControllerSetup();
Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR));
S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
if (Settings.ApplyCheats)
{
if (!S9xLoadCheatFile(S9xGetFilename(".bml", CHEAT_DIR)))
S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
}
S9xParseArgsForCheats(argv, argc);
CPU.Flags = saved_flags;
Settings.StopEmulation = FALSE;

View File

@ -157,7 +157,10 @@
#define IDC_KEYBOARD 1127
#define IDC_ALLOWLEFTRIGHT 1127
#define IDC_CHEAT_ADDRESS 1128
#define IDC_SEARCH_DB 1128
#define IDC_CHEAT_BYTE 1129
#define IDC_DELETE_CHEAT2 1129
#define IDC_DELETE_ALL 1129
#define IDC_ADD_CHEAT 1130
#define IDC_CHEAT_LIST 1131
#define IDC_PICTURE 1132
@ -386,28 +389,6 @@
#define ID_SOUND_22050HZ 40035
#define ID_SOUND_44100HZ 40036
#define ID_SOUND_30000HZ 40037
#define ID_FILE_SAVE0 44000
#define ID_FILE_SAVE1 44001
#define ID_FILE_SAVE2 44002
#define ID_FILE_SAVE3 44003
#define ID_FILE_SAVE4 44004
#define ID_FILE_SAVE5 44005
#define ID_FILE_SAVE6 44006
#define ID_FILE_SAVE7 44007
#define ID_FILE_SAVE8 44008
#define ID_FILE_SAVE9 44009
#define ID_FILE_SAVE_FILE 44010
#define ID_FILE_LOAD0 44020
#define ID_FILE_LOAD1 44021
#define ID_FILE_LOAD2 44022
#define ID_FILE_LOAD3 44023
#define ID_FILE_LOAD4 44024
#define ID_FILE_LOAD5 44025
#define ID_FILE_LOAD6 44026
#define ID_FILE_LOAD7 44027
#define ID_FILE_LOAD8 44028
#define ID_FILE_LOAD9 44029
#define ID_FILE_LOAD_FILE 44030
#define ID_CHEAT_ENTER 40063
#define ID_CHEAT_SEARCH 40064
#define ID_CHEAT_APPLY 40065
@ -504,13 +485,35 @@
#define ID_DEBUG_APU_TRACE 40173
#define ID_EMULATION_BACKGROUNDINPUT 40174
#define ID_SAVEMEMPACK 40175
#define ID_FILE_SAVE0 44000
#define ID_FILE_SAVE1 44001
#define ID_FILE_SAVE2 44002
#define ID_FILE_SAVE3 44003
#define ID_FILE_SAVE4 44004
#define ID_FILE_SAVE5 44005
#define ID_FILE_SAVE6 44006
#define ID_FILE_SAVE7 44007
#define ID_FILE_SAVE8 44008
#define ID_FILE_SAVE9 44009
#define ID_FILE_SAVE_FILE 44010
#define ID_FILE_LOAD0 44020
#define ID_FILE_LOAD1 44021
#define ID_FILE_LOAD2 44022
#define ID_FILE_LOAD3 44023
#define ID_FILE_LOAD4 44024
#define ID_FILE_LOAD5 44025
#define ID_FILE_LOAD6 44026
#define ID_FILE_LOAD7 44027
#define ID_FILE_LOAD8 44028
#define ID_FILE_LOAD9 44029
#define ID_FILE_LOAD_FILE 44030
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 153
#define _APS_NEXT_RESOURCE_VALUE 154
#define _APS_NEXT_COMMAND_VALUE 40176
#define _APS_NEXT_CONTROL_VALUE 3022
#define _APS_NEXT_SYMED_VALUE 101

View File

@ -60,7 +60,7 @@ END
IDD_SOUND_OPTS DIALOGEX 0, 0, 413, 144
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "Sound Settings"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Sound Quality",IDC_STATIC,119,7,286,112,0,WS_EX_TRANSPARENT
DEFPUSHBUTTON "&OK",IDOK,288,122,56,16
@ -95,7 +95,7 @@ END
IDD_ROM_INFO DIALOGEX 0, 0, 233, 185
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "Rom Info"
FONT 8, "MS Sans Serif", 0, 0, 0x0
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,85,164,50,14
EDITTEXT IDC_ROM_DATA,7,7,219,153,ES_MULTILINE | ES_READONLY
@ -104,7 +104,7 @@ END
IDD_ABOUT DIALOGEX 0, 0, 232, 181
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "APP - About Dialog"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,90,160,50,14
EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY | WS_VSCROLL,WS_EX_STATICEDGE
@ -113,7 +113,7 @@ END
IDD_EMU_SETTINGS DIALOGEX 0, 0, 341, 173
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "APP - Emulator Settings"
FONT 8, "MS Sans Serif", 0, 0, 0x0
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_CUSTOM_FOLDER_FIELD,102,28,163,14,ES_AUTOHSCROLL
PUSHBUTTON "&Browse...",IDC_BROWSE,286,27,48,14
@ -152,7 +152,7 @@ END
IDD_OPEN_ROM DIALOGEX 0, 0, 430, 223
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "Open ROM"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "Tree1",IDC_ROM_DIR,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | WS_BORDER | WS_TABSTOP,4,4,154,192,WS_EX_CLIENTEDGE
CONTROL "List1",IDC_ROMLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_OWNERDATA | WS_TABSTOP,161,4,266,192,WS_EX_CLIENTEDGE
@ -171,7 +171,7 @@ END
IDD_NPOPTIONS DIALOGEX 0, 0, 187, 161
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION
CAPTION "Netplay Options"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Port Settings",IDC_PORTNUMBLOCK,5,5,180,25,0,WS_EX_TRANSPARENT
RTEXT "Socket Port Number",IDC_LABEL_PORTNUM,10,15,85,10,SS_CENTERIMAGE
@ -195,7 +195,7 @@ END
IDD_NEWDISPLAY DIALOGEX 0, 0, 353, 283
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION
CAPTION "Display Settings"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,239,259,50,14
PUSHBUTTON "Cancel",IDCANCEL,296,259,50,14
@ -246,32 +246,30 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,168,131,10
END
IDD_CHEATER DIALOGEX 0, 0, 262, 218
IDD_CHEATER DIALOGEX 0, 0, 375, 194
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "Cheat Entry and Editor"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "List1",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,5,200,125,WS_EX_CLIENTEDGE
PUSHBUTTON "&Add",IDC_ADD_CHEAT,215,5,40,15,WS_DISABLED
PUSHBUTTON "&Delete",IDC_DELETE_CHEAT,215,25,40,15,WS_DISABLED
PUSHBUTTON "&Update",IDC_UPDATE_CHEAT,215,45,40,15,WS_DISABLED
PUSHBUTTON "C&lear",IDC_CLEAR_CHEATS,215,65,40,15
EDITTEXT IDC_CHEAT_CODE,86,134,118,15,ES_UPPERCASE | ES_AUTOHSCROLL
EDITTEXT IDC_CHEAT_DESCRIPTION,85,154,119,15,ES_AUTOHSCROLL
EDITTEXT IDC_CHEAT_ADDRESS,85,175,44,15,ES_UPPERCASE | ES_AUTOHSCROLL
EDITTEXT IDC_CHEAT_BYTE,215,175,26,15,ES_UPPERCASE | ES_AUTOHSCROLL
PUSHBUTTON "&OK",IDOK,93,196,50,15
PUSHBUTTON "&Cancel",IDCANCEL,151,196,50,15
RTEXT "Enter Cheat Code:",IDC_LABEL_CHEAT_CODE,23,134,59,15,SS_CENTERIMAGE
RTEXT "Cheat Description",IDC_LABEL_CHEAT_DESCRIPTION,19,154,61,15,SS_CENTERIMAGE
RTEXT "Cheat Address (hex)",IDC_LABEL_CHEAT_ADDRESS,18,175,64,15,SS_CENTERIMAGE
RTEXT "New Value (dec or hex)",IDC_LABEL_CHEAT_BYTE,134,175,74,15,SS_CENTERIMAGE
CONTROL "List1",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,5,291,125,WS_EX_CLIENTEDGE
PUSHBUTTON "&Add",IDC_ADD_CHEAT,306,7,62,15,WS_DISABLED
PUSHBUTTON "&Delete",IDC_DELETE_CHEAT,306,66,62,15,WS_DISABLED
PUSHBUTTON "&Update",IDC_UPDATE_CHEAT,306,26,62,15,WS_DISABLED
PUSHBUTTON "C&lear",IDC_CLEAR_CHEATS,306,46,62,15
EDITTEXT IDC_CHEAT_CODE,86,134,206,15,ES_UPPERCASE | ES_AUTOHSCROLL
EDITTEXT IDC_CHEAT_DESCRIPTION,86,154,206,15,ES_AUTOHSCROLL
PUSHBUTTON "&OK",IDOK,99,174,50,15
PUSHBUTTON "&Cancel",IDCANCEL,154,174,50,15
RTEXT "Enter Cheat Code:",IDC_LABEL_CHEAT_CODE,19,134,61,15,SS_CENTERIMAGE
RTEXT "Cheat Description:",IDC_LABEL_CHEAT_DESCRIPTION,19,154,61,15,SS_CENTERIMAGE
PUSHBUTTON "&Search Database",IDC_SEARCH_DB,306,115,62,15
PUSHBUTTON "&Remove All",IDC_DELETE_ALL,306,85,62,15
END
IDD_NETPLAYPROGRESS DIALOG 0, 0, 186, 61
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Sans Serif"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Static",IDC_STATIC,5,0,160,20
CONTROL "Progress1",IDC_NPPROGRESS,"msctls_progress32",WS_BORDER,5,30,160,25
@ -280,7 +278,7 @@ END
IDD_INPUTCONFIG DIALOGEX 0, 0, 327, 150
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION
CAPTION " "
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
COMBOBOX IDC_JPCOMBO,12,11,77,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Enabled",IDC_JPTOGGLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,100,13,42,10
@ -328,7 +326,7 @@ END
IDD_CHEAT_SEARCH DIALOGEX 0, 0, 272, 275
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "Cheat Search"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "&OK",IDOK,161,253,50,14
PUSHBUTTON "&Cancel",IDCANCEL,218,253,50,14
@ -368,7 +366,7 @@ END
IDD_CHEAT_FROM_SEARCH DIALOG 0, 0, 187, 143
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU
CAPTION "Cheat Details"
FONT 8, "MS Sans Serif"
FONT 8, "MS Shell Dlg"
BEGIN
PUSHBUTTON "&OK",IDOK,85,123,45,13
PUSHBUTTON "&Cancel",IDCANCEL,135,123,45,13
@ -387,7 +385,7 @@ END
IDD_OPENMOVIE DIALOGEX 0, 0, 304, 166
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Play Movie"
FONT 8, "MS Sans Serif", 0, 0, 0x0
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,187,149,50,14
PUSHBUTTON "Cancel",IDCANCEL,246,149,50,14
@ -422,7 +420,7 @@ END
IDD_CREATEMOVIE DIALOGEX 0, 0, 303, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Record Movie"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,187,96,50,14
PUSHBUTTON "Cancel",IDCANCEL,246,96,50,14
@ -446,7 +444,7 @@ END
IDD_KEYCUSTOM DIALOGEX 0, 0, 349, 203
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION
CAPTION "Customize Special Keys"
FONT 8, "MS Sans Serif", 0, 0, 0x1
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Cancel",IDCANCEL,66,182,50,14
PUSHBUTTON "OK",IDOK,16,182,50,14
@ -552,7 +550,7 @@ END
IDD_NETCONNECT DIALOGEX 0, 0, 227, 61
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION
CAPTION "Connect to Server"
FONT 8, "MS Sans Serif", 0, 0, 0x0
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "&OK",IDOK,120,45,50,14
PUSHBUTTON "Canccel",IDCANCEL,175,45,50,14
@ -622,9 +620,8 @@ BEGIN
IDD_CHEATER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 255
RIGHTMARGIN, 368
TOPMARGIN, 7
BOTTOMMARGIN, 211
END
IDD_NETPLAYPROGRESS, DIALOG
@ -1005,6 +1002,11 @@ BEGIN
0
END
IDD_CHEATER AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -146,6 +146,9 @@
<Profile>true</Profile>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<Manifest>
<EnableDpiAwareness>true</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">
<Midl>
@ -191,6 +194,9 @@
<Profile>false</Profile>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<Manifest>
<EnableDpiAwareness>true</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
<Midl>
@ -240,6 +246,9 @@
<Profile>true</Profile>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<Manifest>
<EnableDpiAwareness>true</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
<Midl>
@ -289,6 +298,9 @@
<Profile>false</Profile>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<Manifest>
<EnableDpiAwareness>true</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<CustomBuild Include="..\65c816.h" />
@ -389,6 +401,7 @@
<ClInclude Include="..\msu1.h" />
<ClInclude Include="..\statemanager.h" />
<ClInclude Include="..\sha256.h" />
<ClInclude Include="..\bml.h" />
<CustomBuild Include="..\stream.h" />
<CustomBuild Include="..\tile.h" />
<ClInclude Include="..\unzip\crypt.h" />
@ -519,6 +532,7 @@
</ClCompile>
<ClCompile Include="..\statemanager.cpp" />
<ClCompile Include="..\sha256.cpp" />
<ClCompile Include="..\bml.cpp" />
<ClCompile Include="..\stream.cpp" />
<ClCompile Include="..\tile.cpp" />
<ClCompile Include="..\unzip\ioapi.c" />

View File

@ -51,6 +51,9 @@
<ClInclude Include="..\sha256.h">
<Filter>Emu</Filter>
</ClInclude>
<ClInclude Include="..\bml.h">
<Filter>Emu</Filter>
</ClInclude>
<ClInclude Include="..\unzip\crypt.h">
<Filter>UnZip</Filter>
</ClInclude>
@ -404,6 +407,9 @@
<ClCompile Include="..\sha256.cpp">
<Filter>Emu</Filter>
</ClCompile>
<ClCompile Include="..\bml.cpp">
<Filter>Emu</Filter>
</ClCompile>
<ClCompile Include="..\stream.cpp">
<Filter>Emu</Filter>
</ClCompile>

View File

@ -546,6 +546,7 @@ Nintendo is a trade mark.")
the current value. This value is used when a cheat is unapplied.\n\
(If left blank, no value is restored when the cheat is unapplied)")
#define SEARCH_ERR_INVALIDSEARCHVALUE TEXT("Please enter a valid value for a search!")
#define SEARCH_COLUMN_CODE TEXT("Code")
#define SEARCH_COLUMN_ADDRESS TEXT("Address")
#define SEARCH_COLUMN_VALUE TEXT("Value")
#define SEARCH_COLUMN_DESCRIPTION TEXT("Description")

File diff suppressed because it is too large Load Diff