From 989d39c26eb9f724e39001e7ae1423a1d7f16ae0 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 05:17:48 -0400 Subject: [PATCH 1/8] Back ported SDL sound bug fixes from QT to GTK GUI. --- src/drivers/sdl/sdl-sound.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) 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++; } + } } /** From 61894c77727d1c0b902c5530a5b4a74751b1f169 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 05:21:29 -0400 Subject: [PATCH 2/8] Bug fix to sync video driver selection on GTK GUI at init. --- src/drivers/sdl/gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 8feaacf9..6e6211c8 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -1052,7 +1052,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); From 5bfbbbba7e197c1d24a071ce4bb20e6dd1eed2a2 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 05:55:59 -0400 Subject: [PATCH 3/8] Back ported SDL joystick/gamepad improvements from Qt to GTK gui. --- src/drivers/sdl/config.cpp | 20 +- src/drivers/sdl/dface.h | 2 + src/drivers/sdl/gui.cpp | 73 +-- src/drivers/sdl/input.cpp | 688 ++++++++++----------- src/drivers/sdl/input.h | 41 +- src/drivers/sdl/sdl-joystick.cpp | 997 +++++++++++++++++++++++++++++-- src/drivers/sdl/sdl-joystick.h | 92 +++ src/drivers/sdl/sdl.cpp | 14 +- 8 files changed, 1441 insertions(+), 486 deletions(-) create mode 100644 src/drivers/sdl/sdl-joystick.h 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 6e6211c8..3e791ac6 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 @@ -74,7 +75,6 @@ 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 }; @@ -137,9 +137,6 @@ int configGamepadButton (GtkButton * button, gpointer 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; @@ -154,28 +151,28 @@ int configGamepadButton (GtkButton * button, gpointer p) snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); prefix = buf; - DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus ); + 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]); +// 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)); + ButtonName (&GamePad[padNo].bmap[x])); if ( buttonMappings[x] != NULL ) { @@ -698,28 +695,25 @@ void updateGamepadConfig (GtkWidget * w, gpointer p) int i; char strBuf[128]; - if ( (padNoCombo == NULL) || (configNoCombo == NULL) ) + if ( (padNoCombo == 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) + if (GamePad[padNo].bmap[i].ButtType == BUTTC_KEYBOARD) { snprintf (strBuf, sizeof (strBuf), "%s", - SDL_GetKeyName (GamePadConfig[padNo][i]. - ButtonNum[configNo])); + SDL_GetKeyName (GamePad[padNo].bmap[i]. + ButtonNum)); } else - sprintf (strBuf, "%s", ButtonName( &GamePadConfig[padNo][i], configNo ) ); + sprintf (strBuf, "%s", ButtonName( &GamePad[padNo].bmap[i] ) ); if ( mappedKey != NULL ) { @@ -734,7 +728,6 @@ static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p) gtk_widget_destroy (w); padNoCombo = NULL; - configNoCombo = NULL; for (int i = 0; i < 10; i++) { @@ -799,20 +792,6 @@ void openGamepadConfig (void) 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))); @@ -827,8 +806,6 @@ void openGamepadConfig (void) 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); diff --git a/src/drivers/sdl/input.cpp b/src/drivers/sdl/input.cpp index 36d2199f..93cb7f78 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 @@ -985,6 +980,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 +994,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 +1001,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 +1017,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 +1026,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 +1101,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 +1139,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 +1208,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 (); @@ -1600,36 +1574,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 +1628,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 +1643,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,9 +1667,24 @@ 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); @@ -1699,23 +1695,24 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigS 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 +1734,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 +1773,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 +1984,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 +2079,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 +2112,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 +2138,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 +2163,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 +2188,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 +2213,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 +2238,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 +2263,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 +2277,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..6e3bedf6 100644 --- a/src/drivers/sdl/sdl-joystick.cpp +++ b/src/drivers/sdl/sdl-joystick.cpp @@ -22,102 +22,1015 @@ /// \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); + + 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); } 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.cpp b/src/drivers/sdl/sdl.cpp index cc79ebf7..3c92e1fa 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -615,12 +615,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; From 1331aeca14c5e2967221ee8fa9976cc8f8da9272 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 07:11:28 -0400 Subject: [PATCH 4/8] input device select combo box logic in work for GTK Gui. --- src/drivers/sdl/gui.cpp | 74 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 3e791ac6..b8a204fa 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -74,8 +74,9 @@ extern bool gtk_gui_run; GtkWidget *MainWindow = NULL; GtkWidget *evbox = NULL; -GtkWidget *padNoCombo = NULL; -GtkWidget *buttonMappings[10] = { NULL }; +static GtkWidget *padNoCombo = NULL; +static GtkWidget *devSelCombo = NULL; +static GtkWidget *buttonMappings[10] = { NULL }; static GtkWidget *Menubar = NULL; static GtkRadioMenuItem *stateSlot[10] = { NULL }; bool gtkIsStarted = false; @@ -739,15 +740,17 @@ static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p) // 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* configNoLabel; + 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), @@ -792,6 +795,67 @@ void openGamepadConfig (void) 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); + } + //printf("Type is String: '%s'\n", s ); + } + } + g_value_unset(&value); + + iterValid = gtk_tree_model_iter_next( treeModel, &iter ); + } + } + //g_signal_connect (typeCombo, "changed", G_CALLBACK (setInputDevice), // gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT // (typeCombo))); @@ -809,6 +873,10 @@ void openGamepadConfig (void) 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); From 1d417a49ae8409b38948aa184d9a0fb7687e21d5 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 22:19:38 -0400 Subject: [PATCH 5/8] Back ported SDL2 game controller improvements to GTK from QT GUI. --- src/CMakeLists.txt | 1 + src/drivers/Qt/GamePadConf.cpp | 1 + src/drivers/sdl/gui.cpp | 664 ++++++++++++++++--------------- src/drivers/sdl/gui.h | 4 + src/drivers/sdl/input.cpp | 7 +- src/drivers/sdl/sdl-joystick.cpp | 5 + src/drivers/sdl/sdl-video.cpp | 16 + src/drivers/sdl/sdl.cpp | 15 +- 8 files changed, 371 insertions(+), 342 deletions(-) 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/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index b8a204fa..4b7c2c03 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -74,14 +74,10 @@ extern bool gtk_gui_run; GtkWidget *MainWindow = NULL; GtkWidget *evbox = NULL; -static GtkWidget *padNoCombo = NULL; -static GtkWidget *devSelCombo = NULL; -static 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; @@ -93,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) @@ -131,63 +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; - - 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]); +//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; // -// if (GamePadConfig[padNo][x].ButtType[0] == BUTTC_KEYBOARD) +// 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 ) // { -// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf); // } -// 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; -} +// +// ButtonConfigEnd (); +// +// buttonConfigStatus = 1; +// +// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); +// +// return 0; +//} void resetVideo (void) { @@ -675,275 +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) ) - { - 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); - } - //printf("Type is String: '%s'\n", s ); - } - } - g_value_unset(&value); - - iterValid = gtk_tree_model_iter_next( treeModel, &iter ); - } - } - - //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; -} int setBufSize (GtkWidget * w, gpointer p) { @@ -2386,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 93cb7f78..7c2f0c88 100644 --- a/src/drivers/sdl/input.cpp +++ b/src/drivers/sdl/input.cpp @@ -952,6 +952,8 @@ UpdatePhysicalInput () { SDL_Event event; + //SDL_JoystickUpdate(); + // loop, handling all pending events while (SDL_PollEvent (&event)) { @@ -1330,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) ); @@ -1691,6 +1693,7 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int *buttonConfigStatus #endif while (SDL_PollEvent (&event)) { + printf("Event Type: %i \n", event.type ); done++; switch (event.type) { diff --git a/src/drivers/sdl/sdl-joystick.cpp b/src/drivers/sdl/sdl-joystick.cpp index 6e3bedf6..3330d32c 100644 --- a/src/drivers/sdl/sdl-joystick.cpp +++ b/src/drivers/sdl/sdl-joystick.cpp @@ -930,6 +930,7 @@ KillJoysticks(void) } SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + printf("Kill Joysticks:\n"); s_jinited = 0; return 0; @@ -1018,6 +1019,9 @@ InitJoysticks(void) } SDL_InitSubSystem(SDL_INIT_JOYSTICK); + SDL_JoystickEventState(SDL_ENABLE); + //SDL_JoystickEventState(SDL_DISABLE); + total = SDL_NumJoysticks(); if (total > MAX_JOYSTICKS) { @@ -1029,6 +1033,7 @@ InitJoysticks(void) /* Open the joystick under SDL. */ AddJoystick(n); } + printf("Init Joysticks: %i \n", total ); s_jinited = 1; return 1; 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 3c92e1fa..21dfba68 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -559,7 +559,8 @@ 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); } @@ -634,18 +635,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", ""); From cd99eaecd305dfb74f47e2a857846db3e187f125 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 22:20:02 -0400 Subject: [PATCH 6/8] Added missing files. --- src/drivers/sdl/GamePadConf.cpp | 832 ++++++++++++++++++++++++++++++++ src/drivers/sdl/GamePadConf.h | 4 + 2 files changed, 836 insertions(+) create mode 100644 src/drivers/sdl/GamePadConf.cpp create mode 100644 src/drivers/sdl/GamePadConf.h diff --git a/src/drivers/sdl/GamePadConf.cpp b/src/drivers/sdl/GamePadConf.cpp new file mode 100644 index 00000000..c5b95838 --- /dev/null +++ b/src/drivers/sdl/GamePadConf.cpp @@ -0,0 +1,832 @@ +// 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); + 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); + 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); + 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); From 1c6851c3f0fd22da102bd411fd6ded048c5fca9f Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Mon, 10 Aug 2020 21:04:42 -0400 Subject: [PATCH 7/8] Bug fix for SDL joystick not working using SDL video driver. By default SDL joystick inputs are ignored if the SDL window does not have focus. Set SDL HINT to allow for background joystick inputs to accepted (i.e. joystick inputs come through even though window not in focus). --- src/drivers/Qt/fceuWrapper.cpp | 4 +++ src/drivers/sdl/sdl.cpp | 45 ++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 19 deletions(-) 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/sdl.cpp b/src/drivers/sdl/sdl.cpp index 21dfba68..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(); } @@ -564,6 +566,10 @@ int main(int argc, char *argv[]) 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); @@ -914,8 +920,9 @@ int main(int argc, char *argv[]) } else { - SDL_Delay(1); + SDL_Delay(10); } + FCEUD_UpdateInput(); while(gtk_events_pending()) { From b16514fcb4fcb95f0ee09ec9b6962fdbe5ded71c Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Mon, 10 Aug 2020 21:12:40 -0400 Subject: [PATCH 8/8] A few box spacing updates on GTK gamepad config window. --- src/drivers/sdl/GamePadConf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/sdl/GamePadConf.cpp b/src/drivers/sdl/GamePadConf.cpp index c5b95838..ea292b84 100644 --- a/src/drivers/sdl/GamePadConf.cpp +++ b/src/drivers/sdl/GamePadConf.cpp @@ -585,6 +585,7 @@ void openGamepadConfig (void) 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"); @@ -616,6 +617,7 @@ void openGamepadConfig (void) 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"); @@ -698,6 +700,7 @@ void openGamepadConfig (void) 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 ("");