idz, idac, swdc: fixed rumble effect

This commit is contained in:
Dniel97 2024-10-29 22:06:07 +01:00
parent 66317a0054
commit 892eb2b859
Signed by untrusted user: Dniel97
GPG Key ID: 6180B3C768FB2E08
6 changed files with 156 additions and 195 deletions

View File

@ -250,7 +250,6 @@ constantForceStrength=100
damperStrength=100 damperStrength=100
; Rumble strength, used for road surface effects. ; Rumble strength, used for road surface effects.
; WARNING: THIS WILL CRASH ON FANATEC (maybe even more) WHEELS!
rumbleStrength=100 rumbleStrength=100
; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect. ; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect.
rumbleDuration=1000 rumbleDuration=1000

View File

@ -240,7 +240,6 @@ constantForceStrength=100
damperStrength=100 damperStrength=100
; Rumble strength, used for road surface effects. ; Rumble strength, used for road surface effects.
; WARNING: THIS WILL CRASH ON FANATEC (maybe even more) WHEELS!
rumbleStrength=100 rumbleStrength=100
; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect. ; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect.
rumbleDuration=1000 rumbleDuration=1000

View File

@ -200,7 +200,6 @@ constantForceStrength=100
damperStrength=100 damperStrength=100
; Rumble strength, used for road surface effects. ; Rumble strength, used for road surface effects.
; WARNING: THIS WILL CRASH ON FANATEC (maybe even more) WHEELS!
rumbleStrength=100 rumbleStrength=100
; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect. ; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect.
rumbleDuration=1000 rumbleDuration=1000

View File

@ -37,9 +37,9 @@ HRESULT idac_di_dev_init(
} }
HRESULT idac_di_dev_poll( HRESULT idac_di_dev_poll(
IDirectInputDevice8W *dev, IDirectInputDevice8W *dev,
HWND wnd, HWND wnd,
union idac_di_state *out) union idac_di_state *out)
{ {
HRESULT hr; HRESULT hr;
MSG msg; MSG msg;
@ -59,17 +59,14 @@ HRESULT idac_di_dev_poll(
} }
hr = IDirectInputDevice8_GetDeviceState( hr = IDirectInputDevice8_GetDeviceState(
dev, dev,
sizeof(out->st), sizeof(out->st),
&out->st); &out->st);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: GetDeviceState error: %08x\n", (int) hr); dprintf("DirectInput: GetDeviceState error: %08x\n", (int)hr);
} }
/* JVS lacks a protocol for reporting hardware errors from poll command
responses, so this ends up returning zeroed input state instead. */
return hr; return hr;
} }
@ -80,29 +77,26 @@ HRESULT idac_di_dev_start(IDirectInputDevice8W *dev, HWND wnd) {
assert(wnd != NULL); assert(wnd != NULL);
hr = IDirectInputDevice8_SetCooperativeLevel( hr = IDirectInputDevice8_SetCooperativeLevel(
dev, dev,
wnd, wnd,
DISCL_BACKGROUND | DISCL_EXCLUSIVE); DISCL_BACKGROUND | DISCL_EXCLUSIVE);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: SetCooperativeLevel failed: %08x\n", (int) hr); dprintf("DirectInput: SetCooperativeLevel failed: %08x\n", (int)hr);
return hr; return hr;
} }
hr = IDirectInputDevice8_SetDataFormat(dev, &c_dfDIJoystick); hr = IDirectInputDevice8_SetDataFormat(dev, &c_dfDIJoystick);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: SetDataFormat failed: %08x\n", (int) hr); dprintf("DirectInput: SetDataFormat failed: %08x\n", (int)hr);
return hr; return hr;
} }
hr = IDirectInputDevice8_Acquire(dev); hr = IDirectInputDevice8_Acquire(dev);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Acquire failed: %08x\n", (int) hr); dprintf("DirectInput: Acquire failed: %08x\n", (int)hr);
return hr; return hr;
} }
@ -168,7 +162,6 @@ void idac_di_ffb_constant_force(uint8_t direction_ffb, uint8_t force)
cf.lMagnitude = (direction_ffb == 0) ? -magnitude : magnitude; cf.lMagnitude = (direction_ffb == 0) ? -magnitude : magnitude;
axis = DIJOFS_X; axis = DIJOFS_X;
/* Irrelevant as magnitude descripbes the direction */
direction = 0; direction = 0;
memset(&fx, 0, sizeof(fx)); memset(&fx, 0, sizeof(fx));
@ -184,38 +177,38 @@ void idac_di_ffb_constant_force(uint8_t direction_ffb, uint8_t force)
fx.cbTypeSpecificParams = sizeof(cf); fx.cbTypeSpecificParams = sizeof(cf);
fx.lpvTypeSpecificParams = &cf; fx.lpvTypeSpecificParams = &cf;
/* Check if the effect already exists */
if (idac_di_fx != NULL) { if (idac_di_fx != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(idac_di_fx, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(idac_di_fx, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return; // Successfully updated existing effect
} else { }
else {
dprintf("DirectInput: Failed to update constant force feedback, recreating effect: %08x\n", (int)hr); dprintf("DirectInput: Failed to update constant force feedback, recreating effect: %08x\n", (int)hr);
// Stop and release the current effect if updating fails
IDirectInputEffect_Stop(idac_di_fx); IDirectInputEffect_Stop(idac_di_fx);
IDirectInputEffect_Release(idac_di_fx); IDirectInputEffect_Release(idac_di_fx);
idac_di_fx = NULL; idac_di_fx = NULL; // Reset the pointer
} }
} }
// Create a new constant force effect /* Create a new constant force effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
idac_di_dev, idac_di_dev,
&GUID_ConstantForce, &GUID_ConstantForce,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Constant force feedback creation failed: %08x\n", (int) hr); dprintf("DirectInput: Constant force feedback creation failed: %08x\n", (int)hr);
return; return;
} }
/* Start the effect */
hr = IDirectInputEffect_Start(obj, INFINITE, 0); hr = IDirectInputEffect_Start(obj, INFINITE, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Constant force feedback start failed: %08x\n", (int) hr); dprintf("DirectInput: Constant force feedback start failed: %08x\n", (int)hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }
@ -239,9 +232,6 @@ void idac_di_ffb_rumble(uint8_t force, uint8_t period)
DIPERIODIC pe; DIPERIODIC pe;
HRESULT hr; HRESULT hr;
/* Duration in microseconds,
Might be totally wrong as especially on FANATEC wheels as this code will
crash the game. TODO: Figure out why this effect will crash on FANATEC! */
DWORD duration = (DWORD)((double)force * ffb_duration); DWORD duration = (DWORD)((double)force * ffb_duration);
memset(&pe, 0, sizeof(pe)); memset(&pe, 0, sizeof(pe));
@ -256,7 +246,7 @@ void idac_di_ffb_rumble(uint8_t force, uint8_t period)
memset(&fx, 0, sizeof(fx)); memset(&fx, 0, sizeof(fx));
fx.dwSize = sizeof(fx); fx.dwSize = sizeof(fx);
fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
fx.dwDuration = duration; fx.dwDuration = INFINITE;
fx.dwGain = DI_FFNOMINALMAX; fx.dwGain = DI_FFNOMINALMAX;
fx.dwTriggerButton = DIEB_NOTRIGGER; fx.dwTriggerButton = DIEB_NOTRIGGER;
fx.dwTriggerRepeatInterval = INFINITE; fx.dwTriggerRepeatInterval = INFINITE;
@ -266,37 +256,38 @@ void idac_di_ffb_rumble(uint8_t force, uint8_t period)
fx.cbTypeSpecificParams = sizeof(pe); fx.cbTypeSpecificParams = sizeof(pe);
fx.lpvTypeSpecificParams = &pe; fx.lpvTypeSpecificParams = &pe;
/* Check if the effect already exists */
if (idac_di_fx_rumble != NULL) { if (idac_di_fx_rumble != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(idac_di_fx_rumble, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(idac_di_fx_rumble, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return;
} else { }
dprintf("DirectInput: Failed to update periodic force feedback, recreating effect: %08x\n", (int)hr); else {
// Stop and release the current effect if updating fails dprintf("DirectInput: Failed to update rumble feedback, recreating effect: %08x\n", (int)hr);
IDirectInputEffect_Stop(idac_di_fx_rumble); IDirectInputEffect_Stop(idac_di_fx_rumble);
IDirectInputEffect_Release(idac_di_fx_rumble); IDirectInputEffect_Release(idac_di_fx_rumble);
idac_di_fx_rumble = NULL; idac_di_fx_rumble = NULL;
} }
} }
/* Create a new rumble effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
idac_di_dev, idac_di_dev,
&GUID_Sine, &GUID_Sine,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Periodic force feedback creation failed: %08x\n", (int) hr); dprintf("DirectInput: Rumble effect creation failed: %08x\n", (int)hr);
return; return;
} }
/* Start the effect */
hr = IDirectInputEffect_Start(obj, INFINITE, 0); hr = IDirectInputEffect_Start(obj, INFINITE, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Periodic force feedback start failed: %08x\n", (int) hr); dprintf("DirectInput: Rumble effect start failed: %08x\n", (int)hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }
@ -343,38 +334,35 @@ void idac_di_ffb_damper(uint8_t force)
fx.cbTypeSpecificParams = sizeof(cond); fx.cbTypeSpecificParams = sizeof(cond);
fx.lpvTypeSpecificParams = &cond; fx.lpvTypeSpecificParams = &cond;
/* Check if the damper effect already exists */
if (idac_di_fx_damper != NULL) { if (idac_di_fx_damper != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(idac_di_fx_damper, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(idac_di_fx_damper, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return;
} else { }
dprintf("DirectInput: Failed to update damper force feedback, recreating effect: %08x\n", (int)hr); else {
// Stop and release the current effect if updating fails
IDirectInputEffect_Stop(idac_di_fx_damper); IDirectInputEffect_Stop(idac_di_fx_damper);
IDirectInputEffect_Release(idac_di_fx_damper); IDirectInputEffect_Release(idac_di_fx_damper);
idac_di_fx_damper = NULL; idac_di_fx_damper = NULL;
} }
} }
// Create a new damper force effect /* Create a new damper effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
idac_di_dev, idac_di_dev,
&GUID_Damper, &GUID_Damper,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Damper force feedback creation failed: %08x\n", (int) hr);
return; return;
} }
hr = IDirectInputEffect_Start(obj, INFINITE, 0); /* Start the effect */
hr = IDirectInputEffect_Start(obj, fx.dwDuration, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Damper force feedback start failed: %08x\n", (int) hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }

View File

@ -37,9 +37,9 @@ HRESULT idz_di_dev_init(
} }
HRESULT idz_di_dev_poll( HRESULT idz_di_dev_poll(
IDirectInputDevice8W *dev, IDirectInputDevice8W *dev,
HWND wnd, HWND wnd,
union idz_di_state *out) union idz_di_state *out)
{ {
HRESULT hr; HRESULT hr;
MSG msg; MSG msg;
@ -59,17 +59,14 @@ HRESULT idz_di_dev_poll(
} }
hr = IDirectInputDevice8_GetDeviceState( hr = IDirectInputDevice8_GetDeviceState(
dev, dev,
sizeof(out->st), sizeof(out->st),
&out->st); &out->st);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: GetDeviceState error: %08x\n", (int) hr); dprintf("DirectInput: GetDeviceState error: %08x\n", (int)hr);
} }
/* JVS lacks a protocol for reporting hardware errors from poll command
responses, so this ends up returning zeroed input state instead. */
return hr; return hr;
} }
@ -80,29 +77,26 @@ HRESULT idz_di_dev_start(IDirectInputDevice8W *dev, HWND wnd) {
assert(wnd != NULL); assert(wnd != NULL);
hr = IDirectInputDevice8_SetCooperativeLevel( hr = IDirectInputDevice8_SetCooperativeLevel(
dev, dev,
wnd, wnd,
DISCL_BACKGROUND | DISCL_EXCLUSIVE); DISCL_BACKGROUND | DISCL_EXCLUSIVE);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: SetCooperativeLevel failed: %08x\n", (int) hr); dprintf("DirectInput: SetCooperativeLevel failed: %08x\n", (int)hr);
return hr; return hr;
} }
hr = IDirectInputDevice8_SetDataFormat(dev, &c_dfDIJoystick); hr = IDirectInputDevice8_SetDataFormat(dev, &c_dfDIJoystick);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: SetDataFormat failed: %08x\n", (int) hr); dprintf("DirectInput: SetDataFormat failed: %08x\n", (int)hr);
return hr; return hr;
} }
hr = IDirectInputDevice8_Acquire(dev); hr = IDirectInputDevice8_Acquire(dev);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Acquire failed: %08x\n", (int) hr); dprintf("DirectInput: Acquire failed: %08x\n", (int)hr);
return hr; return hr;
} }
@ -168,7 +162,6 @@ void idz_di_ffb_constant_force(uint8_t direction_ffb, uint8_t force)
cf.lMagnitude = (direction_ffb == 0) ? -magnitude : magnitude; cf.lMagnitude = (direction_ffb == 0) ? -magnitude : magnitude;
axis = DIJOFS_X; axis = DIJOFS_X;
/* Irrelevant as magnitude descripbes the direction */
direction = 0; direction = 0;
memset(&fx, 0, sizeof(fx)); memset(&fx, 0, sizeof(fx));
@ -184,38 +177,38 @@ void idz_di_ffb_constant_force(uint8_t direction_ffb, uint8_t force)
fx.cbTypeSpecificParams = sizeof(cf); fx.cbTypeSpecificParams = sizeof(cf);
fx.lpvTypeSpecificParams = &cf; fx.lpvTypeSpecificParams = &cf;
/* Check if the effect already exists */
if (idz_di_fx != NULL) { if (idz_di_fx != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(idz_di_fx, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(idz_di_fx, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return; // Successfully updated existing effect
} else { }
else {
dprintf("DirectInput: Failed to update constant force feedback, recreating effect: %08x\n", (int)hr); dprintf("DirectInput: Failed to update constant force feedback, recreating effect: %08x\n", (int)hr);
// Stop and release the current effect if updating fails
IDirectInputEffect_Stop(idz_di_fx); IDirectInputEffect_Stop(idz_di_fx);
IDirectInputEffect_Release(idz_di_fx); IDirectInputEffect_Release(idz_di_fx);
idz_di_fx = NULL; idz_di_fx = NULL; // Reset the pointer
} }
} }
// Create a new constant force effect /* Create a new constant force effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
idz_di_dev, idz_di_dev,
&GUID_ConstantForce, &GUID_ConstantForce,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Constant force feedback creation failed: %08x\n", (int) hr); dprintf("DirectInput: Constant force feedback creation failed: %08x\n", (int)hr);
return; return;
} }
/* Start the effect */
hr = IDirectInputEffect_Start(obj, INFINITE, 0); hr = IDirectInputEffect_Start(obj, INFINITE, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Constant force feedback start failed: %08x\n", (int) hr); dprintf("DirectInput: Constant force feedback start failed: %08x\n", (int)hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }
@ -239,9 +232,6 @@ void idz_di_ffb_rumble(uint8_t force, uint8_t period)
DIPERIODIC pe; DIPERIODIC pe;
HRESULT hr; HRESULT hr;
/* Duration in microseconds,
Might be totally wrong as especially on FANATEC wheels as this code will
crash the game. TODO: Figure out why this effect will crash on FANATEC! */
DWORD duration = (DWORD)((double)force * ffb_duration); DWORD duration = (DWORD)((double)force * ffb_duration);
memset(&pe, 0, sizeof(pe)); memset(&pe, 0, sizeof(pe));
@ -256,7 +246,7 @@ void idz_di_ffb_rumble(uint8_t force, uint8_t period)
memset(&fx, 0, sizeof(fx)); memset(&fx, 0, sizeof(fx));
fx.dwSize = sizeof(fx); fx.dwSize = sizeof(fx);
fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
fx.dwDuration = duration; fx.dwDuration = INFINITE;
fx.dwGain = DI_FFNOMINALMAX; fx.dwGain = DI_FFNOMINALMAX;
fx.dwTriggerButton = DIEB_NOTRIGGER; fx.dwTriggerButton = DIEB_NOTRIGGER;
fx.dwTriggerRepeatInterval = INFINITE; fx.dwTriggerRepeatInterval = INFINITE;
@ -266,37 +256,38 @@ void idz_di_ffb_rumble(uint8_t force, uint8_t period)
fx.cbTypeSpecificParams = sizeof(pe); fx.cbTypeSpecificParams = sizeof(pe);
fx.lpvTypeSpecificParams = &pe; fx.lpvTypeSpecificParams = &pe;
/* Check if the effect already exists */
if (idz_di_fx_rumble != NULL) { if (idz_di_fx_rumble != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(idz_di_fx_rumble, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(idz_di_fx_rumble, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return;
} else { }
dprintf("DirectInput: Failed to update periodic force feedback, recreating effect: %08x\n", (int)hr); else {
// Stop and release the current effect if updating fails dprintf("DirectInput: Failed to update rumble feedback, recreating effect: %08x\n", (int)hr);
IDirectInputEffect_Stop(idz_di_fx_rumble); IDirectInputEffect_Stop(idz_di_fx_rumble);
IDirectInputEffect_Release(idz_di_fx_rumble); IDirectInputEffect_Release(idz_di_fx_rumble);
idz_di_fx_rumble = NULL; idz_di_fx_rumble = NULL;
} }
} }
/* Create a new rumble effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
idz_di_dev, idz_di_dev,
&GUID_Sine, &GUID_Sine,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Periodic force feedback creation failed: %08x\n", (int) hr); dprintf("DirectInput: Rumble effect creation failed: %08x\n", (int)hr);
return; return;
} }
/* Start the effect */
hr = IDirectInputEffect_Start(obj, INFINITE, 0); hr = IDirectInputEffect_Start(obj, INFINITE, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Periodic force feedback start failed: %08x\n", (int) hr); dprintf("DirectInput: Rumble effect start failed: %08x\n", (int)hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }
@ -343,38 +334,35 @@ void idz_di_ffb_damper(uint8_t force)
fx.cbTypeSpecificParams = sizeof(cond); fx.cbTypeSpecificParams = sizeof(cond);
fx.lpvTypeSpecificParams = &cond; fx.lpvTypeSpecificParams = &cond;
/* Check if the damper effect already exists */
if (idz_di_fx_damper != NULL) { if (idz_di_fx_damper != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(idz_di_fx_damper, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(idz_di_fx_damper, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return;
} else { }
dprintf("DirectInput: Failed to update damper force feedback, recreating effect: %08x\n", (int)hr); else {
// Stop and release the current effect if updating fails
IDirectInputEffect_Stop(idz_di_fx_damper); IDirectInputEffect_Stop(idz_di_fx_damper);
IDirectInputEffect_Release(idz_di_fx_damper); IDirectInputEffect_Release(idz_di_fx_damper);
idz_di_fx_damper = NULL; idz_di_fx_damper = NULL;
} }
} }
// Create a new damper force effect /* Create a new damper effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
idz_di_dev, idz_di_dev,
&GUID_Damper, &GUID_Damper,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Damper force feedback creation failed: %08x\n", (int) hr);
return; return;
} }
hr = IDirectInputEffect_Start(obj, INFINITE, 0); /* Start the effect */
hr = IDirectInputEffect_Start(obj, fx.dwDuration, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Damper force feedback start failed: %08x\n", (int) hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }

View File

@ -37,9 +37,9 @@ HRESULT swdc_di_dev_init(
} }
HRESULT swdc_di_dev_poll( HRESULT swdc_di_dev_poll(
IDirectInputDevice8W *dev, IDirectInputDevice8W *dev,
HWND wnd, HWND wnd,
union swdc_di_state *out) union swdc_di_state *out)
{ {
HRESULT hr; HRESULT hr;
MSG msg; MSG msg;
@ -59,17 +59,14 @@ HRESULT swdc_di_dev_poll(
} }
hr = IDirectInputDevice8_GetDeviceState( hr = IDirectInputDevice8_GetDeviceState(
dev, dev,
sizeof(out->st), sizeof(out->st),
&out->st); &out->st);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: GetDeviceState error: %08x\n", (int) hr); dprintf("DirectInput: GetDeviceState error: %08x\n", (int)hr);
} }
/* JVS lacks a protocol for reporting hardware errors from poll command
responses, so this ends up returning zeroed input state instead. */
return hr; return hr;
} }
@ -80,29 +77,26 @@ HRESULT swdc_di_dev_start(IDirectInputDevice8W *dev, HWND wnd) {
assert(wnd != NULL); assert(wnd != NULL);
hr = IDirectInputDevice8_SetCooperativeLevel( hr = IDirectInputDevice8_SetCooperativeLevel(
dev, dev,
wnd, wnd,
DISCL_BACKGROUND | DISCL_EXCLUSIVE); DISCL_BACKGROUND | DISCL_EXCLUSIVE);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: SetCooperativeLevel failed: %08x\n", (int) hr); dprintf("DirectInput: SetCooperativeLevel failed: %08x\n", (int)hr);
return hr; return hr;
} }
hr = IDirectInputDevice8_SetDataFormat(dev, &c_dfDIJoystick); hr = IDirectInputDevice8_SetDataFormat(dev, &c_dfDIJoystick);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: SetDataFormat failed: %08x\n", (int) hr); dprintf("DirectInput: SetDataFormat failed: %08x\n", (int)hr);
return hr; return hr;
} }
hr = IDirectInputDevice8_Acquire(dev); hr = IDirectInputDevice8_Acquire(dev);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Acquire failed: %08x\n", (int) hr); dprintf("DirectInput: Acquire failed: %08x\n", (int)hr);
return hr; return hr;
} }
@ -168,7 +162,6 @@ void swdc_di_ffb_constant_force(uint8_t direction_ffb, uint8_t force)
cf.lMagnitude = (direction_ffb == 0) ? -magnitude : magnitude; cf.lMagnitude = (direction_ffb == 0) ? -magnitude : magnitude;
axis = DIJOFS_X; axis = DIJOFS_X;
/* Irrelevant as magnitude descripbes the direction */
direction = 0; direction = 0;
memset(&fx, 0, sizeof(fx)); memset(&fx, 0, sizeof(fx));
@ -184,38 +177,38 @@ void swdc_di_ffb_constant_force(uint8_t direction_ffb, uint8_t force)
fx.cbTypeSpecificParams = sizeof(cf); fx.cbTypeSpecificParams = sizeof(cf);
fx.lpvTypeSpecificParams = &cf; fx.lpvTypeSpecificParams = &cf;
/* Check if the effect already exists */
if (swdc_di_fx != NULL) { if (swdc_di_fx != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(swdc_di_fx, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(swdc_di_fx, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return; // Successfully updated existing effect
} else { }
else {
dprintf("DirectInput: Failed to update constant force feedback, recreating effect: %08x\n", (int)hr); dprintf("DirectInput: Failed to update constant force feedback, recreating effect: %08x\n", (int)hr);
// Stop and release the current effect if updating fails
IDirectInputEffect_Stop(swdc_di_fx); IDirectInputEffect_Stop(swdc_di_fx);
IDirectInputEffect_Release(swdc_di_fx); IDirectInputEffect_Release(swdc_di_fx);
swdc_di_fx = NULL; swdc_di_fx = NULL; // Reset the pointer
} }
} }
// Create a new constant force effect /* Create a new constant force effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
swdc_di_dev, swdc_di_dev,
&GUID_ConstantForce, &GUID_ConstantForce,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Constant force feedback creation failed: %08x\n", (int) hr); dprintf("DirectInput: Constant force feedback creation failed: %08x\n", (int)hr);
return; return;
} }
/* Start the effect */
hr = IDirectInputEffect_Start(obj, INFINITE, 0); hr = IDirectInputEffect_Start(obj, INFINITE, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Constant force feedback start failed: %08x\n", (int) hr); dprintf("DirectInput: Constant force feedback start failed: %08x\n", (int)hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }
@ -239,9 +232,6 @@ void swdc_di_ffb_rumble(uint8_t force, uint8_t period)
DIPERIODIC pe; DIPERIODIC pe;
HRESULT hr; HRESULT hr;
/* Duration in microseconds,
Might be totally wrong as especially on FANATEC wheels as this code will
crash the game. TODO: Figure out why this effect will crash on FANATEC! */
DWORD duration = (DWORD)((double)force * ffb_duration); DWORD duration = (DWORD)((double)force * ffb_duration);
memset(&pe, 0, sizeof(pe)); memset(&pe, 0, sizeof(pe));
@ -256,7 +246,7 @@ void swdc_di_ffb_rumble(uint8_t force, uint8_t period)
memset(&fx, 0, sizeof(fx)); memset(&fx, 0, sizeof(fx));
fx.dwSize = sizeof(fx); fx.dwSize = sizeof(fx);
fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
fx.dwDuration = duration; fx.dwDuration = INFINITE;
fx.dwGain = DI_FFNOMINALMAX; fx.dwGain = DI_FFNOMINALMAX;
fx.dwTriggerButton = DIEB_NOTRIGGER; fx.dwTriggerButton = DIEB_NOTRIGGER;
fx.dwTriggerRepeatInterval = INFINITE; fx.dwTriggerRepeatInterval = INFINITE;
@ -266,37 +256,38 @@ void swdc_di_ffb_rumble(uint8_t force, uint8_t period)
fx.cbTypeSpecificParams = sizeof(pe); fx.cbTypeSpecificParams = sizeof(pe);
fx.lpvTypeSpecificParams = &pe; fx.lpvTypeSpecificParams = &pe;
/* Check if the effect already exists */
if (swdc_di_fx_rumble != NULL) { if (swdc_di_fx_rumble != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(swdc_di_fx_rumble, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(swdc_di_fx_rumble, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return;
} else { }
dprintf("DirectInput: Failed to update periodic force feedback, recreating effect: %08x\n", (int)hr); else {
// Stop and release the current effect if updating fails dprintf("DirectInput: Failed to update rumble feedback, recreating effect: %08x\n", (int)hr);
IDirectInputEffect_Stop(swdc_di_fx_rumble); IDirectInputEffect_Stop(swdc_di_fx_rumble);
IDirectInputEffect_Release(swdc_di_fx_rumble); IDirectInputEffect_Release(swdc_di_fx_rumble);
swdc_di_fx_rumble = NULL; swdc_di_fx_rumble = NULL;
} }
} }
/* Create a new rumble effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
swdc_di_dev, swdc_di_dev,
&GUID_Sine, &GUID_Sine,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Periodic force feedback creation failed: %08x\n", (int) hr); dprintf("DirectInput: Rumble effect creation failed: %08x\n", (int)hr);
return; return;
} }
/* Start the effect */
hr = IDirectInputEffect_Start(obj, INFINITE, 0); hr = IDirectInputEffect_Start(obj, INFINITE, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Periodic force feedback start failed: %08x\n", (int) hr); dprintf("DirectInput: Rumble effect start failed: %08x\n", (int)hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }
@ -343,38 +334,35 @@ void swdc_di_ffb_damper(uint8_t force)
fx.cbTypeSpecificParams = sizeof(cond); fx.cbTypeSpecificParams = sizeof(cond);
fx.lpvTypeSpecificParams = &cond; fx.lpvTypeSpecificParams = &cond;
/* Check if the damper effect already exists */
if (swdc_di_fx_damper != NULL) { if (swdc_di_fx_damper != NULL) {
// Try to update the existing effect
hr = IDirectInputEffect_SetParameters(swdc_di_fx_damper, &fx, DIEP_TYPESPECIFICPARAMS); hr = IDirectInputEffect_SetParameters(swdc_di_fx_damper, &fx, DIEP_TYPESPECIFICPARAMS);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
return; return;
} else { }
dprintf("DirectInput: Failed to update damper force feedback, recreating effect: %08x\n", (int)hr); else {
// Stop and release the current effect if updating fails
IDirectInputEffect_Stop(swdc_di_fx_damper); IDirectInputEffect_Stop(swdc_di_fx_damper);
IDirectInputEffect_Release(swdc_di_fx_damper); IDirectInputEffect_Release(swdc_di_fx_damper);
swdc_di_fx_damper = NULL; swdc_di_fx_damper = NULL;
} }
} }
// Create a new damper force effect /* Create a new damper effect */
IDirectInputEffect *obj; IDirectInputEffect *obj;
hr = IDirectInputDevice8_CreateEffect( hr = IDirectInputDevice8_CreateEffect(
swdc_di_dev, swdc_di_dev,
&GUID_Damper, &GUID_Damper,
&fx, &fx,
&obj, &obj,
NULL); NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Damper force feedback creation failed: %08x\n", (int) hr);
return; return;
} }
hr = IDirectInputEffect_Start(obj, INFINITE, 0); /* Start the effect */
hr = IDirectInputEffect_Start(obj, fx.dwDuration, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
dprintf("DirectInput: Damper force feedback start failed: %08x\n", (int) hr);
IDirectInputEffect_Release(obj); IDirectInputEffect_Release(obj);
return; return;
} }