More cheats stuff.

This commit is contained in:
Brandon Wright 2018-04-27 20:35:20 -05:00
parent 5b2a754fb4
commit 4edaba97ca
8 changed files with 236 additions and 31 deletions

View File

@ -269,7 +269,7 @@ void S9xDeleteCheatGroup (uint32 index);
bool8 S9xLoadCheatFile (const char *filename); bool8 S9xLoadCheatFile (const char *filename);
bool8 S9xSaveCheatFile (const char *filename); bool8 S9xSaveCheatFile (const char *filename);
void S9xUpdateCheatsInMemory (void); void S9xUpdateCheatsInMemory (void);
bool8 S9xImportCheatsFromDatabase (const char *filename); int S9xImportCheatsFromDatabase(const char *filename);
void S9xCheatsDisable (void); void S9xCheatsDisable (void);
void S9xCheatsEnable (void); void S9xCheatsEnable (void);
char *S9xCheatValidate (char *cheat); char *S9xCheatValidate (char *cheat);

View File

@ -701,6 +701,32 @@ void S9xUpdateCheatsInMemory (void)
} }
} }
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) static void S9xLoadCheatsFromBMLNode (bml_node *n)
{ {
unsigned int i; unsigned int i;
@ -725,7 +751,7 @@ static void S9xLoadCheatsFromBMLNode (bml_node *n)
if (bml_find_sub(c, "enabled")) if (bml_find_sub(c, "enabled"))
enabled = true; enabled = true;
if (desc && code) if (desc && code && !S9xCheatIsDuplicate (desc, code))
{ {
int index = S9xAddCheatGroup (desc, code); int index = S9xAddCheatGroup (desc, code);
@ -878,7 +904,7 @@ void S9xCheatsEnable (void)
} }
} }
bool8 S9xImportCheatsFromDatabase (const char *filename) int S9xImportCheatsFromDatabase (const char *filename)
{ {
bml_node *bml; bml_node *bml;
char sha256_txt[65]; char sha256_txt[65];
@ -888,7 +914,7 @@ bool8 S9xImportCheatsFromDatabase (const char *filename)
bml = bml_parse_file (filename); bml = bml_parse_file (filename);
if (!bml) if (!bml)
return FALSE; return -1; /* No file */
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
@ -909,7 +935,7 @@ bool8 S9xImportCheatsFromDatabase (const char *filename)
{ {
S9xLoadCheatsFromBMLNode (bml->child[i]); S9xLoadCheatsFromBMLNode (bml->child[i]);
bml_free_node (bml); bml_free_node (bml);
return TRUE; return 0;
} }
} }
} }
@ -917,5 +943,5 @@ bool8 S9xImportCheatsFromDatabase (const char *filename)
bml_free_node (bml); bml_free_node (bml);
return FALSE; return -2; /* No codes */
} }

View File

@ -8,7 +8,7 @@ snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti
endif endif
noinst_LIBRARIES = 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 = \ CLEANFILES = \
src/gtk_snes9x_ui.cpp \ src/gtk_snes9x_ui.cpp \

View File

@ -34,7 +34,10 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE")
AM_GLIB_GNU_GETTEXT AM_GLIB_GNU_GETTEXT
snes9xlocaledir='${prefix}/${DATADIRNAME}/locale' snes9xlocaledir='${prefix}/${DATADIRNAME}/locale'
snes9xdatadir='${prefix}/${DATADIRNAME}/snes9x'
AC_SUBST(snes9xlocaledir) AC_SUBST(snes9xlocaledir)
AC_SUBST(snes9xdatadir)
AC_ARG_WITH(debug, AC_ARG_WITH(debug,
[AS_HELP_STRING([--with(out)-debug], [AS_HELP_STRING([--with(out)-debug],
@ -152,9 +155,9 @@ AC_ARG_WITH(screenshot,
AC_ARG_WITH(gtk3, AC_ARG_WITH(gtk3,
[AS_HELP_STRING([--with(out)-gtk3], [AS_HELP_STRING([--with(out)-gtk3],
[Build with GTK+ 3 if available (default: without)])], [Build with GTK+ 3 if available (default: with)])],
[], [],
[with_gtk3=no]) [with_gtk3=yes])
if test yes = "$with_debug" ; then if test yes = "$with_debug" ; then
CFLAGS="$CFLAGS -g" CFLAGS="$CFLAGS -g"
@ -499,7 +502,7 @@ echo "Snes9x will build with support for the following:"
echo "" echo ""
if test yes = "$GTK3_WARNING" ; then if test yes = "$GTK3_WARNING" ; then
echo " GTK+ 3.0 (experimental)" echo " GTK+ 3.0"
else else
echo " GTK+ 2.0" echo " GTK+ 2.0"
fi fi

View File

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

View File

@ -41,12 +41,37 @@ event_remove_code (GtkButton *button, gpointer data)
((Snes9xCheats *) data)->remove_code (); ((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 static void
event_code_toggled (GtkCellRendererToggle *cell_renderer, event_code_toggled (GtkCellRendererToggle *cell_renderer,
gchar *path, gchar *path,
gpointer data) 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; return;
} }
@ -60,13 +85,17 @@ Snes9xCheats::Snes9xCheats (void)
{ {
{ "add_code", G_CALLBACK (event_add_code) }, { "add_code", G_CALLBACK (event_add_code) },
{ "remove_code", G_CALLBACK (event_remove_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} { NULL, NULL}
}; };
view = GTK_TREE_VIEW (get_widget ("cheat_treeview")); 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 (); 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, gtk_tree_view_insert_column_with_attributes (view,
-1, -1,
"", "",
@ -86,6 +115,8 @@ Snes9xCheats::Snes9xCheats (void)
renderer, renderer,
"text", COLUMN_DESCRIPTION, "text", COLUMN_DESCRIPTION,
NULL); NULL);
GtkTreeViewColumn *column = gtk_tree_view_get_column (view, 1);
gtk_tree_view_column_set_resizable (column, TRUE);
renderer = gtk_cell_renderer_text_new (); renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (view, gtk_tree_view_insert_column_with_attributes (view,
@ -94,6 +125,9 @@ Snes9xCheats::Snes9xCheats (void)
renderer, renderer,
"text", COLUMN_CHEAT, "text", COLUMN_CHEAT,
NULL); NULL);
column = gtk_tree_view_get_column (view, 2);
gtk_tree_view_column_set_resizable (column, TRUE);
store = gtk_list_store_new (NUM_COLS, store = gtk_list_store_new (NUM_COLS,
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
@ -182,14 +216,25 @@ void
Snes9xCheats::refresh_tree_view (void) Snes9xCheats::refresh_tree_view (void)
{ {
GtkTreeIter iter; GtkTreeIter iter;
unsigned int list_size;
gtk_list_store_clear (store); 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);
for (unsigned int i = 0; i < Cheat.g.size (); i++) for (unsigned int i = 0; i < Cheat.g.size (); i++)
{ {
char *str = S9xCheatGroupToText (i); char *str = S9xCheatGroupToText (i);
gtk_list_store_append (store, &iter); if (i > 0)
gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
gtk_list_store_set (store, &iter, gtk_list_store_set (store, &iter,
COLUMN_DESCRIPTION, COLUMN_DESCRIPTION,
!strcmp (Cheat.g [i].name, "") ? _("No description") !strcmp (Cheat.g [i].name, "") ? _("No description")
@ -200,7 +245,6 @@ Snes9xCheats::refresh_tree_view (void)
delete[] str; delete[] str;
} }
return; return;
} }
@ -228,31 +272,127 @@ void
Snes9xCheats::remove_code (void) Snes9xCheats::remove_code (void)
{ {
int index = get_selected_index (); int index = get_selected_index ();
GtkTreeIter iter;
if (index < 0) if (index < 0)
return; return;
S9xDeleteCheatGroup (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; return;
} }
void void
Snes9xCheats::toggle_code (const gchar *path) Snes9xCheats::delete_all_cheats (void)
{ {
int index = get_index_from_path (path); S9xDeleteCheats ();
gtk_list_store_clear (store);
if (index < 0)
return; return;
}
if (Cheat.g[index].enabled)
S9xDisableCheatGroup (index); void
else Snes9xCheats::search_database (void)
S9xEnableCheatGroup (index); {
std::string filename;
refresh_tree_view (); int result;
int reason = 0;
filename = S9xGetFilename ("cheats.bml", CHEAT_DIR);
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 = S9xGetFilename ("cheats.bml", ROM_DIR);
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; return;
} }

View File

@ -15,7 +15,10 @@ class Snes9xCheats : public GtkBuilderWindow
void show (void); void show (void);
void add_code (void); void add_code (void);
void remove_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: private:
void refresh_tree_view (void); void refresh_tree_view (void);

View File

@ -256,8 +256,8 @@
<property name="page_increment">0.10000000000000001</property> <property name="page_increment">0.10000000000000001</property>
</object> </object>
<object class="GtkDialog" id="cheat_window"> <object class="GtkDialog" id="cheat_window">
<property name="width_request">512</property> <property name="width_request">720</property>
<property name="height_request">350</property> <property name="height_request">480</property>
<property name="can_focus">False</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="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> <property name="border_width">5</property>
@ -438,6 +438,36 @@
<property name="position">5</property> <property name="position">5</property>
</packing> </packing>
</child> </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> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>