From ef79bbde537d6b9c745a7d86cb9df1d04c35590d Mon Sep 17 00:00:00 2001 From: PCSX* teams Date: Tue, 16 Nov 2010 14:15:22 +0200 Subject: pcsxr-1.9.92 --- gui/Cheat.c | 1176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1176 insertions(+) create mode 100644 gui/Cheat.c (limited to 'gui/Cheat.c') diff --git a/gui/Cheat.c b/gui/Cheat.c new file mode 100644 index 0000000..4047e2f --- /dev/null +++ b/gui/Cheat.c @@ -0,0 +1,1176 @@ +/* Cheat Support for PCSX-Reloaded + * Copyright (C) 2009, Wei Mingzhi . + * + * This program 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 Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "Linux.h" + +#include "../libpcsxcore/cheat.h" +#include "../libpcsxcore/psxmem.h" + +GtkWidget *CheatListDlg = NULL; +GtkWidget *CheatSearchDlg = NULL; + +static void LoadCheatListItems(int index) { + GtkListStore *store = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING); + GtkTreeIter iter; + GtkWidget *widget; + GladeXML *xml; + + int i; + + xml = glade_get_widget_tree(CheatListDlg); + widget = glade_xml_get_widget(xml, "GtkCList_Cheat"); + + for (i = 0; i < NumCheats; i++) { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, Cheats[i].Enabled, 1, Cheats[i].Descr, -1); + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE); + gtk_widget_show(widget); + + if (index >= NumCheats) { + index = NumCheats - 1; + } + + if (index >= 0) { + GtkTreePath *path; + GtkTreeSelection *sel; + + path = gtk_tree_path_new_from_indices(index, -1); + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + + gtk_tree_selection_select_path(sel, path); + gtk_tree_path_free(path); + } +} + +static void CheatList_TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { + GladeXML *xml; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + gboolean selected; + int i; + + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + + if (selected) { + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + gtk_tree_path_free(path); + + // If a row was selected, and the row is not blank, we can now enable + // some of the disabled widgets + xml = glade_get_widget_tree(CheatListDlg); + + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "delbutton1")), TRUE); + } else { + xml = glade_get_widget_tree(CheatListDlg); + + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "delbutton1")), FALSE); + } + + gtk_widget_set_sensitive (GTK_WIDGET(glade_xml_get_widget(xml, "savebutton1")), NumCheats); +} + +static void OnCheatListDlg_AddClicked(GtkWidget *widget, gpointer user_data) { + GtkWidget *dlg; + GtkWidget *box, *scroll, *label, *descr_edit, *code_edit; + + dlg = gtk_dialog_new_with_buttons(_("Add New Cheat"), GTK_WINDOW(CheatListDlg), + GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); + + gtk_window_set_default_size(GTK_WINDOW(dlg), 350, 350); + + box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox); + + label = gtk_label_new(_("Cheat Description:")); + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + descr_edit = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(box), descr_edit, FALSE, FALSE, 5); + gtk_widget_show(descr_edit); + + label = gtk_label_new(_("Cheat Code:")); + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + code_edit = gtk_text_view_new(); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(code_edit), GTK_WRAP_CHAR); + + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), code_edit); + gtk_widget_show(code_edit); + + gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 5); + gtk_widget_show(scroll); + + gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER); + + gtk_widget_show_all(dlg); + + if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) { + GtkTextBuffer *b = gtk_text_view_get_buffer(GTK_TEXT_VIEW(code_edit)); + GtkTextIter s, e; + char *codetext; + + gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(b), &s, &e); + codetext = strdup(gtk_text_buffer_get_text(GTK_TEXT_BUFFER(b), &s, &e, FALSE)); + + if (AddCheat(gtk_entry_get_text(GTK_ENTRY(descr_edit)), codetext) != 0) { + SysErrorMessage(_("Error"), _("Invalid cheat code!")); + } + + LoadCheatListItems(NumCheats - 1); + + free(codetext); + } + + gtk_widget_destroy(dlg); +} + +static void OnCheatListDlg_EditClicked(GtkWidget *widget, gpointer user_data) { + GtkWidget *dlg; + GtkWidget *box, *scroll, *label, *descr_edit, *code_edit; + GladeXML *xml; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + gboolean selected; + int index, i; + char buf[8192]; + char *p = buf; + + xml = glade_get_widget_tree(CheatListDlg); + widget = glade_xml_get_widget(xml, "GtkCList_Cheat"); + + selected = gtk_tree_selection_get_selected( + gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), + &model, &iter); + + if (!selected) { + return; + } + + path = gtk_tree_model_get_path(model, &iter); + index = *gtk_tree_path_get_indices(path); + gtk_tree_path_free(path); + + dlg = gtk_dialog_new_with_buttons(_("Edit Cheat"), GTK_WINDOW(CheatListDlg), + GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); + + gtk_window_set_default_size(GTK_WINDOW(dlg), 350, 350); + + box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox); + + label = gtk_label_new(_("Cheat Description:")); + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + descr_edit = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(descr_edit), Cheats[index].Descr); + gtk_box_pack_start(GTK_BOX(box), descr_edit, FALSE, FALSE, 5); + gtk_widget_show(descr_edit); + + label = gtk_label_new(_("Cheat Code:")); + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + code_edit = gtk_text_view_new(); + + for (i = Cheats[index].First; i < Cheats[index].First + Cheats[index].n; i++) { + sprintf(p, "%.8X %.4X\n", CheatCodes[i].Addr, CheatCodes[i].Val); + p += 14; + *p = '\0'; + } + + gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(code_edit)), + buf, -1); + + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(code_edit), GTK_WRAP_CHAR); + + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), code_edit); + gtk_widget_show(code_edit); + + gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 5); + gtk_widget_show(scroll); + + gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER); + + gtk_widget_show_all(dlg); + + if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) { + GtkTextBuffer *b = gtk_text_view_get_buffer(GTK_TEXT_VIEW(code_edit)); + GtkTextIter s, e; + char *codetext; + + gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(b), &s, &e); + codetext = strdup(gtk_text_buffer_get_text(GTK_TEXT_BUFFER(b), &s, &e, FALSE)); + + if (EditCheat(index, gtk_entry_get_text(GTK_ENTRY(descr_edit)), codetext) != 0) { + SysErrorMessage(_("Error"), _("Invalid cheat code!")); + } + + LoadCheatListItems(index); + + free(codetext); + } + + gtk_widget_destroy(dlg); +} + +static void OnCheatListDlg_DelClicked(GtkWidget *widget, gpointer user_data) { + GladeXML *xml; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + + gboolean selected; + int i = -1; + + xml = glade_get_widget_tree(CheatListDlg); + widget = glade_xml_get_widget(xml, "GtkCList_Cheat"); + + selected = gtk_tree_selection_get_selected( + gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)), + &model, &iter); + + if (selected) { + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + gtk_tree_path_free(path); + + RemoveCheat(i); + } + + LoadCheatListItems(i); // FIXME: should remove it from the list directly + // rather than regenerating the whole list +} + +static void OnCheatListDlg_EnableToggled(GtkWidget *widget, gchar *path, gpointer user_data) { + int i = atoi(path); + + assert(i >= 0 && i < NumCheats); + Cheats[i].Enabled ^= 1; + + LoadCheatListItems(i); // FIXME: should modify it in the list directly + // rather than regenerating the whole list +} + +static void OnCheatListDlg_OpenClicked(GtkWidget *widget, gpointer user_data) { + GtkWidget *chooser; + gchar *filename; + + GtkFileFilter *filter; + + chooser = gtk_file_chooser_dialog_new (_("Open Cheat File"), + NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + + filename = g_build_filename(getenv("HOME"), CHEATS_DIR, NULL); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), filename); + g_free(filename); + + filter = gtk_file_filter_new (); + gtk_file_filter_add_pattern (filter, "*.cht"); + gtk_file_filter_set_name (filter, _("PCSX Cheat Code Files (*.cht)")); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter); + + if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); + gtk_widget_destroy (GTK_WIDGET (chooser)); + while (gtk_events_pending()) gtk_main_iteration(); + } else { + gtk_widget_destroy (GTK_WIDGET (chooser)); + while (gtk_events_pending()) gtk_main_iteration(); + return; + } + + LoadCheats(filename); + + g_free(filename); + + LoadCheatListItems(-1); +} + +static void OnCheatListDlg_SaveClicked(GtkWidget *widget, gpointer user_data) { + GtkWidget *chooser; + gchar *filename; + GtkFileFilter *filter; + + chooser = gtk_file_chooser_dialog_new(_("Save Cheat File"), + NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + + filename = g_build_filename(getenv("HOME"), CHEATS_DIR, NULL); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), filename); + g_free(filename); + + filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, "*.cht"); + gtk_file_filter_set_name(filter, _("PCSX Cheat Code Files (*.cht)")); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter); + + filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, "*"); + gtk_file_filter_set_name(filter, _("All Files (*.*)")); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter); + + if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); + gtk_widget_destroy (GTK_WIDGET(chooser)); + while (gtk_events_pending()) gtk_main_iteration(); + } else { + gtk_widget_destroy (GTK_WIDGET(chooser)); + while (gtk_events_pending()) gtk_main_iteration(); + return; + } + + SaveCheats(filename); + + g_free(filename); +} + +static void OnCheatListDlg_CloseClicked() { + gtk_widget_destroy(CheatListDlg); + CheatListDlg = NULL; +} + +// run the cheat list dialog +void RunCheatListDialog() { + GladeXML *xml; + GtkWidget *widget; + GtkTreeSelection *treesel; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "CheatListDlg", NULL); + if (!xml) { + g_warning(_("Error: Glade interface could not be loaded!")); + return; + } + + CheatListDlg = glade_xml_get_widget(xml, "CheatListDlg"); + gtk_window_set_title(GTK_WINDOW(CheatListDlg), _("Cheat Codes")); + + widget = glade_xml_get_widget(xml, "GtkCList_Cheat"); + + // column for enable + renderer = gtk_cell_renderer_toggle_new(); + column = gtk_tree_view_column_new_with_attributes(_("Enable"), + renderer, "active", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(OnCheatListDlg_EnableToggled), 0); + + // column for description + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Description"), + renderer, "text", 1, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + LoadCheatListItems(-1); + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + g_signal_connect_data(G_OBJECT (treesel), "changed", + G_CALLBACK (CheatList_TreeSelectionChanged), + NULL, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "addbutton1"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatListDlg_AddClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "editbutton1"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatListDlg_EditClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "delbutton1"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatListDlg_DelClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "loadbutton1"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatListDlg_OpenClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "savebutton1"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatListDlg_SaveClicked), xml, NULL, G_CONNECT_AFTER); + + // Setup a handler for when Close or Cancel is clicked + g_signal_connect_data(GTK_OBJECT(CheatListDlg), "response", + GTK_SIGNAL_FUNC(OnCheatListDlg_CloseClicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER); + + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "savebutton1")), NumCheats); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "delbutton1")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), FALSE); +} + +/////////////////////////////////////////////////////////////////////////////// + +#define SEARCH_EQUALVAL 0 +#define SEARCH_NOTEQUALVAL 1 +#define SEARCH_RANGE 2 +#define SEARCH_INCBY 3 +#define SEARCH_DECBY 4 +#define SEARCH_INC 5 +#define SEARCH_DEC 6 +#define SEARCH_DIFFERENT 7 +#define SEARCH_NOCHANGE 8 + +#define SEARCHTYPE_8BIT 0 +#define SEARCHTYPE_16BIT 1 +#define SEARCHTYPE_32BIT 2 + +#define SEARCHBASE_DEC 0 +#define SEARCHBASE_HEX 1 + +static char current_search = SEARCH_EQUALVAL; +static char current_searchtype = SEARCHTYPE_8BIT; +static char current_searchbase = SEARCHBASE_DEC; +static uint32_t current_valuefrom = 0; +static uint32_t current_valueto = 0; + +// update the cheat search dialog +static void UpdateCheatSearchDialog() { + GladeXML *xml; + char buf[256]; + int i; + u32 addr; + GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING); + GtkTreeIter iter; + GtkWidget *widget; + + xml = glade_get_widget_tree(CheatSearchDlg); + widget = glade_xml_get_widget(xml, "GtkCList_Result"); + + gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_searchfor")), current_search); + gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_datatype")), current_searchtype); + gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_database")), current_searchbase); + + if (current_searchbase == SEARCHBASE_DEC) { + sprintf(buf, "%u", current_valuefrom); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf); + sprintf(buf, "%u", current_valueto); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf); + } + else { + sprintf(buf, "%X", current_valuefrom); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf); + sprintf(buf, "%X", current_valueto); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf); + } + + if (current_search == SEARCH_RANGE) { + gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto"))); + gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto"))); + } + else { + gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto"))); + gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto"))); + } + + if (current_search >= SEARCH_INC) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), FALSE); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), TRUE); + } + + if (current_search >= SEARCH_INCBY && prevM == NULL) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), FALSE); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), TRUE); + } + + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_freeze")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_modify")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_copy")), FALSE); + + if (prevM != NULL) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "combo_datatype")), FALSE); + + if (NumSearchResults > 100) { + // too many results to be shown + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, _("Too many addresses found."), -1); + gtk_widget_set_sensitive(widget, FALSE); + } + else { + for (i = 0; i < NumSearchResults; i++) { + addr = SearchResults[i]; + + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + sprintf(buf, _("%.8X Current: %u (%.2X), Previous: %u (%.2X)"), + addr, PSXMu8(addr), PSXMu8(addr), PrevMu8(addr), PrevMu8(addr)); + break; + + case SEARCHTYPE_16BIT: + sprintf(buf, _("%.8X Current: %u (%.4X), Previous: %u (%.4X)"), + addr, PSXMu16(addr), PSXMu16(addr), PrevMu16(addr), PrevMu16(addr)); + break; + + case SEARCHTYPE_32BIT: + sprintf(buf, _("%.8X Current: %u (%.8X), Previous: %u (%.8X)"), + addr, PSXMu32(addr), PSXMu32(addr), PrevMu32(addr), PrevMu32(addr)); + break; + + default: + assert(FALSE); // impossible + break; + } + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, buf, -1); + } + gtk_widget_set_sensitive(widget, TRUE); + } + + sprintf(buf, _("Founded Addresses: %d"), NumSearchResults); + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "label_resultsfound")), buf); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "combo_datatype")), TRUE); + gtk_widget_set_sensitive(widget, FALSE); + + gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "label_resultsfound")), + _("Enter the values and start your search.")); + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store)); + g_object_unref(G_OBJECT(store)); + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE); + gtk_widget_show(widget); +} + +// get the current selected result index in the list +static int GetSelectedResultIndex() { + GladeXML *xml; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + gboolean selected; + int i; + + xml = glade_get_widget_tree(CheatSearchDlg); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(xml, "GtkCList_Result"))); + selected = gtk_tree_selection_get_selected(selection, &model, &iter); + + if (!selected) { + return -1; + } + + path = gtk_tree_model_get_path(model, &iter); + i = *gtk_tree_path_get_indices(path); + gtk_tree_path_free(path); + + assert(i < NumSearchResults); + return i; +} + +// add cheat code to freeze the value +static void OnCheatSearchDlg_FreezeClicked(GtkWidget *widget, gpointer user_data) { + GtkWidget *dlg; + GtkWidget *box, *hbox, *label, *descr_edit, *value_edit; + char buf[256]; + u32 addr, val = 0; + + addr = SearchResults[GetSelectedResultIndex()]; + + dlg = gtk_dialog_new_with_buttons(_("Freeze value"), GTK_WINDOW(CheatListDlg), + GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); + + box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox); + + label = gtk_label_new(_("Description:")); + gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + descr_edit = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(box), descr_edit, FALSE, FALSE, 10); + gtk_widget_show(descr_edit); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 15); + + label = gtk_label_new(_("Value:")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + value_edit = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), value_edit, FALSE, FALSE, 10); + gtk_widget_show(value_edit); + + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + val = PSXMu8(addr); + break; + + case SEARCHTYPE_16BIT: + val = PSXMu16(addr); + break; + + case SEARCHTYPE_32BIT: + val = PSXMu32(addr); + break; + + default: + assert(FALSE); // should not reach here + break; + } + + sprintf(buf, "%u", val); + gtk_entry_set_text(GTK_ENTRY(value_edit), buf); + + sprintf(buf, "%.8X", addr); + gtk_entry_set_text(GTK_ENTRY(descr_edit), buf); + + gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER); + gtk_widget_show_all(dlg); + + if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) { + val = 0; + sscanf(gtk_entry_get_text(GTK_ENTRY(value_edit)), "%u", &val); + + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + if (val > (u32)0xFF) { + val = 0xFF; + } + sprintf(buf, "%.8X %.4X", (addr & 0x1FFFFF) | (CHEAT_CONST8 << 24), val); + break; + + case SEARCHTYPE_16BIT: + if (val > (u32)0xFFFF) { + val = 0xFFFF; + } + sprintf(buf, "%.8X %.4X", (addr & 0x1FFFFF) | (CHEAT_CONST16 << 24), val); + break; + + case SEARCHTYPE_32BIT: + sprintf(buf, "%.8X %.4X\n%.8X %.4X", + (addr & 0x1FFFFF) | (CHEAT_CONST16 << 24), val & 0xFFFF, + ((addr + 2) & 0x1FFFFF) | (CHEAT_CONST16 << 24), ((val & 0xFFFF0000) >> 16) & 0xFFFF); + break; + + default: + assert(FALSE); // should not reach here + break; + } + + if (AddCheat(gtk_entry_get_text(GTK_ENTRY(descr_edit)), buf) == 0) { + Cheats[NumCheats - 1].Enabled = 1; + } + } + + gtk_widget_destroy(dlg); +} + +// modify the value on the fly +static void OnCheatSearchDlg_ModifyClicked(GtkWidget *widget, gpointer user_data) { + GtkWidget *dlg; + GtkWidget *box, *hbox, *label, *value_edit; + char buf[256]; + u32 addr, val = 0; + + addr = SearchResults[GetSelectedResultIndex()]; + + dlg = gtk_dialog_new_with_buttons(_("Modify value"), GTK_WINDOW(CheatListDlg), + GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); + + box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox); + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 5); + + label = gtk_label_new(_("New value:")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); + gtk_widget_show(label); + + value_edit = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), value_edit, FALSE, FALSE, 10); + gtk_widget_show(value_edit); + + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + val = PSXMu8(addr); + break; + + case SEARCHTYPE_16BIT: + val = PSXMu16(addr); + break; + + case SEARCHTYPE_32BIT: + val = PSXMu32(addr); + break; + + default: + assert(FALSE); // should not reach here + break; + } + + sprintf(buf, "%u", val); + gtk_entry_set_text(GTK_ENTRY(value_edit), buf); + + gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER); + gtk_widget_show_all(dlg); + + if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) { + val = 0; + sscanf(gtk_entry_get_text(GTK_ENTRY(value_edit)), "%u", &val); + + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + if (val > 0xFF) { + val = 0xFF; + } + psxMemWrite8(addr, (u8)val); + break; + + case SEARCHTYPE_16BIT: + if (val > 0xFFFF) { + val = 0xFFFF; + } + psxMemWrite16(addr, (u16)val); + break; + + case SEARCHTYPE_32BIT: + psxMemWrite32(addr, (u32)val); + break; + + default: + assert(FALSE); // should not reach here + break; + } + + UpdateCheatSearchDialog(); + } + + gtk_widget_destroy(dlg); +} + +// copy the selected address to clipboard +static void OnCheatSearchDlg_CopyClicked(GtkWidget *widget, gpointer user_data) { + int i; + char buf[9]; + + i = GetSelectedResultIndex(); + assert(i != -1); + + sprintf(buf, "%8X", SearchResults[i]); + buf[8] = '\0'; + + gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buf, 8); +} + +// preform the search +static void OnCheatSearchDlg_SearchClicked(GtkWidget *widget, gpointer user_data) { + GladeXML *xml; + + xml = glade_get_widget_tree(CheatSearchDlg); + + current_search = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_searchfor"))); + current_searchtype = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_datatype"))); + current_searchbase = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_database"))); + current_valuefrom = 0; + current_valueto = 0; + + if (current_searchbase == SEARCHBASE_DEC) { + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%u", ¤t_valuefrom); + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%u", ¤t_valueto); + } + else { + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%x", ¤t_valuefrom); + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%x", ¤t_valueto); + } + + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + if (current_valuefrom > (u32)0xFF) { + current_valuefrom = 0xFF; + } + if (current_valueto > (u32)0xFF) { + current_valueto = 0xFF; + } + break; + + case SEARCHTYPE_16BIT: + if (current_valuefrom > (u32)0xFFFF) { + current_valuefrom = 0xFFFF; + } + if (current_valueto > (u32)0xFFFF) { + current_valueto = 0xFFFF; + } + break; + } + + if (current_search == SEARCH_RANGE && current_valuefrom > current_valueto) { + u32 t = current_valuefrom; + current_valuefrom = current_valueto; + current_valueto = t; + } + + switch (current_search) { + case SEARCH_EQUALVAL: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchEqual8((u8)current_valuefrom); + break; + + case SEARCHTYPE_16BIT: + CheatSearchEqual16((u16)current_valuefrom); + break; + + case SEARCHTYPE_32BIT: + CheatSearchEqual32((u32)current_valuefrom); + break; + } + break; + + case SEARCH_NOTEQUALVAL: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchNotEqual8((u8)current_valuefrom); + break; + + case SEARCHTYPE_16BIT: + CheatSearchNotEqual16((u16)current_valuefrom); + break; + + case SEARCHTYPE_32BIT: + CheatSearchNotEqual32((u32)current_valuefrom); + break; + } + break; + + case SEARCH_RANGE: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchRange8((u8)current_valuefrom, (u8)current_valueto); + break; + + case SEARCHTYPE_16BIT: + CheatSearchRange16((u16)current_valuefrom, (u16)current_valueto); + break; + + case SEARCHTYPE_32BIT: + CheatSearchRange32((u32)current_valuefrom, (u32)current_valueto); + break; + } + break; + + case SEARCH_INCBY: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchIncreasedBy8((u8)current_valuefrom); + break; + + case SEARCHTYPE_16BIT: + CheatSearchIncreasedBy16((u16)current_valuefrom); + break; + + case SEARCHTYPE_32BIT: + CheatSearchIncreasedBy32((u32)current_valuefrom); + break; + } + break; + + case SEARCH_DECBY: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchDecreasedBy8((u8)current_valuefrom); + break; + + case SEARCHTYPE_16BIT: + CheatSearchDecreasedBy16((u16)current_valuefrom); + break; + + case SEARCHTYPE_32BIT: + CheatSearchDecreasedBy32((u32)current_valuefrom); + break; + } + break; + + case SEARCH_INC: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchIncreased8(); + break; + + case SEARCHTYPE_16BIT: + CheatSearchIncreased16(); + break; + + case SEARCHTYPE_32BIT: + CheatSearchIncreased32(); + break; + } + break; + + case SEARCH_DEC: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchDecreased8(); + break; + + case SEARCHTYPE_16BIT: + CheatSearchDecreased16(); + break; + + case SEARCHTYPE_32BIT: + CheatSearchDecreased32(); + break; + } + break; + + case SEARCH_DIFFERENT: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchDifferent8(); + break; + + case SEARCHTYPE_16BIT: + CheatSearchDifferent16(); + break; + + case SEARCHTYPE_32BIT: + CheatSearchDifferent32(); + break; + } + break; + + case SEARCH_NOCHANGE: + switch (current_searchtype) { + case SEARCHTYPE_8BIT: + CheatSearchNoChange8(); + break; + + case SEARCHTYPE_16BIT: + CheatSearchNoChange16(); + break; + + case SEARCHTYPE_32BIT: + CheatSearchNoChange32(); + break; + } + break; + + default: + assert(FALSE); // not possible + break; + } + + UpdateCheatSearchDialog(); +} + +// restart the search +static void OnCheatSearchDlg_RestartClicked(GtkWidget *widget, gpointer user_data) { + FreeCheatSearchResults(); + FreeCheatSearchMem(); + + current_search = SEARCH_EQUALVAL; + current_searchtype = SEARCHTYPE_8BIT; + current_searchbase = SEARCHBASE_DEC; + current_valuefrom = 0; + current_valueto = 0; + + UpdateCheatSearchDialog(); +} + +// close the cheat search window +static void OnCheatSearchDlg_CloseClicked(GtkWidget *widget, gpointer user_data) { + gtk_widget_destroy(CheatSearchDlg); + CheatSearchDlg = NULL; +} + +static void OnCheatSearchDlg_SearchForChanged(GtkWidget *widget, gpointer user_data) { + GladeXML *xml; + + xml = glade_get_widget_tree(CheatSearchDlg); + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) == SEARCH_RANGE) { + gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto"))); + gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto"))); + } + else { + gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto"))); + gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto"))); + } + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) >= SEARCH_INC) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), FALSE); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), TRUE); + } + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) >= SEARCH_INCBY && prevM == NULL) { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), FALSE); + } + else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), TRUE); + } +} + +static void OnCheatSearchDlg_DataBaseChanged(GtkWidget *widget, gpointer user_data) { + u32 val; + char buf[256]; + GladeXML *xml; + + xml = glade_get_widget_tree(CheatSearchDlg); + + if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) == SEARCHBASE_DEC) { + val = 0; + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%x", &val); + sprintf(buf, "%u", val); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf); + + val = 0; + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%x", &val); + sprintf(buf, "%u", val); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf); + } + else { + val = 0; + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%u", &val); + sprintf(buf, "%X", val); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf); + + val = 0; + sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%u", &val); + sprintf(buf, "%X", val); + gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf); + } +} + +static void CheatSearch_TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { + GladeXML *xml; + + xml = glade_get_widget_tree(CheatSearchDlg); + + if (GetSelectedResultIndex() != -1) { + // If a row was selected, we can now enable some of the disabled widgets + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_freeze")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_modify")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_copy")), TRUE); + } else { + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_freeze")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_modify")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_copy")), FALSE); + } +} + +// run the cheat search dialog +void RunCheatSearchDialog() { + GladeXML *xml; + GtkWidget *widget; + GtkCellRenderer *renderer; + GtkTreeSelection *treesel; + GtkTreeViewColumn *column; + + xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "CheatSearchDlg", NULL); + if (!xml) { + g_warning(_("Error: Glade interface could not be loaded!")); + return; + } + + CheatSearchDlg = glade_xml_get_widget(xml, "CheatSearchDlg"); + gtk_window_set_title(GTK_WINDOW(CheatSearchDlg), _("Cheat Search")); + + widget = glade_xml_get_widget(xml, "GtkCList_Result"); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes(_("Search Results"), + renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column); + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + gtk_tree_selection_set_mode (treesel, GTK_SELECTION_SINGLE); + g_signal_connect_data(G_OBJECT(treesel), "changed", + G_CALLBACK(CheatSearch_TreeSelectionChanged), + NULL, NULL, G_CONNECT_AFTER); + + UpdateCheatSearchDialog(); + + widget = glade_xml_get_widget(xml, "btn_freeze"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_FreezeClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btn_modify"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_ModifyClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btn_copy"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_CopyClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btn_start"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_SearchClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "btn_restart"); + g_signal_connect_data(GTK_OBJECT(widget), "clicked", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_RestartClicked), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "combo_searchfor"); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_SearchForChanged), xml, NULL, G_CONNECT_AFTER); + + widget = glade_xml_get_widget(xml, "combo_database"); + g_signal_connect_data(GTK_OBJECT(widget), "changed", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_DataBaseChanged), xml, NULL, G_CONNECT_AFTER); + + g_signal_connect_data(GTK_OBJECT(CheatSearchDlg), "response", + GTK_SIGNAL_FUNC(OnCheatSearchDlg_CloseClicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER); +} -- cgit v1.2.3