forked from Dniel97/segatools
idz, idac, swdc: added FFB centering spring feature
This commit is contained in:
parent
4ffcf25555
commit
72db08ac93
7
dist/idac/segatools.ini
vendored
7
dist/idac/segatools.ini
vendored
@ -29,7 +29,7 @@ enable=1
|
|||||||
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||||
; that subnet must start with 192.168. Set it to your LAN's subnet if you
|
; that subnet must start with 192.168. Set it to your LAN's subnet if you
|
||||||
; want to play head-to-head using netenv=1.
|
; want to play head-to-head using netenv=1.
|
||||||
subnet=192.168.100.0
|
subnet=192.168.158.0
|
||||||
|
|
||||||
; Override the keychip's region code. Most games seem to pay attention to the
|
; Override the keychip's region code. Most games seem to pay attention to the
|
||||||
; DS EEPROM region code and not the keychip region code, and this seems to be
|
; DS EEPROM region code and not the keychip region code, and this seems to be
|
||||||
@ -174,3 +174,8 @@ gear6=18
|
|||||||
; (Needed when using DirectInput for the Dualshock 4 for example)
|
; (Needed when using DirectInput for the Dualshock 4 for example)
|
||||||
reverseAccelAxis=0
|
reverseAccelAxis=0
|
||||||
reverseBrakeAxis=0
|
reverseBrakeAxis=0
|
||||||
|
|
||||||
|
; Force feedback settings.
|
||||||
|
; Strength of the force feedback spring effect in percent. Possible values
|
||||||
|
; are 0-100.
|
||||||
|
centerSpringStrength=30
|
||||||
|
5
dist/idz/segatools.ini
vendored
5
dist/idz/segatools.ini
vendored
@ -173,3 +173,8 @@ gear6=18
|
|||||||
; (Needed when using DirectInput for the Dualshock 4 for example)
|
; (Needed when using DirectInput for the Dualshock 4 for example)
|
||||||
reverseAccelAxis=0
|
reverseAccelAxis=0
|
||||||
reverseBrakeAxis=0
|
reverseBrakeAxis=0
|
||||||
|
|
||||||
|
; Force feedback settings.
|
||||||
|
; Strength of the force feedback spring effect in percent. Possible values
|
||||||
|
; are 0-100.
|
||||||
|
centerSpringStrength=30
|
||||||
|
5
dist/swdc/segatools.ini
vendored
5
dist/swdc/segatools.ini
vendored
@ -133,3 +133,8 @@ wheelGreen=10
|
|||||||
; (Needed when using DirectInput for the Dualshock 4 for example)
|
; (Needed when using DirectInput for the Dualshock 4 for example)
|
||||||
reverseAccelAxis=0
|
reverseAccelAxis=0
|
||||||
reverseBrakeAxis=0
|
reverseBrakeAxis=0
|
||||||
|
|
||||||
|
; Force feedback settings.
|
||||||
|
; Strength of the force feedback spring effect in percent. Possible values
|
||||||
|
; are 0-100.
|
||||||
|
centerSpringStrength=30
|
||||||
|
@ -79,6 +79,14 @@ void idac_di_config_load(struct idac_di_config *cfg, const wchar_t *filename)
|
|||||||
cfg->gear[i] = GetPrivateProfileIntW(L"dinput", key, i + 1, filename);
|
cfg->gear[i] = GetPrivateProfileIntW(L"dinput", key, i + 1, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
|
||||||
|
cfg->center_spring_strength = GetPrivateProfileIntW(
|
||||||
|
L"dinput",
|
||||||
|
L"centerSpringStrength",
|
||||||
|
30,
|
||||||
|
filename);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_xi_config_load(struct idac_xi_config *cfg, const wchar_t *filename)
|
void idac_xi_config_load(struct idac_xi_config *cfg, const wchar_t *filename)
|
||||||
|
@ -23,6 +23,9 @@ struct idac_di_config {
|
|||||||
uint8_t gear[6];
|
uint8_t gear[6];
|
||||||
bool reverse_brake_axis;
|
bool reverse_brake_axis;
|
||||||
bool reverse_accel_axis;
|
bool reverse_accel_axis;
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
uint16_t center_spring_strength;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct idac_xi_config {
|
struct idac_xi_config {
|
||||||
|
@ -44,7 +44,8 @@ HRESULT idac_di_dev_start(IDirectInputDevice8W *dev, HWND wnd)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
void idac_di_dev_start_fx(
|
||||||
|
IDirectInputDevice8W *dev, IDirectInputEffect **out, uint16_t strength)
|
||||||
{
|
{
|
||||||
/* Set up force-feedback on devices that support it. This is just a stub
|
/* Set up force-feedback on devices that support it. This is just a stub
|
||||||
for the time being, since we don't yet know how the serial port force
|
for the time being, since we don't yet know how the serial port force
|
||||||
@ -67,7 +68,7 @@ void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
DWORD axis;
|
DWORD axis;
|
||||||
LONG direction;
|
LONG direction;
|
||||||
DIEFFECT fx;
|
DIEFFECT fx;
|
||||||
DICONSTANTFORCE cf;
|
DICONDITION cond;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
assert(dev != NULL);
|
assert(dev != NULL);
|
||||||
@ -77,11 +78,17 @@ void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
|
|
||||||
dprintf("DirectInput: Starting force feedback (may take a sec)\n");
|
dprintf("DirectInput: Starting force feedback (may take a sec)\n");
|
||||||
|
|
||||||
|
// Auto-centering effect
|
||||||
axis = DIJOFS_X;
|
axis = DIJOFS_X;
|
||||||
direction = 0;
|
direction = 0;
|
||||||
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
memset(&cond, 0, sizeof(cond));
|
||||||
cf.lMagnitude = 0;
|
cond.lOffset = 0;
|
||||||
|
cond.lPositiveCoefficient = strength;
|
||||||
|
cond.lNegativeCoefficient = strength;
|
||||||
|
cond.dwPositiveSaturation = strength; // For FG920?
|
||||||
|
cond.dwNegativeSaturation = strength; // For FG920?
|
||||||
|
cond.lDeadBand = 0;
|
||||||
|
|
||||||
memset(&fx, 0, sizeof(fx));
|
memset(&fx, 0, sizeof(fx));
|
||||||
fx.dwSize = sizeof(fx);
|
fx.dwSize = sizeof(fx);
|
||||||
@ -93,20 +100,19 @@ void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
fx.cAxes = 1;
|
fx.cAxes = 1;
|
||||||
fx.rgdwAxes = &axis;
|
fx.rgdwAxes = &axis;
|
||||||
fx.rglDirection = &direction;
|
fx.rglDirection = &direction;
|
||||||
fx.cbTypeSpecificParams = sizeof(cf);
|
fx.cbTypeSpecificParams = sizeof(cond);
|
||||||
fx.lpvTypeSpecificParams = &cf;
|
fx.lpvTypeSpecificParams = &cond;
|
||||||
|
|
||||||
hr = IDirectInputDevice8_CreateEffect(
|
hr = IDirectInputDevice8_CreateEffect(
|
||||||
dev,
|
dev,
|
||||||
&GUID_ConstantForce,
|
&GUID_Spring,
|
||||||
&fx,
|
&fx,
|
||||||
&obj,
|
&obj,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("DirectInput: DirectInput force feedback unavailable: %08x\n",
|
dprintf("DirectInput: Centering spring force feedback unavailable: %08x\n",
|
||||||
(int) hr);
|
(int) hr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,15 +120,15 @@ void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
IDirectInputEffect_Release(obj);
|
IDirectInputEffect_Release(obj);
|
||||||
dprintf("DirectInput: DirectInput force feedback start failed: %08x\n",
|
dprintf("DirectInput: Centering spring force feedback start failed: %08x\n",
|
||||||
(int) hr);
|
(int) hr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = obj;
|
*out = obj;
|
||||||
|
|
||||||
dprintf("DirectInput: Force feedback initialized and set to zero\n");
|
dprintf("DirectInput: Centering spring effects initialized with strength %d%%\n",
|
||||||
|
strength / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT idac_di_dev_poll(
|
HRESULT idac_di_dev_poll(
|
||||||
|
@ -11,7 +11,7 @@ union idac_di_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HRESULT idac_di_dev_start(IDirectInputDevice8W *dev, HWND wnd);
|
HRESULT idac_di_dev_start(IDirectInputDevice8W *dev, HWND wnd);
|
||||||
void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out);
|
void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out, uint16_t strength);
|
||||||
HRESULT idac_di_dev_poll(
|
HRESULT idac_di_dev_poll(
|
||||||
IDirectInputDevice8W *dev,
|
IDirectInputDevice8W *dev,
|
||||||
HWND wnd,
|
HWND wnd,
|
||||||
|
15
idacio/di.c
15
idacio/di.c
@ -75,6 +75,7 @@ static uint8_t idac_di_gear[6];
|
|||||||
static bool idac_di_use_pedals;
|
static bool idac_di_use_pedals;
|
||||||
static bool idac_di_reverse_brake_axis;
|
static bool idac_di_reverse_brake_axis;
|
||||||
static bool idac_di_reverse_accel_axis;
|
static bool idac_di_reverse_accel_axis;
|
||||||
|
static uint16_t idac_di_center_spring_strength;
|
||||||
|
|
||||||
HRESULT idac_di_init(
|
HRESULT idac_di_init(
|
||||||
const struct idac_di_config *cfg,
|
const struct idac_di_config *cfg,
|
||||||
@ -173,7 +174,9 @@ HRESULT idac_di_init(
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
idac_di_dev_start_fx(idac_di_dev, &idac_di_fx);
|
// Convert the strength from 0-100 to 0-10000 for DirectInput
|
||||||
|
idac_di_dev_start_fx(idac_di_dev, &idac_di_fx,
|
||||||
|
idac_di_center_spring_strength * 100);
|
||||||
|
|
||||||
if (cfg->pedals_name[0] != L'\0') {
|
if (cfg->pedals_name[0] != L'\0') {
|
||||||
hr = IDirectInput8_EnumDevices(
|
hr = IDirectInput8_EnumDevices(
|
||||||
@ -364,6 +367,16 @@ static HRESULT idac_di_config_apply(const struct idac_di_config *cfg)
|
|||||||
idac_di_gear[i] = cfg->gear[i];
|
idac_di_gear[i] = cfg->gear[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
|
||||||
|
if (cfg->center_spring_strength < 0 || cfg->center_spring_strength > 100) {
|
||||||
|
dprintf("Wheel: Invalid center spring strength: %i\n", cfg->center_spring_strength);
|
||||||
|
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
idac_di_center_spring_strength = cfg->center_spring_strength;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,13 @@ void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename)
|
|||||||
cfg->gear[i] = GetPrivateProfileIntW(L"dinput", key, i + 1, filename);
|
cfg->gear[i] = GetPrivateProfileIntW(L"dinput", key, i + 1, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
|
||||||
|
cfg->center_spring_strength = GetPrivateProfileIntW(
|
||||||
|
L"dinput",
|
||||||
|
L"centerSpringStrength",
|
||||||
|
30,
|
||||||
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void idz_xi_config_load(struct idz_xi_config *cfg, const wchar_t *filename)
|
void idz_xi_config_load(struct idz_xi_config *cfg, const wchar_t *filename)
|
||||||
|
@ -21,6 +21,9 @@ struct idz_di_config {
|
|||||||
uint8_t gear[6];
|
uint8_t gear[6];
|
||||||
bool reverse_brake_axis;
|
bool reverse_brake_axis;
|
||||||
bool reverse_accel_axis;
|
bool reverse_accel_axis;
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
uint16_t center_spring_strength;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct idz_xi_config {
|
struct idz_xi_config {
|
||||||
|
@ -44,7 +44,8 @@ HRESULT idz_di_dev_start(IDirectInputDevice8W *dev, HWND wnd)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
void idz_di_dev_start_fx(
|
||||||
|
IDirectInputDevice8W *dev, IDirectInputEffect **out, uint16_t strength)
|
||||||
{
|
{
|
||||||
/* Set up force-feedback on devices that support it. This is just a stub
|
/* Set up force-feedback on devices that support it. This is just a stub
|
||||||
for the time being, since we don't yet know how the serial port force
|
for the time being, since we don't yet know how the serial port force
|
||||||
@ -67,7 +68,7 @@ void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
DWORD axis;
|
DWORD axis;
|
||||||
LONG direction;
|
LONG direction;
|
||||||
DIEFFECT fx;
|
DIEFFECT fx;
|
||||||
DICONSTANTFORCE cf;
|
DICONDITION cond;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
assert(dev != NULL);
|
assert(dev != NULL);
|
||||||
@ -77,11 +78,17 @@ void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
|
|
||||||
dprintf("DirectInput: Starting force feedback (may take a sec)\n");
|
dprintf("DirectInput: Starting force feedback (may take a sec)\n");
|
||||||
|
|
||||||
|
// Auto-centering effect
|
||||||
axis = DIJOFS_X;
|
axis = DIJOFS_X;
|
||||||
direction = 0;
|
direction = 0;
|
||||||
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
memset(&cond, 0, sizeof(cond));
|
||||||
cf.lMagnitude = 0;
|
cond.lOffset = 0;
|
||||||
|
cond.lPositiveCoefficient = strength;
|
||||||
|
cond.lNegativeCoefficient = strength;
|
||||||
|
cond.dwPositiveSaturation = strength; // For FG920?
|
||||||
|
cond.dwNegativeSaturation = strength; // For FG920?
|
||||||
|
cond.lDeadBand = 0;
|
||||||
|
|
||||||
memset(&fx, 0, sizeof(fx));
|
memset(&fx, 0, sizeof(fx));
|
||||||
fx.dwSize = sizeof(fx);
|
fx.dwSize = sizeof(fx);
|
||||||
@ -93,20 +100,19 @@ void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
fx.cAxes = 1;
|
fx.cAxes = 1;
|
||||||
fx.rgdwAxes = &axis;
|
fx.rgdwAxes = &axis;
|
||||||
fx.rglDirection = &direction;
|
fx.rglDirection = &direction;
|
||||||
fx.cbTypeSpecificParams = sizeof(cf);
|
fx.cbTypeSpecificParams = sizeof(cond);
|
||||||
fx.lpvTypeSpecificParams = &cf;
|
fx.lpvTypeSpecificParams = &cond;
|
||||||
|
|
||||||
hr = IDirectInputDevice8_CreateEffect(
|
hr = IDirectInputDevice8_CreateEffect(
|
||||||
dev,
|
dev,
|
||||||
&GUID_ConstantForce,
|
&GUID_Spring,
|
||||||
&fx,
|
&fx,
|
||||||
&obj,
|
&obj,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("DirectInput: DirectInput force feedback unavailable: %08x\n",
|
dprintf("DirectInput: Centering spring force feedback unavailable: %08x\n",
|
||||||
(int) hr);
|
(int) hr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,15 +120,15 @@ void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
IDirectInputEffect_Release(obj);
|
IDirectInputEffect_Release(obj);
|
||||||
dprintf("DirectInput: DirectInput force feedback start failed: %08x\n",
|
dprintf("DirectInput: Centering spring force feedback start failed: %08x\n",
|
||||||
(int) hr);
|
(int) hr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = obj;
|
*out = obj;
|
||||||
|
|
||||||
dprintf("DirectInput: Force feedback initialized and set to zero\n");
|
dprintf("DirectInput: Centering spring effects initialized with strength %d%%\n",
|
||||||
|
strength / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT idz_di_dev_poll(
|
HRESULT idz_di_dev_poll(
|
||||||
|
@ -11,7 +11,7 @@ union idz_di_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HRESULT idz_di_dev_start(IDirectInputDevice8W *dev, HWND wnd);
|
HRESULT idz_di_dev_start(IDirectInputDevice8W *dev, HWND wnd);
|
||||||
void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out);
|
void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out, uint16_t strength);
|
||||||
HRESULT idz_di_dev_poll(
|
HRESULT idz_di_dev_poll(
|
||||||
IDirectInputDevice8W *dev,
|
IDirectInputDevice8W *dev,
|
||||||
HWND wnd,
|
HWND wnd,
|
||||||
|
15
idzio/di.c
15
idzio/di.c
@ -73,6 +73,7 @@ static uint8_t idz_di_gear[6];
|
|||||||
static bool idz_di_use_pedals;
|
static bool idz_di_use_pedals;
|
||||||
static bool idz_di_reverse_brake_axis;
|
static bool idz_di_reverse_brake_axis;
|
||||||
static bool idz_di_reverse_accel_axis;
|
static bool idz_di_reverse_accel_axis;
|
||||||
|
static uint16_t idz_di_center_spring_strength;
|
||||||
|
|
||||||
HRESULT idz_di_init(
|
HRESULT idz_di_init(
|
||||||
const struct idz_di_config *cfg,
|
const struct idz_di_config *cfg,
|
||||||
@ -171,7 +172,9 @@ HRESULT idz_di_init(
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
idz_di_dev_start_fx(idz_di_dev, &idz_di_fx);
|
// Convert the strength from 0-100 to 0-10000 for DirectInput
|
||||||
|
idz_di_dev_start_fx(idz_di_dev, &idz_di_fx,
|
||||||
|
idz_di_center_spring_strength * 100);
|
||||||
|
|
||||||
if (cfg->pedals_name[0] != L'\0') {
|
if (cfg->pedals_name[0] != L'\0') {
|
||||||
hr = IDirectInput8_EnumDevices(
|
hr = IDirectInput8_EnumDevices(
|
||||||
@ -346,6 +349,16 @@ static HRESULT idz_di_config_apply(const struct idz_di_config *cfg)
|
|||||||
idz_di_gear[i] = cfg->gear[i];
|
idz_di_gear[i] = cfg->gear[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
|
||||||
|
if (cfg->center_spring_strength < 0 || cfg->center_spring_strength > 100) {
|
||||||
|
dprintf("Wheel: Invalid center spring strength: %i\n", cfg->center_spring_strength);
|
||||||
|
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
idz_di_center_spring_strength = cfg->center_spring_strength;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,14 @@ void swdc_di_config_load(struct swdc_di_config *cfg, const wchar_t *filename)
|
|||||||
L"reverseAccelAxis",
|
L"reverseAccelAxis",
|
||||||
0,
|
0,
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
|
||||||
|
cfg->center_spring_strength = GetPrivateProfileIntW(
|
||||||
|
L"dinput",
|
||||||
|
L"centerSpringStrength",
|
||||||
|
30,
|
||||||
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swdc_xi_config_load(struct swdc_xi_config *cfg, const wchar_t *filename)
|
void swdc_xi_config_load(struct swdc_xi_config *cfg, const wchar_t *filename)
|
||||||
|
@ -19,6 +19,9 @@ struct swdc_di_config {
|
|||||||
uint8_t wheel_yellow;
|
uint8_t wheel_yellow;
|
||||||
bool reverse_brake_axis;
|
bool reverse_brake_axis;
|
||||||
bool reverse_accel_axis;
|
bool reverse_accel_axis;
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
uint16_t center_spring_strength;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct swdc_xi_config {
|
struct swdc_xi_config {
|
||||||
|
@ -44,7 +44,8 @@ HRESULT swdc_di_dev_start(IDirectInputDevice8W *dev, HWND wnd)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
void swdc_di_dev_start_fx(
|
||||||
|
IDirectInputDevice8W *dev, IDirectInputEffect **out, uint16_t strength)
|
||||||
{
|
{
|
||||||
/* Set up force-feedback on devices that support it. This is just a stub
|
/* Set up force-feedback on devices that support it. This is just a stub
|
||||||
for the time being, since we don't yet know how the serial port force
|
for the time being, since we don't yet know how the serial port force
|
||||||
@ -67,7 +68,7 @@ void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
DWORD axis;
|
DWORD axis;
|
||||||
LONG direction;
|
LONG direction;
|
||||||
DIEFFECT fx;
|
DIEFFECT fx;
|
||||||
DICONSTANTFORCE cf;
|
DICONDITION cond;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
assert(dev != NULL);
|
assert(dev != NULL);
|
||||||
@ -77,11 +78,17 @@ void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
|
|
||||||
dprintf("DirectInput: Starting force feedback (may take a sec)\n");
|
dprintf("DirectInput: Starting force feedback (may take a sec)\n");
|
||||||
|
|
||||||
|
// Auto-centering effect
|
||||||
axis = DIJOFS_X;
|
axis = DIJOFS_X;
|
||||||
direction = 0;
|
direction = 0;
|
||||||
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
memset(&cond, 0, sizeof(cond));
|
||||||
cf.lMagnitude = 0;
|
cond.lOffset = 0;
|
||||||
|
cond.lPositiveCoefficient = strength;
|
||||||
|
cond.lNegativeCoefficient = strength;
|
||||||
|
cond.dwPositiveSaturation = strength; // For FG920?
|
||||||
|
cond.dwNegativeSaturation = strength; // For FG920?
|
||||||
|
cond.lDeadBand = 0;
|
||||||
|
|
||||||
memset(&fx, 0, sizeof(fx));
|
memset(&fx, 0, sizeof(fx));
|
||||||
fx.dwSize = sizeof(fx);
|
fx.dwSize = sizeof(fx);
|
||||||
@ -93,20 +100,19 @@ void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
fx.cAxes = 1;
|
fx.cAxes = 1;
|
||||||
fx.rgdwAxes = &axis;
|
fx.rgdwAxes = &axis;
|
||||||
fx.rglDirection = &direction;
|
fx.rglDirection = &direction;
|
||||||
fx.cbTypeSpecificParams = sizeof(cf);
|
fx.cbTypeSpecificParams = sizeof(cond);
|
||||||
fx.lpvTypeSpecificParams = &cf;
|
fx.lpvTypeSpecificParams = &cond;
|
||||||
|
|
||||||
hr = IDirectInputDevice8_CreateEffect(
|
hr = IDirectInputDevice8_CreateEffect(
|
||||||
dev,
|
dev,
|
||||||
&GUID_ConstantForce,
|
&GUID_Spring,
|
||||||
&fx,
|
&fx,
|
||||||
&obj,
|
&obj,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("DirectInput: DirectInput force feedback unavailable: %08x\n",
|
dprintf("DirectInput: Centering spring force feedback unavailable: %08x\n",
|
||||||
(int) hr);
|
(int) hr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,15 +120,15 @@ void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out)
|
|||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
IDirectInputEffect_Release(obj);
|
IDirectInputEffect_Release(obj);
|
||||||
dprintf("DirectInput: DirectInput force feedback start failed: %08x\n",
|
dprintf("DirectInput: Centering spring force feedback start failed: %08x\n",
|
||||||
(int) hr);
|
(int) hr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = obj;
|
*out = obj;
|
||||||
|
|
||||||
dprintf("DirectInput: Force feedback initialized and set to zero\n");
|
dprintf("DirectInput: Centering spring effects initialized with strength %d%%\n",
|
||||||
|
strength / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT swdc_di_dev_poll(
|
HRESULT swdc_di_dev_poll(
|
||||||
|
@ -11,7 +11,7 @@ union swdc_di_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HRESULT swdc_di_dev_start(IDirectInputDevice8W *dev, HWND wnd);
|
HRESULT swdc_di_dev_start(IDirectInputDevice8W *dev, HWND wnd);
|
||||||
void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out);
|
void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out, uint16_t strength);
|
||||||
HRESULT swdc_di_dev_poll(
|
HRESULT swdc_di_dev_poll(
|
||||||
IDirectInputDevice8W *dev,
|
IDirectInputDevice8W *dev,
|
||||||
HWND wnd,
|
HWND wnd,
|
||||||
|
15
swdcio/di.c
15
swdcio/di.c
@ -70,6 +70,7 @@ static uint8_t swdc_di_wheel_yellow;
|
|||||||
static bool swdc_di_use_pedals;
|
static bool swdc_di_use_pedals;
|
||||||
static bool swdc_di_reverse_brake_axis;
|
static bool swdc_di_reverse_brake_axis;
|
||||||
static bool swdc_di_reverse_accel_axis;
|
static bool swdc_di_reverse_accel_axis;
|
||||||
|
static uint16_t swdc_di_center_spring_strength;
|
||||||
|
|
||||||
HRESULT swdc_di_init(
|
HRESULT swdc_di_init(
|
||||||
const struct swdc_di_config *cfg,
|
const struct swdc_di_config *cfg,
|
||||||
@ -168,7 +169,9 @@ HRESULT swdc_di_init(
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
swdc_di_dev_start_fx(swdc_di_dev, &swdc_di_fx);
|
// Convert the strength from 0-100 to 0-10000 for DirectInput
|
||||||
|
swdc_di_dev_start_fx(swdc_di_dev, &swdc_di_fx,
|
||||||
|
swdc_di_center_spring_strength * 100);
|
||||||
|
|
||||||
if (cfg->pedals_name[0] != L'\0') {
|
if (cfg->pedals_name[0] != L'\0') {
|
||||||
hr = IDirectInput8_EnumDevices(
|
hr = IDirectInput8_EnumDevices(
|
||||||
@ -320,6 +323,16 @@ static HRESULT swdc_di_config_apply(const struct swdc_di_config *cfg)
|
|||||||
swdc_di_reverse_brake_axis = cfg->reverse_brake_axis;
|
swdc_di_reverse_brake_axis = cfg->reverse_brake_axis;
|
||||||
swdc_di_reverse_accel_axis = cfg->reverse_accel_axis;
|
swdc_di_reverse_accel_axis = cfg->reverse_accel_axis;
|
||||||
|
|
||||||
|
// FFB configuration
|
||||||
|
|
||||||
|
if (cfg->center_spring_strength < 0 || cfg->center_spring_strength > 100) {
|
||||||
|
dprintf("Wheel: Invalid center spring strength: %i\n", cfg->center_spring_strength);
|
||||||
|
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
swdc_di_center_spring_strength = cfg->center_spring_strength;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user