diff --git a/android/native/jni/input_android.c b/android/native/jni/input_android.c index 193dae7530..d7ac140604 100644 --- a/android/native/jni/input_android.c +++ b/android/native/jni/input_android.c @@ -33,6 +33,12 @@ typedef struct float dzone_max; } dpad_values_t; +typedef struct +{ + int16_t lx, ly; + int16_t rx, ry; +} analog_t; + #define PRESSED_UP(x, y) ((y <= dzone_min)) #define PRESSED_DOWN(x, y) ((y >= dzone_max)) #define PRESSED_LEFT(x, y) ((x <= dzone_min)) @@ -43,7 +49,7 @@ static int state_device_ids[MAX_PADS]; static uint64_t state[MAX_PADS]; static uint64_t keycode_lut[LAST_KEYCODE]; dpad_values_t dpad_state[MAX_PADS]; - +analog_t analog_state[MAX_PADS]; struct input_pointer { @@ -61,10 +67,12 @@ enum AXIS_Z = 11, AXIS_RZ = 14, AXIS_HAT_X = 15, - AXIS_HAT_Y = 16 + AXIS_HAT_Y = 16, + AXIS_LTRIGGER = 17, + AXIS_RTRIGGER = 18, }; -void (*engine_handle_dpad)(AInputEvent*, size_t, int, char*, size_t, int, bool); +void (*engine_handle_dpad)(AInputEvent*, size_t, int, char*, size_t, int, bool, unsigned); extern float AMotionEvent_getAxisValue(const AInputEvent* motion_event, int32_t axis, size_t pointer_index); @@ -183,7 +191,7 @@ void engine_handle_cmd(void) static void engine_handle_dpad_default(AInputEvent *event, size_t motion_pointer, int state_id, char *msg, size_t msg_sizeof, - int source, bool debug_enable) + int source, bool debug_enable, unsigned emulation) { uint64_t *state_cur = &state[state_id]; float dzone_min = dpad_state[state_id].dzone_min; @@ -194,10 +202,14 @@ static void engine_handle_dpad_default(AInputEvent *event, *state_cur &= ~((1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)); - *state_cur |= PRESSED_LEFT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; - *state_cur |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; - *state_cur |= PRESSED_UP(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0; - *state_cur |= PRESSED_DOWN(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; + + if (emulation == ANALOG_DPAD_LSTICK) + { + *state_cur |= PRESSED_LEFT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; + *state_cur |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; + *state_cur |= PRESSED_UP(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0; + *state_cur |= PRESSED_DOWN(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; + } if (debug_enable) snprintf(msg, msg_sizeof, "Pad %d : x = %.2f, y = %.2f, src %d.\n", @@ -206,7 +218,7 @@ static void engine_handle_dpad_default(AInputEvent *event, static void engine_handle_dpad_getaxisvalue(AInputEvent *event, size_t motion_pointer, int state_id, char *msg, size_t msg_sizeof, int source, - bool debug_enable) + bool debug_enable, unsigned emulation) { uint64_t *state_cur = &state[state_id]; float dzone_min = dpad_state[state_id].dzone_min; @@ -217,20 +229,23 @@ static void engine_handle_dpad_getaxisvalue(AInputEvent *event, float rz = AMotionEvent_getAxisValue(event, AXIS_RZ, motion_pointer); float hatx = AMotionEvent_getAxisValue(event, AXIS_HAT_X, motion_pointer); float haty = AMotionEvent_getAxisValue(event, AXIS_HAT_Y, motion_pointer); + float ltrig = AMotionEvent_getAxisValue(event, AXIS_LTRIGGER, motion_pointer); + float rtrig = AMotionEvent_getAxisValue(event, AXIS_RTRIGGER, motion_pointer); *state_cur &= ~((1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | + (1ULL << RETRO_DEVICE_ID_JOYPAD_L2) | (1ULL << RETRO_DEVICE_ID_JOYPAD_R2) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)); /* On some devices the dpad sends AXIS_HAT_X / AXIS_HAT_Y events, use those first if the returned values are nonzero */ - if (fabs(hatx) > 0.0001 || fabs(haty) > 0.0001) + if (fabsf(hatx) > 0.0001f || fabsf(haty) > 0.0001f) { *state_cur |= PRESSED_LEFT(hatx, haty) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; *state_cur |= PRESSED_RIGHT(hatx, haty) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; *state_cur |= PRESSED_UP(hatx, haty) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0; *state_cur |= PRESSED_DOWN(hatx, haty) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; } - else + else if (emulation == ANALOG_DPAD_LSTICK) { *state_cur |= PRESSED_LEFT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; *state_cur |= PRESSED_RIGHT(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; @@ -238,6 +253,19 @@ static void engine_handle_dpad_getaxisvalue(AInputEvent *event, *state_cur |= PRESSED_DOWN(x, y) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; } + if (ltrig > 0.5f) + *state_cur |= 1ULL << RETRO_DEVICE_ID_JOYPAD_L2; + if (rtrig > 0.5f) + *state_cur |= 1ULL << RETRO_DEVICE_ID_JOYPAD_R2; + + if (emulation == ANALOG_DPAD_DUALANALOG) + { + analog_state[state_id].lx = x * 0x7fff; + analog_state[state_id].ly = y * 0x7fff; + analog_state[state_id].rx = z * 0x7fff; + analog_state[state_id].ry = rz * 0x7fff; + } + if (debug_enable) snprintf(msg, msg_sizeof, "Pad %d : x %.2f, y %.2f, z %.2f, rz %.2f, src %d.\n", state_id, x, y, z, rz, source); @@ -248,7 +276,7 @@ static void *android_input_init(void) unsigned i, j, k; pads_connected = 0; - for(j = 0; j < LAST_KEYCODE; j++) + for (j = 0; j < LAST_KEYCODE; j++) keycode_lut[j] = 0; if (!g_settings.input.autodetect_enable) @@ -267,9 +295,9 @@ static void *android_input_init(void) } } - for(i = 0; i < MAX_PADS; i++) + for (i = 0; i < MAX_PADS; i++) { - for(j = 0; j < RARCH_FIRST_META_KEY; j++) + for (j = 0; j < RARCH_FIRST_META_KEY; j++) { g_settings.input.binds[i][j].id = i; g_settings.input.binds[i][j].joykey = 0; @@ -1447,6 +1475,20 @@ static void android_input_set_keybinds(void *data, unsigned device, keycode_lut[AKEYCODE_BUTTON_L1]|= ((RETRO_DEVICE_ID_JOYPAD_L+1) << shift); keycode_lut[AKEYCODE_BUTTON_R1]|= ((RETRO_DEVICE_ID_JOYPAD_R+1) << shift); break; + case DEVICE_NVIDIA_SHIELD: + g_settings.input.device[port] = device; + strlcpy(g_settings.input.device_names[port], "NVIDIA Shield", + sizeof(g_settings.input.device_names[port])); + g_settings.input.dpad_emulation[port] = ANALOG_DPAD_DUALANALOG; + keycode_lut[AKEYCODE_BUTTON_B] |= ((RETRO_DEVICE_ID_JOYPAD_A+1) << shift); + keycode_lut[AKEYCODE_BUTTON_A] |= ((RETRO_DEVICE_ID_JOYPAD_B+1) << shift); + keycode_lut[AKEYCODE_BUTTON_X] |= ((RETRO_DEVICE_ID_JOYPAD_X+1) << shift); + keycode_lut[AKEYCODE_BUTTON_Y] |= ((RETRO_DEVICE_ID_JOYPAD_Y+1) << shift); + keycode_lut[AKEYCODE_BUTTON_L1] |= ((RETRO_DEVICE_ID_JOYPAD_L+1) << shift); + keycode_lut[AKEYCODE_BUTTON_R1] |= ((RETRO_DEVICE_ID_JOYPAD_R+1) << shift); + keycode_lut[AKEYCODE_BUTTON_THUMBL] |= ((RETRO_DEVICE_ID_JOYPAD_SELECT+1) << shift); + keycode_lut[AKEYCODE_BUTTON_THUMBR] |= ((RETRO_DEVICE_ID_JOYPAD_START+1) << shift); + break; case DEVICE_CCPCREATIONS_WIIUSE_IME: g_settings.input.device[port] = device; strlcpy(g_settings.input.device_names[port], "ccpCreations WiiUse IME", @@ -1596,7 +1638,7 @@ static void android_input_poll(void *data) int predispatched; msg[0] = 0; - predispatched =AInputQueue_preDispatchEvent(android_app->inputQueue,event); + predispatched = AInputQueue_preDispatchEvent(android_app->inputQueue,event); if (predispatched) continue; @@ -1622,10 +1664,24 @@ static void android_input_poll(void *data) if (state_id < 0) { state_id = pads_connected; - state_device_ids[pads_connected++] = id; - if (g_settings.input.autodetect_enable) - input_autodetect_setup(android_app, msg, sizeof(msg), state_id, id, source); + { + bool primary = false; + input_autodetect_setup(android_app, msg, sizeof(msg), state_id, id, source, &primary); + + if (primary) + { + RARCH_LOG("Found primary input device.\n"); + memmove(state_device_ids + 1, state_device_ids, pads_connected * sizeof(state_device_ids[0])); + state_id = 0; + state_device_ids[0] = id; + pads_connected++; + } + else + state_device_ids[pads_connected++] = id; + } + else + state_device_ids[pads_connected++] = id; long_msg_enable = true; } @@ -1677,7 +1733,8 @@ static void android_input_poll(void *data) if (source & ~(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_MOUSE)) { if (g_settings.input.dpad_emulation[state_id] != ANALOG_DPAD_NONE) - engine_handle_dpad(event, motion_pointer, state_id, msg, sizeof(msg), source, debug_enable); + engine_handle_dpad(event, motion_pointer, state_id, msg, sizeof(msg), source, debug_enable, + g_settings.input.dpad_emulation[state_id]); } else { @@ -1745,7 +1802,11 @@ static void android_input_poll(void *data) } if (msg[0] != 0) + { + msg_queue_clear(g_extern.msg_queue); msg_queue_push(g_extern.msg_queue, msg, 0, long_msg_enable ? 180 : 30); + RARCH_LOG("Input debug: %s\n", msg); + } AInputQueue_finishEvent(android_app->inputQueue, event, handled); processed = 1; @@ -1765,8 +1826,22 @@ static int16_t android_input_state(void *data, const struct retro_keybind **bind { case RETRO_DEVICE_JOYPAD: return ((state[port] & binds[port][id].joykey) && (port < pads_connected)); + case RETRO_DEVICE_ANALOG: + if (port < pads_connected) + return 0; + switch ((index << 1) || id) + { + case (RETRO_DEVICE_INDEX_ANALOG_LEFT << 1) | RETRO_DEVICE_ID_ANALOG_X: + return analog_state[port].lx; + case (RETRO_DEVICE_INDEX_ANALOG_LEFT << 1) | RETRO_DEVICE_ID_ANALOG_Y: + return analog_state[port].ly; + case (RETRO_DEVICE_INDEX_ANALOG_RIGHT << 1) | RETRO_DEVICE_ID_ANALOG_X: + return analog_state[port].rx; + case (RETRO_DEVICE_INDEX_ANALOG_RIGHT << 1) | RETRO_DEVICE_ID_ANALOG_Y: + return analog_state[port].ry; + } case RETRO_DEVICE_POINTER: - switch(id) + switch (id) { case RETRO_DEVICE_ID_POINTER_X: return pointer[index].x; @@ -1778,7 +1853,7 @@ static int16_t android_input_state(void *data, const struct retro_keybind **bind return 0; } case RARCH_DEVICE_POINTER_SCREEN: - switch(id) + switch (id) { case RETRO_DEVICE_ID_POINTER_X: return pointer[index].full_x; diff --git a/android/native/jni/input_autodetect.c b/android/native/jni/input_autodetect.c index 8f7050daa4..0e82f8be30 100644 --- a/android/native/jni/input_autodetect.c +++ b/android/native/jni/input_autodetect.c @@ -67,7 +67,7 @@ end: (*vm)->DetachCurrentThread(vm); } -void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned port, unsigned id, int source) +void input_autodetect_setup(void *data, char *msg, size_t sizeof_msg, unsigned port, unsigned id, int source, bool *primary) { struct android_app *android_app = (struct android_app*)data; @@ -219,6 +219,12 @@ void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned device = DEVICE_DEFENDER_GAME_RACER_CLASSIC; else if (strstr(name_buf, "HOLTEK JC - U912F vibration game")) device = DEVICE_HOLTEK_JC_U912F; + else if (strstr(name_buf, "NVIDIA Controller")) + { + device = DEVICE_NVIDIA_SHIELD; + port = 0; // Shield is always player 1. + *primary = true; + } if (strstr(current_ime, "net.obsidianx.android.mogaime")) { diff --git a/android/native/jni/input_autodetect.h b/android/native/jni/input_autodetect.h index 2763d74b2d..6c85008825 100644 --- a/android/native/jni/input_autodetect.h +++ b/android/native/jni/input_autodetect.h @@ -81,7 +81,7 @@ enum { #define LAST_KEYCODE AKEYCODE_ASSIST -void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned port, unsigned id, int source); +void input_autodetect_setup(void *data, char *msg, size_t sizeof_msg, unsigned port, unsigned id, int source, bool *primary); /* Xperia Play externs */ extern unsigned zeus_port; diff --git a/driver.h b/driver.h index 944b51889c..d51e37bc0d 100644 --- a/driver.h +++ b/driver.h @@ -270,6 +270,7 @@ enum input_devices DEVICE_GAMEMID, DEVICE_DEFENDER_GAME_RACER_CLASSIC, DEVICE_HOLTEK_JC_U912F, + DEVICE_NVIDIA_SHIELD, #elif defined(GEKKO) DEVICE_GAMECUBE = 0, #ifdef HW_RVL @@ -301,6 +302,7 @@ enum analog_dpad_bind_enums ANALOG_DPAD_NONE = 0, ANALOG_DPAD_LSTICK, ANALOG_DPAD_RSTICK, + ANALOG_DPAD_DUALANALOG, ANALOG_DPAD_LAST };