1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2025-02-21 21:00:02 +01:00

vigem-sdvxio: Add relative mode and address comments

This commit is contained in:
Will Xyen 2020-09-26 18:46:17 -07:00
parent 4f3135439d
commit a9ebc30ea7
6 changed files with 126 additions and 21 deletions

View File

@ -1,24 +1,24 @@
This application allows you to use any sdvxio backend to drive an XB360 controller. This application allows you to use any sdvxio backend, e.g. `sdvxio-kfca.dll`, to be available as a XBOX 360 game controller on windows.
Thus, it allows you to use a real cab with *any* game that supports xinput. Thus, it allows you to use a real cab with *any* game that supports xinput.
# Setup # Setup
* Install ViGEmBus (https://github.com/ViGEm/ViGEmBus/releases) * Install [ViGEmBus](https://github.com/ViGEm/ViGEmBus/releases)
* Place the following in the same folder as vigem-sdvxio: * Place the following in the same folder as vigem-sdvxio:
* Get a copy of ViGEmClient.dll (https://bin.jvnv.net/file/ZgMJK/ViGEmClient.zip) * Get a copy of [ViGEmClient.dll](https://bin.jvnv.net/file/ZgMJK/ViGEmClient.zip) (or from bemanitools-supplements)
* Rename your corresponding sdvxio-device.dll to sdvxio.dll. * Rename your corresponding `sdvxio-XXX.dll`, e.g. `sdvxio-kfca.dll`, to `sdvxio.dll`.
* Run vigem-sdvxio.exe so that the config file gets created * Run `vigem-sdvxio.exe` so that the config file gets created
* Edit vigem-sdvxio.conf so that the config file gets created as needed * Edit `vigem-sdvxio.conf` so that the config file gets created as needed
# Usage # Usage
* Run vigem-sdvxio.exe * Run `vigem-sdvxio.exe`
* To quit the program, hit the TEST + SERVICE button at the same time * To quit the program, hit the TEST + SERVICE button at the same time
# Mapping # Mapping
* BT ABCD are mapped to ABXY * BT ABCD are mapped to ABXY
* FX LR are mapped to LB/RB * FX LR are mapped to LB/RB
* VOL LR are mapped to L/R thumbstick X * VOL LR are mapped to L thumbstick X/Y (either in absolute or relative mode depending on the config)
# Additional Notes For Cabinets: # Additional Notes For Cabinets (Running on embedded Windows 7):
* Make sure that you follow the instructions exactly from the release page (Prerequisites for Windows 7) * Make sure that you follow the instructions exactly from the release page ([Prerequisites for Windows 7](https://github.com/ViGEm/ViGEmBus/wiki/Prerequisites-for-Windows-7))
* If you get an error while trying to install KB3033929, re-enable windows update * If you get an error while trying to install KB3033929, re-enable windows update
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once) * Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once)

View File

@ -6,11 +6,13 @@
#include "util/log.h" #include "util/log.h"
#define VIGEM_SDVXIO_CONFIG_ENABLE_KEYLIGHT_KEY "sdvxio.enable_keylight" #define VIGEM_SDVXIO_CONFIG_ENABLE_KEYLIGHT_KEY "sdvxio.enable_keylight"
#define VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY "sdvxio.use_relative_analog"
#define VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY "sdvxio.pwm_wings" #define VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY "sdvxio.pwm_wings"
#define VIGEM_SDVXIO_CONFIG_PWM_CONTROLLER_KEY "sdvxio.pwm_controller" #define VIGEM_SDVXIO_CONFIG_PWM_CONTROLLER_KEY "sdvxio.pwm_controller"
#define VIGEM_SDVXIO_CONFIG_AMP_VOLUME_KEY "sdvxio.amp_volume" #define VIGEM_SDVXIO_CONFIG_AMP_VOLUME_KEY "sdvxio.amp_volume"
#define VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE true #define VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE true
#define VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE false
#define VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_WINGS_VALUE 128 #define VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_WINGS_VALUE 128
#define VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_CONTROLLER_VALUE 64 #define VIGEM_SDVXIO_CONFIG_DEFAULT_PWM_CONTROLLER_VALUE 64
#define VIGEM_SDVXIO_CONFIG_DEFAULT_AMP_VOLUME_VALUE 48 #define VIGEM_SDVXIO_CONFIG_DEFAULT_AMP_VOLUME_VALUE 48
@ -23,6 +25,12 @@ void vigem_sdvxio_config_init(struct cconfig *config)
VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE, VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE,
"Enable input based key lighting"); "Enable input based key lighting");
cconfig_util_set_bool(
config,
VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY,
VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE,
"Use relative mode analog mapping");
cconfig_util_set_int( cconfig_util_set_int(
config, config,
VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY, VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY,
@ -57,6 +65,18 @@ void vigem_sdvxio_config_get(
VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE); VIGEM_SDVXIO_CONFIG_DEFAULT_ENABLE_KEYLIGHT_VALUE);
} }
if (!cconfig_util_get_bool(
config,
VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY,
&vigem_config->relative_analog,
VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
VIGEM_SDVXIO_CONFIG_RELATIVE_ANALOG_KEY,
VIGEM_SDVXIO_CONFIG_DEFAULT_RELATIVE_ANALOG_VALUE);
}
if (!cconfig_util_get_int( if (!cconfig_util_get_int(
config, config,
VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY, VIGEM_SDVXIO_CONFIG_PWM_WINGS_KEY,
@ -94,7 +114,7 @@ void vigem_sdvxio_config_get(
} }
} }
void get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out) bool get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out)
{ {
struct cconfig *config; struct cconfig *config;
@ -111,7 +131,7 @@ void get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out)
"vigem-sdvxio", "vigem-sdvxio",
CCONFIG_CMD_USAGE_OUT_STDOUT)) { CCONFIG_CMD_USAGE_OUT_STDOUT)) {
cconfig_finit(config); cconfig_finit(config);
exit(EXIT_FAILURE); return false;
} }
vigem_sdvxio_config_get(config_out, config); vigem_sdvxio_config_get(config_out, config);
@ -125,4 +145,5 @@ void get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out)
if (config_out->pwm_wings > 255) { if (config_out->pwm_wings > 255) {
config_out->pwm_wings = 255; config_out->pwm_wings = 255;
} }
return true;
} }

View File

@ -7,11 +7,12 @@
struct vigem_sdvxio_config { struct vigem_sdvxio_config {
bool enable_keylight; bool enable_keylight;
bool relative_analog;
int32_t pwm_wings; int32_t pwm_wings;
int32_t pwm_controller; int32_t pwm_controller;
int32_t amp_volume; int32_t amp_volume;
}; };
void get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out); bool get_vigem_sdvxio_config(struct vigem_sdvxio_config *config_out);
#endif #endif

View File

@ -15,12 +15,74 @@
#include "vigem-sdvxio/config-vigem-sdvxio.h" #include "vigem-sdvxio/config-vigem-sdvxio.h"
int64_t convert_analog_to_s16(uint16_t val) #define ANALOG_FIXED_SENSITIVITY 1024
int16_t convert_analog_to_s16(uint16_t val)
{ {
// val is 10 bit // val is 10 bit
return (int64_t)(val * 64); return (int64_t)(val * 64);
} }
int16_t get_relative_delta(int16_t val, int16_t last)
{
// val is 10 bit
const int16_t half_point = 512; // 2^9
int16_t delta = val - last;
if (delta > half_point) {
delta -= 1024;
}
if (delta < -half_point) {
delta += 1024;
}
// delta is now between (-512 - 512)
return delta;
}
int16_t filter_floor(int32_t value, int16_t floor) {
if (abs(value) < floor) {
return 0;
}
if (value > INT16_MAX) {
value = INT16_MAX;
}
if (value < INT16_MIN) {
value = INT16_MIN;
}
return value;
}
int32_t convert_relative_analog(
uint16_t val, uint16_t last, int32_t buffered_last, int16_t multiplier)
{
int16_t delta = get_relative_delta(val, last);
if (delta == 0) {
// ease the stick back to 0 like a real stick would
return buffered_last / 2.f;
} else {
int64_t result = buffered_last;
result += delta * multiplier;
// we use an i32 to store the buffered value
// so that we can overshoot an i16 by up to 1.5x
// this allows users to stay at the min/max stick positions
// without perfect knob turning
if (result > INT16_MAX*1.5) {
result = INT16_MAX*1.5;
}
if (result < INT16_MIN*1.5) {
result = INT16_MIN*1.5;
}
return result;
}
}
bool check_key(uint16_t input, size_t idx_in) bool check_key(uint16_t input, size_t idx_in)
{ {
if ((input >> idx_in) & 1) { if ((input >> idx_in) & 1) {
@ -87,7 +149,9 @@ int main(int argc, char **argv)
log_to_writer(log_writer_stdout, NULL); log_to_writer(log_writer_stdout, NULL);
struct vigem_sdvxio_config config; struct vigem_sdvxio_config config;
get_vigem_sdvxio_config(&config); if (!get_vigem_sdvxio_config(&config)) {
exit(EXIT_FAILURE);
}
sdvx_io_set_loggers( sdvx_io_set_loggers(
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal); log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
@ -100,12 +164,14 @@ int main(int argc, char **argv)
sdvx_io_set_amp_volume(config.amp_volume, config.amp_volume, config.amp_volume); sdvx_io_set_amp_volume(config.amp_volume, config.amp_volume, config.amp_volume);
PVIGEM_CLIENT client = vigem_helper_setup(); PVIGEM_CLIENT client = vigem_helper_setup();
if (!client) { if (!client) {
log_warning("client failed to connect failed"); log_warning("client failed to connect failed");
return -1; return -1;
} }
PVIGEM_TARGET pad = vigem_helper_add_pad(client); PVIGEM_TARGET pad = vigem_helper_add_pad(client);
if (!pad) { if (!pad) {
log_warning("vigem_alloc pad 1 failed"); log_warning("vigem_alloc pad 1 failed");
return -1; return -1;
@ -117,10 +183,14 @@ int main(int argc, char **argv)
uint16_t gpio0; uint16_t gpio0;
uint16_t gpio1; uint16_t gpio1;
uint16_t vol[2] = {0, 0}; uint16_t vol[2] = {0, 0};
uint16_t last_vol[2] = {0, 0};
int32_t buffered_vol[2] = {0, 0};
XUSB_REPORT state; XUSB_REPORT state;
log_info("vigem init succeeded, beginning poll loop"); log_info("vigem init succeeded, beginning poll loop");
while (loop) { while (loop) {
sdvx_io_read_input(); sdvx_io_read_input();
@ -133,8 +203,19 @@ int main(int argc, char **argv)
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
state.sThumbLX = convert_analog_to_s16(vol[0]); if (config.relative_analog) {
state.sThumbRX = convert_analog_to_s16(vol[1]); buffered_vol[0] = convert_relative_analog(vol[0], last_vol[0], buffered_vol[0], ANALOG_FIXED_SENSITIVITY);
buffered_vol[1] = convert_relative_analog(vol[1], last_vol[1], buffered_vol[1], ANALOG_FIXED_SENSITIVITY);
state.sThumbLX = filter_floor(buffered_vol[0], ANALOG_FIXED_SENSITIVITY/2);
state.sThumbLY = filter_floor(buffered_vol[1], ANALOG_FIXED_SENSITIVITY/2);
last_vol[0] = vol[0];
last_vol[1] = vol[1];
} else {
state.sThumbLX = convert_analog_to_s16(vol[0]);
state.sThumbLY = convert_analog_to_s16(vol[1]);
}
state.wButtons |= check_assign_key( state.wButtons |= check_assign_key(
gpio0, SDVX_IO_IN_GPIO_0_START, XUSB_GAMEPAD_START); gpio0, SDVX_IO_IN_GPIO_0_START, XUSB_GAMEPAD_START);

View File

@ -5,6 +5,7 @@ cppflags_vigemstub := \
-I src/imports \ -I src/imports \
libs_vigemstub := \ libs_vigemstub := \
util \
src_vigemstub := \ src_vigemstub := \
helper.c \ helper.c \

View File

@ -4,6 +4,7 @@
#include "ViGEm/Client.h" #include "ViGEm/Client.h"
#include "util/log.h"
#include "vigemstub/helper.h" #include "vigemstub/helper.h"
PVIGEM_CLIENT vigem_helper_setup(void) PVIGEM_CLIENT vigem_helper_setup(void)
@ -11,14 +12,14 @@ PVIGEM_CLIENT vigem_helper_setup(void)
PVIGEM_CLIENT client = vigem_alloc(); PVIGEM_CLIENT client = vigem_alloc();
if (client == NULL) { if (client == NULL) {
printf("vigem_alloc failed\n"); log_warning("vigem_alloc failed\n");
return NULL; return NULL;
} }
VIGEM_ERROR retval = vigem_connect(client); VIGEM_ERROR retval = vigem_connect(client);
if (!VIGEM_SUCCESS(retval)) { if (!VIGEM_SUCCESS(retval)) {
printf("ViGEm Bus connection failed with error code: 0x%x\n", retval); log_warning("ViGEm Bus connection failed with error code: 0x%x\n", retval);
return NULL; return NULL;
} }
@ -30,14 +31,14 @@ PVIGEM_TARGET vigem_helper_add_pad(PVIGEM_CLIENT client)
PVIGEM_TARGET pad = vigem_target_x360_alloc(); PVIGEM_TARGET pad = vigem_target_x360_alloc();
if (pad == NULL) { if (pad == NULL) {
printf("vigem_target_x360_alloc failed\n"); log_warning("vigem_target_x360_alloc failed\n");
return NULL; return NULL;
} }
VIGEM_ERROR pir = vigem_target_add(client, pad); VIGEM_ERROR pir = vigem_target_add(client, pad);
if (!VIGEM_SUCCESS(pir)) { if (!VIGEM_SUCCESS(pir)) {
printf("Target plugin failed with error code: 0x%x\n", pir); log_warning("Target plugin failed with error code: 0x%x\n", pir);
return NULL; return NULL;
} }