NagyD / SDLPoP

An open-source port of Prince of Persia, based on the disassembly of the DOS version.
GNU General Public License v3.0
1.09k stars 139 forks source link

XBOX 360 joystick run/walk issue #144

Open Wilstorm opened 6 years ago

Wilstorm commented 6 years ago

I am running SDLPoP version 1.17 within RetroPie. When using an XBOX 360 wireless controller it seems to work fine until you touch the right thumb stick. Once you move the right thumb stick and go back to the left stick you can only take "careful" (shift) steps and your character no longer runs. The only way I found to correct the issue is exit the game and start over. I posted over in the forum but no replies yet so I thought I would try here to see if anyone else is having the same issue.

Also is it possible to assign joystick buttons for the versatility but also to save, load, exit from a joystick only vs. needing the keyboard? I always load SDLPoP in RetroPie and it's one of the few games I need to have the keyboard & joystick handy to play.

Thank you.

NagyD commented 6 years ago

First of all, please note that I don't have a joystick or gamepad, so I can't directly test this.

Once you move the right thumb stick and go back to the left stick you can only take "careful" (shift) steps and your character no longer runs

"shift" in joystick/gamepad mode is handled here: https://github.com/NagyD/SDLPoP/blob/master/src/seg000.c#L1257 You could try adding some debug printouts to see which part of the condition becomes true in your case.

Also is it possible to assign joystick buttons for the versatility but also to save, load, exit from a joystick only vs. needing the keyboard?

One button was assigned to quitting, but it "disappeared" in e7ec4cc69ac65c24f3cd958559f1b109e47feb8e when @Falcury migrated the code to the Controller API.

Buttons are handled here: https://github.com/NagyD/SDLPoP/blob/master/src/seg009.c#L2722 As you can see, it converts some gamepad buttons to Ctrl+key combinations. You could add your own ones there or change the existing ones.

NagyD commented 6 years ago

I posted over in the forum but no replies yet

Which forum do you mean?

Falcury commented 6 years ago

My expectation is that the mapping of the right analog stick for some reason got swapped with either the left or right trigger. These are supposed to also act like "shift" (so you can literally "grab" on to ledges, etc).

If that's indeed the case, disabling the checks in these lines should solve the problem for you: https://github.com/NagyD/SDLPoP/blob/master/src/seg000.c#L1258-L1259

I could try to reproduce this, but I don't have a RetroPie installation at the moment so I would first have to set that up.

EDIT: I also have the issue on Windows using an Xbox 360 controller, so it isn't related to RetroPie after all. It looks like the issue was caused by this commit: https://github.com/NagyD/SDLPoP/commit/92f8cd460d2a8bf0640ed3de2543131527be14cc The problem is that the SDL_GameController interface still emits SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP and SDL_JOYAXISMOTION events. The current code handles these events, but they should actually be ignored.

Falcury commented 6 years ago

One button was assigned to quitting, but it "disappeared" in e7ec4cc when @Falcury migrated the code to the Controller API.

If I remember correctly, I replaced quitting with restarting the game, because it seemed to me that people would want to be able to do that as well. Hm, maybe pressing "start" twice could quit the game, then? (i.e., if you are already on the title screen, pressing "start" quits the game.)

Wilstorm commented 6 years ago

Which forum do you mean?

Sorry, I was referring to the RetroPie forum at retropie.org.uk. I use RetroPie for retro gaming but always load SDLPoP as it's a staple game! :)

Wilstorm commented 6 years ago

Hm, maybe pressing "start" twice could quit the game, then? (i.e., if you are already on the title screen, pressing "start" quits the game.)

That might work! I do have a Raspberry Pi setup and a controller so I could do any testing you might want.

One thing I always notice for me is I try and move major games functions like save, load, exit from a single key press on the main keys ABXY. If I am having a "wild" game session I tend to start hitting buttons around the main ones.

For like Libretro/Retroarch I do something like consoles. Where the start button starts the game and select+start to exit. On controllers there always seems to be a "select" and a start so it works well.

Libretro/Retroarch reserves a "hotkey" enable button which most people set to the select button on a controller. Then you can press select plus any another key to perform a function. Such as select+start = exit, select+left shoulder = save, select+right shoulder = load, select+right trigger = pause, etc.

NagyD commented 6 years ago

Hi @Wilstorm, I merged pull request #145 that should fix your problem with run/walk. Could you please check if it works for you?

I think the hotkey feature should be a separate issue.

NagyD commented 6 years ago

This patch is included in the latest release. @Wilstorm, @Falcury, does it fix the problem? Can I close this issue?

Wilstorm commented 6 years ago

It still has the same issue. The right stick still does the same as in the original post. You can run a few steps and then are locked to careful/shift steps. The left stick you can only take careful/shift steps.

The left and right triggers pull up the save, load & quit menu. The left/right triggers seem like a good fit for "shift" holding a ledge, stepping etc. or a button would work too.

There is a nice menu for saving, loading, quitting, etc. on the left and right triggers now. That menu seems like it would fit well on the start or select button.

Also I noticed when I jump to grab a ledge it's automatically in "shift mode" and I can hold on to the ledge indefinitely without holding any joystick button.

I have no idea if it will help but they use the xpad.drv on Raspbian running RetroPie but I think they will be upgrading to Stretch soon. http://www.retropie.org.uk

NagyD commented 6 years ago

It still has the same issue. The right stick still does the same as in the original post.

@Falcury, do you have any idea? (As you know, I can't test this myself.)

Sorry, I was referring to the RetroPie forum at retropie.org.uk.

For the record, here is the thread in that forum: https://retropie.org.uk/forum/topic/13562/sdlpop-joystick-control-issue

Falcury commented 6 years ago

Then it seems that it was two separate issues after all. See the first part of my post from 22 October 2017.

The expected mapping for the analog axes should something like:

Left stick horizontal: left/right Left stick vertical: up/down (if all-directional controls enabled) Right stick horizontal: left/right Right stick vertical: up/down (if all-directional controls enabled) Left trigger: shift Right trigger: shift

Note that the left/right triggers are also analog axes, but they have no center point (for the sticks, 0 is the center point, and the value can become either negative or positive depending on the direction).

My guess is that one or more of the right stick axes (either horizontal or vertical) somehow got swapped with one or more of the trigger axes. As soon as the right stick is touched, SDLPoP would register that the trigger threshold has been exceeded (keep in mind, the trigger axes have no center point) which causes shift to be set in an always-on state.

My expectation is that this is not to blame on SDLPoP, but on the faulty mapping, arising either from SDL's GameController API or from RetroPie itself.

I have a Raspberry Pi, but I don't run RetroPie on it, so I still can't test this. Running on the latest version of Raspbian, last time I checked (just before the 1.18 release) everything worked fine with the Xbox 360 controller.

As a possible workaround (though not an actual solution), disabling the two joy_axis checks in read_joyst_control() in seg000.c might suppress the movement issue:

if (joy_X_button_state == 1 ||
        joy_axis[SDL_CONTROLLER_AXIS_TRIGGERLEFT] > 8000 ||
        joy_axis[SDL_CONTROLLER_AXIS_TRIGGERRIGHT] > 8000)
{
    control_shift = -1;
}
NagyD commented 6 years ago

@Wilstorm, did you compile SDLPoP for yourself? That is, can you recompile with Falcury's workaround yourself, or should we compile for you?

Wilstorm commented 6 years ago

I am not sure how to make the changes. Basically RetroPie has it in a menu with two choices. 'Update from binary' or 'Update from source'. You press enter and when it's done it's in Emulationstation ready to go! :) If there's any issues he has you paste the log and he usually fixes it within hours some times minutes.

Falcury commented 6 years ago

Then I guess I should try to install RetroPie myself some time, in order to reproduce the issue.

NagyD commented 4 years ago

PR #202 solves a similar problem, can someone check if it solves this as well?

carlosefr commented 6 months ago

I had this exact issue yesterday with SDLPoP v1.23 and here's what worked for me, in case someone else bumps into it and ends up googling their way into this thread:

I used sdl2-jstest to check the button mappings for my Xbox 360 controller and noticed half of them were wrong (e.g. start was mapped to b7 when it should be mapped to b9). The ID of my controller — actually the ID of the non-Microsoft wireless receiver I have — seems to be shared by devices from different manufacturers which unfortunately number the buttons differently.

I searched gamecontrollerdb.txt for an entry that had the correct mappings under a different ID and found one (that saved me from having to write one from scratch).

I created a new gamecontrollerdb.txt in the same directory as the prince executable with just that line but with the ID changed to my controller's ID (as reported by sdl2-jstest). Then I uncommented the ; gamecontrollerdb_file = gamecontrollerdb.txt in SDLPoP.ini and things improved, but not quite there yet.

The final change was to remove the mappings for the right-side analog stick (rightx and righty), ending up with this in gamecontrollerdb.txt:

030000005e040000a102000007010000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,

As an extra, I added the following to my ~/.bashrc to fix the mappings for other SDL games. Notice that the rightx and righty mappings are included, as that tweak is only needed for SDLPoP:

export SDL_GAMECONTROLLERCONFIG="030000005e040000a102000007010000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,"

The control issue with SDLPoP only starts after touching the right-side analog stick because SDL reports analog inputs as zero until they're first activated. But once the stick is touched and returns back to its center position, the true center value is never zero (it's not even the same every time). SDLPoP interprets this as a button being pressed.