diff --git a/src/game/gamestart.c b/src/game/gamestart.c index a820f54..343bb05 100644 --- a/src/game/gamestart.c +++ b/src/game/gamestart.c @@ -15671,19 +15671,19 @@ int32_t getPressState(int32_t player, EButton key) { // パッドボタン割り case BTN_GIVEUP: conkey.type = YGS_CONKEY_BUTTON; conkey.index = SDL_CONTROLLER_BUTTON_BACK; - ctmp = YGS2kIsPressConPlayerKey(playerCons[pl], &conkey); + ctmp = YGS2kIsPressConKey(playerCons[pl], &conkey); break; case BTN_PAUSE: conkey.type = YGS_CONKEY_BUTTON; conkey.index = SDL_CONTROLLER_BUTTON_START; - ctmp = YGS2kIsPressConPlayerKey(playerCons[pl], &conkey); + ctmp = YGS2kIsPressConKey(playerCons[pl], &conkey); break; default: ctmp = inmenu ? - IsPressMenu(pl, key, YGS2kGetConPlayerType(playerCons[pl])) : - YGS2kIsPressConPlayerKey(playerCons[pl], &conKeyAssign[key + 8 * pl]); + IsPressMenu(pl, key, YGS2kGetConType(playerCons[pl])) : + YGS2kIsPressConKey(playerCons[pl], &conKeyAssign[key + 8 * pl]); break; } #endif @@ -15765,19 +15765,19 @@ int32_t getPushState(int32_t player, EButton key) { // パッドボタン割り case BTN_GIVEUP: conkey.type = YGS_CONKEY_BUTTON; conkey.index = SDL_CONTROLLER_BUTTON_BACK; - ctmp = YGS2kIsPushConPlayerKey(playerCons[pl], &conkey); + ctmp = YGS2kIsPushConKey(playerCons[pl], &conkey); break; case BTN_PAUSE: conkey.type = YGS_CONKEY_BUTTON; conkey.index = SDL_CONTROLLER_BUTTON_START; - ctmp = YGS2kIsPushConPlayerKey(playerCons[pl], &conkey); + ctmp = YGS2kIsPushConKey(playerCons[pl], &conkey); break; default: ctmp = inmenu ? - IsPushMenu(pl, key, YGS2kGetConPlayerType(playerCons[pl])) : - YGS2kIsPushConPlayerKey(playerCons[pl], &conKeyAssign[key + 8 * pl]); + IsPushMenu(pl, key, YGS2kGetConType(playerCons[pl])) : + YGS2kIsPushConKey(playerCons[pl], &conKeyAssign[key + 8 * pl]); break; } #endif @@ -15817,39 +15817,39 @@ int IsPressMenu(int32_t player, EButton button, YGS2kEInputType type) { case BTN_UP: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 3 }; - pushed = YGS2kIsPressConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPressConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_UP }; - return pushed || YGS2kIsPressConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPressConKey(playerCons[player], &key); case BTN_DOWN: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 2 }; - pushed = YGS2kIsPressConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPressConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_DOWN }; - return pushed || YGS2kIsPressConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPressConKey(playerCons[player], &key); case BTN_LEFT: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 1 }; - pushed = YGS2kIsPressConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPressConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_LEFT }; - return pushed || YGS2kIsPressConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPressConKey(playerCons[player], &key); case BTN_RIGHT: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 0 }; - pushed = YGS2kIsPressConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPressConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_RIGHT }; - return pushed || YGS2kIsPressConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPressConKey(playerCons[player], &key); case BTN_A: key.type = YGS_CONKEY_BUTTON; if (type == YGS_INPUT_NINTENDO) key.index = SDL_CONTROLLER_BUTTON_B; else key.index = SDL_CONTROLLER_BUTTON_A; - return YGS2kIsPressConPlayerKey(playerCons[player], &key); + return YGS2kIsPressConKey(playerCons[player], &key); case BTN_B: key.type = YGS_CONKEY_BUTTON; if (type == YGS_INPUT_NINTENDO) key.index = SDL_CONTROLLER_BUTTON_A; else key.index = SDL_CONTROLLER_BUTTON_B; - return YGS2kIsPressConPlayerKey(playerCons[player], &key); + return YGS2kIsPressConKey(playerCons[player], &key); break; - case BTN_C: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_X; return YGS2kIsPressConPlayerKey(playerCons[player], &key); - case BTN_D: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_Y; return YGS2kIsPressConPlayerKey(playerCons[player], &key); - case BTN_GIVEUP: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_BACK; return YGS2kIsPressConPlayerKey(playerCons[player], &key); - case BTN_PAUSE: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_START; return YGS2kIsPressConPlayerKey(playerCons[player], &key); + case BTN_C: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_X; return YGS2kIsPressConKey(playerCons[player], &key); + case BTN_D: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_Y; return YGS2kIsPressConKey(playerCons[player], &key); + case BTN_GIVEUP: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_BACK; return YGS2kIsPressConKey(playerCons[player], &key); + case BTN_PAUSE: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_START; return YGS2kIsPressConKey(playerCons[player], &key); default: return 0; } break; @@ -15880,39 +15880,39 @@ int IsPushMenu(int32_t player, EButton button, YGS2kEInputType type) { case BTN_UP: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 3 }; - pushed = YGS2kIsPushConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPushConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_UP }; - return pushed || YGS2kIsPushConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPushConKey(playerCons[player], &key); case BTN_DOWN: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 2 }; - pushed = YGS2kIsPushConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPushConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_DOWN }; - return pushed || YGS2kIsPushConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPushConKey(playerCons[player], &key); case BTN_LEFT: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 1 }; - pushed = YGS2kIsPushConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPushConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_LEFT }; - return pushed || YGS2kIsPushConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPushConKey(playerCons[player], &key); case BTN_RIGHT: key = (YGS2kSConKey) { .type = YGS_CONKEY_AXIS, .index = 0 }; - pushed = YGS2kIsPushConPlayerKey(playerCons[player], &key); + pushed = YGS2kIsPushConKey(playerCons[player], &key); key = (YGS2kSConKey) { .type = YGS_CONKEY_BUTTON, .index = SDL_CONTROLLER_BUTTON_DPAD_RIGHT }; - return pushed || YGS2kIsPushConPlayerKey(playerCons[player], &key); + return pushed || YGS2kIsPushConKey(playerCons[player], &key); case BTN_A: key.type = YGS_CONKEY_BUTTON; if (type == YGS_INPUT_NINTENDO) key.index = SDL_CONTROLLER_BUTTON_B; else key.index = SDL_CONTROLLER_BUTTON_A; - return YGS2kIsPushConPlayerKey(playerCons[player], &key); + return YGS2kIsPushConKey(playerCons[player], &key); case BTN_B: key.type = YGS_CONKEY_BUTTON; if (type == YGS_INPUT_NINTENDO) key.index = SDL_CONTROLLER_BUTTON_A; else key.index = SDL_CONTROLLER_BUTTON_B; - return YGS2kIsPushConPlayerKey(playerCons[player], &key); + return YGS2kIsPushConKey(playerCons[player], &key); break; - case BTN_C: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_X; return YGS2kIsPushConPlayerKey(playerCons[player], &key); - case BTN_D: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_Y; return YGS2kIsPushConPlayerKey(playerCons[player], &key); - case BTN_GIVEUP: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_BACK; return YGS2kIsPushConPlayerKey(playerCons[player], &key); - case BTN_PAUSE: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_START; return YGS2kIsPushConPlayerKey(playerCons[player], &key); + case BTN_C: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_X; return YGS2kIsPushConKey(playerCons[player], &key); + case BTN_D: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_Y; return YGS2kIsPushConKey(playerCons[player], &key); + case BTN_GIVEUP: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_BACK; return YGS2kIsPushConKey(playerCons[player], &key); + case BTN_PAUSE: key.type = YGS_CONKEY_BUTTON; key.index = SDL_CONTROLLER_BUTTON_START; return YGS2kIsPushConKey(playerCons[player], &key); default: return 0; } break; @@ -15941,8 +15941,8 @@ int IsPressConTypeKey(YGS2kEInputType type, YGS2kSConKey* key) return 0; } - for (int conPlayer = 0; conPlayer < YGS2kGetNumConPlayers(); conPlayer++) { - if (YGS2kGetConPlayerType(conPlayer) == type && YGS2kIsPressConPlayerKey(conPlayer, key)) return 1; + for (int player = 0; player < YGS2kGetNumPlayerSlots(); player++) { + if (YGS2kGetConType(player) == type && YGS2kIsPressConKey(player, key)) return 1; } return 0; } @@ -15959,8 +15959,8 @@ int IsPushConTypeKey(YGS2kEInputType type, YGS2kSConKey* key) return 0; } - for (int conPlayer = 0; conPlayer < YGS2kGetNumConPlayers(); conPlayer++) { - if (YGS2kGetConPlayerType(conPlayer) == type && YGS2kIsPushConPlayerKey(conPlayer, key)) return 1; + for (int player = 0; player < YGS2kGetNumPlayerSlots(); player++) { + if (YGS2kGetConType(player) == type && YGS2kIsPushConKey(player, key)) return 1; } return 0; } @@ -17459,11 +17459,11 @@ void spriteTime() { case YGS_INPUT_XBOX: case YGS_INPUT_PLAYSTATION: case YGS_INPUT_NINTENDO: { - int conPlayer = YGS2kGetLastActiveConPlayer(); - if (conPlayer == playerCons[0]) { + int player = YGS2kGetLastActiveCon(); + if (player == playerCons[0]) { lastPlayerInputType[0] = lastInputType; } - else if (conPlayer == playerCons[1]) { + else if (player == playerCons[1]) { lastPlayerInputType[1] = lastInputType; } break; @@ -17518,16 +17518,16 @@ void spriteTime() { #ifdef ENABLE_GAME_CONTROLLER if (inmenu) { - up = up || IsPushMenu(pl, BTN_UP, YGS2kGetConPlayerType(playerCons[pl])); - down = down || IsPushMenu(pl, BTN_DOWN, YGS2kGetConPlayerType(playerCons[pl])); - left = left || IsPushMenu(pl, BTN_LEFT, YGS2kGetConPlayerType(playerCons[pl])); - right = right || IsPushMenu(pl, BTN_RIGHT, YGS2kGetConPlayerType(playerCons[pl])); + up = up || IsPushMenu(pl, BTN_UP, YGS2kGetConType(playerCons[pl])); + down = down || IsPushMenu(pl, BTN_DOWN, YGS2kGetConType(playerCons[pl])); + left = left || IsPushMenu(pl, BTN_LEFT, YGS2kGetConType(playerCons[pl])); + right = right || IsPushMenu(pl, BTN_RIGHT, YGS2kGetConType(playerCons[pl])); } else { - up = up || YGS2kIsPushConPlayerKey(playerCons[pl], &conKeyAssign[BTN_UP + 8 * pl]); - down = down || YGS2kIsPushConPlayerKey(playerCons[pl], &conKeyAssign[BTN_DOWN + 8 * pl]); - left = left || YGS2kIsPushConPlayerKey(playerCons[pl], &conKeyAssign[BTN_LEFT + 8 * pl]); - right = right || YGS2kIsPushConPlayerKey(playerCons[pl], &conKeyAssign[BTN_RIGHT + 8 * pl]); + up = up || YGS2kIsPushConKey(playerCons[pl], &conKeyAssign[BTN_UP + 8 * pl]); + down = down || YGS2kIsPushConKey(playerCons[pl], &conKeyAssign[BTN_DOWN + 8 * pl]); + left = left || YGS2kIsPushConKey(playerCons[pl], &conKeyAssign[BTN_LEFT + 8 * pl]); + right = right || YGS2kIsPushConKey(playerCons[pl], &conKeyAssign[BTN_RIGHT + 8 * pl]); } #endif @@ -17568,16 +17568,16 @@ void spriteTime() { #ifdef ENABLE_GAME_CONTROLLER if (inmenu) { - up = up || IsPressMenu(pl, BTN_UP, YGS2kGetConPlayerType(playerCons[pl])); - down = down || IsPressMenu(pl, BTN_DOWN, YGS2kGetConPlayerType(playerCons[pl])); - left = left || IsPressMenu(pl, BTN_LEFT, YGS2kGetConPlayerType(playerCons[pl])); - right = right || IsPressMenu(pl, BTN_RIGHT, YGS2kGetConPlayerType(playerCons[pl])); + up = up || IsPressMenu(pl, BTN_UP, YGS2kGetConType(playerCons[pl])); + down = down || IsPressMenu(pl, BTN_DOWN, YGS2kGetConType(playerCons[pl])); + left = left || IsPressMenu(pl, BTN_LEFT, YGS2kGetConType(playerCons[pl])); + right = right || IsPressMenu(pl, BTN_RIGHT, YGS2kGetConType(playerCons[pl])); } else { - up = up || YGS2kIsPressConPlayerKey(playerCons[pl], &conKeyAssign[BTN_UP + 8 * pl]); - down = down || YGS2kIsPressConPlayerKey(playerCons[pl], &conKeyAssign[BTN_DOWN + 8 * pl]); - left = left || YGS2kIsPressConPlayerKey(playerCons[pl], &conKeyAssign[BTN_LEFT + 8 * pl]); - right = right || YGS2kIsPressConPlayerKey(playerCons[pl], &conKeyAssign[BTN_RIGHT + 8 * pl]); + up = up || YGS2kIsPressConKey(playerCons[pl], &conKeyAssign[BTN_UP + 8 * pl]); + down = down || YGS2kIsPressConKey(playerCons[pl], &conKeyAssign[BTN_DOWN + 8 * pl]); + left = left || YGS2kIsPressConKey(playerCons[pl], &conKeyAssign[BTN_LEFT + 8 * pl]); + right = right || YGS2kIsPressConKey(playerCons[pl], &conKeyAssign[BTN_RIGHT + 8 * pl]); } #endif diff --git a/src/main_sdl/ygs2kfunc.c b/src/main_sdl/ygs2kfunc.c index b3cb7c6..a6449b0 100644 --- a/src/main_sdl/ygs2kfunc.c +++ b/src/main_sdl/ygs2kfunc.c @@ -392,16 +392,12 @@ bool YGS2kHalt() /* イベント処理 || Process events */ - #ifdef ENABLE_JOYSTICK - bool joysChanged = false; - #endif - - #ifdef ENABLE_GAME_CONTROLLER - bool consChanged = false; - #endif SDL_PumpEvents(); SDL_Event ev; int showCursor = SDL_DISABLE; + #if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) + bool slotsChanged = false; + #endif while (SDL_PeepEvents(&ev, 1, SDL_GETEVENT, 0, SDL_LASTEVENT) == 1) { switch(ev.type){ @@ -418,13 +414,13 @@ bool YGS2kHalt() #ifdef ENABLE_JOYSTICK case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEREMOVED: - joysChanged = true; + slotsChanged = true; #endif #ifdef ENABLE_GAME_CONTROLLER case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: - consChanged = true; + slotsChanged = true; break; #endif @@ -451,19 +447,9 @@ bool YGS2kHalt() SDL_ShowCursor(SDL_DISABLE); } - #ifdef ENABLE_JOYSTICK - if (joysChanged) - { - YGS2kJoysClose(); - if (!YGS2kJoysOpen()) { - YGS2kExit(EXIT_FAILURE); - } - } - #endif - - #ifdef ENABLE_GAME_CONTROLLER - if (consChanged) { - if (!YGS2kConsChanged()) { + #if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) + if (slotsChanged) { + if (!YGS2kPlayerSlotsChanged()) { YGS2kExit(EXIT_FAILURE); } } diff --git a/src/main_sdl/ygs2kinput.c b/src/main_sdl/ygs2kinput.c index de87212..d5f1390 100644 --- a/src/main_sdl/ygs2kinput.c +++ b/src/main_sdl/ygs2kinput.c @@ -23,8 +23,6 @@ typedef struct YGS2kSJoy int* hatsRepeat; int* buttonsRepeat; } YGS2kSJoy; -static YGS2kSJoy* s_aJoys = NULL; -static int s_iNumJoys = -1; #endif #ifdef ENABLE_GAME_CONTROLLER @@ -32,21 +30,29 @@ static int s_iNumJoys = -1; typedef struct YGS2kSCon { SDL_GameController* controller; - SDL_JoystickID joyid; int axesRepeat[YGS_CONAXIS_MAX]; int buttonsRepeat[YGS_CONBUTTON_MAX]; } YGS2kSCon; -static YGS2kSCon* s_aConPlayerSlots = NULL; -static int s_iNumConPlayerSlots = 0; -static int s_iLastActiveConPlayer = -1; +static int s_iLastActiveCon = -1; +#endif -bool YGS2kIsCon ( int device ) +#if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) +typedef struct YGS2kSPlayerSlot { - return - (SDL_IsGameController(device) && SDL_GameControllerTypeForIndex(device) != SDL_CONTROLLER_TYPE_UNKNOWN) || - SDL_GameControllerMappingForGUID(SDL_JoystickGetDeviceGUID(device)) != NULL; -} + YGS2kEPlayerSlotType type; + union + { + #ifdef ENABLE_JOYSTICK + YGS2kSJoy joy; + #endif + #ifdef ENABLE_GAME_CONTROLLER + YGS2kSCon con; + #endif + }; +} YGS2kSPlayerSlot; +static YGS2kSPlayerSlot* s_aPlayerSlots = NULL; +static int s_iNumPlayerSlots = 0; #endif YGS2kEInputType YGS2kGetLastInputType () @@ -97,116 +103,303 @@ int YGS2kGetMaxKey () } #endif -#ifdef ENABLE_JOYSTICK -// TODO: Change joysticks to use SDL player index APIs instead of SDL device -// index APIs, similar to game controllers. +#if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) -void YGS2kJoysClose () +static bool YGS2kIsCon ( int device ) { - if (s_aJoys) - { - for (int device = 0; device < s_iNumJoys; device++) - { - if (s_aJoys[device].joystick && SDL_JoystickGetAttached(s_aJoys[device].joystick)) SDL_JoystickClose(s_aJoys[device].joystick); - if (s_aJoys[device].axesRepeat) free(s_aJoys[device].axesRepeat); - if (s_aJoys[device].hatsRepeat) free(s_aJoys[device].hatsRepeat); - if (s_aJoys[device].buttonsRepeat) free(s_aJoys[device].buttonsRepeat); - } - free(s_aJoys); + if (device < 0) { + return false; } - s_aJoys = NULL; - s_iNumJoys = -1; + + return + (SDL_IsGameController(device) && SDL_GameControllerTypeForIndex(device) != SDL_CONTROLLER_TYPE_UNKNOWN) || + SDL_GameControllerMappingForGUID(SDL_JoystickGetDeviceGUID(device)) != NULL; } -bool YGS2kJoysOpen () -{ - if ((s_iNumJoys = SDL_NumJoysticks()) > 0) - { - if (!(s_aJoys = (YGS2kSJoy*)calloc((size_t)s_iNumJoys, sizeof(YGS2kSJoy)))) - { - s_iNumJoys = -1; +static bool YGS2kResizePlayerSlots(int numSlots) { + if (numSlots == s_iNumPlayerSlots) { + return true; + } + else if (numSlots == 0) { + free(s_aPlayerSlots); + s_aPlayerSlots = NULL; + s_iNumPlayerSlots = 0; + return true; + } + + YGS2kSPlayerSlot* const oldSlots = s_aPlayerSlots; + const int oldNumSlots = s_iNumPlayerSlots; + if (s_aPlayerSlots) { + s_aPlayerSlots = realloc(s_aPlayerSlots, sizeof(YGS2kSPlayerSlot) * numSlots); + } + else { + s_aPlayerSlots = malloc(sizeof(YGS2kSPlayerSlot) * numSlots); + } + if (!s_aPlayerSlots) { + fprintf(stderr, "Failed to resize joysticks/controllers array\n"); + s_aPlayerSlots = oldSlots; + return false; + } + for (int player = s_iNumPlayerSlots; player < numSlots; player++) { + s_aPlayerSlots[player] = (YGS2kSPlayerSlot) { 0 }; + } + s_iNumPlayerSlots = numSlots; + return true; +} + +bool YGS2kPlayerSlotsChanged() { + for (int player = 0; player < s_iNumPlayerSlots; player++) { + YGS2kSPlayerSlot* const slot = &s_aPlayerSlots[player]; + switch (slot->type) { + #ifdef ENABLE_JOYSTICK + case YGS_PLAYERSLOT_JOY: + if (!SDL_JoystickGetAttached(slot->joy.joystick)) { + if (slot->joy.axesRepeat) free(slot->joy.axesRepeat); + if (slot->joy.hatsRepeat) free(slot->joy.hatsRepeat); + if (slot->joy.buttonsRepeat) free(slot->joy.buttonsRepeat); + *slot = (YGS2kSPlayerSlot) { 0 }; + } + break; + #endif + + #ifdef ENABLE_GAME_CONTROLLER + case YGS_PLAYERSLOT_CON: + if (!SDL_GameControllerGetAttached(slot->con.controller)) { + *slot = (YGS2kSPlayerSlot) { 0 }; + } + break; + #endif + + default: + case YGS_PLAYERSLOT_NULL: + break; + } + } + + const int numJoys = SDL_NumJoysticks(); + + // Only opened joysticks will have a non-NULL return value from + // SDL_JoystickFromInstanceID(), so we can use it to skip already opened + // devices. + // + // Internally, SDL uses joystick APIs for game controllers, so it also skips + // already opened game controllers. + + #ifdef ENABLE_GAME_CONTROLLER + for (int device = 0; device < numJoys; device++) { + const SDL_JoystickID id = SDL_JoystickGetDeviceInstanceID(device); + if (id >= 0 && SDL_JoystickFromInstanceID(id)) { + continue; + } + if (!YGS2kIsCon(device)) { + continue; + } + + SDL_GameController* const controller = SDL_GameControllerOpen(device); + if (!controller) { + fprintf(stderr, "Failed to open controller: %s\n", SDL_GetError()); + return false; + } + bool playerIndexFound = false; + int player; + for (player = 0; player < s_iNumPlayerSlots; player++) { + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_NULL) { + playerIndexFound = true; + break; + } + } + if (!playerIndexFound) { + if (!YGS2kResizePlayerSlots(s_iNumPlayerSlots + 1)) { + fprintf(stderr, "Failed to open controller: %s\n", SDL_GetError()); + SDL_GameControllerClose(controller); + return false; + } + player = s_iNumPlayerSlots - 1; + } + SDL_GameControllerSetPlayerIndex(controller, player); + s_aPlayerSlots[player].con.controller = controller; + s_aPlayerSlots[player].type = YGS_PLAYERSLOT_CON; + } + #endif + + #ifdef ENABLE_JOYSTICK + for (int device = 0; device < numJoys; device++) { + const SDL_JoystickID id = SDL_JoystickGetDeviceInstanceID(device); + if (id >= 0 && SDL_JoystickFromInstanceID(id)) { + continue; + } + if (YGS2kIsCon(device)) { + continue; + } + + SDL_Joystick* const joystick = SDL_JoystickOpen(device); + if (!joystick) { + fprintf(stderr, "Failed to open joystick: %s\n", SDL_GetError()); + goto fail; + } + bool playerIndexFound = false; + int player; + for (player = 0; player < s_iNumPlayerSlots; player++) { + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_NULL) { + playerIndexFound = true; + break; + } + } + if (!playerIndexFound) { + if (!YGS2kResizePlayerSlots(s_iNumPlayerSlots + 1)) { + goto fail; + } + player = s_iNumPlayerSlots - 1; + } + SDL_JoystickSetPlayerIndex(joystick, player); + + if ( + (s_aPlayerSlots[player].joy.numAxes = SDL_JoystickNumAxes(joystick)) >= 0 && + (s_aPlayerSlots[player].joy.numHats = SDL_JoystickNumHats(joystick)) >= 0 && + (s_aPlayerSlots[player].joy.numButtons = SDL_JoystickNumButtons(joystick)) >= 0 + ) { + if (s_aPlayerSlots[player].joy.numAxes > 0 && !(s_aPlayerSlots[player].joy.axesRepeat = (int*)calloc((size_t)s_aPlayerSlots[player].joy.numAxes * 2, sizeof(int)))) { + fprintf(stderr, "Failed to allocate axes repeat array for joystick\n"); + goto fail; + } + if (s_aPlayerSlots[player].joy.numHats > 0 && !(s_aPlayerSlots[player].joy.hatsRepeat = (int*)calloc((size_t)s_aPlayerSlots[player].joy.numHats * 4, sizeof(int)))) { + fprintf(stderr, "Failed to allocate hats repeat array for joystick\n"); + goto fail; + } + if (s_aPlayerSlots[player].joy.numButtons > 0 && !(s_aPlayerSlots[player].joy.buttonsRepeat = (int*)calloc((size_t)s_aPlayerSlots[player].joy.numButtons, sizeof(int)))) { + fprintf(stderr, "Failed to allocate buttons repeat array for joystick\n"); + goto fail; + } + } + if (false) { + fail: + if (s_aPlayerSlots[player].joy.axesRepeat) free(s_aPlayerSlots[player].joy.axesRepeat); + if (s_aPlayerSlots[player].joy.hatsRepeat) free(s_aPlayerSlots[player].joy.hatsRepeat); + if (s_aPlayerSlots[player].joy.buttonsRepeat) free(s_aPlayerSlots[player].joy.buttonsRepeat); + if (joystick) SDL_JoystickClose(joystick); return false; } + s_aPlayerSlots[player].joy.joystick = joystick; + s_aPlayerSlots[player].type = YGS_PLAYERSLOT_JOY; + } + #endif - for (int device = 0; device < s_iNumJoys; device++) + int numRequiredSlots = 0; + for (int player = 0; player < s_iNumPlayerSlots; player++) { + if (s_aPlayerSlots[player].type != YGS_PLAYERSLOT_NULL) { + numRequiredSlots = player + 1; + } + } + return YGS2kResizePlayerSlots(numRequiredSlots); +} + +static void YGS2kPlayerSlotsClose() +{ + if (s_aPlayerSlots) + { + for (int player = 0; player < s_iNumPlayerSlots; player++) { - #ifdef ENABLE_GAME_CONTROLLER - if (!YGS2kIsCon(device)) + switch (s_aPlayerSlots[player].type) { - #endif - bool fail = false; - if (!(s_aJoys[device].joystick = SDL_JoystickOpen(device))) fail = true; - else if ( - (s_aJoys[device].numAxes = SDL_JoystickNumAxes(s_aJoys[device].joystick)) >= 0 && - (s_aJoys[device].numHats = SDL_JoystickNumHats(s_aJoys[device].joystick)) >= 0 && - (s_aJoys[device].numButtons = SDL_JoystickNumButtons(s_aJoys[device].joystick)) >= 0 - ) + #ifdef ENABLE_JOYSTICK + case YGS_PLAYERSLOT_JOY: { + YGS2kSJoy* const joy = &s_aPlayerSlots[player].joy; + if (SDL_JoystickGetAttached(joy->joystick)) { - if (s_aJoys[device].numAxes > 0 && !(s_aJoys[device].axesRepeat = (int*)calloc((size_t)s_aJoys[device].numAxes * 2, sizeof(int)))) fail = true; - if (s_aJoys[device].numHats > 0 && !(s_aJoys[device].hatsRepeat = (int*)calloc((size_t)s_aJoys[device].numHats * 4, sizeof(int)))) fail = true; - if (s_aJoys[device].numButtons > 0 && !(s_aJoys[device].buttonsRepeat = (int*)calloc((size_t)s_aJoys[device].numButtons, sizeof(int)))) fail = true; + SDL_JoystickClose(joy->joystick); } - if (fail) + if (joy->axesRepeat) free(joy->axesRepeat); + if (joy->hatsRepeat) free(joy->hatsRepeat); + if (joy->buttonsRepeat) free(joy->buttonsRepeat); + break; + } + #endif + + #ifdef ENABLE_GAME_CONTROLLER + case YGS_PLAYERSLOT_CON: { + if (SDL_GameControllerGetAttached(s_aPlayerSlots[player].con.controller)) { - s_iNumJoys = device + !!s_aJoys[device].joystick; - YGS2kJoysClose(); - s_iNumJoys = -1; - return false; + SDL_GameControllerClose(s_aPlayerSlots[player].con.controller); } - #ifdef ENABLE_GAME_CONTROLLER + break; } #endif + + default: + case YGS_PLAYERSLOT_NULL: + break; + } } - return true; + free(s_aPlayerSlots); + } + s_aPlayerSlots = NULL; + s_iNumPlayerSlots = 0; +} + +int YGS2kGetNumPlayerSlots() +{ + return s_iNumPlayerSlots; +} + +YGS2kEPlayerSlotType YGS2kGetPlayerSlotType(int player) +{ + if (player < 0 || player >= s_iNumPlayerSlots) { + return YGS_PLAYERSLOT_NULL; + } + else { + return s_aPlayerSlots[player].type; } - else if (s_iNumJoys == 0) return true; - else return false; } +#endif + +#ifdef ENABLE_JOYSTICK + static void YGS2kJoyInputsUpdate () { - if (!s_aJoys) return; + if (!s_aPlayerSlots) return; - for (int device = 0; device < s_iNumJoys; device++) + for (int player = 0; player < s_iNumPlayerSlots; player++) { - #ifdef ENABLE_GAME_CONTROLLER - if (YGS2kIsCon(device)) continue; - #endif - if (!SDL_JoystickGetAttached(s_aJoys[device].joystick)) - { + if ( + s_aPlayerSlots[player].type != YGS_PLAYERSLOT_JOY || + !SDL_JoystickGetAttached(s_aPlayerSlots[player].joy.joystick) + ) { continue; } - const YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(device); + const YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(player); const YGS2kSJoyGUID zeroGUID = { 0 }; if (memcmp(checkGUID.data, zeroGUID.data, sizeof(checkGUID.data)) == 0) continue; - for (int axis = 0; axis < s_aJoys[device].numAxes; axis++) + YGS2kSJoy* const joy = &s_aPlayerSlots[player].joy; + + for (int axis = 0; axis < joy->numAxes; axis++) { - const int value = SDL_JoystickGetAxis(s_aJoys[device].joystick, axis); + const int value = SDL_JoystickGetAxis(joy->joystick, axis); if (value < -YGS_DEADZONE_MAX) { - if (++s_aJoys[device].axesRepeat[axis*2 + 0] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; + if (++joy->axesRepeat[axis*2 + 0] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; } else { - s_aJoys[device].axesRepeat[axis*2 + 0] = 0; + joy->axesRepeat[axis*2 + 0] = 0; } if (value > +YGS_DEADZONE_MAX) { - if (++s_aJoys[device].axesRepeat[axis*2 + 1] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; + if (++joy->axesRepeat[axis*2 + 1] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; } else { - s_aJoys[device].axesRepeat[axis*2 + 1] = 0; + joy->axesRepeat[axis*2 + 1] = 0; } } - for (int hat = 0; hat < s_aJoys[device].numHats; hat++) + for (int hat = 0; hat < joy->numHats; hat++) { - Uint8 value = SDL_JoystickGetHat(s_aJoys[device].joystick, hat); + Uint8 value = SDL_JoystickGetHat(joy->joystick, hat); const Uint8 hatValues[4] = { SDL_HAT_LEFT, @@ -218,24 +411,24 @@ static void YGS2kJoyInputsUpdate () { if (value & hatValues[valueIndex]) { - if (++s_aJoys[device].hatsRepeat[hat*4 + valueIndex] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; + if (++joy->hatsRepeat[hat*4 + valueIndex] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; } else { - s_aJoys[device].hatsRepeat[hat*4 + valueIndex] = 0; + joy->hatsRepeat[hat*4 + valueIndex] = 0; } } } - for (int button = 0; button < s_aJoys[device].numButtons; button++) + for (int button = 0; button < joy->numButtons; button++) { - if (SDL_JoystickGetButton(s_aJoys[device].joystick, button)) + if (SDL_JoystickGetButton(joy->joystick, button)) { - if (++s_aJoys[device].buttonsRepeat[button] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; + if (++joy->buttonsRepeat[button] == 1) YGS2kLastInputType = YGS_INPUT_JOYSTICK; } else { - s_aJoys[device].buttonsRepeat[button] = 0; + joy->buttonsRepeat[button] = 0; } } } @@ -243,77 +436,79 @@ static void YGS2kJoyInputsUpdate () bool YGS2kIsPushJoyKey ( const YGS2kSJoyKey* const key ) { - if (!s_aJoys || s_iNumJoys <= 0 || key == NULL || key->device >= s_iNumJoys) return false; + if (!s_aPlayerSlots || s_iNumPlayerSlots <= 0 || key == NULL || key->player >= s_iNumPlayerSlots) return false; - int device = 0; - int deviceMax = 0; - if (key->device >= 0) + int player = 0; + int playerMax = 0; + if (key->player >= 0) { - YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(key->device); + YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(key->player); YGS2kSJoyGUID zeroGUID = { 0 }; if (memcmp(checkGUID.data, zeroGUID.data, sizeof(checkGUID.data)) != 0 && memcmp(key->guid.data, checkGUID.data, sizeof(checkGUID.data)) == 0) { - device = key->device; - deviceMax = key->device + 1; + player = key->player; + playerMax = key->player + 1; } } else { - device = 0; - deviceMax = s_iNumJoys; + player = 0; + playerMax = s_iNumPlayerSlots; } - for (; device < deviceMax; device++) + for (; player < playerMax; player++) { + YGS2kSJoy* const joy = &s_aPlayerSlots[player].joy; + switch (key->type) { case YGS_JOYKEY_ANY: - for (int axis = 0; axis < s_aJoys[device].numAxes; axis++) + for (int axis = 0; axis < joy->numAxes; axis++) { - if (s_aJoys[device].axesRepeat[axis*2 + 0] == 1) return true; - if (s_aJoys[device].axesRepeat[axis*2 + 1] == 1) return true; + if (joy->axesRepeat[axis*2 + 0] == 1) return true; + if (joy->axesRepeat[axis*2 + 1] == 1) return true; } - for (int hat = 0; hat < s_aJoys[device].numHats; hat++) + for (int hat = 0; hat < joy->numHats; hat++) { - if (s_aJoys[device].hatsRepeat[hat] == 1) return true; + if (joy->hatsRepeat[hat] == 1) return true; } - for (int button = 0; button < s_aJoys[device].numButtons; button++) + for (int button = 0; button < joy->numButtons; button++) { - if (s_aJoys[device].buttonsRepeat[button] == 1) return true; + if (joy->buttonsRepeat[button] == 1) return true; } break; case YGS_JOYKEY_AXIS: - if (key->setting.index < s_aJoys[device].numAxes) + if (key->setting.index < joy->numAxes) { if (key->setting.value == -YGS_DEADZONE_MAX) { - return s_aJoys[device].axesRepeat[key->setting.index * 2 + 0] == 1; + return joy->axesRepeat[key->setting.index * 2 + 0] == 1; } else if (key->setting.value == +YGS_DEADZONE_MAX) { - return s_aJoys[device].axesRepeat[key->setting.index * 2 + 1] == 1; + return joy->axesRepeat[key->setting.index * 2 + 1] == 1; } } break; case YGS_JOYKEY_HAT: - if (key->setting.index < s_aJoys[device].numHats) + if (key->setting.index < joy->numHats) { switch (key->setting.value) { case SDL_HAT_LEFT: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 0] == 1; + return joy->hatsRepeat[key->setting.index * 4 + 0] == 1; case SDL_HAT_RIGHT: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 1] == 1; + return joy->hatsRepeat[key->setting.index * 4 + 1] == 1; case SDL_HAT_UP: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 2] == 1; + return joy->hatsRepeat[key->setting.index * 4 + 2] == 1; case SDL_HAT_DOWN: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 3] == 1; + return joy->hatsRepeat[key->setting.index * 4 + 3] == 1; default: break; } } break; case YGS_JOYKEY_BUTTON: - if (key->setting.button < s_aJoys[device].numButtons) return s_aJoys[device].buttonsRepeat[key->setting.button] == 1; + if (key->setting.button < joy->numButtons) return joy->buttonsRepeat[key->setting.button] == 1; break; default: break; @@ -324,77 +519,79 @@ bool YGS2kIsPushJoyKey ( const YGS2kSJoyKey* const key ) bool YGS2kIsPressJoyKey ( const YGS2kSJoyKey* const key ) { - if (!s_aJoys || s_iNumJoys <= 0 || key == NULL || key->device >= s_iNumJoys) return false; + if (!s_aPlayerSlots || s_iNumPlayerSlots <= 0 || key == NULL || key->player >= s_iNumPlayerSlots) return false; - int device = 0; - int deviceMax = 0; - if (key->device >= 0) + int player = 0; + int playerMax = 0; + if (key->player >= 0) { - YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(key->device); + YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(key->player); YGS2kSJoyGUID zeroGUID = { 0 }; if (memcmp(checkGUID.data, zeroGUID.data, sizeof(checkGUID.data)) != 0 && memcmp(key->guid.data, checkGUID.data, sizeof(checkGUID.data)) == 0) { - device = key->device; - deviceMax = key->device + 1; + player = key->player; + playerMax = key->player + 1; } } else { - device = 0; - deviceMax = s_iNumJoys; + player = 0; + playerMax = s_iNumPlayerSlots; } - for (; device < deviceMax; device++) + for (; player < playerMax; player++) { + YGS2kSJoy* const joy = &s_aPlayerSlots[player].joy; + switch (key->type) { case YGS_JOYKEY_ANY: - for (int axis = 0; axis < s_aJoys[device].numAxes; axis++) + for (int axis = 0; axis < joy->numAxes; axis++) { - if (s_aJoys[device].axesRepeat[axis*2 + 0] != 0) return true; - if (s_aJoys[device].axesRepeat[axis*2 + 1] != 0) return true; + if (joy->axesRepeat[axis*2 + 0] != 0) return true; + if (joy->axesRepeat[axis*2 + 1] != 0) return true; } - for (int hat = 0; hat < s_aJoys[device].numHats; hat++) + for (int hat = 0; hat < joy->numHats; hat++) { - if (s_aJoys[device].hatsRepeat[hat] != 0) return true; + if (joy->hatsRepeat[hat] != 0) return true; } - for (int button = 0; button < s_aJoys[device].numButtons; button++) + for (int button = 0; button < joy->numButtons; button++) { - if (s_aJoys[device].buttonsRepeat[button] != 0) return true; + if (joy->buttonsRepeat[button] != 0) return true; } break; case YGS_JOYKEY_AXIS: - if (key->setting.index < s_aJoys[device].numAxes) + if (key->setting.index < joy->numAxes) { if (key->setting.value == -YGS_DEADZONE_MAX) { - return s_aJoys[device].axesRepeat[key->setting.index * 2 + 0] != 0; + return joy->axesRepeat[key->setting.index * 2 + 0] != 0; } else if (key->setting.value == +YGS_DEADZONE_MAX) { - return s_aJoys[device].axesRepeat[key->setting.index * 2 + 1] != 0; + return joy->axesRepeat[key->setting.index * 2 + 1] != 0; } } break; case YGS_JOYKEY_HAT: - if (key->setting.index < s_aJoys[device].numHats) + if (key->setting.index < joy->numHats) { switch (key->setting.value) { case SDL_HAT_LEFT: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 0] != 0; + return joy->hatsRepeat[key->setting.index * 4 + 0] != 0; case SDL_HAT_RIGHT: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 1] != 0; + return joy->hatsRepeat[key->setting.index * 4 + 1] != 0; case SDL_HAT_UP: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 2] != 0; + return joy->hatsRepeat[key->setting.index * 4 + 2] != 0; case SDL_HAT_DOWN: - return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 3] != 0; + return joy->hatsRepeat[key->setting.index * 4 + 3] != 0; default: break; } } break; case YGS_JOYKEY_BUTTON: - if (key->setting.button < s_aJoys[device].numButtons) return s_aJoys[device].buttonsRepeat[key->setting.button] != 0 ? 1 : 0; + if (key->setting.button < joy->numButtons) return joy->buttonsRepeat[key->setting.button] != 0; break; default: break; @@ -405,111 +602,113 @@ bool YGS2kIsPressJoyKey ( const YGS2kSJoyKey* const key ) int YGS2kGetJoyKeyRepeat ( const YGS2kSJoyKey* const key ) { - if (!s_aJoys || s_iNumJoys <= 0 || key == NULL || key->device >= s_iNumJoys) return 0; + if (!s_aPlayerSlots || s_iNumPlayerSlots <= 0 || key == NULL || key->player >= s_iNumPlayerSlots) return 0; bool multi; - int device = 0; - int deviceMax = 0; + int player = 0; + int playerMax = 0; int maxRepeat = 0; - if (key->device >= 0) + if (key->player >= 0) { - YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(key->device); + YGS2kSJoyGUID checkGUID = YGS2kGetJoyGUID(key->player); YGS2kSJoyGUID zeroGUID = { 0 }; if (memcmp(checkGUID.data, zeroGUID.data, sizeof(checkGUID.data)) != 0 && memcmp(key->guid.data, checkGUID.data, sizeof(checkGUID.data)) == 0) { - device = key->device; - deviceMax = key->device + 1; + player = key->player; + playerMax = key->player + 1; multi = false; } } else { - device = 0; - deviceMax = s_iNumJoys; + player = 0; + playerMax = s_iNumPlayerSlots; multi = true; } - for (; device < deviceMax; device++) + for (; player < playerMax; player++) { + YGS2kSJoy* const joy = &s_aPlayerSlots[player].joy; + switch (key->type) { case YGS_JOYKEY_ANY: - for (int axis = 0; axis < s_aJoys[device].numAxes; axis++) + for (int axis = 0; axis < joy->numAxes; axis++) { - if (s_aJoys[device].axesRepeat[axis*2 + 0] > maxRepeat) maxRepeat = s_aJoys[device].axesRepeat[axis*2 + 0]; - if (s_aJoys[device].axesRepeat[axis*2 + 1] > maxRepeat) maxRepeat = s_aJoys[device].axesRepeat[axis*2 + 1]; + if (joy->axesRepeat[axis*2 + 0] > maxRepeat) maxRepeat = joy->axesRepeat[axis*2 + 0]; + if (joy->axesRepeat[axis*2 + 1] > maxRepeat) maxRepeat = joy->axesRepeat[axis*2 + 1]; } - for (int hat = 0; hat < s_aJoys[device].numHats; hat++) + for (int hat = 0; hat < joy->numHats; hat++) { - if (s_aJoys[device].hatsRepeat[hat] > maxRepeat) maxRepeat = s_aJoys[device].hatsRepeat[hat]; + if (joy->hatsRepeat[hat] > maxRepeat) maxRepeat = joy->hatsRepeat[hat]; } - for (int button = 0; button < s_aJoys[device].numButtons; button++) + for (int button = 0; button < joy->numButtons; button++) { - if (s_aJoys[device].buttonsRepeat[button] > maxRepeat) maxRepeat = s_aJoys[device].buttonsRepeat[button]; + if (joy->buttonsRepeat[button] > maxRepeat) maxRepeat = joy->buttonsRepeat[button]; } break; case YGS_JOYKEY_AXIS: - if (key->setting.index < s_aJoys[device].numAxes) + if (key->setting.index < joy->numAxes) { if (key->setting.value == -YGS_DEADZONE_MAX) { if (multi) { - if (s_aJoys[device].axesRepeat[key->setting.index * 2 + 0] > maxRepeat) maxRepeat = s_aJoys[device].axesRepeat[key->setting.index * 2 + 0]; + if (joy->axesRepeat[key->setting.index * 2 + 0] > maxRepeat) maxRepeat = joy->axesRepeat[key->setting.index * 2 + 0]; } - else return s_aJoys[device].axesRepeat[key->setting.index * 2 + 0]; + else return joy->axesRepeat[key->setting.index * 2 + 0]; } else if (key->setting.value == +YGS_DEADZONE_MAX) { if (multi) { - if (s_aJoys[device].axesRepeat[key->setting.index * 2 + 1] > maxRepeat) maxRepeat = s_aJoys[device].axesRepeat[key->setting.index * 2 + 1]; + if (joy->axesRepeat[key->setting.index * 2 + 1] > maxRepeat) maxRepeat = joy->axesRepeat[key->setting.index * 2 + 1]; } - else return s_aJoys[device].axesRepeat[key->setting.index * 2 + 1]; + else return joy->axesRepeat[key->setting.index * 2 + 1]; } } break; case YGS_JOYKEY_HAT: - if (key->setting.index < s_aJoys[device].numHats) + if (key->setting.index < joy->numHats) { switch (key->setting.value) { case SDL_HAT_LEFT: if (multi) { - if (s_aJoys[device].hatsRepeat[key->setting.index * 4 + 0] > maxRepeat) maxRepeat = s_aJoys[device].hatsRepeat[key->setting.index * 4 + 0]; + if (joy->hatsRepeat[key->setting.index * 4 + 0] > maxRepeat) maxRepeat = joy->hatsRepeat[key->setting.index * 4 + 0]; } - else return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 0]; + else return joy->hatsRepeat[key->setting.index * 4 + 0]; case SDL_HAT_RIGHT: if (multi) { - if (s_aJoys[device].hatsRepeat[key->setting.index * 4 + 1] > maxRepeat) maxRepeat = s_aJoys[device].hatsRepeat[key->setting.index * 4 + 1]; + if (joy->hatsRepeat[key->setting.index * 4 + 1] > maxRepeat) maxRepeat = joy->hatsRepeat[key->setting.index * 4 + 1]; } - else return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 1]; + else return joy->hatsRepeat[key->setting.index * 4 + 1]; case SDL_HAT_UP: if (multi) { - if (s_aJoys[device].hatsRepeat[key->setting.index * 4 + 2] > maxRepeat) maxRepeat = s_aJoys[device].hatsRepeat[key->setting.index * 4 + 2]; + if (joy->hatsRepeat[key->setting.index * 4 + 2] > maxRepeat) maxRepeat = joy->hatsRepeat[key->setting.index * 4 + 2]; } - else return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 2]; + else return joy->hatsRepeat[key->setting.index * 4 + 2]; case SDL_HAT_DOWN: if (multi) { - if (s_aJoys[device].hatsRepeat[key->setting.index * 4 + 3] > maxRepeat) maxRepeat = s_aJoys[device].hatsRepeat[key->setting.index * 4 + 3]; + if (joy->hatsRepeat[key->setting.index * 4 + 3] > maxRepeat) maxRepeat = joy->hatsRepeat[key->setting.index * 4 + 3]; } - else return s_aJoys[device].hatsRepeat[key->setting.index * 4 + 3]; + else return joy->hatsRepeat[key->setting.index * 4 + 3]; default: break; } } break; case YGS_JOYKEY_BUTTON: - if (key->setting.button < s_aJoys[device].numButtons) + if (key->setting.button < joy->numButtons) { if (multi) { - if (s_aJoys[device].buttonsRepeat[key->setting.button] > maxRepeat) maxRepeat = s_aJoys[device].buttonsRepeat[key->setting.button]; + if (joy->buttonsRepeat[key->setting.button] > maxRepeat) maxRepeat = joy->buttonsRepeat[key->setting.button]; } - else return s_aJoys[device].buttonsRepeat[key->setting.button]; + else return joy->buttonsRepeat[key->setting.button]; } break; default: @@ -519,35 +718,30 @@ int YGS2kGetJoyKeyRepeat ( const YGS2kSJoyKey* const key ) return maxRepeat; } -int YGS2kGetMaxJoys() -{ - return s_iNumJoys; -} - int YGS2kGetNumJoys() { - #ifdef ENABLE_GAME_CONTROLLER - int numJoys = 0; - for (int device = 0; device < s_iNumJoys; device++) - { - if (!YGS2kIsCon(device)) numJoys++; + int foundJoys; + for (int player = 0; player < s_iNumPlayerSlots; player++) { + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_JOY) { + foundJoys++; + } } - return numJoys; - #else - return s_iNumJoys; - #endif + return foundJoys; } -YGS2kSJoyGUID YGS2kGetJoyGUID(int device) +YGS2kSJoyGUID YGS2kGetJoyGUID(int player) { - if (s_iNumJoys <= 0 || device >= s_iNumJoys - #ifdef ENABLE_GAME_CONTROLLER - || YGS2kIsCon(device) - #endif - ) return (YGS2kSJoyGUID) { 0 }; + if ( + player < 0 || + s_iNumPlayerSlots <= 0 || + player >= s_iNumPlayerSlots || + s_aPlayerSlots[player].type != YGS_PLAYERSLOT_JOY + ) { + return (YGS2kSJoyGUID) { 0 }; + } SDL_JoystickGUID sdlGUID; - sdlGUID = SDL_JoystickGetGUID(s_aJoys[device].joystick); + sdlGUID = SDL_JoystickGetGUID(s_aPlayerSlots[player].joy.joystick); YGS2kSJoyGUID joyGUID = { 0 }; for (int32_t i = 0; i < 4; i++) @@ -561,22 +755,18 @@ YGS2kSJoyGUID YGS2kGetJoyGUID(int device) return joyGUID; } -int YGS2kGetMaxJoyAxis(int device) +int YGS2kGetMaxJoyAxis(int player) { - if (s_iNumJoys > 0 && device < s_iNumJoys) + if (player >= 0 && s_iNumPlayerSlots > 0 && player < s_iNumPlayerSlots) { - #ifdef ENABLE_GAME_CONTROLLER - if (!YGS2kIsCon(device)) + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_JOY) { - return s_aJoys[device].numAxes; + return s_aPlayerSlots[player].joy.numAxes; } else { return -1; } - #else - return s_aJoys[device].numAxes; - #endif } else { @@ -584,22 +774,18 @@ int YGS2kGetMaxJoyAxis(int device) } } -int YGS2kGetMaxJoyHat(int device) +int YGS2kGetMaxJoyHat(int player) { - if (s_iNumJoys > 0 && device < s_iNumJoys) + if (player >= 0 && s_iNumPlayerSlots > 0 && player < s_iNumPlayerSlots) { - #ifdef ENABLE_GAME_CONTROLLER - if (!YGS2kIsCon(device)) + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_JOY) { - return s_aJoys[device].numHats; + return s_aPlayerSlots[player].joy.numHats; } else { return -1; } - #else - return s_aJoys[device].numHats; - #endif } else { @@ -607,22 +793,18 @@ int YGS2kGetMaxJoyHat(int device) } } -int YGS2kGetMaxJoyButton(int device) +int YGS2kGetMaxJoyButton(int player) { - if (s_iNumJoys > 0 && device < s_iNumJoys) + if (player >= 0 && s_iNumPlayerSlots > 0 && player < s_iNumPlayerSlots) { - #ifdef ENABLE_GAME_CONTROLLER - if (!YGS2kIsCon(device)) + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_JOY) { - return s_aJoys[device].numButtons; + return s_aPlayerSlots[player].joy.numButtons; } else { return -1; } - #else - return s_aJoys[device].numButtons; - #endif } else { @@ -632,97 +814,6 @@ int YGS2kGetMaxJoyButton(int device) #endif #ifdef ENABLE_GAME_CONTROLLER -void YGS2kConsClose() -{ - for (int player = 0; player < s_iNumConPlayerSlots; player++) - { - if (s_aConPlayerSlots[player].controller && SDL_GameControllerGetAttached(s_aConPlayerSlots[player].controller)) - { - SDL_GameControllerClose(s_aConPlayerSlots[player].controller); - } - } - if (s_aConPlayerSlots) { - free(s_aConPlayerSlots); - s_aConPlayerSlots = NULL; - } - s_iNumConPlayerSlots = 0; -} - -static bool YGS2kConPlayerSlotsResize(int numSlots) { - if (numSlots == s_iNumConPlayerSlots) { - return true; - } - else if (numSlots == 0) { - free(s_aConPlayerSlots); - s_aConPlayerSlots = NULL; - s_iNumConPlayerSlots = 0; - return true; - } - - YGS2kSCon* const oldSlots = s_aConPlayerSlots; - const int oldNumSlots = s_iNumConPlayerSlots; - if (s_aConPlayerSlots) { - s_aConPlayerSlots = realloc(s_aConPlayerSlots, sizeof(YGS2kSCon) * numSlots); - } - else { - s_aConPlayerSlots = malloc(sizeof(YGS2kSCon) * numSlots); - } - if (!s_aConPlayerSlots) { - printf("Failed to resize controllers array\n"); - s_aConPlayerSlots = oldSlots; - return false; - } - for (int player = s_iNumConPlayerSlots; player < numSlots; player++) { - s_aConPlayerSlots[player] = (YGS2kSCon) { 0 }; - } - s_iNumConPlayerSlots = numSlots; - return true; -} - -bool YGS2kConsChanged() { - for (int player = 0; player < s_iNumConPlayerSlots; player++) { - if (!SDL_GameControllerGetAttached(s_aConPlayerSlots[player].controller)) { - s_aConPlayerSlots[player] = (YGS2kSCon) { 0 }; - } - } - - const int numJoys = SDL_NumJoysticks(); - for (int device = 0; device < numJoys; device++) { - if (YGS2kIsCon(device)) { - // SDL internally calls SDL_JoystickOpen() in SDL_GameControllerOpen(), and - // SDL_JoystickFromInstanceID() only returns a joystick if it's been opened, so - // we can use SDL_JoystickFromInstanceID() to determine if a device index is - // already open. - const SDL_JoystickID id = SDL_JoystickGetDeviceInstanceID(device); - if (id >= 0 && !SDL_JoystickFromInstanceID(id)) { - SDL_GameController* const controller = SDL_GameControllerOpen(device); - if (!controller) { - printf("Failed to open controller\n"); - return false; - } - const int player = SDL_GameControllerGetPlayerIndex(controller); - if (player < 0) { - printf("Failed to get controller player index\n"); - SDL_GameControllerClose(controller); - return false; - } - if (player >= s_iNumConPlayerSlots && !YGS2kConPlayerSlotsResize(player + 1)) { - SDL_GameControllerClose(controller); - return false; - } - s_aConPlayerSlots[player].controller = controller; - } - } - } - - int numRequiredSlots = 0; - for (int player = 0; player < s_iNumConPlayerSlots; player++) { - if (s_aConPlayerSlots[player].controller) { - numRequiredSlots = player + 1; - } - } - return YGS2kConPlayerSlotsResize(numRequiredSlots); -} static SDL_GameControllerType YGS2kGetSDLGameControllerType(SDL_GameController* const controller) { @@ -735,164 +826,170 @@ static SDL_GameControllerType YGS2kGetSDLGameControllerType(SDL_GameController* static void YGS2kConInputsUpdate() { - if (!s_aConPlayerSlots) return; + if (!s_aPlayerSlots) return; - for (int player = 0; player < s_iNumConPlayerSlots; player++) + for (int player = 0; player < s_iNumPlayerSlots; player++) { - if (!SDL_GameControllerGetAttached(s_aConPlayerSlots[player].controller)) continue; + YGS2kSPlayerSlot* const slot = &s_aPlayerSlots[player]; + if (slot->type != YGS_PLAYERSLOT_CON) { + continue; + } + YGS2kSCon* const con = &slot->con; + + if (!SDL_GameControllerGetAttached(con->controller)) continue; - YGS2kEInputType const inputType = YGS2kGetConPlayerType(player); + YGS2kEInputType const inputType = YGS2kGetConType(player); Sint16 axisValue; - axisValue = SDL_GameControllerGetAxis(s_aConPlayerSlots[player].controller, SDL_CONTROLLER_AXIS_LEFTX); + axisValue = SDL_GameControllerGetAxis(con->controller, SDL_CONTROLLER_AXIS_LEFTX); if (axisValue > 0 && axisValue > +YGS_DEADZONE_MAX) { - if (++s_aConPlayerSlots[player].axesRepeat[0] == 1) + if (++con->axesRepeat[0] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } - s_aConPlayerSlots[player].axesRepeat[1] = 0; + con->axesRepeat[1] = 0; } else if (axisValue < 0 && axisValue < -YGS_DEADZONE_MAX) { - s_aConPlayerSlots[player].axesRepeat[0] = 0; - if (++s_aConPlayerSlots[player].axesRepeat[1] == 1) + con->axesRepeat[0] = 0; + if (++con->axesRepeat[1] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].axesRepeat[0] = 0; - s_aConPlayerSlots[player].axesRepeat[1] = 0; + con->axesRepeat[0] = 0; + con->axesRepeat[1] = 0; } - axisValue = SDL_GameControllerGetAxis(s_aConPlayerSlots[player].controller, SDL_CONTROLLER_AXIS_LEFTY); + axisValue = SDL_GameControllerGetAxis(con->controller, SDL_CONTROLLER_AXIS_LEFTY); if (axisValue > 0 && axisValue > +YGS_DEADZONE_MAX) { - if (++s_aConPlayerSlots[player].axesRepeat[2] == 1) + if (++con->axesRepeat[2] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } - s_aConPlayerSlots[player].axesRepeat[3] = 0; + con->axesRepeat[3] = 0; } else if (axisValue < 0 && axisValue < -YGS_DEADZONE_MAX) { - s_aConPlayerSlots[player].axesRepeat[2] = 0; - if (++s_aConPlayerSlots[player].axesRepeat[3] == 1) + con->axesRepeat[2] = 0; + if (++con->axesRepeat[3] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].axesRepeat[2] = 0; - s_aConPlayerSlots[player].axesRepeat[3] = 0; + con->axesRepeat[2] = 0; + con->axesRepeat[3] = 0; } - axisValue = SDL_GameControllerGetAxis(s_aConPlayerSlots[player].controller, SDL_CONTROLLER_AXIS_RIGHTX); + axisValue = SDL_GameControllerGetAxis(con->controller, SDL_CONTROLLER_AXIS_RIGHTX); if (axisValue > 0 && axisValue > +YGS_DEADZONE_MAX) { - if (++s_aConPlayerSlots[player].axesRepeat[4] == 1) + if (++con->axesRepeat[4] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } - s_aConPlayerSlots[player].axesRepeat[5] = 0; + con->axesRepeat[5] = 0; } else if (axisValue < 0 && axisValue < -YGS_DEADZONE_MAX) { - s_aConPlayerSlots[player].axesRepeat[4] = 0; - if (++s_aConPlayerSlots[player].axesRepeat[5] == 1) + con->axesRepeat[4] = 0; + if (++con->axesRepeat[5] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].axesRepeat[4] = 0; - s_aConPlayerSlots[player].axesRepeat[5] = 0; + con->axesRepeat[4] = 0; + con->axesRepeat[5] = 0; } - axisValue = SDL_GameControllerGetAxis(s_aConPlayerSlots[player].controller, SDL_CONTROLLER_AXIS_RIGHTY); + axisValue = SDL_GameControllerGetAxis(con->controller, SDL_CONTROLLER_AXIS_RIGHTY); if (axisValue > 0 && axisValue > +YGS_DEADZONE_MAX) { - if (++s_aConPlayerSlots[player].axesRepeat[6] == 1) + if (++con->axesRepeat[6] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } - s_aConPlayerSlots[player].axesRepeat[7] = 0; + con->axesRepeat[7] = 0; } else if (axisValue < 0 && axisValue < -YGS_DEADZONE_MAX) { - s_aConPlayerSlots[player].axesRepeat[6] = 0; - if (++s_aConPlayerSlots[player].axesRepeat[7] == 1) + con->axesRepeat[6] = 0; + if (++con->axesRepeat[7] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].axesRepeat[6] = 0; - s_aConPlayerSlots[player].axesRepeat[7] = 0; + con->axesRepeat[6] = 0; + con->axesRepeat[7] = 0; } - axisValue = SDL_GameControllerGetAxis(s_aConPlayerSlots[player].controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT); + axisValue = SDL_GameControllerGetAxis(con->controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT); if (axisValue > YGS_DEADZONE_MAX) { - if (++s_aConPlayerSlots[player].axesRepeat[8] == 1) + if (++con->axesRepeat[8] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].axesRepeat[8] = 0; + con->axesRepeat[8] = 0; } - axisValue = SDL_GameControllerGetAxis(s_aConPlayerSlots[player].controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); + axisValue = SDL_GameControllerGetAxis(con->controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); if (axisValue > YGS_DEADZONE_MAX) { - if (++s_aConPlayerSlots[player].axesRepeat[9] == 1) + if (++con->axesRepeat[9] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].axesRepeat[9] = 0; + con->axesRepeat[9] = 0; } for (SDL_GameControllerButton button = 0; button < SDL_CONTROLLER_BUTTON_MAX; button++) { - if (SDL_GameControllerGetButton(s_aConPlayerSlots[player].controller, button)) + if (SDL_GameControllerGetButton(con->controller, button)) { - if (++s_aConPlayerSlots[player].buttonsRepeat[button] == 1) + if (++con->buttonsRepeat[button] == 1) { YGS2kLastInputType = inputType; - s_iLastActiveConPlayer = player; + s_iLastActiveCon = player; } } else { - s_aConPlayerSlots[player].buttonsRepeat[button] = 0; + con->buttonsRepeat[button] = 0; } } } } -bool YGS2kIsPushConPlayerKey ( const int player, const YGS2kSConKey* const key ) +bool YGS2kIsPushConKey ( const int player, const YGS2kSConKey* const key ) { - if (!s_aConPlayerSlots || s_iNumConPlayerSlots == 0 || player >= s_iNumConPlayerSlots || !s_aConPlayerSlots[player].controller || !key) return false; + if (!key || !s_aPlayerSlots || s_iNumPlayerSlots == 0 || player >= s_iNumPlayerSlots) return false; int playerStart = 0; int playerMax = 0; @@ -904,32 +1001,39 @@ bool YGS2kIsPushConPlayerKey ( const int player, const YGS2kSConKey* const key ) else { playerStart = 0; - playerMax = s_iNumConPlayerSlots; + playerMax = s_iNumPlayerSlots; } for (; playerStart < playerMax; playerStart++) { + if (s_aPlayerSlots[playerStart].type != YGS_PLAYERSLOT_CON) + { + continue; + } + + YGS2kSCon* const con = &s_aPlayerSlots[playerStart].con; + switch (key->type) { case YGS_CONKEY_ANY: for (int axis = 0; axis < YGS_CONAXIS_MAX; axis++) { - if (s_aConPlayerSlots[playerStart].axesRepeat[axis] == 1) return true; + if (con->axesRepeat[axis] == 1) return true; } for (int button = 0; button < YGS_CONBUTTON_MAX; button++) { - if (s_aConPlayerSlots[playerStart].buttonsRepeat[button] == 1) return true; + if (con->buttonsRepeat[button] == 1) return true; } break; case YGS_CONKEY_AXIS: if (key->index < YGS_CONAXIS_MAX) { - if (s_aConPlayerSlots[playerStart].axesRepeat[key->index] == 1) return true; + if (con->axesRepeat[key->index] == 1) return true; } break; case YGS_CONKEY_BUTTON: if (key->index < YGS_CONBUTTON_MAX) { - if (s_aConPlayerSlots[playerStart].buttonsRepeat[key->index] == 1) return true; + if (con->buttonsRepeat[key->index] == 1) return true; } break; default: @@ -939,9 +1043,9 @@ bool YGS2kIsPushConPlayerKey ( const int player, const YGS2kSConKey* const key ) return false; } -bool YGS2kIsPressConPlayerKey ( const int player, const YGS2kSConKey* const key ) +bool YGS2kIsPressConKey ( const int player, const YGS2kSConKey* const key ) { - if (!s_aConPlayerSlots || s_iNumConPlayerSlots == 0 || player >= s_iNumConPlayerSlots || !s_aConPlayerSlots[player].controller || !key) return false; + if (!key || !s_aPlayerSlots || s_iNumPlayerSlots == 0 || player >= s_iNumPlayerSlots) return false; int playerStart = 0; int playerMax = 0; @@ -953,32 +1057,39 @@ bool YGS2kIsPressConPlayerKey ( const int player, const YGS2kSConKey* const key else { playerStart = 0; - playerMax = s_iNumConPlayerSlots; + playerMax = s_iNumPlayerSlots; } for (; playerStart < playerMax; playerStart++) { + if (s_aPlayerSlots[playerStart].type != YGS_PLAYERSLOT_CON) + { + continue; + } + + YGS2kSCon* const con = &s_aPlayerSlots[playerStart].con; + switch (key->type) { case YGS_CONKEY_ANY: for (int axis = 0; axis < YGS_CONAXIS_MAX; axis++) { - if (s_aConPlayerSlots[playerStart].axesRepeat[axis] != 0) return true; + if (con->axesRepeat[axis] != 0) return true; } for (int button = 0; button < YGS_CONBUTTON_MAX; button++) { - if (s_aConPlayerSlots[playerStart].buttonsRepeat[button] != 0) return true; + if (con->buttonsRepeat[button] != 0) return true; } break; case YGS_CONKEY_AXIS: if (key->index < YGS_CONAXIS_MAX) { - if (s_aConPlayerSlots[playerStart].axesRepeat[key->index] != 0) return true; + if (con->axesRepeat[key->index] != 0) return true; } break; case YGS_CONKEY_BUTTON: if (key->index < YGS_CONBUTTON_MAX) { - if (s_aConPlayerSlots[playerStart].buttonsRepeat[key->index] != 0) return true; + if (con->buttonsRepeat[key->index] != 0) return true; } break; default: @@ -988,9 +1099,9 @@ bool YGS2kIsPressConPlayerKey ( const int player, const YGS2kSConKey* const key return false; } -int YGS2kGetConPlayerKeyRepeat ( const int player, YGS2kSConKey* const key ) +int YGS2kGetConKeyRepeat ( const int player, YGS2kSConKey* const key ) { - if (!s_aConPlayerSlots || s_iNumConPlayerSlots == 0 || player >= s_iNumConPlayerSlots || !s_aConPlayerSlots[player].controller || !key) return 0; + if (!key || !s_aPlayerSlots || s_iNumPlayerSlots == 0 || player >= s_iNumPlayerSlots) return 0; bool multi; int playerStart = 0; @@ -1005,21 +1116,28 @@ int YGS2kGetConPlayerKeyRepeat ( const int player, YGS2kSConKey* const key ) else { playerStart = 0; - playerMax = s_iNumConPlayerSlots; + playerMax = s_iNumPlayerSlots; multi = true; } for (; playerStart < playerMax; playerStart++) { + if (s_aPlayerSlots[playerStart].type != YGS_PLAYERSLOT_CON) + { + continue; + } + + YGS2kSCon* const con = &s_aPlayerSlots[playerStart].con; + switch (key->type) { case YGS_CONKEY_ANY: for (int axis = 0; axis < YGS_CONAXIS_MAX; axis++) { - if (s_aConPlayerSlots[playerStart].axesRepeat[axis] > maxRepeat) maxRepeat = s_aConPlayerSlots[playerStart].axesRepeat[axis]; + if (con->axesRepeat[axis] > maxRepeat) maxRepeat = con->axesRepeat[axis]; } for (int button = 0; button < YGS_CONBUTTON_MAX; button++) { - if (s_aConPlayerSlots[playerStart].buttonsRepeat[button] > maxRepeat) maxRepeat = s_aConPlayerSlots[playerStart].buttonsRepeat[button]; + if (con->buttonsRepeat[button] > maxRepeat) maxRepeat = con->buttonsRepeat[button]; } break; case YGS_CONKEY_AXIS: @@ -1027,9 +1145,9 @@ int YGS2kGetConPlayerKeyRepeat ( const int player, YGS2kSConKey* const key ) { if (multi) { - if (s_aConPlayerSlots[playerStart].axesRepeat[key->index] > maxRepeat) maxRepeat = s_aConPlayerSlots[playerStart].axesRepeat[key->index]; + if (con->axesRepeat[key->index] > maxRepeat) maxRepeat = con->axesRepeat[key->index]; } - else return s_aConPlayerSlots[playerStart].axesRepeat[key->index]; + else return con->axesRepeat[key->index]; } break; case YGS_CONKEY_BUTTON: @@ -1037,9 +1155,9 @@ int YGS2kGetConPlayerKeyRepeat ( const int player, YGS2kSConKey* const key ) { if (multi) { - if (s_aConPlayerSlots[playerStart].buttonsRepeat[key->index] > maxRepeat) maxRepeat = s_aConPlayerSlots[playerStart].buttonsRepeat[key->index]; + if (con->buttonsRepeat[key->index] > maxRepeat) maxRepeat = con->buttonsRepeat[key->index]; } - else return s_aConPlayerSlots[playerStart].buttonsRepeat[key->index]; + else return con->buttonsRepeat[key->index]; } break; default: @@ -1049,61 +1167,109 @@ int YGS2kGetConPlayerKeyRepeat ( const int player, YGS2kSConKey* const key ) return maxRepeat; } -void YGS2kResetLastActiveConPlayer() +int YGS2kGetNumCons() { - s_iLastActiveConPlayer = -1; + int foundCons; + for (int player = 0; player < s_iNumPlayerSlots; player++) { + if (s_aPlayerSlots[player].type == YGS_PLAYERSLOT_CON) { + foundCons++; + } + } + return foundCons; } -int YGS2kGetLastActiveConPlayer() +void YGS2kResetLastActiveCon() { - return s_iLastActiveConPlayer; + s_iLastActiveCon = -1; } -int YGS2kGetNumConPlayers() +int YGS2kGetLastActiveCon() { - return s_iNumConPlayerSlots; + return s_iLastActiveCon; } -YGS2kEInputType YGS2kGetConPlayerType(const int player) +/* + * Controller type constants were introduced in SDL 2.0.12, with later versions + * introducing more. + * + * SDL 2.0.12: + * SDL_CONTROLLER_TYPE_UNKNOWN + * SDL_CONTROLLER_TYPE_XBOX360 + * SDL_CONTROLLER_TYPE_XBOXONE + * SDL_CONTROLLER_TYPE_PS3 + * SDL_CONTROLLER_TYPE_PS4 + * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO + * + * SDL 2.0.14: + * SDL_CONTROLLER_TYPE_VIRTUAL + * SDL_CONTROLLER_TYPE_PS5 + * + * SDL 2.0.16: + * SDL_CONTROLLER_TYPE_AMAZON_LUNA + * SDL_CONTROLLER_TYPE_GOOGLE_STADIA + * + * SDL 2.24.0: + * SDL_CONTROLLER_TYPE_NVIDIA_SHIELD + * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT + * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT + * SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR + */ +YGS2kEInputType YGS2kGetConType(const int player) { - if (!s_aConPlayerSlots || s_iNumConPlayerSlots == 0 || player < 0 || player >= s_iNumConPlayerSlots || !s_aConPlayerSlots[player].controller) return YGS_INPUT_NULL; + if (!s_aPlayerSlots || s_iNumPlayerSlots == 0 || player < 0 || player >= s_iNumPlayerSlots || s_aPlayerSlots[player].type != YGS_PLAYERSLOT_CON) return YGS_INPUT_NULL; #ifdef ONLY_INPUT_TYPE return ONLY_INPUT_TYPE; #else - switch(YGS2kGetSDLGameControllerType(s_aConPlayerSlots[player].controller)) + switch(YGS2kGetSDLGameControllerType(s_aPlayerSlots[player].con.controller)) { default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: - case SDL_CONTROLLER_TYPE_VIRTUAL: - case SDL_CONTROLLER_TYPE_AMAZON_LUNA: - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: - case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: return YGS_INPUT_XBOX; case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: - case SDL_CONTROLLER_TYPE_PS5: return YGS_INPUT_PLAYSTATION; case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + return YGS_INPUT_NINTENDO; + + #if SDL_VERSION_ATLEAST(2, 0, 14) + case SDL_CONTROLLER_TYPE_VIRTUAL: + return YGS_INPUT_XBOX; + + case SDL_CONTROLLER_TYPE_PS5: + return YGS_INPUT_PLAYSTATION; + #endif + + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + return YGS_INPUT_XBOX; + #endif + + #if SDL_VERSION_ATLEAST(2, 24, 0) + case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + return YGS_INPUT_XBOX; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: return YGS_INPUT_NINTENDO; + #endif } #endif } -bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, const char** text, EButton* button) +bool YGS2kGetConKeyDesc(const int player, const YGS2kSConKey* const key, const char** text, EButton* button) { if ( - !s_aConPlayerSlots || - s_iNumConPlayerSlots == 0 || + !s_aPlayerSlots || + s_iNumPlayerSlots == 0 || player < 0 || - player >= s_iNumConPlayerSlots || - !s_aConPlayerSlots[player].controller || + player >= s_iNumPlayerSlots || + s_aPlayerSlots[player].type != YGS_PLAYERSLOT_CON || !key || !text || !button @@ -1113,7 +1279,7 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c *text = NULL; *button = BTN_NULL; - const SDL_GameControllerType sdlGameControllerType = YGS2kGetSDLGameControllerType(s_aConPlayerSlots[player].controller); + const SDL_GameControllerType sdlGameControllerType = YGS2kGetSDLGameControllerType(s_aPlayerSlots[player].con.controller); switch (key->type) { case YGS_CONKEY_AXIS: @@ -1157,28 +1323,42 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + #endif *text = "LT"; break; - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif *text = "L2"; break; case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "ZL"; break; + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: *text = "SL"; break; + #endif } break; case 9: @@ -1187,28 +1367,42 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + #endif *text = "RT"; break; - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif *text = "R2"; break; case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "ZR"; break; + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: *text = "SR"; break; + #endif } break; default: @@ -1222,15 +1416,18 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c case SDL_CONTROLLER_BUTTON_START: // "Start" and "Back" are reserved for "Pause" and "Give Up", and may not be remapped. break; + case SDL_CONTROLLER_BUTTON_GUIDE: *text = "HOME"; break; + case SDL_CONTROLLER_BUTTON_A: case SDL_CONTROLLER_BUTTON_B: case SDL_CONTROLLER_BUTTON_X: case SDL_CONTROLLER_BUTTON_Y: *button = BTN_A + key->index; break; + case SDL_CONTROLLER_BUTTON_DPAD_UP: case SDL_CONTROLLER_BUTTON_DPAD_DOWN: case SDL_CONTROLLER_BUTTON_DPAD_LEFT: @@ -1238,6 +1435,7 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c *text = "DPAD"; *button = BTN_UP + key->index - SDL_CONTROLLER_BUTTON_DPAD_UP; break; + case SDL_CONTROLLER_BUTTON_MISC1: switch(sdlGameControllerType) { @@ -1245,20 +1443,34 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c case SDL_CONTROLLER_TYPE_XBOXONE: *text = "SHARE"; break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "CAPTURE"; break; + + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #if SDL_VERSION_ATLEAST(2, 0, 16) case SDL_CONTROLLER_TYPE_AMAZON_LUNA: case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + #endif *text = "MICROPHONE"; break; + #endif + + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: default: *text = "MISC1"; break; + #endif } break; case SDL_CONTROLLER_BUTTON_PADDLE1: @@ -1282,19 +1494,30 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: - case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "LS"; break; - case SDL_CONTROLLER_TYPE_AMAZON_LUNA: - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif *text = "L3"; break; } @@ -1305,17 +1528,26 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: - case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "RS"; break; - case SDL_CONTROLLER_TYPE_AMAZON_LUNA: - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif *text = "R3"; break; } @@ -1326,19 +1558,33 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + #endif *text = "LB"; break; - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif *text = "L1"; break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 24, 0) + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "L"; break; } @@ -1349,19 +1595,33 @@ bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, c default: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_XBOXONE: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_VIRTUAL: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + #endif + #if SDL_VERSION_ATLEAST(2, 24, 0) case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + #endif *text = "RB"; break; - case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: case SDL_CONTROLLER_TYPE_PS3: case SDL_CONTROLLER_TYPE_PS4: + #if SDL_VERSION_ATLEAST(2, 0, 14) case SDL_CONTROLLER_TYPE_PS5: + #endif + #if SDL_VERSION_ATLEAST(2, 0, 16) + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + #endif *text = "R1"; break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + #if SDL_VERSION_ATLEAST(2, 24, 0) + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + #endif *text = "R"; break; } @@ -1442,15 +1702,8 @@ bool YGS2kInputsOpen() memset(s_iKeyRepeat, 0, sizeof(s_iKeyRepeat)); #endif - /* パッドの初期化 */ - - #ifdef ENABLE_JOYSTICK - if (!YGS2kJoysOpen()) { - return false; - } - #endif - #ifdef ENABLE_GAME_CONTROLLER + /* パッドの初期化 */ OpenGameControllerDB(); SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); #endif @@ -1478,12 +1731,8 @@ void YGS2kInputsClose() memset(s_iKeyRepeat, 0, sizeof(s_iKeyRepeat)); #endif - #ifdef ENABLE_JOYSTICK - YGS2kJoysClose(); - #endif - - #ifdef ENABLE_GAME_CONTROLLER - YGS2kConsClose(); + #if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) + YGS2kPlayerSlotsClose(); #endif } diff --git a/src/main_sdl/ygs2kinput.h b/src/main_sdl/ygs2kinput.h index 19c54da..b7487a2 100644 --- a/src/main_sdl/ygs2kinput.h +++ b/src/main_sdl/ygs2kinput.h @@ -46,6 +46,18 @@ int YGS2kGetKeyRepeat(int key); int YGS2kGetMaxKey(); #endif +#if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) +typedef enum YGS2kEPlayerSlotType +{ + YGS_PLAYERSLOT_NULL, + YGS_PLAYERSLOT_JOY, + YGS_PLAYERSLOT_CON +} YGS2kEPlayerSlotType; + +int YGS2kGetNumPlayerSlots(); +YGS2kEPlayerSlotType YGS2kGetPlayerSlotType(int player); +#endif + #ifdef ENABLE_JOYSTICK typedef struct YGS2kSJoyGUID { int32_t data[4]; @@ -67,7 +79,7 @@ typedef union YGS2kSJoyKeySetting { } YGS2kSJoyKeySetting; typedef struct YGS2kSJoyKey { - int device; + int player; YGS2kSJoyGUID guid; YGS2kEJoyKeyType type; YGS2kSJoyKeySetting setting; @@ -77,19 +89,17 @@ bool YGS2kIsPushJoyKey(const YGS2kSJoyKey* const key); bool YGS2kIsPressJoyKey(const YGS2kSJoyKey* const key); int YGS2kGetJoyKeyRepeat(const YGS2kSJoyKey* const key); // If key->type == YGS_JOYKEY_ANY, checks all inputs of the key's joystick and returns the max repeat value. -int YGS2kGetMaxJoys(); -int YGS2kGetNumJoys(); - -// If game controller support is enabled, a joystick device can possibly +// If game controller support is enabled, a joystick player can possibly // correspond to a game controller, in which case these functions return -1 if -// the joystick device refers to a game controller. Also, YGS2kGetJoyGUID -// returns the zero GUID for a joystick device that's actually a game +// the joystick player refers to a game controller. Also, YGS2kGetJoyGUID +// returns the zero GUID for a joystick player that's actually a game // controller. -YGS2kSJoyGUID YGS2kGetJoyGUID(int device); -int YGS2kGetMaxJoyAxis(int device); -int YGS2kGetMaxJoyHat(int device); -int YGS2kGetMaxJoyButton(int device); +int YGS2kGetNumJoys(); +YGS2kSJoyGUID YGS2kGetJoyGUID(int player); +int YGS2kGetMaxJoyAxis(int player); +int YGS2kGetMaxJoyHat(int player); +int YGS2kGetMaxJoyButton(int player); #endif #ifdef ENABLE_GAME_CONTROLLER @@ -104,7 +114,7 @@ typedef struct YGS2kSConKey { int index; } YGS2kSConKey; - /* Two for each stick, one for each trigger: +/* Two for each stick, one for each trigger: 0,1: Left stick right,left 2,3: Left stick down,up 4,5: Right stick right,left @@ -117,14 +127,13 @@ typedef struct YGS2kSConKey { // Button numbers are the same as the SDL_CONTROLLER_BUTTON_* constants. #define YGS_CONBUTTON_MAX SDL_CONTROLLER_BUTTON_MAX -bool YGS2kIsPushConPlayerKey(const int player, const YGS2kSConKey* const key); -bool YGS2kIsPressConPlayerKey(const int player, const YGS2kSConKey* const key); -int YGS2kGetConPlayerKeyRepeat(const int player, YGS2kSConKey* const key); +bool YGS2kIsPushConKey(const int player, const YGS2kSConKey* const key); +bool YGS2kIsPressConKey(const int player, const YGS2kSConKey* const key); +int YGS2kGetConKeyRepeat(const int player, YGS2kSConKey* const key); -bool YGS2kIsCon(int device); -void YGS2kResetLastActiveConPlayer(); -int YGS2kGetLastActiveConPlayer(); -int YGS2kGetNumConPlayers(); -YGS2kEInputType YGS2kGetConPlayerType(const int player); -bool YGS2kGetConPlayerKeyDesc(const int player, const YGS2kSConKey* const key, const char** text, EButton* button); +int YGS2kGetNumCons(); +void YGS2kResetLastActiveCon(); +int YGS2kGetLastActiveCon(); +YGS2kEInputType YGS2kGetConType(const int player); +bool YGS2kGetConKeyDesc(const int player, const YGS2kSConKey* const key, const char** text, EButton* button); #endif diff --git a/src/main_sdl/ygs2kprivate.h b/src/main_sdl/ygs2kprivate.h index 8081d11..ac936f1 100644 --- a/src/main_sdl/ygs2kprivate.h +++ b/src/main_sdl/ygs2kprivate.h @@ -14,18 +14,8 @@ extern YGS2kEInputType YGS2kLastInputType; -#ifdef ENABLE_JOYSTICK -// TODO: Replace YGS2kJoysClose() + YGS2kJoysOpen() with YGS2kJoysChanged() and -// make joysticks use player indices instead of device indices, like -// controllers - -void YGS2kJoysClose(); -bool YGS2kJoysOpen(); -#endif - -#ifdef ENABLE_GAME_CONTROLLER -void YGS2kConsClose(); -bool YGS2kConsChanged(); +#if defined(ENABLE_JOYSTICK) || defined(ENABLE_GAME_CONTROLLER) +bool YGS2kPlayerSlotsChanged(); #endif bool YGS2kInputsOpen(); diff --git a/src/script/config.c b/src/script/config.c index 3b07239..7350a7d 100644 --- a/src/script/config.c +++ b/src/script/config.c @@ -138,7 +138,7 @@ int32_t SaveConfig(void) { for (int32_t key = 0; key < 10; key++) { int32_t *plbuf = &joykeybuf[pl * 10 * 8 + key * 8]; YGS2kSJoyKey *pljoy = &joyKeyAssign[pl * 10 + key]; - plbuf[0] = pljoy->device; + plbuf[0] = pljoy->player; for (int32_t i = 0; i < 4; i++) { plbuf[1 + i] = pljoy->guid.data[i]; } @@ -314,7 +314,7 @@ int32_t LoadConfig(void) { for (int32_t key = 0; key < 10; key++) { YGS2kSJoyKey *pljoy = &joyKeyAssign[pl * 10 + key]; int32_t *plbuf = &joykeybuf[pl * 10 * 8 + key * 8]; - pljoy->device = plbuf[0]; + pljoy->player = plbuf[0]; for (int32_t i = 0; i < 4; i++) { pljoy->guid.data[i] = plbuf[1 + i]; } @@ -473,7 +473,7 @@ void ConfigMenu() { for (int32_t pl = 0; pl < 2; pl++) { int32_t *plbuf = &joykeybuf[pl * 10 * 8]; YGS2kSJoyKey *pljoy = &joyKeyAssign[pl * 10]; - plbuf[0] = pljoy->device; + plbuf[0] = pljoy->player; for (int32_t i = 0; i < 4; i++) { plbuf[1 + i] = pljoy->guid.data[i]; } @@ -1525,13 +1525,13 @@ void ConfigMenu() { for(i = 0; i < statusc[0]; i++) { switch((YGS2kEJoyKeyType)ncfg[j+5+i*8]) { case YGS_JOYKEY_AXIS: - sprintf(string[0], "J%d:A%d%c", (int)ncfg[j+0+i*8], (int)ncfg[j+6+i*8], ncfg[j+7+i*8] >= 0 ? '+' : '-'); + sprintf(string[0], "JOY%dP:A%d%c", (int)ncfg[j+0+i*8] + 1, (int)ncfg[j+6+i*8], ncfg[j+7+i*8] >= 0 ? '+' : '-'); break; case YGS_JOYKEY_HAT: - sprintf(string[0], "J%d:H%d,%d", (int)ncfg[j+0+i*8], (int)ncfg[j+6+i*8], (int)ncfg[j+7+i*8]); + sprintf(string[0], "JOY%dP:H%d,%d", (int)ncfg[j+0+i*8] + 1, (int)ncfg[j+6+i*8], (int)ncfg[j+7+i*8]); break; case YGS_JOYKEY_BUTTON: - sprintf(string[0], "J%d:B%d", (int)ncfg[j+0+i*8], (int)ncfg[j+6+i*8]); + sprintf(string[0], "JOY%dP:B%d", (int)ncfg[j+0+i*8] + 1, (int)ncfg[j+6+i*8]); break; default: sprintf(string[0], "???"); @@ -1544,9 +1544,13 @@ void ConfigMenu() { printFont(10, 6 + statusc[0], "_", digitc[rots[0]] * (count % 2)); YGS2kSJoyKey pushKey; bool pushed = false; - for (int32_t i = 0; i < YGS2kGetMaxJoys(); i++) + for (int32_t i = 0; i < YGS2kGetNumPlayerSlots(); i++) { - pushKey.device = i; + if (YGS2kGetPlayerSlotType(i) != YGS_PLAYERSLOT_JOY) { + continue; + } + + pushKey.player = i; pushKey.guid = YGS2kGetJoyGUID(i); pushKey.type = YGS_JOYKEY_AXIS; @@ -1618,7 +1622,7 @@ void ConfigMenu() { bool unmapped = true; for (EButton button = 0; button < statusc[0]; button++) { if ( - ncfg[j+0+button*8] == pushKey.device && + ncfg[j+0+button*8] == pushKey.player && memcmp(&ncfg[j+1+button*8], pushKey.guid.data, sizeof(int32_t) * 4) == 0 && ncfg[j+5+button*8] == pushKey.type ) { @@ -1638,7 +1642,7 @@ void ConfigMenu() { } if (unmapped) { PlaySE(5); - ncfg[j+0+statusc[0]*8] = pushKey.device; + ncfg[j+0+statusc[0]*8] = pushKey.player; for (int32_t i = 0; i < 4; i++) { ncfg[j+1+i+statusc[0]*8] = pushKey.guid.data[i]; } @@ -1668,7 +1672,7 @@ void ConfigMenu() { for (EButton button = 0; button < NUMBTNS; button++) { YGS2kSJoyKey *pljoy = &joyKeyAssign[pl * 10 + button]; int32_t *plcfg = &ncfg[80 + pl * 10 * 8 + button * 8]; - pljoy->device = plcfg[0]; + pljoy->player = plcfg[0]; for (int32_t i = 0; i < 4; i++) { pljoy->guid.data[i] = plcfg[1 + i]; } @@ -1696,7 +1700,7 @@ void ConfigMenu() { for (EButton button = 0; button < NUMBTNS; button++) { int32_t *plcfg = &ncfg[80 + pl * 10 * 8 + button * 8]; YGS2kSJoyKey *pljoy = &joyKeyAssign[pl * 10 + button]; - plcfg[0] = pljoy->device; + plcfg[0] = pljoy->player; for (int32_t i = 0; i < 4; i++) { plcfg[1 + i] = pljoy->guid.data[i]; } @@ -1722,7 +1726,7 @@ void ConfigMenu() { for (EButton button = 0; button < 10; button++) { int32_t *plcfg = &ncfg[80 + pl * 10 * 8 + button * 8]; YGS2kSJoyKey *pljoy = &joyKeyAssign[pl * 10 + button]; - plcfg[0] = pljoy->device; + plcfg[0] = pljoy->player; for (int32_t i = 0; i < 4; i++) { plcfg[1 + i] = pljoy->guid.data[i]; } @@ -1752,7 +1756,7 @@ void ConfigMenu() { #ifdef ENABLE_GAME_CONTROLLER else if(optionIndex += 2, (statusc[2] == optionIndex - 2) || (statusc[2] == optionIndex - 1)) { // game controller setting - if (YGS2kGetNumConPlayers() <= 0) { + if (YGS2kGetNumCons() <= 0) { statusc[0] = 0; statusc[2] = 0; } @@ -1766,7 +1770,7 @@ void ConfigMenu() { case YGS_INPUT_XBOX: case YGS_INPUT_PLAYSTATION: case YGS_INPUT_NINTENDO: - if (YGS2kIsPushConPlayerKey(-1, &cancelKey)) { + if (YGS2kIsPushConKey(-1, &cancelKey)) { PlaySE(5); statusc[0] = 0; statusc[2] = 0; @@ -1825,11 +1829,11 @@ void ConfigMenu() { YGS2kSConKey key; int lastConPlayer = -1; key.type = YGS_CONKEY_ANY; - if (conPlayer == -1 && !YGS2kIsPressConPlayerKey(-1, &key)) { - YGS2kResetLastActiveConPlayer(); + if (conPlayer == -1 && !YGS2kIsPressConKey(-1, &key)) { + YGS2kResetLastActiveCon(); conPlayer = -2; } - else if (conPlayer == -2 && (lastConPlayer = YGS2kGetLastActiveConPlayer()) >= 0) { + else if (conPlayer == -2 && (lastConPlayer = YGS2kGetLastActiveCon()) >= 0) { conPlayer = lastConPlayer; ncfg[240 + pl * (1 + 2 * 8)] = conPlayer; } @@ -1852,7 +1856,7 @@ void ConfigMenu() { pushKey.type = YGS_CONKEY_BUTTON; for (pushKey.index = 0; pushKey.index < YGS_CONBUTTON_MAX; pushKey.index++) { - if (YGS2kIsPushConPlayerKey(conPlayer, &pushKey)) { + if (YGS2kIsPushConKey(conPlayer, &pushKey)) { pushed = true; break; } @@ -1861,7 +1865,7 @@ void ConfigMenu() { if (!pushed) { pushKey.type = YGS_CONKEY_AXIS; for (pushKey.index = 0; pushKey.index < YGS_CONAXIS_MAX; pushKey.index++) { - if (YGS2kIsPushConPlayerKey(conPlayer, &pushKey)) { + if (YGS2kIsPushConKey(conPlayer, &pushKey)) { pushed = true; break; } @@ -1945,7 +1949,7 @@ void ConfigMenu() { || YGS2kIsPressJoyKey(&joyKeyAssign[i + 10 * pl]) // キー入力状態取得 #endif #ifdef ENABLE_GAME_CONTROLLER - || YGS2kIsPressConPlayerKey(playerCons[pl], &conKeyAssign[i + 8 * pl]) + || YGS2kIsPressConKey(playerCons[pl], &conKeyAssign[i + 8 * pl]) #endif ; if(j) sprintf(string[0],"d"); @@ -1995,35 +1999,32 @@ void ConfigMenu() { #ifdef ENABLE_JOYSTICK YGS2kSJoyKey* const key = &joyKeyAssign[i + pl * 10]; - YGS2kSJoyGUID getGUID = YGS2kGetJoyGUID(key->device); + YGS2kSJoyGUID getGUID = YGS2kGetJoyGUID(key->player); YGS2kSJoyGUID zeroGUID = { 0 }; if ( - YGS2kGetNumJoys() > 0 && key->device < YGS2kGetMaxJoys() && - #ifdef ENABLE_GAME_CONTROLLER - !YGS2kIsCon(key->device) && - #endif + YGS2kGetPlayerSlotType(key->player) == YGS_PLAYERSLOT_JOY && memcmp(key->guid.data, zeroGUID.data, sizeof(key->guid.data)) != 0 && memcmp(getGUID.data, zeroGUID.data, sizeof(getGUID.data)) != 0 && memcmp(key->guid.data, getGUID.data, sizeof(key->guid.data)) == 0 ) { switch(key->type) { case YGS_JOYKEY_AXIS: - sprintf(string[1], " J%d:A%d%c", - key->device, + sprintf(string[1], " JOY%dP:A%d%c", + key->player + 1, key->setting.index, key->setting.value >= 0 ? '+' : '-' ); break; case YGS_JOYKEY_HAT: - sprintf(string[1], " J%d:H%d,%d", - key->device, + sprintf(string[1], " JOY%dP:H%d,%d", + key->player + 1, key->setting.index, key->setting.value ); break; case YGS_JOYKEY_BUTTON: - sprintf(string[1], " J%d:B%d", - key->device, + sprintf(string[1], " JOY%dP:B%d", + key->player + 1, key->setting.button ); break; @@ -2040,7 +2041,7 @@ void ConfigMenu() { #ifdef ENABLE_GAME_CONTROLLER YGS2kSConKey conKey = conKeyAssign[i + pl * 8]; - if (YGS2kGetConPlayerType(playerCons[pl]) != YGS_INPUT_NULL && (conKey.type == YGS_CONKEY_AXIS || conKey.type == YGS_CONKEY_BUTTON)) { + if (YGS2kGetPlayerSlotType(playerCons[pl]) == YGS_PLAYERSLOT_CON && (conKey.type == YGS_CONKEY_AXIS || conKey.type == YGS_CONKEY_BUTTON)) { if (string[0][0] != '\0') printFont(5, 7 + i + pl * 10, string[0], 0); sprintf(string[1], " CON%" PRId32 "P:", playerCons[pl] + 1); int32_t x = 5 + strlen(string[0]); diff --git a/src/script/setdef.c b/src/script/setdef.c index 5bee16c..e7c135f 100644 --- a/src/script/setdef.c +++ b/src/script/setdef.c @@ -402,7 +402,7 @@ void SetDefaultConfig() for (int32_t key = 0; key < 10; key++) { int32_t *plbuf = &joykeybuf[pl * 10 * 8 + key * 8]; const YGS2kSJoyKey *pljoy = &DefaultConfig.joyKeyAssign[pl * 10 + key]; - plbuf[0] = pljoy->device; + plbuf[0] = pljoy->player; for (int32_t i = 0; i < 4; i++) { plbuf[1 + i] = pljoy->guid.data[i]; } diff --git a/src/script/view.c b/src/script/view.c index 40f48c3..7c2aa17 100644 --- a/src/script/view.c +++ b/src/script/view.c @@ -2111,18 +2111,18 @@ void printMenuButton(int32_t fontX, int32_t fontY, EButton button, int32_t playe #ifdef ENABLE_GAME_CONTROLLER void printConKey(int32_t fontX, int32_t fontY, int32_t conPlayer, YGS2kSConKey* key, int32_t fontColor) { - if (YGS2kGetNumConPlayers() <= 0 || conPlayer < 0 || conPlayer >= YGS2kGetNumConPlayers() || key == NULL) return; + if (conPlayer < 0 || conPlayer >= YGS2kGetNumPlayerSlots() || !key) return; const char* text; EButton button; - if (YGS2kGetConPlayerKeyDesc(conPlayer, key, &text, &button)) { + if (YGS2kGetConKeyDesc(conPlayer, key, &text, &button)) { if (text != NULL) { printFont(fontX, fontY, text, fontColor); if (button != BTN_NULL) { - ExBltRect(23, (fontX + strlen(text)) * 8, fontY * 8, button * 8, (YGS2kGetConPlayerType(conPlayer) - YGS_INPUT_FIRSTGAMECONTROLLERTYPE + 1) * 8, 8, 8); + ExBltRect(23, (fontX + strlen(text)) * 8, fontY * 8, button * 8, (YGS2kGetConType(conPlayer) - YGS_INPUT_FIRSTGAMECONTROLLERTYPE + 1) * 8, 8, 8); } } else if (button != BTN_NULL) { - ExBltRect(23, fontX * 8, fontY * 8, button * 8, (YGS2kGetConPlayerType(conPlayer) - YGS_INPUT_FIRSTGAMECONTROLLERTYPE + 1) * 8, 8, 8); + ExBltRect(23, fontX * 8, fontY * 8, button * 8, (YGS2kGetConType(conPlayer) - YGS_INPUT_FIRSTGAMECONTROLLERTYPE + 1) * 8, 8, 8); } } }