forked from Hay1tsme/segatools
Compare commits
4 Commits
2023-12-03
...
2023-12-17
Author | SHA1 | Date | |
---|---|---|---|
ed042176d7
|
|||
ad154a83e5
|
|||
1cbc33d97d
|
|||
72db08ac93
|
@ -18,6 +18,7 @@ struct aime_dll {
|
||||
|
||||
struct aime_dll_config {
|
||||
wchar_t path[MAX_PATH];
|
||||
bool path64;
|
||||
};
|
||||
|
||||
extern struct aime_dll aime_dll;
|
||||
|
@ -9,18 +9,59 @@
|
||||
#include "board/config.h"
|
||||
#include "board/sg-reader.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
// Check windows
|
||||
#if _WIN32 || _WIN64
|
||||
#if _WIN64
|
||||
#define ENV64BIT
|
||||
#else
|
||||
#define ENV32BIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Check GCC
|
||||
#if __GNUC__
|
||||
#if __x86_64__ || __ppc64__
|
||||
#define ENV64BIT
|
||||
#else
|
||||
#define ENV32BIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void aime_dll_config_load(struct aime_dll_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
// Workaround for x64/x86 external IO dlls
|
||||
// path32 for 32bit, path64 for 64bit
|
||||
// for else.. is that possible? idk
|
||||
|
||||
if (cfg->path64) {
|
||||
#if defined(ENV32BIT)
|
||||
// Always empty, due to amdaemon being 64 bit in 32 bit mode
|
||||
memset(cfg->path, 0, sizeof(cfg->path));
|
||||
#elif defined(ENV64BIT)
|
||||
GetPrivateProfileStringW(
|
||||
L"aimeio",
|
||||
L"path",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
#else
|
||||
#error "Unknown environment"
|
||||
#endif
|
||||
} else {
|
||||
GetPrivateProfileStringW(
|
||||
L"aimeio",
|
||||
L"path",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
}
|
||||
}
|
||||
|
||||
void aime_config_load(struct aime_config *cfg, const wchar_t *filename)
|
||||
|
@ -38,7 +38,7 @@ void chuni_io_jvs_read_coin_counter(uint16_t *out)
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(chuni_io_cfg.vk_coin)) {
|
||||
if (GetAsyncKeyState(chuni_io_cfg.vk_coin) & 0x8000) {
|
||||
if (!chuni_io_coin) {
|
||||
chuni_io_coin = true;
|
||||
chuni_io_coins++;
|
||||
@ -62,15 +62,6 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams)
|
||||
*opbtn |= CHUNI_IO_OPBTN_SERVICE;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(chuni_io_cfg.vk_coin) & 0x8000) {
|
||||
if (!chuni_io_coin) {
|
||||
chuni_io_coin = true;
|
||||
*opbtn |= CHUNI_IO_OPBTN_COIN;
|
||||
}
|
||||
} else {
|
||||
chuni_io_coin = false;
|
||||
}
|
||||
|
||||
if (chuni_io_cfg.vk_ir_emu) {
|
||||
// Use emulated AIR
|
||||
if (GetAsyncKeyState(chuni_io_cfg.vk_ir_emu)) {
|
||||
|
@ -57,7 +57,7 @@ void chuni_io_config_load(
|
||||
filename);
|
||||
}
|
||||
|
||||
GetPrivateProfileStringW(L"slider", L"ledport", L"COM2", port_input, 6, filename);
|
||||
GetPrivateProfileStringW(L"slider", L"ledport", L"COM5", port_input, 6, filename);
|
||||
wcsncpy(cfg->led_com, L"\\\\.\\", 4);
|
||||
wcsncat_s(cfg->led_com, 11, port_input, 6);
|
||||
}
|
||||
|
@ -141,6 +141,9 @@ void chusan_hook_config_load(
|
||||
|
||||
memset(cfg, 0, sizeof(*cfg));
|
||||
|
||||
// Force load the 64bit Aime DLL instead of the 32bit one
|
||||
cfg->aime.dll.path64 = true;
|
||||
|
||||
platform_config_load(&cfg->platform, filename);
|
||||
aime_config_load(&cfg->aime, filename);
|
||||
dvd_config_load(&cfg->dvd, filename);
|
||||
|
@ -100,11 +100,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||
}
|
||||
|
||||
bool *dipsw = &chusan_hook_cfg.platform.dipsw.dipsw[0];
|
||||
|
||||
if (dipsw[1] != dipsw[2]) {
|
||||
dprintf("DipSw: DipSw2 and 3 must be set to the same value!\n");
|
||||
goto fail;
|
||||
}
|
||||
bool *is_sp = dipsw + 2;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
switch (i) {
|
||||
@ -117,13 +113,21 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dprintf("DipSw: Aime Reader: %s\n", dipsw[2] ? "CVT" : "SP");
|
||||
dprintf("DipSw: Cab Type: %s\n", is_sp ? "SP" : "CVT");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int first_port = dipsw[1] ? 2 : 20;
|
||||
unsigned int first_port = is_sp ? 20 : 2;
|
||||
|
||||
if (is_sp) {
|
||||
hr = vfd_hook_init(2);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
hr = led15093_hook_init(&chusan_hook_cfg.led15093, first_port, 2, 2, 1);
|
||||
|
||||
@ -131,7 +135,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, dipsw[2] ? 2 : 3, chusan_hook_mod);
|
||||
hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_sp ? 3: 2, chusan_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
|
@ -73,6 +73,7 @@ static HRESULT chusan_io4_poll(void* ctx, struct io4_state* state)
|
||||
beams = 0;
|
||||
|
||||
chuni_dll.jvs_poll(&opbtn, &beams);
|
||||
chuni_dll.jvs_read_coin_counter(&coins);
|
||||
|
||||
if (chuni_dll.api_version >= 0x0101) {
|
||||
// Use correct mapping
|
||||
@ -90,9 +91,7 @@ static HRESULT chusan_io4_poll(void* ctx, struct io4_state* state)
|
||||
state->buttons[0] |= IO4_BUTTON_SERVICE;
|
||||
}
|
||||
|
||||
if (opbtn & CHUNI_IO_OPBTN_COIN) {
|
||||
coins++;
|
||||
}
|
||||
// Update the coin counter with the value from jvs_read_coin_counter
|
||||
state->chutes[0] = coins << 8;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
|
4
dist/chuni/segatools.ini
vendored
4
dist/chuni/segatools.ini
vendored
@ -82,3 +82,7 @@ coin=0x33
|
||||
;cell31=0x53
|
||||
;cell30=0x53
|
||||
; ... etc ...
|
||||
|
||||
; Enable slider LED serial output. This follows OpeNITHM Serial LED Protocol.
|
||||
; eg. COM5
|
||||
;ledport=
|
||||
|
14
dist/chusan/segatools.ini
vendored
14
dist/chusan/segatools.ini
vendored
@ -16,9 +16,9 @@ aimePath=DEVICE\aime.txt
|
||||
;highbaud=1
|
||||
|
||||
[aimeio]
|
||||
; x64 aimeio dll path.
|
||||
; Uncomment this if you have custom aime implementation.
|
||||
;path64=
|
||||
; Uncomment this if you have custom (x64) aime implementation.
|
||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||
;path=
|
||||
|
||||
[dns]
|
||||
; Insert the hostname or IP address of the server you wish to use here.
|
||||
@ -35,7 +35,7 @@ enable=1
|
||||
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
||||
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||
; that subnet must start with 192.168.
|
||||
subnet=192.168.100.0
|
||||
subnet=192.168.139.0
|
||||
|
||||
[gpio]
|
||||
; ALLS DIP switches.
|
||||
@ -49,10 +49,10 @@ freeplay=0
|
||||
; LAN Install: If multiple machines are present on the same LAN then set
|
||||
; this to 1 on exactly one machine and set this to 0 on all others.
|
||||
dipsw1=1
|
||||
; Monitor type: 0 = 120FPS (SP), 1 = 60FPS (CVT)
|
||||
; Monitor type: 0 = 120FPS, 1 = 60FPS
|
||||
dipsw2=1
|
||||
; Aime reader hardware type: 0 = SP, 1 = CVT. Both dipsw2 and dipsw3 must be
|
||||
; the same value.
|
||||
; Cab type: 0 = SP, 1 = CVT. SP will enable VFD and eMoney. This setting will switch
|
||||
; the LED 837-15093-06 COM port and the AiMe reder hardware generation as well.
|
||||
dipsw3=1
|
||||
|
||||
[gfx]
|
||||
|
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
|
||||
; 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
|
||||
|
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)
|
||||
reverseAccelAxis=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)
|
||||
reverseAccelAxis=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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
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_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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
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_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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
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_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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user