snes9x/gtk/src/gtk_cheat.cpp
2010-10-30 10:56:44 -05:00

290 lines
7.2 KiB
C++

#include "gtk_s9xcore.h"
#include "gtk_s9x.h"
#include "gtk_cheat.h"
enum
{
COLUMN_ENABLED = 0,
COLUMN_DESCRIPTION = 1,
COLUMN_CHEAT = 2,
NUM_COLS
};
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)
{
GtkWidget *dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s",
error);
gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return;
}
static void
event_add_code (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->add_code ();
}
static void
event_remove_code (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->remove_code ();
}
static void
event_code_toggled (GtkCellRendererToggle *cell_renderer,
gchar *path,
gpointer data)
{
((Snes9xCheats *) data)->toggle_code (path);
return;
}
Snes9xCheats::Snes9xCheats (void)
: GtkBuilderWindow ("cheat_window")
{
GtkTreeView *view;
GtkCellRenderer *renderer;
GtkBuilderWindowCallbacks callbacks[] =
{
{ "add_code", G_CALLBACK (event_add_code) },
{ "remove_code", G_CALLBACK (event_remove_code) },
{ NULL, NULL}
};
view = GTK_TREE_VIEW (get_widget ("cheat_treeview"));
renderer = gtk_cell_renderer_toggle_new ();
gtk_tree_view_insert_column_with_attributes (view,
-1,
"",
renderer,
"active", COLUMN_ENABLED,
NULL);
g_signal_connect (renderer,
"toggled",
G_CALLBACK (event_code_toggled),
(gpointer) this);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (view,
-1,
_("Description"),
renderer,
"text", COLUMN_DESCRIPTION,
NULL);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (view,
-1,
_("Cheat"),
renderer,
"text", COLUMN_CHEAT,
NULL);
store = gtk_list_store_new (NUM_COLS,
G_TYPE_BOOLEAN,
G_TYPE_STRING,
G_TYPE_STRING);
gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
gtk_widget_realize (window);
signal_connect (callbacks);
return;
}
Snes9xCheats::~Snes9xCheats (void)
{
gtk_widget_destroy (window);
g_object_unref (store);
return;
}
void
Snes9xCheats::show (void)
{
top_level->pause_from_focus_change ();
gtk_window_set_transient_for (GTK_WINDOW (window),
top_level->get_window ());
refresh_tree_view ();
gtk_dialog_run (GTK_DIALOG (window));
top_level->unpause_from_focus_change ();
return;
}
int
Snes9xCheats::get_selected_index (void)
{
GtkTreeSelection *selection;
GList *rows;
gint *indices;
int index;
GtkTreeModel *model = GTK_TREE_MODEL (store);
selection =
gtk_tree_view_get_selection (
GTK_TREE_VIEW (get_widget ("cheat_treeview")));
rows = gtk_tree_selection_get_selected_rows (selection,
&model);
if (rows)
{
indices = gtk_tree_path_get_indices ((GtkTreePath *) (rows->data));
index = indices[0];
for (GList *i = rows; i; i = i->next)
gtk_tree_path_free ((GtkTreePath *)(i->data));
g_list_free (rows);
}
else
index = -1;
return index;
}
int
Snes9xCheats::get_index_from_path (const gchar *path)
{
GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
gint *indices = gtk_tree_path_get_indices (tree_path);
int index = indices[0];
gtk_tree_path_free (tree_path);
return index;
}
void
Snes9xCheats::refresh_tree_view (void)
{
GtkTreeIter iter;
char str [1024];
gtk_list_store_clear (store);
for (unsigned int i = 0; i < Cheat.num_cheats; i++)
{
snprintf (str,
1024,
"%06x:%02x/%02x",
Cheat.c [i].address,
Cheat.c [i].byte,
Cheat.c [i].saved_byte);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_DESCRIPTION,
!strcmp (Cheat.c [i].name, "") ? _("No description")
: Cheat.c [i].name,
COLUMN_CHEAT, str,
COLUMN_ENABLED, Cheat.c [i].enabled,
-1);
}
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."));
}
gtk_widget_grab_focus (get_widget ("code_entry"));
refresh_tree_view ();
return;
}
void
Snes9xCheats::remove_code (void)
{
int index = get_selected_index ();
if (index < 0)
return;
S9xDeleteCheat (index);
refresh_tree_view ();
return;
}
void
Snes9xCheats::toggle_code (const gchar *path)
{
int index = get_index_from_path (path);
if (index < 0)
return;
if (Cheat.c[index].enabled)
S9xDisableCheat (index);
else
S9xEnableCheat (index);
refresh_tree_view ();
return;
}