diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 38256b01..03331a32 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -399,6 +399,7 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/debugger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/glxwin.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/gui.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/GamePadConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/input.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/memview.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/sdl/ramwatch.cpp diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index efd908ee..41bc3460 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -637,6 +637,7 @@ void GamePadConfDialog_t::saveConfig(void) { lcl[portNum].btn[i].needsSave = 0; } + g_config->save(); } //---------------------------------------------------- void GamePadConfDialog_t::createNewProfile( const char *name ) diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index 5e2ea31d..886e08d4 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -438,6 +438,10 @@ int fceuWrapperInit( int argc, char *argv[] ) printf("Could not initialize SDL: %s.\n", SDL_GetError()); exit(-1); } + if ( SDL_SetHint( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1" ) == SDL_FALSE ) + { + printf("Error setting SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS\n"); + } // Initialize the configuration system g_config = InitConfig(); diff --git a/src/drivers/sdl/GamePadConf.cpp b/src/drivers/sdl/GamePadConf.cpp new file mode 100644 index 00000000..ea292b84 --- /dev/null +++ b/src/drivers/sdl/GamePadConf.cpp @@ -0,0 +1,835 @@ +// GamePadConf.cpp +#include +#include +#include + +#include + +#include "sdl/GamePadConf.h" +#include "sdl/main.h" +#include "sdl/dface.h" +#include "sdl/input.h" +#include "sdl/config.h" +#include "sdl/keyscan.h" +#include "sdl/sdl-joystick.h" +#include "sdl/gui.h" + +extern Config *g_config; +static GtkWidget *gamePadConfwin = NULL; +static GtkWidget *padNoCombo = NULL; +static GtkWidget *devSelCombo = NULL; +static GtkWidget *mapProfCombo = NULL; +static GtkWidget *buttonMappings[GAMEPAD_NUM_BUTTONS] = { NULL }; +static GtkWidget *buttonState[GAMEPAD_NUM_BUTTONS] = { NULL }; +static GtkWidget *guidLbl = NULL; +static GtkWidget *msgLbl = NULL; +static int buttonConfigStatus = 0; +static int padNo = 0; +static int numProfiles = 0; + +struct GamePadConfigLocalData_t +{ + std::string guid; + std::string profile; + + struct { + + char needsSave; + + } btn[GAMEPAD_NUM_BUTTONS]; + + GamePadConfigLocalData_t(void) + { + for (int i=0; i%s", + SDL_GetKeyName (GamePad[padNo].bmap[i]. + ButtonNum)); + } + else + sprintf (strBuf, "%s", ButtonName( &GamePad[padNo].bmap[i] ) ); + + if ( mappedKey != NULL ) + { + gtk_label_set_text (GTK_LABEL (mappedKey), strBuf); + gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE); + } + } +} + +static void loadMapList(void) +{ + const char *baseDir = FCEUI_GetBaseDirectory(); + const char *guid; + std::string path; + std::string prefix, mapName; + int devIdx = -1; + jsDev_t *js; + size_t i,n=0; + char stmp[256]; + struct dirent *d; + DIR *dir; + + devIdx = getDeviceIndex(); + + if ( devIdx < 0 ) + { + guid = "keyboard"; + } + else + { + js = getJoystickDevice( devIdx ); + + guid = js->getGUID(); + } + + if ( guid == NULL ) + { + return; + } + + path = std::string(baseDir) + "/input/" + std::string(guid); + + sprintf( stmp, "SDL.Input.GamePad.%u.", padNo ); + prefix = stmp; + + g_config->getOption(prefix + "Profile", &mapName ); + + gtk_combo_box_text_remove_all( GTK_COMBO_BOX_TEXT(mapProfCombo) ); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), "default"); + gtk_combo_box_set_active (GTK_COMBO_BOX (mapProfCombo), 0); + + numProfiles = n = 1; + dir = ::opendir( path.c_str() ); + + if ( dir == NULL ) return; + + d = ::readdir( dir ); + + while ( d != NULL ) + { + i=0; + while ( d->d_name[i] != 0 ) + { + if ( d->d_name[i] == '.' ) + { + break; + } + stmp[i] = d->d_name[i]; i++; + } + stmp[i] = 0; + + //printf("Directory: '%s'\n", stmp ); + + if ( i > 0 ) + { + if ( strcmp( stmp, "default" ) != 0 ) + { + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), stmp); + + if ( mapName.compare(stmp) == 0 ) + { + gtk_combo_box_set_active (GTK_COMBO_BOX (mapProfCombo), n); + } + n++; + } + } + + d = ::readdir( dir ); + } + numProfiles = n; + + ::closedir( dir ); + +} + +static void selPortChanged( GtkWidget * w, gpointer p ) +{ + padNo = + atoi (gtk_combo_box_text_get_active_text + (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1; + + GtkTreeModel *treeModel = gtk_combo_box_get_model( GTK_COMBO_BOX (devSelCombo) ); + GtkTreeIter iter; + gboolean iterValid; + + iterValid = gtk_tree_model_get_iter_first( treeModel, &iter ); + + while ( iterValid ) + { + GValue value; + + memset( &value, 0, sizeof(value)); + + gtk_tree_model_get_value (treeModel, &iter, 0, &value ); + + if ( G_IS_VALUE(&value) ) + { + if ( G_VALUE_TYPE(&value) == G_TYPE_STRING ) + { + int devIdx = -1; + const char *s = (const char *)g_value_peek_pointer( &value ); + + if ( isdigit( s[0] ) ) + { + devIdx = atoi(s); + } + if ( (devIdx >= 0) && (devIdx == GamePad[padNo].getDeviceIndex() ) ) + { + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (devSelCombo), &iter); + } + } + } + g_value_unset(&value); + + iterValid = gtk_tree_model_iter_next( treeModel, &iter ); + } + gtk_label_set_text( GTK_LABEL(guidLbl), GamePad[padNo].getGUID() ); + + loadMapList(); + + updateCntrlrDpy(); +} + +static void selInputDevice (GtkWidget * w, gpointer p) +{ + //std::string s = "SDL.Input."; + int devIdx = -1; + jsDev_t *js; + + if ( (padNoCombo == NULL) ) + { + return; + } + + devIdx = getDeviceIndex(); + + js = getJoystickDevice( devIdx ); + + if ( js != NULL ) + { + if ( js->isConnected() ) + { + gtk_label_set_text( GTK_LABEL(guidLbl), js->getGUID() ); + } + } + else + { + gtk_label_set_text( GTK_LABEL(guidLbl), "keyboard" ); + } + GamePad[padNo].setDeviceIndex( devIdx ); + + lcl[padNo].guid.assign( GamePad[padNo].getGUID() ); + lcl[padNo].profile.assign("default"); + + loadMapList(); + + updateCntrlrDpy(); + + return; +} + +static void saveConfig(void) +{ + int i; + char stmp[256]; + std::string prefix, mapName; + + sprintf( stmp, "SDL.Input.GamePad.%u.", padNo ); + prefix = stmp; + + mapName.assign( gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) ) ); + + g_config->setOption(prefix + "DeviceGUID", GamePad[padNo].getGUID() ); + g_config->setOption(prefix + "Profile" , mapName.c_str() ); + + for (i=0; isave(); +} + +static void createNewProfile( const char *name ) +{ + char stmp[256]; + //printf("Creating: %s \n", name ); + + GamePad[padNo].createProfile(name); + + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), name); + numProfiles++; + + gtk_combo_box_set_active( GTK_COMBO_BOX (mapProfCombo), numProfiles - 1 ); + + saveConfig(); + + sprintf( stmp, "Mapping Created: %s/%s \n", GamePad[padNo].getGUID(), name ); + gtk_label_set_text( GTK_LABEL(msgLbl), stmp ); + + loadMapList(); +} + +static void loadProfileCB (GtkButton * button, gpointer p) +{ + char stmp[256]; + int devIdx, ret; + std::string mapName; + + devIdx = getDeviceIndex(); + + mapName.assign( gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) ) ); + + GamePad[padNo].setDeviceIndex( devIdx ); + + if ( mapName.compare("default") == 0 ) + { + ret = GamePad[padNo].loadDefaults(); + } + else + { + ret = GamePad[padNo].loadProfile( mapName.c_str() ); + } + if ( ret == 0 ) + { + saveConfig(); + + sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Load Mapping: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() ); + } + gtk_label_set_text( GTK_LABEL(msgLbl), stmp ); + + updateCntrlrDpy(); +} + +static void saveProfileCB (GtkButton * button, gpointer p) +{ + int ret; + std::string mapName; + char stmp[256]; + + mapName.assign( gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) ) ); + + ret = GamePad[padNo].saveCurrentMapToFile( mapName.c_str() ); + + if ( ret == 0 ) + { + saveConfig(); + + sprintf( stmp, "Mapping Saved: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Save Mapping: %s \n", mapName.c_str() ); + } + gtk_label_set_text( GTK_LABEL(msgLbl), stmp ); +} + +static void newProfileCB (GtkButton * button, gpointer p) +{ + int ret; + GtkWidget *vbox, *lbl, *entry; + GtkWidget *dialog + = gtk_dialog_new_with_buttons ("New Profile", GTK_WINDOW(gamePadConfwin), + (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), + "_Cancel", GTK_RESPONSE_CANCEL, "_Create", GTK_RESPONSE_ACCEPT, NULL ); + + vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_box_set_homogeneous (GTK_BOX (vbox), FALSE); + + lbl = gtk_label_new("Specify New Profile Name"); + entry = gtk_entry_new(); + + gtk_box_pack_start (GTK_BOX (vbox), lbl, TRUE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 5); + + gtk_widget_show_all( dialog ); + + ret = gtk_dialog_run( GTK_DIALOG(dialog) ); + + if ( ret == GTK_RESPONSE_ACCEPT ) + { + printf("Text: '%s'\n", gtk_entry_get_text( GTK_ENTRY(entry) ) ); + + createNewProfile( gtk_entry_get_text( GTK_ENTRY(entry) ) ); + } + + gtk_widget_destroy( dialog ); +} + +static void deleteProfileCB (GtkButton * button, gpointer p) +{ + int ret; + std::string mapName; + char stmp[256]; + + mapName.assign( gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(mapProfCombo) ) ); + + ret = GamePad[padNo].deleteMapping( mapName.c_str() ); + + if ( ret == 0 ) + { + sprintf( stmp, "Mapping Deleted: %s/%s \n", GamePad[padNo].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Delete Mapping: %s \n", mapName.c_str() ); + } + gtk_label_set_text( GTK_LABEL(msgLbl), stmp ); + + loadMapList(); +} + +// This function configures a single button on a gamepad +static void clearGamepadButton (GtkButton * button, gpointer p) +{ + long int x = (long int)p; + + GamePad[padNo].bmap[x].ButtonNum = -1; + + gtk_label_set_text (GTK_LABEL (buttonMappings[x]), ""); + + lcl[padNo].btn[x].needsSave = 1; + + updateCntrlrDpy(); +} + +// This function configures a single button on a gamepad +static void configGamepadButton (GtkButton * button, gpointer p) +{ + gint x = ((gint) (glong) (p)); + //gint x = GPOINTER_TO_INT(p); + + 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; + + gtk_button_set_label (GTK_BUTTON (button), "Waiting"); + + buttonConfigStatus = 2; + + ButtonConfigBegin (); + + snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); + prefix = buf; + DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus ); + +// 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 (&GamePad[padNo].bmap[x])); + + if ( buttonMappings[x] != NULL ) + { + gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf); + } + lcl[padNo].btn[x].needsSave = 1; + + ButtonConfigEnd (); + + buttonConfigStatus = 1; + + gtk_button_set_label (GTK_BUTTON (button), "Change"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); + + return; +} + +//static void updateGamepadConfig (GtkWidget * w, gpointer p) +//{ +// updateCntrlrDpy(); +//} + +static gint timeout_callback (gpointer data) +{ + if ( gamePadConfwin == NULL ) + { + return FALSE; + } + + for (int i=0; isetStyleSheet("color: red;"); + //} + //else + //{ + // keyName[i]->setStyleSheet("color: black;"); + //} + } + + return TRUE; +} + +static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p) +{ + gtk_widget_destroy (w); + + gamePadConfwin = NULL; + padNoCombo = NULL; + + for (int i = 0; i < GAMEPAD_NUM_BUTTONS; i++) + { + buttonMappings[i] = NULL; + buttonState[i] = NULL; + } + buttonConfigStatus = 0; +} + +void openGamepadConfig (void) +{ + GtkWidget *win; + GtkWidget *mainVbox; + GtkWidget *hbox, /* *vbox,*/ *lbl; + GtkWidget *hboxPadNo; + GtkWidget *padNoLabel; + GtkWidget* devSelLabel, *devSelHbox; + GtkWidget *fourScoreChk; + GtkWidget *oppositeDirChk; + GtkWidget *buttonFrame; + GtkWidget *buttonTable; + GtkWidget *button; + GtkWidget *grid; + GtkWidget *mappingFrame; + char stmp[256]; + + if ( gamePadConfwin != NULL ) + { + return; + } + padNo = 0; + + win = gtk_dialog_new_with_buttons ("Controller Configuration", + GTK_WINDOW (MainWindow), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_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); + + mainVbox = gtk_dialog_get_content_area (GTK_DIALOG (win)); + gtk_box_set_homogeneous (GTK_BOX (mainVbox), FALSE); + + hboxPadNo = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_set_homogeneous( GTK_BOX(hboxPadNo), TRUE ); + 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 (selPortChanged), NULL); + + devSelHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_set_homogeneous( GTK_BOX(devSelHbox), TRUE ); + devSelLabel = gtk_label_new ("Device:"); + devSelCombo = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (devSelCombo), "Keyboard"); + + gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0); + + for (int i=0; iisConnected() ) + { + sprintf( stmp, "%i: %s", i, js->getName() ); + gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT (devSelCombo), stmp ); + } + } + } + gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0); + + { + GtkTreeModel *treeModel = gtk_combo_box_get_model( GTK_COMBO_BOX (devSelCombo) ); + GtkTreeIter iter; + gboolean iterValid; + + iterValid = gtk_tree_model_get_iter_first( treeModel, &iter ); + + while ( iterValid ) + { + GValue value; + + memset( &value, 0, sizeof(value)); + + gtk_tree_model_get_value (treeModel, &iter, 0, &value ); + + if ( G_IS_VALUE(&value) ) + { + if ( G_VALUE_TYPE(&value) == G_TYPE_STRING ) + { + int devIdx = -1; + const char *s = (const char *)g_value_peek_pointer( &value ); + + if ( isdigit( s[0] ) ) + { + devIdx = atoi(s); + } + if ( (devIdx >= 0) && (devIdx == GamePad[padNo].getDeviceIndex() ) ) + { + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (devSelCombo), &iter); + } + } + } + g_value_unset(&value); + + iterValid = gtk_tree_model_iter_next( treeModel, &iter ); + } + } + g_signal_connect (devSelCombo, "changed", G_CALLBACK (selInputDevice), 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 (mainVbox), hboxPadNo, FALSE, TRUE, 5); + //gtk_box_pack_start_defaults(GTK_BOX(mainVbox), typeCombo); + + gtk_box_pack_start (GTK_BOX (devSelHbox), devSelLabel, TRUE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (devSelHbox), devSelCombo, TRUE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (mainVbox), devSelHbox, TRUE, TRUE, 5); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_set_homogeneous( GTK_BOX(hbox), TRUE ); + lbl = gtk_label_new ("GUID:"); + guidLbl = gtk_label_new (""); + + gtk_box_pack_start (GTK_BOX (hbox), lbl, TRUE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (hbox), guidLbl, TRUE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (mainVbox), hbox, TRUE, TRUE, 5); + + gtk_label_set_text( GTK_LABEL(guidLbl), GamePad[padNo].getGUID() ); + + mappingFrame = gtk_frame_new ("Mapping Profile:"); + gtk_label_set_use_markup (GTK_LABEL + (gtk_frame_get_label_widget + (GTK_FRAME (mappingFrame))), TRUE); + gtk_box_pack_start (GTK_BOX (mainVbox), mappingFrame, FALSE, TRUE, 5); + grid = gtk_grid_new (); + gtk_grid_set_row_spacing (GTK_GRID (grid), 5); + gtk_grid_set_column_spacing (GTK_GRID (grid), 5); + gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE); + + //vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add (GTK_CONTAINER (mappingFrame), grid); + + mapProfCombo = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (mapProfCombo), "default"); + gtk_combo_box_set_active (GTK_COMBO_BOX (mapProfCombo), 0); + gtk_grid_attach (GTK_GRID (grid), mapProfCombo, 0, 0, 2, 1 ); + + button = gtk_button_new_with_label ("Load"); + gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1 ); + g_signal_connect (button, "clicked", G_CALLBACK (loadProfileCB), NULL ); + + button = gtk_button_new_with_label ("Save"); + gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1 ); + g_signal_connect (button, "clicked", G_CALLBACK (saveProfileCB), NULL ); + + button = gtk_button_new_with_label ("New"); + gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 1, 1 ); + g_signal_connect (button, "clicked", G_CALLBACK (newProfileCB), NULL ); + + button = gtk_button_new_with_label ("Delete"); + gtk_grid_attach (GTK_GRID (grid), button, 1, 2, 1, 1 ); + g_signal_connect (button, "clicked", G_CALLBACK (deleteProfileCB), NULL ); + + msgLbl = gtk_label_new(""); + gtk_grid_attach (GTK_GRID (grid), msgLbl, 0, 3, 2, 1 ); + + gtk_box_pack_start (GTK_BOX (mainVbox), fourScoreChk, FALSE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (mainVbox), oppositeDirChk, FALSE, TRUE, 5); + + + // create gamepad buttons + buttonFrame = gtk_frame_new ("Active Button Mappings:"); + gtk_label_set_use_markup (GTK_LABEL + (gtk_frame_get_label_widget + (GTK_FRAME (buttonFrame))), TRUE); + buttonTable = gtk_grid_new (); + gtk_container_add (GTK_CONTAINER (buttonFrame), buttonTable); + + for (int i = 0; i < 3; i++) + { + gtk_grid_insert_column (GTK_GRID (buttonTable), i); + } + gtk_grid_set_column_spacing (GTK_GRID (buttonTable), 5); + gtk_grid_set_column_homogeneous (GTK_GRID (buttonTable), TRUE); + gtk_grid_set_row_spacing (GTK_GRID (buttonTable), 3); + + for (int i = 0; i < GAMEPAD_NUM_BUTTONS; i++) + { + GtkWidget *buttonName = gtk_label_new (GamePadNames[i]); + GtkWidget *mappedKey = gtk_label_new (NULL); + GtkWidget *changeButton = gtk_toggle_button_new (); + GtkWidget *clearButton = gtk_button_new (); + char strBuf[128]; + + lbl = gtk_label_new ("State:"); + buttonState[i] = gtk_label_new (" F "); + + gtk_grid_insert_row (GTK_GRID (buttonTable), i); + + sprintf (strBuf, "%s:", GamePadNames[i]); + gtk_label_set_text (GTK_LABEL (buttonName), strBuf); + + gtk_button_set_label (GTK_BUTTON (changeButton), "Change"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (changeButton), + FALSE); + + gtk_button_set_label (GTK_BUTTON (clearButton), "Clear"); + + gtk_grid_attach (GTK_GRID (buttonTable), buttonName, 0, i, 1, 1); + gtk_grid_attach (GTK_GRID (buttonTable), mappedKey, 1, i, 1, 1); + gtk_grid_attach (GTK_GRID (buttonTable), lbl, 2, i, 1, 1); + gtk_grid_attach (GTK_GRID (buttonTable), buttonState[i], 3, i, 1, 1); + gtk_grid_attach (GTK_GRID (buttonTable), changeButton, 4, i, 1, 1); + gtk_grid_attach (GTK_GRID (buttonTable), clearButton, 5, i, 1, 1); + + g_signal_connect (changeButton, "clicked", + G_CALLBACK (configGamepadButton), + GINT_TO_POINTER (i)); + + g_signal_connect (clearButton, "clicked", + G_CALLBACK (clearGamepadButton), + GINT_TO_POINTER (i)); + + buttonMappings[i] = mappedKey; + } + + gtk_box_pack_start (GTK_BOX (mainVbox), buttonFrame, TRUE, TRUE, 5); + + g_signal_connect (win, "delete-event", G_CALLBACK (closeGamepadConfig), NULL); + g_signal_connect (win, "response", G_CALLBACK (closeGamepadConfig), NULL); + + gtk_widget_show_all (win); + + g_signal_connect (G_OBJECT (win), "key-press-event", + G_CALLBACK (convertKeypress), NULL); + g_signal_connect (G_OBJECT (win), "key-release-event", + G_CALLBACK (convertKeypress), NULL); + + buttonConfigStatus = 1; + + gamePadConfwin = win; + + loadMapList(); + + // display the button mappings for the currently selected configuration + updateCntrlrDpy(); + + g_timeout_add ( 100, timeout_callback, NULL ); + + return; +} + diff --git a/src/drivers/sdl/GamePadConf.h b/src/drivers/sdl/GamePadConf.h new file mode 100644 index 00000000..4a84e9f8 --- /dev/null +++ b/src/drivers/sdl/GamePadConf.h @@ -0,0 +1,4 @@ +// GamePadConf.h + +// creates and opens the gamepad config window (GTK) +void openGamepadConfig (void); diff --git a/src/drivers/sdl/config.cpp b/src/drivers/sdl/config.cpp index 8389d65a..f4631980 100644 --- a/src/drivers/sdl/config.cpp +++ b/src/drivers/sdl/config.cpp @@ -102,20 +102,20 @@ LoadCPalette(const std::string &file) static void CreateDirs(const std::string &dir) { - const char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"}; + const char *subs[9]={"fcs","snaps","gameinfo","sav","cheats","movies","input"}; std::string subdir; int x; #if defined(WIN32) || defined(NEED_MINGW_HACKS) mkdir(dir.c_str()); chmod(dir.c_str(), 755); - for(x = 0; x < 6; x++) { + for(x = 0; x < 7; x++) { subdir = dir + PSS + subs[x]; mkdir(subdir.c_str()); } #else mkdir(dir.c_str(), S_IRWXU); - for(x = 0; x < 6; x++) { + for(x = 0; x < 7; x++) { subdir = dir + PSS + subs[x]; mkdir(subdir.c_str(), S_IRWXU); } @@ -242,7 +242,7 @@ InitConfig() config->addOption("input4", "SDL.Input.3", "Gamepad.3"); // allow for input configuration - config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg); + //config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg); // display input config->addOption("inputdisplay", "SDL.InputDisplay", 0); @@ -286,8 +286,6 @@ InitConfig() //TODO implement this config->addOption("periodicsaves", "SDL.PeriodicSaves", 0); - - #ifdef _GTK char* home_dir = getenv("HOME"); // prefixed with _ because they are internal (not cli options) config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir); @@ -295,7 +293,9 @@ InitConfig() config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir); config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir); config->addOption("_lastloadlua", "SDL.LastLoadLua", ""); - #endif + + config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false); + config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false); // fcm -> fm2 conversion config->addOption("fcmconvert", "SDL.FCMConvert", ""); @@ -317,10 +317,8 @@ InitConfig() prefix = buf; config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]); - config->addOption(prefix + "DeviceNum", 0); - for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) { - config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]); - } + config->addOption(prefix + "DeviceGUID", ""); + config->addOption(prefix + "Profile" , ""); } // PowerPad 0 - 1 diff --git a/src/drivers/sdl/dface.h b/src/drivers/sdl/dface.h index f753f3ca..827bbfaf 100644 --- a/src/drivers/sdl/dface.h +++ b/src/drivers/sdl/dface.h @@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */ int InitJoysticks(void); int KillJoysticks(void); +int AddJoystick( int which ); +int RemoveJoystick( int which ); uint32 *GetJSOr(void); int InitVideo(FCEUGI *gi); diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 8feaacf9..4b7c2c03 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -19,6 +19,7 @@ #include "memview.h" #include "ramwatch.h" #include "debugger.h" +#include "sdl-joystick.h" #include "fceux_git_info.h" #ifdef _S9XLUA_H @@ -73,14 +74,10 @@ extern bool gtk_gui_run; GtkWidget *MainWindow = NULL; GtkWidget *evbox = NULL; -GtkWidget *padNoCombo = NULL; -GtkWidget *configNoCombo = NULL; -GtkWidget *buttonMappings[10] = { NULL }; static GtkWidget *Menubar = NULL; static GtkRadioMenuItem *stateSlot[10] = { NULL }; bool gtkIsStarted = false; bool menuTogglingEnabled = false; -static int buttonConfigStatus = 0; enum videoDriver_t videoDriver = VIDEO_NONE; unsigned int gtk_draw_area_width = NES_WIDTH; @@ -92,8 +89,6 @@ static int *cairo_pix_remapper = NULL; static int numRendLines = 0; static void cairo_recalc_mapper(void); -static gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data); - // 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) @@ -130,66 +125,63 @@ void setCheckbox (GtkWidget * w, const char *configName) } // 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; - - buttonConfigStatus = 2; - - ButtonConfigBegin (); - - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); - prefix = buf; - DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus ); - - 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)); - - if ( buttonMappings[x] != NULL ) - { - gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf); - } - - ButtonConfigEnd (); - - buttonConfigStatus = 1; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); - - return 0; -} +//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; +// +// 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; +// +// buttonConfigStatus = 2; +// +// ButtonConfigBegin (); +// +// snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); +// prefix = buf; +// DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus ); +// +//// 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 (&GamePad[padNo].bmap[x])); +// +// if ( buttonMappings[x] != NULL ) +// { +// gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf); +// } +// +// ButtonConfigEnd (); +// +// buttonConfigStatus = 1; +// +// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); +// +// return 0; +//} void resetVideo (void) { @@ -677,228 +669,291 @@ void openHotkeyConfig (void) } -//GtkWidget *typeCombo; - -// TODO: finish this -//int setInputDevice (GtkWidget * w, gpointer p) +//static void selInputDevice (GtkWidget * w, gpointer p) //{ -// std::string s = "SDL.Input."; -// s = s + (char *) p; -// printf ("setInputDevice: %s", s.c_str ()); -// g_config->setOption (s, -// gtk_combo_box_text_get_active_text -// (GTK_COMBO_BOX_TEXT (typeCombo))); -// g_config->save (); +// //std::string s = "SDL.Input."; +// int padNo = 0, devIdx = -1; +// const char *devTxt; +// jsDev_t *js; // -// return 1; +// if ( (padNoCombo == NULL) ) +// { +// return; +// } +// padNo = +// atoi (gtk_combo_box_text_get_active_text +// (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1; +// +// devTxt = gtk_combo_box_text_get_active_text ( GTK_COMBO_BOX_TEXT(w) ); +// +// if ( isdigit( devTxt[0] ) ) +// { +// devIdx = atoi( devTxt ); +// } +// printf ("setInputDevice: %s %i", devTxt, devIdx ); +// +// +// //g_config->setOption (s, +// // gtk_combo_box_text_get_active_text +// // (GTK_COMBO_BOX_TEXT (typeCombo))); +// //g_config->save (); +// +// return; +//} +// +//static void updateGamepadConfig (GtkWidget * w, gpointer p) +//{ +// int i; +// char strBuf[128]; +// +// if ( (padNoCombo == NULL) ) +// { +// return; +// } +// int padNo = +// atoi (gtk_combo_box_text_get_active_text +// (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1; +// +// for (i = 0; i < 10; i++) +// { +// GtkWidget *mappedKey = buttonMappings[i]; +// if (GamePad[padNo].bmap[i].ButtType == BUTTC_KEYBOARD) +// { +// snprintf (strBuf, sizeof (strBuf), "%s", +// SDL_GetKeyName (GamePad[padNo].bmap[i]. +// ButtonNum)); +// } +// else +// sprintf (strBuf, "%s", ButtonName( &GamePad[padNo].bmap[i] ) ); +// +// if ( mappedKey != NULL ) +// { +// gtk_label_set_text (GTK_LABEL (mappedKey), strBuf); +// gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE); +// } +// } +//} +// +//static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p) +//{ +// gtk_widget_destroy (w); +// +// padNoCombo = NULL; +// +// for (int i = 0; i < 10; i++) +// { +// buttonMappings[i] = NULL; +// } +// buttonConfigStatus = 0; +//} +// +//// creates and opens the gamepad config window (requires GTK 2.24) +//void openGamepadConfig (void) +//{ +// int portNum = 0; +// GtkWidget *win; +// GtkWidget *vbox; +// GtkWidget *hboxPadNo; +// GtkWidget *padNoLabel; +// GtkWidget* devSelLabel, *devSelHbox; +// GtkWidget *fourScoreChk; +// GtkWidget *oppositeDirChk; +// GtkWidget *buttonFrame; +// GtkWidget *buttonTable; +// char stmp[256]; +// +// win = gtk_dialog_new_with_buttons ("Controller Configuration", +// GTK_WINDOW (MainWindow), +// (GtkDialogFlags) +// (GTK_DIALOG_DESTROY_WITH_PARENT), +// "_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_box_new (GTK_ORIENTATION_HORIZONTAL, 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); +// +// devSelHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); +// devSelLabel = gtk_label_new ("Device:"); +// devSelCombo = gtk_combo_box_text_new (); +// gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (devSelCombo), "Keyboard"); +// +// gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0); +// +// for (int i=0; iisConnected() ) +// { +// sprintf( stmp, "%i: %s", i, js->getName() ); +// gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT (devSelCombo), stmp ); +// } +// } +// } +// gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0); +// +// { +// GtkTreeModel *treeModel = gtk_combo_box_get_model( GTK_COMBO_BOX (devSelCombo) ); +// GtkTreeIter iter; +// gboolean iterValid; +// +// iterValid = gtk_tree_model_get_iter_first( treeModel, &iter ); +// +// while ( iterValid ) +// { +// GValue value; +// +// memset( &value, 0, sizeof(value)); +// +// gtk_tree_model_get_value (treeModel, &iter, 0, &value ); +// +// if ( G_IS_VALUE(&value) ) +// { +// if ( G_VALUE_TYPE(&value) == G_TYPE_STRING ) +// { +// int devIdx = -1; +// const char *s = (const char *)g_value_peek_pointer( &value ); +// +// if ( isdigit( s[0] ) ) +// { +// devIdx = atoi(s); +// } +// if ( (devIdx >= 0) && (devIdx == GamePad[portNum].getDeviceIndex() ) ) +// { +// gtk_combo_box_set_active_iter (GTK_COMBO_BOX (devSelCombo), &iter); +// } +// } +// } +// g_value_unset(&value); +// +// iterValid = gtk_tree_model_iter_next( treeModel, &iter ); +// } +// } +// g_signal_connect (devSelCombo, "changed", G_CALLBACK (selInputDevice), 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 (vbox), hboxPadNo, FALSE, TRUE, 5); +// //gtk_box_pack_start_defaults(GTK_BOX(vbox), typeCombo); +// +// gtk_box_pack_start (GTK_BOX (devSelHbox), devSelLabel, TRUE, TRUE, 5); +// gtk_box_pack_start (GTK_BOX (devSelHbox), devSelCombo, TRUE, TRUE, 5); +// gtk_box_pack_start (GTK_BOX (vbox), devSelHbox, FALSE, TRUE, 5); +// +// 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_grid_new (); +// gtk_container_add (GTK_CONTAINER (buttonFrame), buttonTable); +// +// for (int i = 0; i < 3; i++) +// { +// gtk_grid_insert_column (GTK_GRID (buttonTable), i); +// } +// gtk_grid_set_column_spacing (GTK_GRID (buttonTable), 5); +// gtk_grid_set_column_homogeneous (GTK_GRID (buttonTable), TRUE); +// gtk_grid_set_row_spacing (GTK_GRID (buttonTable), 3); +// +// 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]; +// +// gtk_grid_insert_row (GTK_GRID (buttonTable), i); +// +// sprintf (strBuf, "%s:", GamePadNames[i]); +// gtk_label_set_text (GTK_LABEL (buttonName), strBuf); +// +// gtk_button_set_label (GTK_BUTTON (changeButton), "Change"); +// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (changeButton), +// FALSE); +// +// gtk_grid_attach (GTK_GRID (buttonTable), buttonName, 0, i, 1, +// 1); +// gtk_grid_attach (GTK_GRID (buttonTable), mappedKey, 1, i, 1, 1); +// gtk_grid_attach (GTK_GRID (buttonTable), changeButton, 2, i, 1, +// 1); +// +// 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 (closeGamepadConfig), NULL); +// g_signal_connect (win, "response", G_CALLBACK (closeGamepadConfig), NULL); +// +// gtk_widget_show_all (win); +// +// g_signal_connect (G_OBJECT (win), "key-press-event", +// G_CALLBACK (convertKeypress), NULL); +// g_signal_connect (G_OBJECT (win), "key-release-event", +// G_CALLBACK (convertKeypress), NULL); +// +// buttonConfigStatus = 1; +// +// return; //} - -void updateGamepadConfig (GtkWidget * w, gpointer p) -{ - int i; - char strBuf[128]; - - if ( (padNoCombo == NULL) || (configNoCombo == NULL) ) - { - return; - } - 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) - { - snprintf (strBuf, sizeof (strBuf), "%s", - SDL_GetKeyName (GamePadConfig[padNo][i]. - ButtonNum[configNo])); - } - else - sprintf (strBuf, "%s", ButtonName( &GamePadConfig[padNo][i], configNo ) ); - - if ( mappedKey != NULL ) - { - gtk_label_set_text (GTK_LABEL (mappedKey), strBuf); - gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE); - } - } -} - -static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p) -{ - gtk_widget_destroy (w); - - padNoCombo = NULL; - configNoCombo = NULL; - - for (int i = 0; i < 10; i++) - { - buttonMappings[i] = NULL; - } - buttonConfigStatus = 0; -} - -// creates and opens the gamepad config window (requires GTK 2.24) -void openGamepadConfig (void) -{ - 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), - "_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_box_new (GTK_ORIENTATION_HORIZONTAL, 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_grid_new (); - gtk_container_add (GTK_CONTAINER (buttonFrame), buttonTable); - - for (int i = 0; i < 3; i++) - { - gtk_grid_insert_column (GTK_GRID (buttonTable), i); - } - gtk_grid_set_column_spacing (GTK_GRID (buttonTable), 5); - gtk_grid_set_column_homogeneous (GTK_GRID (buttonTable), TRUE); - gtk_grid_set_row_spacing (GTK_GRID (buttonTable), 3); - - 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]; - - gtk_grid_insert_row (GTK_GRID (buttonTable), i); - - sprintf (strBuf, "%s:", GamePadNames[i]); - gtk_label_set_text (GTK_LABEL (buttonName), strBuf); - - gtk_button_set_label (GTK_BUTTON (changeButton), "Change"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (changeButton), - FALSE); - - gtk_grid_attach (GTK_GRID (buttonTable), buttonName, 0, i, 1, - 1); - gtk_grid_attach (GTK_GRID (buttonTable), mappedKey, 1, i, 1, 1); - gtk_grid_attach (GTK_GRID (buttonTable), changeButton, 2, i, 1, - 1); - - 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 (closeGamepadConfig), NULL); - g_signal_connect (win, "response", G_CALLBACK (closeGamepadConfig), NULL); - - gtk_widget_show_all (win); - - g_signal_connect (G_OBJECT (win), "key-press-event", - G_CALLBACK (convertKeypress), NULL); - g_signal_connect (G_OBJECT (win), "key-release-event", - G_CALLBACK (convertKeypress), NULL); - - buttonConfigStatus = 1; - - return; -} int setBufSize (GtkWidget * w, gpointer p) { @@ -1052,7 +1107,7 @@ void openVideoConfig (void) // sync with cfg int buf; - g_config->getOption ("SDL.SpecialFilter", &buf); + g_config->getOption ("SDL.VideoDriver", &buf); gtk_combo_box_set_active (GTK_COMBO_BOX (DriverCombo), buf); g_signal_connect (DriverCombo, "changed", G_CALLBACK (setVideoDriver), NULL); @@ -2341,7 +2396,7 @@ unsigned int GDKToSDLKeyval (int gdk_key) // Function adapted from Gens/GS (source/gens/input/input_sdl.c) -static gboolean convertKeypress (GtkWidget * grab, GdkEventKey * event, +gboolean convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data) { SDL_Event sdlev; diff --git a/src/drivers/sdl/gui.h b/src/drivers/sdl/gui.h index aa6c8b5e..98eaa81b 100644 --- a/src/drivers/sdl/gui.h +++ b/src/drivers/sdl/gui.h @@ -35,6 +35,10 @@ void pushOutputToGTK(const char* str); void showGui(bool b); void toggleMenuVis(void); +gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data); +void toggleOption (GtkWidget * w, gpointer p); +void setCheckbox (GtkWidget * w, const char *configName); + bool checkGTKVersion(int major_required, int minor_required); int configHotkey(char* hotkeyString); diff --git a/src/drivers/sdl/input.cpp b/src/drivers/sdl/input.cpp index 36d2199f..7c2f0c88 100644 --- a/src/drivers/sdl/input.cpp +++ b/src/drivers/sdl/input.cpp @@ -24,8 +24,9 @@ #include "config.h" -#include "sdl-video.h" #include "sdl.h" +#include "sdl-video.h" +#include "sdl-joystick.h" #include "../common/cheat.h" #include "../../movie.h" @@ -60,6 +61,7 @@ extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; static int UsrInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE }; static int CurInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE }; static int cspec = 0; +static int buttonConfigInProgress = 0; extern int gametype; @@ -618,10 +620,10 @@ static void KeyboardCommands (void) if (_keyonly (Hotkeys[HK_DECREASE_SPEED])) { - DecreaseEmulationSpeed (); + DecreaseEmulationSpeed(); } - if (_keyonly (Hotkeys[HK_INCREASE_SPEED])) + if (_keyonly(Hotkeys[HK_INCREASE_SPEED])) { IncreaseEmulationSpeed (); } @@ -693,17 +695,10 @@ static void KeyboardCommands (void) //} if (_keyonly (Hotkeys[HK_QUIT])) { - if (noGui == 1) - { - CloseGame (); - } - else - { - CloseGame(); - FCEUI_Kill(); - SDL_Quit(); - exit(0); - } + CloseGame(); + FCEUI_Kill(); + SDL_Quit(); + exit(0); } else #ifdef _S9XLUA_H @@ -957,6 +952,8 @@ UpdatePhysicalInput () { SDL_Event event; + //SDL_JoystickUpdate(); + // loop, handling all pending events while (SDL_PollEvent (&event)) { @@ -985,6 +982,12 @@ UpdatePhysicalInput () g_keyState[ event.key.keysym.scancode ] = (event.type == SDL_KEYDOWN) ? 1 : 0; //checkKeyBoardState( event.key.keysym.scancode ); break; + case SDL_JOYDEVICEADDED: + AddJoystick( event.jdevice.which ); + break; + case SDL_JOYDEVICEREMOVED: + RemoveJoystick( event.jdevice.which ); + break; default: break; } @@ -993,8 +996,6 @@ UpdatePhysicalInput () } -static int bcpv, bcpj; - /** * Begin configuring the buttons by placing the video and joystick * subsystems into a well-known state. Button configuration really @@ -1002,31 +1003,11 @@ static int bcpv, bcpj; */ int ButtonConfigBegin () { -//dont shut down video subsystem if we are using gtk to prevent the sdl window from becoming detached to GTK window -// prg318 - 10-2-2011 -#ifdef _GTK - int noGui; - g_config->getOption ("SDL.NoGUI", &noGui); - if (noGui == 1) - { - //SDL_QuitSubSystem (SDL_INIT_VIDEO); - bcpv = KillVideo (); - } -#else - // XXX soules - why are we doing this right before KillVideo()? - //SDL_QuitSubSystem (SDL_INIT_VIDEO); - - // shut down the video and joystick subsystems - bcpv = KillVideo (); -#endif - //SDL_Surface *screen; - - bcpj = KillJoysticks (); - - // XXX soules - why did we shut this down? - // initialize the joystick subsystem + // initialize the joystick subsystem (if not already inited) InitJoysticks (); + buttonConfigInProgress = 1; + return 1; } @@ -1038,18 +1019,7 @@ int ButtonConfigBegin () void ButtonConfigEnd () { - // shutdown the joystick and video subsystems - KillJoysticks (); - //SDL_QuitSubSystem(SDL_INIT_VIDEO); - - // re-initialize joystick and video subsystems if they were active before - /*if(!bcpv) { - InitVideo(GameInfo); - } */ - if (!bcpj) - { - InitJoysticks (); - } + buttonConfigInProgress = 0; } /** @@ -1058,48 +1028,50 @@ ButtonConfigEnd () static int DTestButton (ButtConfig * bc) { - int x; - for (x = 0; x < bc->NumC; x++) + if (bc->ButtType == BUTTC_KEYBOARD) { - if (bc->ButtType[x] == BUTTC_KEYBOARD) + if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum)]) { - if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum[x])]) - { - return 1; - } + bc->state = 1; + return 1; } - else if (bc->ButtType[x] == BUTTC_JOYSTICK) + else + { + bc->state = 0; + } + } + else if (bc->ButtType == BUTTC_JOYSTICK) + { + if (DTestButtonJoy (bc)) { - if (DTestButtonJoy (bc)) - { - return 1; - } + return 1; } } return 0; } -#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} -#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2} -#define MKZ() {{0},{0},{0},0} +#define MK(x) {BUTTC_KEYBOARD,0,MKK(x),0} +//#define MK2(x1,x2) {BUTTC_KEYBOARD,0,MKK(x1)} +#define MKZ() {0,0,-1,0} #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} -ButtConfig GamePadConfig[4][10] = { -/* Gamepad 1 */ - {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), - MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, - - /* Gamepad 2 */ - GPZ (), - - /* Gamepad 3 */ - GPZ (), - - /* Gamepad 4 */ - GPZ () -}; +//ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] = +//{ +///* Gamepad 1 */ +// {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), +// MK (w), MK (z), MK (a), MK (s), MKZ (), MKZ ()}, +// +// /* Gamepad 2 */ +// GPZ (), +// +// /* Gamepad 3 */ +// GPZ (), +// +// /* Gamepad 4 */ +// GPZ () +//}; /** * Update the status of the gamepad input devices. @@ -1131,7 +1103,7 @@ UpdateGamepad(void) // a, b, select, start, up, down, left, right for (x = 0; x < 8; x++) { - if (DTestButton (&GamePadConfig[wg][x])) + if (DTestButton (&GamePad[wg].bmap[x])) { //printf("GamePad%i Button Hit: %i \n", wg, x ); if(opposite_dirs == 0) @@ -1169,7 +1141,7 @@ UpdateGamepad(void) { for (x = 0; x < 2; x++) { - if (DTestButton (&GamePadConfig[wg][8 + x])) + if (DTestButton (&GamePad[wg].bmap[8 + x])) { JS |= (1 << x) << (wg << 3); } @@ -1238,11 +1210,15 @@ static uint8 fkbkeys[0x48]; /** * Update all of the input devices required for the active game. */ -void FCEUD_UpdateInput () +void FCEUD_UpdateInput(void) { int x; int t = 0; + if ( buttonConfigInProgress ) + { + return; + } UpdatePhysicalInput (); KeyboardCommands (); @@ -1356,8 +1332,8 @@ void InitInputInterface () { void *InputDPtr; - int t; - int x; + int t = 0; + int x = 0; int attrib; memset( g_keyState, 0, sizeof(g_keyState) ); @@ -1600,36 +1576,42 @@ UpdateFTrainer () * @param bc the NES gamepad's button config * @param which the index of the button */ -const char * ButtonName (const ButtConfig * bc, int which) +const char * ButtonName (const ButtConfig * bc) { static char name[256]; - switch (bc->ButtType[which]) + name[0] = 0; + + if (bc->ButtonNum == -1) + { + return name; + } + switch (bc->ButtType) { case BUTTC_KEYBOARD: - return SDL_GetKeyName (bc->ButtonNum[which]); + return SDL_GetKeyName (bc->ButtonNum); break; case BUTTC_JOYSTICK: { int joyNum, inputNum; const char *inputType, *inputDirection; - joyNum = bc->DeviceNum[which]; + joyNum = bc->DeviceNum; - if (bc->ButtonNum[which] & 0x8000) + if (bc->ButtonNum & 0x8000) { inputType = "Axis"; - inputNum = bc->ButtonNum[which] & 0x3FFF; - inputDirection = bc->ButtonNum[which] & 0x4000 ? "-" : "+"; + inputNum = bc->ButtonNum & 0x3FFF; + inputDirection = bc->ButtonNum & 0x4000 ? "-" : "+"; } - else if (bc->ButtonNum[which] & 0x2000) + else if (bc->ButtonNum & 0x2000) { int inputValue; char direction[128] = ""; inputType = "Hat"; - inputNum = (bc->ButtonNum[which] >> 8) & 0x1F; - inputValue = bc->ButtonNum[which] & 0xF; + inputNum = (bc->ButtonNum >> 8) & 0x1F; + inputValue = bc->ButtonNum & 0xF; if (inputValue & SDL_HAT_UP) strncat (direction, "Up ", sizeof (direction)-1); @@ -1648,7 +1630,7 @@ const char * ButtonName (const ButtConfig * bc, int which) else { inputType = "Button"; - inputNum = bc->ButtonNum[which]; + inputNum = bc->ButtonNum; inputDirection = ""; } sprintf( name, "js%i:%s%i%s", joyNum, inputType, inputNum, inputDirection ); @@ -1663,11 +1645,12 @@ const char * ButtonName (const ButtConfig * bc, int which) * Waits for a button input and returns the information as to which * button was pressed. Used in button configuration. */ -int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigStatus ) +int DWaitButton (const uint8_t * text, ButtConfig * bc, int *buttonConfigStatus ) { SDL_Event event; static int32 LastAx[64][64]; int x, y; + int timeout_ms = 10000; if (text) { @@ -1686,36 +1669,53 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS } } + // Purge all pending events, so that this next button press + // will be the one we want. + while (SDL_PollEvent (&event)) + { + + } + while (1) { int done = 0; + + usleep(10000); + timeout_ms -= 10; + + if ( timeout_ms <= 0 ) + { + break; + } #ifdef _GTK while (gtk_events_pending ()) gtk_main_iteration_do (FALSE); #endif while (SDL_PollEvent (&event)) { + printf("Event Type: %i \n", event.type ); done++; switch (event.type) { case SDL_KEYDOWN: - bc->ButtType[wb] = BUTTC_KEYBOARD; - bc->DeviceNum[wb] = 0; - bc->ButtonNum[wb] = event.key.keysym.sym; + //printf("SDL KeyDown:%i \n", event.key.keysym.sym ); + bc->ButtType = BUTTC_KEYBOARD; + bc->DeviceNum = 0; + bc->ButtonNum = event.key.keysym.sym; return (1); case SDL_JOYBUTTONDOWN: - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jbutton.which; - bc->ButtonNum[wb] = event.jbutton.button; + bc->ButtType = BUTTC_JOYSTICK; + bc->DeviceNum = event.jbutton.which; + bc->ButtonNum = event.jbutton.button; return (1); case SDL_JOYHATMOTION: if (event.jhat.value == SDL_HAT_CENTERED) done--; else { - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jhat.which; - bc->ButtonNum[wb] = + bc->ButtType = BUTTC_JOYSTICK; + bc->DeviceNum = event.jhat.which; + bc->ButtonNum = (0x2000 | ((event.jhat.hat & 0x1F) << 8) | event. jhat.value); return (1); @@ -1737,9 +1737,9 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS (LastAx[event.jaxis.which][event.jaxis.axis] - event.jaxis.value) >= 8192) { - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jaxis.which; - bc->ButtonNum[wb] = (0x8000 | event.jaxis.axis | + bc->ButtType = BUTTC_JOYSTICK; + bc->DeviceNum = event.jaxis.which; + bc->ButtonNum = (0x8000 | event.jaxis.axis | ((event.jaxis.value < 0) ? 0x4000 : 0)); return (1); @@ -1776,213 +1776,206 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS * used as input for the specified button, thus allowing up to four * possible settings for each input button. */ - void -ConfigButton (char *text, ButtConfig * bc) -{ - uint8 buf[256]; - int wc; - - for (wc = 0; wc < MAXBUTTCONFIG; wc++) - { - sprintf ((char *) buf, "%s (%d)", text, wc + 1); - DWaitButton (buf, bc, wc, NULL); - - if (wc && - bc->ButtType[wc] == bc->ButtType[wc - 1] && - bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] && - bc->ButtonNum[wc] == bc->ButtonNum[wc - 1]) - { - break; - } - } - bc->NumC = wc; -} +// void +//ConfigButton (char *text, ButtConfig * bc) +//{ +// uint8 buf[256]; +// int wc; +// +// for (wc = 0; wc < MAXBUTTCONFIG; wc++) +// { +// sprintf ((char *) buf, "%s (%d)", text, wc + 1); +// DWaitButton (buf, bc, wc, NULL); +// +// if (wc && +// bc->ButtType[wc] == bc->ButtType[wc - 1] && +// bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] && +// bc->ButtonNum[wc] == bc->ButtonNum[wc - 1]) +// { +// break; +// } +// } +//} /** * Update the button configuration for a specified device. */ extern Config *g_config; -void ConfigDevice (int which, int arg) -{ - char buf[256]; - int x; - std::string prefix; - const char *str[10] = - { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A", - "Rapid B" - }; - - // XXX soules - set the configuration options so that later calls - // don't override these. This is a temp hack until I - // can clean up this file. - - ButtonConfigBegin (); - switch (which) - { - case FCFGD_QUIZKING: - prefix = "SDL.Input.QuizKing."; - for (x = 0; x < 6; x++) - { - sprintf (buf, "Quiz King Buzzer #%d", x + 1); - ConfigButton (buf, &QuizKingButtons[x]); - - g_config->setOption (prefix + QuizKingNames[x], - QuizKingButtons[x].ButtonNum[0]); - } - - if (QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - QuizKingButtons[0].DeviceNum[0]); - break; - case FCFGD_HYPERSHOT: - prefix = "SDL.Input.HyperShot."; - for (x = 0; x < 4; x++) - { - sprintf (buf, "Hyper Shot %d: %s", - ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN"); - ConfigButton (buf, &HyperShotButtons[x]); - - g_config->setOption (prefix + HyperShotNames[x], - HyperShotButtons[x].ButtonNum[0]); - } - - if (HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - HyperShotButtons[0].DeviceNum[0]); - break; - case FCFGD_POWERPAD: - snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1)); - prefix = buf; - for (x = 0; x < 12; x++) - { - sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11); - ConfigButton (buf, &powerpadsc[arg & 1][x]); - - g_config->setOption (prefix + PowerPadNames[x], - powerpadsc[arg & 1][x].ButtonNum[0]); - } - - if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - powerpadsc[arg & 1][0].DeviceNum[0]); - break; - - case FCFGD_GAMEPAD: - snprintf (buf, 256, "SDL.Input.GamePad.%d", arg); - prefix = buf; - for (x = 0; x < 10; x++) - { - sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]); - ConfigButton (buf, &GamePadConfig[arg][x]); - - g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[arg][x].ButtonNum[0]); - } - - if (GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePadConfig[arg][0].DeviceNum[0]); - break; - } - - ButtonConfigEnd (); -} +//void ConfigDevice (int which, int arg) +//{ +// char buf[256]; +// int x; +// std::string prefix; +// const char *str[10] = +// { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A", +// "Rapid B" +// }; +// +// // XXX soules - set the configuration options so that later calls +// // don't override these. This is a temp hack until I +// // can clean up this file. +// +// ButtonConfigBegin (); +// switch (which) +// { +// case FCFGD_QUIZKING: +// prefix = "SDL.Input.QuizKing."; +// for (x = 0; x < 6; x++) +// { +// sprintf (buf, "Quiz King Buzzer #%d", x + 1); +// ConfigButton (buf, &QuizKingButtons[x]); +// +// g_config->setOption (prefix + QuizKingNames[x], +// QuizKingButtons[x].ButtonNum); +// } +// +// if (QuizKingButtons[0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (QuizKingButtons[0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// QuizKingButtons[0].DeviceNum); +// break; +// case FCFGD_HYPERSHOT: +// prefix = "SDL.Input.HyperShot."; +// for (x = 0; x < 4; x++) +// { +// sprintf (buf, "Hyper Shot %d: %s", +// ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN"); +// ConfigButton (buf, &HyperShotButtons[x]); +// +// g_config->setOption (prefix + HyperShotNames[x], +// HyperShotButtons[x].ButtonNum); +// } +// +// if (HyperShotButtons[0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (HyperShotButtons[0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// HyperShotButtons[0].DeviceNum); +// break; +// case FCFGD_POWERPAD: +// snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1)); +// prefix = buf; +// for (x = 0; x < 12; x++) +// { +// sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11); +// ConfigButton (buf, &powerpadsc[arg & 1][x]); +// +// g_config->setOption (prefix + PowerPadNames[x], +// powerpadsc[arg & 1][x].ButtonNum); +// } +// +// if (powerpadsc[arg & 1][0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (powerpadsc[arg & 1][0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// powerpadsc[arg & 1][0].DeviceNum); +// break; +// +// case FCFGD_GAMEPAD: +// snprintf (buf, 256, "SDL.Input.GamePad.%d", arg); +// prefix = buf; +// for (x = 0; x < 10; x++) +// { +// sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]); +// ConfigButton (buf, &GamePadConfig[arg][x]); +// +// g_config->setOption (prefix + GamePadNames[x], +// GamePadConfig[arg][x].ButtonNum); +// } +// +// if (GamePadConfig[arg][0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (GamePadConfig[arg][0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// GamePadConfig[arg][0].DeviceNum); +// break; +// } +// +// ButtonConfigEnd (); +//} /** * Update the button configuration for a device, specified by a text string. */ -void InputCfg (const std::string & text) -{ -#ifdef _GTK - // enable noGui to prevent the gtk x11 hack from executing - noGui = 1; - // this is only called at the begininng of execution; make sure the video subsystem is initialized - InitVideo (GameInfo); -#endif - - if (noGui) - { - if (text.find ("gamepad") != std::string::npos) - { - int device = (text[strlen ("gamepad")] - '1'); - if (device < 0 || device > 3) - { - FCEUD_PrintError - ("Invalid gamepad device specified; must be one of gamepad1 through gamepad4"); - exit (-1); - } - ConfigDevice (FCFGD_GAMEPAD, device); - } - else if (text.find ("powerpad") != std::string::npos) - { - int device = (text[strlen ("powerpad")] - '1'); - if (device < 0 || device > 1) - { - FCEUD_PrintError - ("Invalid powerpad device specified; must be powerpad1 or powerpad2"); - exit (-1); - } - ConfigDevice (FCFGD_POWERPAD, device); - } - else if (text.find ("hypershot") != std::string::npos) - { - ConfigDevice (FCFGD_HYPERSHOT, 0); - } - else if (text.find ("quizking") != std::string::npos) - { - ConfigDevice (FCFGD_QUIZKING, 0); - } - } - else - printf ("Please run \"fceux --nogui\" before using --inputcfg\n"); - -} +//void InputCfg (const std::string & text) +//{ +// +// if (noGui) +// { +// if (text.find ("gamepad") != std::string::npos) +// { +// int device = (text[strlen ("gamepad")] - '1'); +// if (device < 0 || device > 3) +// { +// FCEUD_PrintError +// ("Invalid gamepad device specified; must be one of gamepad1 through gamepad4"); +// exit (-1); +// } +// ConfigDevice (FCFGD_GAMEPAD, device); +// } +// else if (text.find ("powerpad") != std::string::npos) +// { +// int device = (text[strlen ("powerpad")] - '1'); +// if (device < 0 || device > 1) +// { +// FCEUD_PrintError +// ("Invalid powerpad device specified; must be powerpad1 or powerpad2"); +// exit (-1); +// } +// ConfigDevice (FCFGD_POWERPAD, device); +// } +// else if (text.find ("hypershot") != std::string::npos) +// { +// ConfigDevice (FCFGD_HYPERSHOT, 0); +// } +// else if (text.find ("quizking") != std::string::npos) +// { +// ConfigDevice (FCFGD_QUIZKING, 0); +// } +// } +// else +// printf ("Please run \"fceux --nogui\" before using --inputcfg\n"); +// +//} /** @@ -1994,7 +1987,9 @@ void InputCfg (const std::string & text) UpdateInput (Config * config) { char buf[64]; - std::string device, prefix; + std::string device, prefix, guid, mapping; + + InitJoysticks(); for (unsigned int i = 0; i < 3; i++) { @@ -2087,37 +2082,18 @@ UpdateInput (Config * config) snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i); prefix = buf; - config->getOption (prefix + "DeviceType", &device); - if (device.find ("Keyboard") != std::string::npos) - { - type = BUTTC_KEYBOARD; - } - else if (device.find ("Joystick") != std::string::npos) - { - type = BUTTC_JOYSTICK; - } - else - { - type = 0; - } + config->getOption (prefix + "DeviceType", &device ); + config->getOption (prefix + "DeviceGUID", &guid ); + config->getOption (prefix + "Profile" , &mapping); - config->getOption (prefix + "DeviceNum", &devnum); - for (unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) - { - config->getOption (prefix + GamePadNames[j], &button); - - GamePadConfig[i][j].ButtType[0] = type; - GamePadConfig[i][j].DeviceNum[0] = devnum; - GamePadConfig[i][j].ButtonNum[0] = button; - GamePadConfig[i][j].NumC = 1; - } + GamePad[i].init( i, guid.c_str(), mapping.c_str() ); } // PowerPad 0 - 1 for (unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { char buf[64]; - snprintf (buf, 32, "SDL.Input.PowerPad.%u.", i); + snprintf (buf, sizeof(buf)-1, "SDL.Input.PowerPad.%u.", i); prefix = buf; config->getOption (prefix + "DeviceType", &device); @@ -2139,10 +2115,9 @@ UpdateInput (Config * config) { config->getOption (prefix + PowerPadNames[j], &button); - powerpadsc[i][j].ButtType[0] = type; - powerpadsc[i][j].DeviceNum[0] = devnum; - powerpadsc[i][j].ButtonNum[0] = button; - powerpadsc[i][j].NumC = 1; + powerpadsc[i][j].ButtType = type; + powerpadsc[i][j].DeviceNum = devnum; + powerpadsc[i][j].ButtonNum = button; } } @@ -2166,10 +2141,9 @@ UpdateInput (Config * config) { config->getOption (prefix + QuizKingNames[j], &button); - QuizKingButtons[j].ButtType[0] = type; - QuizKingButtons[j].DeviceNum[0] = devnum; - QuizKingButtons[j].ButtonNum[0] = button; - QuizKingButtons[j].NumC = 1; + QuizKingButtons[j].ButtType = type; + QuizKingButtons[j].DeviceNum = devnum; + QuizKingButtons[j].ButtonNum = button; } // HyperShot @@ -2192,10 +2166,9 @@ UpdateInput (Config * config) { config->getOption (prefix + HyperShotNames[j], &button); - HyperShotButtons[j].ButtType[0] = type; - HyperShotButtons[j].DeviceNum[0] = devnum; - HyperShotButtons[j].ButtonNum[0] = button; - HyperShotButtons[j].NumC = 1; + HyperShotButtons[j].ButtType = type; + HyperShotButtons[j].DeviceNum = devnum; + HyperShotButtons[j].ButtonNum = button; } // Mahjong @@ -2218,10 +2191,9 @@ UpdateInput (Config * config) { config->getOption (prefix + MahjongNames[j], &button); - MahjongButtons[j].ButtType[0] = type; - MahjongButtons[j].DeviceNum[0] = devnum; - MahjongButtons[j].ButtonNum[0] = button; - MahjongButtons[j].NumC = 1; + MahjongButtons[j].ButtType = type; + MahjongButtons[j].DeviceNum = devnum; + MahjongButtons[j].ButtonNum = button; } // TopRider @@ -2244,10 +2216,9 @@ UpdateInput (Config * config) { config->getOption (prefix + TopRiderNames[j], &button); - TopRiderButtons[j].ButtType[0] = type; - TopRiderButtons[j].DeviceNum[0] = devnum; - TopRiderButtons[j].ButtonNum[0] = button; - TopRiderButtons[j].NumC = 1; + TopRiderButtons[j].ButtType = type; + TopRiderButtons[j].DeviceNum = devnum; + TopRiderButtons[j].ButtonNum = button; } // FTrainer @@ -2270,10 +2241,9 @@ UpdateInput (Config * config) { config->getOption (prefix + FTrainerNames[j], &button); - FTrainerButtons[j].ButtType[0] = type; - FTrainerButtons[j].DeviceNum[0] = devnum; - FTrainerButtons[j].ButtonNum[0] = button; - FTrainerButtons[j].NumC = 1; + FTrainerButtons[j].ButtType = type; + FTrainerButtons[j].DeviceNum = devnum; + FTrainerButtons[j].ButtonNum = button; } // FamilyKeyBoard @@ -2296,10 +2266,9 @@ UpdateInput (Config * config) { config->getOption (prefix + FamilyKeyBoardNames[j], &button); - fkbmap[j].ButtType[0] = type; - fkbmap[j].DeviceNum[0] = devnum; - fkbmap[j].ButtonNum[0] = button; - fkbmap[j].NumC = 1; + fkbmap[j].ButtType = type; + fkbmap[j].DeviceNum = devnum; + fkbmap[j].ButtonNum = button; } } @@ -2311,11 +2280,11 @@ const char *GamePadNames[GAMEPAD_NUM_BUTTONS] = { "A", "B", "Select", "Start", const char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] = { "Keyboard", "None", "None", "None" }; const int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] = -{ {SDLK_F, SDLK_D, SDLK_S, SDLK_RETURN, - SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, 0, 0}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +{ {SDLK_f, SDLK_d, SDLK_s, SDLK_RETURN, + SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, -1, -1}, +{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1} }; // PowerPad defaults diff --git a/src/drivers/sdl/input.h b/src/drivers/sdl/input.h index 2a1a2d85..07dc1d04 100644 --- a/src/drivers/sdl/input.h +++ b/src/drivers/sdl/input.h @@ -1,34 +1,39 @@ #ifndef _aosdfjk02fmasf #define _aosdfjk02fmasf -#include "../common/configSys.h" +#include -#define MAXBUTTCONFIG 4 -typedef struct { - uint8 ButtType[MAXBUTTCONFIG]; - uint8 DeviceNum[MAXBUTTCONFIG]; - //uint16 ButtonNum[MAXBUTTCONFIG]; - int ButtonNum[MAXBUTTCONFIG]; - uint32 NumC; +#include "common/configSys.h" + +//#define MAXBUTTCONFIG 4 + +enum { + BUTTC_KEYBOARD = 0, + BUTTC_JOYSTICK = 1, + BUTTC_MOUSE = 2 +}; +struct ButtConfig +{ + int ButtType; //[MAXBUTTCONFIG]; + int DeviceNum; //[MAXBUTTCONFIG]; + int ButtonNum; //[MAXBUTTCONFIG]; + int state; + //uint32_t NumC; //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ -} ButtConfig; - +}; extern int NoWaiting; extern CFGSTRUCT InputConfig[]; extern ARGPSTRUCT InputArgs[]; extern int Hotkeys[]; void ParseGIInput(FCEUGI *GI); -void setHotKeys(); +void setHotKeys(void); int getKeyState( int k ); int ButtonConfigBegin(); void ButtonConfigEnd(); void ConfigButton(char *text, ButtConfig *bc); -int DWaitButton(const uint8 *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL); +int DWaitButton(const uint8_t *text, ButtConfig *bc, int *buttonConfigStatus = NULL); -#define BUTTC_KEYBOARD 0x00 -#define BUTTC_JOYSTICK 0x01 -#define BUTTC_MOUSE 0x02 #define FCFGD_GAMEPAD 1 #define FCFGD_POWERPAD 2 @@ -41,7 +46,7 @@ void InitInputInterface(void); void InputUserActiveFix(void); extern bool replaceP2StartWithMicrophone; -extern ButtConfig GamePadConfig[4][10]; +//extern ButtConfig GamePadConfig[4][10]; //extern ButtConfig powerpadsc[2][12]; //extern ButtConfig QuizKingButtons[6]; //extern ButtConfig FTrainerButtons[12]; @@ -54,9 +59,9 @@ int DTestButtonJoy(ButtConfig *bc); void FCEUD_UpdateInput(void); void UpdateInput(Config *config); -void InputCfg(const std::string &); +//void InputCfg(const std::string &); std::string GetUserText(const char* title); -const char* ButtonName(const ButtConfig* bc, int which); +const char* ButtonName(const ButtConfig* bc); #endif diff --git a/src/drivers/sdl/sdl-joystick.cpp b/src/drivers/sdl/sdl-joystick.cpp index 690b012b..3330d32c 100644 --- a/src/drivers/sdl/sdl-joystick.cpp +++ b/src/drivers/sdl/sdl-joystick.cpp @@ -22,102 +22,1020 @@ /// \file /// \brief Handles joystick input using the SDL. -#include "sdl.h" +//#include +#include "Qt/sdl.h" +#include "Qt/sdl-joystick.h" #include #include #include #include -#define MAX_JOYSTICKS 32 -static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL}; +//#define MAX_JOYSTICKS 32 +// Public Variables +GamePad_t GamePad[4]; + +// Static Functions +static int sdlButton2NesGpIdx( const char *id ); + +// Static Variables static int s_jinited = 0; +static const char *buttonNames[ GAMEPAD_NUM_BUTTONS ] = +{ + "a", "b","back","start", + "dpup","dpdown","dpleft","dpright", + "turboA","turboB" +}; +//******************************************************************************** +// Joystick Device +jsDev_t::jsDev_t(void) +{ + js = NULL; + gc = NULL; + devIdx = 0; + portBindMask = 0; +}; + +//******************************************************************************** +int jsDev_t::close(void) +{ + if ( gc ) + { + SDL_GameControllerClose( gc ); gc = NULL; js = NULL; + } + else + { + if ( js ) + { + SDL_JoystickClose( js ); js = NULL; + } + } + return 0; +} + +//******************************************************************************** +SDL_Joystick *jsDev_t::getJS(void) +{ + return js; +} + +//******************************************************************************** +const char *jsDev_t::getName(void) +{ + return ( name.c_str() ); +} + +//******************************************************************************** +const char *jsDev_t::getGUID(void) +{ + return ( guidStr.c_str() ); +} + +//******************************************************************************** +int jsDev_t::bindPort( int idx ) +{ + portBindMask |= (0x00000001 << idx); + + return portBindMask; +} +//******************************************************************************** +int jsDev_t::unbindPort( int idx ) +{ + portBindMask &= ~(0x00000001 << idx); + + return portBindMask; +} +//******************************************************************************** +int jsDev_t::getBindPorts(void) +{ + return portBindMask; +} +//******************************************************************************** +bool jsDev_t::isGameController(void) +{ + return ( gc != NULL ); +} + +//******************************************************************************** +bool jsDev_t::isConnected(void) +{ + return ( (js != NULL) || (gc != NULL) ); +} + +//******************************************************************************** +void jsDev_t::init( int idx ) +{ + SDL_JoystickGUID guid; + char stmp[64]; + + devIdx = idx; + + if ( gc ) + { + js = SDL_GameControllerGetJoystick( gc ); + + guid = SDL_JoystickGetGUID( js ); + + name.assign( SDL_GameControllerName(gc) ); + } + else + { + guid = SDL_JoystickGetGUID( js ); + + name.assign( SDL_JoystickName(js) ); + } + SDL_JoystickGetGUIDString( guid, stmp, sizeof(stmp) ); + + guidStr.assign( stmp ); + +} + +void jsDev_t::print(void) +{ + char guidStr[64]; + + SDL_JoystickGUID guid = SDL_JoystickGetGUID( js ); + + SDL_JoystickGetGUIDString( guid, guidStr, sizeof(guidStr) ); + + printf("JoyStickID: %i: '%s' \n", + SDL_JoystickInstanceID( js ), SDL_JoystickName( js ) ); + printf("GUID: %s \n", guidStr ); + printf("NumAxes: %i \n", SDL_JoystickNumAxes(js) ); + printf("NumButtons: %i \n", SDL_JoystickNumButtons(js) ); + printf("NumHats: %i \n", SDL_JoystickNumHats(js) ); + + if ( gc ) + { + printf("GameController Name: '%s'\n", SDL_GameControllerName(gc) ); + printf("GameController Mapping: %s\n", SDL_GameControllerMapping(gc) ); + } +} + +static jsDev_t jsDev[ MAX_JOYSTICKS ]; + +//******************************************************************************** +nesGamePadMap_t::nesGamePadMap_t(void) +{ + clearMapping(); +} +//******************************************************************************** +nesGamePadMap_t::~nesGamePadMap_t(void) +{ + +} +//******************************************************************************** +void nesGamePadMap_t::clearMapping(void) +{ + guid[0] = 0; + name[0] = 0; + os[0] = 0; + for (int i=0; i= 0 ) + { + strcpy( btn[bIdx], val[i] ); + } + else if ( strcmp( id[i], "platform" ) == 0 ) + { + strcpy( os, val[i] ); + } + } + return 0; +} +//******************************************************************************** +GamePad_t::GamePad_t(void) +{ + devIdx = -1; + portNum = 0; + + for (int i=0; i= 0 ) + { + jsDev[ devIdx ].unbindPort( portNum ); + } + + devIdx = in; + + if ( devIdx >= 0 ) + { + jsDev[ devIdx ].bindPort( portNum ); + } + return 0; +} +//******************************************************************************** +const char *GamePad_t::getGUID(void) +{ + if ( devIdx < 0 ) + { + return "keyboard"; + } + if ( jsDev[ devIdx ].isConnected() ) + { + return jsDev[ devIdx ].getGUID(); + } + return NULL; +} +//******************************************************************************** +static int sdlButton2NesGpIdx( const char *id ) +{ + int i, idx = -1; + + for (i=0; ibtn[i][0] == 0) + { + continue; + } + if (gpm->btn[i][0] == 'k') + { + SDL_Keycode key; + + bmap[i].ButtType = BUTTC_KEYBOARD; + bmap[i].DeviceNum = -1; + + key = SDL_GetKeyFromName( &gpm->btn[i][1] ); + + if ( key != SDLK_UNKNOWN ) + { + bmap[i].ButtonNum = key; + } + else + { + bmap[i].ButtonNum = -1; + } + } + else if ( (gpm->btn[i][0] == 'b') && isdigit( gpm->btn[i][1] ) ) + { + bmap[i].ButtType = BUTTC_JOYSTICK; + bmap[i].DeviceNum = devIdx; + bmap[i].ButtonNum = atoi( &gpm->btn[i][1] ); + } + else if ( (gpm->btn[i][0] == 'h') && isdigit( gpm->btn[i][1] ) && + (gpm->btn[i][2] == '.') && isdigit( gpm->btn[i][3] ) ) + { + int hatIdx, hatVal; + + hatIdx = gpm->btn[i][1] - '0'; + hatVal = atoi( &gpm->btn[i][3] ); + + bmap[i].ButtType = BUTTC_JOYSTICK; + bmap[i].DeviceNum = devIdx; + bmap[i].ButtonNum = 0x2000 | ( (hatIdx & 0x1F) << 8) | (hatVal & 0xFF); + } + else if ( (gpm->btn[i][0] == 'a') || (gpm->btn[i][1] == 'a') ) + { + int l=0, axisIdx=0, axisSign=0; + + l=0; + if ( gpm->btn[i][l] == '-' ) + { + axisSign = 1; l++; + } + else if ( gpm->btn[i][l] == '+' ) + { + axisSign = 0; l++; + } + + if ( gpm->btn[i][l] == 'a' ) + { + l++; + } + if ( isdigit( gpm->btn[i][l] ) ) + { + axisIdx = atoi( &gpm->btn[i][l] ); + + while ( isdigit(gpm->btn[i][l]) ) l++; + } + if ( gpm->btn[i][l] == '-' ) + { + axisSign = 1; l++; + } + else if ( gpm->btn[i][l] == '+' ) + { + axisSign = 0; l++; + } + bmap[i].ButtType = BUTTC_JOYSTICK; + bmap[i].DeviceNum = devIdx; + bmap[i].ButtonNum = 0x8000 | (axisSign ? 0x4000 : 0) | (axisIdx & 0xFF); + } + } + return 0; +} +//******************************************************************************** +int GamePad_t::setMapping( const char *map ) +{ + nesGamePadMap_t gpm; + + gpm.parseMapping( map ); + setMapping( &gpm ); + + return 0; +} +//******************************************************************************** +int GamePad_t::getMapFromFile( const char *filename, char *out ) +{ + int i=0,j=0; + FILE *fp; + char line[256]; + + out[0] = 0; + + fp = ::fopen( filename, "r" ); + + if ( fp == NULL ) + { + return -1; + } + while ( fgets( line, sizeof(line), fp ) != 0 ) + { + i=0; + while (line[i] != 0) + { + if ( line[i] == '#' ) + { + line[i] = 0; break; + } + i++; + } + + if ( i < 32 ) continue; // need at least 32 chars for a valid line entry + + i=0; j=0; + while ( isspace(line[i]) ) i++; + + while ( line[i] != 0 ) + { + out[j] = line[i]; i++; j++; + } + out[j] = 0; + + if ( j < 34 ) continue; + + break; + } + + ::fclose(fp); + + return (j < 34); +} +//******************************************************************************** +int GamePad_t::getDefaultMap( char *out, const char *guid ) +{ + char txtMap[256]; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + + out[0] = 0; + + if ( devIdx < 0 ) + { + guid = "keyboard"; + } + if ( guid == NULL ) + { + if ( jsDev[ devIdx ].isConnected() ) + { + guid = jsDev[ devIdx ].getGUID(); + } + } + if ( guid == NULL ) + { + return -1; + } + + path = std::string(baseDir) + "/input/" + std::string(guid) + "/default.txt"; + + if ( getMapFromFile( path.c_str(), txtMap ) == 0 ) + { + printf("Using Mapping From File: %s\n", path.c_str() ); + strcpy( out, txtMap ); + return 0; + } + + if ( devIdx >= 0 ) + { + if ( jsDev[ devIdx ].gc ) + { + char *sdlMapping; + + sdlMapping = SDL_GameControllerMapping( jsDev[ devIdx ].gc ); + + if ( sdlMapping == NULL ) return -1; + + strcpy( out, sdlMapping ); + + SDL_free(sdlMapping); + + return 0; + } + } + else + { + if ( strcmp( guid, "keyboard" ) == 0 ) + { + for (int x=0; x= 0 ) + { + if ( !jsDev[devIdx].isConnected() ) + { + printf("Error: JS%i Not Connected\n", devIdx ); + return -1; + } + guid = jsDev[devIdx].getGUID(); + } + else + { + guid = "keyboard"; + } + path = std::string(baseDir) + "/input/" + std::string(guid); + + //dir.mkpath( QString::fromStdString(path) ); + + path += "/" + std::string(name) + ".txt"; + + output.assign( guid ); + output.append( "," ); + output.append( name ); + output.append( "," ); + + for (i=0; i> 8) & 0x1F, bmap[i].ButtonNum & 0xFF ); + } + else if (bmap[i].ButtonNum & 0x8000) + { + /* Axis "button" */ + sprintf( stmp, "%ca%i", + (bmap[i].ButtonNum & 0x4000) ? '-' : '+', bmap[i].ButtonNum & 0x3FFF ); + } + else + { + /* Button */ + sprintf( stmp, "b%i", bmap[i].ButtonNum ); + } + } + output.append( buttonNames[i] ); + output.append( ":" ); + output.append( stmp ); + output.append( "," ); + } + + return saveMappingToFile( path.c_str(), output.c_str() ); +} +//******************************************************************************** +int GamePad_t::saveMappingToFile( const char *filename, const char *txtMap ) +{ + FILE *fp; + + fp = ::fopen(filename, "w"); + + if ( fp == NULL ) + { + return -1; + } + fprintf( fp, "%s\n", txtMap ); + + ::fclose(fp); + + return 0; +} +//******************************************************************************** +int GamePad_t::createProfile( const char *name ) +{ + const char *guid = NULL; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + //QDir dir; + + if ( baseDir[0] == 0 ) + { + printf("Error: Invalid base directory\n"); + return -1; + } + if ( devIdx >= 0 ) + { + if ( !jsDev[devIdx].isConnected() ) + { + printf("Error: JS%i Not Connected\n", devIdx ); + return -1; + } + guid = jsDev[devIdx].getGUID(); + } + else + { + guid = "keyboard"; + } + path = std::string(baseDir) + "/input/" + std::string(guid); + + //dir.mkpath( QString::fromStdString(path) ); + //printf("DIR: '%s'\n", path.c_str() ); + + //path += "/" + std::string(name) + ".txt"; + + //printf("File: '%s'\n", path.c_str() ); + + saveCurrentMapToFile( name ); + + return 0; +} +//******************************************************************************** +int GamePad_t::deleteMapping( const char *name ) +{ + const char *guid = NULL; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + + if ( baseDir[0] == 0 ) + { + printf("Error: Invalid base directory\n"); + return -1; + } + if ( devIdx >= 0 ) + { + if ( !jsDev[devIdx].isConnected() ) + { + printf("Error: JS%i Not Connected\n", devIdx ); + return -1; + } + guid = jsDev[devIdx].getGUID(); + } + else + { + guid = "keyboard"; + } + path = std::string(baseDir) + "/input/" + std::string(guid) + + "/" + std::string(name) + ".txt"; + + //printf("File: '%s'\n", path.c_str() ); + + return remove( path.c_str() ); +} +//******************************************************************************** +jsDev_t *getJoystickDevice( int devNum ) +{ + if ( (devNum >= 0) && (devNum < MAX_JOYSTICKS) ) + { + return &jsDev[ devNum ]; + } + return NULL; +} + +//******************************************************************************** /** * Tests if the given button is active on the joystick. */ int DTestButtonJoy(ButtConfig *bc) { - int x; + SDL_Joystick *js; - for(x = 0; x < bc->NumC; x++) + if (bc->ButtonNum == -1) { - if(bc->ButtonNum[x] & 0x2000) - { - /* Hat "button" */ - if(SDL_JoystickGetHat(s_Joysticks[bc->DeviceNum[x]], - ((bc->ButtonNum[x] >> 8) & 0x1F)) & - (bc->ButtonNum[x]&0xFF)) - return 1; - } - else if(bc->ButtonNum[x] & 0x8000) - { - /* Axis "button" */ - int pos; - pos = SDL_JoystickGetAxis(s_Joysticks[bc->DeviceNum[x]], - bc->ButtonNum[x] & 16383); - if ((bc->ButtonNum[x] & 0x4000) && pos <= -16383) { - return 1; - } else if (!(bc->ButtonNum[x] & 0x4000) && pos >= 16363) { - return 1; - } - } - else if(SDL_JoystickGetButton(s_Joysticks[bc->DeviceNum[x]], - bc->ButtonNum[x])) - return 1; + return 0; } + if ( bc->DeviceNum < 0 ) + { + return 0; + } + js = jsDev[bc->DeviceNum].getJS(); + + if (bc->ButtonNum & 0x2000) + { + /* Hat "button" */ + if (SDL_JoystickGetHat( js, + ((bc->ButtonNum >> 8) & 0x1F)) & + (bc->ButtonNum&0xFF)) + { + bc->state = 1; + return 1; + } + else + { + bc->state = 0; + } + } + else if (bc->ButtonNum & 0x8000) + { + /* Axis "button" */ + int pos; + pos = SDL_JoystickGetAxis( js, + bc->ButtonNum & 0x3FFF); + if ((bc->ButtonNum & 0x4000) && pos <= -16383) + { + bc->state = 1; + return 1; + } + else if (!(bc->ButtonNum & 0x4000) && pos >= 16363) + { + bc->state = 1; + return 1; + } + else + { + bc->state = 0; + } + } + else if (SDL_JoystickGetButton( js, + bc->ButtonNum)) + { + bc->state = 1; + return 1; + } + else + { + bc->state = 0; + } + return 0; } +//******************************************************************************** + +//static void printJoystick( SDL_Joystick *js ) +//{ +// char guidStr[64]; +// SDL_Joystick *js; +// +// js = jsDev[i].getJS(); +// +// SDL_JoystickGUID guid = SDL_JoystickGetGUID( js ); +// +// SDL_JoystickGetGUIDString( guid, guidStr, sizeof(guidStr) ); +// +// printf("JoyStickID: %i: %s \n", +// SDL_JoystickInstanceID( js ), SDL_JoystickName( js ) ); +// printf("GUID: %s \n", guidStr ); +// printf("NumAxes: %i \n", SDL_JoystickNumAxes(js) ); +// printf("NumButtons: %i \n", SDL_JoystickNumButtons(js) ); +// printf("NumHats: %i \n", SDL_JoystickNumHats(js) ); +// +//} + +//******************************************************************************** /** * Shutdown the SDL joystick subsystem. */ int -KillJoysticks() +KillJoysticks(void) { int n; /* joystick index */ - if(!s_jinited) { + if (!s_jinited) { return -1; } - for(n = 0; n < MAX_JOYSTICKS; n++) { - if (s_Joysticks[n] != 0) { - SDL_JoystickClose(s_Joysticks[n]); - } - s_Joysticks[n]=0; + for (n = 0; n < MAX_JOYSTICKS; n++) + { + jsDev[n].close(); } SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + + printf("Kill Joysticks:\n"); + s_jinited = 0; + return 0; } +//******************************************************************************** +int AddJoystick( int which ) +{ + if ( jsDev[ which ].isConnected() ) + { + //printf("Error: Joystick already exists at device index %i \n", which ); + return -1; + } + else + { + if ( SDL_IsGameController(which) ) + { + jsDev[which].gc = SDL_GameControllerOpen(which); + + if ( jsDev[which].gc == NULL ) + { + printf("Could not open game controller %d: %s.\n", + which, SDL_GetError()); + } + else + { + //printf("Added Joystick: %i \n", which ); + jsDev[which].init(which); + //jsDev[which].print(); + //printJoystick( s_Joysticks[which] ); + } + } + else + { + jsDev[which].js = SDL_JoystickOpen(which); + + if ( jsDev[which].js == NULL ) + { + printf("Could not open joystick %d: %s.\n", + which, SDL_GetError()); + } + else + { + //printf("Added Joystick: %i \n", which ); + jsDev[which].init(which); + //jsDev[which].print(); + //printJoystick( s_Joysticks[which] ); + } + } + } + return 0; +} + +//******************************************************************************** +int RemoveJoystick( int which ) +{ + //printf("Remove Joystick: %i \n", which ); + + for (int i=0; iMAX_JOYSTICKS) { + if (total > MAX_JOYSTICKS) + { total = MAX_JOYSTICKS; } - for(n = 0; n < total; n++) { + for (n = 0; n < total; n++) + { /* Open the joystick under SDL. */ - s_Joysticks[n] = SDL_JoystickOpen(n); - //printf("Could not open joystick %d: %s.\n", - //joy[n] - 1, SDL_GetError()); - continue; + AddJoystick(n); } + printf("Init Joysticks: %i \n", total ); s_jinited = 1; return 1; } +//******************************************************************************** diff --git a/src/drivers/sdl/sdl-joystick.h b/src/drivers/sdl/sdl-joystick.h new file mode 100644 index 00000000..568f736b --- /dev/null +++ b/src/drivers/sdl/sdl-joystick.h @@ -0,0 +1,92 @@ +// sdl-joystick.h + +#ifndef __SDL_JOYSTICK_H__ +#define __SDL_JOYSTICK_H__ + +#include + +#include "Qt/main.h" +#include "Qt/input.h" +#include "Qt/sdl.h" + +#define MAX_JOYSTICKS 32 + +struct nesGamePadMap_t +{ + char guid[64]; + char name[128]; + char btn[GAMEPAD_NUM_BUTTONS][32]; + char os[64]; + + nesGamePadMap_t(void); + ~nesGamePadMap_t(void); + + void clearMapping(void); + int parseMapping( const char *text ); +}; + +struct jsDev_t +{ + SDL_Joystick *js; + SDL_GameController *gc; + + jsDev_t(void); + //~jsDev_t(void); + + void init( int idx ); + int close(void); + SDL_Joystick *getJS(void); + bool isGameController(void); + bool isConnected(void); + void print(void); + int bindPort( int idx ); + int unbindPort( int idx ); + int getBindPorts(void); + const char *getName(void); + const char *getGUID(void); + + private: + int devIdx; + int portBindMask; + std::string guidStr; + std::string name; +}; + +class GamePad_t +{ + public: + + ButtConfig bmap[GAMEPAD_NUM_BUTTONS]; + + GamePad_t(void); + ~GamePad_t(void); + + int init( int port, const char *guid, const char *profile = NULL ); + const char *getGUID(void); + + int loadDefaults(void); + int loadProfile( const char *name, const char *guid = NULL ); + + int getDeviceIndex(void){ return devIdx; } + int setDeviceIndex( int devIdx ); + int setMapping( const char *map ); + int setMapping( nesGamePadMap_t *map ); + + int createProfile( const char *name ); + int getMapFromFile( const char *filename, char *out ); + int getDefaultMap( char *out, const char *guid = NULL ); + int saveMappingToFile( const char *filename, const char *txtMap ); + int saveCurrentMapToFile( const char *filename ); + int deleteMapping( const char *name ); + + private: + int devIdx; + int portNum; + +}; + +extern GamePad_t GamePad[4]; + +jsDev_t *getJoystickDevice( int devNum ); + +#endif diff --git a/src/drivers/sdl/sdl-sound.cpp b/src/drivers/sdl/sdl-sound.cpp index 00b7c9a6..dbba79df 100644 --- a/src/drivers/sdl/sdl-sound.cpp +++ b/src/drivers/sdl/sdl-sound.cpp @@ -49,16 +49,21 @@ fillaudio(void *udata, uint8 *stream, int len) { + static int16_t sample = 0; int16 *tmps = (int16*)stream; len >>= 1; - while(len) { - int16 sample = 0; - if(s_BufferIn) { + while (len) + { + if (s_BufferIn) + { sample = s_Buffer[s_BufferRead]; s_BufferRead = (s_BufferRead + 1) % s_BufferSize; s_BufferIn--; } else { - sample = 0; + // Retain last known sample value, helps avoid clicking + // noise when sound system is starved of audio data. + //sample = 0; + //bufStarveDetected = 1; } *tmps = sample; @@ -179,11 +184,20 @@ WriteSound(int32 *buf, { extern int EmulationPaused; if (EmulationPaused == 0) + { + int waitCount = 0; + while(Count) { while(s_BufferIn == s_BufferSize) { - SDL_Delay(1); + SDL_Delay(1); waitCount++; + + if ( waitCount > 1000 ) + { + printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n"); + return; + } } s_Buffer[s_BufferWrite] = *buf; @@ -196,6 +210,7 @@ WriteSound(int32 *buf, buf++; } + } } /** diff --git a/src/drivers/sdl/sdl-video.cpp b/src/drivers/sdl/sdl-video.cpp index c4bc3e82..0edbfb4c 100644 --- a/src/drivers/sdl/sdl-video.cpp +++ b/src/drivers/sdl/sdl-video.cpp @@ -472,6 +472,21 @@ int init_gtk3_sdl_video( void ) int sdlRendW, sdlRendH; int vsyncEnabled=0; + if ( (gtk_draw_area_width < GLX_NES_WIDTH) || (gtk_draw_area_height < GLX_NES_HEIGHT) ) + { + usleep(100000); + return -1; + } + if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) + { + printf("[SDL] Failed to initialize video subsystem.\n"); + return -1; + } + else + { + printf("Initialized SDL Video Subsystem\n"); + } + if ( gdkWin == NULL ) { printf("Error: Failed to obtain gdkWindow Handle for evbox widget\n"); @@ -544,6 +559,7 @@ int destroy_gtk3_sdl_video(void) SDL_DestroyRenderer(sdlRenderer); sdlRenderer = NULL; } + //SDL_QuitSubSystem(SDL_INIT_VIDEO); return 0; } //***************************************************************************** diff --git a/src/drivers/sdl/sdl.cpp b/src/drivers/sdl/sdl.cpp index cc79ebf7..59d2e6c1 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -355,6 +355,7 @@ FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count) { + int blitDone = 0; extern int FCEUDnetplay; #ifdef CREATE_AVI @@ -381,8 +382,8 @@ FCEUD_Update(uint8 *XBuf, if (!mutecapture) if(Count > 0 && Buffer) WriteSound(Buffer,Count); } - if(inited & 2) - FCEUD_UpdateInput(); + // if(inited & 2) + // FCEUD_UpdateInput(); if(XBuf && (inited & 4)) BlitScreen(XBuf); //SpeedThrottle(); @@ -414,7 +415,9 @@ FCEUD_Update(uint8 *XBuf, // don't underflow when scaling fps if(g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow)) { if(XBuf && (inited&4) && !(NoWaiting & 2)) - BlitScreen(XBuf); + { + BlitScreen(XBuf); blitDone = 1; + } Buffer+=can; Count-=can; if(Count) { @@ -449,24 +452,23 @@ FCEUD_Update(uint8 *XBuf, } } else { - if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused())) - while (SpeedThrottle()) + //if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused())) + //while (SpeedThrottle()) + //{ + // FCEUD_UpdateInput(); + //} + if (XBuf && (inited&4)) { - FCEUD_UpdateInput(); - } - if(XBuf && (inited&4)) { - BlitScreen(XBuf); + BlitScreen(XBuf); blitDone = 1; + } + } + if ( !blitDone ) + { + if (XBuf && (inited&4)) + { + BlitScreen(XBuf); blitDone = 1; } } - FCEUD_UpdateInput(); - //if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE)) - // SpeedThrottle(); - //if(XBuf && (inited&4)) - //{ - // BlitScreen(XBuf); - //} - //if(Count) - // WriteSound(Buffer,Count,NoWaiting); //FCEUD_UpdateInput(); } @@ -559,10 +561,15 @@ int main(int argc, char *argv[]) #endif /* SDL_INIT_VIDEO Needed for (joystick config) event processing? */ - if(SDL_Init(SDL_INIT_VIDEO)) { + if (SDL_Init(SDL_INIT_VIDEO)) + { printf("Could not initialize SDL: %s.\n", SDL_GetError()); return(-1); } + if ( SDL_SetHint( SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1" ) == SDL_FALSE ) + { + printf("Error setting SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS\n"); + } //#ifdef OPENGL // SDL_GL_LoadLibrary(0); @@ -615,12 +622,14 @@ int main(int argc, char *argv[]) std::string s; - g_config->getOption("SDL.InputCfg", &s); - if(s.size() != 0) - { - InitVideo(GameInfo); - InputCfg(s); - } + //g_config->getOption("SDL.InputCfg", &s); + // + //if(s.size() != 0) + //{ + // InitVideo(GameInfo); + // InputCfg(s); + //} + // set the FAMICOM PAD 2 Mic thing { int t; @@ -632,18 +641,6 @@ int main(int argc, char *argv[]) // update the input devices UpdateInput(g_config); - // check if opengl is enabled with a scaler and display an error and bail - int opengl; - int scaler; - g_config->getOption("SDL.OpenGL", &opengl); - g_config->getOption("SDL.SpecialFilter", &scaler); - if(opengl && scaler) - { - printf("Scalers are not supported in OpenGL mode. Terminating.\n"); - exit(2); - } - - // check for a .fcm file to convert to .fm2 g_config->getOption ("SDL.FCMConvert", &s); g_config->setOption ("SDL.FCMConvert", ""); @@ -923,8 +920,9 @@ int main(int argc, char *argv[]) } else { - SDL_Delay(1); + SDL_Delay(10); } + FCEUD_UpdateInput(); while(gtk_events_pending()) {