mirror of
https://github.com/libretro/RetroArch
synced 2025-02-28 22:13:51 +00:00
add joypad driver for emscripten
This commit is contained in:
parent
38ec1acf8e
commit
21d928ba0e
@ -554,6 +554,7 @@ endif
|
||||
ifeq ($(HAVE_EMSCRIPTEN), 1)
|
||||
OBJ += frontend/drivers/platform_emscripten.o \
|
||||
input/drivers/rwebinput_input.o \
|
||||
input/drivers_joypad/rwebpad_joypad.o \
|
||||
audio/drivers/rwebaudio.o \
|
||||
camera/drivers/rwebcam.o
|
||||
endif
|
||||
|
@ -548,6 +548,7 @@ INPUT
|
||||
#include "../input/drivers_joypad/qnx_joypad.c"
|
||||
#elif defined(EMSCRIPTEN)
|
||||
#include "../input/drivers/rwebinput_input.c"
|
||||
#include "../input/drivers_joypad/rwebpad_joypad.c"
|
||||
#elif defined(DJGPP)
|
||||
#include "../input/drivers/dos_input.c"
|
||||
#include "../input/drivers_joypad/dos_joypad.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2015 - Michael Lelli
|
||||
* Copyright (C) 2010-2018 - Michael Lelli
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
@ -66,6 +66,7 @@ typedef struct rwebinput_input
|
||||
{
|
||||
rwebinput_keyboard_state_t keyboard;
|
||||
rwebinput_mouse_state_t mouse;
|
||||
const input_device_driver_t *joypad;
|
||||
bool blocked;
|
||||
} rwebinput_input_t;
|
||||
|
||||
@ -186,8 +187,8 @@ static const rwebinput_key_to_code_map_entry_t rwebinput_key_to_code_map[] =
|
||||
{ "Power", RETROK_POWER },
|
||||
};
|
||||
|
||||
static bool g_initialized;
|
||||
static rwebinput_keyboard_state_t *g_keyboard;
|
||||
static bool g_rwebinput_mouset_initialized;
|
||||
static rwebinput_keyboard_state_t *g_rwebinput_mouset_keyboard;
|
||||
static rwebinput_mouse_state_t *g_mouse;
|
||||
|
||||
/* to make the string labels for codes from JavaScript work, we convert them
|
||||
@ -275,7 +276,7 @@ static EM_BOOL rwebinput_keyboard_cb(int event_type,
|
||||
|
||||
if (translated_keycode < RETROK_LAST)
|
||||
{
|
||||
g_keyboard->keys[translated_keycode] = keydown;
|
||||
g_rwebinput_mouset_keyboard->keys[translated_keycode] = keydown;
|
||||
}
|
||||
|
||||
return EM_TRUE;
|
||||
@ -321,19 +322,19 @@ static void *rwebinput_input_init(const char *joypad_driver)
|
||||
{
|
||||
rwebinput_input_t *rwebinput =
|
||||
(rwebinput_input_t*)calloc(1, sizeof(*rwebinput));
|
||||
g_keyboard =
|
||||
(rwebinput_keyboard_state_t*)calloc(1, sizeof(rwebinput_keyboard_state_t));
|
||||
g_mouse =
|
||||
(rwebinput_mouse_state_t*)calloc(1, sizeof(rwebinput_mouse_state_t));
|
||||
g_rwebinput_mouset_keyboard = (rwebinput_keyboard_state_t*)
|
||||
calloc(1, sizeof(rwebinput_keyboard_state_t));
|
||||
g_mouse = (rwebinput_mouse_state_t*)
|
||||
calloc(1, sizeof(rwebinput_mouse_state_t));
|
||||
|
||||
if (!rwebinput || !g_keyboard || !g_mouse)
|
||||
if (!rwebinput || !g_rwebinput_mouset_keyboard || !g_mouse)
|
||||
goto error;
|
||||
|
||||
if (!g_initialized)
|
||||
if (!g_rwebinput_mouset_initialized)
|
||||
{
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
g_initialized = true;
|
||||
g_rwebinput_mouset_initialized = true;
|
||||
rwebinput_generate_lut();
|
||||
|
||||
/* emscripten currently doesn't have an API to remove handlers, so make
|
||||
@ -397,16 +398,19 @@ static void *rwebinput_input_init(const char *joypad_driver)
|
||||
|
||||
input_keymaps_init_keyboard_lut(rarch_key_map_rwebinput);
|
||||
|
||||
rwebinput->joypad = input_joypad_init_driver(joypad_driver, rwebinput);
|
||||
|
||||
return rwebinput;
|
||||
|
||||
error:
|
||||
free(g_keyboard);
|
||||
free(g_rwebinput_mouset_keyboard);
|
||||
free(g_mouse);
|
||||
free(rwebinput);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool rwebinput_key_pressed(rwebinput_keyboard_state_t *keyboard, int key)
|
||||
static bool rwebinput_key_pressed(rwebinput_keyboard_state_t *keyboard,
|
||||
int key)
|
||||
{
|
||||
if (key >= RETROK_LAST)
|
||||
return false;
|
||||
@ -414,20 +418,6 @@ static bool rwebinput_key_pressed(rwebinput_keyboard_state_t *keyboard, int key)
|
||||
return keyboard->keys[key];
|
||||
}
|
||||
|
||||
static bool rwebinput_is_pressed(rwebinput_keyboard_state_t *keyboard,
|
||||
const struct retro_keybind *binds, unsigned id)
|
||||
{
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
{
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
int key = binds[id].key;
|
||||
return bind->valid && (key < RETROK_LAST)
|
||||
&& rwebinput_key_pressed(keyboard, key);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int16_t rwebinput_pointer_device_state(rwebinput_mouse_state_t *mouse,
|
||||
unsigned id, bool screen)
|
||||
{
|
||||
@ -455,8 +445,6 @@ static int16_t rwebinput_pointer_device_state(rwebinput_mouse_state_t *mouse,
|
||||
res_y = res_screen_y;
|
||||
}
|
||||
|
||||
printf("%d %d %d %d\n", res_x, res_y, res_screen_x, res_screen_y);
|
||||
|
||||
inside = (res_x >= -0x7fff) && (res_y >= -0x7fff);
|
||||
|
||||
if (!inside)
|
||||
@ -507,8 +495,36 @@ static int16_t rwebinput_mouse_state(rwebinput_mouse_state_t *mouse,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool rwebinput_is_pressed(rwebinput_input_t *rwebinput,
|
||||
rarch_joypad_info_t joypad_info, const struct retro_keybind *binds,
|
||||
unsigned port, unsigned id)
|
||||
{
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
{
|
||||
const struct retro_keybind *bind = &binds[id];
|
||||
int key = bind->key;
|
||||
|
||||
if (!rwebinput->blocked && (bind->key < RETROK_LAST) &&
|
||||
rwebinput_key_pressed(&rwebinput->keyboard, key))
|
||||
return true;
|
||||
|
||||
if (bind->valid)
|
||||
{
|
||||
if (port == 0 && !!rwebinput_mouse_state(&rwebinput->mouse,
|
||||
bind->mbutton, false))
|
||||
return true;
|
||||
if (input_joypad_pressed(rwebinput->joypad, joypad_info, port, binds,
|
||||
id))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int16_t rwebinput_analog_pressed(rwebinput_input_t *rwebinput,
|
||||
const struct retro_keybind *binds, unsigned idx, unsigned id)
|
||||
rarch_joypad_info_t joypad_info, const struct retro_keybind *binds,
|
||||
unsigned idx, unsigned id)
|
||||
{
|
||||
int16_t pressed_minus = 0, pressed_plus = 0;
|
||||
unsigned id_minus = 0;
|
||||
@ -516,9 +532,9 @@ static int16_t rwebinput_analog_pressed(rwebinput_input_t *rwebinput,
|
||||
|
||||
input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus);
|
||||
|
||||
if (rwebinput_is_pressed(&rwebinput->keyboard, binds, id_minus))
|
||||
if (rwebinput_is_pressed(rwebinput, joypad_info, binds, idx, id_minus))
|
||||
pressed_minus = -0x7fff;
|
||||
if (rwebinput_is_pressed(&rwebinput->keyboard, binds, id_plus))
|
||||
if (rwebinput_is_pressed(rwebinput, joypad_info, binds, idx, id_plus))
|
||||
pressed_plus = 0x7fff;
|
||||
|
||||
return pressed_plus + pressed_minus;
|
||||
@ -529,14 +545,23 @@ static int16_t rwebinput_input_state(void *data,
|
||||
const struct retro_keybind **binds,
|
||||
unsigned port, unsigned device, unsigned idx, unsigned id)
|
||||
{
|
||||
int16_t ret;
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
return rwebinput_is_pressed(&rwebinput->keyboard, binds[port], id);
|
||||
if (id < RARCH_BIND_LIST_END)
|
||||
return rwebinput_is_pressed(rwebinput, joypad_info, binds[port],
|
||||
port, id);
|
||||
break;
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
return rwebinput_analog_pressed(rwebinput, binds[port], idx, id);
|
||||
ret = rwebinput_analog_pressed(rwebinput, joypad_info, binds[port],
|
||||
idx, id);
|
||||
if (!ret && binds[port])
|
||||
ret = input_joypad_analog(rwebinput->joypad, joypad_info, port,
|
||||
idx, id, binds[port]);
|
||||
return ret;
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
return rwebinput_key_pressed(&rwebinput->keyboard, id);
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
@ -556,8 +581,8 @@ static void rwebinput_input_free(void *data)
|
||||
{
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
|
||||
free(g_keyboard);
|
||||
g_keyboard = NULL;
|
||||
free(g_rwebinput_mouset_keyboard);
|
||||
g_rwebinput_mouset_keyboard = NULL;
|
||||
free(g_mouse);
|
||||
g_mouse = NULL;
|
||||
free(rwebinput);
|
||||
@ -568,11 +593,15 @@ static void rwebinput_input_poll(void *data)
|
||||
unsigned i;
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
|
||||
memcpy(&rwebinput->keyboard, g_keyboard, sizeof(*g_keyboard));
|
||||
memcpy(&rwebinput->keyboard, g_rwebinput_mouset_keyboard,
|
||||
sizeof(*g_rwebinput_mouset_keyboard));
|
||||
memcpy(&rwebinput->mouse, g_mouse, sizeof(*g_mouse));
|
||||
|
||||
g_mouse->delta_x = g_mouse->delta_y = 0;
|
||||
g_mouse->scroll_x = g_mouse->scroll_y = 0.0;
|
||||
|
||||
if (rwebinput->joypad)
|
||||
rwebinput->joypad->poll();
|
||||
}
|
||||
|
||||
static void rwebinput_grab_mouse(void *data, bool state)
|
||||
@ -596,6 +625,14 @@ static bool rwebinput_set_rumble(void *data, unsigned port,
|
||||
return false;
|
||||
}
|
||||
|
||||
static const input_device_driver_t *rwebinput_get_joypad_driver(void *data)
|
||||
{
|
||||
rwebinput_input_t *rwebinput = (rwebinput_input_t*)data;
|
||||
if (!rwebinput)
|
||||
return NULL;
|
||||
return rwebinput->joypad;
|
||||
}
|
||||
|
||||
static uint64_t rwebinput_get_capabilities(void *data)
|
||||
{
|
||||
uint64_t caps = 0;
|
||||
@ -637,7 +674,7 @@ input_driver_t input_rwebinput = {
|
||||
rwebinput_grab_mouse,
|
||||
NULL,
|
||||
rwebinput_set_rumble,
|
||||
NULL,
|
||||
rwebinput_get_joypad_driver,
|
||||
NULL,
|
||||
rwebinput_keyboard_mapping_is_blocked,
|
||||
rwebinput_keyboard_mapping_set_block,
|
||||
|
195
input/drivers_joypad/rwebpad_joypad.c
Normal file
195
input/drivers_joypad/rwebpad_joypad.c
Normal file
@ -0,0 +1,195 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2018 - Michael Lelli
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include "../input_driver.h"
|
||||
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
static bool g_rwebpad_initialized;
|
||||
|
||||
static EM_BOOL rwebpad_gamepad_cb(int event_type,
|
||||
const EmscriptenGamepadEvent *gamepad_event, void *user_data)
|
||||
{
|
||||
(void)event_type;
|
||||
(void)gamepad_event;
|
||||
(void)user_data;
|
||||
|
||||
if (event_type == EMSCRIPTEN_EVENT_GAMEPADCONNECTED)
|
||||
{
|
||||
if(!input_autoconfigure_connect(
|
||||
gamepad_event->id, /* name */
|
||||
NULL, /* display name */
|
||||
rwebpad_joypad.ident, /* driver */
|
||||
gamepad_event->index, /* idx */
|
||||
0, /* vid */
|
||||
0)) /* pid */
|
||||
input_config_set_device_name(gamepad_event->index,
|
||||
gamepad_event->id);
|
||||
}
|
||||
else if (event_type == EMSCRIPTEN_EVENT_GAMEPADDISCONNECTED)
|
||||
{
|
||||
input_autoconfigure_disconnect(gamepad_event->index,
|
||||
rwebpad_joypad.ident);
|
||||
}
|
||||
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static bool rwebpad_joypad_init(void *data)
|
||||
{
|
||||
int supported = emscripten_get_num_gamepads();
|
||||
(void)data;
|
||||
|
||||
if (supported == EMSCRIPTEN_RESULT_NOT_SUPPORTED)
|
||||
return false;
|
||||
|
||||
if (!g_rwebpad_initialized)
|
||||
{
|
||||
EMSCRIPTEN_RESULT r;
|
||||
g_rwebpad_initialized = true;
|
||||
|
||||
/* callbacks needs to be registered for gamepads to connect */
|
||||
r = emscripten_set_gamepadconnected_callback(NULL, false,
|
||||
rwebpad_gamepad_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/PAD] failed to create connect callback: %d\n", r);
|
||||
}
|
||||
|
||||
r = emscripten_set_gamepaddisconnected_callback(NULL, false,
|
||||
rwebpad_gamepad_cb);
|
||||
if (r != EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[EMSCRIPTEN/PAD] failed to create disconnect callback: %d\n", r);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *rwebpad_joypad_name(unsigned pad)
|
||||
{
|
||||
static EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(pad, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
return gamepad_state.id;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool rwebpad_joypad_button(unsigned port_num, uint16_t joykey)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(port_num, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
if (joykey < ARRAY_SIZE(gamepad_state.digitalButton))
|
||||
{
|
||||
return gamepad_state.digitalButton[joykey];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rwebpad_joypad_get_buttons(unsigned port_num, retro_bits_t *state)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
|
||||
r = emscripten_get_gamepad_status(port_num, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gamepad_state.digitalButton); i++)
|
||||
{
|
||||
if (gamepad_state.digitalButton[i])
|
||||
BIT256_SET_PTR(state, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t rwebpad_joypad_axis(unsigned port_num, uint32_t joyaxis)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
if (joyaxis > ARRAY_SIZE(gamepad_state.axis))
|
||||
return 0;
|
||||
|
||||
r = emscripten_get_gamepad_status(port_num, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
return gamepad_state.axis[joyaxis] * 0x7FFF;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rwebpad_joypad_poll(void)
|
||||
{
|
||||
/* this call makes emscripten poll gamepad state */
|
||||
(void)emscripten_get_num_gamepads();
|
||||
}
|
||||
|
||||
static bool rwebpad_joypad_query_pad(unsigned pad)
|
||||
{
|
||||
EmscriptenGamepadEvent gamepad_state;
|
||||
EMSCRIPTEN_RESULT r;
|
||||
|
||||
r = emscripten_get_gamepad_status(pad, &gamepad_state);
|
||||
|
||||
if (r == EMSCRIPTEN_RESULT_SUCCESS)
|
||||
return gamepad_state.connected == EM_TRUE;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void rwebpad_joypad_destroy(void)
|
||||
{
|
||||
}
|
||||
|
||||
input_device_driver_t rwebpad_joypad = {
|
||||
rwebpad_joypad_init,
|
||||
rwebpad_joypad_query_pad,
|
||||
rwebpad_joypad_destroy,
|
||||
rwebpad_joypad_button,
|
||||
rwebpad_joypad_get_buttons,
|
||||
rwebpad_joypad_axis,
|
||||
rwebpad_joypad_poll,
|
||||
NULL,
|
||||
rwebpad_joypad_name,
|
||||
"rwebpad",
|
||||
};
|
@ -181,6 +181,9 @@ static input_device_driver_t *joypad_drivers[] = {
|
||||
* to be selectable in the UI. */
|
||||
#if defined(HAVE_HID) && !defined(WIIU)
|
||||
&hid_joypad,
|
||||
#endif
|
||||
#ifdef EMSCRIPTEN
|
||||
&rwebpad_joypad,
|
||||
#endif
|
||||
&null_joypad,
|
||||
NULL,
|
||||
@ -804,7 +807,7 @@ void state_tracker_update_input(uint16_t *input1, uint16_t *input2)
|
||||
static INLINE bool input_keys_pressed_iterate(unsigned i,
|
||||
retro_bits_t* p_new_state)
|
||||
{
|
||||
if ((i >= RARCH_FIRST_META_KEY) &&
|
||||
if ((i >= RARCH_FIRST_META_KEY) &&
|
||||
BIT64_GET(lifecycle_state, i)
|
||||
)
|
||||
return true;
|
||||
|
@ -814,6 +814,7 @@ extern input_device_driver_t qnx_joypad;
|
||||
extern input_device_driver_t null_joypad;
|
||||
extern input_device_driver_t mfi_joypad;
|
||||
extern input_device_driver_t dos_joypad;
|
||||
extern input_device_driver_t rwebpad_joypad;
|
||||
|
||||
extern input_driver_t input_android;
|
||||
extern input_driver_t input_sdl;
|
||||
|
Loading…
x
Reference in New Issue
Block a user