Repository navigation
Mac: DM_PAD_PRESS_TO_JOIN=1, a controller becomes a player at its first button press - #1596
Closed
elieteyssedou wants to merge 5 commits into
Closed
elieteyssedou wants to merge 5 commits into
elieteyssedou wants to merge 5 commits into
Conversation
…says YES a5281d0 skipped every HID pad for which +[GCController supportsHIDDevice:] answers YES. It answers YES for the 8BitDo Ultimate 2C Wireless (2dc8:301b), which GameController then never lists, so the pad got no input from either path (seedds#637 again). The call is now made only for Microsoft, Sony and Nintendo pads, the vendors GameController does list; other vendors are read as HID.
… and is read as HID if it never comes +[GCController supportsHIDDevice:] is only a hint: it answers YES for the 8BitDo Ultimate 2C (2dc8:301b), which GameController then never lists (GitHub issue seedds#965). A device it says YES for now waits HIDPAD_GC_WAIT seconds for a GCController of its name; without one it is read as HID, and dropped again if that GCController connects later. A device it says NO for is read at once, as before. This replaces the Microsoft, Sony and Nintendo vendor list, so a pad of another vendor that GameController does list is not read twice.
# Conflicts: # dm/host/front_mac.m
… are each a player of their own (issue seedds#1218) Two Pro Controllers over USB are listed as one by GameController. When IOKit has at least two pads of a model and more than GameController lists, after a 3 s wait, every pad of that model is read here, by USB location, each a player of its own: - a Switch Pro Controller from its report 0x30 (pad_pro.h), with its gyro, and its sticks from its own calibration in SPI flash (the user's, else the factory's), asked with subcommand 0x10; until it answers, or if it never does, each axis measures its rest and reach itself; - any other model from its HID elements as pad_hid.h reads them: no gyro, 8BitDo's button numbering unless DM_HID_MAP says otherwise. Built on seedds#859: the devices GameController lists are now kept, unread, to count them. GameController gives a controller no HID identity, so its controllers of such a model are left unread rather than read twice. DM_PAD_IDENTICAL=0 turns it off. No rumble or player lights on such pads, and Home does not quit from them. Tests: t_pad_pro (report 0x30, the SPI read, both calibrations), t_pad_hid (when a model is read here). Run: Mario Kart World 1.8.0 on an M4 Pro (macOS 27), 33 min of split-screen races, two Pro Controllers over USB, which GameController lists as one: each was a player of its own, each with its own calibration (one the factory's, one the user's), read over USB and over Bluetooth; two Xbox controllers over Bluetooth, which GameController lists both, joined as players 3 and 4 while the game ran. A duplicate player found in that run (GameController's own Pro Controller also joining) is fixed here; the fix builds and the unit tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st button press The players pick their order whatever the port, the order of connection or the link (Bluetooth has no port), and for identical pads too: each controller is no player until one of its buttons is pressed, then takes the lowest player free. GameController controllers, raw HID pads and identical pads read here alike. Not with DM_PAD_MERGE. Test: t_hid (pad_slot_take_lowest). Run in Mario Kart World with the commit before it (see there): the players chose their order, and two controllers connected while the game ran joined at their first press. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks done
seedds
added a commit
that referenced
this pull request
Nov 7, 2026
… player at its first button press, the lowest player free, on the Mac and on iOS (PR #1596) Players could not choose who is player 1: the order followed GameController's list, and for identical pads read from IOKit, the USB port; Bluetooth has no port. With the setting on, a controller is no player until one of its buttons is pressed, then it takes the lowest free slot (pad_slot_take_lowest, pad_slots.h): GameController controllers, raw HID pads and identical pads alike. The press also reaches the game. Not with DM_PAD_MERGE. Off by default. Beyond the PR: the same rule in the iOS front end (DmGamepad.m; a controller waiting for its press hides the touch gamepad, as a connected one does), and a launcher row (settings.tsv, Controls: Press a button to join) so both launchers offer it. docs/settings.md and playing.md say to press on every controller before the game asks how many play: the controller applet stand-in (ctrl_support, hle_hid.c) cancels when fewer have joined than the game wants. Tests: t_hid (pad_slot_take_lowest); host tests pass; DmGamepad.m compiles for iOS. The PR's version ran in Mario Kart World 1.8.0 on the Mac; the iOS side awaits a device test. Co-authored-by: Elie <8143621+elieteyssedou@users.noreply.github.com>
Owner
|
Landed in 62be7fa, with you credited as co-author. It sits on top of the reworked #1595 (1ed28ed): Added on top:
Not run with controllers yet; the iOS side needs a device test. |
seedds
added a commit
that referenced
this pull request
Nov 7, 2026
…sks for more players than it sees gets a prompt over the game that holds its thread until enough controllers have joined (a first button with Press a button to join, a connection without) or the player closes it, as the Switch's player screen; without a window or with DM_KEYS / DM_CTL it is canceled at once as before Mario Kart World 1.8.0 closed its player screen when the second controller had not pressed yet (pull request #1596). The rules are in dm/host/ctrl_prompt.h (t_ctrl_prompt): B or Escape cancels; with the minimum in, A or Return, the game's maximum, or no connected controller left to join finishes it; the press that makes a controller join counts for neither; no time limit and no close on a focus loss. The game gets no input while it is up, nor until the A or B that closed it is let go. hle_hid.c ctrl_support calls the new front_ctrl_support (front.h) and counts the players again after it (dm_players_reported). The Mac draws it on the Home prompt's card (hq_card_view), iOS as a card with Done and Cancel buttons (DmGamepad.m). The docs no longer ask players to press on every controller first. Front-ends: a front end may pass the controller prompt's texts in the player's language as DM_CTRL_PROMPT_TEXT, one per line: title, hint, count, done, cancel, with {min}, {max} and {joined} replaced by the numbers (docs/frontends.md#starting-a-game) Fixes #1640
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
… player at its first button press, the lowest player free, on the Mac and on iOS (PR seedds#1596) Players could not choose who is player 1: the order followed GameController's list, and for identical pads read from IOKit, the USB port; Bluetooth has no port. With the setting on, a controller is no player until one of its buttons is pressed, then it takes the lowest free slot (pad_slot_take_lowest, pad_slots.h): GameController controllers, raw HID pads and identical pads alike. The press also reaches the game. Not with DM_PAD_MERGE. Off by default. Beyond the PR: the same rule in the iOS front end (DmGamepad.m; a controller waiting for its press hides the touch gamepad, as a connected one does), and a launcher row (settings.tsv, Controls: Press a button to join) so both launchers offer it. docs/settings.md and playing.md say to press on every controller before the game asks how many play: the controller applet stand-in (ctrl_support, hle_hid.c) cancels when fewer have joined than the game wants. Tests: t_hid (pad_slot_take_lowest); host tests pass; DmGamepad.m compiles for iOS. The PR's version ran in Mario Kart World 1.8.0 on the Mac; the iOS side awaits a device test. Co-authored-by: Elie <8143621+elieteyssedou@users.noreply.github.com>
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
…sks for more players than it sees gets a prompt over the game that holds its thread until enough controllers have joined (a first button with Press a button to join, a connection without) or the player closes it, as the Switch's player screen; without a window or with DM_KEYS / DM_CTL it is canceled at once as before Mario Kart World 1.8.0 closed its player screen when the second controller had not pressed yet (pull request seedds#1596). The rules are in dm/host/ctrl_prompt.h (t_ctrl_prompt): B or Escape cancels; with the minimum in, A or Return, the game's maximum, or no connected controller left to join finishes it; the press that makes a controller join counts for neither; no time limit and no close on a focus loss. The game gets no input while it is up, nor until the A or B that closed it is let go. hle_hid.c ctrl_support calls the new front_ctrl_support (front.h) and counts the players again after it (dm_players_reported). The Mac draws it on the Home prompt's card (hq_card_view), iOS as a card with Done and Cancel buttons (DmGamepad.m). The docs no longer ask players to press on every controller first. Front-ends: a front end may pass the controller prompt's texts in the player's language as DM_CTRL_PROMPT_TEXT, one per line: title, hint, count, done, cancel, with {min}, {max} and {joined} replaced by the numbers (docs/frontends.md#starting-a-game) Fixes seedds#1640
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Builds on #1595 (and #859): its commit is the last one here.
Players cannot choose who is player 1 on the Mac: the order follows GameController's list, and for identical pads read from their reports, the USB port. Bluetooth has no port, so nothing chooses it there.
With
DM_PAD_PRESS_TO_JOIN=1, a controller is no player until one of its buttons is pressed, then it takes the lowest player free (pad_slot_take_lowest,pad_slots.h), as a console's "press a button" screen does: GameController controllers, raw HID pads and identical pads alike. Not withDM_PAD_MERGE. Off by default, so nothing changes unless it is set.Checked
make -C dm/host/tests GAME=0400C3F00006E000 runpasses;t_hidcheckspad_slot_take_lowest(the order of presses, identical names, a freed player 1, no slot left).0400C3F00006E000) 1.8.0 as a Mac app, 33 minutes of split-screen races (the same run as Mac: identical pads that GameController lists as one are each a player of their own (issue #1218) #1595): the players chose their order with two Pro Controllers over USB, and two Xbox Wireless Controllers connected over Bluetooth while the game ran joined as players 3 and 4 at their first press.2 to 2 players wanted, 1 connected); pressing on both pads first avoids it.Docs
docs/playing.md,docs/env_switches.tsv🤖 Generated with Claude Code