#include #include #include #include "../../types.h" #include "../../fceu.h" #include "../../driver.h" #include "../../version.h" #include "../common/configSys.h" #include "sdl.h" #include "gui.h" #include "dface.h" #include "input.h" #ifdef _S9XLUA_H #include "../../fceulua.h" #endif void toggleSound(GtkWidget* check, gpointer data); extern Config *g_config; GtkWidget* MainWindow = NULL; GtkWidget* padNoCombo; // This function configures a single button on a gamepad int configGamepadButton(GtkButton* button, gpointer p) { int x = GPOINTER_TO_INT(p); int padNo = 0; char* padStr = gtk_combo_box_get_active_text(GTK_COMBO_BOX(padNoCombo)); if(!strcmp(padStr, "1")) padNo = 0; if(!strcmp(padStr, "2")) padNo = 1; if(!strcmp(padStr, "3")) padNo = 2; if(!strcmp(padStr, "4")) padNo = 3; char buf[256]; std::string prefix; ButtonConfigBegin(); snprintf(buf, 256, "SDL.Input.GamePad.%d", padNo); prefix = buf; ConfigButton((char*)GamePadNames[x], &GamePadConfig[padNo][x]); g_config->setOption(prefix + GamePadNames[x], GamePadConfig[padNo][x].ButtonNum[0]); 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][0].DeviceNum[0]); ButtonConfigEnd(); return 0; } // creates and opens the gamepad config window void openGamepadConfig() { GtkWidget* win; GtkWidget* vbox; GtkWidget* hboxPadNo; GtkWidget* padNoLabel; GtkWidget* buttons[10]; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), "Gamepad Config"); gtk_widget_set_size_request(win, 250, 500); vbox = gtk_vbox_new(TRUE, 2); hboxPadNo = gtk_hbox_new(TRUE, 1); padNoLabel = gtk_label_new("Gamepad Number:"); padNoCombo = gtk_combo_box_new_text(); gtk_combo_box_append_text(GTK_COMBO_BOX(padNoCombo), "1"); gtk_combo_box_append_text(GTK_COMBO_BOX(padNoCombo), "2"); gtk_combo_box_append_text(GTK_COMBO_BOX(padNoCombo), "3"); gtk_combo_box_append_text(GTK_COMBO_BOX(padNoCombo), "4"); gtk_combo_box_set_active(GTK_COMBO_BOX(padNoCombo), 0); gtk_box_pack_start(GTK_BOX(hboxPadNo), padNoLabel, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hboxPadNo), padNoCombo, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hboxPadNo, TRUE, TRUE, 5); // create gamepad buttons for(int i=0; i<10; i++) { buttons[i] = gtk_button_new_with_label(GamePadNames[i]); gtk_box_pack_start(GTK_BOX(vbox), buttons[i], TRUE, TRUE, 2); gtk_signal_connect(GTK_OBJECT(buttons[i]), "clicked", G_CALLBACK(configGamepadButton), GINT_TO_POINTER(i)); } gtk_container_add(GTK_CONTAINER(win), vbox); 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.SoundBufSize", x); // reset sound subsystem for changes to take effect KillSound(); InitSound(); return false; } void setRate(GtkWidget* w, gpointer p) { char* str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); g_config->setOption("SDL.SoundRate", atoi(str)); // reset sound subsystem for changes to take effect KillSound(); InitSound(); return; } void setQuality(GtkWidget* w, gpointer p) { char* str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); if(!strcmp(str, "High")) g_config->setOption("SDL.SoundQuality", 1); if(!strcmp(str, "Low")) g_config->setOption("SDL.SoundQuality", 0); // reset sound subsystem for changes to take effect KillSound(); InitSound(); return; } void setScaler(GtkWidget* w, gpointer p) { int x = gtk_combo_box_get_active(GTK_COMBO_BOX(w)); g_config->setOption("SDL.SpecialFilter", x); } void openVideoConfig() { GtkWidget* win; GtkWidget* vbox; GtkWidget* hbox1; GtkWidget* scalerLbl; GtkWidget* scalerCombo; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), "Video Prefernces"); gtk_widget_set_size_request(win, 250, 400); vbox = gtk_vbox_new(FALSE, 3); // scalar widgets hbox1 = gtk_hbox_new(FALSE, 3); scalerLbl = gtk_label_new("Special Scaler: "); scalerCombo = gtk_combo_box_new_text(); gtk_combo_box_append_text(GTK_COMBO_BOX(scalerCombo), "none"); gtk_combo_box_append_text(GTK_COMBO_BOX(scalerCombo), "hq2x"); gtk_combo_box_append_text(GTK_COMBO_BOX(scalerCombo), "scale2x"); gtk_combo_box_append_text(GTK_COMBO_BOX(scalerCombo), "hq3x"); gtk_combo_box_append_text(GTK_COMBO_BOX(scalerCombo), "scale3x"); // sync with cfg int buf; g_config->getOption("SDL.SpecialFilter", &buf); gtk_combo_box_set_active(GTK_COMBO_BOX(scalerCombo), buf); g_signal_connect(GTK_OBJECT(scalerCombo), "changed", G_CALLBACK(setScaler), NULL); gtk_box_pack_start(GTK_BOX(hbox1), scalerLbl, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(hbox1), scalerCombo, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 2); gtk_container_add(GTK_CONTAINER(win), vbox); gtk_widget_show_all(win); return; } void openSoundConfig() { GtkWidget* win; GtkWidget* vbox; GtkWidget* soundChk; GtkWidget* hbox1; GtkWidget* qualityCombo; GtkWidget* qualityLbl; GtkWidget* hbox2; GtkWidget* rateCombo; GtkWidget* rateLbl; GtkWidget* hbox3; GtkWidget* bufferLbl; GtkWidget* bufferHscale; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), "Sound Preferences"); vbox = gtk_vbox_new(False, 2); gtk_widget_set_size_request(win, 350, 250); // sound enable check soundChk = gtk_check_button_new_with_label("Enable sound"); // sync with cfg int cfgBuf; g_config->getOption("SDL.Sound", &cfgBuf); if(cfgBuf) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(soundChk), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(soundChk), FALSE); gtk_signal_connect(GTK_OBJECT(soundChk), "clicked", G_CALLBACK(toggleSound), NULL); // sound quality combo box hbox1 = gtk_hbox_new(FALSE, 3); qualityCombo = gtk_combo_box_new_text(); gtk_combo_box_append_text(GTK_COMBO_BOX(qualityCombo), "Low"); gtk_combo_box_append_text(GTK_COMBO_BOX(qualityCombo), "High"); // sync widget with cfg g_config->getOption("SDL.SoundQuality", &cfgBuf); if(cfgBuf) gtk_combo_box_set_active(GTK_COMBO_BOX(qualityCombo), 1); else gtk_combo_box_set_active(GTK_COMBO_BOX(qualityCombo), 0); g_signal_connect(qualityCombo, "changed", G_CALLBACK(setQuality), NULL); qualityLbl = gtk_label_new("Quality: "); gtk_box_pack_start(GTK_BOX(hbox1), qualityLbl, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(hbox1), qualityCombo, FALSE, FALSE, 3); // sound rate widgets hbox2 = gtk_hbox_new(FALSE, 3); rateCombo = gtk_combo_box_new_text(); const int rates[5] = {11025, 22050, 44100, 48000, 96000}; char buf[8]; for(int i=0; i<5;i++) { sprintf(buf, "%d", rates[i]); gtk_combo_box_append_text(GTK_COMBO_BOX(rateCombo), buf); } // sync widget with cfg g_config->getOption("SDL.SoundRate", &cfgBuf); for(int i=0; i<5; i++) if(cfgBuf == 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, 3); gtk_box_pack_start(GTK_BOX(hbox2), rateCombo, FALSE, FALSE, 3); hbox3 = gtk_hbox_new(FALSE, 2); bufferHscale = gtk_hscale_new_with_range(15, 200, 2); bufferLbl = gtk_label_new("Buffer size (ms): "); gtk_box_pack_start(GTK_BOX(hbox3), bufferLbl, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(hbox3), bufferHscale, TRUE, TRUE, 2); // sync widget with cfg g_config->getOption("SDL.SoundBufSize", &cfgBuf); gtk_range_set_value(GTK_RANGE(bufferHscale), cfgBuf); g_signal_connect(bufferHscale, "button-release-event", G_CALLBACK(setBufSize), NULL); // packing some boxes gtk_box_pack_start(GTK_BOX(vbox), soundChk, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox3, FALSE, FALSE, 2); gtk_container_add(GTK_CONTAINER(win), vbox); gtk_widget_show_all(win); return; } void quit () { FCEUI_Kill(); SDL_Quit(); gtk_main_quit(); exit(0); } GtkWidget* aboutDialog; inline void quitAbout(void) { gtk_widget_hide_all(aboutDialog);} void showAbout () { aboutDialog = gtk_about_dialog_new (); gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(aboutDialog), "About fceuX"); gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(aboutDialog), "fceuX"); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(aboutDialog), FCEU_VERSION_STRING); gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(aboutDialog), "GPL-2; See COPYING"); gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(aboutDialog), "http://fceux.com"); gtk_widget_show_all(GTK_WIDGET(aboutDialog)); g_signal_connect(G_OBJECT(aboutDialog), "delete-event", quitAbout, NULL); } void toggleSound(GtkWidget* check, gpointer data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) { g_config->setOption("SDL.Sound", 1); InitSound(); } else { g_config->setOption("SDL.Sound", 0); KillSound(); } } void emuReset () { ResetNES(); } void emuPause () { FCEUI_SetEmulationPaused(1); } void emuResume () { FCEUI_SetEmulationPaused(0); } void enableFullscreen () { ToggleFS(); } #ifdef _S9XLUA_H void loadLua () { GtkWidget* fileChooser; 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); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); FCEU_LoadLuaCode(filename); g_free(filename); } gtk_widget_destroy (fileChooser); } #endif void loadGame () { GtkWidget* fileChooser; 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); if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) { char* filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); LoadGame(filename); g_free(filename); } gtk_widget_destroy (fileChooser); } void closeGame() { CloseGame(); } // this is not used currently; it is used in rendering sdl in // the gtk window which is broken gint configureEvent (GtkWidget* widget, GdkEventConfigure* event) { //neccessary for SDL rendering on gtk win (i think?) //s_screen = SDL_SetVideoMode(event->width, event->height, 0, 0); return TRUE; } void saveStateAs() { GtkWidget* fileChooser; 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_OPEN, GTK_RESPONSE_ACCEPT, NULL); 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_free(filename); } gtk_widget_destroy (fileChooser); } void loadStateFrom() { GtkWidget* fileChooser; 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); 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_free(filename); } gtk_widget_destroy (fileChooser); } /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */ static GtkItemFactoryEntry menu_items[] = { { "/_File", NULL, NULL, 0, "" }, //{ "/File/_New", "N", NULL, 0, "", GTK_STOCK_NEW }, { "/File/_Open ROM", "O", loadGame, 0, "", GTK_STOCK_OPEN }, { "/File/_Close ROM", "C", closeGame, 0, "", GTK_STOCK_CLOSE }, // { "/File/Save _As", NULL, NULL, 0, "" }, { "/File/sep1", NULL, NULL, 0, "" }, { "/File/Savestate", NULL, NULL, 0, "" }, { "/File/Savestate/Load State _From", NULL, loadStateFrom, 0, ""}, { "/File/Savestate/Save State _As", NULL, saveStateAs, 0, ""}, #ifdef _S9XLUA_H { "/File/Load _Lua Script", NULL, loadLua, 0, ""}, #endif { "/File/_Screenshot", "F12", FCEUI_SaveSnapshot, 0, ""}, { "/File/_Quit", "Q", quit, 0, "", GTK_STOCK_QUIT }, { "/_Options", NULL, NULL, 0, "" }, { "/_Emulator", NULL, NULL, 0, "" }, { "/Emulator/_Reset", NULL, emuReset, 0, ""}, { "/Emulator/_Pause", NULL, emuPause, 0, ""}, { "/Emulator/R_esume", NULL, emuResume, 0, ""}, { "/Options/_Gamepad Config", NULL , openGamepadConfig, 0, "", GTK_STOCK_PREFERENCES }, { "/Options/_Sound Config", NULL , openSoundConfig, 0, "" }, { "/Options/_Vound Config", NULL , openVideoConfig, 0, "" }, { "/Options/tear", NULL, NULL, 0, "" }, { "/Options/_Fullscreen", NULL, enableFullscreen, 0, "" }, { "/_Help", NULL, NULL, 0, "" }, { "/_Help/About", NULL, showAbout, 0, "" }, }; static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); static GtkWidget* CreateMenubar( GtkWidget* window) { GtkItemFactory *item_factory; GtkAccelGroup *accel_group; /* Make an accelerator group (shortcut keys) */ accel_group = gtk_accel_group_new (); /* Make an ItemFactory (that makes a menubar) */ item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "
", accel_group); /* This function generates the menu items. Pass the item factory, the number of items in the array, the array itself, and any callback data for the the menu items. */ gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); /* Attach the new accelerator group to the window. */ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); /* Finally, return the actual menu bar created by the item factory. */ return gtk_item_factory_get_widget (item_factory, "
"); } int InitGTKSubsystem(int argc, char** argv) { //GtkWidget* MainWindow; GtkWidget* Menubar; GtkWidget* vbox; int xres, yres; g_config->getOption("SDL.XResolution", &xres); g_config->getOption("SDL.YResolution", &yres); gtk_init(&argc, &argv); MainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(MainWindow), "FceuX"); gtk_window_set_default_size(GTK_WINDOW(MainWindow), 359, 200); vbox = gtk_vbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(MainWindow), vbox); Menubar = CreateMenubar(MainWindow); //gtk_container_add(GTK_CONTAINER(vbox), Menubar); gtk_box_pack_start (GTK_BOX(vbox), Menubar, FALSE, TRUE, 0); // broken SDL embedding code //gtk_widget_set_usize(MainWindow, xres, yres); //gtk_widget_realize(MainWindow); // event handlers gtk_widget_add_events(MainWindow, GDK_BUTTON_PRESS_MASK); //gtk_signal_connect(GTK_OBJECT(MainWindow), "configure_event", // GTK_SIGNAL_FUNC(configureEvent), 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 /* GtkWidget* socket = gtk_socket_new(); gtk_widget_show (socket) ; gtk_container_add (GTK_CONTAINER(MainWindow), socket); gtk_widget_realize (socket); char SDL_windowhack[24]; sprintf(SDL_windowhack, "SDL_WINDOWID=%ld", (long int)gtk_socket_get_id (GTK_SOCKET(socket))); putenv(SDL_windowhack); // init SDL if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Couldn't init SDL: %s\n", SDL_GetError()); gtk_main_quit(); } // test rendering //screen = SDL_SetVideoMode(xres, yres, 0, 0); //hello = SDL_LoadBMP( "hello.bmp" ); */ // signal handlers g_signal_connect(G_OBJECT(MainWindow), "delete-event", quit, NULL); //g_signal_connect(G_OBJECT(MainWindow), "destroy-event", quit, NULL); //gtk_idle_add(mainLoop, MainWindow); gtk_widget_set_size_request (GTK_WIDGET(MainWindow), 300, 200); gtk_widget_show_all(MainWindow); return 0; }