-
-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amiberry segfaults whenever launched with Bluetooth WiiMote connected. #542
Comments
Thanks for the report. You can find the |
Ok, doing that doesn't cure the problem. Some more info though: I found an old (sticky) USB Thrustmaster Firestorm Dual Power Gamepad, so, with the WiiMote disconnected I tried using that and it works (and doesn't control the GUI as expected with that changed setting, but does when it's changed back). When I THEN re added the WiiMote, Amiberry would still launch, and I could see (several) Wii controllers listed in the Amiberry input device selector (Though THRUSTMASTER was still selected as expected). HOWEVER - when I then disconnected the USB Thrustmaster Gamepad and tried to launch (with just the WiiMote still connected) it segfaulted again, and if I reconnect the USB Thrustmaster Gamepad, it still segfaults. It only launches successfully again when I disconnect the WiiMote. I've tried all sorts of combinations of reboots and deleting and repairing the WiiMote in bluetooth settings, but it seems as though the only time it worked is the first time ever I used it, and then the first time after adding a new gamepad. After that, it fails every time. I've also just noticed that this failure (segfault) is now only for the Amiberry GUI itself. Since I have set up configurations pointing to the proper Kickstart ROMs, they will actually launch with the WiiMote connected, but it segfaults as soon as I hit F12 for the Amiberry GUI, and segfaults everytime on attempted launch of "+ START AMIBERRY". |
@rickwookie I'll have to do some tests here to see if I can recreate the problem, which is going to be a little tricky as I don't have the same controller (and it works with those I have here). But we've had reports of a similar issue with a PS4 controller when connected via Bluetooth (only, cable works!), perhaps these two cases are related. |
Ok, so another quirk I just noticed considering that joystick for GUI setting (gui_joystick_control=no), if I start Amiberry GUI with gui_joystick_control=no, just have a keyboard and the USB gamepad connected, it all works. Then, if I turn on the paired WiiMote (wake it with a button press so it re-connects) WHILE AMIBERRY GUI IS RUNNING, the GUI freezes for about a second while the WiiMote seems to get detected and then I can move around the Amiberry GUI using the D-Pad on the WiiMote, even though gui_joystick_control=no, and there was no GUI control from the USB Gamepad (as expected). Further, the movement around the menu is as expected (press up on the D-Pad and it goes up one line) vs what happens with the WiiMote in the actual RetroPie Emulation Station UI where it jumps two lines every press of the D-Pad. So I wonder is the system picking up the WiiMote simultaneously as both a USB keyboard AND a controller? this would explain the double input behaviour and why Amiberry sees it as a keyboard too? Possibly not related issue, but thought it worth reporting anyway. |
It depends on how the system detects it, if it also sends keyboard commands that would explain the double input and also the fact that you can still use it in the GUI, even with that option disabled. |
You must have a friend with an old Wii collecting dust somewhere, that you can use to test right? |
It segfaults also for dualshock4 controllers. You can workaround it by disabling the accelerometer/motion control on ds4. I assume the same would work for the Wii controller. See https://retropie.org.uk/forum/topic/17650/dualshock-controllers-on-4-4-with-3b/34 I did some debugging of the input code in amiberry. It crashes during an SDL call SDL_JoystickGetAxis but I'm not sure it's the fault of SDL yet. The init_joystick code in amiberry gets triggered 4 times which seems wrong, but the input code isn't too easy to follow and I'm not that familiar with the codebase. |
I made a quick fix to resolve this but I won't do a PR as I think it may be fixed better in a different way. I think the input code is in need of an overhaul (sorry). The function read_joystick in |
@joolswills |
@joolswills I also tested 2 more scenarios:
It seems to work in both cases here. Does this only happen if the controller is paired through Bluetooth? |
Tested on RetroPie via Bluetooth also now, it didn't crash on me with the PS4 controller. I tried the following:
|
Did you launch directly to a game/demo? The GUI is ok afaik. I've not tested with a ds4. That was a user on our forum. I tested with a Wii controller. |
@joolswills So the differences here are:
SDL2 has had a number of controller-related fixes and improvements the last couple of weeks, so it could be related to that. I'll test on another system which has the same as above, but without the latest SDL2 to be sure. Otherwise it might be that only controllers that are mapped with a Retroarch config have this problem. I'll post more once I have more test results. |
It doesn't matter if they are mapped or not. Btw I debugged this with gdb on a source level. It may well be fixed in a newer SDL but it's logical to not try and read non existing axis. So the code fix makes sense in any case. |
That's true, I'm just trying to understand why I'm not getting a crash on my other environments :) |
Probably an SDL change. OS version doesn't make a difference btw. It happens on both stretch and buster (I was testing on buster with the RetroPie SDL 2.0.9). |
@rickwookie @joolswills |
Sorry for the delay. Actually it seems we need more than this. My apologies as I missed this before - maybe I wrapped more code in the getaxis call. The code after the axis check now segfaults on the button reads. Need to check NumButtons also for the same reason. I did this just now and it solved it, but there are other getButton calls that might need wrapping. |
This is for the Wii controller at least. I did a quick patch to ditch all joysticks with no axes or buttons. Need to check another segfault I got when entering GUI. Will update later though as I need sleep. |
Ah looks like it's due to gui_joystick in main_window.cpp. we need to disable this if joystick 0 has no axes or buttons too (or skip to the next one). The GUI is hard coded to the first controller it seems and in my test case this was the Wii device with no axes/buttons. |
This diff is only intended as an illustration to stop the segfaults - not as a final fix but it's easier to illustrate. Applies against the commit before your change btw. Had to hack the SDL_JOYAXISMOTION: case also as this seems to segfault if gui_joystick is null. diff --git a/external/libmpeg2 b/external/libmpeg2
index 185d891..6891249 160000
--- a/external/libmpeg2
+++ b/external/libmpeg2
@@ -1 +1 @@
-Subproject commit 185d891f1c282732584f5dbfed224ddefe864cc6
+Subproject commit 6891249c9ca2237b08665380b169d78f96878a51
diff --git a/src/osdep/amiberry_input.cpp b/src/osdep/amiberry_input.cpp
index 5bc1e9d..de70281 100644
--- a/src/osdep/amiberry_input.cpp
+++ b/src/osdep/amiberry_input.cpp
@@ -736,6 +736,11 @@ static int init_joystick()
strncpy(joystick_name[cpt], SDL_JoystickNameForIndex(cpt), sizeof joystick_name[cpt] - 1);
write_log("Controller Detection for Device: %s \n", joystick_name[cpt]);
+ if (SDL_JoystickNumAxes(joysticktable[cpt]) == 0 || SDL_JoystickNumButtons(joysticktable[cpt]) == 0) {
+ write_log("Controller has no Axes or Buttons - Skipping \n");
+ joysticktable[cpt] = nullptr;
+ }
+
//this now uses controllers path (in tmp)
char control_config[255];
strcpy(control_config, tmp);
diff --git a/src/osdep/gui/main_window.cpp b/src/osdep/gui/main_window.cpp
index 3ee846c..41bb5bd 100644
--- a/src/osdep/gui/main_window.cpp
+++ b/src/osdep/gui/main_window.cpp
@@ -615,6 +615,8 @@ void checkInput()
break;
case SDL_JOYAXISMOTION:
+ if (gui_joystick)
+ {
// Deadzone
if (std::abs(gui_event.jaxis.value) >= 10000 || std::abs(gui_event.jaxis.value) <= 5000)
{
@@ -663,7 +665,7 @@ void checkInput()
}
}
break;
-
+ }
case SDL_KEYDOWN:
if (gui_event.key.keysym.sym == key_for_gui)
{
@@ -778,7 +780,11 @@ void amiberry_gui_run()
if (gui_joystick_control && SDL_NumJoysticks() > 0)
{
gui_joystick = SDL_JoystickOpen(0);
- joypad_axis_state.assign(SDL_JoystickNumAxes(gui_joystick), 0);
+ if (SDL_JoystickNumAxes(gui_joystick) > 0 && SDL_JoystickNumButtons(gui_joystick) > 0) {
+ joypad_axis_state.assign(SDL_JoystickNumAxes(gui_joystick), 0);
+ } else {
+ gui_joystick = nullptr;
+ }
}
// Prepare the screen once |
Btw in case you were wondering. The first joystick device is "Nintendo Wii Remote IR". Hence the no axes/buttons. Of course SDL should handle this better and the new version may do. But still good to work around this imho for now. Also the missing check in SDL_JOYAXISMOTION seems needed (I think this code being hard coded to joystick 0 should be improved - maybe putting all input functions into its own class and reusing them with GUI/in-game). Anyway - a quick fix for now would be good :-) whatever you think is best |
I can confirm this issue exists with PS4 dualshock. Works fine when launching games with keyboard only, segfaults while launching if the PS4 dualshock is paired. I tried setting gui_joystick_control to no which didn't resolve the issue. |
@joolswills |
I think it resolves all cases but it's not ideal as it means no joystick control in GUI. Also the indent needs fixing for the Case statement - I excluded indent to make the diff simpler. But it stops the crash yep. |
@joolswills |
@joolswills PS: The indentation seems correct here, btw. |
Unfortunately didn't solve the issue for me. PS4 dual shocked paired. (SDL2 + DispmanX)
|
@morfeus77 |
Seems unrelated. I solved the issue as mentioned in one of the above posts the issue was caused by motion controls. fixed with https://retropie.org.uk/forum/topic/17650/dualshock-controllers-on-4-4-with-3b/35 |
This should have fixed that issue but I'm looking into it as I was able to reproduce a crash when rebuilding master via RetroPie-Setup even though my debug build from master worked. Doing some more testing - maybe I missed something due to differing parameters etc. |
The logic in my fix was changed. The joystick should be skipped if it has no axis or buttons. This resolves the crash with my Wii controller.
|
@joolswills |
Then you will need to wrap all the button code in a check so it works for controllers that miss buttons and the same for axes (which was done in the amiberry_input earlier in this ticket). |
This was a quick fix. The input code should only try and read buttons if there are buttons and read axes if there are axes. And the same with hats etc. |
My dpad controllers use axes for dpad and buttons for everything else. However of course a controller could use just buttons also. Your code would work for that for input but fail for an axes only device. The best fix is to check in read_joystick and not try and fetch buttons/axes/hats if they are not present). |
Wrapping the button reads is simple enough btw but you have the hat code that handles hats or buttons. Perhaps reading button states into an array at the start which is wrapped then using that would simplify logic. But I'm not as familiar with this code as you. If this is done you can of course remove the checks on init_joystick. /Issue spam :-) |
A quick example. Without re-indenting (the file has a mix of spaces and tabs that should be sorted imho) diff --git a/external/libmpeg2 b/external/libmpeg2
index 185d891..6891249 160000
--- a/external/libmpeg2
+++ b/external/libmpeg2
@@ -1 +1 @@
-Subproject commit 185d891f1c282732584f5dbfed224ddefe864cc6
+Subproject commit 6891249c9ca2237b08665380b169d78f96878a51
diff --git a/src/osdep/amiberry_input.cpp b/src/osdep/amiberry_input.cpp
index 8373d8a..288f713 100644
--- a/src/osdep/amiberry_input.cpp
+++ b/src/osdep/amiberry_input.cpp
@@ -729,16 +729,7 @@ static int init_joystick()
for (auto cpt = 0; cpt < nr_joysticks; cpt++)
{
joysticktable[cpt] = SDL_JoystickOpen(cpt);
- if (SDL_JoystickNumAxes(joysticktable[cpt]) == 0
- && SDL_JoystickNumButtons(joysticktable[cpt]) == 0)
- {
- if (SDL_JoystickNameForIndex(cpt) != nullptr)
- strncpy(joystick_name[cpt], SDL_JoystickNameForIndex(cpt), sizeof joystick_name[cpt] - 1);
- write_log("Controller %s has no Axes or Buttons - Skipping... \n", joystick_name[cpt]);
- SDL_JoystickClose(joysticktable[cpt]);
- joysticktable[cpt] = nullptr;
- }
-
+
if (joysticktable[cpt] != nullptr)
{
if (SDL_JoystickNameForIndex(cpt) != nullptr)
@@ -876,8 +867,7 @@ static void close_joystick()
{
for (auto cpt = 0; cpt < nr_joysticks; cpt++)
{
- if (joysticktable[cpt] != nullptr)
- SDL_JoystickClose(joysticktable[cpt]);
+ SDL_JoystickClose(joysticktable[cpt]);
}
nr_joysticks = 0;
}
@@ -1093,6 +1083,8 @@ static void read_joystick()
auto held_offset = 0;
+ if (SDL_JoystickNumButtons(joysticktable[hostjoyid]) > 0)
+ {
// detect standalone retroarch hotkeys
if (current_controller_map.hotkey_button == -1)
{
@@ -1145,6 +1137,8 @@ static void read_joystick()
held_offset = 0;
}
+ }
+
if (SDL_JoystickNumAxes(joysticktable[hostjoyid]) > 0)
{
int val;
@@ -1211,6 +1205,9 @@ static void read_joystick()
setjoystickstate(hostjoyid + 1, 3, val, upper_bound);
}
+
+ if (SDL_JoystickNumButtons(joysticktable[hostjoyid]) > 0)
+ {
// cd32 red, blue, green, yellow
// south
setjoybuttonstate(hostjoyid + 1, 0 + held_offset,
@@ -1238,6 +1235,10 @@ static void read_joystick()
SDL_JoystickGetButton(joysticktable[hostjoyid], current_controller_map.start_button) & 1);
// start
+ }
+
+ if (SDL_JoystickNumHats(joysticktable[hostjoyid]) > 0 && SDL_JoystickNumButtons(joysticktable[hostjoyid]) > 0)
+ {
// up down left right
// HAT Handling *or* D-PAD buttons
const int hat = SDL_JoystickGetHat(joysticktable[hostjoyid], 0);
@@ -1277,6 +1278,7 @@ static void read_joystick()
SDL_JoystickGetButton(joysticktable[hostjoyid],
current_controller_map.select_button) & 1);
// select button
+ }
}
}
} |
Fixed a c&p error in last diff. Sorry again for all the ticket spam. The above solution (if indentated properly) is a better fix if only temporary until things are reworked a bit. |
|
had a brain fart - the problem is elsewhere as this check isn't an issue at all. I think I need sleep :) |
Last post - promise. After getting myself confused and rechecking via gdb from 3 The problem is the code initialises things like current_controller_map members to -1. These are getting passed through to SDL and it's segfaulting. The SDL code correctly fails for non existent buttons but not if you ask for a button or axis of -1. Which could be checked in SDL but the correct fix for this is to revert the workarounds and checking NumAxis etc and just make sure you don't send any -1 values to GetAxis or GetButton. Of course you still shouldn't call these functions imho if there are no corresponding buttons/axis but I think it's best to rework this code rather than hiding the issue with the checks in my previous post. Sorry I missed this before. |
Ah of course, that makes sense :) |
Don't attempt to get Joystick Axis or Button if it's not mapped (set to -1)
Could someone test with the latest commit above please? This is meant as a temporary fix until that area is improved in a future update. |
Works fine on my side! Good job. |
@morfeus77 Thanks for confirming! |
After trying to create a custom control within Amiberry so that I could assign J1 Fire button to one of the buttons on my WiiMote, now whenever I try to launch Amiberry while a WiiMote is connected, it fails with the following in runcommand.log:
Parameters: Executing: bash "/home/pi/RetroPie/roms/amiga/+Start Amiberry.sh" INFO: --- New exception --- INFO: JIT not in use. INFO: Segmentation Fault INFO: info.si_signo = 11 INFO: info.si_errno = 0 INFO: info.si_code = -6 INFO: info.si_addr = 00001288 INFO: r0 = 0x00000000 INFO: r1 = 0xbef6650c INFO: r2 = 0x00000000 INFO: r3 = 0x00000008 INFO: r4 = 0xb6fc4968 INFO: r5 = 0x0000000b INFO: r6 = 0xbef6650c INFO: r7 = 0x000000af INFO: r8 = 0x040f0fa4 INFO: r9 = 0x40000045 INFO: r10 = 0x00000001 INFO: FP = 0x00000001 INFO: IP = 0x00000000 INFO: SP = 0xbef66508 INFO: LR = 0x00000000 INFO: PC = 0xb6dea8ec INFO: CPSR = 0x00000010 INFO: Fault Address = 0x00000000 INFO: Trap no = 0x0000000e INFO: Err Code = 0x00000207 INFO: Old Mask = 0x00000000 INFO: LR - 0x00000000: symbol not found INFO: Stack trace: INFO: 0x001a8350 <(null) + 0x001a8350> (./amiberry) INFO: 0xb67b7130 <__default_rt_sa_restorer + 0x00000000> (/lib/arm-linux-gnueabihf/libc.so.6) INFO: IP out of range INFO: Stack trace (non-dedicated): INFO: ./amiberry() [0x1a8468] INFO: /lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb67b7130] INFO: End of stack trace. INFO: --- end exception --- ~
This is on an RPi 4 using RetroPie built from source on a fullt updated Raspbian Lite yesterday.
I've tried using the RetroPie setup script to remove Amiberry (I then delected the amiga folders in both config and roms) and then used Retropie setup script to re-install it (so it all got recompiled/re-built again), but something is obviously lingering as the segfault happens immediately when I try to launch Amiberry again with a WiiMote connected.
If I disconnect the WiiMote, Amiberry runs fine again.
The text was updated successfully, but these errors were encountered: