Ignore Down+Left, Down+Right, Up+Left, Up+Right?

Found a bug? Please report it, but remember to follow the bug reporting guidelines.
Missing a sane feature? Let us know!
But please do NOT request ports to other systems.

Moderator: ZSNES Mods

Post Reply
Red_Wraith
Rookie
Posts: 16
Joined: Mon Nov 05, 2007 11:58 pm

Ignore Down+Left, Down+Right, Up+Left, Up+Right?

Post by Red_Wraith »

If one uses a gamepad with a 8 way d-pad, playing in ZSNES becomes a pain. The reason is that e.g. pressing Downleft on the d-pad results in Left and Down being sent at the same time (or nearly at the same time) and ZSNES treats this as if only Left was pressed (at least with my P1500 gamepad). This makes it really difficult to press Down because if you don't press it 100% perfectly a Left or a Right will be the result. That's worse than a non-perfect Down not being noticed at all because it results in an unwanted move.
The same problem occurs with the other diagonals on the d-pad.

Is it possible to implement a feature which filters out Down+Left, Down+Right, Up+Left and Up+Right signals to solve the problems?


PS: I am aware of the following thread: http://board.zsnes.com/phpBB2/viewtopic ... light=dpad
Deathlike2
ZSNES Developer
ZSNES Developer
Posts: 6747
Joined: Tue Dec 28, 2004 6:47 am

Post by Deathlike2 »

Assuming you are using ZSNES 1.50 or later, try playing around with joystick sensitivity in the cfg file.
Continuing [url=http://slickproductions.org/forum/index.php?board=13.0]FF4[/url] Research...
Red_Wraith
Rookie
Posts: 16
Joined: Mon Nov 05, 2007 11:58 pm

Post by Red_Wraith »

Deathlike2 wrote:Assuming you are using ZSNES 1.50 or later, try playing around with joystick sensitivity in the cfg file.
I'm using ZSNES 1.52.
I tried what you suggested and I haven't noticed any difference.
Deathlike2
ZSNES Developer
ZSNES Developer
Posts: 6747
Joined: Tue Dec 28, 2004 6:47 am

Post by Deathlike2 »

There is no ZSNES 1.52. It is not an official version.
Continuing [url=http://slickproductions.org/forum/index.php?board=13.0]FF4[/url] Research...
Red_Wraith
Rookie
Posts: 16
Joined: Mon Nov 05, 2007 11:58 pm

Post by Red_Wraith »

Deathlike2 wrote:There is no ZSNES 1.52. It is not an official version.
Oops. :oops: I meant ZSNES 1.51 (for Windows). It was a typo.

But back to the topic: Could ignoring Down+Left etc. resolve the problem?
blackmyst
Zealot
Posts: 1161
Joined: Sun Sep 26, 2004 8:36 pm
Location: Place.

Post by blackmyst »

There is no such thing as an 8-way D-pad. Never has been, never will.

The only trouble you have is because of the shitty design of the D-pad shape itself, failing to register a straight direction press properly. It's not a fault of Zsnes, it's also not an issue with your pad being too "modern" or something. It's just a crappy pad.
[size=75][b]Procrastination.[/b]
Hard Work Often Pays Off After Time, but Laziness Always Pays Off Now.[/size]
byuu

Post by byuu »

Hmm.

If the joypad is in analog mode, the code will poll X/Y axis values, between -0x7fff (left for X, top for Y), 0 (center) and 0x8000 (right for X, bottom for Y). A joypad resistance variable basically controls how perfect the presses have to be. Some cheaper joypads will only send -0x7fff or 0x8000 on perfect angle presses, or not at all. Hence being within ~10% of those values is usually a good, loose threshold. More for fighters, less for RPGs.

Digital mode is the same, but gives exact positions from the above (eg either -0x7fff, 0, or 0x8000 -- nothing else in between), and may trigger the same nasty issues with perfect angles and such. However, the thing to note here is that a joypad resistance variable has no effect on digital mode.

There is also the analog mode POV hat. This one gives precise angles in a 360*100 "degree" circle. But even though you're in analog mode, the POV hat is digital. So agian, you could run into a lousy driver.

Anyway, be sure to try both digital and analog modes if you can.

Your best bet is to try out the Windows control panel joypad calibrator. If you are able to make the movements you want, then ZSNES' driver could use some work. If you are not, then throw your gamepad away :(
Red_Wraith
Rookie
Posts: 16
Joined: Mon Nov 05, 2007 11:58 pm

Post by Red_Wraith »

byuu wrote:Your best bet is to try out the Windows control panel joypad calibrator. If you are able to make the movements you want, then ZSNES' driver could use some work. If you are not, then throw your gamepad away :(
The gamepad works fine in the game controller configuration in the the windows control panel. When I use the analog stick on the game pad I can move the cross around perfectly. If I press a direction on the d-pad it is shown in the field "Cooliehat" (I think it's also called "POV"). For example if I press Downleft a red arrow indicates Downleft on the Cooliehat. It works with all 8 directions of the Cooliehat.
However, if I press Downleft in ZSNES this is recognized as Left.

By the way, when setting the controls in ZSNES it doesn't make any difference if I press a certain direction on the d-pad or if I move the analog stick to that direction.
byuu

Post by byuu »

If I press a direction on the d-pad it is shown in the field "Cooliehat" (I think it's also called "POV"). For example if I press Downleft a red arrow indicates Downleft on the Cooliehat. It works with all 8 directions of the Cooliehat.
However, if I press Downleft in ZSNES this is recognized as Left.
Here is the code that checks the position of the POV hat:

Code: Select all

https://zsnes.bountysource.com/svn/!source/5159/trunk/src/win/winlink.cpp#2838
In short, ZSNES' code is correct. You can see that there are eight possible positions for the POV hat, in multiples of 4500 (it makes a 360*100 degree circle). And, as you can see, there are three unique positions that will set each key: up, down, left and right.

Up would be "up-left", "pure up" and "up-right"; Left would be "down-left", "pure left" and "up-left"; etc.

The only idea I have is to maybe divide the POV hat value by 4500 first, just in case the actual values are not exactly multiples of 4500 for some reason. Eg this would trigger a right keypress for 4500 - 13499, rather than for only 4500, 9000 and 13500.

Code: Select all

switch (js[i].rgdwPOV[p])
Would become:

Code: Select all

switch (js[i].rgdwPOV[p] / 4500 * 4500)
I don't suppose you'd be interested in trying out one of my software programs to see if the joypad support there works for you? I poll the POV hat the same way, so if it's broken there, I can try fixing it. If that works, we can apply the fix to ZSNES. I understand if you're busy or don't want to.
Red_Wraith
Rookie
Posts: 16
Joined: Mon Nov 05, 2007 11:58 pm

Post by Red_Wraith »

byuu wrote:I don't suppose you'd be interested in trying out one of my software programs to see if the joypad support there works for you? I poll the POV hat the same way, so if it's broken there, I can try fixing it. If that works, we can apply the fix to ZSNES. I understand if you're busy or don't want to.
No, I wouldn't mind trying one of your programs. Just tell me where to download it and what I have to do.
byuu

Post by byuu »

Ok, I spoke with Red_Wraith to track down the problem.

The POV hat is working as designed, it's just not very sensitive with only nine possible positions available. And the game in question had some of its own control handling problems.

However, there was in fact an issue with the analog joystick on ZSNES' side.

Code: Select all

https://zsnes.bountysource.com/svn/!source/5159/trunk/src/win/winlink.cpp
Take a look at line 2722:

Code: Select all

2722             if (!X1Disable[i])
2723            {
2724              if (js[i].lX > 0)
2725              {
2726                keys[0x100 + I * 32 + 0] = 1;
2727              }
2728            }
2729    
2730            if (!X2Disable[i])
2731            {
2732              if (js[i].lX < 0)
2733              {
2734                keys[0x100 + I * 32 + 1] = 1;
2735              }
2736            }
2737    
2738            if (!Y1Disable[i])
2739            {
2740              if (js[i].lY > 0)
2741              {
2742                keys[0x100 + I * 32 + 2] = 1;
2743              }
2744            }
2745    
2746            if (!Y2Disable[i])
2747            {
2748              if (js[i].lY < 0)
2749              {
2750                keys[0x100 + I * 32 + 3] = 1;
2751              }
2752            }
There's more code below this to test lZ, rX, rY and rZ. l for left, r for right, obviously. All of it applies ... though I don't know of any controllers with a Z-axis on their analog stick.

Basically, when your analog stick is centered, lX = 0, lY = 0. Left is a negative lX value, up to -32767 when the stick is all the way to the left. Right is positive, up to 32768. Up goes to 32768 and down to -32767.

ZSNES is basically triggering a keypress whenever the axis is even one point off center in any direction. This basically makes the controls way too loose to be enjoyable. And if you have a particularly bad analog connection (one that shakes on its own in joy.cpl), it may even send false keypresses when you don't touch the controller.

There is now zinput.cfg, which contains:

Code: Select all

; Joystick Sensitivity [0..32767]
; Change this value if you have input issues. Higher value = less sensitive.
; If your joystick is not being read at all, try 128 or other low values.
joy_sensitivity=N
However, it appears this variable is not used at all by the current DirectInput code (maybe it's SDL-specific?)

My recommendation would be to modify the above code as such:

Code: Select all

if (js[i].lX > joy_sensitivity)

Code: Select all

if (js[i].lX < -joy_sensitivity)

Code: Select all

if (js[i].lY > joy_sensitivity)

Code: Select all

if (js[i].lY < -joy_sensitivity)
Also, the default value for this is a little tricky ... it appears some controllers have a smaller cap for sensitivity than -32767 to 32768. Red_Wraith's was -16384 to 16383.

I would recommend converting joy_sensitivity to a sensitivity percentage (eg 0 - 100 percent). Then to adjust, do something like this:

Code: Select all

int range = min(5, max(joy_sensitivity, 95)) / 100 * (axis_range / 2);
To get the correct range, modify line 1113 in this file get the range rather than set it, as setting it apparently isn't doing you any favors when you compare the current position against zero.

A good default resistance that works well both with loose control games such as fighters, and tight control games such as RPGs, is 75%. Meaning, you have to push the axis 75% of the way to the edge to trigger a keypress in the emulator.
deathtok
Hazed
Posts: 59
Joined: Tue Oct 12, 2004 6:30 pm

Post by deathtok »

Yeah the D-Pad design has always been flawed. You can mess with the .CFG as has been suggested but I'm going to recommend a different controller. I use a PS2 to USB adapter that solves this problem. The Playstation 2 controller has segmented buttons for it's D-Pad so this never really becomes an issue.

Hope this helps.
Red_Wraith
Rookie
Posts: 16
Joined: Mon Nov 05, 2007 11:58 pm

Post by Red_Wraith »

Here is what I changed in src\win\winlink.cpp of revision 4538 to fix my analog stick. The forum user joebells asked me about this and here is my quick fix (about line 2919).
Of course byuu's suggestion would be much better, but what I needed was just a quick 'n dirty fix.

Code: Select all

         if (!X1Disable[i])
         {
            if (js[i].lX>16383) keys[0x100 + i * 32 + 0] = 1;
         }

         if (!X2Disable[i])
         {
            if (js[i].lX<-16383) keys[0x100 + i * 32 + 1] = 1;
         }

         if (!Y1Disable[i])
         {
            if (js[i].lY>16383) keys[0x100 + i * 32 + 2] = 1;
         }

         if (!Y2Disable[i])
         {
            if (js[i].lY<-16383) keys[0x100 + i * 32 + 3] = 1;
Maybe it would also work if "-16384" was used instead of "-16383" (not tested).

We couldn't fix the problem with my D-Pad because it was a hardware problem (sucky D-Pad) but the fix for the analog stick made the analog stick more useable.

Quote about the D-Pad thing (original topic):
Red_Wraith wrote:I managed it: The diagonal directions get blocked now.
Unfortunately the gaming experience hasn't become much better using the D-pad. Now at least no unintended directions are triggered anymore but the fact that it is hard to press left, right, up or down without pressing one of the diagonals by accident instead doesn't make the control much more pleasesureful. Thus, I can forget my 8 way D-pad.
joebells
Rookie
Posts: 29
Joined: Thu Apr 17, 2008 10:27 pm

Post by joebells »

Thanks Red_Wraith I had tried putting joy_sensitivity in there but that led to the joy not working at all. I had to go with 8192 for my controller. I tried your middle value but that didn't quite work(it sort of did but not great) then I tried 24575 and that didn't work worth anything. So I went with 8192 and in my limited testing it seems much better. It doesn't register a down press until about half way between left or right and down.

I wish someone would either come up with a replacement dpad setup for the 360 controller, or someone make a bluetooth, ps3 dual shock driver that works under vistax64. I imagine someone will write the second one at some point as the ps3 gets more popular. I can't believe ms screwed up the dpad so badly. There hardware usually isn't too bad.

So thank you Red_Wraith for that, byuu for the initial help, and nach for making zget so easy to use. And of course thanks to all the other zsnes devs for making such a great emulator. Can't wait for 2.0
Deathlike2
ZSNES Developer
ZSNES Developer
Posts: 6747
Joined: Tue Dec 28, 2004 6:47 am

Post by Deathlike2 »

byuu wrote:Ok, I spoke with Red_Wraith to track down the problem.

The POV hat is working as designed, it's just not very sensitive with only nine possible positions available. And the game in question had some of its own control handling problems.

However, there was in fact an issue with the analog joystick on ZSNES' side.

Code: Select all

https://zsnes.bountysource.com/svn/!source/5159/trunk/src/win/winlink.cpp
Take a look at line 2722:

Code: Select all

2722             if (!X1Disable[i])
2723            {
2724              if (js[i].lX > 0)
2725              {
2726                keys[0x100 + I * 32 + 0] = 1;
2727              }
2728            }
2729    
2730            if (!X2Disable[i])
2731            {
2732              if (js[i].lX < 0)
2733              {
2734                keys[0x100 + I * 32 + 1] = 1;
2735              }
2736            }
2737    
2738            if (!Y1Disable[i])
2739            {
2740              if (js[i].lY > 0)
2741              {
2742                keys[0x100 + I * 32 + 2] = 1;
2743              }
2744            }
2745    
2746            if (!Y2Disable[i])
2747            {
2748              if (js[i].lY < 0)
2749              {
2750                keys[0x100 + I * 32 + 3] = 1;
2751              }
2752            }
There's more code below this to test lZ, rX, rY and rZ. l for left, r for right, obviously. All of it applies ... though I don't know of any controllers with a Z-axis on their analog stick.

Basically, when your analog stick is centered, lX = 0, lY = 0. Left is a negative lX value, up to -32767 when the stick is all the way to the left. Right is positive, up to 32768. Up goes to 32768 and down to -32767.

ZSNES is basically triggering a keypress whenever the axis is even one point off center in any direction. This basically makes the controls way too loose to be enjoyable. And if you have a particularly bad analog connection (one that shakes on its own in joy.cpl), it may even send false keypresses when you don't touch the controller.

There is now zinput.cfg, which contains:

Code: Select all

; Joystick Sensitivity [0..32767]
; Change this value if you have input issues. Higher value = less sensitive.
; If your joystick is not being read at all, try 128 or other low values.
joy_sensitivity=N
However, it appears this variable is not used at all by the current DirectInput code (maybe it's SDL-specific?)
The variable is used differently between the SDL and Windows ports. I wasn't aware of this, so it shouldn't be a problem to change.
Continuing [url=http://slickproductions.org/forum/index.php?board=13.0]FF4[/url] Research...
byuu

Post by byuu »

joebells wrote:I had to go with 8192 for my controller.
Yes, the Xbox 360 controller is odd. 99% of gamepads have an axis range of -32768 to +32767 in both directions. The Xbox controller has a range of -16384 to +16383. So you actually picked the perfect value for pointing to the middle of your controller.

50% tolerance is a pretty good compromise between working well in both fighting and role playing games.
I wasn't aware of this, so it shouldn't be a problem to change.
Neat, thanks. Let me know if it gives you any trouble. I need to add the axis range detection code myself, as I don't think my code supports the Xbox 360 controller, either.
joebells
Rookie
Posts: 29
Joined: Thu Apr 17, 2008 10:27 pm

Post by joebells »

actually byuu your emulator supported my 360 controller perfectly, joystick and all.
joebells
Rookie
Posts: 29
Joined: Thu Apr 17, 2008 10:27 pm

Post by joebells »

Well I used perfect when really neither truly supports the 360 controller as it uses Xinput and when using it through direct input you can't use both L and R triggers at the same time. They get treated as one axis with one being negative and one being positive and when you press them both at the same time they cancel each other out. But thats a whole different can of worms. I get by using the L and R bumpers, doesn't feel as nice but it works.
byuu

Post by byuu »

joebells wrote:actually byuu your emulator supported my 360 controller perfectly, joystick and all.
That's odd ...

Code: Select all

      int resistance = 75; //config::input.axis_resistance;
      resistance = max(1, min(99, resistance));
      resistance = int32_t(double(resistance) * 32768.0 / 100.0);
      int resistance_lo = 0x7fff - resistance;
      int resistance_hi = 0x8000 + resistance;
75 * 32768 / 100 = 24576. You said it didn't work at all even with 16384. Well, if it works, it works :)
Well I used perfect when really neither truly supports the 360 controller as it uses Xinput and when using it through direct input you can't use both L and R triggers at the same time.
Darn, another API. Eh, I'll look into it when more controllers require it.
joebells
Rookie
Posts: 29
Joined: Thu Apr 17, 2008 10:27 pm

Post by joebells »

I have heard it is extremely easy to program. yeah I think the 360 controller is the only one to use it. Still wouldn't be an issue period if microsoft had just put a decent dpad on the 360 controller instead of making us use the analog, and if they had written a proper controller driver so the buttons could be setup and mapped and such instead of trying to push everyone to use Xinput. The 360 controller control panel is a joke.

The controller does feel the best out of all of them though I think.

And yeah when I was using bsnes for a couple of days I had no issues with the analog joystick as my input method. It correctly registerd a right or left press until about 45 degrees up or down instead of until 1 degree up or down like zsnes was.
Gil_Hamilton
Buzzkill Gil
Posts: 4294
Joined: Wed Jan 12, 2005 7:14 pm

Post by Gil_Hamilton »

joebells wrote:Well I used perfect when really neither truly supports the 360 controller as it uses Xinput and when using it through direct input you can't use both L and R triggers at the same time. They get treated as one axis with one being negative and one being positive and when you press them both at the same time they cancel each other out. But thats a whole different can of worms. I get by using the L and R bumpers, doesn't feel as nice but it works.
That's because MS is stupid.

If I recall, their DirectInput mapping treats L and R as the left and right halves of ONE axis instead of two separate axes.

XBCD will let you reconfigure that.
joebells
Rookie
Posts: 29
Joined: Thu Apr 17, 2008 10:27 pm

Post by joebells »

Gil_Hamilton wrote:
If I recall, their DirectInput mapping treats L and R as the left and right halves of ONE axis instead of two separate axes.

XBCD will let you reconfigure that.
thats what my post said about the one axis :)

as far as xbcd no luck for us wireless folk it only works on the wired version. There is a japanese driver someone wrote for the wireless but it only allows one controller per wireless gaming receiver instead of the four normally allowed. The driver is not signed either and under vista sp1 you cannot permanately disable driver signing so f8 every boot or install some funky boot software to do it for you. Other than that though the driver is really nice with lots of options.
Post Reply