diff --git a/include/config/config_rom.h b/include/config/config_rom.h index 6ba7df52d..02101667c 100644 --- a/include/config/config_rom.h +++ b/include/config/config_rom.h @@ -29,6 +29,11 @@ */ #define MAX_NUM_PLAYERS 1 +/** + * Allows the player to use a button combo (defined in game_input.h) to toggle the ability to plug/unplug controllers and change the controller order. + */ +#define ALLOW_STATUS_REPOLLING_COMBO + /** * Informs supported emulators to default to GameCube controller inputs. */ diff --git a/src/game/area.c b/src/game/area.c index e53ea475d..6e092df5a 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -361,7 +361,8 @@ void play_transition_after_delay(s16 transType, s16 time, u8 red, u8 green, u8 b play_transition(transType, time, red, green, blue); } -#if (MAX_NUM_PLAYERS > 1) +#ifdef ALLOW_STATUS_REPOLLING_COMBO + #if (MAX_NUM_PLAYERS > 1) ALIGNED8 static const char* sN64ButtonNames[16] = { "A", // A_BUTTON "B", // B_BUTTON @@ -401,7 +402,7 @@ static size_t button_combo_to_string(char* strp, u16 buttons) { return count; } -#endif + #endif // (MAX_NUM_PLAYERS > 1) ALIGNED8 static const struct ControllerIcon sControllerIcons[] = { { .type = CONT_NONE, .texture = texture_controller_port }, @@ -511,13 +512,13 @@ void render_controllers_overlay(void) { if (gContStatusPollingReadyForInput) { sprintf(text_buffer, "PRESS BUTTON TO ASSIGN P%d", (gNumPlayers + 1)); drawSmallStringCol(&dlHead, (SCREEN_CENTER_X - 77), (SCREEN_CENTER_Y - 28), text_buffer, col, col, col); -#if (MAX_NUM_PLAYERS > 1) + #if (MAX_NUM_PLAYERS > 1) char comboStr[32] = ""; size_t count = button_combo_to_string(comboStr, TOGGLE_CONT_STATUS_POLLING_COMBO); sprintf(text_buffer, "OR %s TO EXIT", comboStr); s32 xOffset = ((strlen("ORTOEXIT") + 1 + count) / 2) * 7; // Center the text based on char count. drawSmallStringCol(&dlHead, (SCREEN_CENTER_X - xOffset), (SCREEN_CENTER_Y + 28), text_buffer, col, col, col); -#endif + #endif // (MAX_NUM_PLAYERS > 1) } else { drawSmallStringCol(&dlHead, (SCREEN_CENTER_X - 84), (SCREEN_CENTER_Y - 28), "RELEASE ALL INPUTS TO START", col, col, col); } @@ -540,6 +541,7 @@ void render_controllers_overlay(void) { gDisplayListHead = dlHead; } +#endif // ALLOW_STATUS_REPOLLING_COMBO void render_game(void) { if (gCurrentArea != NULL && !gWarpTransition.pauseRendering) { @@ -598,7 +600,9 @@ void render_game(void) { gViewportOverride = NULL; gViewportClip = NULL; +#ifdef ALLOW_STATUS_REPOLLING_COMBO render_controllers_overlay(); +#endif profiler_update(PROFILER_TIME_GFX); profiler_print_times(); diff --git a/src/game/game_input.c b/src/game/game_input.c index 01045abd7..b7af6b27f 100644 --- a/src/game/game_input.c +++ b/src/game/game_input.c @@ -23,12 +23,12 @@ struct Controller* const gPlayer4Controller = &gControllers[3]; OSContStatus gControllerStatuses[MAXCONTROLLERS]; OSContPadEx gControllerPads[MAXCONTROLLERS]; -u8 gNumPlayers = 0; -u8 gControllerBits = 0b0000; // Which ports have a controller connected to them. -u8 gContStatusPolling = FALSE; -u8 gContStatusPollingIsBootMode = FALSE; -u8 gContStatusPollingReadyForInput = TRUE; -u32 gContStatusPollTimer = 0; +u8 gNumPlayers = 0; // The number of controllers currently assigned to a player. +u8 gControllerBits = 0b0000; // Which ports have a controller connected to them (low to high). +u8 gContStatusPolling = FALSE; // Whether controller status polling is enabled. +u8 gContStatusPollingIsBootMode = FALSE; // Whether controller status polling was triggered on boot and should be invisible. +u8 gContStatusPollingReadyForInput = TRUE; // Whether all inputs have been released after starting status repolling. +u32 gContStatusPollTimer = 0; // Time since controller status repolling has started. // Title Screen Demo Handler struct DemoInput* gCurrDemoInput = NULL; @@ -202,6 +202,9 @@ static void poll_controller_statuses(OSMesg* mesg) { * invisible and the controller with the first detected input (including analog sticks) becomes player 1. */ void start_controller_status_polling(s32 isBootMode) { + if (isBootMode) { + gContStatusPollingReadyForInput = TRUE; + } gContStatusPollingIsBootMode = isBootMode; gContStatusPolling = TRUE; gContStatusPollTimer = 0; @@ -275,7 +278,7 @@ void read_controller_inputs_status_polling(void) { ) { portInfo->playerNum = ++gNumPlayers; } -#if (MAX_NUM_PLAYERS > 1) +#if (defined(ALLOW_STATUS_REPOLLING_COMBO) && (MAX_NUM_PLAYERS > 1)) u16 pressed = (~portInfo->statusPollButtons & button); // If the combo is pressed, stop polling and assign the current controllers. @@ -366,11 +369,12 @@ void read_controller_inputs_normal(void) { // 0.5x A presses are a good meme controller->buttonDown = button; adjust_analog_stick(controller); - +#ifdef ALLOW_STATUS_REPOLLING_COMBO if (check_button_pressed_combo(controller->buttonDown, controller->buttonPressed, TOGGLE_CONT_STATUS_POLLING_COMBO)) { gContStatusPollingReadyForInput = FALSE; start_controller_status_polling(FALSE); } +#endif } else { // Otherwise, if controllerData is NULL or the cooldown hasn't finished, zero out all of the inputs. controller->rawStickX = 0; diff --git a/src/game/game_input.h b/src/game/game_input.h index 7af06af57..9574c503f 100644 --- a/src/game/game_input.h +++ b/src/game/game_input.h @@ -34,11 +34,11 @@ extern struct Controller* const gPlayer4Controller; extern OSContStatus gControllerStatuses[MAXCONTROLLERS]; extern OSContPadEx gControllerPads[MAXCONTROLLERS]; -extern u8 gNumPlayers; -extern u8 gControllerBits; -extern u8 gContStatusPolling; -extern u8 gContStatusPollingIsBootMode; -extern u8 gContStatusPollingReadyForInput; +extern u8 gNumPlayers; +extern u8 gControllerBits; +extern u8 gContStatusPolling; +extern u8 gContStatusPollingIsBootMode; +extern u8 gContStatusPollingReadyForInput; extern u32 gContStatusPollTimer; extern struct DemoInput* gCurrDemoInput;