forked from TeamTofuShop/segatools
idac, idz, swdc: Fixed DInput brake/accel, added cubic steering
This commit is contained in:
94
idacio/xi.c
94
idacio/xi.c
@ -1,16 +1,16 @@
|
||||
#include <windows.h>
|
||||
#include <xinput.h>
|
||||
#include "idacio/xi.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
#include <xinput.h>
|
||||
|
||||
#include "idacio/backend.h"
|
||||
#include "idacio/config.h"
|
||||
#include "idacio/idacio.h"
|
||||
#include "idacio/shifter.h"
|
||||
#include "idacio/xi.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void idac_xi_get_gamebtns(uint8_t *gamebtn_out);
|
||||
@ -20,15 +20,15 @@ static void idac_xi_get_analogs(struct idac_io_analog_state *out);
|
||||
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg);
|
||||
|
||||
static const struct idac_io_backend idac_xi_backend = {
|
||||
.get_gamebtns = idac_xi_get_gamebtns,
|
||||
.get_shifter = idac_xi_get_shifter,
|
||||
.get_analogs = idac_xi_get_analogs,
|
||||
.get_gamebtns = idac_xi_get_gamebtns,
|
||||
.get_shifter = idac_xi_get_shifter,
|
||||
.get_analogs = idac_xi_get_analogs,
|
||||
};
|
||||
|
||||
static bool idac_xi_single_stick_steering;
|
||||
static bool idac_xi_linear_steering;
|
||||
|
||||
HRESULT idac_xi_init(const struct idac_xi_config *cfg, const struct idac_io_backend **backend)
|
||||
{
|
||||
HRESULT idac_xi_init(const struct idac_xi_config *cfg, const struct idac_io_backend **backend) {
|
||||
HRESULT hr;
|
||||
assert(cfg != NULL);
|
||||
assert(backend != NULL);
|
||||
@ -45,24 +45,23 @@ HRESULT idac_xi_init(const struct idac_xi_config *cfg, const struct idac_io_back
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT idac_io_poll(void)
|
||||
{
|
||||
HRESULT idac_io_poll(void) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg)
|
||||
{
|
||||
static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg) {
|
||||
dprintf("XInput: --- Begin configuration ---\n");
|
||||
dprintf("XInput: Single Stick Steering : %i\n", cfg->single_stick_steering);
|
||||
dprintf("XInput: Linear Steering . . . : %i\n", cfg->linear_steering);
|
||||
dprintf("XInput: --- End configuration ---\n");
|
||||
|
||||
idac_xi_single_stick_steering = cfg->single_stick_steering;
|
||||
idac_xi_linear_steering = cfg->linear_steering;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void idac_xi_get_gamebtns(uint8_t *gamebtn_out)
|
||||
{
|
||||
static void idac_xi_get_gamebtns(uint8_t *gamebtn_out) {
|
||||
uint8_t gamebtn;
|
||||
XINPUT_STATE xi;
|
||||
WORD xb;
|
||||
@ -102,8 +101,7 @@ static void idac_xi_get_gamebtns(uint8_t *gamebtn_out)
|
||||
*gamebtn_out = gamebtn;
|
||||
}
|
||||
|
||||
static void idac_xi_get_shifter(uint8_t *gear)
|
||||
{
|
||||
static void idac_xi_get_shifter(uint8_t *gear) {
|
||||
bool shift_dn;
|
||||
bool shift_up;
|
||||
XINPUT_STATE xi;
|
||||
@ -144,8 +142,32 @@ static void idac_xi_get_shifter(uint8_t *gear)
|
||||
*gear = idac_shifter_current_gear();
|
||||
}
|
||||
|
||||
static void idac_xi_get_analogs(struct idac_io_analog_state *out)
|
||||
{
|
||||
static int apply_non_linear_transform(int value, int deadzone_center) {
|
||||
const int max_input = 32767;
|
||||
const double power_factor = 3.0;
|
||||
|
||||
// Apply deadzone only after passing the center threshold
|
||||
if (abs(value) < deadzone_center) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Scale the value to the range [-1.0, 1.0]
|
||||
double scaled_value = (abs(value) - deadzone_center) / (double)(max_input - deadzone_center);
|
||||
|
||||
// Apply a non-linear transform (cubing in this case) and preserve the sign
|
||||
double signed_value = copysign(pow(scaled_value, power_factor), value);
|
||||
|
||||
// Scale the value back to the range [-32770, 32767]
|
||||
int transformed_value = (int)(signed_value * max_input);
|
||||
|
||||
// Clamp the value to the range [-32767, 32767]
|
||||
transformed_value = (transformed_value > max_input) ? max_input : transformed_value;
|
||||
transformed_value = (transformed_value < -max_input) ? -max_input : transformed_value;
|
||||
|
||||
return transformed_value;
|
||||
}
|
||||
|
||||
static void idac_xi_get_analogs(struct idac_io_analog_state *out) {
|
||||
XINPUT_STATE xi;
|
||||
int left;
|
||||
int right;
|
||||
@ -156,27 +178,33 @@ static void idac_xi_get_analogs(struct idac_io_analog_state *out)
|
||||
XInputGetState(0, &xi);
|
||||
|
||||
left = xi.Gamepad.sThumbLX;
|
||||
|
||||
if (left < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) {
|
||||
left += XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
|
||||
} else if (left > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) {
|
||||
left -= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
|
||||
} else {
|
||||
left = 0;
|
||||
}
|
||||
|
||||
right = xi.Gamepad.sThumbRX;
|
||||
|
||||
if (right < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) {
|
||||
right += XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
|
||||
} else if (right > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) {
|
||||
right -= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
|
||||
if (!idac_xi_linear_steering) {
|
||||
// Apply non-linear transform for both sticks
|
||||
left = apply_non_linear_transform(left, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
|
||||
right = apply_non_linear_transform(right, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
|
||||
} else {
|
||||
right = 0;
|
||||
if (left < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) {
|
||||
left += XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
|
||||
} else if (left > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) {
|
||||
left -= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
|
||||
} else {
|
||||
left = 0;
|
||||
}
|
||||
|
||||
if (right < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) {
|
||||
right += XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
|
||||
} else if (right > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) {
|
||||
right -= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE;
|
||||
} else {
|
||||
right = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (idac_xi_single_stick_steering) {
|
||||
out->wheel = left;
|
||||
// dprintf("XInput: Single Stick Steering: %i\n", out->wheel);
|
||||
} else {
|
||||
out->wheel = (left + right) / 2;
|
||||
}
|
||||
|
Reference in New Issue
Block a user