## Summary
Automatic controller assignment for Eden, aimed at couch co-op and handheld PCs (Steam Deck,
Legion Go, ROG Ally, AYN Odin), plus a set of fixes for running Eden in Steam's Game Mode
(gamescope) and under Steam Input.
## Controller Assignment Handler
Settings > Controls gains a **Controllers** tab. The handler is a segmented choice:
| Handler | Behaviour |
|---|---|
| **Modern Console** | Automatic: each controller that connects becomes the next player (up to 8). |
| **Manual** (default) | Players are set in each player's tab, as before. Its Controller Applet choice: **Disabled**, **Custom Frontend** or **Real Hardware** (the console's own applet, LLE). |
Under Modern Console, **Portable Handheld Gaming Device with Built-in Controller** (on/off)
makes external controllers take the players first, with the handheld's own controls used only
when none is connected.
In the automatic modes:
- Players follow their controllers across reconnects: a controller that leaves keeps its player
for 45 seconds and takes it back when it returns. Each controller keeps its own mappings when
it changes player, for the session.
- At most eight players; a ninth controller waits until a player is free.
- The user's saved controller setup is never rewritten; remaps made in the Controls tab last for
the session, and input profiles are what persist.
- Input profiles can be picked or removed per player, from the Controllers tab or each player tab.
- A controller whose player has no controller mappings (a fresh setup) gets its default mapping.
A DSU (cemuhook) motion binding from the manual setup is kept, for handhelds whose own gyro
needs it.
## Gameplay options
- **Pause When a Controller Disconnects** (on by default): the game pauses when a player's
controller is turned off, or has been gone for 3 seconds, and resumes when a controller takes
that player again. Pressing + on another controller goes on without it.
- **Use Any Controller as Joy-Cons**: a game that only takes Joy-Cons gets them automatically
(dual, or a single sideways one with the buttons arranged to fit).
- **Button Layout**: By Position or By Label, for Xbox and PlayStation style controllers.
- **Player Lights**: controllers that have them show their player number.
## Controllers tab and player tabs
- Connected Players: each player with its controller and battery, profile picker, Swap, Config,
Turn Off (Bluetooth), reorder arrows, drag to swap, and click to rumble. Controllers can be
given a name for the session.
- Assign Handheld Controller: auto-detect, or pick/Identify the handheld's own pad.
- P1-P8 tabs show each player's battery and can be dragged or moved with arrows to change the
player order.
- In Modern Console the Controllers and player tabs use a modern card layout that follows the
light and dark themes, including the system's dark mode (macOS).
## On-screen display
- **Controller Overlay** (View menu, Ctrl+Shift+V): players, their controllers and batteries,
and each player's recent buttons, including stick moves (LS/RS) and clicks (L3/R3). How many
inputs are kept and for how long can be set.
- **Controller Hints**: names a controller in the bottom-left corner when it joins or leaves
a player, and says when the game pauses for a disconnected one. Works without the overlay.
Both are drawn into the presented frame as crisp overlay panels (not scaled with the game, not
in screenshots), so they show inside gamescope.
## Steam Input and gamescope fixes
- **Native gyro under Steam Input.** Steam's virtual pads carry no motion sensors. Eden now opens
the real motion-capable controller behind each virtual pad for its sensors only (Steam Deck,
Steam Controller incl. the 2026 model, Sony, Nintendo), and turns on the Deck's IMU, which
Steam keeps off unless the layout uses the gyro. No DSU server or Steam layout change needed.
- **Bypass Steam Input** (Controllers tab, shown when launched through Steam): Eden opens the
real controllers itself instead of Steam's virtual pads.
- **Controller identity under Steam.** All virtual pads share one GUID and Steam moves physical
controllers between them; controllers are tracked by their Steam handle and slot instead.
- **Handheld detection under Steam.** The Deck's own controls are recognised behind Steam Input
without mistaking standalone controllers (e.g. the Steam Controller) for them.
- **Windows no longer rescale on hover in Game Mode.** gamescope scales a window to fit the
screen together with any tooltip reaching past it, so the main window and Settings grew and
shrank on hover. Under gamescope they now fill the screen.
- **VSync modes in Game Mode.** gamescope offers only some present modes, so Immediate and FIFO
Relaxed vanished silently. They are now listed greyed out with a tooltip pointing to Steam's
Disable Frame Limit and Allow Tearing settings.
- **Stick range testers on small screens.** The controller drawing scales down to fit on
800-pixel screens instead of cutting off the stick range circles.
- **Midnight Blue themes.** A hovered menu-bar item is readable again, and hovered tabs no longer
change size (which made the Settings tabs shake).
## Fixes
- Crash when HID received a controller update before NPad's applet resource was set up.
## Testing
Tested on a Steam Deck (Desktop and Game Mode, direct and Steam launches) with Xbox
controllers, plus a stress test with up to 10 virtual controllers connecting, disconnecting and
pressing at random in both automatic modes (no assignment errors, never more than 8 players,
disconnect pauses resume as expected).
## AI disclosure
Developed with Claude Opus 5.5 (implementation and debugging). I reviewed, tested and can
explain every change.
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
---
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4583
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Replaces all instances of ankerl's unordered map/set with boost's
`unordered_flat_*` classes. This uses std::hash since boost::hash is
actually a lot slower.
Also adds an abstraction layer in `Common` so future changes are quicker
and easier.
Other implementation details:
- ankerl provided hash specializations for tuple and pair, so those were
ported here
- std::erase_if doesn't work on boost, so just used the ADL'd erase_if
This should be about equal or superior performance as unordered_dense for everything except iteration.
Signed-off-by: crueter <crueter@eden-emu.dev>
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4326
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Should warnings be errors? that's a philosophical debate which I can only answer with "no, but if you think otherwise here is an option for you"
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4080
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
So, many users hate the fact when they press START+SELECT, an additional HOME event is sent.
That is annoying coz for most users' default hotkey settings, it closes eden when not in game, and when in game it calls a NOT controller responsive prompt about leaving Eden.
There are several games with reasons to press start+select, also there are homebrews which relies on that combo to open internal menus.
Again. That is annoying.
Digging deep i've found that SDL implements something called guide hack: When Start+Select is pressed it sends a synthetic GUIDE(which code equals to HOME).
This was intended for controllers missing the HOME button, but SDL fails to track them all, and misses API to disabling it.
I've figured out a patch to SDL to disable it, but since it would be better to invest on a PR straight into SDL repo, on our side i thought it better to simply add an option to disable WGI (Windows.Gaming.Input) and Xinput, both paths which could lead into the hack enabling.
Setting is available in a remote place no one will bother.
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4237
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
I'm not into millennial humor, personally.
Proactively removed as much profanity as I could grep.
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4239
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
from PS4 PR - this should help fix the case where a controller
doesn't have an associated gamepad and thus its not automatically
configured.
this should fix that :)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4172
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
the function returned the key AFTER this one, which points to an invalid object
basically its like "oh im returning the index AFTER Myself"
off-by-1 error basically; now it returns OUR own key.
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4178
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
reworked a bit to remove references of parent objects and instead pass as arguments to methods to prevent useless reloads
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: maufeat <sahyno1996@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3908
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Since the launch of the steam controller I think it's only best to push towards updating to SDL3 allowing for a wider range of controller support
I went ahead and started on getting it working. Everything here should be functional, I've personally tested it all on Arch Linux. Still untested on windows, so looking for feedback on that
Any feedback and help would be appreciated!
Main changes:
- Bump everything to SDL3
- Handle SDL3 audio and input
- Add steam controller support, including HD Rumble
- Improved battery reporting via the status icon by using real % rather than state alone
Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3952
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
- our logging code was bigger than spdlog itself, why???? just keep it simple
- fix issues when logging before logging system is even started
- removes the "initialized logging twice" issue
- removes uneeded indirection in file logging
- uses direct formatting instead of jumping hoopla-around the fmt::format() ressult
- code duplication and dead code removal as usual
I did explore dup2() but I think it's not worth the hassle
I did try `fwopen()` but it's better if things are just kept as-is.
there is a lot of noise because I removed a bunch of redundant files on logging and just put everything in one file
now normally this wouldn't be a good idea, however consider: the complexity of logging; it's less than 500 lines... does it really need a whole subsystem?!?!?! ITS JUST LOGGING
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3688
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
Closes#3466
Like said in the issue and the OpenSSL equivalent, disabling SDL2 on
desktop is just not something we want to do. It's not worth the added
burden of supporting the n+1'th matrix.
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3632
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
mainly doing this to reduce memory footprint; we all know how nice ankerl::unordered_dense is
in theory 4x faster - in practice these maps arent that "hot" anyways so not likely to have much perf gained
i just want to reduce mem fragmentation to ease my porting process, plus it helps other platforms as well (ahem weak Mediatek devices) :)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3442
Reviewed-by: DraVee <dravee@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
this should fix issue where you couldn't connect more than 4 controllers at once
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3305
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
No need to have those nano-sleeps for these threads...
Signed-off-by: lizzie lizzie@eden-emu.dev
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2982
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
This fixes an issue in builds where libusb is disabled, it also uses and prioritizes system dependencies over vendored ones (so ports is easier)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2649
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
Mainly because - while we can just give out an AppImage and call it a day - building natively should be an option for all major distros.
And "base" stable debian doesn't provide a new enough g++/clang++ so... we need to make some "fixups".
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2763
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
Compilation and CMake fixes for both Windows on ARM and clang-cl, meaning Windows can now be built on both MSVC and clang on both amd64 and aarch64.
Compiling on clang is *dramatically* faster so this should be useful for CI.
Co-authored-by: crueter <crueter@eden-emu.dev>
Co-authored-by: crueter <crueter@crueter.xyz>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/348
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
Includes citron, sudachi, yuzu
currently broken, because the eden dir is always made early?
Signed-off-by: swurl <swurl@swurl.xyz>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/91
Co-authored-by: swurl <swurl@swurl.xyz>
Co-committed-by: swurl <swurl@swurl.xyz>