From 6b5aef09a14754004083735abf1bae452c9d7ee5 Mon Sep 17 00:00:00 2001 From: Ash Date: Sat, 19 Aug 2017 17:40:56 +1000 Subject: [PATCH] [WiiU] DRC touch support as pointer device Allow using the Gamepad's touch screen as a RETRO_DEVICE_POINTER. Methodology could use some work, had to add an extra axis to joypad in order to get the data transferred into the input driver. Feel free to change this. Needs to emulate RETRO_DEVICE_LIGHTGUN to really be useful. Potential for Wiimote IR in future. Partially addresses libretro/RetroArch#5294 --- input/drivers/wiiu_input.c | 42 ++++++++++++++++++++------ input/drivers_joypad/wiiu_joypad.c | 48 ++++++++++++++++++++++++++---- wiiu/system/imports.h | 1 + 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/input/drivers/wiiu_input.c b/input/drivers/wiiu_input.c index af1a8b7f76..2fb3a6736f 100644 --- a/input/drivers/wiiu_input.c +++ b/input/drivers/wiiu_input.c @@ -22,6 +22,7 @@ #include #include +#include #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -96,18 +97,37 @@ void kb_key_callback(KBDKeyEvent *key) RETRO_DEVICE_KEYBOARD); } +/* TODO: emulate a relative mouse. This is suprisingly + hard to get working nicely. +*/ + +static int16_t wiiu_pointer_device_state(wiiu_input_t* wiiu, unsigned id) +{ + switch (id) + { + case RETRO_DEVICE_ID_POINTER_PRESSED: + return wiiu->joypad->get_buttons(0) & VPAD_BUTTON_TOUCH; + case RETRO_DEVICE_ID_POINTER_X: + return wiiu->joypad->axis(0, 0xFFFF0004UL); + case RETRO_DEVICE_ID_POINTER_Y: + return wiiu->joypad->axis(0, 0xFFFF0005UL); + } + + return 0; +} + static void wiiu_input_poll(void *data) { wiiu_input_t *wiiu = (wiiu_input_t*)data; if (wiiu && wiiu->joypad) - wiiu->joypad->poll(); + wiiu->joypad->poll(); } static bool wiiu_key_pressed(int key) { bool ret = false; - + if (key >= RETROK_LAST) return false; @@ -127,7 +147,7 @@ static int16_t wiiu_input_state(void *data, if(!wiiu || !(port < MAX_PADS) || !binds || !binds[port]) return 0; - + switch (device) { case RETRO_DEVICE_JOYPAD: @@ -140,6 +160,9 @@ static int16_t wiiu_input_state(void *data, return input_joypad_analog(wiiu->joypad, joypad_info, port, idx, id, binds[port]); break; + case RETRO_DEVICE_POINTER: + case RARCH_DEVICE_POINTER_SCREEN: + return wiiu_pointer_device_state(wiiu, id); } return 0; @@ -151,7 +174,7 @@ static void wiiu_input_free_input(void *data) if (wiiu && wiiu->joypad) wiiu->joypad->destroy(); - + KBDTeardown(); free(data); @@ -165,10 +188,10 @@ static void* wiiu_input_init(const char *joypad_driver) DEBUG_STR(joypad_driver); wiiu->joypad = input_joypad_init_driver(joypad_driver, wiiu); - + KBDSetup(&kb_connection_callback, &kb_disconnection_callback,&kb_key_callback); - + input_keymaps_init_keyboard_lut(rarch_key_map_wiiu); return wiiu; @@ -186,9 +209,10 @@ static uint64_t wiiu_input_get_capabilities(void *data) { (void)data; - return (1 << RETRO_DEVICE_JOYPAD) | - (1 << RETRO_DEVICE_ANALOG) | - (1 << RETRO_DEVICE_KEYBOARD); + return (1 << RETRO_DEVICE_JOYPAD) | + (1 << RETRO_DEVICE_ANALOG) | + (1 << RETRO_DEVICE_KEYBOARD) | + (1 << RETRO_DEVICE_POINTER); } static const input_device_driver_t *wiiu_input_get_joypad_driver(void *data) diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 4b59c909eb..33d2da4d7b 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -29,6 +29,7 @@ #include "../../tasks/tasks_internal.h" #include "../../retroarch.h" #include "../../command.h" +#include "../../gfx/video_driver.h" #include "string.h" #include "wiiu_dbg.h" @@ -57,7 +58,8 @@ static uint8_t pad_type[KPAD_COUNT] = {WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, static uint8_t hid_status[HID_COUNT]; static InputData hid_data[HID_COUNT]; -static int16_t analog_state[MAX_PADS][2][2]; +/* 3 axis - one for touch/future IR support? */ +static int16_t analog_state[MAX_PADS][3][2]; static bool wiiu_pad_inited = false; static char hidName[HID_COUNT][255]; @@ -135,12 +137,12 @@ static int16_t wiiu_joypad_axis(unsigned port_num, uint32_t joyaxis) if (joyaxis == AXIS_NONE || port_num >= MAX_PADS) return 0; - if (AXIS_NEG_GET(joyaxis) < 4) + if (AXIS_NEG_GET(joyaxis) < 6) { axis = AXIS_NEG_GET(joyaxis); is_neg = true; } - else if (AXIS_POS_GET(joyaxis) < 4) + else if (AXIS_POS_GET(joyaxis) < 6) { axis = AXIS_POS_GET(joyaxis); is_pos = true; @@ -163,6 +165,14 @@ static int16_t wiiu_joypad_axis(unsigned port_num, uint32_t joyaxis) case 3: val = analog_state[port_num][1][1]; break; + + case 4: + val = analog_state[port_num][2][0]; + break; + + case 5: + val = analog_state[port_num][2][1]; + break; } if (is_neg && val > 0) @@ -173,6 +183,12 @@ static int16_t wiiu_joypad_axis(unsigned port_num, uint32_t joyaxis) return val; } +static float scaleTP(float oldMin, float oldMax, float newMin, float newMax, float val) { + float oldRange = (oldMax - oldMin); + float newRange = (newMax - newMin); + return (((val - oldMin) * newRange) / oldRange) + newMin; +} + static void wiiu_joypad_poll(void) { int i, c, result; @@ -183,7 +199,7 @@ static void wiiu_joypad_poll(void) if (!vpadError) { - pad_state[0] = vpad.hold & ~0x7F800000; /* clear out emulated analog sticks */ + pad_state[0] = vpad.hold & VPAD_MASK_BUTTONS; /* buttons only */ analog_state[0][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X] = vpad.leftStick.x * 0x7FF0; analog_state[0][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y] = vpad.leftStick.y * 0x7FF0; analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] = vpad.rightStick.x * 0x7FF0; @@ -191,8 +207,28 @@ static void wiiu_joypad_poll(void) BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE); - if ((vpad.tpNormal.touched) && (vpad.tpNormal.x > 200) && (vpad.tpNormal.validity) == 0) - BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE); + /* You can only call VPADData once every loop, else the second one + won't get any data. Thus; I had to hack touch support into the existing + joystick API. Woo-hoo? Misplaced requests for touch axis are filtered + out in wiiu_input. + */ + if (vpad.tpNormal.touched && vpad.tpNormal.validity == VPAD_VALID) { + struct video_viewport vp = {0}; + video_driver_get_viewport_info(&vp); + VPADTouchData cal = {0}; + /* Calibrates data to a 720p screen, seems to clamp outer 12px */ + VPADGetTPCalibratedPoint(0, &cal, &(vpad.tpNormal)); + /* Calibrate to viewport and save as axis 2 (idx 4,5) */ + analog_state[0][2][0] = (int16_t)scaleTP(12.0f, 1268.0f, 0.0f, (float)(vp.full_width), (float)cal.x); + analog_state[0][2][1] = (int16_t)scaleTP(12.0f, 708.0f, 0.0f, (float)(vp.full_height), (float)cal.y); + + /* Emulating a button for touch; lets people assign it to menu + for that traditional RetroArch Wii U feel */ + pad_state[0] |= VPAD_BUTTON_TOUCH; + } else { + /* This is probably 0 anyway */ + pad_state[0] &= ~VPAD_BUTTON_TOUCH; + } /* panic button */ if ((vpad.hold & (VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_STICK_L)) diff --git a/wiiu/system/imports.h b/wiiu/system/imports.h index 3aa90a6746..866382c1de 100644 --- a/wiiu/system/imports.h +++ b/wiiu/system/imports.h @@ -225,6 +225,7 @@ IMPORT_BEGIN(vpad); IMPORT(VPADRead); IMPORT(VPADInit); +IMPORT(VPADGetTPCalibratedPoint); IMPORT_END();