#include "../../types.h" #include "../../fceu.h" #include "../../cheat.h" #include "../../driver.h" #include "../../version.h" #include "../../movie.h" #include "../../palette.h" #include "../../fds.h" #include "../common/configSys.h" #include "sdl.h" #include "gui.h" #include "dface.h" #include "input.h" #include "config.h" #include "icon.xpm" #ifdef _S9XLUA_H #include "../../fceulua.h" #endif #include #include #ifdef GDK_WINDOWING_X11 #include #endif #ifdef _GTK3 #include #endif #include #include #include // Fix compliation errors for older version of GTK (Ubuntu 10.04 LTS) #if GTK_MINOR_VERSION < 24 && GTK_MAJOR_VERSION == 2 #define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX #define gtk_combo_box_text_new gtk_combo_box_new #define gtk_combo_box_text_get_active_text gtk_combo_box_get_active_text #define gtk_combo_box_text_append_text gtk_combo_box_append_text #endif void toggleSound(GtkWidget* check, gpointer data); void loadGame (); void closeGame(); extern Config *g_config; GtkWidget* MainWindow = NULL; GtkWidget* evbox = NULL; GtkWidget* padNoCombo = NULL; GtkWidget* configNoCombo = NULL; GtkWidget* buttonMappings[10]; GtkWidget* Menubar; GtkRadioAction* stateSlot = NULL; bool gtkIsStarted = false; bool menuTogglingEnabled; //----------------------------------------- // Cheat static variables static GtkTreeStore *actv_cheats_store = NULL; static GtkTreeStore *ram_match_store = NULL; static GtkTreeIter actv_cheats_iter; static GtkTreeIter ram_match_iter; static int cheat_search_known_value = 0; static int cheat_search_neq_value = 0; static int cheat_search_gt_value = 0; static int cheat_search_lt_value = 0; static int new_cheat_addr = 0; static int new_cheat_val = 0; static int new_cheat_cmp = -1; static std::string new_cheat_name; // check to see if a particular GTK version is available // 2.24 is required for most of the dialogs -- ie: checkGTKVersion(2,24); bool checkGTKVersion(int major_required, int minor_required) { int major = GTK_MAJOR_VERSION; int minor = GTK_MINOR_VERSION; if(major > major_required) { return true; } else if (major == major_required) { if(minor >= minor_required) { return true; } else { return false; } } else { return false; } } void setCheckbox(GtkWidget* w, const char* configName) { int buf; g_config->getOption(configName, &buf); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), buf); } // This function configures a single hotkey int configHotkey(char* hotkeyString) { // This is broken right now //SDL_Surface *screen; // SDL_Event event; // KillVideo(); #if SDL_VERSION_ATLEAST(2, 0, 0) return 0; // TODO - SDL 2.0 #else //screen = SDL_SetVideoMode(420, 200, 8, 0); //SDL_WM_SetCaption("Press a key to bind...", 0); /* int newkey = 0; while(1) { SDL_WaitEvent(&event); switch (event.type) { case SDL_KEYDOWN: newkey = event.key.keysym.sym; g_config->setOption(hotkeyString, newkey); extern FCEUGI *GameInfo; InitVideo(GameInfo); return 0; } } return 0;*/ #endif } // This function configures a single button on a gamepad int configGamepadButton(GtkButton* button, gpointer p) { gint x = ((gint)(glong)(p)); //gint x = GPOINTER_TO_INT(p); int padNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(padNoCombo))) - 1; int configNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(configNoCombo))) - 1; char buf[256]; std::string prefix; // only configure when the "Change" button is pressed in, not when it is unpressed if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) return 0; ButtonConfigBegin(); snprintf(buf, sizeof(buf), "SDL.Input.GamePad.%d", padNo); prefix = buf; DWaitButton(NULL, &GamePadConfig[padNo][x], configNo); g_config->setOption(prefix + GamePadNames[x], GamePadConfig[padNo][x].ButtonNum[configNo]); if(GamePadConfig[padNo][x].ButtType[0] == BUTTC_KEYBOARD) { g_config->setOption(prefix + "DeviceType", "Keyboard"); } else if(GamePadConfig[padNo][x].ButtType[0] == BUTTC_JOYSTICK) { g_config->setOption(prefix + "DeviceType", "Joystick"); } else { g_config->setOption(prefix + "DeviceType", "Unknown"); } g_config->setOption(prefix + "DeviceNum", GamePadConfig[padNo][x].DeviceNum[configNo]); snprintf(buf, sizeof(buf), "%s", ButtonName(&GamePadConfig[padNo][x], configNo)); gtk_label_set_markup(GTK_LABEL(buttonMappings[x]), buf); ButtonConfigEnd(); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); return 0; } void resetVideo() { KillVideo(); InitVideo(GameInfo); } void closeVideoWin(GtkWidget* w, gint response, gpointer p) { resetVideo(); if(response != GTK_RESPONSE_APPLY) { gtk_widget_destroy(w); } } void closeDialog(GtkWidget* w, GdkEvent* e, gpointer p) { gtk_widget_destroy(w); } void toggleLowPass(GtkWidget* w, gpointer p) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) { g_config->setOption("SDL.Sound.LowPass", 1); FCEUI_SetLowPass(1); } else { g_config->setOption("SDL.Sound.LowPass", 0); FCEUI_SetLowPass(0); } g_config->save(); } void toggleSwapDuty(GtkWidget* w, gpointer p) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) { g_config->setOption("SDL.SwapDuty", 1); swapDuty = 1; } else { g_config->setOption("SDL.SwapDuty", 0); swapDuty = 0; } g_config->save(); } // Wrapper for pushing GTK options into the config file // p : pointer to the string that names the config option // w : toggle widget void toggleOption(GtkWidget* w, gpointer p) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) g_config->setOption((char*)p, 1); else g_config->setOption((char*)p, 0); g_config->save(); UpdateEMUCore(g_config); } int setTint(GtkWidget* w, gpointer p) { int v = gtk_range_get_value(GTK_RANGE(w)); g_config->setOption("SDL.Tint", v); g_config->save(); int c, h; g_config->getOption("SDL.NTSCpalette", &c); g_config->getOption("SDL.Hue", &h); FCEUI_SetNTSCTH(c, v, h); return 0; } int setHue(GtkWidget* w, gpointer p) { int v = gtk_range_get_value(GTK_RANGE(w)); g_config->setOption("SDL.Hue", v); g_config->save(); int c, t; g_config->getOption("SDL.Tint", &t); g_config->getOption("SDL.SDL.NTSCpalette", &c); FCEUI_SetNTSCTH(c, t, v); return 0; } void loadPalette (GtkWidget* w, gpointer p) { GtkWidget* fileChooser; fileChooser = gtk_file_chooser_dialog_new ("Open NES Palette", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), "/usr/share/fceux/palettes"); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); g_config->setOption("SDL.Palette", filename); g_config->setOption("SDL.SDL.NTSCpalette", 0); LoadCPalette(filename); gtk_entry_set_text(GTK_ENTRY(p), filename); } gtk_widget_destroy (fileChooser); } void clearPalette(GtkWidget* w, gpointer p) { g_config->setOption("SDL.Palette", 0); gtk_entry_set_text(GTK_ENTRY(p), ""); } void openPaletteConfig() { GtkWidget* win; GtkWidget* vbox; GtkWidget* paletteFrame; GtkWidget* paletteHbox; GtkWidget* paletteButton; GtkWidget* paletteEntry; GtkWidget* clearButton; GtkWidget* ntscColorChk; GtkWidget* slidersFrame; GtkWidget* slidersVbox; GtkWidget* tintFrame; GtkWidget* tintHscale; GtkWidget* hueFrame; GtkWidget* hueHscale; win = gtk_dialog_new_with_buttons("Palette Options", GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); gtk_window_set_icon_name(GTK_WINDOW(win), GTK_STOCK_SELECT_COLOR); vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); paletteFrame = gtk_frame_new("Custom palette: "); paletteHbox = gtk_hbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(paletteHbox), 5); gtk_container_add(GTK_CONTAINER(paletteFrame), paletteHbox); paletteButton = gtk_button_new_from_stock(GTK_STOCK_OPEN); gtk_button_set_label(GTK_BUTTON(paletteButton), "Open palette"); paletteEntry = gtk_entry_new(); gtk_editable_set_editable(GTK_EDITABLE(paletteEntry), FALSE); clearButton = gtk_button_new_from_stock(GTK_STOCK_CLEAR); gtk_box_pack_start(GTK_BOX(paletteHbox), paletteButton, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(paletteHbox), paletteEntry, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(paletteHbox), clearButton, FALSE, FALSE, 0); g_signal_connect(paletteButton, "clicked", G_CALLBACK(loadPalette), paletteEntry); g_signal_connect(clearButton, "clicked", G_CALLBACK(clearPalette), paletteEntry); // sync with config std::string fn; g_config->getOption("SDL.Palette", &fn); gtk_entry_set_text(GTK_ENTRY(paletteEntry), fn.c_str()); // ntsc color check ntscColorChk = gtk_check_button_new_with_label("Use NTSC palette"); g_signal_connect(ntscColorChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.NTSCpalette"); setCheckbox(ntscColorChk, "SDL.NTSCpalette"); // color / tint / hue sliders slidersFrame = gtk_frame_new("NTSC palette controls"); slidersVbox = gtk_vbox_new(FALSE, 2); tintFrame = gtk_frame_new("Tint"); tintHscale = gtk_hscale_new_with_range(0, 128, 1); gtk_container_add(GTK_CONTAINER(tintFrame), tintHscale); hueFrame = gtk_frame_new("Hue"); hueHscale = gtk_hscale_new_with_range(0, 128, 1); gtk_container_add(GTK_CONTAINER(hueFrame), hueHscale); g_signal_connect(tintHscale, "button-release-event", G_CALLBACK(setTint), NULL); g_signal_connect(hueHscale, "button-release-event", G_CALLBACK(setHue), NULL); // sync with config int h, t; g_config->getOption("SDL.Hue", &h); g_config->getOption("SDL.Tint", &t); gtk_range_set_value(GTK_RANGE(hueHscale), h); gtk_range_set_value(GTK_RANGE(tintHscale), t); gtk_container_add(GTK_CONTAINER(slidersFrame), slidersVbox); gtk_box_pack_start(GTK_BOX(slidersVbox), ntscColorChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(slidersVbox), tintFrame, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(slidersVbox), hueFrame, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), paletteFrame, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), slidersFrame, FALSE, TRUE, 5); g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); g_signal_connect(win, "response", G_CALLBACK(closeDialog), NULL); gtk_widget_show_all(win); return; } GtkWidget* ipEntry; GtkWidget* portSpin; GtkWidget* pwEntry; void launchNet(GtkWidget* w, gpointer p) { char* ip = (char*)gtk_entry_get_text(GTK_ENTRY(ipEntry)); char* pw = (char*)gtk_entry_get_text(GTK_ENTRY(pwEntry)); int port = (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(portSpin)); g_config->setOption("SDL.NetworkIP", ip); g_config->setOption("SDL.NetworkPassword", pw); g_config->setOption("SDL.NetworkPort", port); gtk_widget_destroy(GTK_WIDGET(w)); loadGame(); } void setUsername(GtkWidget* w, gpointer p) { char* s = (char*)gtk_entry_get_text(GTK_ENTRY(w)); g_config->setOption("SDL.NetworkUsername", s); } void netResponse(GtkWidget* w, gint response_id, gpointer p) { if(response_id == GTK_RESPONSE_OK) launchNet(w, p); else gtk_widget_destroy(w); } void openNetworkConfig() { GtkWidget* win; GtkWidget* box; GtkWidget* userBox; GtkWidget* userEntry; GtkWidget* userLbl; GtkWidget* frame; GtkWidget* vbox; GtkWidget* ipBox; GtkWidget* ipLbl; GtkWidget* portBox; GtkWidget* portLbl; //GtkWidget* localPlayersCbo; GtkWidget* pwBox; GtkWidget* pwLbl; win = gtk_dialog_new_with_buttons("Network Options",GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT),GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_CONNECT, GTK_RESPONSE_OK, NULL); gtk_window_set_icon_name(GTK_WINDOW(win), GTK_STOCK_NETWORK); box = gtk_dialog_get_content_area(GTK_DIALOG(win)); userBox = gtk_hbox_new(FALSE, 3); userLbl = gtk_label_new("Username:"); userEntry = gtk_entry_new(); std::string s; g_config->getOption("SDL.NetworkUsername", &s); gtk_entry_set_text(GTK_ENTRY(userEntry), s.c_str()); g_signal_connect(userEntry, "changed", G_CALLBACK(setUsername), NULL); frame = gtk_frame_new("Network options"); vbox = gtk_vbox_new(FALSE, 5); ipBox = gtk_hbox_new(FALSE, 5); ipLbl = gtk_label_new("Server IP:"); ipEntry = gtk_entry_new(); portBox = gtk_hbox_new(FALSE, 5); portLbl = gtk_label_new("Server port:"); portSpin = gtk_spin_button_new_with_range(0, 999999, 1); //localPlayersCbo = gtk_combo_box_new_text(); pwBox = gtk_hbox_new(FALSE, 3); pwLbl = gtk_label_new("Server password:"); pwEntry = gtk_entry_new(); gtk_spin_button_set_value(GTK_SPIN_BUTTON(portSpin), 4046); gtk_box_pack_start(GTK_BOX(userBox), userLbl, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(userBox), userEntry, TRUE , TRUE, 3); gtk_box_pack_start(GTK_BOX(portBox), portLbl, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(portBox), portSpin, FALSE , FALSE, 3); gtk_box_pack_start(GTK_BOX(ipBox), ipLbl, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(ipBox), ipEntry, TRUE , TRUE, 3); gtk_box_pack_start(GTK_BOX(pwBox), pwLbl, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(pwBox), pwEntry, TRUE , TRUE, 3); gtk_box_pack_start(GTK_BOX(vbox), ipBox, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox), portBox, FALSE, FALSE, 3); //gtk_box_pack_start_defaults(GTK_BOX(vbox), localPlayersCbo); gtk_box_pack_start(GTK_BOX(vbox), pwBox, FALSE, FALSE, 3); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_box_pack_start(GTK_BOX(box), userBox, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), frame, TRUE, TRUE, 0); gtk_widget_show_all(win); g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); g_signal_connect(win, "response", G_CALLBACK(netResponse), NULL); } // handler prototype static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data); void flushGtkEvents() { while (gtk_events_pending ()) gtk_main_iteration_do (FALSE); return; } GtkWidget* HotkeyWin; // creates and opens hotkey config window void openHotkeyConfig() { enum { COMMAND_COLUMN, KEY_COLUMN, N_COLUMNS }; GtkWidget* win = gtk_dialog_new_with_buttons("Hotkey Configuration", GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); gtk_window_set_default_size(GTK_WINDOW(win), 400, 800); HotkeyWin = win; GtkWidget *tree; GtkWidget *vbox; GtkWidget *scroll; vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); GtkTreeStore *hotkey_store = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); std::string prefix = "SDL.Hotkeys."; GtkTreeIter iter; gtk_tree_store_append(hotkey_store, &iter, NULL); // aquire iter int keycode; for(int i=0; igetOption(optionName.c_str(), &keycode); gtk_tree_store_set(hotkey_store, &iter, COMMAND_COLUMN, optionName.c_str(), KEY_COLUMN, #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_GetKeyName(keycode), #else SDL_GetKeyName((SDLKey)keycode), #endif -1); gtk_tree_store_append(hotkey_store, &iter, NULL); // acquire child iterator } tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(hotkey_store)); GtkCellRenderer *renderer; GtkTreeViewColumn* column; renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Command", renderer, "text", COMMAND_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", KEY_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); 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), tree); gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 5); gtk_widget_show_all(win); g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); g_signal_connect(win, "response", G_CALLBACK(closeDialog), NULL); GtkTreeSelection *select; select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); g_signal_connect ( G_OBJECT (select), "changed", G_CALLBACK (tree_selection_changed_cb), NULL); gtk_tree_selection_unselect_all (select); } static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data) { GtkTreeIter iter; GtkTreeModel *model; char* hotkey; if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, 0, &hotkey, -1); gtk_widget_hide(HotkeyWin); flushGtkEvents(); configHotkey(hotkey); g_signal_emit_by_name(HotkeyWin, "destroy-event"); openHotkeyConfig(); g_free (hotkey); } } GtkWidget* typeCombo; // TODO: finish this int setInputDevice(GtkWidget* w, gpointer p) { std::string s = "SDL.Input."; s = s + (char*)p; printf("%s", s.c_str()); g_config->setOption(s, gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(typeCombo))); g_config->save(); return 1; } void updateGamepadConfig(GtkWidget* w, gpointer p) { int i; char strBuf[128]; int padNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(padNoCombo))) - 1; int configNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(configNoCombo))) - 1; for(i=0; i<10; i++) { GtkWidget* mappedKey = buttonMappings[i]; if(GamePadConfig[padNo][i].ButtType[configNo] == BUTTC_KEYBOARD) { #if SDL_VERSION_ATLEAST(2, 0, 0) snprintf(strBuf, sizeof(strBuf), "%s", SDL_GetKeyName(GamePadConfig[padNo][i].ButtonNum[configNo])); #else snprintf(strBuf, sizeof(strBuf), "%s", SDL_GetKeyName((SDLKey)GamePadConfig[padNo][i].ButtonNum[configNo])); #endif } else // FIXME: display joystick button/hat/axis names properly strncpy(strBuf, "Joystick", sizeof(strBuf)); gtk_label_set_text(GTK_LABEL(mappedKey), strBuf); gtk_label_set_use_markup(GTK_LABEL(mappedKey), TRUE); } } // creates and opens the gamepad config window (requires GTK 2.24) void openGamepadConfig() { // GTK 2.24 required for this dialog if (checkGTKVersion(2, 24) == false) { // TODO: present this in a GTK MessageBox? printf(" Warning: GTK >= 2.24 required for this dialog.\nTo configure the gamepads, use \"--inputcfg\" from the command line (ie: \"fceux --inputcfg gamepad1\").\n"); return; } GtkWidget* win; GtkWidget* vbox; GtkWidget* hboxPadNo; GtkWidget* padNoLabel; //GtkWidget* configNoLabel; GtkWidget* fourScoreChk; GtkWidget* oppositeDirChk; GtkWidget* buttonFrame; GtkWidget* buttonTable; win = gtk_dialog_new_with_buttons("Controller Configuration", GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); gtk_window_set_title(GTK_WINDOW(win), "Controller Configuration"); gtk_window_set_icon_name(GTK_WINDOW(win), "input-gaming"); gtk_widget_set_size_request(win, 350, 500); vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE); hboxPadNo = gtk_hbox_new(FALSE, 0); padNoLabel = gtk_label_new("Port:"); //configNoLabel = gtk_label_new("Config Number:"); fourScoreChk = gtk_check_button_new_with_label("Enable Four Score"); oppositeDirChk = gtk_check_button_new_with_label("Allow Up+Down / Left+Right"); typeCombo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(typeCombo), "gamepad"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(typeCombo), "zapper"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(typeCombo), "powerpad.0"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(typeCombo), "powerpad.1"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(typeCombo), "arkanoid"); gtk_combo_box_set_active(GTK_COMBO_BOX(typeCombo), 0); padNoCombo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(padNoCombo), "1"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(padNoCombo), "2"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(padNoCombo), "3"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(padNoCombo), "4"); gtk_combo_box_set_active(GTK_COMBO_BOX(padNoCombo), 0); g_signal_connect(padNoCombo, "changed", G_CALLBACK(updateGamepadConfig), NULL); configNoCombo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "1"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "2"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "3"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "4"); gtk_combo_box_set_active(GTK_COMBO_BOX(configNoCombo), 0); g_signal_connect(padNoCombo, "changed", G_CALLBACK(updateGamepadConfig), NULL); g_signal_connect(typeCombo, "changed", G_CALLBACK(setInputDevice), gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(typeCombo))); setCheckbox(fourScoreChk, "SDL.FourScore"); g_signal_connect(fourScoreChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.FourScore"); setCheckbox(oppositeDirChk, "SDL.Input.EnableOppositeDirectionals"); g_signal_connect(oppositeDirChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.Input.EnableOppositeDirectionals"); gtk_box_pack_start(GTK_BOX(hboxPadNo), padNoLabel, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(hboxPadNo), padNoCombo, TRUE, TRUE, 5); //gtk_box_pack_start(GTK_BOX(hboxPadNo), configNoLabel, TRUE, TRUE, 5); //gtk_box_pack_start(GTK_BOX(hboxPadNo), configNoCombo, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), hboxPadNo, FALSE, TRUE, 5); //gtk_box_pack_start_defaults(GTK_BOX(vbox), typeCombo); gtk_box_pack_start(GTK_BOX(vbox), fourScoreChk, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), oppositeDirChk, FALSE, TRUE, 5); // create gamepad buttons buttonFrame = gtk_frame_new("Buttons"); gtk_label_set_use_markup(GTK_LABEL(gtk_frame_get_label_widget(GTK_FRAME(buttonFrame))), TRUE); buttonTable = gtk_table_new(10, 3, FALSE); gtk_table_set_col_spacings(GTK_TABLE(buttonTable), 5); gtk_container_add(GTK_CONTAINER(buttonFrame), buttonTable); for(int i=0; i<10; i++) { GtkWidget* buttonName = gtk_label_new(GamePadNames[i]); GtkWidget* mappedKey = gtk_label_new(NULL); GtkWidget* changeButton = gtk_toggle_button_new(); char strBuf[128]; sprintf(strBuf, "%s:", GamePadNames[i]); gtk_label_set_text(GTK_LABEL(buttonName), strBuf); gtk_misc_set_alignment(GTK_MISC(buttonName), 1.0, 0.5); gtk_misc_set_alignment(GTK_MISC(mappedKey), 0.0, 0.5); gtk_button_set_label(GTK_BUTTON(changeButton), "Change"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(changeButton), FALSE); gtk_table_attach(GTK_TABLE(buttonTable), buttonName, 0, 1, i, i+1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(buttonTable), mappedKey, 1, 2, i, i+1, (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), 0, 0); gtk_table_attach(GTK_TABLE(buttonTable), changeButton, 2, 3, i, i+1, (GtkAttachOptions)0, (GtkAttachOptions)0, 0, 0); g_signal_connect(changeButton, "clicked", G_CALLBACK(configGamepadButton), GINT_TO_POINTER(i)); buttonMappings[i] = mappedKey; } // display the button mappings for the currently selected configuration updateGamepadConfig(NULL, NULL); gtk_box_pack_start(GTK_BOX(vbox), buttonFrame, TRUE, TRUE, 5); g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); g_signal_connect(win, "response", G_CALLBACK(closeDialog), NULL); gtk_widget_show_all(win); return; } int setBufSize(GtkWidget* w, gpointer p) { int x = gtk_range_get_value(GTK_RANGE(w)); g_config->setOption("SDL.Sound.BufSize", x); // reset sound subsystem for changes to take effect KillSound(); InitSound(); return false; } void setRate(GtkWidget* w, gpointer p) { char* str = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w)); g_config->setOption("SDL.Sound.Rate", atoi(str)); // reset sound subsystem for changes to take effect KillSound(); InitSound(); g_config->save(); return; } void setQuality(GtkWidget* w, gpointer p) { char* str = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w)); if(!strcmp(str, "Very High")) g_config->setOption("SDL.Sound.Quality", 2); if(!strcmp(str, "High")) g_config->setOption("SDL.Sound.Quality", 1); if(!strcmp(str, "Low")) g_config->setOption("SDL.Sound.Quality", 0); // reset sound subsystem for changes to take effect KillSound(); InitSound(); g_config->save(); return; } void resizeGtkWindow() { if(GameInfo == 0) { double xscale, yscale; g_config->getOption("SDL.XScale", &xscale); g_config->getOption("SDL.YScale", &yscale); gtk_widget_set_size_request(evbox, 256*xscale, 224*yscale); GtkRequisition req; gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); } return; } void setScaler(GtkWidget* w, gpointer p) { int scaler = gtk_combo_box_get_active(GTK_COMBO_BOX(w)); int opengl; g_config->getOption("SDL.OpenGL", &opengl); if(opengl && scaler) { FCEUD_PrintError("Scalers not supported in OpenGL mode."); gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0); return; } g_config->setOption("SDL.SpecialFilter", scaler); // 1=hq2x 2=Scale2x 3=NTSC2x 4=hq3x 5=Scale3x 6=Prescale2x 7=Prescale3x 8=Prescale4x 9=pal switch(scaler) { case 4: // hq3x case 5: // scale3x case 7: // prescale3x g_config->setOption("SDL.XScale", 3.0); g_config->setOption("SDL.YScale", 3.0); resizeGtkWindow(); break; case 8: // prescale4x g_config->setOption("SDL.XScale", 4.0); g_config->setOption("SDL.YScale", 4.0); break; default: g_config->setOption("SDL.XScale", 2.0); g_config->setOption("SDL.YScale", 2.0); resizeGtkWindow(); break; } g_config->save(); } void setRegion(GtkWidget* w, gpointer p) { int region = gtk_combo_box_get_active(GTK_COMBO_BOX(w)); g_config->setOption("SDL.PAL", region); FCEUI_SetRegion(region); g_config->save(); } int setXscale(GtkWidget* w, gpointer p) { double v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)); g_config->setOption("SDL.XScale", v); g_config->save(); resizeGtkWindow(); return 0; } int setYscale(GtkWidget* w, gpointer p) { double v = gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)); g_config->setOption("SDL.YScale", v); g_config->save(); resizeGtkWindow(); return 0; } #ifdef OPENGL void setGl(GtkWidget* w, gpointer p) { int scaler; int opengl = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); g_config->getOption("SDL.SpecialFilter", &scaler); if(scaler && opengl) { FCEUD_PrintError("Scalers not supported in OpenGL mode."); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), 0); return; } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) g_config->setOption("SDL.OpenGL", 1); else g_config->setOption("SDL.OpenGL", 0); g_config->save(); } void setDoubleBuffering(GtkWidget* w, gpointer p) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) g_config->setOption("SDL.DoubleBuffering", 1); else g_config->setOption("SDL.DoubleBuffering", 0); g_config->save(); } #endif void openVideoConfig() { GtkWidget* win; GtkWidget* vbox; GtkWidget* lbl; GtkWidget* hbox1; GtkWidget* scalerLbl; GtkWidget* scalerCombo; GtkWidget* glChk; GtkWidget* linearChk; GtkWidget* dbChk; GtkWidget* palHbox; GtkWidget* palLbl; GtkWidget* palCombo; GtkWidget* ppuChk; GtkWidget* spriteLimitChk; GtkWidget* frameskipChk; GtkWidget* clipSidesChk; GtkWidget* xscaleSpin; GtkWidget* yscaleSpin; GtkWidget* xscaleLbl; GtkWidget* yscaleLbl; GtkWidget* xscaleHbox; GtkWidget* yscaleHbox; GtkWidget* showFpsChk; win = gtk_dialog_new_with_buttons("Video Preferences", GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); gtk_window_set_icon_name(GTK_WINDOW(win), "video-display"); //gtk_widget_set_size_request(win, 250, 250); vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); lbl = gtk_label_new("Video options will not take\neffect until the emulator is restarted."); // scalar widgets hbox1 = gtk_hbox_new(FALSE, 3); scalerLbl = gtk_label_new("Special Scaler: "); scalerCombo = gtk_combo_box_text_new(); // -Video Modes Tag- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "none"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "hq2x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "scale2x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "NTSC 2x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "hq3x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "scale3x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "prescale2x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "prescale3x"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "prescale4x"); //gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "pal"); // sync with cfg int buf; g_config->getOption("SDL.SpecialFilter", &buf); gtk_combo_box_set_active(GTK_COMBO_BOX(scalerCombo), buf); g_signal_connect(scalerCombo, "changed", G_CALLBACK(setScaler), NULL); gtk_box_pack_start(GTK_BOX(hbox1), scalerLbl, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox1), scalerCombo, FALSE, FALSE, 5); #ifdef OPENGL // openGL check glChk = gtk_check_button_new_with_label("Enable OpenGL"); g_signal_connect(glChk, "clicked", G_CALLBACK(setGl), NULL); setCheckbox(glChk, "SDL.OpenGL"); // openGL linear filter check linearChk = gtk_check_button_new_with_label("Enable OpenGL linear filter"); g_signal_connect(linearChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.OpenGLip"); setCheckbox(linearChk, "SDL.OpenGLip"); // DoubleBuffering check dbChk = gtk_check_button_new_with_label("Enable double buffering"); g_signal_connect(dbChk, "clicked", G_CALLBACK(setDoubleBuffering), NULL); setCheckbox(dbChk, "SDL.DoubleBuffering"); #endif // Region (NTSC/PAL/Dendy) palHbox = gtk_hbox_new(FALSE, 3); palLbl = gtk_label_new("Region: "); palCombo = gtk_combo_box_text_new(); // -Video Modes Tag- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(palCombo), "NTSC"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(palCombo), "PAL"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(palCombo), "Dendy"); // sync with cfg g_config->getOption("SDL.PAL", &buf); gtk_combo_box_set_active(GTK_COMBO_BOX(palCombo), buf); g_signal_connect(palCombo, "changed", G_CALLBACK(setRegion), NULL); gtk_box_pack_start(GTK_BOX(palHbox), palLbl, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(palHbox), palCombo, FALSE, FALSE, 5); // New PPU check ppuChk = gtk_check_button_new_with_label("Enable new PPU"); g_signal_connect(ppuChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.NewPPU"); setCheckbox(ppuChk, "SDL.NewPPU"); // "disable 8 sprite limit" check spriteLimitChk = gtk_check_button_new_with_label("Disable sprite limit"); g_signal_connect(spriteLimitChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.DisableSpriteLimit"); setCheckbox(spriteLimitChk, "SDL.DisableSpriteLimit"); // frameskip check frameskipChk = gtk_check_button_new_with_label("Enable frameskip"); g_signal_connect(frameskipChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.Frameskip"); setCheckbox(frameskipChk, "SDL.Frameskip"); // clip sides check clipSidesChk = gtk_check_button_new_with_label("Clip sides"); g_signal_connect(clipSidesChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.ClipSides"); setCheckbox(clipSidesChk, "SDL.ClipSides"); // xscale / yscale xscaleHbox = gtk_hbox_new(FALSE, 5); xscaleLbl = gtk_label_new("X scaling factor"); xscaleSpin = gtk_spin_button_new_with_range(1.0, 40.0, .1); yscaleHbox = gtk_hbox_new(FALSE, 5); yscaleLbl = gtk_label_new("Y scaling factor"); yscaleSpin = gtk_spin_button_new_with_range(1.0, 40.0, .1); gtk_box_pack_start(GTK_BOX(xscaleHbox), xscaleLbl, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(xscaleHbox), xscaleSpin, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(yscaleHbox), yscaleLbl, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(yscaleHbox), yscaleSpin, FALSE, FALSE, 2); g_signal_connect(xscaleSpin, "value-changed", G_CALLBACK(setXscale), NULL); g_signal_connect(yscaleSpin, "value-changed", G_CALLBACK(setYscale), NULL); double f; // sync with config g_config->getOption("SDL.XScale", &f); gtk_spin_button_set_value(GTK_SPIN_BUTTON(xscaleSpin), f); g_config->getOption("SDL.YScale", &f); gtk_spin_button_set_value(GTK_SPIN_BUTTON(yscaleSpin), f); // show FPS check showFpsChk = gtk_check_button_new_with_label("Show FPS"); g_signal_connect(showFpsChk, "clicked", G_CALLBACK(toggleOption), (gpointer)"SDL.ShowFPS"); setCheckbox(showFpsChk, "SDL.ShowFPS"); gtk_box_pack_start(GTK_BOX(vbox), lbl, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 5); #ifdef OPENGL gtk_box_pack_start(GTK_BOX(vbox), glChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), linearChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), dbChk, FALSE, FALSE, 5); #endif gtk_box_pack_start(GTK_BOX(vbox), palHbox, FALSE, FALSE,5); gtk_box_pack_start(GTK_BOX(vbox), ppuChk, FALSE, FALSE, 5); #ifdef FRAMESKIP gtk_box_pack_start(GTK_BOX(vbox), frameskipChk, FALSE, FALSE, 5); #endif gtk_box_pack_start(GTK_BOX(vbox), spriteLimitChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), clipSidesChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), xscaleHbox, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), yscaleHbox, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), showFpsChk, FALSE, FALSE, 5); g_signal_connect(win, "delete-event", G_CALLBACK(closeVideoWin), NULL); g_signal_connect(win, "response", G_CALLBACK(closeVideoWin), NULL); gtk_widget_show_all(win); return; } const char* mixerStrings[6] = {"Volume", "Triangle", "Square1", "Square2", "Noise", "PCM"}; int mixerChanged(GtkWidget* w, gpointer p) { int v = gtk_range_get_value(GTK_RANGE(w)); GtkWidget* parent = gtk_widget_get_parent(w); char* lbl = (char*)gtk_frame_get_label(GTK_FRAME(parent)); if(strcmp(lbl, "Volume") == 0) { g_config->setOption("SDL.Sound.Volume", v); FCEUI_SetSoundVolume(v); } if(strcmp(lbl, "Triangle") == 0) { g_config->setOption("SDL.Sound.TriangleVolume", v); FCEUI_SetTriangleVolume(v); } if(strcmp(lbl, "Square1") == 0) { g_config->setOption("SDL.Sound.Square1Volume", v); FCEUI_SetSquare1Volume(v); } if(strcmp(lbl, "Square2") == 0) { g_config->setOption("SDL.Sound.Square2Volume", v); FCEUI_SetSquare2Volume(v); } if(strcmp(lbl, "Noise") == 0) { g_config->setOption("SDL.Sound.NoiseVolume", v); FCEUI_SetNoiseVolume(v); } if(strcmp(lbl, "PCM") == 0) { g_config->setOption("SDL.Sound.PCMVolume", v); FCEUI_SetPCMVolume(v); } return 0; } void openSoundConfig() { GtkWidget* win; GtkWidget* main_hbox; GtkWidget* vbox; GtkWidget* soundChk; GtkWidget* lowpassChk; GtkWidget* hbox1; GtkWidget* qualityCombo; GtkWidget* qualityLbl; GtkWidget* hbox2; GtkWidget* rateCombo; GtkWidget* rateLbl; GtkWidget* bufferLbl; GtkWidget* bufferHscale; GtkWidget* swapDutyChk; GtkWidget* mixerFrame; GtkWidget* mixerHbox; GtkWidget* mixers[6]; GtkWidget* mixerFrames[6]; win = gtk_dialog_new_with_buttons("Sound Preferences", GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); gtk_window_set_icon_name(GTK_WINDOW(win), "audio-x-generic"); main_hbox = gtk_hbox_new(FALSE, 15); vbox = gtk_vbox_new(FALSE, 5); // sound enable check soundChk = gtk_check_button_new_with_label("Enable sound"); g_signal_connect(soundChk, "clicked", G_CALLBACK(toggleSound), NULL); setCheckbox(soundChk,"SDL.Sound"); // low pass filter check lowpassChk = gtk_check_button_new_with_label("Enable low pass filter"); g_signal_connect(lowpassChk, "clicked", G_CALLBACK(toggleLowPass), NULL); setCheckbox(lowpassChk, "SDL.Sound.LowPass"); // sound quality combo box hbox1 = gtk_hbox_new(FALSE, 3); qualityCombo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(qualityCombo), "Low"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(qualityCombo), "High"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(qualityCombo), "Very High"); // sync widget with cfg int buf; g_config->getOption("SDL.Sound.Quality", &buf); gtk_combo_box_set_active(GTK_COMBO_BOX(qualityCombo), buf); g_signal_connect(qualityCombo, "changed", G_CALLBACK(setQuality), NULL); qualityLbl = gtk_label_new("Quality: "); gtk_box_pack_start(GTK_BOX(hbox1), qualityLbl, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox1), qualityCombo, FALSE, FALSE, 5); // sound rate widgets hbox2 = gtk_hbox_new(FALSE, 3); rateCombo = gtk_combo_box_text_new(); const int rates[5] = {11025, 22050, 44100, 48000, 96000}; char choices[8]; for(int i=0; i<5;i++) { sprintf(choices, "%d", rates[i]); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rateCombo), choices); } // sync widget with cfg g_config->getOption("SDL.Sound.Rate", &buf); for(int i=0; i<5; i++) if(buf == rates[i]) gtk_combo_box_set_active(GTK_COMBO_BOX(rateCombo), i); g_signal_connect(rateCombo, "changed", G_CALLBACK(setRate), NULL); // sound rate widgets rateLbl = gtk_label_new("Rate (Hz): "); gtk_box_pack_start(GTK_BOX(hbox2), rateLbl, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox2), rateCombo, FALSE, FALSE, 5); bufferHscale = gtk_hscale_new_with_range(15, 200, 2); bufferLbl = gtk_label_new("Buffer size (in ms)"); // sync widget with cfg g_config->getOption("SDL.Sound.BufSize", &buf); gtk_range_set_value(GTK_RANGE(bufferHscale), buf); g_signal_connect(bufferHscale, "button-release-event", G_CALLBACK(setBufSize), NULL); // Swap duty cycles swapDutyChk = gtk_check_button_new_with_label("Swap Duty Cycles"); g_signal_connect(swapDutyChk, "clicked", G_CALLBACK(toggleSwapDuty), NULL); setCheckbox(swapDutyChk, "SDL.SwapDuty"); // mixer mixerFrame = gtk_frame_new("Mixer:"); mixerHbox = gtk_hbox_new(TRUE, 5); for(int i=0; i<6; i++) { mixers[i] = gtk_vscale_new_with_range(0, 256, 1); gtk_range_set_inverted(GTK_RANGE(mixers[i]), TRUE); mixerFrames[i] = gtk_frame_new(mixerStrings[i]); gtk_container_add(GTK_CONTAINER(mixerFrames[i]), mixers[i]); gtk_box_pack_start(GTK_BOX(mixerHbox), mixerFrames[i], FALSE, TRUE, 5); g_signal_connect(mixers[i], "button-release-event", G_CALLBACK(mixerChanged), (gpointer)i); } // sync with cfg int v; g_config->getOption("SDL.Sound.Volume", &v); gtk_range_set_value(GTK_RANGE(mixers[0]), v); g_config->getOption("SDL.Sound.TriangleVolume", &v); gtk_range_set_value(GTK_RANGE(mixers[1]), v); g_config->getOption("SDL.Sound.Square1Volume", &v); gtk_range_set_value(GTK_RANGE(mixers[2]), v); g_config->getOption("SDL.Sound.Square2Volume", &v); gtk_range_set_value(GTK_RANGE(mixers[3]), v); g_config->getOption("SDL.Sound.NoiseVolume", &v); gtk_range_set_value(GTK_RANGE(mixers[4]), v); g_config->getOption("SDL.Sound.PCMVolume", &v); gtk_range_set_value(GTK_RANGE(mixers[5]), v); // packing some boxes gtk_box_pack_start(GTK_BOX(main_hbox), vbox, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), soundChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), lowpassChk, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), bufferLbl, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), bufferHscale, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(vbox), swapDutyChk, FALSE, TRUE, 5); gtk_box_pack_start(GTK_BOX(main_hbox), mixerFrame, TRUE, TRUE, 5); gtk_container_add(GTK_CONTAINER(mixerFrame), mixerHbox); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(win))), main_hbox, TRUE, TRUE, 0); g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); g_signal_connect(win, "response", G_CALLBACK(closeDialog), NULL); gtk_widget_show_all(win); return; } void quit () { // manually flush GTK event queue while(gtk_events_pending()) gtk_main_iteration_do(FALSE); // this is not neccesary to be explicitly called // it raises a GTK-Critical when its called //gtk_main_quit(); FCEUI_CloseGame(); FCEUI_Kill(); // LoadGame() checks for an IP and if it finds one begins a network session // clear the NetworkIP field so this doesn't happen unintentionally g_config->setOption("SDL.NetworkIP", ""); g_config->save(); SDL_Quit(); exit(0); } const char* Authors[]= { "Linux/SDL Developers:", " Lukas Sabota //punkrockguy318", " Soules", " Bryan Cain", " radsaq", " Shinydoofy", "FceuX 2.0 Developers:", " SP", " zeromus", " adelikat", " caH4e3", " qfox", " Luke Gustafson", " _mz", " UncombedCoconut", " DwEdit", " AnS", "rainwarrior", "feos", "Pre 2.0 Guys:", " Bero", " Xodnizel", " Aaron Oneal", " Joe Nahmias", " Paul Kuliniewicz", " Quietust", " Ben Parnell", " Parasyte & bbitmaster", " blip & nitsuja", "Included components:", " Mitsutaka Okazaki - YM2413 emulator", " Andrea Mazzoleni - Scale2x/Scale3x scalers", " Gilles Vollant - unzip.c PKZIP fileio", NULL}; void openAbout () { GdkPixbuf* logo = gdk_pixbuf_new_from_xpm_data(icon_xpm); gtk_show_about_dialog(GTK_WINDOW(MainWindow), "program-name", "fceuX", "version", FCEU_VERSION_STRING, "copyright", "© 2016 FceuX development team", "license", "GPL-2; See COPYING", //"license-type", GTK_LICENSE_GPL_2_0, "website", "http://fceux.com", "authors", Authors, "logo", logo, NULL); } void toggleSound(GtkWidget* check, gpointer data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) { int last_soundopt; g_config->getOption("SDL.Sound", &last_soundopt); g_config->setOption("SDL.Sound", 1); if(GameInfo && !last_soundopt) InitSound(); } else { g_config->setOption("SDL.Sound", 0); KillSound(); } } void emuReset () { if(isloaded) ResetNES(); } void hardReset () { if(isloaded) { closeGame(); const char* lastFile; g_config->getOption("SDL.LastOpenFile", &lastFile); LoadGame(lastFile); resizeGtkWindow(); } } void enableFullscreen () { if(isloaded) ToggleFS(); } void toggleMenuToggling (GtkToggleAction *action) { bool toggleMenu = gtk_toggle_action_get_active(action); g_config->setOption("SDL.ToggleMenu", (int)toggleMenu); menuTogglingEnabled = toggleMenu; } void toggleAutoResume (GtkToggleAction *action) { bool autoResume = gtk_toggle_action_get_active(action); g_config->setOption("SDL.AutoResume", (int)autoResume); AutoResumePlay = autoResume; } static int ShowCheatSearchResultsCallB(uint32 a, uint8 last, uint8 current) { char addrStr[32], lastStr[32], curStr[32]; sprintf( addrStr, "0x%04x", a ); sprintf( lastStr, "0x%02x", last ); sprintf( curStr, "| 0x%02x", current ); gtk_tree_store_set(ram_match_store, &ram_match_iter, 0, addrStr, 1, lastStr, 2, curStr, -1); gtk_tree_store_append( ram_match_store, &ram_match_iter, NULL); // aquire iter return 1; } static void showCheatSearchResults(void) { int total_matches = 0; gtk_tree_store_clear(ram_match_store); gtk_tree_store_append( ram_match_store, &ram_match_iter, NULL); // aquire iter total_matches = FCEUI_CheatSearchGetCount(); printf("Cheat Search Matches: %i \n", total_matches ); FCEUI_CheatSearchGetRange( 0, total_matches, ShowCheatSearchResultsCallB ); } static void cheatSearchReset( GtkButton *button, gpointer user_data) { printf("Cheat Search Reset!\n"); cheat_search_known_value = 0; cheat_search_neq_value = 0; cheat_search_gt_value = 0; cheat_search_lt_value = 0; FCEUI_CheatSearchBegin(); showCheatSearchResults(); // Enable Cheat Search Buttons - Change Sensitivity } static void cheatSearchKnown( GtkButton *button, gpointer user_data) { //printf("Cheat Search Known!\n"); FCEUI_CheatSearchEnd(FCEU_SEARCH_NEWVAL_KNOWN, cheat_search_known_value, 0); showCheatSearchResults(); } static void cheatSearchEqual( GtkButton *button, gpointer user_data) { //printf("Cheat Search Equal !\n"); FCEUI_CheatSearchEnd(FCEU_SEARCH_PUERLY_RELATIVE_CHANGE, 0, cheat_search_neq_value); showCheatSearchResults(); } static void cheatSearchNotEqual( GtkButton *button, GtkToggleButton *chkbox ) { int checked = gtk_toggle_button_get_active(chkbox); //printf("Cheat Search NotEqual %i!\n", checked); if ( checked ){ FCEUI_CheatSearchEnd(FCEU_SEARCH_PUERLY_RELATIVE_CHANGE, 0, cheat_search_neq_value); } else { FCEUI_CheatSearchEnd(FCEU_SEARCH_ANY_CHANGE, 0, 0); } showCheatSearchResults(); } static void cheatSearchGreaterThan( GtkButton *button, GtkToggleButton *chkbox ) { int checked = gtk_toggle_button_get_active(chkbox); //printf("Cheat Search GreaterThan %i!\n", checked); if ( checked ){ FCEUI_CheatSearchEnd(FCEU_SEARCH_NEWVAL_GT_KNOWN, 0, cheat_search_gt_value); } else { FCEUI_CheatSearchEnd(FCEU_SEARCH_NEWVAL_GT, 0, 0); } showCheatSearchResults(); } static void cheatSearchLessThan( GtkButton *button, GtkToggleButton *chkbox ) { int checked = gtk_toggle_button_get_active(chkbox); //printf("Cheat Search LessThan %i!\n", checked); if ( checked ){ FCEUI_CheatSearchEnd(FCEU_SEARCH_NEWVAL_LT_KNOWN, 0, cheat_search_gt_value); } else { FCEUI_CheatSearchEnd(FCEU_SEARCH_NEWVAL_LT, 0, 0); } showCheatSearchResults(); } static void cheatSearchValueEntryCB( GtkWidget *widget, void *userData ) { long value; const gchar *entry_text; entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); value = strtol( entry_text, NULL, 16 ); switch ( (long)userData ) { default: case 0: break; case 1: cheat_search_known_value = value; break; case 2: cheat_search_neq_value = value; break; case 3: cheat_search_gt_value = value; break; case 4: cheat_search_lt_value = value; break; } //printf("Cheat Value Entry contents: '%s' Value: 0x%02lx\n", entry_text, value); } static int activeCheatListCB(char *name, uint32 a, uint8 v, int c, int s, int type, void* data) { char addrStr[32], valStr[16], cmpStr[16]; //printf("Cheat Name:'%s' Addr:0x%04x Val:0x%02x \n", name, a, v ); sprintf( addrStr, "0x%04x", a ); sprintf( valStr, "0x%02x", v ); if ( c >= 0 ){ sprintf( cmpStr, "0x%02x", c ); } else { strcpy( cmpStr, "0xff"); } gtk_tree_store_set(actv_cheats_store, &actv_cheats_iter, 0, addrStr, 1, valStr, 2, cmpStr, 3, name, -1); gtk_tree_store_append( actv_cheats_store, &actv_cheats_iter, NULL); // aquire iter return 1; } static void showActiveCheatList(void) { gtk_tree_store_clear(actv_cheats_store); gtk_tree_store_append( actv_cheats_store, &actv_cheats_iter, NULL); // aquire iter FCEUI_ListCheats( activeCheatListCB, 0 ); } static void openCheatFile( GtkWidget *widget, void *userData ) { GtkWidget* fileChooser; GtkFileFilter* filterCht; GtkFileFilter* filterAll; filterCht = gtk_file_filter_new(); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterCht, "*.cht"); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterCht, "*.cht"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Open Cheat", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); const char* last_dir; g_config->getOption("SDL.LastOpenFile", &last_dir); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), last_dir); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterCht); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { FILE *fp; char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); gtk_widget_destroy (fileChooser); fp = fopen( filename, "r"); if ( fp != NULL ) { FCEU_LoadGameCheats( fp, 0 ); fclose(fp); } //g_config->setOption("SDL.LastOpenFile", filename); // Error dialog no longer required with GTK implementation of FCEUD_PrintError() resizeGtkWindow(); g_free( filename); } else { gtk_widget_destroy (fileChooser); } showActiveCheatList(); } static void newCheatEntryCB( GtkWidget *widget, void *userData ) { const gchar *entry_text; entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); switch ( (long)userData ) { default: case 0: new_cheat_addr = strtol( entry_text, NULL, 16 ); break; case 1: new_cheat_val = strtol( entry_text, NULL, 16 ); break; case 2: { if ( entry_text[0] == 0 ) { new_cheat_cmp = -1; } else { new_cheat_cmp = strtol( entry_text, NULL, 16 ); } } break; case 3: new_cheat_name.assign( entry_text ); break; } //printf("Cheat Value Entry contents: '%s' Value: 0x%02lx\n", entry_text, value); } static void addCheat2Active( GtkWidget *widget, void *userData ) { if ( FCEUI_AddCheat( new_cheat_name.c_str(), new_cheat_addr, new_cheat_val, new_cheat_cmp, 1) ) { showActiveCheatList(); } } static void removeCheatFromActive( GtkWidget *widget, GtkTreeView *tree ) { int numListRows; GList *selListRows, *tmpList; GtkTreeModel *model = NULL; GtkTreeSelection *treeSel = gtk_tree_view_get_selection(tree); numListRows = gtk_tree_selection_count_selected_rows( treeSel ); //printf("Number of Rows Selected: %i\n", numListRows ); selListRows = gtk_tree_selection_get_selected_rows( treeSel, &model ); tmpList = selListRows; while ( tmpList ) { int depth; int *indexArray; GtkTreePath *path = (GtkTreePath*)tmpList->data; depth = gtk_tree_path_get_depth(path); indexArray = gtk_tree_path_get_indices(path); if ( depth > 0 ) { FCEUI_DelCheat( indexArray[0] ); } //printf("Depth: %i \n", depth ); //for (int i=0; inext; } g_list_free_full(selListRows, (GDestroyNotify) gtk_tree_path_free); showActiveCheatList(); } static void updateCheatList( GtkWidget *widget, void *userData ) { showActiveCheatList(); } // creates and opens cheats window static void openCheatsWindow(void) { GtkWidget* win; GtkWidget* main_hbox; GtkWidget* hbox; GtkWidget* vbox, *prev_cmp_vbox; GtkWidget* frame; GtkWidget* label, *txt_entry; GtkWidget* button, *chkbutton; GtkWidget *tree; GtkWidget *scroll; GtkWidget *align; win = gtk_dialog_new_with_buttons("Cheats", GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); gtk_window_set_default_size(GTK_WINDOW(win), 600, 600); main_hbox = gtk_hbox_new(FALSE, 2); vbox = gtk_vbox_new(FALSE, 5); frame = gtk_frame_new("Active Cheats"); actv_cheats_store = gtk_tree_store_new( 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); GtkTreeIter iter; gtk_tree_store_append(actv_cheats_store, &iter, NULL); // aquire iter //for(int i=0; i<15; i++) //{ // std::string cheatName = "Test"; // gtk_tree_store_set(actv_cheats_store, &iter, // 0, cheatName.c_str(), // -1); // gtk_tree_store_append(actv_cheats_store, &iter, NULL); // acquire child iterator //} tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(actv_cheats_store)); GtkCellRenderer *renderer; GtkTreeViewColumn* column; renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Addr", renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); column = gtk_tree_view_column_new_with_attributes("Val", renderer, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); column = gtk_tree_view_column_new_with_attributes("Cmp", renderer, "text", 2, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); column = gtk_tree_view_column_new_with_attributes("Desc", renderer, "text", 3, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); 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), tree); gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 1); hbox = gtk_hbox_new(FALSE, 2); label = gtk_label_new("Name:"); txt_entry = gtk_entry_new(); g_signal_connect( txt_entry, "activate", G_CALLBACK(newCheatEntryCB), (void*)3L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(newCheatEntryCB), (void*)3L ); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, TRUE, TRUE, 1); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 1); hbox = gtk_hbox_new(FALSE, 6); label = gtk_label_new("Addr:"); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 4 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 4 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(newCheatEntryCB), (void*)0L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(newCheatEntryCB), (void*)0L ); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, TRUE, TRUE, 1); label = gtk_label_new("Val:"); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 2 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 2 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(newCheatEntryCB), (void*)1L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(newCheatEntryCB), (void*)1L ); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, TRUE, TRUE, 1); label = gtk_label_new("Cmp:"); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 2 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 2 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(newCheatEntryCB), (void*)2L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(newCheatEntryCB), (void*)2L ); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, TRUE, TRUE, 1); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 1); hbox = gtk_hbox_new(FALSE, 3); button = gtk_button_new_with_label("Add"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 1); g_signal_connect( button, "clicked", G_CALLBACK (addCheat2Active), (gpointer) NULL ); button = gtk_button_new_with_label("Delete"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 1); g_signal_connect( button, "clicked", G_CALLBACK (removeCheatFromActive), (gpointer) tree ); button = gtk_button_new_with_label("Update"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 1); g_signal_connect( button, "clicked", G_CALLBACK (updateCheatList), (gpointer) NULL ); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 1); hbox = gtk_hbox_new(FALSE, 1); button = gtk_button_new_with_label("Add from CHT file..."); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 1); g_signal_connect( button, "clicked", G_CALLBACK (openCheatFile), (gpointer) NULL ); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 1); gtk_container_add(GTK_CONTAINER(frame), vbox); // gtk_box_pack_start(GTK_BOX(main_hbox), frame, TRUE, TRUE, 1); vbox = gtk_vbox_new(FALSE, 5); hbox = gtk_hbox_new(FALSE, 1); button = gtk_button_new_with_label("Reset"); g_signal_connect( button, "clicked", G_CALLBACK (cheatSearchReset), (gpointer) NULL ); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); hbox = gtk_hbox_new(FALSE, 3); button = gtk_button_new_with_label("Known Value:"); g_signal_connect( button, "clicked", G_CALLBACK (cheatSearchKnown), (gpointer) NULL ); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5); label = gtk_label_new("0x"); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 2 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 2 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(cheatSearchValueEntryCB), (void*)1L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(cheatSearchValueEntryCB), (void*)1L ); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); frame = gtk_frame_new("Previous Compare"); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5); button = gtk_check_button_new_with_label("Pause emulation when this window is active"); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 5); prev_cmp_vbox = gtk_vbox_new(FALSE, 4); gtk_container_add(GTK_CONTAINER(frame), prev_cmp_vbox); hbox = gtk_hbox_new(FALSE, 1); align = gtk_alignment_new( 0, 0, 0.5, 0 ); button = gtk_button_new_with_label("Equal"); gtk_container_add( GTK_CONTAINER(align), button ); gtk_box_pack_start(GTK_BOX(hbox), align, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(prev_cmp_vbox), hbox, FALSE, FALSE, 5); g_signal_connect( button, "clicked", G_CALLBACK (cheatSearchEqual), (gpointer) NULL ); hbox = gtk_hbox_new(FALSE, 4); align = gtk_alignment_new( 0, 0, 1, 0 ); button = gtk_button_new_with_label("Not Equal"); gtk_container_add( GTK_CONTAINER(align), button ); gtk_box_pack_start(GTK_BOX(hbox), align, TRUE, TRUE, 5); chkbutton = gtk_check_button_new(); gtk_box_pack_start(GTK_BOX(hbox), chkbutton, FALSE, FALSE, 5); g_signal_connect( button, "clicked", G_CALLBACK (cheatSearchNotEqual), (gpointer) chkbutton ); label = gtk_label_new("By: 0x"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 2 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 2 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(cheatSearchValueEntryCB), (void*)2L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(cheatSearchValueEntryCB), (void*)2L ); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(prev_cmp_vbox), hbox, FALSE, FALSE, 5); hbox = gtk_hbox_new(FALSE, 4); align = gtk_alignment_new( 0, 0, 1, 0 ); button = gtk_button_new_with_label("Greater Than"); gtk_container_add( GTK_CONTAINER(align), button ); gtk_box_pack_start(GTK_BOX(hbox), align, TRUE, TRUE, 5); chkbutton = gtk_check_button_new(); g_signal_connect( button, "clicked", G_CALLBACK (cheatSearchGreaterThan), (gpointer) chkbutton ); gtk_box_pack_start(GTK_BOX(hbox), chkbutton, FALSE, FALSE, 5); label = gtk_label_new("By: 0x"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 2 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 2 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(cheatSearchValueEntryCB), (void*)3L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(cheatSearchValueEntryCB), (void*)3L ); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(prev_cmp_vbox), hbox, FALSE, FALSE, 5); hbox = gtk_hbox_new(FALSE, 4); align = gtk_alignment_new( 0, 0, 1, 0 ); button = gtk_button_new_with_label("Less Than"); gtk_container_add( GTK_CONTAINER(align), button ); gtk_box_pack_start(GTK_BOX(hbox), align, TRUE, TRUE, 5); chkbutton = gtk_check_button_new(); g_signal_connect( button, "clicked", G_CALLBACK (cheatSearchLessThan), (gpointer) chkbutton ); gtk_box_pack_start(GTK_BOX(hbox), chkbutton, FALSE, FALSE, 5); label = gtk_label_new("By: 0x"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); txt_entry = gtk_entry_new(); gtk_entry_set_max_length( GTK_ENTRY(txt_entry), 2 ); gtk_entry_set_width_chars( GTK_ENTRY(txt_entry), 2 ); g_signal_connect( txt_entry, "activate", G_CALLBACK(cheatSearchValueEntryCB), (void*)4L ); g_signal_connect( txt_entry, "changed", G_CALLBACK(cheatSearchValueEntryCB), (void*)4L ); gtk_box_pack_start(GTK_BOX(hbox), txt_entry, FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(prev_cmp_vbox), hbox, FALSE, FALSE, 1); hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 1); frame = gtk_frame_new("Cheat Search"); gtk_container_add(GTK_CONTAINER(frame), hbox); gtk_box_pack_start(GTK_BOX(main_hbox), frame, TRUE, TRUE, 5); vbox = gtk_vbox_new(FALSE, 5); //hbox = gtk_hbox_new(FALSE, 1); ram_match_store = gtk_tree_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); gtk_tree_store_append( ram_match_store, &ram_match_iter, NULL); // aquire iter //for(int i=0; i<15; i++) //{ // std::string ramText = "Test"; // gtk_tree_store_set(ram_match_store, &ram_match_iter, // 0, ramText.c_str(), // -1); // gtk_tree_store_append(ram_match_store, &ram_match_iter, NULL); // acquire child iterator //} tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ram_match_store)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Addr", renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); column = gtk_tree_view_column_new_with_attributes("Last", renderer, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); column = gtk_tree_view_column_new_with_attributes("Curr", renderer, "text", 2, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); 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), tree); gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 5); frame = gtk_frame_new(""); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(win))), main_hbox, TRUE, TRUE, 0); g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); g_signal_connect(win, "response", G_CALLBACK(closeDialog), NULL); gtk_widget_show_all(win); } void recordMovie() { if(isloaded) { std::string name = FCEU_MakeFName(FCEUMKF_MOVIE, 0, 0); FCEUI_printf("Recording movie to %s\n", name.c_str()); FCEUI_SaveMovie(name.c_str(), MOVIE_FLAG_NONE, L""); } return; } void recordMovieAs () { if(!isloaded) { return; } GtkWidget* fileChooser; GtkFileFilter* filterFm2; GtkFileFilter* filterAll; filterFm2 = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterFm2, "*.fm2"); gtk_file_filter_set_name(filterFm2, "FM2 Movies"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Save FM2 movie for recording", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(fileChooser), ".fm2"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterFm2); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), getcwd(NULL, 0)); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { std::string fname; fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); if (!fname.size()) return; // no filename selected, quit the whole thing std::string s = GetUserText("Author name"); std::wstring author(s.begin(), s.end()); FCEUI_SaveMovie(fname.c_str(), MOVIE_FLAG_NONE, author); } gtk_widget_destroy (fileChooser); } void loadMovie () { GtkWidget* fileChooser; GtkFileFilter* filterMovies; GtkFileFilter* filterFm2; GtkFileFilter* filterAll; filterMovies = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterMovies, "*.fm2"); gtk_file_filter_add_pattern(filterMovies, "*.FM2f"); gtk_file_filter_add_pattern(filterMovies, "*.fm3"); gtk_file_filter_set_name(filterMovies, "FM2 Movies, TAS Editor Projects"); filterFm2 = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterFm2, "*.fm2"); gtk_file_filter_add_pattern(filterFm2, "*.FM2f"); gtk_file_filter_set_name(filterFm2, "FM2 Movies"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Open FM2 Movie", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterMovies); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterFm2); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), getcwd(NULL, 0)); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* fname; fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); static int pauseframe; g_config->getOption("SDL.PauseFrame", &pauseframe); g_config->setOption("SDL.PauseFrame", 0); FCEUI_printf("Playing back movie located at %s\n", fname); if(FCEUI_LoadMovie(fname, false, pauseframe ? pauseframe : false) == FALSE) { GtkWidget* d; d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the movie file."); gtk_dialog_run(GTK_DIALOG(d)); gtk_widget_destroy(d); } } gtk_widget_destroy (fileChooser); } #ifdef _S9XLUA_H void loadLua () { GtkWidget* fileChooser; GtkFileFilter* filterLua; GtkFileFilter* filterAll; filterLua = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterLua, "*.lua"); gtk_file_filter_add_pattern(filterLua, "*.LUA"); gtk_file_filter_set_name(filterLua, "Lua scripts"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Open LUA Script", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterLua); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); const char* last_file; g_config->getOption("SDL.LastLoadLua", &last_file); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), last_file); if(strcmp(last_file, "") == 0) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), "/usr/share/fceux/luaScripts"); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); g_config->setOption("SDL.LastLoadLua", filename); gtk_widget_destroy(fileChooser); if(FCEU_LoadLuaCode(filename) == 0) { // This is necessary because lua scripts do not use FCEUD_PrintError to print errors. GtkWidget* d; d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the selected lua script."); gtk_dialog_run(GTK_DIALOG(d)); gtk_widget_destroy(d); } g_free(filename); } else gtk_widget_destroy (fileChooser); } #endif void loadFdsBios () { GtkWidget* fileChooser; GtkFileFilter* filterDiskSys; GtkFileFilter* filterRom; GtkFileFilter* filterAll; filterDiskSys = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterDiskSys, "disksys.rom"); gtk_file_filter_set_name(filterDiskSys, "disksys.rom"); filterRom = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterRom, "*.rom"); gtk_file_filter_set_name(filterRom, "*.rom"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Load FDS BIOS (disksys.rom)", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterDiskSys); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterRom); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), getcwd(NULL, 0)); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); // copy BIOS file to proper place (~/.fceux/disksys.rom) std::ifstream fdsBios (filename,std::fstream::binary); std::string output_filename = FCEU_MakeFName(FCEUMKF_FDSROM, 0, ""); std::ofstream outFile (output_filename.c_str(),std::fstream::trunc|std::fstream::binary); outFile<setOption("SDL.GameGenie", enabled); g_config->save(); FCEUI_SetGameGenie(enabled); } void toggleGameGenie(GtkToggleAction *action) { enableGameGenie(gtk_toggle_action_get_active(action)); } void togglePause(GtkAction *action) { SDL_Event sdlev; int paused; if(isloaded) { paused = FCEUI_EmulationPaused(); sdlev.type = SDL_FCEU_HOTKEY_EVENT; sdlev.user.code = HK_PAUSE; if(SDL_PushEvent(&sdlev) < 0) { FCEU_printf("Failed to push SDL event to %s game.\n", paused ? "resume" : "pause"); return; } gtk_action_set_label(action, paused ? "Pause" : "Resume"); gtk_action_set_stock_id(action, paused ? GTK_STOCK_MEDIA_PAUSE : GTK_STOCK_MEDIA_PLAY); } } void loadGameGenie () { GtkWidget* fileChooser; GtkFileFilter* filterGG; GtkFileFilter* filterRom; GtkFileFilter* filterNes; GtkFileFilter* filterAll; filterGG = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterGG, "gg.rom"); gtk_file_filter_set_name(filterGG, "gg.rom"); filterRom = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterRom, "*.rom"); gtk_file_filter_set_name(filterRom, "*.rom"); filterNes = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterNes, "*.nes"); gtk_file_filter_set_name(filterNes, "*.nes"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Load Game Genie ROM", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterGG); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterRom); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterNes); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), getcwd(NULL, 0)); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); // copy file to proper place (~/.fceux/gg.rom) std::ifstream f1 (filename,std::fstream::binary); std::string fn_out = FCEU_MakeFName(FCEUMKF_GGROM, 0, ""); std::ofstream f2 (fn_out.c_str(),std::fstream::trunc|std::fstream::binary); gtk_widget_destroy (fileChooser); GtkWidget* d; enableGameGenie(TRUE); d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Game Genie ROM copied to: '%s'.", fn_out.c_str()); gtk_dialog_run(GTK_DIALOG(d)); gtk_widget_destroy(d); f2<getOption("SDL.LastOpenNSF", &last_dir); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), last_dir); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterNSF); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterZip); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); gtk_widget_destroy (fileChooser); LoadGame(filename); // no longer required with GTK FCEUD_PrintError implementation /*if(LoadGame(filename) == 0) { GtkWidget* d; d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the selected NSF file."); gtk_dialog_run(GTK_DIALOG(d)); gtk_widget_destroy(d); }*/ g_config->setOption("SDL.LastOpenNSF", filename); g_free(filename); } else gtk_widget_destroy (fileChooser); } void closeGame() { GdkColor bg = {0, 0, 0, 0}; gtk_widget_modify_bg(evbox, GTK_STATE_NORMAL, &bg); CloseGame(); } void loadGame () { GtkWidget* fileChooser; GtkFileFilter* filterFCEU; GtkFileFilter* filterNes; GtkFileFilter* filterFds; GtkFileFilter* filterNSF; GtkFileFilter* filterZip; GtkFileFilter* filterAll; filterFCEU = gtk_file_filter_new(); filterNes = gtk_file_filter_new(); filterFds = gtk_file_filter_new(); filterNSF = gtk_file_filter_new(); filterZip = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterFCEU, "*.nes"); gtk_file_filter_add_pattern(filterFCEU, "*.NES"); gtk_file_filter_add_pattern(filterFCEU, "*.fds"); gtk_file_filter_add_pattern(filterFCEU, "*.FDS"); gtk_file_filter_add_pattern(filterFCEU, "*.zip"); gtk_file_filter_add_pattern(filterFCEU, "*.ZIP"); gtk_file_filter_add_pattern(filterFCEU, "*.Nes"); gtk_file_filter_add_pattern(filterFCEU, "*.Fds"); gtk_file_filter_add_pattern(filterFCEU, "*.Zip"); gtk_file_filter_add_pattern(filterFCEU, "*.nsf"); gtk_file_filter_add_pattern(filterFCEU, "*.NSF"); gtk_file_filter_add_pattern(filterNes, "*.nes"); gtk_file_filter_add_pattern(filterNes, "*.NES"); gtk_file_filter_add_pattern(filterFds, "*.fds"); gtk_file_filter_add_pattern(filterFds, "*.FDS"); gtk_file_filter_add_pattern(filterNSF, "*.nsf"); gtk_file_filter_add_pattern(filterNSF, "*.NSF"); gtk_file_filter_add_pattern(filterZip, "*.zip"); gtk_file_filter_add_pattern(filterZip, "*.zip"); gtk_file_filter_set_name(filterFCEU, "*.nes;*.fds;*.nsf;*.zip"); gtk_file_filter_set_name(filterNes, "NES ROM files"); gtk_file_filter_set_name(filterFds, "FDS ROM files"); gtk_file_filter_set_name(filterNSF, "NSF sound files"); gtk_file_filter_set_name(filterZip, "Zip archives"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Open ROM", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); const char* last_dir; g_config->getOption("SDL.LastOpenFile", &last_dir); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), last_dir); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterFCEU); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterNes); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterFds); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterNSF); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterZip); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); gtk_widget_destroy (fileChooser); g_config->setOption("SDL.LastOpenFile", filename); closeGame(); LoadGame(filename); // Error dialog no longer required with GTK implementation of FCEUD_PrintError() /*if(LoadGame(filename) == 0) { GtkWidget* d; d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not open the selected ROM file."); gtk_dialog_run(GTK_DIALOG(d)); gtk_widget_destroy(d); }*/ resizeGtkWindow(); g_free(filename); } else gtk_widget_destroy (fileChooser); } void saveStateAs() { GtkWidget* fileChooser; GtkFileFilter* filterSav; GtkFileFilter* filterAll; filterSav = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterSav, "*.sav"); gtk_file_filter_add_pattern(filterSav, "*.SAV"); gtk_file_filter_set_name(filterSav, "SAV files"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); const char* last_dir; g_config->getOption("SDL.LastSaveStateAs", &last_dir); fileChooser = gtk_file_chooser_dialog_new ("Save State As", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), last_dir); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(fileChooser), ".sav"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterSav); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); FCEUI_SaveState(filename); g_config->setOption("SDL.LastSaveStateAs", filename); g_free(filename); } gtk_widget_destroy (fileChooser); } void loadStateFrom() { GtkWidget* fileChooser; GtkFileFilter* filterFcs; GtkFileFilter* filterSav; GtkFileFilter* filterAll; filterSav = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterSav, "*.sav"); gtk_file_filter_add_pattern(filterSav, "*.SAV"); gtk_file_filter_set_name(filterSav, "SAV files"); filterFcs = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterFcs, "*.fc?"); gtk_file_filter_add_pattern(filterFcs, "*.FC?"); gtk_file_filter_set_name(filterFcs, "FCS files"); filterAll = gtk_file_filter_new(); gtk_file_filter_add_pattern(filterAll, "*"); gtk_file_filter_set_name(filterAll, "All Files"); fileChooser = gtk_file_chooser_dialog_new ("Load State From", GTK_WINDOW(MainWindow), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); const char* last_dir; g_config->getOption("SDL.LastLoadStateFrom", &last_dir); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), last_dir); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterFcs); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterSav); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterAll); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); FCEUI_LoadState(filename); g_config->setOption("SDL.LastLoadStateFrom", filename); g_free(filename); } gtk_widget_destroy (fileChooser); } void quickLoad() { FCEUI_LoadState(NULL); } void quickSave() { FCEUI_SaveState(NULL); } void changeState(GtkAction *action, GtkRadioAction *current, gpointer data) { FCEUI_SelectState(gtk_radio_action_get_current_value(current), 0); } #if SDL_VERSION_ATLEAST(2, 0, 0) // SDL 1.2/2.0 compatibility macros #define SDLK_SCROLLOCK SDLK_SCROLLLOCK #define SDLK_PRINT SDLK_PRINTSCREEN #define SDLK_BREAK 0 #define SDLK_COMPOSE 0 #define SDLK_NUMLOCK SDLK_NUMLOCKCLEAR #define SDLK_KP0 SDLK_KP_0 #define SDLK_KP1 SDLK_KP_1 #define SDLK_KP2 SDLK_KP_2 #define SDLK_KP3 SDLK_KP_3 #define SDLK_KP4 SDLK_KP_4 #define SDLK_KP5 SDLK_KP_5 #define SDLK_KP6 SDLK_KP_6 #define SDLK_KP7 SDLK_KP_7 #define SDLK_KP8 SDLK_KP_8 #define SDLK_KP9 SDLK_KP_9 #define SDLK_LSUPER SDLK_LGUI #define SDLK_RSUPER SDLK_RGUI #define SDLK_LMETA 0 #define SDLK_RMETA 0 #endif // Adapted from Gens/GS. Converts a GDK key value into an SDL key value. unsigned short GDKToSDLKeyval(int gdk_key) { if (!(gdk_key & 0xFF00)) { // ASCII symbol. // SDL and GDK use the same values for these keys. // Make sure the key value is lowercase. gdk_key = tolower(gdk_key); // Return the key value. return gdk_key; } if (gdk_key & 0xFFFF0000) { // Extended X11 key. Not supported by SDL. #ifdef GDK_WINDOWING_X11 fprintf(stderr, "Unhandled extended X11 key: 0x%08X (%s)", gdk_key, XKeysymToString(gdk_key)); #else fprintf(stderr, "Unhandled extended key: 0x%08X\n", gdk_key); #endif return 0; } // Non-ASCII symbol. static const uint16_t gdk_to_sdl_table[0x100] = { // 0x00 - 0x0F 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_BACKSPACE, SDLK_TAB, SDLK_RETURN, SDLK_CLEAR, 0x0000, SDLK_RETURN, 0x0000, 0x0000, // 0x10 - 0x1F 0x0000, 0x0000, 0x0000, SDLK_PAUSE, SDLK_SCROLLOCK, SDLK_SYSREQ, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_ESCAPE, 0x0000, 0x0000, 0x0000, 0x0000, // 0x20 - 0x2F SDLK_COMPOSE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x30 - 0x3F [Japanese keys] 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x40 - 0x4F [unused] 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x50 - 0x5F SDLK_HOME, SDLK_LEFT, SDLK_UP, SDLK_RIGHT, SDLK_DOWN, SDLK_PAGEUP, SDLK_PAGEDOWN, SDLK_END, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x60 - 0x6F 0x0000, SDLK_PRINT, 0x0000, SDLK_INSERT, SDLK_UNDO, 0x0000, 0x0000, SDLK_MENU, 0x0000, SDLK_HELP, SDLK_BREAK, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x70 - 0x7F [mostly unused, except for Alt Gr and Num Lock] 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_MODE, SDLK_NUMLOCK, // 0x80 - 0x8F [mostly unused, except for some numeric keypad keys] SDLK_KP5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_KP_ENTER, 0x0000, 0x0000, // 0x90 - 0x9F 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_KP7, SDLK_KP4, SDLK_KP8, SDLK_KP6, SDLK_KP2, SDLK_KP9, SDLK_KP3, SDLK_KP1, SDLK_KP5, SDLK_KP0, SDLK_KP_PERIOD, // 0xA0 - 0xAF 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_KP_MULTIPLY, SDLK_KP_PLUS, 0x0000, SDLK_KP_MINUS, SDLK_KP_PERIOD, SDLK_KP_DIVIDE, // 0xB0 - 0xBF SDLK_KP0, SDLK_KP1, SDLK_KP2, SDLK_KP3, SDLK_KP4, SDLK_KP5, SDLK_KP6, SDLK_KP7, SDLK_KP8, SDLK_KP9, 0x0000, 0x0000, 0x0000, SDLK_KP_EQUALS, SDLK_F1, SDLK_F2, // 0xC0 - 0xCF SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12, SDLK_F13, SDLK_F14, SDLK_F15, 0x0000, 0x0000, 0x0000, // 0xD0 - 0xDF [L* and R* function keys] 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0xE0 - 0xEF 0x0000, SDLK_LSHIFT, SDLK_RSHIFT, SDLK_LCTRL, SDLK_RCTRL, SDLK_CAPSLOCK, 0x0000, SDLK_LMETA, SDLK_RMETA, SDLK_LALT, SDLK_RALT, SDLK_LSUPER, SDLK_RSUPER, 0x0000, 0x0000, 0x0000, // 0xF0 - 0xFF [mostly unused, except for Delete] 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_DELETE, }; unsigned short sdl_key = gdk_to_sdl_table[gdk_key & 0xFF]; if (sdl_key == 0) { // Unhandled GDK key. fprintf(stderr, "Unhandled GDK key: 0x%04X (%s)", gdk_key, gdk_keyval_name(gdk_key)); return 0; } // ignore pause and screenshot hotkeys since they is handled by GTK+ as accelerators if (sdl_key == Hotkeys[HK_PAUSE] || sdl_key == Hotkeys[HK_SCREENSHOT] || sdl_key == Hotkeys[HK_SAVE_STATE] || sdl_key == Hotkeys[HK_LOAD_STATE]) return 0; return sdl_key; } // Function adapted from Gens/GS (source/gens/input/input_sdl.c) gint convertKeypress(GtkWidget *grab, GdkEventKey *event, gpointer user_data) { SDL_Event sdlev; int keystate; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_Keycode sdlkey; #else SDLKey sdlkey; #endif switch (event->type) { case GDK_KEY_PRESS: sdlev.type = SDL_KEYDOWN; sdlev.key.state = SDL_PRESSED; keystate = 1; break; case GDK_KEY_RELEASE: sdlev.type = SDL_KEYUP; sdlev.key.state = SDL_RELEASED; keystate = 0; break; default: fprintf(stderr, "Unhandled GDK event type: %d", event->type); return FALSE; } // Convert this keypress from GDK to SDL. #if SDL_VERSION_ATLEAST(2, 0, 0) sdlkey = GDKToSDLKeyval(event->keyval); #else sdlkey = (SDLKey)GDKToSDLKeyval(event->keyval); #endif // Create an SDL event from the keypress. sdlev.key.keysym.sym = sdlkey; if (sdlkey != 0) { SDL_PushEvent(&sdlev); // Only let the emulator handle the key event if this window has the input focus. if(keystate == 0 || gtk_window_is_active(GTK_WINDOW(MainWindow))) { #if SDL_VERSION_ATLEAST(2, 0, 0) // Not sure how to do this yet with SDL 2.0 // TODO - SDL 2.0 //SDL_GetKeyboardState(NULL)[SDL_GetScancodeFromKey(sdlkey)] = keystate; #else SDL_GetKeyState(NULL)[sdlkey] = keystate; #endif } } // Allow GTK+ to process this key. return FALSE; } // Our menu, in the XML markup format used by GtkUIManager static char* menuXml = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " #ifdef _S9XLUA_H " " #endif " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; // Menu items, as an array of GtkActionEntry structures that define each item static GtkActionEntry normal_entries[] = { {"FileMenuAction", NULL, "_File"}, {"OpenRomAction", GTK_STOCK_OPEN, "_Open ROM", "O", NULL, G_CALLBACK(loadGame)}, {"CloseRomAction", GTK_STOCK_CLOSE, "_Close ROM", "C", NULL, G_CALLBACK(closeGame)}, {"PlayNsfAction", GTK_STOCK_OPEN, "_Play NSF", "N", NULL, G_CALLBACK(loadNSF)}, {"LoadStateFromAction", GTK_STOCK_OPEN, "Load State _From", "", NULL, G_CALLBACK(loadStateFrom)}, {"SaveStateAsAction", GTK_STOCK_SAVE_AS, "Save State _As", NULL, NULL, G_CALLBACK(saveStateAs)}, {"QuickLoadAction", "go-jump", "Quick _Load", "F7", NULL, G_CALLBACK(quickLoad)}, {"QuickSaveAction", GTK_STOCK_SAVE, "Qu_ick Save", "F5", NULL, G_CALLBACK(quickSave)}, {"ChangeStateMenuAction", NULL, "C_hange State"}, #ifdef _S9XLUA_H {"LoadLuaScriptAction", GTK_STOCK_OPEN, "Load L_ua Script", "", NULL, G_CALLBACK(loadLua)}, #endif {"ScreenshotAction", NULL, "_Screenshot", "F12", NULL, G_CALLBACK(FCEUI_SaveSnapshot)}, {"QuitAction", GTK_STOCK_QUIT, "_Quit", "Q", NULL, G_CALLBACK(quit)}, {"OptionsMenuAction", NULL, "_Options"}, #if GTK_MAJOR_VERSION == 3 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24) {"GamepadConfigAction", "input-gaming", "_Gamepad Config", NULL, NULL, G_CALLBACK(openGamepadConfig)}, #endif {"HotkeyConfigAction", "input", "_Hotkey Config", NULL, NULL, G_CALLBACK(openHotkeyConfig)}, {"SoundConfigAction", "audio-x-generic", "_Sound Config", NULL, NULL, G_CALLBACK(openSoundConfig)}, {"VideoConfigAction", "video-display", "_Video Config", NULL, NULL, G_CALLBACK(openVideoConfig)}, {"PaletteConfigAction", GTK_STOCK_SELECT_COLOR, "_Palette Config", NULL, NULL, G_CALLBACK(openPaletteConfig)}, {"NetworkConfigAction", GTK_STOCK_NETWORK, "_Network Config", NULL, NULL, G_CALLBACK(openNetworkConfig)}, {"FullscreenAction", GTK_STOCK_FULLSCREEN, "_Fullscreen", "Return", NULL, G_CALLBACK(enableFullscreen)}, {"EmulationMenuAction", NULL, "_Emulation"}, {"PowerAction", NULL, "P_ower", NULL, NULL, G_CALLBACK(FCEUI_PowerNES)}, {"SoftResetAction", GTK_STOCK_REFRESH, "_Soft Reset", NULL, NULL, G_CALLBACK(emuReset)}, {"ResetAction", GTK_STOCK_REFRESH, "_Reset", NULL, NULL, G_CALLBACK(hardReset)}, {"PauseToggleAction", GTK_STOCK_MEDIA_PAUSE, "_Pause", "Pause", NULL, G_CALLBACK(togglePause)}, {"FdsMenuAction", GTK_STOCK_FLOPPY, "_FDS"}, {"SwitchDiskAction", "go-jump", "_Switch Disk", NULL, NULL, G_CALLBACK(FCEU_FDSSelect)}, {"EjectDiskAction", "media-eject", "_Eject Disk", NULL, NULL, G_CALLBACK(FCEU_FDSInsert)}, {"LoadBiosAction", GTK_STOCK_OPEN, "Load _BIOS File", "", NULL, G_CALLBACK(loadFdsBios)}, {"LoadGameGenieAction", GTK_STOCK_OPEN, "_Load Game Genie ROM", "", NULL, G_CALLBACK(loadGameGenie)}, {"InsertCoinAction", NULL, "_Insert Coin", NULL, NULL, G_CALLBACK(FCEUI_VSUniCoin)}, {"ToolsMenuAction", NULL, "_Tools"}, {"CheatsAction", "cheats-win", "_Cheats...", NULL, NULL, G_CALLBACK(openCheatsWindow)}, {"MovieMenuAction", NULL, "_Movie"}, {"OpenMovieAction", GTK_STOCK_OPEN, "_Open", "F7", NULL, G_CALLBACK(loadMovie)}, {"StopMovieAction", GTK_STOCK_MEDIA_STOP, "S_top", NULL, NULL, G_CALLBACK(FCEUI_StopMovie)}, {"RecordMovieAction", GTK_STOCK_MEDIA_RECORD, "_Record", "F5", NULL, G_CALLBACK(recordMovie)}, {"RecordMovieAsAction", NULL, "Record _As", NULL, NULL, G_CALLBACK(recordMovieAs)}, {"HelpMenuAction", NULL, "_Help"}, {"AboutAction", GTK_STOCK_ABOUT, "_About", NULL, NULL, G_CALLBACK(openAbout)}, }; // Menu items with a check box that can be toggled on or off static GtkToggleActionEntry toggle_entries[] = { {"GameGenieToggleAction", NULL, "Enable Game _Genie", NULL, NULL, G_CALLBACK(toggleGameGenie), FALSE}, {"AutoResumeAction", NULL, "Auto-Resume Play", NULL, NULL, G_CALLBACK(toggleAutoResume), FALSE}, {"ToggleMenuAction", NULL, "Toggle Menubar (alt)", NULL, NULL, G_CALLBACK(toggleMenuToggling), FALSE}, }; // Menu items for selecting a save state slot using radio buttons static GtkRadioActionEntry radio_entries[] = { {"State0Action", NULL, "0", NULL, NULL, 0}, {"State1Action", NULL, "1", NULL, NULL, 1}, {"State2Action", NULL, "2", NULL, NULL, 2}, {"State3Action", NULL, "3", NULL, NULL, 3}, {"State4Action", NULL, "4", NULL, NULL, 4}, {"State5Action", NULL, "5", NULL, NULL, 5}, {"State6Action", NULL, "6", NULL, NULL, 6}, {"State7Action", NULL, "7", NULL, NULL, 7}, {"State8Action", NULL, "8", NULL, NULL, 8}, {"State9Action", NULL, "9", NULL, NULL, 9}, }; static GtkWidget* CreateMenubar( GtkWidget* window) { GtkUIManager *ui_manager; GtkActionGroup *action_group; GtkAccelGroup* accel_group; GError *error = NULL; GtkAction* state; /* Make an UIManager (which makes a menubar). */ ui_manager = gtk_ui_manager_new (); /* Add the menu items to the UIManager as a GtkActionGroup. */ action_group = gtk_action_group_new ("MenubarActions"); gtk_action_group_add_actions (action_group, normal_entries, G_N_ELEMENTS (normal_entries), NULL); gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), NULL); gtk_action_group_add_radio_actions (action_group, radio_entries, G_N_ELEMENTS (radio_entries), 0, G_CALLBACK(changeState), NULL); gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); /* Read the menu layout from the XML markup. */ gtk_ui_manager_add_ui_from_string (ui_manager, menuXml, -1, &error); if (error) { fprintf (stderr, "Unable to create menu bar: %s\n", error->message); g_error_free (error); } /* Attach the new accelerator group to the window. */ accel_group = gtk_ui_manager_get_accel_group (ui_manager); gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); /* Get an action that can be used to change the active state slot selection. */ state = gtk_action_group_get_action (action_group, "State0Action"); if (state && GTK_IS_RADIO_ACTION (state)) stateSlot = GTK_RADIO_ACTION (state); /* Set the autoResume checkbox */ GtkCheckMenuItem* auto_resume_chk = (GtkCheckMenuItem*) gtk_ui_manager_get_widget ( ui_manager, "/Menubar/OptionsMenuAction/AutoResumeAction"); gtk_check_menu_item_set_active (auto_resume_chk, (bool)AutoResumePlay); // Sync State of GameGenie Toggle Action to Startup Configuration int gameGenieEnabled=0; g_config->getOption("SDL.GameGenie", &gameGenieEnabled); if ( gameGenieEnabled ) { state = gtk_action_group_get_action (action_group, "GameGenieToggleAction"); if ( state ){ gtk_action_activate( state ); } } enableGameGenie(gameGenieEnabled); /* Finally, return the actual menu bar created by the UIManager. */ return gtk_ui_manager_get_widget (ui_manager, "/Menubar"); } void pushOutputToGTK(const char* str) { // we don't really do anything with the output right now return; } void showGui(bool b) { if(b) gtk_widget_show_all(MainWindow); else gtk_widget_hide(MainWindow); } gint handleKeyRelease(GtkWidget* w, GdkEvent* event, gpointer cb_data) { if(menuTogglingEnabled) { static bool menuShown = true; if(((GdkEventKey*)event)->keyval == GDK_KEY_Alt_L || ((GdkEventKey*)event)->keyval == GDK_KEY_Alt_R) { if(menuShown) { gtk_widget_hide(Menubar); menuShown = false; } else { gtk_widget_show(Menubar); menuShown = true; } } } return 0; }; int GtkMouseData[3] = {0,0,0}; gint handleMouseClick(GtkWidget* widget, GdkEvent *event, gpointer callback_data) { GtkMouseData[0] = ((GdkEventButton*)event)->x; GtkMouseData[1] = ((GdkEventButton*)event)->y; int button = ((GdkEventButton*)event)->button; if(!(((GdkEventButton*)event)->type == GDK_BUTTON_PRESS)) GtkMouseData[2] = 0; else { if(button == 1) GtkMouseData[2] |= 0x1; if(button == 3) GtkMouseData[2] |= 0x3; } // this doesn't work because we poll the mouse position rather // than use events /* SDL_Event sdlev; sdlev.type = SDL_MOUSEBUTTONDOWN; if(((GdkEventButton*)event)->type == GDK_BUTTON_PRESS) sdlev.button.type = SDL_MOUSEBUTTONDOWN; else sdlev.button.type = SDL_MOUSEBUTTONUP; sdlev.button.button = ((GdkEventButton*)event)->button; sdlev.button.state = ((GdkEventButton*)event)->state; sdlev.button.x = ((GdkEventButton*)event)->x; sdlev.button.y = ((GdkEventButton*)event)->y; SDL_PushEvent(&sdlev); */ return 0; } // NES resolution = 256x240 const int NES_WIDTH=256; const int NES_HEIGHT=240; void handle_resize(GtkWindow* win, GdkEvent* event, gpointer data) { // TODO this is a stub atm // this should handle resizing so the emulation takes up as much // of the GTK window as possible // get new window width/height int width, height; width = event->configure.width; height = event->configure.height; printf("DEBUG: new window size: %dx%d\n", width, height); // get width/height multipliers double xscale = width / (double)NES_WIDTH; double yscale = height / (double)NES_HEIGHT; // TODO check KeepRatio (where is this) // do this to keep aspect ratio if(xscale > yscale) xscale = yscale; if(yscale > xscale) yscale = xscale; //TODO if openGL make these integers g_config->setOption("SDL.XScale", xscale); g_config->setOption("SDL.YScale", yscale); //gtk_widget_realize(evbox); flushGtkEvents(); if(GameInfo != 0) { KillVideo(); InitVideo(GameInfo); } gtk_widget_set_size_request(evbox, (int)(NES_WIDTH*xscale), (int)(NES_HEIGHT*yscale)); // Currently unused; unsure why /* GdkColor black; black.red = 0; black.green = 0; black.blue = 0; gtk_widget_modify_bg(GTK_WIDGET(win), GTK_STATE_NORMAL, &black);*/ printf("DEBUG: new xscale: %f yscale: %f\n", xscale, yscale); return; } int InitGTKSubsystem(int argc, char** argv) { GtkWidget* vbox; MainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_events(GTK_WIDGET(MainWindow), GDK_KEY_RELEASE_MASK); // gtk_window_set_policy (GTK_WINDOW (MainWindow), FALSE, FALSE, TRUE); gtk_window_set_resizable(GTK_WINDOW(MainWindow), TRUE); gtk_window_set_title(GTK_WINDOW(MainWindow), FCEU_NAME_AND_VERSION); gtk_window_set_default_size(GTK_WINDOW(MainWindow), NES_WIDTH, NES_HEIGHT); GdkPixbuf* icon = gdk_pixbuf_new_from_xpm_data(icon_xpm); gtk_window_set_default_icon(icon); gtk_window_set_icon(GTK_WINDOW(MainWindow), icon); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(MainWindow), vbox); Menubar = CreateMenubar(MainWindow); gtk_box_pack_start (GTK_BOX(vbox), Menubar, FALSE, TRUE, 0); // PRG: this code here is the the windowID "hack" to render SDL // in a GTK window. however, I can't get it to work right now // so i'm commenting it out and haivng a seperate GTK2 window with // controls // 12/21/09 // --- // uncommented and fixed by Bryan Cain // 1/24/11 // // prg - Bryan Cain, you are the man! evbox = gtk_event_box_new(); gtk_box_pack_start (GTK_BOX(vbox), evbox, TRUE, TRUE, 0); double xscale, yscale; g_config->getOption("SDL.XScale", &xscale); g_config->getOption("SDL.YScale", &yscale); gtk_widget_set_size_request(evbox, NES_WIDTH*xscale, NES_HEIGHT*yscale); gtk_widget_realize(evbox); gtk_widget_show(evbox); gtk_widget_show_all(vbox); GdkColor bg = {0, 0, 0, 0}; gtk_widget_modify_bg(evbox, GTK_STATE_NORMAL, &bg); // set up keypress "snooper" to convert GDK keypress events into SDL keypresses gtk_key_snooper_install(convertKeypress, NULL); // pass along mouse data from GTK to SDL g_signal_connect(G_OBJECT(evbox), "button-press-event", G_CALLBACK(handleMouseClick), NULL); g_signal_connect(G_OBJECT(evbox), "button-release-event", G_CALLBACK(handleMouseClick), NULL); g_signal_connect(G_OBJECT(MainWindow), "key-release-event", G_CALLBACK(handleKeyRelease), NULL); // signal handlers g_signal_connect(MainWindow, "delete-event", quit, NULL); g_signal_connect(MainWindow, "destroy-event", quit, NULL); // resize handler // g_signal_connect(MainWindow, "configure-event", G_CALLBACK(handle_resize), NULL); gtk_widget_show_all(MainWindow); GtkRequisition req; gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); gtkIsStarted = true; return 0; }