2010-09-25 17:46:12 +02:00
|
|
|
#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
|
|
|
|
display_errorbox (const char *error)
|
|
|
|
{
|
|
|
|
GtkWidget *dialog = gtk_message_dialog_new (NULL,
|
|
|
|
GTK_DIALOG_MODAL,
|
|
|
|
GTK_MESSAGE_ERROR,
|
|
|
|
GTK_BUTTONS_OK,
|
|
|
|
"%s",
|
|
|
|
error);
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
|
2010-09-25 17:46:12 +02:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
static void
|
|
|
|
event_code_toggled (GtkCellRendererToggle *cell_renderer,
|
|
|
|
gchar *path,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2018-04-28 03:35:20 +02:00
|
|
|
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);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Snes9xCheats::Snes9xCheats (void)
|
2010-09-26 11:19:15 +02:00
|
|
|
: GtkBuilderWindow ("cheat_window")
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
GtkTreeView *view;
|
|
|
|
GtkCellRenderer *renderer;
|
2010-09-26 11:19:15 +02:00
|
|
|
GtkBuilderWindowCallbacks callbacks[] =
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
{ "add_code", G_CALLBACK (event_add_code) },
|
|
|
|
{ "remove_code", G_CALLBACK (event_remove_code) },
|
2018-04-28 03:35:20 +02:00
|
|
|
{ "search_database", G_CALLBACK (event_search_database) },
|
|
|
|
{ "delete_all_cheats", G_CALLBACK (event_delete_all_cheats) },
|
2010-09-25 17:46:12 +02:00
|
|
|
{ NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
view = GTK_TREE_VIEW (get_widget ("cheat_treeview"));
|
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
g_signal_connect (view, "row-activated", G_CALLBACK (event_row_activated), (gpointer) this);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
renderer = gtk_cell_renderer_toggle_new ();
|
2018-04-28 03:35:20 +02:00
|
|
|
gtk_cell_renderer_toggle_set_activatable (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
|
2010-09-25 17:46:12 +02:00
|
|
|
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);
|
2018-04-28 03:35:20 +02:00
|
|
|
GtkTreeViewColumn *column = gtk_tree_view_get_column (view, 1);
|
|
|
|
gtk_tree_view_column_set_resizable (column, TRUE);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
|
|
gtk_tree_view_insert_column_with_attributes (view,
|
|
|
|
-1,
|
|
|
|
_("Cheat"),
|
|
|
|
renderer,
|
|
|
|
"text", COLUMN_CHEAT,
|
|
|
|
NULL);
|
2018-04-28 03:35:20 +02:00
|
|
|
column = gtk_tree_view_get_column (view, 2);
|
|
|
|
gtk_tree_view_column_set_resizable (column, TRUE);
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
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;
|
2018-04-28 03:35:20 +02:00
|
|
|
unsigned int list_size;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
list_size = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL);
|
|
|
|
|
|
|
|
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);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-04-26 02:29:26 +02:00
|
|
|
for (unsigned int i = 0; i < Cheat.g.size (); i++)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2018-04-26 02:29:26 +02:00
|
|
|
char *str = S9xCheatGroupToText (i);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
if (i > 0)
|
|
|
|
gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
gtk_list_store_set (store, &iter,
|
|
|
|
COLUMN_DESCRIPTION,
|
2018-04-26 02:29:26 +02:00
|
|
|
!strcmp (Cheat.g [i].name, "") ? _("No description")
|
|
|
|
: Cheat.g [i].name,
|
2010-09-25 17:46:12 +02:00
|
|
|
COLUMN_CHEAT, str,
|
2018-04-26 02:29:26 +02:00
|
|
|
COLUMN_ENABLED, Cheat.g [i].enabled,
|
2010-09-25 17:46:12 +02:00
|
|
|
-1);
|
2018-04-26 02:29:26 +02:00
|
|
|
delete[] str;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xCheats::add_code (void)
|
|
|
|
{
|
2010-10-30 17:56:44 +02:00
|
|
|
const char *description;
|
2010-09-25 17:46:12 +02:00
|
|
|
const gchar *code = get_entry_text ("code_entry");
|
|
|
|
|
2010-10-30 17:56:44 +02:00
|
|
|
description = get_entry_text ("description_entry");
|
|
|
|
if (description[0] == '\0')
|
|
|
|
description = _("No description");
|
|
|
|
|
2018-04-26 02:29:26 +02:00
|
|
|
if (S9xAddCheatGroup (description, code) < 0)
|
|
|
|
display_errorbox (_("Couldn't find any cheat codes in input."));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
gtk_widget_grab_focus (get_widget ("code_entry"));
|
|
|
|
|
|
|
|
refresh_tree_view ();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xCheats::remove_code (void)
|
|
|
|
{
|
|
|
|
int index = get_selected_index ();
|
2018-04-28 03:35:20 +02:00
|
|
|
GtkTreeIter iter;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
if (index < 0)
|
|
|
|
return;
|
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, NULL, index);
|
|
|
|
gtk_list_store_remove (store, &iter);
|
|
|
|
|
2018-04-26 02:29:26 +02:00
|
|
|
S9xDeleteCheatGroup (index);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Snes9xCheats::delete_all_cheats (void)
|
|
|
|
{
|
|
|
|
S9xDeleteCheats ();
|
|
|
|
gtk_list_store_clear (store);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-04-28 03:35:20 +02:00
|
|
|
Snes9xCheats::search_database (void)
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2018-04-28 03:35:20 +02:00
|
|
|
std::string filename;
|
|
|
|
int result;
|
|
|
|
int reason = 0;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-05-02 01:00:39 +02:00
|
|
|
filename = S9xGetDirectory (CHEAT_DIR);
|
|
|
|
filename += "/cheats.bml";
|
2018-04-28 03:35:20 +02:00
|
|
|
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ())))
|
|
|
|
{
|
|
|
|
refresh_tree_view ();
|
2010-09-25 17:46:12 +02:00
|
|
|
return;
|
2018-04-28 03:35:20 +02:00
|
|
|
}
|
2010-09-25 17:46:12 +02:00
|
|
|
|
2018-04-28 03:35:20 +02:00
|
|
|
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;
|
|
|
|
|
2018-05-02 01:00:39 +02:00
|
|
|
filename = S9xGetDirectory (ROM_DIR);
|
|
|
|
filename += "/cheats.bml";
|
2018-04-28 03:35:20 +02:00
|
|
|
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)
|
2018-04-26 02:29:26 +02:00
|
|
|
S9xEnableCheatGroup (index);
|
2018-04-28 03:35:20 +02:00
|
|
|
else
|
|
|
|
S9xDisableCheatGroup (index);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|