Skip to content

Commit

Permalink
Get initial cheat support down.
Browse files Browse the repository at this point in the history
  • Loading branch information
Themaister committed Apr 17, 2011
1 parent 1005d7f commit 092fa9d
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ ifeq ($(HAVE_CG), 1)
endif

ifeq ($(HAVE_XML), 1)
OBJ += gfx/shader_glsl.o sha256.o
OBJ += gfx/shader_glsl.o sha256.o cheats.o
LIBS += $(XML_LIBS)
DEFINES += $(XML_CFLAGS)
endif
Expand Down
2 changes: 1 addition & 1 deletion Makefile.win32
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ ifeq ($(HAVE_RSOUND), 1)
endif

ifeq ($(HAVE_XML), 1)
OBJ += gfx/shader_glsl.o sha256.o
OBJ += gfx/shader_glsl.o sha256.o cheats.o
DEFINES += $(XML_CFLAGS) -DHAVE_XML
LIBS += -lxml2
endif
Expand Down
163 changes: 163 additions & 0 deletions cheats.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/

#include "cheats.h"
#include "sha256.h"
#include "dynamic.h"
#include "general.h"

#include <stdlib.h>
#include <stddef.h>
#include <string.h>

#include <libxml/parser.h>
#include <libxml/tree.h>

struct cheat
{
char *desc;
bool state;
char *code;
};

struct cheat_manager
{
struct cheat *cheats;
unsigned ptr;
unsigned size;
};

static void xml_grab_cheats(cheat_manager_t *handle, xmlNodePtr ptr)
{
xmlNodePtr node = NULL;
for (node = ptr; node; node = node->next)
{
if (strcmp((const char*)node->name, "name") == 0)
{
xmlChar *name = xmlNodeGetContent(node);
if (name)
{
SSNES_LOG("Found cheat for game: \"%s\"\n", name);
xmlFree(name);
}
}
}
}

cheat_manager_t* cheat_manager_new(const char *path)
{
psnes_cheat_reset();

cheat_manager_t *handle = calloc(1, sizeof(handle));
if (!handle)
return NULL;

xmlParserCtxtPtr ctx = NULL;
xmlDocPtr doc = NULL;

ctx = xmlNewParserCtxt();
if (!ctx)
goto error;

doc = xmlCtxtReadFile(ctx, path, NULL, 0);
if (!doc)
{
SSNES_ERR("Failed to parse XML file: %s\n", path);
goto error;
}

if (ctx->valid == 0)
{
SSNES_ERR("Cannot validate XML file: %s\n", path);
goto error;
}

xmlNodePtr head = xmlDocGetRootElement(doc);
xmlNodePtr cur = NULL;
for (cur = head; cur; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && strcmp((const char*)cur->name, "database") == 0)
break;
}

if (!cur)
goto error;

for (cur = cur->children; cur; cur = cur->next)
{
if (cur->type != XML_ELEMENT_NODE)
continue;

if (strcmp((const char*)cur->name, "cartridge") == 0)
{
xmlChar *sha256 = xmlGetProp(cur, (const xmlChar*)"sha256");
if (!sha256)
continue;

if (memcmp(sha256, g_extern.sha256, 64) == 0)
{
xmlFree(sha256);
break;
}

xmlFree(sha256);
}
}

if (!cur)
goto error;

xml_grab_cheats(handle, cur->children);

xmlFreeDoc(doc);
xmlFreeParserCtxt(ctx);
return handle;

error:
cheat_manager_free(handle);
if (doc)
xmlFreeDoc(doc);
if (ctx)
xmlFreeParserCtxt(ctx);
return NULL;
}

void cheat_manager_free(cheat_manager_t *handle)
{
if (!handle)
return;

if (handle->cheats)
{
for (unsigned i = 0; i < handle->size; i++)
{
xmlFree(handle->cheats[i].desc);
xmlFree(handle->cheats[i].code);
}

free(handle->cheats);
}

free(handle);
}

void cheat_manager_toggle(cheat_manager_t *handle)
{
handle->cheats[handle->ptr].state ^= true;
psnes_cheat_set(handle->ptr, handle->cheats[handle->ptr].state, handle->cheats[handle->ptr].code);
}

29 changes: 29 additions & 0 deletions cheats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __SSNES_CHEATS_H
#define __SSNES_CHEATS_H

typedef struct cheat_manager cheat_manager_t;

cheat_manager_t* cheat_manager_new(const char *path);
void cheat_manager_free(cheat_manager_t *handle);

void cheat_manager_index_offset(cheat_manager_t *handle, int offset);
void cheat_manager_toggle(cheat_manager_t *handle);

#endif
3 changes: 3 additions & 0 deletions driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ enum
SSNES_RESET,
SSNES_SHADER_NEXT,
SSNES_SHADER_PREV,
SSNES_CHEAT_INDEX_PLUS,
SSNES_CHEAT_INDEX_MINUS,
SSNES_CHEAT_TOGGLE
};


Expand Down
7 changes: 7 additions & 0 deletions dynamic.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ void (*psnes_set_input_state)(snes_input_state_t);
void (*psnes_reset)(void);
void (*psnes_run)(void);

void (*psnes_cheat_reset)(void);
void (*psnes_cheat_set)(unsigned, bool, const char*);

const char *(*psnes_library_id)(void) = NULL;
unsigned (*psnes_library_revision_minor)(void);
unsigned (*psnes_library_revision_major)(void);
Expand Down Expand Up @@ -111,6 +114,8 @@ static void load_dynamic(void)
OPT_SYM(snes_library_id);
SYM(snes_library_revision_minor);
SYM(snes_library_revision_major);
SYM(snes_cheat_reset);
SYM(snes_cheat_set);
SYM(snes_reset);
SYM(snes_run);
SYM(snes_get_region);
Expand Down Expand Up @@ -145,6 +150,8 @@ static void set_statics(void)
SSYM(snes_set_input_state);
SSYM(snes_library_revision_minor);
SSYM(snes_library_revision_major);
SSYM(snes_cheat_reset);
SSYM(snes_cheat_set);
SSYM(snes_reset);
SSYM(snes_run);
SSYM(snes_get_region);
Expand Down
3 changes: 3 additions & 0 deletions dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ extern void (*psnes_set_audio_sample)(snes_audio_sample_t);
extern void (*psnes_set_input_poll)(snes_input_poll_t);
extern void (*psnes_set_input_state)(snes_input_state_t);

extern void (*psnes_cheat_reset)(void);
extern void (*psnes_cheat_set)(unsigned, bool, const char*);

extern const char* (*psnes_library_id)(void);
extern unsigned (*psnes_library_revision_minor)(void);
extern unsigned (*psnes_library_revision_major)(void);
Expand Down
8 changes: 7 additions & 1 deletion general.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "autosave.h"
#include "netplay.h"
#include "dynamic.h"
#include "cheats.h"

#ifdef HAVE_CONFIG_H
#include "config.h"
Expand All @@ -42,7 +43,7 @@


#define MAX_PLAYERS 5
#define MAX_BINDS 28 // Needs to be increased every time there are new binds added.
#define MAX_BINDS 31 // Needs to be increased every time there are new binds added.
#define SSNES_NO_JOYPAD 0xFFFF

enum ssnes_shader_type
Expand Down Expand Up @@ -110,6 +111,7 @@ struct settings
} input;

char libsnes[256];
char cheat_database[256];

bool rewind_enable;
unsigned rewind_buffer_size;
Expand Down Expand Up @@ -245,6 +247,10 @@ struct global
} shader_dir;

char sha256[65];

#ifdef HAVE_XML
cheat_manager_t *cheat;
#endif
};

void parse_config(void);
Expand Down
17 changes: 17 additions & 0 deletions settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ static void parse_config_file(void)
CONFIG_GET_BOOL(pause_nonactive, "pause_nonactive");
CONFIG_GET_INT(autosave_interval, "autosave_interval");

CONFIG_GET_STRING(cheat_database, "cheat_database_path");

read_keybinds(conf);

config_file_free(conf);
Expand Down Expand Up @@ -414,6 +416,9 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = {
DECLARE_BIND(reset, SSNES_RESET)
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
},
{
DECLARE_BIND(player2_a, SNES_DEVICE_ID_JOYPAD_A)
Expand Down Expand Up @@ -443,6 +448,9 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = {
DECLARE_BIND(reset, SSNES_RESET)
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
},
{
DECLARE_BIND(player3_a, SNES_DEVICE_ID_JOYPAD_A)
Expand Down Expand Up @@ -472,6 +480,9 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = {
DECLARE_BIND(reset, SSNES_RESET)
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
},
{
DECLARE_BIND(player4_a, SNES_DEVICE_ID_JOYPAD_A)
Expand Down Expand Up @@ -501,6 +512,9 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = {
DECLARE_BIND(reset, SSNES_RESET)
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
},
{
DECLARE_BIND(player5_a, SNES_DEVICE_ID_JOYPAD_A)
Expand Down Expand Up @@ -530,6 +544,9 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = {
DECLARE_BIND(reset, SSNES_RESET)
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
},
};

Expand Down
Loading

0 comments on commit 092fa9d

Please sign in to comment.