N64 joystick emulation (#828)

* input.cpp: pass dev nr to joy_analog

This allows for per-controller behavior

* N64: add emulation for the analog joystick

This applies the reduced-range octagonal gate of the N64 analog stick to
regular analog sticks.

The code was mostly written by Patrick Pollock with small optimizations
by Martin Donlon and myself.
This commit is contained in:
Marcoen Hirschberg
2023-09-24 11:22:02 +02:00
committed by GitHub
parent 257e81ed32
commit d53a998eac
4 changed files with 86 additions and 17 deletions

View File

@@ -1198,6 +1198,7 @@ typedef struct
char id[80];
char name[128];
char sysfs[512];
int max_range;
} devInput;
static devInput input[NUMDEV] = {};
@@ -2074,16 +2075,30 @@ static void joy_digital(int jnum, uint32_t mask, uint32_t code, char press, int
}
}
static void joy_analog(int num, int axis, int offset, int stick = 0)
static void joy_analog(int dev, int axis, int offset, int stick = 0)
{
int num = input[dev].num;
static int pos[2][NUMPLAYERS][2] = {};
if (grabbed && num > 0 && num < NUMPLAYERS+1)
{
num--;
pos[stick][num][axis] = offset;
if(stick) user_io_r_analog_joystick(num, (char)(pos[1][num][0]), (char)(pos[1][num][1]));
else user_io_l_analog_joystick(num, (char)(pos[0][num][0]), (char)(pos[0][num][1]));
int x = pos[stick][num][0];
int y = pos[stick][num][1];
if (is_n64() && stick == 0)
{
const int abs_x = abs(x);
const int abs_y = abs(y);
if (abs_x > input[dev].max_range) input[dev].max_range = abs_x;
if (abs_y > input[dev].max_range) input[dev].max_range = abs_y;
// emulate n64 joystick range and shape for regular -127-+127 controllers
n64_joy_emu(x, y, &x, &y, input[dev].max_range);
}
if(stick) user_io_r_analog_joystick(num, (char)x, (char)y);
else user_io_l_analog_joystick(num, (char)x, (char)y);
}
}
@@ -3323,58 +3338,58 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
// steering wheel passes full range, pedals are standardised in +127 to 0 to -127 range
if (ev->code == input[dev].wh_steer)
{
joy_analog(input[dev].num, 0, value, 0);
joy_analog(dev, 0, value, 0);
}
else if (ev->code == input[dev].wh_accel)
{
joy_analog(input[dev].num, 1, wh_value, 0);
joy_analog(dev, 1, wh_value, 0);
}
else if (ev->code == input[dev].wh_brake)
{
joy_analog(input[dev].num, 1, wh_value, 1);
joy_analog(dev, 1, wh_value, 1);
}
else if (ev->code == input[dev].wh_clutch)
{
joy_analog(input[dev].num, 0, wh_value, 1);
joy_analog(dev, 0, wh_value, 1);
}
else if (ev->code == input[dev].wh_combo)
{
// if accel and brake pedal use a shared axis then map negative to accel and positive to brake
if (value < -1) joy_analog(input[dev].num, 1, value, 0);
else if (value > 1) joy_analog(input[dev].num, 1, -value, 1);
if (value < -1) joy_analog(dev, 1, value, 0);
else if (value > 1) joy_analog(dev, 1, -value, 1);
else
{
joy_analog(input[dev].num, 1, 0, 0);
joy_analog(input[dev].num, 1, 0, 0);
joy_analog(dev, 1, 0, 0);
joy_analog(dev, 1, 0, 0);
}
}
}
else if (ev->code == 0 && input[dev].lightgun)
{
joy_analog(input[dev].num, 0, value);
joy_analog(dev, 0, value);
}
else if (ev->code == 1 && input[dev].lightgun)
{
joy_analog(input[dev].num, 1, value);
joy_analog(dev, 1, value);
}
else
{
int offset = (value < -1 || value>1) ? value : 0;
if (input[dev].stick_l[0] && ev->code == (uint16_t)input[dev].mmap[input[dev].stick_l[0]])
{
joy_analog(input[dev].num, 0, offset, 0);
joy_analog(dev, 0, offset, 0);
}
else if (input[dev].stick_l[1] && ev->code == (uint16_t)input[dev].mmap[input[dev].stick_l[1]])
{
joy_analog(input[dev].num, 1, offset, 0);
joy_analog(dev, 1, offset, 0);
}
else if (input[dev].stick_r[0] && ev->code == (uint16_t)input[dev].mmap[input[dev].stick_r[0]])
{
joy_analog(input[dev].num, 0, offset, 1);
joy_analog(dev, 0, offset, 1);
}
else if (input[dev].stick_r[1] && ev->code == (uint16_t)input[dev].mmap[input[dev].stick_r[1]])
{
joy_analog(input[dev].num, 1, offset, 1);
joy_analog(dev, 1, offset, 1);
}
}
}