Skip to content

Dynamic controller assignment#2958

Open
imsys wants to merge 1 commit into
nesbox:mainfrom
imsys:controllerdetection
Open

Dynamic controller assignment#2958
imsys wants to merge 1 commit into
nesbox:mainfrom
imsys:controllerdetection

Conversation

@imsys

@imsys imsys commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

This was mainly coded by Gemini, I mostly reviewed and tested it.

This fixes #2955. I tested with cart 893, note that this test cart is positioned as:

P1 P3
P2 P4

Before this patch, when I try to play on my PC with a Xbox controller, it is assigned to P3. If I plug another controller, it gets assigned to P4.

With this patch I also ested that:
The first player to that moves or press any button is the 1st player. If I turn it off and on again, it also keeps being the 1st player.

This will probably have a merge conflict with #2952

Following is the comments by Gemini:

Key Changes:

Increased Controller Support: Expanded the internal controller ports from 4 to 16. This ensures that even if you have multiple "ghost" devices or adapters at low SDL indices, your active controller will still be detected and opened.

Assignment by First Use: Introduced a mapping system that tracks the registration order of controllers. A controller is only assigned to a player slot (1-4) once it shows some activity (button press or stick movement).

Active Removal Handling: Corrected the hotplug logic to properly identify which controller is being disconnected using its unique SDL Instance ID, ensuring assigned slots are freed if a controller is unplugged.

Robust Mapping: Initialized all player slots as unassigned at startup. The first controller to send input becomes Player 1, the second becomes Player 2, and so on.

Details:

  • Added SDL_JoystickID mapping[TIC_GAMEPADS] to the platform.gamepad structure.
  • Implemented isControllerActive() to detect button presses or axis movements exceeding a deadzone threshold.
  • Updated processGamepad() to perform a two-phase check: first, mapping unassigned active controllers to available slots; then, reading input from the mapped controllers.
  • Fixed SDL_CONTROLLERDEVICEREMOVED to use Instance IDs instead of indices, which is the correct behavior for this SDL event.

[Gemini] Key Changes:
Increased Controller Support: Expanded the internal controller ports
from 4 to 16. This ensures that even if you have multiple "ghost"
devices or adapters at low SDL indices, your active controller will
still be detected and opened.
Assignment by First Use: Introduced a mapping system that tracks the
registration order of controllers. A controller is only assigned to a
player slot (1-4) once it shows some activity (button press or stick
movement).
Active Removal Handling: Corrected the hotplug logic to properly
identify which controller is being disconnected using its unique SDL
Instance ID, ensuring assigned slots are freed if a controller is
unplugged.
Robust Mapping: Initialized all player slots as unassigned at startup.
The first controller to send input becomes Player 1, the second becomes
Player 2, and so on.

Details:
- Added SDL_JoystickID mapping[TIC_GAMEPADS] to the platform.gamepad
structure.
- Implemented isControllerActive() to detect button presses or axis
movements exceeding a deadzone threshold.
- Updated processGamepad() to perform a two-phase check: first, mapping
unassigned active controllers to available slots; then, reading input
from the mapped controllers.
- Fixed SDL_CONTROLLERDEVICEREMOVED to use Instance IDs instead of
indices, which is the correct behavior for this SDL event.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Player 1 is not necessarily the first controller in use

1 participant