diff --git a/Makefile.common b/Makefile.common index 80e132cc49..d6039739bb 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1508,6 +1508,7 @@ ifeq ($(HAVE_NETWORKING), 1) network/netplay/netplay_handshake.o \ network/netplay/netplay_init.o \ network/netplay/netplay_io.o \ + network/netplay/netplay_keyboard.o \ network/netplay/netplay_sync.o \ network/netplay/netplay_discovery.o \ network/netplay/netplay_buf.o \ diff --git a/griffin/griffin.c b/griffin/griffin.c index 4f7fc0384a..008039d3ee 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1029,6 +1029,7 @@ NETPLAY #include "../network/netplay/netplay_handshake.c" #include "../network/netplay/netplay_init.c" #include "../network/netplay/netplay_io.c" +#include "../network/netplay/netplay_keyboard.c" #include "../network/netplay/netplay_sync.c" #include "../network/netplay/netplay_discovery.c" #include "../network/netplay/netplay_buf.c" diff --git a/network/netplay/README b/network/netplay/README index dda433a9b5..2d3aa8a41d 100644 --- a/network/netplay/README +++ b/network/netplay/README @@ -379,6 +379,9 @@ MOUSE X: int16 } +KEYBOARD + (5 words, see netplay_keys.h) + LIGHTGUN { unused, unused, Trigger, Cursor, Turbo, Pause, Start diff --git a/network/netplay/netplay_delta.c b/network/netplay/netplay_delta.c index de4737b7c1..edfd225427 100644 --- a/network/netplay/netplay_delta.c +++ b/network/netplay/netplay_delta.c @@ -179,6 +179,7 @@ uint32_t netplay_expected_input_size(netplay_t *netplay, uint32_t devices) * fixed size, documented in network/netplay/README */ case RETRO_DEVICE_JOYPAD: ret += 1; break; case RETRO_DEVICE_MOUSE: ret += 2; break; + case RETRO_DEVICE_KEYBOARD: ret += 5; break; case RETRO_DEVICE_LIGHTGUN: ret += 2; break; case RETRO_DEVICE_ANALOG: ret += 3; break; default: break; /* Unsupported */ diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 89b914f646..8b107c6772 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -201,6 +201,26 @@ static bool get_self_input_state(netplay_t *netplay) } break; } + + case RETRO_DEVICE_KEYBOARD: + { + unsigned key, word = 0, bit = 1; + for (key = 1; key < NETPLAY_KEY_LAST; key++) + { + state[word] |= + cb(local_device, RETRO_DEVICE_KEYBOARD, 0, netplay_key_ntoh(key)) ? + (1U << bit) : 0; + bit++; + if (bit >= 32) + { + bit = 0; + word++; + if (word >= istate->size) + break; + } + } + break; + } } } } @@ -536,7 +556,8 @@ static int16_t netplay_input_state(netplay_t *netplay, return 0; /* If the port doesn't seem to correspond to the device, "correct" it. This - * is common with e.g. zappers. */ + * is common with devices that typically only have one instance, such as + * keyboards, mice and lightguns. */ if (device != RETRO_DEVICE_JOYPAD && (netplay->config_devices[port]&RETRO_DEVICE_MASK) != device) { @@ -582,6 +603,19 @@ static int16_t netplay_input_state(netplay_t *netplay, return ((1 << id) & curr_input_state[0]) ? 1 : 0; } + case RETRO_DEVICE_KEYBOARD: + { + unsigned key, word, bit; + key = netplay_key_hton(id); + if (key == NETPLAY_KEY_UNKNOWN) + return 0; + word = key/32; + bit = key%32; + if (word <= istate->size) + return ((1U<config_devices[i] = pad.device; + if ((pad.device&RETRO_DEVICE_MASK) == RETRO_DEVICE_KEYBOARD) + netplay_key_hton_init(); core_set_controller_port_device(&pad); } diff --git a/network/netplay/netplay_init.c b/network/netplay/netplay_init.c index 893e3d89e9..8ab5c50459 100644 --- a/network/netplay/netplay_init.c +++ b/network/netplay/netplay_init.c @@ -475,6 +475,8 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, { uint32_t dtype = input_config_get_device(i); netplay->config_devices[i] = dtype; + if ((dtype&RETRO_DEVICE_MASK) == RETRO_DEVICE_KEYBOARD) + netplay_key_hton_init(); if (dtype != RETRO_DEVICE_NONE && !netplay_expected_input_size(netplay, 1<. + */ + +#include + +#include "netplay_private.h" + +/* The mapping of keys from netplay (network) to libretro (host) */ +const uint16_t netplay_key_ntoh_mapping[] = { + (uint16_t) RETROK_UNKNOWN, +#define K(k) (uint16_t) RETROK_ ## k, +#define KL(k,l) (uint16_t) l, +#include "netplay_keys.h" +#undef KL +#undef K + 0 +}; + +static bool mapping_defined = false; +static uint16_t mapping[RETROK_LAST]; + +/* The mapping of keys from libretro (host) to netplay (network) */ +uint32_t netplay_key_hton(unsigned key) +{ + if (key >= RETROK_LAST) + return NETPLAY_KEY_UNKNOWN; + return mapping[key]; +} + +/* Because the hton keymapping has to be generated, call this before using + * netplay_key_hton */ +void netplay_key_hton_init(void) +{ + if (!mapping_defined) + { + uint16_t i; + for (i = 0; i < NETPLAY_KEY_LAST; i++) + mapping[netplay_key_ntoh(i)] = i; + mapping_defined = true; + } +} diff --git a/network/netplay/netplay_keys.h b/network/netplay/netplay_keys.h new file mode 100644 index 0000000000..0184497a1b --- /dev/null +++ b/network/netplay/netplay_keys.h @@ -0,0 +1,169 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2016-2017 - Gregor Richards + * + * 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 . + */ + +/* This is an X-include file which defines the mapping of keycodes used by + * libretro to keycodes used by RetroArch Netplay. The keycodes are different + * because the keycodes supported by libretro are in discontiguous blocks, + * which would create gaps in the input data, requiring more space and more + * network bandwidth to represent them. + * + * If you want to add a new keycode, make sure you add it to the END. The order + * that the keys appear in this file defines their indices in the netplay + * protocol, so adding a key in the middle will break backwards compatibility. + * If you want to clean up the order and thereby break backwards compatibility, + * make sure you bump the protocol version in netplay_private.h. + */ + +K(BACKSPACE) +K(TAB) +KL(LINEFEED, 10) +K(CLEAR) +K(RETURN) +K(PAUSE) +K(ESCAPE) +K(SPACE) +K(EXCLAIM) +K(QUOTEDBL) +K(HASH) +K(DOLLAR) +K(AMPERSAND) +K(QUOTE) +K(LEFTPAREN) +K(RIGHTPAREN) +K(ASTERISK) +K(PLUS) +K(COMMA) +K(MINUS) +K(PERIOD) +K(SLASH) +K(0) +K(1) +K(2) +K(3) +K(4) +K(5) +K(6) +K(7) +K(8) +K(9) +K(COLON) +K(SEMICOLON) +K(LESS) +K(EQUALS) +K(GREATER) +K(QUESTION) +K(AT) +K(LEFTBRACKET) +K(BACKSLASH) +K(RIGHTBRACKET) +K(CARET) +K(UNDERSCORE) +K(BACKQUOTE) +K(a) +K(b) +K(c) +K(d) +K(e) +K(f) +K(g) +K(h) +K(i) +K(j) +K(k) +K(l) +K(m) +K(n) +K(o) +K(p) +K(q) +K(r) +K(s) +K(t) +K(u) +K(v) +K(w) +K(x) +K(y) +K(z) +K(DELETE) + +K(KP0) +K(KP1) +K(KP2) +K(KP3) +K(KP4) +K(KP5) +K(KP6) +K(KP7) +K(KP8) +K(KP9) +K(KP_PERIOD) +K(KP_DIVIDE) +K(KP_MULTIPLY) +K(KP_MINUS) +K(KP_PLUS) +K(KP_ENTER) +K(KP_EQUALS) + +K(UP) +K(DOWN) +K(RIGHT) +K(LEFT) +K(INSERT) +K(HOME) +K(END) +K(PAGEUP) +K(PAGEDOWN) + +K(F1) +K(F2) +K(F3) +K(F4) +K(F5) +K(F6) +K(F7) +K(F8) +K(F9) +K(F10) +K(F11) +K(F12) +K(F13) +K(F14) +K(F15) + +K(NUMLOCK) +K(CAPSLOCK) +K(SCROLLOCK) +K(RSHIFT) +K(LSHIFT) +K(RCTRL) +K(LCTRL) +K(RALT) +K(LALT) +K(RMETA) +K(LMETA) +K(LSUPER) +K(RSUPER) +K(MODE) +K(COMPOSE) + +K(HELP) +K(PRINT) +K(SYSREQ) +K(BREAK) +K(MENU) +K(POWER) +K(EURO) +K(UNDO) diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index cb87db74c1..14e31d720f 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -48,10 +48,9 @@ #define MAX_CLIENTS 32 typedef uint32_t client_bitmap_t; -/* For now we only support the normal or analog gamepad */ -#define NETPLAY_SUPPORTED_DEVICES ( \ - (1<resolved_input[device], 1, dsize, false, false); if (!oldresstate) continue;