/* 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 02110-1301 USA */ #include #include #include #include #include #include #include "Linux.h" #include "../libpcsxcore/cheat.h" #include "../libpcsxcore/psxmem.h" static GtkBuilder *builder; 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; int i; widget = GTK_WIDGET(gtk_builder_get_object(builder, "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_search_column(GTK_TREE_VIEW(widget), 1); 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) { 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); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "editbutton1")), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "delbutton1")), TRUE); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "editbutton1")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "delbutton1")), FALSE); } gtk_widget_set_sensitive (GTK_WIDGET(gtk_builder_get_object(builder, "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, "_Cancel", GTK_RESPONSE_CANCEL, "_OK", GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_default_size(GTK_WINDOW(dlg), 350, 350); box = GTK_WIDGET(gtk_dialog_get_content_area(GTK_DIALOG(dlg))); 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_container_add(GTK_CONTAINER(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); while (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!")); continue; } LoadCheatListItems(NumCheats - 1); free(codetext); break; } gtk_widget_destroy(dlg); } static void OnCheatListDlg_EditClicked(GtkWidget *widget, gpointer user_data) { GtkWidget *dlg; GtkWidget *box, *scroll, *label, *descr_edit, *code_edit; GtkTreeIter iter; GtkTreeModel *model; GtkTreePath *path; gboolean selected; int index, i; char buf[8192]; char *p = buf; widget = GTK_WIDGET(gtk_builder_get_object(builder, "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, "_Cancel", GTK_RESPONSE_CANCEL, "_OK", GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_default_size(GTK_WINDOW(dlg), 350, 350); box = GTK_WIDGET(gtk_dialog_get_content_area(GTK_DIALOG(dlg))); 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_container_add(GTK_CONTAINER(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) { GtkTreeIter iter; GtkTreeModel *model; GtkTreePath *path; gboolean selected; int i = -1; widget = GTK_WIDGET(gtk_builder_get_object(builder, "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_list_store_remove (GTK_LIST_STORE (model), &iter); gtk_tree_path_free(path); RemoveCheat(i); } } static void OnCheatListDlg_EnableToggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer user_data) { GtkWidget *widget; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; gboolean fixed; widget = GTK_WIDGET(gtk_builder_get_object (builder, "GtkCList_Cheat")); model = gtk_tree_view_get_model (GTK_TREE_VIEW(widget)); path = gtk_tree_path_new_from_string (path_str); gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get (model, &iter, 0, &fixed, -1); fixed ^= 1; int i = atoi(path_str); assert(i >= 0 && i < NumCheats); Cheats[i].Enabled = fixed; gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, fixed, -1); gtk_tree_path_free (path); } // last chosen filename is kept in here gchar *cheat_last_filename = NULL; const gchar* file_filter_all = NULL; 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, "_Cancel", GTK_RESPONSE_CANCEL, "_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); //gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(chooser), filename); g_free(filename); filter = gtk_file_filter_new (); gtk_file_filter_add_pattern (filter, all_extension_cht); gtk_file_filter_set_name (filter, _("PCSXR 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, file_filter_all); 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(cheat_last_filename); cheat_last_filename = g_path_get_basename(filename); g_free(filename); LoadCheatListItems(-1); } static void OnCheatListDlg_SaveClicked(GtkWidget *widget, gpointer user_data) { GtkWidget *chooser; gchar *filename, *filename2=NULL; GtkFileFilter *filter; chooser = gtk_file_chooser_dialog_new(_("Save Cheat File"), NULL, GTK_FILE_CHOOSER_ACTION_SAVE, "_Cancel", GTK_RESPONSE_CANCEL, "_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); // Use game code as default filename, otherwise remember what user selected if (!cheat_last_filename) { cheat_last_filename = get_cdrom_label_id(dot_extension_cht); } gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser), cheat_last_filename); g_free(filename); filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, all_extension_cht); gtk_file_filter_set_name(filter, _("PCSXR 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, file_filter_all); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter); if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) { filename = filename2 = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser)); if (!g_str_has_suffix(filename, dot_extension_cht) // add extension if cht filter chosen and filename doesn't end with .cht && strcmp(file_filter_all, gtk_file_filter_get_name( gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(chooser)))) != 0) { filename = g_strdup_printf ("%s%s", filename2, dot_extension_cht); } else { filename2 = NULL; } 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(cheat_last_filename); cheat_last_filename = g_path_get_basename(filename); g_free(filename); g_free(filename2); } static void OnCheatListDlg_CloseClicked() { gtk_widget_destroy(CheatListDlg); CheatListDlg = NULL; //g_free(lastfilename); //lastfilename = NULL; } // run the cheat list dialog void RunCheatListDialog() { GtkWidget *widget; GtkTreeSelection *treesel; GtkTreeViewColumn *column; GtkCellRenderer *renderer; file_filter_all = _("All Files (*.*)"); builder = gtk_builder_new(); if (!gtk_builder_add_from_resource(builder, "/org/pcsxr/gui/pcsxr.ui", NULL)) { g_warning("Error: interface could not be loaded!"); return; } CheatListDlg = GTK_WIDGET(gtk_builder_get_object(builder, "CheatListDlg")); gtk_window_set_title(GTK_WINDOW(CheatListDlg), _("Cheat Codes")); gtk_widget_show (CheatListDlg); widget = GTK_WIDGET(gtk_builder_get_object(builder, "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 = GTK_WIDGET(gtk_builder_get_object(builder, "addbutton1")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatListDlg_AddClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "editbutton1")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatListDlg_EditClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "delbutton1")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatListDlg_DelClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "loadbutton1")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatListDlg_OpenClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "savebutton1")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatListDlg_SaveClicked), builder, NULL, G_CONNECT_AFTER); // Setup a handler for when Close or Cancel is clicked g_signal_connect_data(G_OBJECT(CheatListDlg), "response", G_CALLBACK(OnCheatListDlg_CloseClicked), builder, (GClosureNotify)g_object_unref, G_CONNECT_AFTER); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "savebutton1")), NumCheats); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "editbutton1")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "delbutton1")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "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() { char buf[256]; int i; u32 addr; GtkListStore *store = gtk_list_store_new(1, G_TYPE_STRING); GtkTreeIter iter; GtkWidget *widget; widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkCList_Result")); gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_searchfor")), current_search); gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_datatype")), current_searchtype); gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_database")), current_searchbase); if (current_searchbase == SEARCHBASE_DEC) { sprintf(buf, "%u", current_valuefrom); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value")), buf); sprintf(buf, "%u", current_valueto); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto")), buf); } else { sprintf(buf, "%X", current_valuefrom); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value")), buf); sprintf(buf, "%X", current_valueto); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto")), buf); } if (current_search == SEARCH_RANGE) { gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(builder, "label_valueto"))); gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(builder, "entry_valueto"))); } else { gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(builder, "label_valueto"))); gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(builder, "entry_valueto"))); } if (current_search >= SEARCH_INC) { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "entry_value")), FALSE); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "entry_value")), TRUE); } if (current_search >= SEARCH_INCBY && prevM == NULL) { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_start")), FALSE); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_start")), TRUE); } gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_freeze")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_modify")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_copy")), FALSE); if (prevM != NULL) { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "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(gtk_builder_get_object(builder, "label_resultsfound")), buf); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "combo_datatype")), TRUE); gtk_widget_set_sensitive(widget, FALSE); gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(builder, "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_widget_show(widget); } // get the current selected result index in the list static int GetSelectedResultIndex() { GtkTreeSelection *selection; GtkTreeIter iter; GtkTreeModel *model; GtkTreePath *path; gboolean selected; int i; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtk_builder_get_object(builder, "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, "_OK", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL); box = GTK_WIDGET(gtk_dialog_get_content_area(GTK_DIALOG(dlg))); 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_box_new(GTK_ORIENTATION_HORIZONTAL, 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, "_OK", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL); box = GTK_WIDGET(gtk_dialog_get_content_area(GTK_DIALOG(dlg))); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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) { current_search = gtk_combo_box_get_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_searchfor"))); current_searchtype = gtk_combo_box_get_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_datatype"))); current_searchbase = gtk_combo_box_get_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combo_database"))); current_valuefrom = 0; current_valueto = 0; if (current_searchbase == SEARCHBASE_DEC) { sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value"))), "%u", ¤t_valuefrom); sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto"))), "%u", ¤t_valueto); } else { sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value"))), "%x", ¤t_valuefrom); sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "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) { if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) == SEARCH_RANGE) { gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(builder, "label_valueto"))); gtk_widget_show(GTK_WIDGET(gtk_builder_get_object(builder, "entry_valueto"))); } else { gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(builder, "label_valueto"))); gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(builder, "entry_valueto"))); } if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) >= SEARCH_INC) { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "entry_value")), FALSE); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "entry_value")), TRUE); } if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) >= SEARCH_INCBY && prevM == NULL) { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_start")), FALSE); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_start")), TRUE); } } static void OnCheatSearchDlg_DataBaseChanged(GtkWidget *widget, gpointer user_data) { u32 val; char buf[256]; if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) == SEARCHBASE_DEC) { val = 0; sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value"))), "%x", &val); sprintf(buf, "%u", val); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value")), buf); val = 0; sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto"))), "%x", &val); sprintf(buf, "%u", val); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto")), buf); } else { val = 0; sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value"))), "%u", &val); sprintf(buf, "%X", val); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_value")), buf); val = 0; sscanf(gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto"))), "%u", &val); sprintf(buf, "%X", val); gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_valueto")), buf); } } static void CheatSearch_TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { if (GetSelectedResultIndex() != -1) { // If a row was selected, we can now enable some of the disabled widgets gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_freeze")), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_modify")), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_copy")), TRUE); } else { gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_freeze")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_modify")), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(builder, "btn_copy")), FALSE); } } // run the cheat search dialog void RunCheatSearchDialog() { GtkWidget *widget; GtkCellRenderer *renderer; GtkTreeSelection *treesel; GtkTreeViewColumn *column; builder = gtk_builder_new(); if (!gtk_builder_add_from_resource(builder, "/org/pcsxr/gui/pcsxr.ui", NULL)) { g_warning("Error: interface could not be loaded!"); return; } CheatSearchDlg = GTK_WIDGET(gtk_builder_get_object(builder, "CheatSearchDlg")); gtk_window_set_title(GTK_WINDOW(CheatSearchDlg), _("Cheat Search")); gtk_widget_show (CheatSearchDlg); widget = GTK_WIDGET(gtk_builder_get_object(builder, "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 = GTK_WIDGET(gtk_builder_get_object(builder, "btn_freeze")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatSearchDlg_FreezeClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "btn_modify")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatSearchDlg_ModifyClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "btn_copy")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatSearchDlg_CopyClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "btn_start")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatSearchDlg_SearchClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "btn_restart")); g_signal_connect_data(G_OBJECT(widget), "clicked", G_CALLBACK(OnCheatSearchDlg_RestartClicked), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "combo_searchfor")); g_signal_connect_data(G_OBJECT(widget), "changed", G_CALLBACK(OnCheatSearchDlg_SearchForChanged), builder, NULL, G_CONNECT_AFTER); widget = GTK_WIDGET(gtk_builder_get_object(builder, "combo_database")); g_signal_connect_data(G_OBJECT(widget), "changed", G_CALLBACK(OnCheatSearchDlg_DataBaseChanged), builder, NULL, G_CONNECT_AFTER); g_signal_connect_data(G_OBJECT(CheatSearchDlg), "response", G_CALLBACK(OnCheatSearchDlg_CloseClicked), builder, (GClosureNotify)g_object_unref, G_CONNECT_AFTER); }