From 5bfbbbba7e197c1d24a071ce4bb20e6dd1eed2a2 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sun, 9 Aug 2020 05:55:59 -0400 Subject: [PATCH] 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;