mirror of https://github.com/PCSX2/pcsx2.git
Compare commits
4 Commits
0ddef3d802
...
93c59427e3
Author | SHA1 | Date |
---|---|---|
badfontkeming | 93c59427e3 | |
Tyler Wilding | 1fff69b0aa | |
PCSX2 Bot | 4d347305b5 | |
badfontkeming | 6d9b9d44a1 |
|
@ -1117,6 +1117,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000bc2000000155000000010000,SNK NEOGEO Arcade Stick Pro,a:b1,b:b4,x:b0,y:b3,back:b10,guide:b9,start:b11,leftshoulder:b2,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
|
||||
|
||||
# Linux
|
||||
03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
@ -1324,7 +1325,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b13,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
|
||||
030000000d0f0000c100000011010000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
|
@ -1609,6 +1610,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,
|
||||
03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,
|
||||
03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux,
|
||||
03000000a30600000d5f000010010000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
|
||||
03000000a30600000c04000011010000,Saitek P2900,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,
|
||||
03000000a306000018f5000010010000,Saitek P3200 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -60,17 +60,17 @@ namespace usb_pad
|
|||
void SDLFFDevice::CreateEffects(const std::string_view device)
|
||||
{
|
||||
// Most games appear to assume that requested forces will be applied indefinitely.
|
||||
// Gran Turismo 4 uses a single indefinite spring(?) force to center the wheel in menus,
|
||||
// and both GT4 and the NFS games have been observed using only a single constant force
|
||||
// Gran Turismo 4 uses a single indefinite spring(?) force to center the wheel in menus,
|
||||
// and both GT4 and the NFS games have been observed using only a single constant force
|
||||
// command over long, consistent turns on smooth roads.
|
||||
//
|
||||
//
|
||||
// An infinite force is necessary as the normal mechanism for looping FFB effects,
|
||||
// the iteration count, isn't implemented by a large number of new wheels. This deficiency
|
||||
// exists at a firmware level and can only be dealt with by manually restarting forces.
|
||||
//
|
||||
//
|
||||
// Manually restarting forces causes problems on some wheels, however, so infinite forces
|
||||
// are preferred for the vast majority of wheels which do correctly handle them.
|
||||
//
|
||||
//
|
||||
// Known "Problem" wheels which don't implement effect iterations
|
||||
// - Moza series: DOES implement infinite durations
|
||||
// - Accuforce v2: DOES implement infinite durations (deduced from anecdote, not confirmed manually)
|
||||
|
@ -195,18 +195,57 @@ namespace usb_pad
|
|||
if (m_constant_effect_id < 0)
|
||||
return;
|
||||
|
||||
const s16 new_level = static_cast<s16>(std::clamp(level, -32768, 32767));
|
||||
s16 new_level = static_cast<s16>(std::clamp(level, -32768, 32767));
|
||||
if (m_constant_effect.constant.level != new_level)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
if (bypass_sdl_when_updating)
|
||||
{
|
||||
new_level = new_level * 10000 / 32767;
|
||||
// TODO: Other force types probably need the same type of attention, but constant forces are
|
||||
// the most sensitive to this issue as they're generally going to be updated the most frequently.
|
||||
|
||||
// DANGER! Reading this code may give you radiation poisoning.
|
||||
// It's ugly, but it works. Ideally SDL would be patched to make this unnecessary,
|
||||
// but if patching SDL proves to be too unwieldy, a cleaned-up version of this
|
||||
// might be appropriate.
|
||||
|
||||
// It's not easy to identify by hand if you're not highly experienced, so I'd recommend
|
||||
// average joes use USBPcap via Wireshark in order to verify whether your approach works.
|
||||
// Try this filter:
|
||||
// usb.src=="host" && usb.data_len!=0 && usbhid.data
|
||||
|
||||
// Steal the raw DirectInput references from SDL and update them directly.
|
||||
// Allows us to set our own flags for SetParameters. This is important because
|
||||
// SDL sends unnecessary flags with its updates, which causes unnecessary HID reports,
|
||||
// which may be causing a loss in detail due to wheels unnecessarily reinitializing
|
||||
// the force.
|
||||
|
||||
// Yeah there's raw C casts, I couldn't figure out how to appease the C++ compiler
|
||||
// when using stl casts before I had to stop working on this
|
||||
_SDL_Haptic* real = (_SDL_Haptic*)(m_haptic);
|
||||
auto ref = real->effects[m_constant_effect_id].hweffect->ref;
|
||||
auto k = (DICONSTANTFORCE*)real->effects[m_constant_effect_id].hweffect->effect.lpvTypeSpecificParams;
|
||||
k->lMagnitude = new_level;
|
||||
ref->SetParameters(&real->effects[m_constant_effect_id].hweffect->effect, DIEP_TYPESPECIFICPARAMS);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_constant_effect.constant.level = new_level;
|
||||
if (SDL_HapticUpdateEffect(m_haptic, m_constant_effect_id, &m_constant_effect) != 0)
|
||||
Console.Warning("SDL_HapticUpdateEffect() for constant failed: %s", SDL_GetError());
|
||||
}
|
||||
#else
|
||||
m_constant_effect.constant.level = new_level;
|
||||
if (SDL_HapticUpdateEffect(m_haptic, m_constant_effect_id, &m_constant_effect) != 0)
|
||||
Console.Warning("SDL_HapticUpdateEffect() for constant failed: %s", SDL_GetError());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Avoid re-running already-running effects by default. Re-running a running effect
|
||||
// causes a variety of issues on different wheels, ranging from quality/detail loss,
|
||||
// to abrupt judders of the wheel's FFB rapidly cutting out and back in.
|
||||
//
|
||||
//
|
||||
// Known problem wheels:
|
||||
// Most common (Moza, Simagic, likely others): Loss of definition or quality
|
||||
// Accuforce v2: Split-second FFB drop with each update
|
||||
|
|
|
@ -5,6 +5,51 @@
|
|||
|
||||
#include "USB/usb-pad/usb-pad.h"
|
||||
#include "Input/SDLInputSource.h"
|
||||
#ifdef __WIN32__
|
||||
#include <sdl_haptic.h>
|
||||
#include <dinput.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
// Copied some internal structure definitions from SDL's source
|
||||
// in order to scoop out their inner bits that are excluded from
|
||||
// public-facing headers.
|
||||
|
||||
// It's ugly, but it works for the purposes of this hack/PoC
|
||||
|
||||
struct haptic_hweffect
|
||||
{
|
||||
DIEFFECT effect;
|
||||
LPDIRECTINPUTEFFECT ref;
|
||||
};
|
||||
|
||||
struct haptic_effect
|
||||
{
|
||||
SDL_HapticEffect effect; // The current event
|
||||
struct haptic_hweffect* hweffect; // The hardware behind the event
|
||||
};
|
||||
|
||||
struct _SDL_Haptic
|
||||
{
|
||||
Uint8 index; /* Stores index it is attached to */
|
||||
|
||||
struct haptic_effect* effects; /* Allocated effects */
|
||||
int neffects; /* Maximum amount of effects */
|
||||
int nplaying; /* Maximum amount of effects to play at the same time */
|
||||
unsigned int supported; /* Supported effects */
|
||||
int naxes; /* Number of axes on the device. */
|
||||
|
||||
struct haptic_hwdata* hwdata; /* Driver dependent */
|
||||
int ref_count; /* Count for multiple opens */
|
||||
|
||||
int rumble_id; /* ID of rumble effect for simple rumble API. */
|
||||
SDL_HapticEffect rumble_effect; /* Rumble effect. */
|
||||
struct _SDL_Haptic* next; /* pointer to next haptic we have allocated */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
|
|
|
@ -166,6 +166,9 @@ namespace usb_pad
|
|||
"Off", nullptr, nullptr, nullptr, nullptr, SteeringCurveExponentOptions},
|
||||
{SettingInfo::Type::Boolean, "FfbDropoutWorkaround", TRANSLATE_NOOP("USB", "Workaround for Intermittent FFB Loss"),
|
||||
TRANSLATE_NOOP("USB", "Works around bugs in some wheels' firmware that result in brief interruptions in force. Leave this disabled unless you need it, as it has negative side effects on many wheels."),
|
||||
"false"},
|
||||
{SettingInfo::Type::Boolean, "FfbDirectInputHack", TRANSLATE_NOOP("USB", "HACK: Bypass SDL for FFB updates on Windows"),
|
||||
TRANSLATE_NOOP("USB", "Forgive me, SDL. It's not you, it's me. (It's you). Has no effect on non-Windows platforms."),
|
||||
"false"}
|
||||
};
|
||||
|
||||
|
@ -234,6 +237,11 @@ namespace usb_pad
|
|||
const bool use_ffb_dropout_workaround = USB::GetConfigBool(si, port, devname, "FfbDropoutWorkaround", false);
|
||||
mFFdev->use_ffb_dropout_workaround = use_ffb_dropout_workaround;
|
||||
}
|
||||
if (mFFdev != NULL)
|
||||
{
|
||||
const bool bypass_sdl_when_updating = USB::GetConfigBool(si, port, devname, "FfbDirectInputHack", false);
|
||||
mFFdev->bypass_sdl_when_updating = bypass_sdl_when_updating;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -289,6 +289,7 @@ namespace usb_pad
|
|||
virtual void DisableForce(EffectID force) = 0;
|
||||
|
||||
bool use_ffb_dropout_workaround = false;
|
||||
bool bypass_sdl_when_updating = false;
|
||||
};
|
||||
|
||||
struct PadState
|
||||
|
|
Loading…
Reference in New Issue