diff --git a/dist/idac/segatools.ini b/dist/idac/segatools.ini index 830f78b..bf9bafc 100644 --- a/dist/idac/segatools.ini +++ b/dist/idac/segatools.ini @@ -29,7 +29,7 @@ enable=1 ; 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 ; 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 ; 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) reverseAccelAxis=0 reverseBrakeAxis=0 + +; Force feedback settings. +; Strength of the force feedback spring effect in percent. Possible values +; are 0-100. +centerSpringStrength=30 diff --git a/dist/idz/segatools.ini b/dist/idz/segatools.ini index c7fa88b..e7b0701 100644 --- a/dist/idz/segatools.ini +++ b/dist/idz/segatools.ini @@ -173,3 +173,8 @@ gear6=18 ; (Needed when using DirectInput for the Dualshock 4 for example) reverseAccelAxis=0 reverseBrakeAxis=0 + +; Force feedback settings. +; Strength of the force feedback spring effect in percent. Possible values +; are 0-100. +centerSpringStrength=30 diff --git a/dist/swdc/segatools.ini b/dist/swdc/segatools.ini index f3867a7..fb93e50 100644 --- a/dist/swdc/segatools.ini +++ b/dist/swdc/segatools.ini @@ -133,3 +133,8 @@ wheelGreen=10 ; (Needed when using DirectInput for the Dualshock 4 for example) reverseAccelAxis=0 reverseBrakeAxis=0 + +; Force feedback settings. +; Strength of the force feedback spring effect in percent. Possible values +; are 0-100. +centerSpringStrength=30 diff --git a/idacio/config.c b/idacio/config.c index f6ed605..2daeb8f 100644 --- a/idacio/config.c +++ b/idacio/config.c @@ -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); } + // 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) diff --git a/idacio/config.h b/idacio/config.h index ec91ce6..bbf568d 100644 --- a/idacio/config.h +++ b/idacio/config.h @@ -23,6 +23,9 @@ struct idac_di_config { uint8_t gear[6]; bool reverse_brake_axis; bool reverse_accel_axis; + + // FFB configuration + uint16_t center_spring_strength; }; struct idac_xi_config { diff --git a/idacio/di-dev.c b/idacio/di-dev.c index c77584b..62cab2f 100644 --- a/idacio/di-dev.c +++ b/idacio/di-dev.c @@ -44,7 +44,8 @@ HRESULT idac_di_dev_start(IDirectInputDevice8W *dev, HWND wnd) 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 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; LONG direction; DIEFFECT fx; - DICONSTANTFORCE cf; + DICONDITION cond; HRESULT hr; 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"); + // Auto-centering effect axis = DIJOFS_X; direction = 0; - memset(&cf, 0, sizeof(cf)); - cf.lMagnitude = 0; + memset(&cond, 0, sizeof(cond)); + 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)); fx.dwSize = sizeof(fx); @@ -93,20 +100,19 @@ void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out) fx.cAxes = 1; fx.rgdwAxes = &axis; fx.rglDirection = &direction; - fx.cbTypeSpecificParams = sizeof(cf); - fx.lpvTypeSpecificParams = &cf; + fx.cbTypeSpecificParams = sizeof(cond); + fx.lpvTypeSpecificParams = &cond; hr = IDirectInputDevice8_CreateEffect( dev, - &GUID_ConstantForce, + &GUID_Spring, &fx, &obj, NULL); if (FAILED(hr)) { - dprintf("DirectInput: DirectInput force feedback unavailable: %08x\n", + dprintf("DirectInput: Centering spring force feedback unavailable: %08x\n", (int) hr); - return; } @@ -114,15 +120,15 @@ void idac_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out) if (FAILED(hr)) { IDirectInputEffect_Release(obj); - dprintf("DirectInput: DirectInput force feedback start failed: %08x\n", + dprintf("DirectInput: Centering spring force feedback start failed: %08x\n", (int) hr); - return; } *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( diff --git a/idacio/di-dev.h b/idacio/di-dev.h index efbe39e..b1559e3 100644 --- a/idacio/di-dev.h +++ b/idacio/di-dev.h @@ -11,7 +11,7 @@ union idac_di_state { }; 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( IDirectInputDevice8W *dev, HWND wnd, diff --git a/idacio/di.c b/idacio/di.c index 75e2c50..55018e8 100644 --- a/idacio/di.c +++ b/idacio/di.c @@ -75,6 +75,7 @@ static uint8_t idac_di_gear[6]; static bool idac_di_use_pedals; static bool idac_di_reverse_brake_axis; static bool idac_di_reverse_accel_axis; +static uint16_t idac_di_center_spring_strength; HRESULT idac_di_init( const struct idac_di_config *cfg, @@ -173,7 +174,9 @@ HRESULT idac_di_init( 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') { 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]; } + // 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; } diff --git a/idzio/config.c b/idzio/config.c index 25b188d..2a6e083 100644 --- a/idzio/config.c +++ b/idzio/config.c @@ -76,7 +76,14 @@ void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename) swprintf_s(key, _countof(key), L"gear%i", i + 1); 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) diff --git a/idzio/config.h b/idzio/config.h index 6b4cd20..155f797 100644 --- a/idzio/config.h +++ b/idzio/config.h @@ -21,6 +21,9 @@ struct idz_di_config { uint8_t gear[6]; bool reverse_brake_axis; bool reverse_accel_axis; + + // FFB configuration + uint16_t center_spring_strength; }; struct idz_xi_config { diff --git a/idzio/di-dev.c b/idzio/di-dev.c index 6f66bf0..26cf6e3 100644 --- a/idzio/di-dev.c +++ b/idzio/di-dev.c @@ -44,7 +44,8 @@ HRESULT idz_di_dev_start(IDirectInputDevice8W *dev, HWND wnd) 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 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; LONG direction; DIEFFECT fx; - DICONSTANTFORCE cf; + DICONDITION cond; HRESULT hr; 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"); + // Auto-centering effect axis = DIJOFS_X; direction = 0; - memset(&cf, 0, sizeof(cf)); - cf.lMagnitude = 0; + memset(&cond, 0, sizeof(cond)); + 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)); fx.dwSize = sizeof(fx); @@ -93,20 +100,19 @@ void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out) fx.cAxes = 1; fx.rgdwAxes = &axis; fx.rglDirection = &direction; - fx.cbTypeSpecificParams = sizeof(cf); - fx.lpvTypeSpecificParams = &cf; + fx.cbTypeSpecificParams = sizeof(cond); + fx.lpvTypeSpecificParams = &cond; hr = IDirectInputDevice8_CreateEffect( dev, - &GUID_ConstantForce, + &GUID_Spring, &fx, &obj, NULL); if (FAILED(hr)) { - dprintf("DirectInput: DirectInput force feedback unavailable: %08x\n", + dprintf("DirectInput: Centering spring force feedback unavailable: %08x\n", (int) hr); - return; } @@ -114,15 +120,15 @@ void idz_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out) if (FAILED(hr)) { IDirectInputEffect_Release(obj); - dprintf("DirectInput: DirectInput force feedback start failed: %08x\n", + dprintf("DirectInput: Centering spring force feedback start failed: %08x\n", (int) hr); - return; } *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( diff --git a/idzio/di-dev.h b/idzio/di-dev.h index 9c8b2d2..9b3d03f 100644 --- a/idzio/di-dev.h +++ b/idzio/di-dev.h @@ -11,7 +11,7 @@ union idz_di_state { }; 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( IDirectInputDevice8W *dev, HWND wnd, diff --git a/idzio/di.c b/idzio/di.c index 5d0a454..e0cb4c6 100644 --- a/idzio/di.c +++ b/idzio/di.c @@ -73,6 +73,7 @@ static uint8_t idz_di_gear[6]; static bool idz_di_use_pedals; static bool idz_di_reverse_brake_axis; static bool idz_di_reverse_accel_axis; +static uint16_t idz_di_center_spring_strength; HRESULT idz_di_init( const struct idz_di_config *cfg, @@ -171,7 +172,9 @@ HRESULT idz_di_init( 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') { 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]; } + // 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; } diff --git a/swdcio/config.c b/swdcio/config.c index 0dce00e..4208c76 100644 --- a/swdcio/config.c +++ b/swdcio/config.c @@ -67,6 +67,14 @@ void swdc_di_config_load(struct swdc_di_config *cfg, const wchar_t *filename) L"reverseAccelAxis", 0, 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) diff --git a/swdcio/config.h b/swdcio/config.h index d6f9667..ba3240c 100644 --- a/swdcio/config.h +++ b/swdcio/config.h @@ -19,6 +19,9 @@ struct swdc_di_config { uint8_t wheel_yellow; bool reverse_brake_axis; bool reverse_accel_axis; + + // FFB configuration + uint16_t center_spring_strength; }; struct swdc_xi_config { diff --git a/swdcio/di-dev.c b/swdcio/di-dev.c index 116e529..254596a 100644 --- a/swdcio/di-dev.c +++ b/swdcio/di-dev.c @@ -44,7 +44,8 @@ HRESULT swdc_di_dev_start(IDirectInputDevice8W *dev, HWND wnd) 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 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; LONG direction; DIEFFECT fx; - DICONSTANTFORCE cf; + DICONDITION cond; HRESULT hr; 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"); + // Auto-centering effect axis = DIJOFS_X; direction = 0; - memset(&cf, 0, sizeof(cf)); - cf.lMagnitude = 0; + memset(&cond, 0, sizeof(cond)); + 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)); fx.dwSize = sizeof(fx); @@ -93,20 +100,19 @@ void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out) fx.cAxes = 1; fx.rgdwAxes = &axis; fx.rglDirection = &direction; - fx.cbTypeSpecificParams = sizeof(cf); - fx.lpvTypeSpecificParams = &cf; + fx.cbTypeSpecificParams = sizeof(cond); + fx.lpvTypeSpecificParams = &cond; hr = IDirectInputDevice8_CreateEffect( dev, - &GUID_ConstantForce, + &GUID_Spring, &fx, &obj, NULL); if (FAILED(hr)) { - dprintf("DirectInput: DirectInput force feedback unavailable: %08x\n", + dprintf("DirectInput: Centering spring force feedback unavailable: %08x\n", (int) hr); - return; } @@ -114,15 +120,15 @@ void swdc_di_dev_start_fx(IDirectInputDevice8W *dev, IDirectInputEffect **out) if (FAILED(hr)) { IDirectInputEffect_Release(obj); - dprintf("DirectInput: DirectInput force feedback start failed: %08x\n", + dprintf("DirectInput: Centering spring force feedback start failed: %08x\n", (int) hr); - return; } *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( diff --git a/swdcio/di-dev.h b/swdcio/di-dev.h index 82ceef0..06ac036 100644 --- a/swdcio/di-dev.h +++ b/swdcio/di-dev.h @@ -11,7 +11,7 @@ union swdc_di_state { }; 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( IDirectInputDevice8W *dev, HWND wnd, diff --git a/swdcio/di.c b/swdcio/di.c index 35c6463..09f25d0 100644 --- a/swdcio/di.c +++ b/swdcio/di.c @@ -70,6 +70,7 @@ static uint8_t swdc_di_wheel_yellow; static bool swdc_di_use_pedals; static bool swdc_di_reverse_brake_axis; static bool swdc_di_reverse_accel_axis; +static uint16_t swdc_di_center_spring_strength; HRESULT swdc_di_init( const struct swdc_di_config *cfg, @@ -168,7 +169,9 @@ HRESULT swdc_di_init( 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') { 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_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; }