mirror of
https://github.com/libretro/RetroArch
synced 2025-01-29 18:32:44 +00:00
Some simplifications in Windows input drivers
This commit is contained in:
parent
89902c3339
commit
10c042f1dc
176
input/dinput.c
176
input/dinput.c
@ -72,11 +72,11 @@ static struct dinput_joypad g_pads[MAX_USERS];
|
||||
|
||||
static void dinput_destroy_context(void)
|
||||
{
|
||||
if (g_ctx)
|
||||
{
|
||||
IDirectInput8_Release(g_ctx);
|
||||
g_ctx = NULL;
|
||||
}
|
||||
if (!g_ctx)
|
||||
return;
|
||||
|
||||
IDirectInput8_Release(g_ctx);
|
||||
g_ctx = NULL;
|
||||
}
|
||||
|
||||
static bool dinput_init_context(void)
|
||||
@ -106,13 +106,15 @@ static bool dinput_init_context(void)
|
||||
|
||||
static void *dinput_init(void)
|
||||
{
|
||||
struct dinput_input *di = NULL;
|
||||
|
||||
if (!dinput_init_context())
|
||||
{
|
||||
RARCH_ERR("Failed to start DirectInput driver.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dinput_input *di = (struct dinput_input*)calloc(1, sizeof(*di));
|
||||
di = (struct dinput_input*)calloc(1, sizeof(*di));
|
||||
if (!di)
|
||||
return NULL;
|
||||
|
||||
@ -217,10 +219,11 @@ static void dinput_poll(void *data)
|
||||
|
||||
static bool dinput_keyboard_pressed(struct dinput_input *di, unsigned key)
|
||||
{
|
||||
unsigned sym;
|
||||
if (key >= RETROK_LAST)
|
||||
return false;
|
||||
|
||||
unsigned sym = input_translate_rk_to_keysym((enum retro_key)key);
|
||||
sym = input_translate_rk_to_keysym((enum retro_key)key);
|
||||
return di->state[sym] & 0x80;
|
||||
}
|
||||
|
||||
@ -228,10 +231,10 @@ static bool dinput_is_pressed(struct dinput_input *di,
|
||||
const struct retro_keybind *binds,
|
||||
unsigned port, unsigned id)
|
||||
{
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
if (id >= RARCH_BIND_LIST_END)
|
||||
return false;
|
||||
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
return dinput_keyboard_pressed(di, bind->key) ||
|
||||
input_joypad_pressed(di->joypad, port, binds, id);
|
||||
}
|
||||
@ -240,19 +243,23 @@ static int16_t dinput_pressed_analog(struct dinput_input *di,
|
||||
const struct retro_keybind *binds,
|
||||
unsigned idx, unsigned id)
|
||||
{
|
||||
unsigned id_minus = 0;
|
||||
unsigned id_plus = 0;
|
||||
const struct retro_keybind *bind_minus, *bind_plus;
|
||||
int16_t pressed_minus = 0, pressed_plus = 0;
|
||||
unsigned id_minus = 0, id_plus = 0;
|
||||
|
||||
input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus);
|
||||
|
||||
const struct retro_keybind *bind_minus = &binds[id_minus];
|
||||
const struct retro_keybind *bind_plus = &binds[id_plus];
|
||||
bind_minus = &binds[id_minus];
|
||||
bind_plus = &binds[id_plus];
|
||||
|
||||
if (!bind_minus->valid || !bind_plus->valid)
|
||||
return 0;
|
||||
|
||||
int16_t pressed_minus =
|
||||
dinput_keyboard_pressed(di, bind_minus->key) ? -0x7fff : 0;
|
||||
int16_t pressed_plus =
|
||||
dinput_keyboard_pressed(di, bind_plus->key) ? 0x7fff : 0;
|
||||
if (dinput_keyboard_pressed(di, bind_minus->key))
|
||||
pressed_minus = -0x7fff;
|
||||
if (dinput_keyboard_pressed(di, bind_plus->key))
|
||||
pressed_plus = 0x7fff;
|
||||
|
||||
return pressed_plus + pressed_minus;
|
||||
}
|
||||
|
||||
@ -311,9 +318,12 @@ static int16_t dinput_mouse_state(struct dinput_input *di, unsigned id)
|
||||
static int16_t dinput_pointer_state(struct dinput_input *di,
|
||||
unsigned idx, unsigned id, bool screen)
|
||||
{
|
||||
bool pointer_down, valid, inside;
|
||||
int x, y;
|
||||
int16_t res_x = 0, res_y = 0, res_screen_x = 0, res_screen_y = 0;
|
||||
unsigned num = 0;
|
||||
struct pointer_status *check_pos = di->pointer_head.next;
|
||||
|
||||
while (check_pos && num < idx)
|
||||
{
|
||||
num++;
|
||||
@ -322,11 +332,11 @@ static int16_t dinput_pointer_state(struct dinput_input *di,
|
||||
if (!check_pos && idx > 0) /* idx = 0 has mouse fallback. */
|
||||
return 0;
|
||||
|
||||
int x = check_pos ? check_pos->pointer_x : di->mouse_x;
|
||||
int y = check_pos ? check_pos->pointer_y : di->mouse_y;
|
||||
bool pointer_down = check_pos ? true : di->mouse_l;
|
||||
x = check_pos ? check_pos->pointer_x : di->mouse_x;
|
||||
y = check_pos ? check_pos->pointer_y : di->mouse_y;
|
||||
pointer_down = check_pos ? true : di->mouse_l;
|
||||
|
||||
bool valid = input_translate_coord_viewport(x, y,
|
||||
valid = input_translate_coord_viewport(x, y,
|
||||
&res_x, &res_y, &res_screen_x, &res_screen_y);
|
||||
|
||||
if (!valid)
|
||||
@ -338,7 +348,7 @@ static int16_t dinput_pointer_state(struct dinput_input *di,
|
||||
res_y = res_screen_y;
|
||||
}
|
||||
|
||||
bool inside = (res_x >= -0x7fff) && (res_y >= -0x7fff);
|
||||
inside = (res_x >= -0x7fff) && (res_y >= -0x7fff);
|
||||
|
||||
if (!inside)
|
||||
return 0;
|
||||
@ -388,22 +398,25 @@ static int16_t dinput_input_state(void *data,
|
||||
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
return dinput_lightgun_state(di, id);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* these are defined in later SDKs, thus ifdeffed. */
|
||||
/* These are defined in later SDKs, thus ifdeffed. */
|
||||
|
||||
#ifndef WM_POINTERUPDATE
|
||||
#define WM_POINTERUPDATE 0x0245
|
||||
#endif
|
||||
|
||||
#ifndef WM_POINTERDOWN
|
||||
#define WM_POINTERDOWN 0x0246
|
||||
#endif
|
||||
|
||||
#ifndef WM_POINTERUP
|
||||
#define WM_POINTERUP 0x0247
|
||||
#endif
|
||||
|
||||
#ifndef GET_POINTERID_WPARAM
|
||||
#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam))
|
||||
#endif
|
||||
@ -412,6 +425,7 @@ static int16_t dinput_input_state(void *data,
|
||||
void dinput_pointer_store_pos(struct pointer_status *pointer, WPARAM lParam)
|
||||
{
|
||||
POINT point;
|
||||
|
||||
point.x = GET_X_LPARAM(lParam);
|
||||
point.y = GET_Y_LPARAM(lParam);
|
||||
ScreenToClient((HWND)driver.video_window, &point);
|
||||
@ -422,8 +436,11 @@ void dinput_pointer_store_pos(struct pointer_status *pointer, WPARAM lParam)
|
||||
void dinput_add_pointer(struct dinput_input *di,
|
||||
struct pointer_status *new_pointer)
|
||||
{
|
||||
struct pointer_status *insert_pos = NULL;
|
||||
|
||||
new_pointer->next = NULL;
|
||||
struct pointer_status *insert_pos = &di->pointer_head;
|
||||
insert_pos = &di->pointer_head;
|
||||
|
||||
while (insert_pos->next)
|
||||
insert_pos = insert_pos->next;
|
||||
insert_pos->next = new_pointer;
|
||||
@ -432,11 +449,13 @@ void dinput_add_pointer(struct dinput_input *di,
|
||||
void dinput_delete_pointer(struct dinput_input *di, int pointer_id)
|
||||
{
|
||||
struct pointer_status *check_pos = &di->pointer_head;
|
||||
|
||||
while (check_pos && check_pos->next)
|
||||
{
|
||||
if (check_pos->next->pointer_id == pointer_id)
|
||||
{
|
||||
struct pointer_status *to_delete = check_pos->next;
|
||||
|
||||
check_pos->next = check_pos->next->next;
|
||||
free(to_delete);
|
||||
}
|
||||
@ -448,6 +467,7 @@ struct pointer_status *dinput_find_pointer(struct dinput_input *di,
|
||||
int pointer_id)
|
||||
{
|
||||
struct pointer_status *check_pos = di->pointer_head.next;
|
||||
|
||||
while (check_pos)
|
||||
{
|
||||
if (check_pos->pointer_id == pointer_id)
|
||||
@ -460,9 +480,11 @@ struct pointer_status *dinput_find_pointer(struct dinput_input *di,
|
||||
void dinput_clear_pointers(struct dinput_input *di)
|
||||
{
|
||||
struct pointer_status *pointer = &di->pointer_head;
|
||||
|
||||
while (pointer->next)
|
||||
{
|
||||
struct pointer_status *del = pointer->next;
|
||||
|
||||
pointer->next = pointer->next->next;
|
||||
free(del);
|
||||
}
|
||||
@ -475,11 +497,11 @@ bool dinput_handle_message(void *dinput, UINT message, WPARAM wParam, LPARAM lPa
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input *)dinput;
|
||||
/* WM_POINTERDOWN : Arrives for each new touch event
|
||||
* with a new ID - add to list.
|
||||
* with a new ID - add to list.
|
||||
* WM_POINTERUP : Arrives once the pointer is no
|
||||
* longer down - remove from list.
|
||||
* longer down - remove from list.
|
||||
* WM_POINTERUPDATE : arrives for both pressed and
|
||||
* hovering pointers - ignore hovering
|
||||
* hovering pointers - ignore hovering
|
||||
*/
|
||||
|
||||
switch (message)
|
||||
@ -488,6 +510,7 @@ bool dinput_handle_message(void *dinput, UINT message, WPARAM wParam, LPARAM lPa
|
||||
{
|
||||
struct pointer_status *new_pointer =
|
||||
(struct pointer_status *)malloc(sizeof(struct pointer_status));
|
||||
|
||||
if (!new_pointer)
|
||||
{
|
||||
RARCH_ERR("dinput_handle_message: pointer allocation in WM_POINTERDOWN failed.\n");
|
||||
@ -555,6 +578,7 @@ static void dinput_free(void *data)
|
||||
static void dinput_grab_mouse(void *data, bool state)
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input*)data;
|
||||
|
||||
IDirectInputDevice8_Unacquire(di->mouse);
|
||||
IDirectInputDevice8_SetCooperativeLevel(di->mouse,
|
||||
(HWND)driver.video_window,
|
||||
@ -568,12 +592,16 @@ static bool dinput_set_rumble(void *data, unsigned port,
|
||||
enum retro_rumble_effect effect, uint16_t strength)
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input*)data;
|
||||
if (!di)
|
||||
return false;
|
||||
return input_joypad_set_rumble(di->joypad, port, effect, strength);
|
||||
}
|
||||
|
||||
static const rarch_joypad_driver_t *dinput_get_joypad_driver(void *data)
|
||||
{
|
||||
struct dinput_input *di = (struct dinput_input*)data;
|
||||
if (!di)
|
||||
return false;
|
||||
return di->joypad;
|
||||
}
|
||||
|
||||
@ -641,9 +669,9 @@ static void dinput_joypad_destroy(void)
|
||||
static BOOL CALLBACK enum_axes_cb(
|
||||
const DIDEVICEOBJECTINSTANCE *inst, void *p)
|
||||
{
|
||||
DIPROPRANGE range;
|
||||
LPDIRECTINPUTDEVICE8 joypad = (LPDIRECTINPUTDEVICE8)p;
|
||||
|
||||
DIPROPRANGE range;
|
||||
memset(&range, 0, sizeof(range));
|
||||
range.diph.dwSize = sizeof(DIPROPRANGE);
|
||||
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
@ -657,17 +685,16 @@ static BOOL CALLBACK enum_axes_cb(
|
||||
}
|
||||
|
||||
static const GUID common_xinput_guids[] = {
|
||||
{MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, // valve streaming pad
|
||||
{MAKELONG(0x045E, 0x02A1),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, // wired 360 pad
|
||||
{MAKELONG(0x045E, 0x028E),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}} // wireless 360 pad
|
||||
{MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Valve streaming pad */
|
||||
{MAKELONG(0x045E, 0x02A1),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Wired 360 pad */
|
||||
{MAKELONG(0x045E, 0x028E),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}} /* wireless 360 pad */
|
||||
};
|
||||
|
||||
/* Based on SDL2's implementation. */
|
||||
static bool guid_is_xinput_device(const GUID* product_guid)
|
||||
{
|
||||
unsigned i, num_raw_devs = 0;
|
||||
PRAWINPUTDEVICELIST raw_devs = NULL;
|
||||
unsigned num_raw_devs = 0;
|
||||
unsigned i;
|
||||
|
||||
/* Check for well known XInput device GUIDs,
|
||||
* thereby removing the need for the IG_ check.
|
||||
@ -711,6 +738,7 @@ static bool guid_is_xinput_device(const GUID* product_guid)
|
||||
UINT nameSize = sizeof(devName);
|
||||
|
||||
rdi.cbSize = sizeof (rdi);
|
||||
|
||||
if ((raw_devs[i].dwType == RIM_TYPEHID) &&
|
||||
(GetRawInputDeviceInfoA(raw_devs[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
|
||||
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)product_guid->Data1)) &&
|
||||
@ -735,11 +763,15 @@ static unsigned g_last_xinput_pad_idx;
|
||||
|
||||
static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
|
||||
{
|
||||
bool is_xinput_pad;
|
||||
LPDIRECTINPUTDEVICE8 *pad = NULL;
|
||||
|
||||
(void)p;
|
||||
|
||||
if (g_joypad_cnt == MAX_USERS)
|
||||
return DIENUM_STOP;
|
||||
|
||||
LPDIRECTINPUTDEVICE8 *pad = &g_pads[g_joypad_cnt].joypad;
|
||||
pad = &g_pads[g_joypad_cnt].joypad;
|
||||
|
||||
#ifdef __cplusplus
|
||||
if (FAILED(IDirectInput8_CreateDevice(
|
||||
@ -754,10 +786,10 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
|
||||
|
||||
#ifdef HAVE_WINXINPUT
|
||||
#if 0
|
||||
bool is_xinput_pad = g_xinput_block_pads
|
||||
is_xinput_pad = g_xinput_block_pads
|
||||
&& name_is_xinput_pad(inst->tszProductName);
|
||||
#endif
|
||||
bool is_xinput_pad = g_xinput_block_pads
|
||||
is_xinput_pad = g_xinput_block_pads
|
||||
&& guid_is_xinput_device(&inst->guidProduct);
|
||||
|
||||
if (is_xinput_pad)
|
||||
@ -796,6 +828,7 @@ enum_iteration_done:
|
||||
static bool dinput_joypad_init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (!dinput_init_context())
|
||||
return false;
|
||||
|
||||
@ -816,27 +849,29 @@ static bool dinput_joypad_init(void)
|
||||
|
||||
static bool dinput_joypad_button(unsigned port_num, uint16_t joykey)
|
||||
{
|
||||
const struct dinput_joypad *pad = NULL;
|
||||
|
||||
if (joykey == NO_BTN)
|
||||
return false;
|
||||
|
||||
const struct dinput_joypad *pad = &g_pads[port_num];
|
||||
pad = &g_pads[port_num];
|
||||
if (!pad->joypad)
|
||||
return false;
|
||||
|
||||
// Check hat.
|
||||
/* Check hat. */
|
||||
if (GET_HAT_DIR(joykey))
|
||||
{
|
||||
unsigned hat = GET_HAT(joykey);
|
||||
|
||||
unsigned pov;
|
||||
unsigned hat = GET_HAT(joykey);
|
||||
unsigned elems = sizeof(pad->joy_state.rgdwPOV) /
|
||||
sizeof(pad->joy_state.rgdwPOV[0]);
|
||||
|
||||
if (hat >= elems)
|
||||
return false;
|
||||
|
||||
unsigned pov = pad->joy_state.rgdwPOV[hat];
|
||||
pov = pad->joy_state.rgdwPOV[hat];
|
||||
|
||||
// Magic numbers I'm not sure where originate from.
|
||||
/* Magic numbers I'm not sure where originate from. */
|
||||
if (pov < 36000)
|
||||
{
|
||||
switch (GET_HAT_DIR(joykey))
|
||||
@ -868,19 +903,19 @@ static bool dinput_joypad_button(unsigned port_num, uint16_t joykey)
|
||||
|
||||
static int16_t dinput_joypad_axis(unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
const struct dinput_joypad *pad = &g_pads[port_num];
|
||||
if (!pad->joypad)
|
||||
return 0;
|
||||
|
||||
const struct dinput_joypad *pad = NULL;
|
||||
int val = 0;
|
||||
|
||||
int axis = -1;
|
||||
bool is_neg = false;
|
||||
bool is_pos = false;
|
||||
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
pad = &g_pads[port_num];
|
||||
if (!pad->joypad)
|
||||
return 0;
|
||||
|
||||
if (AXIS_NEG_GET(joyaxis) <= 5)
|
||||
{
|
||||
axis = AXIS_NEG_GET(joyaxis);
|
||||
@ -928,30 +963,31 @@ static void dinput_joypad_poll(void)
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
struct dinput_joypad *pad = &g_pads[i];
|
||||
bool polled = g_xinput_pad_indexes[i] < 0;
|
||||
|
||||
if (pad->joypad && g_xinput_pad_indexes[i] < 0)
|
||||
if (!pad || !pad->joypad || !polled)
|
||||
continue;
|
||||
|
||||
memset(&pad->joy_state, 0, sizeof(pad->joy_state));
|
||||
|
||||
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
|
||||
{
|
||||
memset(&pad->joy_state, 0, sizeof(pad->joy_state));
|
||||
|
||||
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
|
||||
if (FAILED(IDirectInputDevice8_Acquire(pad->joypad)))
|
||||
{
|
||||
if (FAILED(IDirectInputDevice8_Acquire(pad->joypad)))
|
||||
{
|
||||
memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If this fails, something *really* bad must have happened. */
|
||||
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
|
||||
{
|
||||
memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
|
||||
continue;
|
||||
}
|
||||
memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
|
||||
continue;
|
||||
}
|
||||
|
||||
IDirectInputDevice8_GetDeviceState(pad->joypad,
|
||||
sizeof(DIJOYSTATE2), &pad->joy_state);
|
||||
/* If this fails, something *really* bad must have happened. */
|
||||
if (FAILED(IDirectInputDevice8_Poll(pad->joypad)))
|
||||
{
|
||||
memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
IDirectInputDevice8_GetDeviceState(pad->joypad,
|
||||
sizeof(DIJOYSTATE2), &pad->joy_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,9 +104,9 @@ static uint64_t gx_input_get_capabilities(void *data)
|
||||
static const rarch_joypad_driver_t *gx_input_get_joypad_driver(void *data)
|
||||
{
|
||||
gx_input_t *gx = (gx_input_t*)data;
|
||||
if (gx)
|
||||
return gx->joypad;
|
||||
return NULL;
|
||||
if (!gx)
|
||||
return NULL;
|
||||
return gx->joypad;
|
||||
}
|
||||
|
||||
input_driver_t input_gx = {
|
||||
|
@ -57,7 +57,10 @@ static void linuxraw_exitGracefully(int sig)
|
||||
|
||||
static void *linuxraw_input_init(void)
|
||||
{
|
||||
// only work on terminals
|
||||
linuxraw_input_t *linuxraw;
|
||||
struct sigaction sa;
|
||||
|
||||
/* Only work on terminals. */
|
||||
if (!isatty(0))
|
||||
return NULL;
|
||||
|
||||
@ -67,7 +70,7 @@ static void *linuxraw_input_init(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linuxraw_input_t *linuxraw = (linuxraw_input_t*)calloc(1, sizeof(*linuxraw));
|
||||
linuxraw = (linuxraw_input_t*)calloc(1, sizeof(*linuxraw));
|
||||
if (!linuxraw)
|
||||
return NULL;
|
||||
|
||||
@ -96,7 +99,6 @@ static void *linuxraw_input_init(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = linuxraw_exitGracefully;
|
||||
sa.sa_flags = SA_RESTART | SA_RESETHAND;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
@ -118,6 +120,7 @@ static void *linuxraw_input_init(void)
|
||||
/* We need to disable use of stdin command interface if
|
||||
* stdin is supposed to be used for input. */
|
||||
driver.stdin_claimed = true;
|
||||
|
||||
return linuxraw;
|
||||
}
|
||||
|
||||
@ -130,32 +133,37 @@ static bool linuxraw_key_pressed(linuxraw_input_t *linuxraw, int key)
|
||||
static bool linuxraw_is_pressed(linuxraw_input_t *linuxraw,
|
||||
const struct retro_keybind *binds, unsigned id)
|
||||
{
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
{
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
if (bind)
|
||||
return bind->valid && linuxraw_key_pressed(linuxraw, binds[id].key);
|
||||
}
|
||||
return false;
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
|
||||
if (id >= RARCH_BIND_LIST_END)
|
||||
return false;
|
||||
if (!bind)
|
||||
return false;
|
||||
|
||||
return bind->valid && linuxraw_key_pressed(linuxraw, binds[id].key);
|
||||
}
|
||||
|
||||
static int16_t linuxraw_analog_pressed(linuxraw_input_t *linuxraw,
|
||||
const struct retro_keybind *binds, unsigned idx, unsigned id)
|
||||
{
|
||||
int16_t pressed_minus = 0, pressed_plus = 0;
|
||||
unsigned id_minus = 0;
|
||||
unsigned id_plus = 0;
|
||||
input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus);
|
||||
|
||||
int16_t pressed_minus = linuxraw_is_pressed(linuxraw,
|
||||
binds, id_minus) ? -0x7fff : 0;
|
||||
int16_t pressed_plus = linuxraw_is_pressed(linuxraw,
|
||||
binds, id_plus) ? 0x7fff : 0;
|
||||
if (linuxraw_is_pressed(linuxraw, binds, id_minus))
|
||||
pressed_minus = -0x7fff;
|
||||
if (linuxraw_is_pressed(linuxraw, binds, id_plus))
|
||||
pressed_plus = 0x7fff;
|
||||
|
||||
return pressed_plus + pressed_minus;
|
||||
}
|
||||
|
||||
static bool linuxraw_bind_button_pressed(void *data, int key)
|
||||
{
|
||||
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||
if (!linuxraw)
|
||||
return false;
|
||||
return linuxraw_is_pressed(linuxraw, g_settings.input.binds[0], key) ||
|
||||
input_joypad_pressed(linuxraw->joypad, 0, g_settings.input.binds[0], key);
|
||||
}
|
||||
@ -178,10 +186,9 @@ static int16_t linuxraw_input_state(void *data,
|
||||
if (!ret)
|
||||
ret = input_joypad_analog(linuxraw->joypad, port, idx, id, binds[port]);
|
||||
return ret;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void linuxraw_input_free(void *data)
|
||||
@ -202,31 +209,33 @@ static bool linuxraw_set_rumble(void *data, unsigned port,
|
||||
enum retro_rumble_effect effect, uint16_t strength)
|
||||
{
|
||||
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||
if (linuxraw)
|
||||
return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength);
|
||||
return false;
|
||||
if (!linuxraw)
|
||||
return false;
|
||||
return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength);
|
||||
}
|
||||
|
||||
static const rarch_joypad_driver_t *linuxraw_get_joypad_driver(void *data)
|
||||
{
|
||||
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||
if (linuxraw)
|
||||
return linuxraw->joypad;
|
||||
return NULL;
|
||||
if (!linuxraw)
|
||||
return false;
|
||||
return linuxraw->joypad;
|
||||
}
|
||||
|
||||
static void linuxraw_input_poll(void *data)
|
||||
{
|
||||
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||
uint8_t c;
|
||||
uint16_t t;
|
||||
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
|
||||
|
||||
while (read(STDIN_FILENO, &c, 1) > 0)
|
||||
{
|
||||
bool pressed;
|
||||
|
||||
if (c == KEY_C && (linuxraw->state[KEY_LEFTCTRL] || linuxraw->state[KEY_RIGHTCTRL]))
|
||||
kill(getpid(), SIGINT);
|
||||
|
||||
bool pressed = !(c & 0x80);
|
||||
pressed = !(c & 0x80);
|
||||
c &= ~0x80;
|
||||
|
||||
// ignore extended scancodes
|
||||
@ -242,9 +251,10 @@ static void linuxraw_input_poll(void *data)
|
||||
|
||||
static uint64_t linuxraw_get_capabilities(void *data)
|
||||
{
|
||||
(void)data;
|
||||
uint64_t caps = 0;
|
||||
|
||||
(void)data;
|
||||
|
||||
caps |= (1 << RETRO_DEVICE_JOYPAD);
|
||||
caps |= (1 << RETRO_DEVICE_ANALOG);
|
||||
|
||||
|
@ -48,6 +48,7 @@ static bool g_hotplug;
|
||||
static void poll_pad(struct linuxraw_joypad *pad)
|
||||
{
|
||||
struct js_event event;
|
||||
|
||||
while (read(pad->fd, &event, sizeof(event)) == (ssize_t)sizeof(event))
|
||||
{
|
||||
unsigned type = event.type & ~JS_EVENT_INIT;
|
||||
@ -120,21 +121,26 @@ static void handle_plugged_pad(void)
|
||||
int i, rc;
|
||||
size_t event_size = sizeof(struct inotify_event) + NAME_MAX + 1;
|
||||
uint8_t *event_buf = (uint8_t*)calloc(1, event_size);
|
||||
|
||||
if (!event_buf)
|
||||
return;
|
||||
|
||||
while ((rc = read(g_notify, event_buf, event_size)) >= 0)
|
||||
{
|
||||
struct inotify_event *event = NULL;
|
||||
// Can read multiple events in one read() call.
|
||||
|
||||
/* Can read multiple events in one read() call. */
|
||||
|
||||
for (i = 0; i < rc; i += event->len + sizeof(struct inotify_event))
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
event = (struct inotify_event*)&event_buf[i];
|
||||
|
||||
if (strstr(event->name, "js") != event->name)
|
||||
continue;
|
||||
|
||||
unsigned idx = strtoul(event->name + 2, NULL, 0);
|
||||
idx = strtoul(event->name + 2, NULL, 0);
|
||||
if (idx >= MAX_USERS)
|
||||
continue;
|
||||
|
||||
@ -165,9 +171,10 @@ static void handle_plugged_pad(void)
|
||||
// Sometimes, device will be created before acess to it is established.
|
||||
else if (event->mask & (IN_CREATE | IN_ATTRIB))
|
||||
{
|
||||
bool ret;
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", event->name);
|
||||
bool ret = linuxraw_joypad_init_pad(path, &linuxraw_pads[idx]);
|
||||
ret = linuxraw_joypad_init_pad(path, &linuxraw_pads[idx]);
|
||||
|
||||
if (*linuxraw_pads[idx].ident && ret)
|
||||
/* TODO - implement VID/PID? */
|
||||
@ -207,17 +214,22 @@ static void linuxraw_joypad_setup_notify(void)
|
||||
static bool linuxraw_joypad_init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
g_epoll = epoll_create(MAX_USERS + 1);
|
||||
if (g_epoll < 0)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct linuxraw_joypad *pad = (struct linuxraw_joypad*)&linuxraw_pads[i];
|
||||
|
||||
if (!pad)
|
||||
continue;
|
||||
|
||||
pad->fd = -1;
|
||||
pad->ident = g_settings.input.device_names[i];
|
||||
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/dev/input/js%u", i);
|
||||
|
||||
/* TODO - implement VID/PID? */
|
||||
@ -233,9 +245,10 @@ static bool linuxraw_joypad_init(void)
|
||||
g_notify = inotify_init();
|
||||
if (g_notify >= 0)
|
||||
{
|
||||
struct epoll_event event;
|
||||
|
||||
linuxraw_joypad_setup_notify();
|
||||
|
||||
struct epoll_event event;
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = NULL;
|
||||
epoll_ctl(g_epoll, EPOLL_CTL_ADD, g_notify, &event);
|
||||
@ -249,6 +262,7 @@ static bool linuxraw_joypad_init(void)
|
||||
static void linuxraw_joypad_destroy(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
if (linuxraw_pads[i].fd >= 0)
|
||||
@ -256,6 +270,7 @@ static void linuxraw_joypad_destroy(void)
|
||||
}
|
||||
|
||||
memset(linuxraw_pads, 0, sizeof(linuxraw_pads));
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
linuxraw_pads[i].fd = -1;
|
||||
|
||||
@ -273,26 +288,27 @@ static void linuxraw_joypad_destroy(void)
|
||||
static bool linuxraw_joypad_button(unsigned port, uint16_t joykey)
|
||||
{
|
||||
const struct linuxraw_joypad *pad = (const struct linuxraw_joypad*)&linuxraw_pads[port];
|
||||
if (pad)
|
||||
return joykey < NUM_BUTTONS && BIT32_GET(pad->buttons, joykey);
|
||||
return false;
|
||||
if (!pad)
|
||||
return false;
|
||||
return joykey < NUM_BUTTONS && BIT32_GET(pad->buttons, joykey);
|
||||
}
|
||||
|
||||
static int16_t linuxraw_joypad_axis(unsigned port, uint32_t joyaxis)
|
||||
{
|
||||
int16_t val = 0;
|
||||
const struct linuxraw_joypad *pad = NULL;
|
||||
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
const struct linuxraw_joypad *pad = (const struct linuxraw_joypad*)
|
||||
&linuxraw_pads[port];
|
||||
pad = (const struct linuxraw_joypad*)&linuxraw_pads[port];
|
||||
|
||||
int16_t val = 0;
|
||||
if (AXIS_NEG_GET(joyaxis) < NUM_AXES)
|
||||
{
|
||||
val = pad->axes[AXIS_NEG_GET(joyaxis)];
|
||||
if (val > 0)
|
||||
val = 0;
|
||||
// Kernel returns values in range [-0x7fff, 0x7fff].
|
||||
/* Kernel returns values in range [-0x7fff, 0x7fff]. */
|
||||
}
|
||||
else if (AXIS_POS_GET(joyaxis) < NUM_AXES)
|
||||
{
|
||||
|
@ -30,8 +30,9 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
// Check the definitions do not already exist.
|
||||
// Official and mingw xinput headers have different include guards
|
||||
/* Check if the definitions do not already exist.
|
||||
* Official and mingw xinput headers have different include guards.
|
||||
*/
|
||||
#if ((!_XINPUT_H_) && (!__WINE_XINPUT_H))
|
||||
|
||||
#define XINPUT_GAMEPAD_DPAD_UP 0x0001
|
||||
@ -74,7 +75,7 @@ typedef struct
|
||||
|
||||
#endif
|
||||
|
||||
// Guide constant is not officially documented
|
||||
/* Guide constant is not officially documented. */
|
||||
#define XINPUT_GAMEPAD_GUIDE 0x0400
|
||||
|
||||
#ifndef ERROR_DEVICE_NOT_CONNECTED
|
||||
@ -85,25 +86,28 @@ typedef struct
|
||||
#error Cannot compile xinput without dinput.
|
||||
#endif
|
||||
|
||||
// Due to 360 pads showing up under both XI and DI, and since we are going
|
||||
// to have to pass through unhandled joypad numbers to DI, a slightly ugly
|
||||
// hack is required here. dinput_joypad_init will fill this.
|
||||
// For each pad index, the appropriate entry will be set to -1 if it is not
|
||||
// a 360 pad, or the correct XInput user number (0..3 inclusive) if it is.
|
||||
/* Due to 360 pads showing up under both XInput and DirectInput,
|
||||
* and since we are going to have to pass through unhandled
|
||||
* joypad numbers to DirectInput, a slightly ugly
|
||||
* hack is required here. dinput_joypad_init will fill this.
|
||||
*
|
||||
* For each pad index, the appropriate entry will be set to -1 if it is not
|
||||
* a 360 pad, or the correct XInput user number (0..3 inclusive) if it is.
|
||||
*/
|
||||
extern int g_xinput_pad_indexes[MAX_USERS];
|
||||
extern bool g_xinput_block_pads;
|
||||
|
||||
// For xinput1_n.dll
|
||||
/* For xinput1_n.dll */
|
||||
static HINSTANCE g_winxinput_dll;
|
||||
|
||||
// Function pointer, to be assigned with GetProcAddress
|
||||
/* Function pointer, to be assigned with GetProcAddress */
|
||||
typedef uint32_t (__stdcall *XInputGetStateEx_t)(uint32_t, XINPUT_STATE*);
|
||||
static XInputGetStateEx_t g_XInputGetStateEx;
|
||||
|
||||
typedef uint32_t (__stdcall *XInputSetState_t)(uint32_t, XINPUT_VIBRATION*);
|
||||
static XInputSetState_t g_XInputSetState;
|
||||
|
||||
// Guide button may or may not be available
|
||||
/* Guide button may or may not be available */
|
||||
static bool g_winxinput_guide_button_supported;
|
||||
|
||||
typedef struct
|
||||
@ -121,8 +125,9 @@ static inline int pad_index_to_xuser_index(unsigned pad)
|
||||
return g_xinput_pad_indexes[pad];
|
||||
}
|
||||
|
||||
// Generic "XInput" instead of "Xbox 360", because there are
|
||||
// some other non-xbox third party PC controllers.
|
||||
/* Generic "XInput" instead of "Xbox 360", because there are
|
||||
* some other non-xbox third party PC controllers.
|
||||
*/
|
||||
static const char* const XBOX_CONTROLLER_NAMES[4] =
|
||||
{
|
||||
"XInput Controller (User 1)",
|
||||
@ -137,26 +142,30 @@ const char* winxinput_joypad_name (unsigned pad)
|
||||
|
||||
if (xuser < 0)
|
||||
return dinput_joypad.name(pad);
|
||||
// TODO: Different name if disconnected?
|
||||
/* TODO: Different name if disconnected? */
|
||||
return XBOX_CONTROLLER_NAMES[xuser];
|
||||
}
|
||||
|
||||
static bool winxinput_joypad_init(void)
|
||||
{
|
||||
unsigned i, autoconf_pad;
|
||||
XINPUT_STATE dummy_state;
|
||||
const char *version = "1.4";
|
||||
|
||||
g_winxinput_dll = NULL;
|
||||
|
||||
// Find the correct path to load the DLL from.
|
||||
// Usually this will be from the system directory,
|
||||
// but occasionally a user may wish to use a third-party
|
||||
// wrapper DLL (such as x360ce); support these by checking
|
||||
// the working directory first.
|
||||
/* Find the correct path to load the DLL from.
|
||||
* Usually this will be from the system directory,
|
||||
* but occasionally a user may wish to use a third-party
|
||||
* wrapper DLL (such as x360ce); support these by checking
|
||||
* the working directory first.
|
||||
*
|
||||
* No need to check for existance as we will be checking LoadLibrary's
|
||||
* success anyway.
|
||||
*/
|
||||
|
||||
// No need to check for existance as we will be checking LoadLibrary's
|
||||
// success anyway.
|
||||
|
||||
const char *version = "1.4";
|
||||
g_winxinput_dll = LoadLibrary("xinput1_4.dll"); // Using dylib_* complicates building joyconfig.
|
||||
/* Using dylib_* complicates building joyconfig. */
|
||||
g_winxinput_dll = LoadLibrary("xinput1_4.dll");
|
||||
if (!g_winxinput_dll)
|
||||
{
|
||||
g_winxinput_dll = LoadLibrary("xinput1_3.dll");
|
||||
@ -171,22 +180,25 @@ static bool winxinput_joypad_init(void)
|
||||
|
||||
RARCH_LOG("Found XInput v%s.\n", version);
|
||||
|
||||
// If we get here then an xinput DLL is correctly loaded.
|
||||
// First try to load ordinal 100 (XInputGetStateEx).
|
||||
/* If we get here then an xinput DLL is correctly loaded.
|
||||
* First try to load ordinal 100 (XInputGetStateEx).
|
||||
*/
|
||||
g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (const char*)100);
|
||||
g_winxinput_guide_button_supported = true;
|
||||
|
||||
if (!g_XInputGetStateEx)
|
||||
{
|
||||
// no ordinal 100. (Presumably a wrapper.) Load the ordinary
|
||||
// XInputGetState, at the cost of losing guide button support.
|
||||
/* no ordinal 100. (Presumably a wrapper.) Load the ordinary
|
||||
* XInputGetState, at the cost of losing guide button support.
|
||||
*/
|
||||
g_winxinput_guide_button_supported = false;
|
||||
g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState");
|
||||
|
||||
if (!g_XInputGetStateEx)
|
||||
{
|
||||
RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n");
|
||||
FreeLibrary(g_winxinput_dll);
|
||||
return false; // DLL was loaded but did not contain the correct function.
|
||||
return false; /* DLL was loaded but did not contain the correct function. */
|
||||
}
|
||||
RARCH_WARN("XInput: No guide button support.\n");
|
||||
}
|
||||
@ -196,15 +208,14 @@ static bool winxinput_joypad_init(void)
|
||||
{
|
||||
RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n");
|
||||
FreeLibrary(g_winxinput_dll);
|
||||
return false; // DLL was loaded but did not contain the correct function.
|
||||
return false; /* DLL was loaded but did not contain the correct function. */
|
||||
}
|
||||
|
||||
// Zero out the states
|
||||
/* Zero out the states. */
|
||||
for (i = 0; i < 4; ++i)
|
||||
memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state));
|
||||
|
||||
// Do a dummy poll to check which controllers are connected.
|
||||
XINPUT_STATE dummy_state;
|
||||
/* Do a dummy poll to check which controllers are connected. */
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
g_winxinput_states[i].connected = !(g_XInputGetStateEx(i, &dummy_state) == ERROR_DEVICE_NOT_CONNECTED);
|
||||
@ -220,8 +231,8 @@ static bool winxinput_joypad_init(void)
|
||||
|
||||
g_xinput_block_pads = true;
|
||||
|
||||
// We're going to have to be buddies with dinput if we want to be able
|
||||
// to use XI and non-XI controllers together.
|
||||
/* We're going to have to be buddies with dinput if we want to be able
|
||||
* to use XInput and non-XInput controllers together. */
|
||||
if (!dinput_joypad.init())
|
||||
{
|
||||
g_xinput_block_pads = false;
|
||||
@ -262,6 +273,7 @@ static void winxinput_joypad_destroy(void)
|
||||
memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state));
|
||||
|
||||
FreeLibrary(g_winxinput_dll);
|
||||
|
||||
g_winxinput_dll = NULL;
|
||||
g_XInputGetStateEx = NULL;
|
||||
g_XInputSetState = NULL;
|
||||
@ -270,9 +282,9 @@ static void winxinput_joypad_destroy(void)
|
||||
g_xinput_block_pads = false;
|
||||
}
|
||||
|
||||
// Buttons are provided by XInput as bits of a uint16.
|
||||
// Map from rarch button index (0..10) to a mask to bitwise-& the buttons against.
|
||||
// dpad is handled seperately.
|
||||
/* Buttons are provided by XInput as bits of a uint16.
|
||||
* Map from rarch button index (0..10) to a mask to bitwise-& the buttons against.
|
||||
* dpad is handled seperately. */
|
||||
static const uint16_t button_index_to_bitmap_code[] = {
|
||||
XINPUT_GAMEPAD_A,
|
||||
XINPUT_GAMEPAD_B,
|
||||
@ -289,17 +301,20 @@ static const uint16_t button_index_to_bitmap_code[] = {
|
||||
|
||||
static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey)
|
||||
{
|
||||
uint16_t btn_word;
|
||||
int xuser;
|
||||
|
||||
if (joykey == NO_BTN)
|
||||
return false;
|
||||
|
||||
int xuser = pad_index_to_xuser_index(port_num);
|
||||
xuser = pad_index_to_xuser_index(port_num);
|
||||
if (xuser == -1)
|
||||
return dinput_joypad.button(port_num, joykey);
|
||||
|
||||
if (!(g_winxinput_states[xuser].connected))
|
||||
return false;
|
||||
|
||||
uint16_t btn_word = g_winxinput_states[xuser].xstate.Gamepad.wButtons;
|
||||
btn_word = g_winxinput_states[xuser].xstate.Gamepad.wButtons;
|
||||
|
||||
if (GET_HAT_DIR(joykey))
|
||||
{
|
||||
@ -329,10 +344,17 @@ static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey)
|
||||
|
||||
static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
int xuser;
|
||||
int16_t val = 0;
|
||||
int axis = -1;
|
||||
|
||||
bool is_neg = false;
|
||||
bool is_pos = false;
|
||||
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
int xuser = pad_index_to_xuser_index(port_num);
|
||||
xuser = pad_index_to_xuser_index(port_num);
|
||||
|
||||
if (xuser == -1)
|
||||
return dinput_joypad.axis(port_num, joyaxis);
|
||||
@ -340,12 +362,6 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis)
|
||||
if (!(g_winxinput_states[xuser].connected))
|
||||
return 0;
|
||||
|
||||
int16_t val = 0;
|
||||
int axis = -1;
|
||||
|
||||
bool is_neg = false;
|
||||
bool is_pos = false;
|
||||
|
||||
/* triggers (axes 4,5) cannot be negative */
|
||||
if (AXIS_NEG_GET(joyaxis) <= 3)
|
||||
{
|
||||
@ -397,6 +413,7 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis)
|
||||
static void winxinput_joypad_poll(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
if (g_winxinput_states[i].connected)
|
||||
@ -404,9 +421,7 @@ static void winxinput_joypad_poll(void)
|
||||
if (g_XInputGetStateEx(i,
|
||||
&(g_winxinput_states[i].xstate))
|
||||
== ERROR_DEVICE_NOT_CONNECTED)
|
||||
{
|
||||
g_winxinput_states[i].connected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,6 +432,7 @@ static bool winxinput_joypad_rumble(unsigned pad,
|
||||
enum retro_rumble_effect effect, uint16_t strength)
|
||||
{
|
||||
int xuser = pad_index_to_xuser_index(pad);
|
||||
|
||||
if (xuser == -1)
|
||||
{
|
||||
if (dinput_joypad.set_rumble)
|
||||
|
Loading…
x
Reference in New Issue
Block a user