1
0
mirror of synced 2025-02-21 03:56:28 +01:00

Add per analogue input deadzones

Each analogue input now gets 3 deadzones, start, middle, and end. These
deadzones are a percentage of the total range that should be squashed to
the extreme.
This commit is contained in:
Hein-Pieter van Braam 2024-12-29 02:28:51 +01:00
parent 603eb118ef
commit 84705ee963
5 changed files with 96 additions and 1 deletions

View File

@ -60,6 +60,18 @@ PLAYER_1_BUTTON_LEFT XBOX_CONTROLLER_ABS_X_MIN
PLAYER_1_BUTTON_RIGHT XBOX_CONTROLLER_ABS_X_MAX
```
You can set a deadzone for analogue axis. Each anaolgue input has 3 potential deadzones: start, middle, and end. The deadzone is a percentage of the range from the start, middle, or end that should snap to its respective extreme. This is useful for input devices that don't perfectly center, or pedals that don't perfectly return to 0. For instance.
```
ANALOGUE_DEADZONE_1 10 13 10
```
Will cause input on analogue input 1 to be clamped as follows:
* At the start of the range the first 10% of the range will be set to 0%. In the case of a steering wheel where left is 0%, center is 50%, and right is 100% this will set steering percentages 0-10% to 0%.
* In the middle of the range the center 13% of the left of middle, and 13% of the right of middle will snap to the middle.
* At the end of the range the last 10% of the range will be set to 100%, similarly to the start case.
## Audio
There are currently no audio options that you can set. If you have a stereo sound card installed then the audio will be downmixed to stereo. If you have a 5.1 sound card installed and the game supports surround sound, each surround channel should be passed through properly and should play sound as it was originally intended.

View File

@ -151,3 +151,12 @@
# ANALOGUE_2 SYNPS_2_SYNAPTICS_TOUCHPAD_ABS_Y
# ANALOGUE_3 SYNPS_2_SYNAPTICS_TOUCHPAD_ABS_Z
# ANALOGUE_4 SYNPS_2_SYNAPTICS_TOUCHPAD_ABS_RZ
# ANALOGUE_DEADZONE_1 0 0 0
# ANALOGUE_DEADZONE_2 0 0 0
# ANALOGUE_DEADZONE_3 0 0 0
# ANALOGUE_DEADZONE_4 0 0 0
# ANALOGUE_DEADZONE_5 0 0 0
# ANALOGUE_DEADZONE_6 0 0 0
# ANALOGUE_DEADZONE_7 0 0 0
# ANALOGUE_DEADZONE_8 0 0 0

View File

@ -953,6 +953,41 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
else if (strcmp(command, "ANALOGUE_8") == 0)
strncpy(config->arcadeInputs.analogue_8, getNextToken(NULL, " ", &saveptr), INPUT_STRING_LENGTH - 1);
// Analogue deadzone
else if (strcmp(command, "ANALOGUE_DEADZONE_1") == 0) {
config->arcadeInputs.analogue_deadzone_start[0] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[0] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[0] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_2") == 0) {
config->arcadeInputs.analogue_deadzone_start[1] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[1] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[1] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_3") == 0) {
config->arcadeInputs.analogue_deadzone_start[2] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[2] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[2] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_4") == 0) {
config->arcadeInputs.analogue_deadzone_start[3] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[3] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[3] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_5") == 0) {
config->arcadeInputs.analogue_deadzone_start[4] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[4] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[4] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_6") == 0) {
config->arcadeInputs.analogue_deadzone_start[5] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[5] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[5] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_7") == 0) {
config->arcadeInputs.analogue_deadzone_start[6] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[6] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[6] = atoi(getNextToken(NULL, " ", &saveptr));
} else if (strcmp(command, "ANALOGUE_DEADZONE_8") == 0) {
config->arcadeInputs.analogue_deadzone_start[7] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_middle[7] = atoi(getNextToken(NULL, " ", &saveptr));
config->arcadeInputs.analogue_deadzone_end[7] = atoi(getNextToken(NULL, " ", &saveptr));
}
else if (strcmp(command, "INPUT_MODE") == 0)
config->inputMode = atoi(getNextToken(NULL, " ", &saveptr));
@ -1030,6 +1065,9 @@ int initConfig()
config.lgjRenderWithMesa = 1;
config.noSDL = 0;
config.phMode = 1;
memset(&config.arcadeInputs.analogue_deadzone_start, 0, sizeof(config.arcadeInputs.analogue_deadzone_start));
memset(&config.arcadeInputs.analogue_deadzone_middle, 0, sizeof(config.arcadeInputs.analogue_deadzone_middle));
memset(&config.arcadeInputs.analogue_deadzone_end, 0, sizeof(config.arcadeInputs.analogue_deadzone_end));
config.crc32 = elf_crc;
if (detectGame(config.crc32) != 0)
{

View File

@ -204,6 +204,10 @@ typedef struct {
char analogue_6[INPUT_STRING_LENGTH];
char analogue_7[INPUT_STRING_LENGTH];
char analogue_8[INPUT_STRING_LENGTH];
int analogue_deadzone_start[8];
int analogue_deadzone_middle[8];
int analogue_deadzone_end[8];
} ArcadeInputs;

View File

@ -777,8 +777,19 @@ typedef struct
{
Controller *controller;
Controllers *controllers;
int analogue_deadzone_start[8];
int analogue_deadzone_middle[8];
int analogue_deadzone_end[8];
} ThreadArguments;
typedef struct
{
double start_max;
double middle_min;
double middle_max;
double end_min;
} AnalogueDeadzones;
static inline const char *typename(unsigned int type)
{
return (type <= EV_MAX && events[type]) ? events[type] : "?";
@ -991,6 +1002,7 @@ void *controllerThread(void *_args)
}
struct input_event event;
AnalogueDeadzones analogue_deadzones[8];
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
@ -1000,6 +1012,13 @@ void *controllerThread(void *_args)
args->controllers->threadsRunning = 1;
for (int i = 0; i < 8; ++i) {
analogue_deadzones[i].start_max = args->analogue_deadzone_start[i] / 100.0;
analogue_deadzones[i].middle_min = 0.5 - (args->analogue_deadzone_middle[i] / 100.0);
analogue_deadzones[i].middle_max = 0.5 + (args->analogue_deadzone_middle[i] / 100.0);
analogue_deadzones[i].end_min = 1.0 - (args->analogue_deadzone_end[i] / 100.0);
}
while (args->controllers->threadsRunning)
{
FD_ZERO(&file_descriptor);
@ -1041,7 +1060,16 @@ void *controllerThread(void *_args)
if (args->controller->absTriggers[event.code].enabled)
{
setAnalogue(args->controller->absTriggers[event.code].channel, scaled * (pow(2, jvsBits) - 1));
int channel = args->controller->absTriggers[event.code].channel;
// Deadzone handling
if (scaled < analogue_deadzones[channel].start_max)
scaled = 0.0;
if (scaled > analogue_deadzones[channel].middle_min && scaled < analogue_deadzones[channel].middle_max)
scaled = 0.5;
if (scaled > analogue_deadzones[channel].end_min)
scaled = 1.0;
setAnalogue(channel, scaled * (pow(2, jvsBits) - 1));
}
if (args->controller->absTriggers[event.code].minEnabled)
@ -1309,9 +1337,13 @@ ControllerStatus startControllerThreads(Controllers *controllers)
if (!controllerHasInputsEnabled)
continue;
EmulatorConfig *config = getConfig();
ThreadArguments *args = malloc(sizeof(ThreadArguments));
args->controller = &controllers->controller[i];
args->controllers = controllers;
memcpy(args->analogue_deadzone_start, config->arcadeInputs.analogue_deadzone_start, sizeof(config->arcadeInputs.analogue_deadzone_start));
memcpy(args->analogue_deadzone_middle, config->arcadeInputs.analogue_deadzone_middle, sizeof(config->arcadeInputs.analogue_deadzone_middle));
memcpy(args->analogue_deadzone_end, config->arcadeInputs.analogue_deadzone_end, sizeof(config->arcadeInputs.analogue_deadzone_end));
pthread_create(&controllers->thread[controllers->threadIndex++], NULL, controllerThread, args);
controllers->controller[i].inUse = 1;
}