From 10b84fa47cbf187b651f220d49fdbf972a4a5d70 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Wed, 22 Jul 2020 22:17:53 -0400 Subject: [PATCH 01/13] Added SDL game controller logic to sdl-joystick. Preparing to re-vamp the input module. --- src/drivers/Qt/GamePadConf.cpp | 3 + src/drivers/Qt/dface.h | 2 + src/drivers/Qt/input.cpp | 28 +--- src/drivers/Qt/sdl-joystick.cpp | 223 +++++++++++++++++++++++++++++--- 4 files changed, 217 insertions(+), 39 deletions(-) diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index 24cfb88c..eafc6de9 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -2,6 +2,7 @@ // #include "Qt/GamePadConf.h" #include "Qt/main.h" +#include "Qt/dface.h" #include "Qt/input.h" #include "Qt/config.h" #include "Qt/keyscan.h" @@ -20,6 +21,8 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) QPushButton *closebutton; QPushButton *clearButton[GAMEPAD_NUM_BUTTONS]; + InitJoysticks(); + portNum = 0; configNo = 0; buttonConfigStatus = 1; diff --git a/src/drivers/Qt/dface.h b/src/drivers/Qt/dface.h index 2f3890ec..12c515ee 100644 --- a/src/drivers/Qt/dface.h +++ b/src/drivers/Qt/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/Qt/input.cpp b/src/drivers/Qt/input.cpp index 552f7ad8..640be3a8 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -956,6 +956,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; } @@ -964,8 +970,6 @@ UpdatePhysicalInput () } -static int bcpv=0, bcpj=0; - /** * Begin configuring the buttons by placing the video and joystick * subsystems into a well-known state. Button configuration really @@ -973,13 +977,7 @@ static int bcpv=0, bcpj=0; */ int ButtonConfigBegin () { - // shut down the joystick subsystems - //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; @@ -995,18 +993,6 @@ 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; } diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 71148b2e..0434e9f3 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -30,7 +30,86 @@ #include #define MAX_JOYSTICKS 32 -static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL}; +struct jsDev_t +{ + SDL_Joystick *js; + SDL_GameController *gc; + + jsDev_t(void) + { + js = NULL; + gc = NULL; + }; + + //~jsDev_t(void) + //{ + // if ( js ) + // { + // SDL_JoystickClose( js ); js = NULL; + // } + // if ( gc ) + // { + // SDL_GameControllerClose( gc ); gc = NULL; + // } + //} + + int close(void) + { + if ( js ) + { + SDL_JoystickClose( js ); js = NULL; + } + if ( gc ) + { + SDL_GameControllerClose( gc ); gc = NULL; + } + return 0; + } + + SDL_Joystick *getJS(void) + { + if ( gc != NULL ) + { + return SDL_GameControllerGetJoystick( gc ); + } + return js; + } + + bool isGameController(void) + { + return ( gc != NULL ); + } + + bool inUse(void) + { + return ( (js != NULL) || (gc != NULL) ); + } + + void print(void) + { + char guidStr[64]; + + SDL_JoystickGUID guid = SDL_JoystickGetGUID( getJS() ); + + SDL_JoystickGetGUIDString( guid, guidStr, sizeof(guidStr) ); + + printf("JoyStickID: %i: '%s' \n", + SDL_JoystickInstanceID( getJS() ), SDL_JoystickName( getJS() ) ); + printf("GUID: %s \n", guidStr ); + printf("NumAxes: %i \n", SDL_JoystickNumAxes(getJS()) ); + printf("NumButtons: %i \n", SDL_JoystickNumButtons(getJS()) ); + printf("NumHats: %i \n", SDL_JoystickNumHats(getJS()) ); + + if ( gc ) + { + printf("GameController Name: '%s'\n", SDL_GameControllerName(gc) ); + printf("GameController Mapping: %s\n", SDL_GameControllerMapping(gc) ); + } + } +}; + +static jsDev_t jsDev[ MAX_JOYSTICKS ]; +//static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL}; static int s_jinited = 0; @@ -42,6 +121,7 @@ int DTestButtonJoy(ButtConfig *bc) { int x; + SDL_Joystick *js; for(x = 0; x < bc->NumC; x++) { @@ -49,10 +129,12 @@ DTestButtonJoy(ButtConfig *bc) { continue; } + js = jsDev[bc->DeviceNum[x]].getJS(); + if (bc->ButtonNum[x] & 0x2000) { /* Hat "button" */ - if(SDL_JoystickGetHat(s_Joysticks[bc->DeviceNum[x]], + if(SDL_JoystickGetHat( js, ((bc->ButtonNum[x] >> 8) & 0x1F)) & (bc->ButtonNum[x]&0xFF)) return 1; @@ -61,7 +143,7 @@ DTestButtonJoy(ButtConfig *bc) { /* Axis "button" */ int pos; - pos = SDL_JoystickGetAxis(s_Joysticks[bc->DeviceNum[x]], + pos = SDL_JoystickGetAxis( js, bc->ButtonNum[x] & 16383); if ((bc->ButtonNum[x] & 0x4000) && pos <= -16383) { return 1; @@ -69,57 +151,162 @@ DTestButtonJoy(ButtConfig *bc) return 1; } } - else if(SDL_JoystickGetButton(s_Joysticks[bc->DeviceNum[x]], + else if(SDL_JoystickGetButton( js, bc->ButtonNum[x])) return 1; } 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); return 0; } +int AddJoystick( int which ) +{ + if ( jsDev[ which ].inUse() ) + { + //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].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].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); + //if ( SDL_IsGameController(n) ) + //{ + // SDL_GameController *gc = SDL_GameControllerOpen(n); + // printf("Is Game Controller: %i \n", n); + + // printf("Mapping: %s \n", SDL_GameControllerMapping(gc) ); + //} + // s_Joysticks[n] = SDL_JoystickOpen(n); + + //if ( s_Joysticks[n] == NULL ) + //{ + // printf("Could not open joystick %d: %s.\n", + // n, SDL_GetError()); + //} + //else + //{ + // printf("Opened JS %i: \n", SDL_JoystickInstanceID( s_Joysticks[n] ) ); + // jsDev[which].print(); + // //printJoystick( s_Joysticks[n] ); + //} } s_jinited = 1; From e018b4b945d2a0e423ea7f815d57242e815f3d3e Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Thu, 23 Jul 2020 18:43:45 -0400 Subject: [PATCH 02/13] Removed unused button config arrays in preparation for implementing SDL2 game controller setup. --- src/drivers/Qt/GamePadConf.cpp | 38 ++- src/drivers/Qt/input.cpp | 431 ++++++++++++++++---------------- src/drivers/Qt/input.h | 14 +- src/drivers/Qt/sdl-joystick.cpp | 55 ++-- 4 files changed, 261 insertions(+), 277 deletions(-) diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index eafc6de9..66c05783 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -24,7 +24,6 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) InitJoysticks(); portNum = 0; - configNo = 0; buttonConfigStatus = 1; setWindowTitle( tr("GamePad Config") ); @@ -157,14 +156,14 @@ void GamePadConfDialog_t::updateCntrlrDpy(void) for (int i=0; isetText( tr(keyNameStr) ); } @@ -210,16 +209,16 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); prefix = buf; - DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus ); + DWaitButton (NULL, &GamePadConfig[padNo][x], &buttonConfigStatus ); g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[padNo][x].ButtonNum[configNo]); + GamePadConfig[padNo][x].ButtonNum); - if (GamePadConfig[padNo][x].ButtType[configNo] == BUTTC_KEYBOARD) + if (GamePadConfig[padNo][x].ButtType == BUTTC_KEYBOARD) { g_config->setOption (prefix + "DeviceType", "Keyboard"); } - else if (GamePadConfig[padNo][x].ButtType[configNo] == BUTTC_JOYSTICK) + else if (GamePadConfig[padNo][x].ButtType == BUTTC_JOYSTICK) { g_config->setOption (prefix + "DeviceType", "Joystick"); } @@ -228,9 +227,9 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) g_config->setOption (prefix + "DeviceType", "Unknown"); } g_config->setOption (prefix + "DeviceNum", - GamePadConfig[padNo][x].DeviceNum[configNo]); + GamePadConfig[padNo][x].DeviceNum); - keyNameStr = ButtonName( &GamePadConfig[padNo][x], configNo ); + keyNameStr = ButtonName( &GamePadConfig[padNo][x] ); keyName[x]->setText( keyNameStr ); button[x]->setText("Change"); @@ -245,7 +244,7 @@ void GamePadConfDialog_t::clearButton( int padNo, int x ) char buf[256]; std::string prefix; - GamePadConfig[padNo][x].ButtonNum[configNo] = -1; + GamePadConfig[padNo][x].ButtonNum = -1; keyName[x]->setText(""); @@ -253,7 +252,7 @@ void GamePadConfDialog_t::clearButton( int padNo, int x ) prefix = buf; g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[padNo][x].ButtonNum[configNo]); + GamePadConfig[padNo][x].ButtonNum); } //---------------------------------------------------- @@ -396,19 +395,18 @@ void GamePadConfDialog_t::loadDefaults(void) for (int x=0; xsetOption (prefix + GamePadNames[x], - GamePadConfig[portNum][x].ButtonNum[configNo]); + GamePadConfig[portNum][x].ButtonNum); - if (GamePadConfig[portNum][x].ButtType[configNo] == BUTTC_KEYBOARD) + if (GamePadConfig[portNum][x].ButtType == BUTTC_KEYBOARD) { g_config->setOption (prefix + "DeviceType", "Keyboard"); } - else if (GamePadConfig[portNum][x].ButtType[configNo] == BUTTC_JOYSTICK) + else if (GamePadConfig[portNum][x].ButtType == BUTTC_JOYSTICK) { g_config->setOption (prefix + "DeviceType", "Joystick"); } @@ -417,7 +415,7 @@ void GamePadConfDialog_t::loadDefaults(void) g_config->setOption (prefix + "DeviceType", "Unknown"); } g_config->setOption (prefix + "DeviceNum", - GamePadConfig[portNum][x].DeviceNum[configNo]); + GamePadConfig[portNum][x].DeviceNum); } updateCntrlrDpy(); } diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index 640be3a8..6da51b33 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -1002,32 +1002,28 @@ 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; - } + return 1; } - else if (bc->ButtType[x] == BUTTC_JOYSTICK) + } + 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},{-1},0} +#define MK(x) {BUTTC_KEYBOARD,0,MKK(x)} +//#define MK2(x1,x2) {BUTTC_KEYBOARD,0,MKK(x1)} +#define MKZ() {0,0,-1} #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] = @@ -1549,42 +1545,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]; name[0] = 0; - if (bc->ButtonNum[which] == -1) + if (bc->ButtonNum == -1) { return name; } - switch (bc->ButtType[which]) + 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); @@ -1603,7 +1599,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 ); @@ -1618,7 +1614,7 @@ 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_t * 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]; @@ -1670,23 +1666,23 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi { case SDL_KEYDOWN: //printf("SDL KeyDown:%i \n", event.key.keysym.sym ); - bc->ButtType[wb] = BUTTC_KEYBOARD; - bc->DeviceNum[wb] = 0; - bc->ButtonNum[wb] = 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); @@ -1708,9 +1704,9 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi (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); @@ -1747,162 +1743,161 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi * 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 (); +//} /** @@ -2071,10 +2066,9 @@ UpdateInput (Config * config) { 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; + GamePadConfig[i][j].ButtType = type; + GamePadConfig[i][j].DeviceNum = devnum; + GamePadConfig[i][j].ButtonNum = button; } } @@ -2104,10 +2098,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; } } @@ -2131,10 +2124,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 @@ -2157,10 +2149,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 @@ -2183,10 +2174,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 @@ -2209,10 +2199,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 @@ -2235,10 +2224,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 @@ -2261,10 +2249,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; } } diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index d9a70118..53eeda0a 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -5,7 +5,7 @@ #include "common/configSys.h" -#define MAXBUTTCONFIG 4 +//#define MAXBUTTCONFIG 4 enum { BUTTC_KEYBOARD = 0, @@ -14,10 +14,10 @@ enum { }; struct ButtConfig { - int ButtType[MAXBUTTCONFIG]; - int DeviceNum[MAXBUTTCONFIG]; - int ButtonNum[MAXBUTTCONFIG]; - uint32_t NumC; + int ButtType; //[MAXBUTTCONFIG]; + int DeviceNum; //[MAXBUTTCONFIG]; + int ButtonNum; //[MAXBUTTCONFIG]; + //uint32_t NumC; //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ }; @@ -32,7 +32,7 @@ int getKeyState( int k ); int ButtonConfigBegin(); void ButtonConfigEnd(); void ConfigButton(char *text, ButtConfig *bc); -int DWaitButton(const uint8_t *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL); +int DWaitButton(const uint8_t *text, ButtConfig *bc, int *buttonConfigStatus = NULL); #define FCFGD_GAMEPAD 1 @@ -62,6 +62,6 @@ void UpdateInput(Config *config); 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/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 0434e9f3..1d02e988 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -120,41 +120,40 @@ static int s_jinited = 0; int DTestButtonJoy(ButtConfig *bc) { - int x; SDL_Joystick *js; - for(x = 0; x < bc->NumC; x++) + if (bc->ButtonNum == -1) { - if (bc->ButtonNum[x] == -1) - { - continue; - } - js = jsDev[bc->DeviceNum[x]].getJS(); + return 0; + } + js = jsDev[bc->DeviceNum].getJS(); - if (bc->ButtonNum[x] & 0x2000) - { - /* Hat "button" */ - if(SDL_JoystickGetHat( js, - ((bc->ButtonNum[x] >> 8) & 0x1F)) & - (bc->ButtonNum[x]&0xFF)) - return 1; + if (bc->ButtonNum & 0x2000) + { + /* Hat "button" */ + if(SDL_JoystickGetHat( js, + ((bc->ButtonNum >> 8) & 0x1F)) & + (bc->ButtonNum&0xFF)) + return 1; + } + else if (bc->ButtonNum & 0x8000) + { + /* Axis "button" */ + int pos; + pos = SDL_JoystickGetAxis( js, + bc->ButtonNum & 16383); + if ((bc->ButtonNum & 0x4000) && pos <= -16383) { + return 1; + } else if (!(bc->ButtonNum & 0x4000) && pos >= 16363) { + return 1; } - else if (bc->ButtonNum[x] & 0x8000) - { - /* Axis "button" */ - int pos; - pos = SDL_JoystickGetAxis( js, - 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( js, - bc->ButtonNum[x])) + } + else if(SDL_JoystickGetButton( js, + bc->ButtonNum)) + { return 1; } + return 0; } From e50d6e22edf7c17f02292c7c2a6e60f27dd9f78e Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 24 Jul 2020 00:11:11 -0400 Subject: [PATCH 03/13] Added logic to load default game pad button bindings from SDL database. --- src/drivers/Qt/GamePadConf.cpp | 161 +++++++++----- src/drivers/Qt/GamePadConf.h | 7 +- src/drivers/Qt/input.cpp | 2 + src/drivers/Qt/input.h | 3 +- src/drivers/Qt/sdl-joystick.cpp | 358 ++++++++++++++++++++++++-------- src/drivers/Qt/sdl-joystick.h | 58 ++++++ 6 files changed, 452 insertions(+), 137 deletions(-) create mode 100644 src/drivers/Qt/sdl-joystick.h diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index 66c05783..6a149f60 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -6,16 +6,18 @@ #include "Qt/input.h" #include "Qt/config.h" #include "Qt/keyscan.h" +#include "Qt/sdl-joystick.h" #include "Qt/fceuWrapper.h" //---------------------------------------------------- GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) : QDialog( parent ) { - QHBoxLayout *hbox1, *hbox2; + QHBoxLayout *hbox1, *hbox2, *hbox3, *hbox4; QGridLayout *grid; QCheckBox *efs_chkbox, *udlr_chkbox; QGroupBox *frame; + QLabel *label; QPushButton *loadDefaultButton; QPushButton *clearAllButton; QPushButton *closebutton; @@ -30,8 +32,10 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) hbox1 = new QHBoxLayout(); hbox2 = new QHBoxLayout(); + hbox3 = new QHBoxLayout(); + hbox4 = new QHBoxLayout(); - QLabel *label = new QLabel(tr("Port:")); + label = new QLabel(tr("Port:")); portSel = new QComboBox(); hbox1->addWidget( label ); hbox1->addWidget( portSel ); @@ -41,6 +45,34 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) portSel->addItem( tr("3"), 2 ); portSel->addItem( tr("4"), 3 ); + label = new QLabel(tr("Device:")); + devSel = new QComboBox(); + hbox2->addWidget( label ); + hbox2->addWidget( devSel ); + + devSel->addItem( tr("Keyboard"), -1 ); + + for (int i=0; iinUse() ) + { + char stmp[128]; + sprintf( stmp, "%i: %s", i, js->getName() ); + devSel->addItem( tr(stmp), i ); + } + } + } + + label = new QLabel(tr("GUID:")); + guidLbl = new QLabel(); + + hbox3->addWidget( label ); + hbox3->addWidget( guidLbl ); + efs_chkbox = new QCheckBox( tr("Enable Four Score") ); udlr_chkbox = new QCheckBox( tr("Allow Up+Down/Left+Right") ); @@ -87,9 +119,9 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) clearAllButton = new QPushButton(tr("Clear All")); closebutton = new QPushButton(tr("Close")); - hbox2->addWidget( loadDefaultButton ); - hbox2->addWidget( clearAllButton ); - hbox2->addWidget( closebutton ); + hbox4->addWidget( loadDefaultButton ); + hbox4->addWidget( clearAllButton ); + hbox4->addWidget( closebutton ); connect(button[0], SIGNAL(clicked()), this, SLOT(changeButton0(void)) ); connect(button[1], SIGNAL(clicked()), this, SLOT(changeButton1(void)) ); @@ -117,17 +149,20 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) ); connect(closebutton , SIGNAL(clicked()), this, SLOT(closeWindow(void)) ); - connect(portSel , SIGNAL(activated(int)), this, SLOT(controllerSelect(int)) ); + connect(portSel , SIGNAL(activated(int)), this, SLOT(portSelect(int)) ); + connect(devSel , SIGNAL(activated(int)), this, SLOT(deviceSelect(int)) ); connect(efs_chkbox , SIGNAL(stateChanged(int)), this, SLOT(ena4score(int)) ); connect(udlr_chkbox, SIGNAL(stateChanged(int)), this, SLOT(oppDirEna(int)) ); QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->addLayout( hbox1 ); + mainLayout->addLayout( hbox2 ); + mainLayout->addLayout( hbox3 ); mainLayout->addWidget( efs_chkbox ); mainLayout->addWidget( udlr_chkbox ); mainLayout->addWidget( frame ); - mainLayout->addLayout( hbox2 ); + mainLayout->addLayout( hbox4 ); setLayout( mainLayout ); @@ -156,26 +191,48 @@ void GamePadConfDialog_t::updateCntrlrDpy(void) for (int i=0; isetText( tr(keyNameStr) ); } } //---------------------------------------------------- -void GamePadConfDialog_t::controllerSelect(int index) +void GamePadConfDialog_t::portSelect(int index) { //printf("Port Number:%i \n", index); portNum = index; updateCntrlrDpy(); } //---------------------------------------------------- +void GamePadConfDialog_t::deviceSelect(int index) +{ + jsDev_t *js; + int devIdx = devSel->itemData(index).toInt(); + + js = getJoystickDevice( devIdx ); + + if ( js != NULL ) + { + if ( js->inUse() ) + { + guidLbl->setText( js->getGUID() ); + } + } + else + { + guidLbl->setText(""); + } + + updateCntrlrDpy(); +} +//---------------------------------------------------- void GamePadConfDialog_t::ena4score(int state) { int value = (state == Qt::Unchecked) ? 0 : 1; @@ -209,16 +266,16 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); prefix = buf; - DWaitButton (NULL, &GamePadConfig[padNo][x], &buttonConfigStatus ); + DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus ); g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[padNo][x].ButtonNum); + GamePad[padNo].bmap[x].ButtonNum); - if (GamePadConfig[padNo][x].ButtType == BUTTC_KEYBOARD) + if (GamePad[padNo].bmap[x].ButtType == BUTTC_KEYBOARD) { g_config->setOption (prefix + "DeviceType", "Keyboard"); } - else if (GamePadConfig[padNo][x].ButtType == BUTTC_JOYSTICK) + else if (GamePad[padNo].bmap[x].ButtType == BUTTC_JOYSTICK) { g_config->setOption (prefix + "DeviceType", "Joystick"); } @@ -227,9 +284,9 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) g_config->setOption (prefix + "DeviceType", "Unknown"); } g_config->setOption (prefix + "DeviceNum", - GamePadConfig[padNo][x].DeviceNum); + GamePad[padNo].bmap[x].DeviceNum); - keyNameStr = ButtonName( &GamePadConfig[padNo][x] ); + keyNameStr = ButtonName( &GamePad[padNo].bmap[x] ); keyName[x]->setText( keyNameStr ); button[x]->setText("Change"); @@ -244,7 +301,7 @@ void GamePadConfDialog_t::clearButton( int padNo, int x ) char buf[256]; std::string prefix; - GamePadConfig[padNo][x].ButtonNum = -1; + GamePad[padNo].bmap[x].ButtonNum = -1; keyName[x]->setText(""); @@ -252,7 +309,7 @@ void GamePadConfDialog_t::clearButton( int padNo, int x ) prefix = buf; g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[padNo][x].ButtonNum); + GamePad[padNo].bmap[x].ButtonNum); } //---------------------------------------------------- @@ -381,41 +438,49 @@ void GamePadConfDialog_t::clearAllCallback(void) //---------------------------------------------------- void GamePadConfDialog_t::loadDefaults(void) { + int index, devIdx; char buf[256]; std::string prefix; - if ( portNum > 0 ) + index = devSel->currentIndex(); + devIdx = devSel->itemData(index).toInt(); + + printf("Selected Device:%i : %i \n", index, devIdx ); + + if ( devIdx == -1 ) { - clearAllCallback(); - return; + snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", portNum); + prefix = buf; + + for (int x=0; xsetOption (prefix + GamePadNames[x], + GamePad[portNum].bmap[x].ButtonNum); + + if (GamePad[portNum].bmap[x].ButtType == BUTTC_KEYBOARD) + { + g_config->setOption (prefix + "DeviceType", "Keyboard"); + } + else if (GamePad[portNum].bmap[x].ButtType == BUTTC_JOYSTICK) + { + g_config->setOption (prefix + "DeviceType", "Joystick"); + } + else + { + g_config->setOption (prefix + "DeviceType", "Unknown"); + } + g_config->setOption (prefix + "DeviceNum", + GamePad[portNum].bmap[x].DeviceNum); + } } - - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", portNum); - prefix = buf; - - for (int x=0; xsetOption (prefix + GamePadNames[x], - GamePadConfig[portNum][x].ButtonNum); - - if (GamePadConfig[portNum][x].ButtType == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePadConfig[portNum][x].ButtType == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePadConfig[portNum][x].DeviceNum); + GamePad[portNum].devIdx = devIdx; + GamePad[portNum].loadDefaults(); } updateCntrlrDpy(); } diff --git a/src/drivers/Qt/GamePadConf.h b/src/drivers/Qt/GamePadConf.h index 0f83000c..fdf1c466 100644 --- a/src/drivers/Qt/GamePadConf.h +++ b/src/drivers/Qt/GamePadConf.h @@ -38,11 +38,13 @@ class GamePadConfDialog_t : public QDialog protected: QComboBox *portSel; + QComboBox *devSel; + QComboBox *profSel; + QLabel *guidLbl; QLabel *keyName[GAMEPAD_NUM_BUTTONS]; GamePadConfigButton_t *button[GAMEPAD_NUM_BUTTONS]; int portNum; - int configNo; int buttonConfigStatus; void changeButton( int port, int button ); @@ -80,6 +82,7 @@ class GamePadConfDialog_t : public QDialog void loadDefaults(void); void ena4score(int state); void oppDirEna(int state); - void controllerSelect(int index); + void portSelect(int index); + void deviceSelect(int index); }; diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index 6da51b33..b688b1a5 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -1956,6 +1956,8 @@ UpdateInput (Config * config) char buf[64]; std::string device, prefix; + InitJoysticks(); + for (unsigned int i = 0; i < 3; i++) { snprintf (buf, 64, "SDL.Input.%u", i); diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index 53eeda0a..14862205 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -21,7 +21,6 @@ struct ButtConfig //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ }; - extern int NoWaiting; extern CFGSTRUCT InputConfig[]; extern ARGPSTRUCT InputArgs[]; @@ -46,7 +45,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]; diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 1d02e988..705c8f1d 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -23,97 +23,303 @@ /// \brief Handles joystick input using the SDL. #include "Qt/sdl.h" +#include "Qt/sdl-joystick.h" #include #include #include #include -#define MAX_JOYSTICKS 32 -struct jsDev_t +//#define MAX_JOYSTICKS 32 + +GamePad_t GamePad[4]; + +jsDev_t::jsDev_t(void) { - SDL_Joystick *js; - SDL_GameController *gc; + js = NULL; + gc = NULL; +}; - jsDev_t(void) +int jsDev_t::close(void) +{ + if ( gc ) { - js = NULL; - gc = NULL; - }; - - //~jsDev_t(void) - //{ - // if ( js ) - // { - // SDL_JoystickClose( js ); js = NULL; - // } - // if ( gc ) - // { - // SDL_GameControllerClose( gc ); gc = NULL; - // } - //} - - int close(void) + SDL_GameControllerClose( gc ); gc = NULL; js = NULL; + } + else { if ( js ) { SDL_JoystickClose( js ); js = NULL; } - if ( gc ) - { - SDL_GameControllerClose( gc ); gc = NULL; - } - return 0; } + return 0; +} - SDL_Joystick *getJS(void) +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() ); +} + +bool jsDev_t::isGameController(void) +{ + return ( gc != NULL ); +} + +bool jsDev_t::inUse(void) +{ + return ( (js != NULL) || (gc != NULL) ); +} + +void jsDev_t::init( int idx ) +{ + SDL_JoystickGUID guid; + char stmp[64]; + + devIdx = idx; + + if ( gc ) { - if ( gc != NULL ) - { - return SDL_GameControllerGetJoystick( gc ); - } - return js; - } + js = SDL_GameControllerGetJoystick( gc ); - bool isGameController(void) + guid = SDL_JoystickGetGUID( js ); + + name.assign( SDL_GameControllerName(gc) ); + } + else { - return ( gc != NULL ); - } + guid = SDL_JoystickGetGUID( js ); - bool inUse(void) + 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 ) { - return ( (js != NULL) || (gc != NULL) ); + printf("GameController Name: '%s'\n", SDL_GameControllerName(gc) ); + printf("GameController Mapping: %s\n", SDL_GameControllerMapping(gc) ); } - - void print(void) - { - char guidStr[64]; - - SDL_JoystickGUID guid = SDL_JoystickGetGUID( getJS() ); - - SDL_JoystickGetGUIDString( guid, guidStr, sizeof(guidStr) ); - - printf("JoyStickID: %i: '%s' \n", - SDL_JoystickInstanceID( getJS() ), SDL_JoystickName( getJS() ) ); - printf("GUID: %s \n", guidStr ); - printf("NumAxes: %i \n", SDL_JoystickNumAxes(getJS()) ); - printf("NumButtons: %i \n", SDL_JoystickNumButtons(getJS()) ); - printf("NumHats: %i \n", SDL_JoystickNumHats(getJS()) ); - - if ( gc ) - { - printf("GameController Name: '%s'\n", SDL_GameControllerName(gc) ); - printf("GameController Mapping: %s\n", SDL_GameControllerMapping(gc) ); - } - } -}; +} static jsDev_t jsDev[ MAX_JOYSTICKS ]; -//static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL}; + +//******************************************************************************** +GamePad_t::GamePad_t(void) +{ + devIdx = 0; + + for (int i=0; i= 0 ) + { + bmap[bIdx].ButtType = BUTTC_JOYSTICK; + bmap[bIdx].DeviceNum = devIdx; + + if ( (val[i][0] == 'b') && isdigit( val[i][1] ) ) + { + bmap[bIdx].ButtonNum = atoi( &val[i][1] ); + } + else if ( (val[i][0] == 'h') && isdigit( val[i][1] ) && + (val[i][2] == '.') && isdigit( val[i][3] ) ) + { + int hatIdx, hatVal; + + hatIdx = val[i][1] - '0'; + hatVal = atoi( &val[i][3] ); + + bmap[bIdx].ButtonNum = 0x2000 | ( (hatIdx & 0x1F) << 8) | (hatVal & 0xFF); + } + else if ( (val[i][0] == 'a') || (val[i][1] == 'a') ) + { + int l, axisIdx, axisSign = 0; + + l=0; + if ( val[i][l] == '-' ) + { + axisSign = 1; l++; + } + else if ( val[i][l] == '+' ) + { + axisSign = 0; l++; + } + + if ( val[i][l] == 'a' ) + { + l++; + } + if ( isdigit( val[i][l] ) ) + { + axisIdx = atoi( &val[i][l] ); + + bmap[bIdx].ButtonNum = 0x8000 | (axisSign ? 0x4000 : 0) | (axisIdx & 0xFF); + } + } + } + } + + return 0; +} +//******************************************************************************** +int GamePad_t::loadDefaults(void) +{ + + if ( jsDev[ devIdx ].gc ) + { + char *mapping; + + mapping = SDL_GameControllerMapping( jsDev[ devIdx ].gc ); + + if ( mapping == NULL ) return -1; + + setMapping( mapping ); + + SDL_free(mapping); + } + return 0; +} +//******************************************************************************** static int s_jinited = 0; +//******************************************************************************** +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. */ @@ -219,7 +425,8 @@ int AddJoystick( int which ) else { printf("Added Joystick: %i \n", which ); - jsDev[which].print(); + jsDev[which].init(which); + //jsDev[which].print(); //printJoystick( s_Joysticks[which] ); } } @@ -235,7 +442,8 @@ int AddJoystick( int which ) else { printf("Added Joystick: %i \n", which ); - jsDev[which].print(); + jsDev[which].init(which); + //jsDev[which].print(); //printJoystick( s_Joysticks[which] ); } } @@ -286,26 +494,6 @@ InitJoysticks(void) { /* Open the joystick under SDL. */ AddJoystick(n); - //if ( SDL_IsGameController(n) ) - //{ - // SDL_GameController *gc = SDL_GameControllerOpen(n); - // printf("Is Game Controller: %i \n", n); - - // printf("Mapping: %s \n", SDL_GameControllerMapping(gc) ); - //} - // s_Joysticks[n] = SDL_JoystickOpen(n); - - //if ( s_Joysticks[n] == NULL ) - //{ - // printf("Could not open joystick %d: %s.\n", - // n, SDL_GetError()); - //} - //else - //{ - // printf("Opened JS %i: \n", SDL_JoystickInstanceID( s_Joysticks[n] ) ); - // jsDev[which].print(); - // //printJoystick( s_Joysticks[n] ); - //} } s_jinited = 1; diff --git a/src/drivers/Qt/sdl-joystick.h b/src/drivers/Qt/sdl-joystick.h new file mode 100644 index 00000000..2f992e01 --- /dev/null +++ b/src/drivers/Qt/sdl-joystick.h @@ -0,0 +1,58 @@ +// 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 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 inUse(void); + void print(void); + const char *getName(void); + const char *getGUID(void); + + private: + int devIdx; + std::string guidStr; + std::string name; +}; + +class GamePad_t +{ + public: + + int type; + int devIdx; + + ButtConfig bmap[GAMEPAD_NUM_BUTTONS]; + + GamePad_t(void); + ~GamePad_t(void); + + int loadDefaults(void); + + int setMapping( const char *map ); +}; + +extern GamePad_t GamePad[4]; + +jsDev_t *getJoystickDevice( int devNum ); + +#endif From b815fbfe47cb5273b708cb493fedc7b583404f46 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Fri, 24 Jul 2020 09:50:03 -0400 Subject: [PATCH 04/13] Added logic to show state of mapped buttons on game pad config page. --- src/drivers/Qt/ConsoleWindow.cpp | 2 + src/drivers/Qt/GamePadConf.cpp | 36 +++++++++++++++-- src/drivers/Qt/GamePadConf.h | 4 ++ src/drivers/Qt/input.cpp | 67 ++++++++++++++++++-------------- src/drivers/Qt/input.h | 1 + src/drivers/Qt/sdl-joystick.cpp | 31 ++++++++++++--- src/drivers/Qt/sdl-joystick.h | 8 ++++ 7 files changed, 111 insertions(+), 38 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index d855d141..89c75483 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -78,6 +78,8 @@ consoleWin_t::~consoleWin_t(void) { nes_shm->runEmulator = 0; + gameTimer->stop(); + if ( gamePadConfWin != NULL ) { gamePadConfWin->closeWindow(); diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index 6a149f60..ae990669 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -28,6 +28,10 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) portNum = 0; buttonConfigStatus = 1; + inputTimer = new QTimer( this ); + + connect( inputTimer, &QTimer::timeout, this, &GamePadConfDialog_t::updatePeriodic ); + setWindowTitle( tr("GamePad Config") ); hbox1 = new QHBoxLayout(); @@ -35,7 +39,7 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) hbox3 = new QHBoxLayout(); hbox4 = new QHBoxLayout(); - label = new QLabel(tr("Port:")); + label = new QLabel(tr("Console Port:")); portSel = new QComboBox(); hbox1->addWidget( label ); hbox1->addWidget( portSel ); @@ -105,13 +109,17 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) buttonName = new QLabel(tr(text)); keyName[i] = new QLabel(); + keyState[i] = new QLabel( tr("F") ); + label = new QLabel( tr("State:") ); button[i] = new GamePadConfigButton_t(i); clearButton[i] = new QPushButton( tr("Clear") ); grid->addWidget( buttonName , i, 0, Qt::AlignCenter ); grid->addWidget( keyName[i] , i, 1, Qt::AlignCenter ); - grid->addWidget( button[i] , i, 2, Qt::AlignCenter ); - grid->addWidget( clearButton[i], i, 3, Qt::AlignCenter ); + grid->addWidget( label , i, 2, Qt::AlignCenter ); + grid->addWidget( keyState[i] , i, 3, Qt::AlignCenter ); + grid->addWidget( button[i] , i, 4, Qt::AlignCenter ); + grid->addWidget( clearButton[i], i, 5, Qt::AlignCenter ); } updateCntrlrDpy(); @@ -166,11 +174,13 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) setLayout( mainLayout ); + inputTimer->start( 33 ); // 30hz } //---------------------------------------------------- GamePadConfDialog_t::~GamePadConfDialog_t(void) { + inputTimer->stop(); buttonConfigStatus = 0; } void GamePadConfDialog_t::keyPressEvent(QKeyEvent *event) @@ -485,6 +495,26 @@ void GamePadConfDialog_t::loadDefaults(void) updateCntrlrDpy(); } //---------------------------------------------------- +void GamePadConfDialog_t::updatePeriodic(void) +{ + for (int i=0; isetText( tr(txt) ); + keyState[i]->setStyleSheet( style ); + } +} +//---------------------------------------------------- GamePadConfigButton_t::GamePadConfigButton_t(int i) { idx = i; diff --git a/src/drivers/Qt/GamePadConf.h b/src/drivers/Qt/GamePadConf.h index fdf1c466..07a92030 100644 --- a/src/drivers/Qt/GamePadConf.h +++ b/src/drivers/Qt/GamePadConf.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "Qt/main.h" @@ -37,11 +38,13 @@ class GamePadConfDialog_t : public QDialog ~GamePadConfDialog_t(void); protected: + QTimer *inputTimer; QComboBox *portSel; QComboBox *devSel; QComboBox *profSel; QLabel *guidLbl; QLabel *keyName[GAMEPAD_NUM_BUTTONS]; + QLabel *keyState[GAMEPAD_NUM_BUTTONS]; GamePadConfigButton_t *button[GAMEPAD_NUM_BUTTONS]; int portNum; @@ -84,5 +87,6 @@ class GamePadConfDialog_t : public QDialog void oppDirEna(int state); void portSelect(int index); void deviceSelect(int index); + void updatePeriodic(void); }; diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index b688b1a5..e96f15c0 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -24,8 +24,9 @@ #include "Qt/config.h" -#include "Qt/sdl-video.h" #include "Qt/sdl.h" +#include "Qt/sdl-video.h" +#include "Qt/sdl-joystick.h" #include "common/cheat.h" #include "../../movie.h" @@ -49,8 +50,8 @@ extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; /* UsrInputType[] is user-specified. CurInputType[] is current (game loading can override user settings) */ -static int UsrInputType[NUM_INPUT_DEVICES]; -static int CurInputType[NUM_INPUT_DEVICES]; +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; @@ -1007,8 +1008,13 @@ DTestButton (ButtConfig * bc) { if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum)]) { + bc->state = 1; return 1; } + else + { + bc->state = 0; + } } else if (bc->ButtType == BUTTC_JOYSTICK) { @@ -1021,26 +1027,26 @@ DTestButton (ButtConfig * bc) } -#define MK(x) {BUTTC_KEYBOARD,0,MKK(x)} +#define MK(x) {BUTTC_KEYBOARD,0,MKK(x),0} //#define MK2(x1,x2) {BUTTC_KEYBOARD,0,MKK(x1)} -#define MKZ() {0,0,-1} +#define MKZ() {0,0,-1,0} #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} -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 () -}; +//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. @@ -1072,7 +1078,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) @@ -1110,7 +1116,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); } @@ -2063,15 +2069,16 @@ UpdateInput (Config * config) type = 0; } - config->getOption (prefix + "DeviceNum", &devnum); - for (unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) - { - config->getOption (prefix + GamePadNames[j], &button); + //FIXME + //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 = type; - GamePadConfig[i][j].DeviceNum = devnum; - GamePadConfig[i][j].ButtonNum = button; - } + // GamePadConfig[i][j].ButtType = type; + // GamePadConfig[i][j].DeviceNum = devnum; + // GamePadConfig[i][j].ButtonNum = button; + //} } // PowerPad 0 - 1 diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index 14862205..8fd218d8 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -17,6 +17,7 @@ struct ButtConfig int ButtType; //[MAXBUTTCONFIG]; int DeviceNum; //[MAXBUTTCONFIG]; int ButtonNum; //[MAXBUTTCONFIG]; + int state; //uint32_t NumC; //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ }; diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 705c8f1d..2b0e6535 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -337,10 +337,17 @@ DTestButtonJoy(ButtConfig *bc) if (bc->ButtonNum & 0x2000) { /* Hat "button" */ - if(SDL_JoystickGetHat( js, + 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) { @@ -348,16 +355,30 @@ DTestButtonJoy(ButtConfig *bc) int pos; pos = SDL_JoystickGetAxis( js, bc->ButtonNum & 16383); - if ((bc->ButtonNum & 0x4000) && pos <= -16383) { - return 1; - } else if (!(bc->ButtonNum & 0x4000) && pos >= 16363) { + 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, + else if (SDL_JoystickGetButton( js, bc->ButtonNum)) { + bc->state = 1; return 1; + } + else + { + bc->state = 0; } return 0; diff --git a/src/drivers/Qt/sdl-joystick.h b/src/drivers/Qt/sdl-joystick.h index 2f992e01..7be32400 100644 --- a/src/drivers/Qt/sdl-joystick.h +++ b/src/drivers/Qt/sdl-joystick.h @@ -11,6 +11,14 @@ #define MAX_JOYSTICKS 32 +struct nesGamePadMap_t +{ + char guid[64]; + char name[128]; + char btn[GAMEPAD_NUM_BUTTONS]; + char os[64]; +}; + struct jsDev_t { SDL_Joystick *js; From 675b73cbedfd1b418a07eb09888f85051835cac8 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Fri, 24 Jul 2020 11:05:20 -0400 Subject: [PATCH 05/13] Added mapping profile widgets. Still TODO, write code behind them. --- src/drivers/Qt/GamePadConf.cpp | 29 +++- src/drivers/Qt/GamePadConf.h | 1 + src/drivers/Qt/sdl-joystick.cpp | 272 +++++++++++++++++++++----------- src/drivers/Qt/sdl-joystick.h | 8 +- 4 files changed, 209 insertions(+), 101 deletions(-) diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index ae990669..8f21ce17 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -16,8 +16,10 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) QHBoxLayout *hbox1, *hbox2, *hbox3, *hbox4; QGridLayout *grid; QCheckBox *efs_chkbox, *udlr_chkbox; - QGroupBox *frame; + QGroupBox *frame1, *frame2; QLabel *label; + QPushButton *newProfileButton; + QPushButton *applyProfileButton; QPushButton *loadDefaultButton; QPushButton *clearAllButton; QPushButton *closebutton; @@ -77,6 +79,21 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) hbox3->addWidget( label ); hbox3->addWidget( guidLbl ); + frame1 = new QGroupBox(tr("Mapping Profile:")); + grid = new QGridLayout(); + + frame1->setLayout( grid ); + + mapSel = new QComboBox(); + applyProfileButton = new QPushButton( tr("Load") ); + newProfileButton = new QPushButton( tr("New") ); + + grid->addWidget( mapSel , 0, 0, Qt::AlignCenter ); + grid->addWidget( applyProfileButton, 0, 1, Qt::AlignCenter ); + grid->addWidget( newProfileButton , 0, 2, Qt::AlignCenter ); + + mapSel->addItem( tr("Default"), 0 ); + efs_chkbox = new QCheckBox( tr("Enable Four Score") ); udlr_chkbox = new QCheckBox( tr("Allow Up+Down/Left+Right") ); @@ -88,13 +105,12 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) g_config->getOption("SDL.Input.EnableOppositeDirectionals", &opposite_dirs); udlr_chkbox->setChecked( opposite_dirs ); - frame = new QGroupBox(tr("Buttons:")); - grid = new QGridLayout(); + frame2 = new QGroupBox(tr("Current Active Button Mappings:")); + grid = new QGridLayout(); grid-> setHorizontalSpacing(50); - //frame->setFrameStyle( QFrame::Box ); - frame->setLayout( grid ); + frame2->setLayout( grid ); for (int i=0; iaddLayout( hbox1 ); mainLayout->addLayout( hbox2 ); mainLayout->addLayout( hbox3 ); + mainLayout->addWidget( frame1 ); mainLayout->addWidget( efs_chkbox ); mainLayout->addWidget( udlr_chkbox ); - mainLayout->addWidget( frame ); + mainLayout->addWidget( frame2 ); mainLayout->addLayout( hbox4 ); setLayout( mainLayout ); diff --git a/src/drivers/Qt/GamePadConf.h b/src/drivers/Qt/GamePadConf.h index 07a92030..ebcdaf3a 100644 --- a/src/drivers/Qt/GamePadConf.h +++ b/src/drivers/Qt/GamePadConf.h @@ -41,6 +41,7 @@ class GamePadConfDialog_t : public QDialog QTimer *inputTimer; QComboBox *portSel; QComboBox *devSel; + QComboBox *mapSel; QComboBox *profSel; QLabel *guidLbl; QLabel *keyName[GAMEPAD_NUM_BUTTONS]; diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 2b0e6535..1b8f0169 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -32,14 +32,24 @@ //#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; + +//******************************************************************************** +// Joystick Device jsDev_t::jsDev_t(void) { js = NULL; gc = NULL; }; +//******************************************************************************** int jsDev_t::close(void) { if ( gc ) @@ -56,31 +66,37 @@ int jsDev_t::close(void) 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() ); } +//******************************************************************************** bool jsDev_t::isGameController(void) { return ( gc != NULL ); } +//******************************************************************************** bool jsDev_t::inUse(void) { return ( (js != NULL) || (gc != NULL) ); } +//******************************************************************************** void jsDev_t::init( int idx ) { SDL_JoystickGUID guid; @@ -132,6 +148,79 @@ void jsDev_t::print(void) static jsDev_t jsDev[ MAX_JOYSTICKS ]; +//******************************************************************************** +nesGamePadMap_t::nesGamePadMap_t(void) +{ + memset( guid, 0, sizeof(guid) ); + memset( name, 0, sizeof(name) ); + memset( os , 0, sizeof(os) ); + memset( btn , 0, sizeof(btn) ); +} +//******************************************************************************** +nesGamePadMap_t::~nesGamePadMap_t(void) +{ + +} +//******************************************************************************** +int nesGamePadMap_t::parseMapping( const char *map ) +{ + int i,j,k,bIdx; + char id[32][64]; + char val[32][64]; + + i=0; j=0; k=0; + + while ( map[i] ) + { + while ( isspace(map[i]) ) i++; + + j=0; + while ( (map[i] != 0) && (map[i] != ',') && (map[i] != ':') ) + { + id[k][j] = map[i]; i++; j++; + } + id[k][j] = 0; + val[k][0] = 0; + + if ( map[i] == ':' ) + { + i++; j=0; + + while ( (map[i] != 0) && (map[i] != ',') ) + { + val[k][j] = map[i]; i++; j++; + } + val[k][j] = 0; + } + + if ( map[i] == ',' ) + { + k++; i++; + } + else + { + break; + } + } + + strcpy( guid, id[0] ); // GUID is always 1st field + strcpy( name, id[1] ); // Name is always 2nd field + + for (i=0; i= 0 ) + { + strcpy( btn[bIdx], val[i] ); + } + else if ( strcmp( id[i], "platform" ) == 0 ) + { + strcpy( os, val[i] ); + } + } +} //******************************************************************************** GamePad_t::GamePad_t(void) { @@ -186,104 +275,96 @@ static int sdlButton2NesGpIdx( const char *id ) { idx = 7; } + else if ( strcmp( id, "turboA" ) == 0 ) + { + idx = 8; + } + else if ( strcmp( id, "turboB" ) == 0 ) + { + idx = 9; + } return idx; } //******************************************************************************** +int GamePad_t::setMapping( nesGamePadMap_t *gpm ) +{ + for (int i=0; ibtn[i][0] == 'k') + { + bmap[i].ButtType = BUTTC_KEYBOARD; + bmap[i].DeviceNum = 0; + bmap[i].ButtonNum = 0; // FIXME + } + 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 ) { - int i,j,k,bIdx; - char id[32][64]; - char val[32][64]; + nesGamePadMap_t gpm; - //char guidStr[64]; - - i=0; j=0; k=0; - - while ( map[i] ) - { - while ( isspace(map[i]) ) i++; - - j=0; - while ( (map[i] != 0) && (map[i] != ',') && (map[i] != ':') ) - { - id[k][j] = map[i]; i++; j++; - } - id[k][j] = 0; - val[k][0] = 0; - - if ( map[i] == ':' ) - { - i++; j=0; - - while ( (map[i] != 0) && (map[i] != ',') ) - { - val[k][j] = map[i]; i++; j++; - } - val[k][j] = 0; - } - - if ( map[i] == ',' ) - { - k++; i++; - } - else - { - break; - } - } - - for (i=0; i= 0 ) - { - bmap[bIdx].ButtType = BUTTC_JOYSTICK; - bmap[bIdx].DeviceNum = devIdx; - - if ( (val[i][0] == 'b') && isdigit( val[i][1] ) ) - { - bmap[bIdx].ButtonNum = atoi( &val[i][1] ); - } - else if ( (val[i][0] == 'h') && isdigit( val[i][1] ) && - (val[i][2] == '.') && isdigit( val[i][3] ) ) - { - int hatIdx, hatVal; - - hatIdx = val[i][1] - '0'; - hatVal = atoi( &val[i][3] ); - - bmap[bIdx].ButtonNum = 0x2000 | ( (hatIdx & 0x1F) << 8) | (hatVal & 0xFF); - } - else if ( (val[i][0] == 'a') || (val[i][1] == 'a') ) - { - int l, axisIdx, axisSign = 0; - - l=0; - if ( val[i][l] == '-' ) - { - axisSign = 1; l++; - } - else if ( val[i][l] == '+' ) - { - axisSign = 0; l++; - } - - if ( val[i][l] == 'a' ) - { - l++; - } - if ( isdigit( val[i][l] ) ) - { - axisIdx = atoi( &val[i][l] ); - - bmap[bIdx].ButtonNum = 0x8000 | (axisSign ? 0x4000 : 0) | (axisIdx & 0xFF); - } - } - } - } + gpm.parseMapping( map ); + setMapping( &gpm ); return 0; } @@ -306,9 +387,6 @@ int GamePad_t::loadDefaults(void) return 0; } //******************************************************************************** - -static int s_jinited = 0; - //******************************************************************************** jsDev_t *getJoystickDevice( int devNum ) { @@ -383,6 +461,7 @@ DTestButtonJoy(ButtConfig *bc) return 0; } +//******************************************************************************** //static void printJoystick( SDL_Joystick *js ) @@ -405,6 +484,7 @@ DTestButtonJoy(ButtConfig *bc) // //} +//******************************************************************************** /** * Shutdown the SDL joystick subsystem. */ @@ -425,6 +505,7 @@ KillJoysticks(void) return 0; } +//******************************************************************************** int AddJoystick( int which ) { if ( jsDev[ which ].inUse() ) @@ -472,6 +553,7 @@ int AddJoystick( int which ) return 0; } +//******************************************************************************** int RemoveJoystick( int which ) { //printf("Remove Joystick: %i \n", which ); @@ -491,6 +573,7 @@ int RemoveJoystick( int which ) return -1; } +//******************************************************************************** /** * Initialize the SDL joystick subsystem. */ @@ -520,3 +603,4 @@ InitJoysticks(void) s_jinited = 1; return 1; } +//******************************************************************************** diff --git a/src/drivers/Qt/sdl-joystick.h b/src/drivers/Qt/sdl-joystick.h index 7be32400..778ad0e3 100644 --- a/src/drivers/Qt/sdl-joystick.h +++ b/src/drivers/Qt/sdl-joystick.h @@ -15,8 +15,13 @@ struct nesGamePadMap_t { char guid[64]; char name[128]; - char btn[GAMEPAD_NUM_BUTTONS]; + char btn[GAMEPAD_NUM_BUTTONS][32]; char os[64]; + + nesGamePadMap_t(void); + ~nesGamePadMap_t(void); + + int parseMapping( const char *text ); }; struct jsDev_t @@ -57,6 +62,7 @@ class GamePad_t int loadDefaults(void); int setMapping( const char *map ); + int setMapping( nesGamePadMap_t *map ); }; extern GamePad_t GamePad[4]; From b71630379a04b046d8f764a5327886a1459ca676 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Fri, 24 Jul 2020 16:56:48 -0400 Subject: [PATCH 06/13] Added game pad button mapping profile logic. --- src/driver.h | 1 + src/drivers/Qt/GamePadConf.cpp | 202 +++++++++++++++- src/drivers/Qt/GamePadConf.h | 6 + src/drivers/Qt/config.cpp | 6 +- src/drivers/Qt/sdl-joystick.cpp | 401 +++++++++++++++++++++++++++----- src/drivers/Qt/sdl-joystick.h | 17 +- src/file.cpp | 5 + 7 files changed, 559 insertions(+), 79 deletions(-) diff --git a/src/driver.h b/src/driver.h index 9987643c..7838369f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -142,6 +142,7 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall); //Sets the base directory(save states, snapshots, etc. are saved in directories below this directory. void FCEUI_SetBaseDirectory(std::string const & dir); +const char *FCEUI_GetBaseDirectory(void); bool FCEUI_GetUserPaletteAvail(void); void FCEUI_SetUserPalette(uint8 *pal, int nEntries); diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index 8f21ce17..e390e485 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -1,5 +1,8 @@ // GamePadConf.cpp // +#include +#include + #include "Qt/GamePadConf.h" #include "Qt/main.h" #include "Qt/dface.h" @@ -13,13 +16,16 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) : QDialog( parent ) { - QHBoxLayout *hbox1, *hbox2, *hbox3, *hbox4; + QHBoxLayout *hbox, *hbox1, *hbox2, *hbox3, *hbox4; + QVBoxLayout *vbox; QGridLayout *grid; QCheckBox *efs_chkbox, *udlr_chkbox; QGroupBox *frame1, *frame2; QLabel *label; QPushButton *newProfileButton; + QPushButton *saveProfileButton; QPushButton *applyProfileButton; + QPushButton *removeProfileButton; QPushButton *loadDefaultButton; QPushButton *clearAllButton; QPushButton *closebutton; @@ -64,7 +70,7 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) if ( js != NULL ) { - if ( js->inUse() ) + if ( js->isConnected() ) { char stmp[128]; sprintf( stmp, "%i: %s", i, js->getName() ); @@ -80,19 +86,45 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) hbox3->addWidget( guidLbl ); frame1 = new QGroupBox(tr("Mapping Profile:")); - grid = new QGridLayout(); + //grid = new QGridLayout(); + vbox = new QVBoxLayout(); - frame1->setLayout( grid ); + //frame1->setLayout( grid ); + frame1->setLayout( vbox ); + + hbox = new QHBoxLayout(); + vbox->addLayout( hbox ); mapSel = new QComboBox(); + hbox->addWidget( mapSel ); + + mapSel->setWhatsThis( tr("Combo box for selection of a saved button mapping profile for the selected device")); + mapSel->addItem( tr("default"), 0 ); + + hbox = new QHBoxLayout(); + vbox->addLayout( hbox ); + applyProfileButton = new QPushButton( tr("Load") ); + applyProfileButton->setWhatsThis(tr("Sets Current Active Map to the Selected Profile")); + hbox->addWidget( applyProfileButton ); + + saveProfileButton = new QPushButton( tr("Save") ); + saveProfileButton->setWhatsThis(tr("Stores Current Active Map to the Selected Profile")); + hbox->addWidget( saveProfileButton ); + + hbox = new QHBoxLayout(); + vbox->addLayout( hbox ); + newProfileButton = new QPushButton( tr("New") ); + newProfileButton->setWhatsThis(tr("Create a New Map Profile")); + hbox->addWidget( newProfileButton ); - grid->addWidget( mapSel , 0, 0, Qt::AlignCenter ); - grid->addWidget( applyProfileButton, 0, 1, Qt::AlignCenter ); - grid->addWidget( newProfileButton , 0, 2, Qt::AlignCenter ); + removeProfileButton = new QPushButton( tr("Delete") ); + removeProfileButton->setWhatsThis(tr("Deletes the Selected Map Profile")); + hbox->addWidget( removeProfileButton ); - mapSel->addItem( tr("Default"), 0 ); + mapMsg = new QLabel(); + vbox->addWidget(mapMsg); efs_chkbox = new QCheckBox( tr("Enable Four Score") ); udlr_chkbox = new QCheckBox( tr("Allow Up+Down/Left+Right") ); @@ -169,6 +201,10 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) connect(clearButton[8], SIGNAL(clicked()), this, SLOT(clearButton8(void)) ); connect(clearButton[9], SIGNAL(clicked()), this, SLOT(clearButton9(void)) ); + connect(newProfileButton , SIGNAL(clicked()), this, SLOT(newProfileCallback(void)) ); + connect(applyProfileButton, SIGNAL(clicked()), this, SLOT(loadProfileCallback(void)) ); + connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) ); + connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) ); connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) ); connect(closebutton , SIGNAL(clicked()), this, SLOT(closeWindow(void)) ); @@ -192,6 +228,8 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) setLayout( mainLayout ); inputTimer->start( 33 ); // 30hz + + loadMapList(); } //---------------------------------------------------- @@ -212,6 +250,62 @@ void GamePadConfDialog_t::keyReleaseEvent(QKeyEvent *event) pushKeyEvent( event, 0 ); } //---------------------------------------------------- +void GamePadConfDialog_t::loadMapList(void) +{ + QDir dir; + QStringList filters, fileList; + const char *baseDir = FCEUI_GetBaseDirectory(); + const char *guid; + std::string path; + int index, devIdx; + jsDev_t *js; + + index = devSel->currentIndex(); + devIdx = devSel->itemData(index).toInt(); + + if ( devIdx < 0 ) + { + guid = "keyboard"; + } + else + { + js = getJoystickDevice( devIdx ); + + guid = js->getGUID(); + } + + if ( guid == NULL ) + { + return; + } + + path = std::string(baseDir) + "/input/" + std::string(guid); + + dir.setPath( QString::fromStdString(path) ); + + filters << "*.txt"; + dir.setNameFilters(filters); + + fileList = dir.entryList( filters, QDir::Files, QDir::NoSort ); + + mapSel->clear(); + mapSel->addItem( tr("default"), 0 ); + + for (size_t i=0; i < fileList.size(); i++) + { + size_t suffixIdx; + std::string fileName = fileList[i].toStdString(); + + suffixIdx = fileName.find_last_of('.'); + + fileName.erase( suffixIdx ); + + //printf("File: %s \n", fileName.c_str() ); + + mapSel->addItem( tr(fileName.c_str()), (int)i+1 ); + } +} +//---------------------------------------------------- void GamePadConfDialog_t::updateCntrlrDpy(void) { char keyNameStr[128]; @@ -247,7 +341,7 @@ void GamePadConfDialog_t::deviceSelect(int index) if ( js != NULL ) { - if ( js->inUse() ) + if ( js->isConnected() ) { guidLbl->setText( js->getGUID() ); } @@ -256,6 +350,9 @@ void GamePadConfDialog_t::deviceSelect(int index) { guidLbl->setText(""); } + GamePad[portNum].setDeviceIndex( devIdx ); + + loadMapList(); updateCntrlrDpy(); } @@ -472,7 +569,7 @@ void GamePadConfDialog_t::loadDefaults(void) index = devSel->currentIndex(); devIdx = devSel->itemData(index).toInt(); - printf("Selected Device:%i : %i \n", index, devIdx ); + //printf("Selected Device:%i : %i \n", index, devIdx ); if ( devIdx == -1 ) { @@ -506,12 +603,95 @@ void GamePadConfDialog_t::loadDefaults(void) } else { - GamePad[portNum].devIdx = devIdx; + GamePad[portNum].setDeviceIndex( devIdx ); GamePad[portNum].loadDefaults(); } updateCntrlrDpy(); } //---------------------------------------------------- +void GamePadConfDialog_t::createNewProfile( const char *name ) +{ + printf("Creating: %s \n", name ); + + GamePad[portNum].createProfile(name); + + mapSel->addItem( tr(name) ); +} +//---------------------------------------------------- +void GamePadConfDialog_t::newProfileCallback(void) +{ + int ret; + QInputDialog dialog(this); + + dialog.setWindowTitle( tr("New Profile") ); + dialog.setLabelText( tr("Specify New Profile Name") ); + dialog.setOkButtonText( tr("Create") ); + + dialog.show(); + ret = dialog.exec(); + + if ( QDialog::Accepted == ret ) + { + createNewProfile( dialog.textValue().toStdString().c_str() ); + } +} +//---------------------------------------------------- +void GamePadConfDialog_t::loadProfileCallback(void) +{ + char stmp[256]; + int index, devIdx, ret; + std::string mapName; + + index = devSel->currentIndex(); + devIdx = devSel->itemData(index).toInt(); + + mapName = mapSel->currentText().toStdString(); + + GamePad[portNum].setDeviceIndex( devIdx ); + + if ( mapName.compare("default") == 0 ) + { + ret =GamePad[portNum].loadDefaults(); + } + else + { + ret = GamePad[portNum].loadProfile( mapName.c_str() ); + } + if ( ret == 0 ) + { + sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Load Mapping: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + mapMsg->setText( tr(stmp) ); + + updateCntrlrDpy(); +} +//---------------------------------------------------- +void GamePadConfDialog_t::saveProfileCallback(void) +{ + int ret; + std::string mapName; + char stmp[256]; + + mapName = mapSel->currentText().toStdString(); + + ret = GamePad[portNum].saveCurrentMapToFile( mapName.c_str() ); + + if ( ret == 0 ) + { + sprintf( stmp, "Mapping Saved: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Save Mapping: %s \n", mapName.c_str() ); + } + mapMsg->setText( tr(stmp) ); + +} +//---------------------------------------------------- void GamePadConfDialog_t::updatePeriodic(void) { for (int i=0; i #include "Qt/sdl.h" #include "Qt/sdl-joystick.h" @@ -41,6 +42,13 @@ 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) @@ -91,7 +99,7 @@ bool jsDev_t::isGameController(void) } //******************************************************************************** -bool jsDev_t::inUse(void) +bool jsDev_t::isConnected(void) { return ( (js != NULL) || (gc != NULL) ); } @@ -151,15 +159,23 @@ static jsDev_t jsDev[ MAX_JOYSTICKS ]; //******************************************************************************** nesGamePadMap_t::nesGamePadMap_t(void) { - memset( guid, 0, sizeof(guid) ); - memset( name, 0, sizeof(name) ); - memset( os , 0, sizeof(os) ); - memset( btn , 0, sizeof(btn) ); + clearMapping(); } //******************************************************************************** nesGamePadMap_t::~nesGamePadMap_t(void) { +} +//******************************************************************************** +void nesGamePadMap_t::clearMapping(void) +{ + guid[0] = 0; + name[0] = 0; + os[0] = 0; + for (int i=0; ibtn[i][0] == 'k') { + SDL_Keycode key; + bmap[i].ButtType = BUTTC_KEYBOARD; - bmap[i].DeviceNum = 0; - bmap[i].ButtonNum = 0; // FIXME + 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] ) ) { @@ -369,24 +386,280 @@ int GamePad_t::setMapping( const char *map ) 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; + } + } + return -1; +} +//******************************************************************************** int GamePad_t::loadDefaults(void) { + char txtMap[256]; - if ( jsDev[ devIdx ].gc ) - { - char *mapping; + if ( getDefaultMap( txtMap ) == 0 ) + { + setMapping( txtMap ); + } - mapping = SDL_GameControllerMapping( jsDev[ devIdx ].gc ); - - if ( mapping == NULL ) return -1; - - setMapping( mapping ); - - SDL_free(mapping); - } return 0; } //******************************************************************************** +int GamePad_t::loadProfile( const char *name, const char *guid ) +{ + char txtMap[256]; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + + 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) + + "/" + std::string(name) + ".txt"; + + //printf("Using File: %s\n", path.c_str() ); + + if ( getMapFromFile( path.c_str(), txtMap ) == 0 ) + { + setMapping( txtMap ); + return 0; + } + + return -1; +} +//******************************************************************************** +int GamePad_t::saveCurrentMapToFile( const char *name ) +{ + int i; + char stmp[64]; + const char *guid = NULL; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path, output; + QDir dir; + + 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) ); + + 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 ) +{ + char txtMap[256]; + 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() ); + + getDefaultMap( txtMap, guid ); + + saveMappingToFile( path.c_str(), txtMap ); + + return 0; +} //******************************************************************************** jsDev_t *getJoystickDevice( int devNum ) { @@ -410,6 +683,10 @@ DTestButtonJoy(ButtConfig *bc) { return 0; } + if ( bc->DeviceNum < 0 ) + { + return 0; + } js = jsDev[bc->DeviceNum].getJS(); if (bc->ButtonNum & 0x2000) @@ -432,7 +709,7 @@ DTestButtonJoy(ButtConfig *bc) /* Axis "button" */ int pos; pos = SDL_JoystickGetAxis( js, - bc->ButtonNum & 16383); + bc->ButtonNum & 0x3FFF); if ((bc->ButtonNum & 0x4000) && pos <= -16383) { bc->state = 1; @@ -508,7 +785,7 @@ KillJoysticks(void) //******************************************************************************** int AddJoystick( int which ) { - if ( jsDev[ which ].inUse() ) + if ( jsDev[ which ].isConnected() ) { //printf("Error: Joystick already exists at device index %i \n", which ); return -1; @@ -560,7 +837,7 @@ int RemoveJoystick( int which ) for (int i=0; i Date: Fri, 24 Jul 2020 17:14:03 -0400 Subject: [PATCH 07/13] Added code to allow for deletion of game pad profiles. --- src/drivers/Qt/GamePadConf.cpp | 33 ++++++++++++++++++++++++++--- src/drivers/Qt/GamePadConf.h | 1 + src/drivers/Qt/sdl-joystick.cpp | 37 +++++++++++++++++++++++++++++++-- src/drivers/Qt/sdl-joystick.h | 1 + 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index e390e485..e55f8ad8 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -201,9 +201,10 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) connect(clearButton[8], SIGNAL(clicked()), this, SLOT(clearButton8(void)) ); connect(clearButton[9], SIGNAL(clicked()), this, SLOT(clearButton9(void)) ); - connect(newProfileButton , SIGNAL(clicked()), this, SLOT(newProfileCallback(void)) ); - connect(applyProfileButton, SIGNAL(clicked()), this, SLOT(loadProfileCallback(void)) ); - connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) ); + connect(newProfileButton , SIGNAL(clicked()), this, SLOT(newProfileCallback(void)) ); + connect(applyProfileButton , SIGNAL(clicked()), this, SLOT(loadProfileCallback(void)) ); + connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) ); + connect(removeProfileButton, SIGNAL(clicked()), this, SLOT(deleteProfileCallback(void)) ); connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) ); connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) ); @@ -301,6 +302,9 @@ void GamePadConfDialog_t::loadMapList(void) fileName.erase( suffixIdx ); //printf("File: %s \n", fileName.c_str() ); + // + + if ( fileName.compare("default") == 0 ) continue; mapSel->addItem( tr(fileName.c_str()), (int)i+1 ); } @@ -692,6 +696,29 @@ void GamePadConfDialog_t::saveProfileCallback(void) } //---------------------------------------------------- +void GamePadConfDialog_t::deleteProfileCallback(void) +{ + int ret; + std::string mapName; + char stmp[256]; + + mapName = mapSel->currentText().toStdString(); + + ret = GamePad[portNum].deleteMapping( mapName.c_str() ); + + if ( ret == 0 ) + { + sprintf( stmp, "Mapping Deleted: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Delete Mapping: %s \n", mapName.c_str() ); + } + mapMsg->setText( tr(stmp) ); + + loadMapList(); +} +//---------------------------------------------------- void GamePadConfDialog_t::updatePeriodic(void) { for (int i=0; i= 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) ) @@ -803,7 +836,7 @@ int AddJoystick( int which ) } else { - printf("Added Joystick: %i \n", which ); + //printf("Added Joystick: %i \n", which ); jsDev[which].init(which); //jsDev[which].print(); //printJoystick( s_Joysticks[which] ); @@ -820,7 +853,7 @@ int AddJoystick( int which ) } else { - printf("Added Joystick: %i \n", which ); + //printf("Added Joystick: %i \n", which ); jsDev[which].init(which); //jsDev[which].print(); //printJoystick( s_Joysticks[which] ); diff --git a/src/drivers/Qt/sdl-joystick.h b/src/drivers/Qt/sdl-joystick.h index 6c33fcf6..c4c3ed24 100644 --- a/src/drivers/Qt/sdl-joystick.h +++ b/src/drivers/Qt/sdl-joystick.h @@ -74,6 +74,7 @@ class GamePad_t 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 ); }; extern GamePad_t GamePad[4]; From 67e87787e3bbbb06b717b11fc541f7236921881c Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 24 Jul 2020 18:44:18 -0400 Subject: [PATCH 08/13] Added logic to load default keyboard mapping. --- src/drivers/Qt/sdl-joystick.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 688040f8..04b46665 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -484,6 +484,18 @@ int GamePad_t::getDefaultMap( char *out, const char *guid ) return 0; } } + else + { + if ( strcmp( guid, "keyboard" ) == 0 ) + { + for (int x=0; x Date: Fri, 24 Jul 2020 21:47:57 -0400 Subject: [PATCH 09/13] Added logic to init game pad mappings at startup --- src/drivers/Qt/GamePadConf.cpp | 109 ++++++++++---------------------- src/drivers/Qt/GamePadConf.h | 2 +- src/drivers/Qt/config.cpp | 6 +- src/drivers/Qt/input.cpp | 31 ++------- src/drivers/Qt/sdl-joystick.cpp | 108 ++++++++++++++++++++++++++++++- src/drivers/Qt/sdl-joystick.h | 14 +++- 6 files changed, 160 insertions(+), 110 deletions(-) diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index e55f8ad8..b91dff54 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -26,7 +26,7 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) QPushButton *saveProfileButton; QPushButton *applyProfileButton; QPushButton *removeProfileButton; - QPushButton *loadDefaultButton; + //QPushButton *loadDefaultButton; QPushButton *clearAllButton; QPushButton *closebutton; QPushButton *clearButton[GAMEPAD_NUM_BUTTONS]; @@ -75,9 +75,17 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) char stmp[128]; sprintf( stmp, "%i: %s", i, js->getName() ); devSel->addItem( tr(stmp), i ); + } } } + for (int i=0; icount(); i++) + { + if ( devSel->itemData(i).toInt() == GamePad[portNum].getDeviceIndex() ) + { + devSel->setCurrentIndex( i ); + } + } label = new QLabel(tr("GUID:")); guidLbl = new QLabel(); @@ -85,6 +93,8 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) hbox3->addWidget( label ); hbox3->addWidget( guidLbl ); + guidLbl->setText( GamePad[portNum].getGUID() ); + frame1 = new QGroupBox(tr("Mapping Profile:")); //grid = new QGridLayout(); vbox = new QVBoxLayout(); @@ -171,11 +181,11 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) } updateCntrlrDpy(); - loadDefaultButton = new QPushButton(tr("Load Defaults")); + //loadDefaultButton = new QPushButton(tr("Load Defaults")); clearAllButton = new QPushButton(tr("Clear All")); closebutton = new QPushButton(tr("Close")); - hbox4->addWidget( loadDefaultButton ); + //hbox4->addWidget( loadDefaultButton ); hbox4->addWidget( clearAllButton ); hbox4->addWidget( closebutton ); @@ -206,7 +216,7 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) ); connect(removeProfileButton, SIGNAL(clicked()), this, SLOT(deleteProfileCallback(void)) ); - connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) ); + //connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) ); connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) ); connect(closebutton , SIGNAL(clicked()), this, SLOT(closeWindow(void)) ); @@ -334,6 +344,17 @@ void GamePadConfDialog_t::portSelect(int index) //printf("Port Number:%i \n", index); portNum = index; updateCntrlrDpy(); + + for (int i=0; icount(); i++) + { + if ( devSel->itemData(i).toInt() == GamePad[portNum].getDeviceIndex() ) + { + devSel->setCurrentIndex( i ); + } + } + guidLbl->setText( GamePad[portNum].getGUID() ); + + loadMapList(); } //---------------------------------------------------- void GamePadConfDialog_t::deviceSelect(int index) @@ -377,8 +398,8 @@ void GamePadConfDialog_t::oppDirEna(int state) //---------------------------------------------------- void GamePadConfDialog_t::changeButton(int padNo, int x) { - char buf[256]; - std::string prefix; + //char buf[256]; + //std::string prefix; const char *keyNameStr; if ( buttonConfigStatus == 2 ) @@ -392,28 +413,8 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) button[x]->setText("Waiting" ); - 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], - GamePad[padNo].bmap[x].ButtonNum); - - if (GamePad[padNo].bmap[x].ButtType == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePad[padNo].bmap[x].ButtType == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePad[padNo].bmap[x].DeviceNum); - keyNameStr = ButtonName( &GamePad[padNo].bmap[x] ); keyName[x]->setText( keyNameStr ); @@ -564,55 +565,6 @@ void GamePadConfDialog_t::clearAllCallback(void) } } //---------------------------------------------------- -void GamePadConfDialog_t::loadDefaults(void) -{ - int index, devIdx; - char buf[256]; - std::string prefix; - - index = devSel->currentIndex(); - devIdx = devSel->itemData(index).toInt(); - - //printf("Selected Device:%i : %i \n", index, devIdx ); - - if ( devIdx == -1 ) - { - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", portNum); - prefix = buf; - - for (int x=0; xsetOption (prefix + GamePadNames[x], - GamePad[portNum].bmap[x].ButtonNum); - - if (GamePad[portNum].bmap[x].ButtType == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePad[portNum].bmap[x].ButtType == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePad[portNum].bmap[x].DeviceNum); - } - } - else - { - GamePad[portNum].setDeviceIndex( devIdx ); - GamePad[portNum].loadDefaults(); - } - updateCntrlrDpy(); -} -//---------------------------------------------------- void GamePadConfDialog_t::createNewProfile( const char *name ) { printf("Creating: %s \n", name ); @@ -663,6 +615,13 @@ void GamePadConfDialog_t::loadProfileCallback(void) } if ( ret == 0 ) { + std::string prefix; + sprintf( stmp, "SDL.Input.GamePad.%u.", portNum ); + prefix = stmp; + + g_config->setOption(prefix + "DeviceGUID", GamePad[portNum].getGUID() ); + g_config->setOption(prefix + "Profile" , mapName.c_str() ); + sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); } else diff --git a/src/drivers/Qt/GamePadConf.h b/src/drivers/Qt/GamePadConf.h index cf6eaa2c..72da9b61 100644 --- a/src/drivers/Qt/GamePadConf.h +++ b/src/drivers/Qt/GamePadConf.h @@ -86,7 +86,7 @@ class GamePadConfDialog_t : public QDialog void clearButton8(void); void clearButton9(void); void clearAllCallback(void); - void loadDefaults(void); + //void loadDefaults(void); void ena4score(int state); void oppDirEna(int state); void portSelect(int index); diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index b357abda..11bbcfea 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -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/Qt/input.cpp b/src/drivers/Qt/input.cpp index e96f15c0..eef69c71 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -1960,7 +1960,7 @@ void InputCfg (const std::string & text) UpdateInput (Config * config) { char buf[64]; - std::string device, prefix; + std::string device, prefix, guid, mapping; InitJoysticks(); @@ -2055,37 +2055,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); - //FIXME - //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 = type; - // GamePadConfig[i][j].DeviceNum = devnum; - // GamePadConfig[i][j].ButtonNum = button; - //} + 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); diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 04b46665..44645a93 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -55,6 +55,8 @@ jsDev_t::jsDev_t(void) { js = NULL; gc = NULL; + devIdx = 0; + portBindMask = 0; }; //******************************************************************************** @@ -92,6 +94,25 @@ 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) { @@ -243,7 +264,8 @@ int nesGamePadMap_t::parseMapping( const char *map ) //******************************************************************************** GamePad_t::GamePad_t(void) { - devIdx = -1; + 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; } //******************************************************************************** @@ -492,7 +595,7 @@ int GamePad_t::getDefaultMap( char *out, const char *guid ) { bmap[x].ButtType = BUTTC_KEYBOARD; bmap[x].DeviceNum = 0; - bmap[x].ButtonNum = DefaultGamePad[0][x]; + bmap[x].ButtonNum = DefaultGamePad[portNum][x]; } } } @@ -505,6 +608,7 @@ int GamePad_t::loadDefaults(void) if ( getDefaultMap( txtMap ) == 0 ) { + //printf("Map:%s\n", txtMap ); setMapping( txtMap ); } diff --git a/src/drivers/Qt/sdl-joystick.h b/src/drivers/Qt/sdl-joystick.h index c4c3ed24..568f736b 100644 --- a/src/drivers/Qt/sdl-joystick.h +++ b/src/drivers/Qt/sdl-joystick.h @@ -39,11 +39,15 @@ struct jsDev_t 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; }; @@ -52,19 +56,18 @@ class GamePad_t { public: - //int type; - int devIdx; - 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 ); @@ -75,6 +78,11 @@ class GamePad_t 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]; From 3db85cd1d25f7c430dedfc92a65fc99de9be1352 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 24 Jul 2020 22:12:45 -0400 Subject: [PATCH 10/13] Game pad code cleanup. --- src/drivers/Qt/GamePadConf.cpp | 55 ++++++++++++++++++++-------------- src/drivers/Qt/GamePadConf.h | 6 ++-- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index b91dff54..eee64188 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -26,7 +26,6 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) QPushButton *saveProfileButton; QPushButton *applyProfileButton; QPushButton *removeProfileButton; - //QPushButton *loadDefaultButton; QPushButton *clearAllButton; QPushButton *closebutton; QPushButton *clearButton[GAMEPAD_NUM_BUTTONS]; @@ -181,11 +180,9 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) } updateCntrlrDpy(); - //loadDefaultButton = new QPushButton(tr("Load Defaults")); clearAllButton = new QPushButton(tr("Clear All")); closebutton = new QPushButton(tr("Close")); - //hbox4->addWidget( loadDefaultButton ); hbox4->addWidget( clearAllButton ); hbox4->addWidget( closebutton ); @@ -216,7 +213,6 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) ); connect(removeProfileButton, SIGNAL(clicked()), this, SLOT(deleteProfileCallback(void)) ); - //connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) ); connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) ); connect(closebutton , SIGNAL(clicked()), this, SLOT(closeWindow(void)) ); @@ -268,8 +264,11 @@ void GamePadConfDialog_t::loadMapList(void) const char *baseDir = FCEUI_GetBaseDirectory(); const char *guid; std::string path; + std::string prefix, mapName; int index, devIdx; jsDev_t *js; + size_t n=0; + char stmp[256]; index = devSel->currentIndex(); devIdx = devSel->itemData(index).toInt(); @@ -299,8 +298,13 @@ void GamePadConfDialog_t::loadMapList(void) fileList = dir.entryList( filters, QDir::Files, QDir::NoSort ); + sprintf( stmp, "SDL.Input.GamePad.%u.", portNum ); + prefix = stmp; + + g_config->getOption(prefix + "Profile", &mapName ); + mapSel->clear(); - mapSel->addItem( tr("default"), 0 ); + mapSel->addItem( tr("default"), 0 ); n=1; for (size_t i=0; i < fileList.size(); i++) { @@ -316,7 +320,13 @@ void GamePadConfDialog_t::loadMapList(void) if ( fileName.compare("default") == 0 ) continue; - mapSel->addItem( tr(fileName.c_str()), (int)i+1 ); + mapSel->addItem( tr(fileName.c_str()), (int)i+1 ); + + if ( mapName.compare( fileName ) == 0 ) + { + mapSel->setCurrentIndex(n); + } + n++; } } //---------------------------------------------------- @@ -427,19 +437,9 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) //---------------------------------------------------- void GamePadConfDialog_t::clearButton( int padNo, int x ) { - char buf[256]; - std::string prefix; - GamePad[padNo].bmap[x].ButtonNum = -1; keyName[x]->setText(""); - - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); - prefix = buf; - - g_config->setOption (prefix + GamePadNames[x], - GamePad[padNo].bmap[x].ButtonNum); - } //---------------------------------------------------- void GamePadConfDialog_t::closeEvent(QCloseEvent *event) @@ -565,6 +565,20 @@ void GamePadConfDialog_t::clearAllCallback(void) } } //---------------------------------------------------- +void GamePadConfDialog_t::saveConfig(void) +{ + char stmp[256]; + std::string prefix, mapName; + + sprintf( stmp, "SDL.Input.GamePad.%u.", portNum ); + prefix = stmp; + + mapName = mapSel->currentText().toStdString(); + + g_config->setOption(prefix + "DeviceGUID", GamePad[portNum].getGUID() ); + g_config->setOption(prefix + "Profile" , mapName.c_str() ); +} +//---------------------------------------------------- void GamePadConfDialog_t::createNewProfile( const char *name ) { printf("Creating: %s \n", name ); @@ -615,12 +629,7 @@ void GamePadConfDialog_t::loadProfileCallback(void) } if ( ret == 0 ) { - std::string prefix; - sprintf( stmp, "SDL.Input.GamePad.%u.", portNum ); - prefix = stmp; - - g_config->setOption(prefix + "DeviceGUID", GamePad[portNum].getGUID() ); - g_config->setOption(prefix + "Profile" , mapName.c_str() ); + saveConfig(); sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); } @@ -645,6 +654,8 @@ void GamePadConfDialog_t::saveProfileCallback(void) if ( ret == 0 ) { + saveConfig(); + sprintf( stmp, "Mapping Saved: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); } else diff --git a/src/drivers/Qt/GamePadConf.h b/src/drivers/Qt/GamePadConf.h index 72da9b61..ba24b463 100644 --- a/src/drivers/Qt/GamePadConf.h +++ b/src/drivers/Qt/GamePadConf.h @@ -59,8 +59,9 @@ class GamePadConfDialog_t : public QDialog void closeEvent(QCloseEvent *bar); private: void updateCntrlrDpy(void); - void createNewProfile( const char *name ); - void loadMapList(void); + void createNewProfile( const char *name ); + void loadMapList(void); + void saveConfig(void); public slots: void closeWindow(void); @@ -86,7 +87,6 @@ class GamePadConfDialog_t : public QDialog void clearButton8(void); void clearButton9(void); void clearAllCallback(void); - //void loadDefaults(void); void ena4score(int state); void oppDirEna(int state); void portSelect(int index); From 4175ca6052da9ddd8ce807210a1d6e267111ce98 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 24 Jul 2020 22:26:09 -0400 Subject: [PATCH 11/13] Added logic to skip unassigned buttons in the config. --- src/drivers/Qt/sdl-joystick.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 44645a93..89a3cbac 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -404,6 +404,10 @@ int GamePad_t::setMapping( nesGamePadMap_t *gpm ) bmap[i].DeviceNum = -1; bmap[i].ButtonNum = -1; + if (gpm->btn[i][0] == 0) + { + continue; + } if (gpm->btn[i][0] == 'k') { SDL_Keycode key; From 976266547c78177af2bd52f1a85e374653f75f02 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 24 Jul 2020 22:41:19 -0400 Subject: [PATCH 12/13] Bug fix for shutdown of joystick system. --- src/drivers/Qt/sdl-joystick.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 89a3cbac..57c2f616 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -932,6 +932,9 @@ KillJoysticks(void) jsDev[n].close(); } SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + + s_jinited = 0; + return 0; } From b48b81c9388896694285f898413c9b56436917e4 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 24 Jul 2020 23:04:56 -0400 Subject: [PATCH 13/13] Commented out command line INOP inputCfg functionality. With new GUI gamepad config, this should not be required anymore. --- src/drivers/Qt/config.cpp | 2 +- src/drivers/Qt/fceuWrapper.cpp | 14 +++++++------- src/drivers/Qt/input.cpp | 10 +++++----- src/drivers/Qt/input.h | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index 11bbcfea..f0d54880 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -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); diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index b65d723d..0d5f18a7 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -414,6 +414,7 @@ static void ShowUsage(const char *prog) int fceuWrapperInit( int argc, char *argv[] ) { int error; + std::string s; for (int i=0; isave(); } - std::string s; - g_config->getOption("SDL.InputCfg", &s); + //g_config->getOption("SDL.InputCfg", &s); - if (s.size() != 0) - { - InitVideo(GameInfo); - InputCfg(s); - } + //if (s.size() != 0) + //{ + // InitVideo(GameInfo); + // InputCfg(s); + //} // update the input devices UpdateInput(g_config); diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index eef69c71..ce2bf93b 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -1909,9 +1909,9 @@ extern Config *g_config; /** * Update the button configuration for a device, specified by a text string. */ -void InputCfg (const std::string & text) -{ - +//void InputCfg (const std::string & text) +//{ +// // if (noGui) // { // if (text.find ("gamepad") != std::string::npos) @@ -1947,8 +1947,8 @@ void InputCfg (const std::string & text) // } // else // printf ("Please run \"fceux --nogui\" before using --inputcfg\n"); - -} +// +//} /** diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index 8fd218d8..07dc1d04 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -59,7 +59,7 @@ 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);