mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 03:32:46 +00:00
Merge pull request #5429 from GregorR/netplay-input-upgrades-1
Netplay input upgrades 1
This commit is contained in:
commit
4a6a97be60
@ -1549,6 +1549,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 \
|
||||
|
@ -159,7 +159,6 @@ static const struct cmd_map map[] = {
|
||||
{ "SCREENSHOT", RARCH_SCREENSHOT },
|
||||
{ "MUTE", RARCH_MUTE },
|
||||
{ "OSK", RARCH_OSK },
|
||||
{ "NETPLAY_FLIP", RARCH_NETPLAY_FLIP },
|
||||
{ "NETPLAY_GAME_WATCH", RARCH_NETPLAY_GAME_WATCH },
|
||||
{ "SLOWMOTION", RARCH_SLOWMOTION },
|
||||
{ "VOLUME_UP", RARCH_VOLUME_UP },
|
||||
@ -2559,9 +2558,6 @@ TODO: Add a setting for these tweaks */
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case CMD_EVENT_NETPLAY_FLIP_PLAYERS:
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, NULL);
|
||||
break;
|
||||
case CMD_EVENT_NETPLAY_GAME_WATCH:
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_GAME_WATCH, NULL);
|
||||
break;
|
||||
@ -2572,7 +2568,6 @@ TODO: Add a setting for these tweaks */
|
||||
case CMD_EVENT_NETPLAY_INIT:
|
||||
case CMD_EVENT_NETPLAY_INIT_DIRECT:
|
||||
case CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED:
|
||||
case CMD_EVENT_NETPLAY_FLIP_PLAYERS:
|
||||
case CMD_EVENT_NETPLAY_GAME_WATCH:
|
||||
return false;
|
||||
#endif
|
||||
|
@ -179,8 +179,6 @@ enum event_command
|
||||
CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED,
|
||||
/* Deinitializes netplay system. */
|
||||
CMD_EVENT_NETPLAY_DEINIT,
|
||||
/* Flip netplay players. */
|
||||
CMD_EVENT_NETPLAY_FLIP_PLAYERS,
|
||||
/* Switch between netplay gaming and watching. */
|
||||
CMD_EVENT_NETPLAY_GAME_WATCH,
|
||||
/* Initializes BSV movie. */
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include "network/netplay/netplay.h"
|
||||
#endif
|
||||
|
||||
#if defined(HW_RVL)
|
||||
#define MAX_GAMMA_SETTING 30
|
||||
#elif defined(GEKKO)
|
||||
@ -544,6 +548,10 @@ static const int netplay_check_frames = 600;
|
||||
|
||||
static const bool netplay_use_mitm_server = false;
|
||||
|
||||
static const unsigned netplay_share_digital = RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE;
|
||||
|
||||
static const unsigned netplay_share_analog = RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE;
|
||||
|
||||
/* On save state load, block SRAM from being overwritten.
|
||||
* This could potentially lead to buggy games. */
|
||||
static const bool block_sram_overwrite = false;
|
||||
|
@ -85,7 +85,6 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
{ true, RARCH_SCREENSHOT, MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_MUTE, MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_OSK, MENU_ENUM_LABEL_VALUE_INPUT_META_OSK, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_NETPLAY_FLIP, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_NETPLAY_GAME_WATCH, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_SLOWMOTION, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_ENABLE_HOTKEY, MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
@ -160,7 +159,6 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
{ true, RARCH_SCREENSHOT, MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT, RETROK_F8, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_MUTE, MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE, RETROK_F9, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_OSK, MENU_ENUM_LABEL_VALUE_INPUT_META_OSK, RETROK_F12, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_NETPLAY_FLIP, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_NETPLAY_GAME_WATCH, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH, RETROK_i, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_SLOWMOTION, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION, RETROK_e, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RARCH_ENABLE_HOTKEY, MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE },
|
||||
|
@ -1158,7 +1158,9 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
{
|
||||
struct config_bool_setting *tmp = (struct config_bool_setting*)malloc((*size + 1) * sizeof(struct config_bool_setting));
|
||||
unsigned count = 0;
|
||||
unsigned user;
|
||||
global_t *global = global_get_ptr();
|
||||
char cfg[64] = {0};
|
||||
|
||||
SETTING_BOOL("automatically_add_content_to_playlist", &settings->bools.automatically_add_content_to_playlist, true, automatically_add_content_to_playlist, false);
|
||||
SETTING_BOOL("ui_companion_start_on_boot", &settings->bools.ui_companion_start_on_boot, true, ui_companion_start_on_boot, false);
|
||||
@ -1173,8 +1175,12 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("netplay_allow_slaves", &settings->bools.netplay_allow_slaves, true, netplay_allow_slaves, false);
|
||||
SETTING_BOOL("netplay_require_slaves", &settings->bools.netplay_require_slaves, true, netplay_require_slaves, false);
|
||||
SETTING_BOOL("netplay_stateless_mode", &settings->bools.netplay_stateless_mode, true, netplay_stateless_mode, false);
|
||||
SETTING_BOOL("netplay_client_swap_input", &settings->bools.netplay_swap_input, true, netplay_client_swap_input, false);
|
||||
SETTING_BOOL("netplay_use_mitm_server", &settings->bools.netplay_use_mitm_server, true, netplay_use_mitm_server, false);
|
||||
for (user = 0; user < MAX_USERS; user++)
|
||||
{
|
||||
snprintf(cfg, sizeof(cfg)-1, "netplay_request_device_p%u", user + 1);
|
||||
SETTING_BOOL(strdup(cfg), &settings->bools.netplay_request_devices[user], true, false, false);
|
||||
}
|
||||
#endif
|
||||
SETTING_BOOL("input_descriptor_label_show", &settings->bools.input_descriptor_label_show, true, input_descriptor_label_show, false);
|
||||
SETTING_BOOL("input_descriptor_hide_unbound", &settings->bools.input_descriptor_hide_unbound, true, input_descriptor_hide_unbound, false);
|
||||
@ -1468,6 +1474,8 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("netplay_ip_port", &settings->uints.netplay_port, true, RARCH_DEFAULT_PORT, false);
|
||||
SETTING_UINT("netplay_input_latency_frames_min",&settings->uints.netplay_input_latency_frames_min, true, 0, false);
|
||||
SETTING_UINT("netplay_input_latency_frames_range",&settings->uints.netplay_input_latency_frames_range, true, 0, false);
|
||||
SETTING_UINT("netplay_share_digital", &settings->uints.netplay_share_digital, true, netplay_share_digital, false);
|
||||
SETTING_UINT("netplay_share_analog", &settings->uints.netplay_share_analog, true, netplay_share_analog, false);
|
||||
#endif
|
||||
#ifdef HAVE_LANGEXTRA
|
||||
SETTING_UINT("user_language", msg_hash_get_uint(MSG_HASH_USER_LANGUAGE), true, RETRO_LANGUAGE_ENGLISH, false);
|
||||
|
@ -174,9 +174,9 @@ typedef struct settings
|
||||
bool netplay_allow_slaves;
|
||||
bool netplay_require_slaves;
|
||||
bool netplay_stateless_mode;
|
||||
bool netplay_swap_input;
|
||||
bool netplay_nat_traversal;
|
||||
bool netplay_use_mitm_server;
|
||||
bool netplay_request_devices[MAX_USERS];
|
||||
|
||||
/* Network */
|
||||
bool network_buildbot_auto_extract_archive;
|
||||
@ -315,6 +315,8 @@ typedef struct settings
|
||||
unsigned netplay_port;
|
||||
unsigned netplay_input_latency_frames_min;
|
||||
unsigned netplay_input_latency_frames_range;
|
||||
unsigned netplay_share_digital;
|
||||
unsigned netplay_share_analog;
|
||||
unsigned bundle_assets_extract_version_current;
|
||||
unsigned bundle_assets_extract_last_version;
|
||||
unsigned content_history_size;
|
||||
|
@ -1057,6 +1057,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"
|
||||
|
@ -91,7 +91,6 @@ enum
|
||||
RARCH_SCREENSHOT,
|
||||
RARCH_MUTE,
|
||||
RARCH_OSK,
|
||||
RARCH_NETPLAY_FLIP,
|
||||
RARCH_NETPLAY_GAME_WATCH,
|
||||
RARCH_SLOWMOTION,
|
||||
RARCH_ENABLE_HOTKEY,
|
||||
|
@ -317,7 +317,6 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
|
||||
DECLARE_META_BIND(2, screenshot, RARCH_SCREENSHOT, MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT),
|
||||
DECLARE_META_BIND(2, audio_mute, RARCH_MUTE, MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE),
|
||||
DECLARE_META_BIND(2, osk_toggle, RARCH_OSK, MENU_ENUM_LABEL_VALUE_INPUT_META_OSK),
|
||||
DECLARE_META_BIND(2, netplay_flip_players_1_2, RARCH_NETPLAY_FLIP, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP),
|
||||
DECLARE_META_BIND(2, netplay_game_watch, RARCH_NETPLAY_GAME_WATCH, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH),
|
||||
DECLARE_META_BIND(2, slowmotion, RARCH_SLOWMOTION, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION),
|
||||
DECLARE_META_BIND(2, enable_hotkey, RARCH_ENABLE_HOTKEY, MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY),
|
||||
|
@ -92,10 +92,6 @@ int menu_hash_get_help_chs_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"显示/隐藏屏显键盘。");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case RARCH_SLOWMOTION:
|
||||
snprintf(s, len,
|
||||
"按住并以慢动作运行。");
|
||||
@ -1641,11 +1637,6 @@ int menu_hash_get_help_chs_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"The username of the person running RetroArch. \n"
|
||||
"This will be used for playing online games.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"When being client over netplay, use \n"
|
||||
"keybinds for player 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"The port of the host IP address. \n"
|
||||
@ -1748,10 +1739,6 @@ int menu_hash_get_help_chs_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Saves state.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Increment cheat index.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"未提供参数也没有内建菜单,显示帮助..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"联机游戏用户已被踢出"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Setting disk in tray"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"你已作为玩家 %d 加入"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"实现有差异。确保正在使用的RetroArch和核心是同版本的。"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"This core does not support inter-architecture netplay between these systems"
|
||||
@ -824,8 +816,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"视频录制开关")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"静音开关")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"联机游戏踢出用户")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"联机游戏切换 游戏/围观 模式")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1016,8 +1006,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY,
|
||||
"在线游戏")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES,
|
||||
"在线游戏检查帧数")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"在线玩家P2使用C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"在线游戏延迟帧数")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2775,8 +2763,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -92,10 +92,6 @@ int menu_hash_get_help_cht_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"顯示/隱藏營幕鍵盤。");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case RARCH_SLOWMOTION:
|
||||
snprintf(s, len,
|
||||
"按住並以慢動作運行。");
|
||||
@ -1638,11 +1634,6 @@ int menu_hash_get_help_cht_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"The username of the person running RetroArch. \n"
|
||||
"This will be used for playing online games.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"When being client over netplay, use \n"
|
||||
"keybinds for player 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"The port of the host IP address. \n"
|
||||
@ -1745,10 +1736,6 @@ int menu_hash_get_help_cht_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"儲存即時存檔.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"踢掉連線遊戲的使用者.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Increment cheat index.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"未提供參數也沒有內建選單,顯示幫助..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"連線遊戲用戶已被踢出"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"設定光碟機裡光碟"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"你已作為玩家 %d 加入"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"執行時錯誤發生。請確保雙方的所使用的RetroArch跟核心是同版本的。"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"This core does not support inter-architecture netplay between these systems"
|
||||
@ -824,8 +816,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"視訊錄製開關")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"靜音開關")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"連線遊戲踢出用戶")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"連線遊戲切換 遊戲/圍觀 模式")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1016,8 +1006,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY,
|
||||
"連線遊戲")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES,
|
||||
"連線遊戲檢查幀數")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"連線玩家P2使用C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"連線遊戲延遲幀數")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2769,8 +2757,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -87,10 +87,6 @@ int menu_hash_get_help_de_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Bildschirmtastatur ein-/ausschalten.");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Netplay-Spieler tauschen.");
|
||||
break;
|
||||
case RARCH_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"Im Netplay zwischen Spiel- und Beobachter-Modus wechseln.");
|
||||
@ -1772,11 +1768,6 @@ int menu_hash_get_help_de_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"Der Benutzername der Person, die RetroArch verwendet. \n"
|
||||
"Wird in Online-Spielen verwendet.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"Verwendet Tastenbelegung für Spieler 1, \n"
|
||||
"wenn du Teilnehmer an einem Netplay-Spiel bist.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"Der Port der Host-IP-Adresse. \n"
|
||||
@ -1892,10 +1883,6 @@ int menu_hash_get_help_de_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Speichert Save-State.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay-Benutzer vertauschen.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Cheat-Index erhöhen.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Es wurden keine Argumente übergeben, außerdem ist kein Menü vorhanden - zeige Hilfe an..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Netplay-Benutzer wurden vertauscht"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Lege Datenträger in Laufwerksschublade ein"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Du bist als Spieler %d beigetreten"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Unterschiedliche Implementierungen. Stelle sicher, dass Du die gleiche Version von RetroArch und dem Core verwendest."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Dieser Core unterstützt kein Netplay zwischen diesen Systemen"
|
||||
@ -831,8 +823,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Videoaufzeichnung starten/beenden")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Audio stumm-/lautschalten")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay-Benutzer vertauschen")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Zwischen Spieler- und Beobachter-Modus wechseln")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1033,8 +1023,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Eingabeverzögerung")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Erlaubte Eingabeverzögerung")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay-Spieler 2 verwendet Client 1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay-Verzögerung")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2855,8 +2843,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Speichere Spielstände in Ordnern ab, die nach dem verwendeten Core benannt sind."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Verwende die Tastenbelegung für Spieler 1, wenn Du ein Client im Netplay bist.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL zum Core-Verzeichnis auf dem libretro-Buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -30,10 +30,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"No arguments supplied and no menu builtin, displaying help..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Netplay users has flipped"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Setting disk in tray"
|
||||
@ -738,8 +734,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Movie record toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Audio mute toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay flip users")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
"On-screen keyboard toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT,
|
||||
@ -928,8 +922,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY,
|
||||
"Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES,
|
||||
"Netplay Check Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 Uses C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay Delay Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2636,8 +2628,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -1084,10 +1084,6 @@ int menu_hash_get_help_es_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Guarda rápidamente la partida.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Cambia los usuarios en red.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Aumenta el índice de trucos.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"No se pasaron argumentos y no hay menú integrado, Mostrando ayuda.."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Usuarios de juego en red se fueron"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Poniendo disco en bandeja"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Unido como jugador %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Las implementaciones difieren. Asegurate de usar la misma versión de Retroarch y del núcleo"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Este núcleo no soporta juego en red entre diferentes arquitecturas de sistemas"
|
||||
@ -1182,10 +1174,6 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Silenciar audio"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Juego en red: intercambiar usuarios"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Juego en red: cambiar modo juego/espectador"
|
||||
@ -1586,10 +1574,6 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Rango de latencia en frames"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Juego en red: P2 Usa Control 1"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Juego en red: retrasar frames"
|
||||
@ -4846,10 +4830,6 @@ MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Ordenar guardados rápidos en carpetas nombradas por núcleo"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Al ser cliente de juego en red, usar controles de jugador 1"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL de la carpeta del actualizador de núcleos en el buildbot Libretro"
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Aucun paramètre fourni et pas de menu intégré, affichage de l'aide..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Utilisateurs réseau intervertis"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Disque inséré dans le lecteur"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Vous avez rejoint le jeu en tant que joueur %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Les implémentations diffèrent. Assurez vous d'utiliser les mêmes versions de RetroArch et du cœur."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Ce cœur ne supporte pas le netplay inter-architectures entre ces systèmes"
|
||||
@ -825,8 +817,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Activer l'enregistrement")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Sourdine")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Intervertir les joueurs en réseau")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Changer de mode joueur/spectateur")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1021,8 +1011,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Latence d'entrées minimale")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Intervalle de latence d'entées")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Joueur #2 contrôle manette #1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay Delay Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2807,8 +2795,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -968,14 +968,6 @@ int menu_hash_get_help_it_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Saves state.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Increment cheat index.\n");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_MINUS:
|
||||
snprintf(s, len,
|
||||
"Decrement cheat index.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Nessun argomento fornito e nessun menu incorporato, visualizzazione della guida..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Gli utenti del Netplay hanno flippato"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"impostazioni del disco nel cassetto"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Sei entrato come giocatore %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Le implementazioni differiscono. Assicurati di utilizzare le stesse versioni di RetroArch e del core."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Questo core non supporta la rete di inter-architettura tra questi sistemi"
|
||||
@ -831,8 +823,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Pulsante registratore Film")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Pulsante per disattivare l'audio ")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay flip users")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Pulsante Netplay per la modalità giocatore/spettatore")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1033,8 +1023,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Input della latenza del Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Input Latency Frames Range")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 Utilizza C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay Delay Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2853,8 +2841,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Ordina i salva stati in cartelle dopo che un core viene utilizzato."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Quando sei un client su netplay, utilizza i tasti di comando per il giocatore 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL alla directory di aggiornamento del core nel buildbot di Libretro.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -93,10 +93,6 @@ int menu_hash_get_help_jp_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Toggles onscreen keyboard.");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case RARCH_SLOWMOTION:
|
||||
snprintf(s, len,
|
||||
"Hold for slowmotion.");
|
||||
@ -1670,11 +1666,6 @@ int menu_hash_get_help_jp_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"The username of the person running RetroArch. \n"
|
||||
"This will be used for playing online games.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"When being client over netplay, use \n"
|
||||
"keybinds for player 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"The port of the host IP address. \n"
|
||||
@ -1777,10 +1768,6 @@ int menu_hash_get_help_jp_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Saves state.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Increment cheat index.\n");
|
||||
|
@ -39,10 +39,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"No arguments supplied and no menu builtin, displaying help..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Netplay users has flipped"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"ディスクがトレイに入りました。"
|
||||
@ -59,10 +55,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"「プレイヤー%d」で接続しました"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"実装が異なります。相手のRetroArchとコアのバージョンが同じに確認してください。"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"This core does not support inter-architecture netplay between these systems"
|
||||
@ -861,8 +853,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"録画")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"消音")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"ネットプレイのユーザ交換")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"ネットプレイの観覧を切り替え")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1063,8 +1053,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"入力遅延フレーム数")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"入力遅延フレーム範囲")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"ネットプレイのP2がC1を使用")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"ネットプレイの延期フレーム")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2841,8 +2829,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -91,10 +91,6 @@ int menu_hash_get_help_ko_enum(enum msg_hash_enums msg, char *s, size_t len) {
|
||||
snprintf(s, len,
|
||||
"온스크린 키보드 전환.");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"넷플레이 사용자 넘김.");
|
||||
break;
|
||||
case RARCH_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"넷플레이 플레이/관전 모드 전환.");
|
||||
@ -1729,11 +1725,6 @@ int menu_hash_get_help_ko_enum(enum msg_hash_enums msg, char *s, size_t len) {
|
||||
"The username of the person running RetroArch. \n"
|
||||
"This will be used for playing online games.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"When being client over netplay, use \n"
|
||||
"keybinds for player 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"The port of the host IP address. \n"
|
||||
@ -1849,10 +1840,6 @@ int menu_hash_get_help_ko_enum(enum msg_hash_enums msg, char *s, size_t len) {
|
||||
snprintf(s, len,
|
||||
"Saves state.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"Netplay toggle play/spectate mode.");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"제공되는 인수 및 메뉴, 도움말이 없습니다..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"넷플레이 사용자가 변경되었습니다"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"디스크 트레이 설정"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Y%d 플레이어로 입장했습니다"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"구현 방법에 차이가 있습니다. 동일한 버전의 RetroArch와 코어인지 확인하십시오."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"현재 코어는 해당 시스템 사이에서 구조 간 넷플레이를 지원하지 않습니다"
|
||||
@ -811,8 +803,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"동영상 기록 시작/중지")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"음소거 켜기/끄기")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"넷플레이 사용자 전환")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"넷플레이 플레이/관전 전환")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1007,8 +997,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"입력 대기 프레임")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"입력 대기 프레임 범위")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"넷플레이 P2 사용 C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"넷플레이 지연 프레임")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2771,8 +2759,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"코어 이름 폴더별로 저장된 상태저장파일 정렬."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"클라이어트로 넷플레이 접속시 사용자 1 키설정 사용.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"Libretro 빌드봇 상의 코어 업데이터 디렉토리 URL.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -625,8 +625,12 @@ MSG_HASH(MENU_ENUM_LABEL_NETPLAY,
|
||||
"netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_CHECK_FRAMES,
|
||||
"netplay_check_frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"netplay_client_swap_input")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_I,
|
||||
"netplay_request_device_%u")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_SHARE_ANALOG,
|
||||
"netplay_share_analog")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_SHARE_DIGITAL,
|
||||
"netplay_share_digital")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"netplay_input_latency_frames_min")
|
||||
MSG_HASH(MENU_ENUM_LABEL_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
|
@ -30,10 +30,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"No arguments supplied and no menu builtin, displaying help..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Netplay users has flipped"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Setting disk in tray"
|
||||
@ -738,8 +734,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Movie record toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Audio mute toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay flip users")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
"On-screen keyboard toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT,
|
||||
@ -926,8 +920,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY,
|
||||
"Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES,
|
||||
"Netplay Check Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 Uses C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay Vertraging Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2640,8 +2632,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Brak argumentów i brak wbudowanego menu, wyświetlanie pomocy..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Użytkownicy Netplay odwrócili się"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Ustawianie dysku w zasobniku"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Dołączyłeś jako gracz %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Implementacja różni się. Upewnij się, że używasz dokładnie tych samych wersji RetroArch i rdzenia."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Ten rdzeń nie obsługuje net-play między architekturami w tych systemach"
|
||||
@ -843,8 +835,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Przełącznik nagrywania filmu")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Przełącznik wyciszania dźwięku")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay przerzuca użytkowników")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Netplay przełącza tryb play / spectate")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1045,8 +1035,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Wejściowe klatki opóźnień")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Zakres latencji wejściowych klatek")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 Używa C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay opóźnij klatki")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2867,8 +2855,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sortuj stany zachowywania w folderach nazwanych po używanym rdzeniu."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"Adres URL do głównego katalogu Updater na kompilatorze Libretro.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -93,10 +93,6 @@ int menu_hash_get_help_pt_br_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Alternar o teclado virtual.");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Inverter usuários do Netplay.");
|
||||
break;
|
||||
case RARCH_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"Alternar modo jogador/espectador do Netplay.");
|
||||
@ -1828,11 +1824,6 @@ int menu_hash_get_help_pt_br_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"o RetroArch. \n"
|
||||
"Será utilizado para jogos online.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"Ao ser o cliente de Netplay, use os \n"
|
||||
"vínculos de teclas do jogador 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"A porta do endereço de IP do hospedeiro. \n"
|
||||
@ -1952,10 +1943,6 @@ int menu_hash_get_help_pt_br_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Salvar Estado de Jogo.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Inverter usuários do Netplay.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"Alternar modo jogador/espectador do Netplay.");
|
||||
|
@ -25,9 +25,6 @@ MSG_HASH(MSG_PUBLIC_ADDRESS,
|
||||
MSG_HASH(MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Nenhum argumento fornecido e nenhum menu interno, exibindo ajuda..."
|
||||
)
|
||||
MSG_HASH(MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Usuários do Netplay foram invertidos"
|
||||
)
|
||||
MSG_HASH(MSG_SETTING_DISK_IN_TRAY,
|
||||
"Definindo disco na bandeja"
|
||||
)
|
||||
@ -40,9 +37,6 @@ MSG_HASH(MSG_NETPLAY_YOU_HAVE_LEFT_THE_GAME,
|
||||
MSG_HASH(MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Você se juntou como jogador %d"
|
||||
)
|
||||
MSG_HASH(MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"As implementações são diferentes. Certifique-se de que está usando exatamente as mesmas versões do RetroArch e do núcleo."
|
||||
)
|
||||
MSG_HASH(MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Este núcleo não suporta Netplay inter-arquitetura entre estes sistemas"
|
||||
)
|
||||
@ -857,9 +851,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Alternar áudio mudo"
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Inverter usuários do Netplay"
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Alternar modo jogador/espectador do Netplay"
|
||||
)
|
||||
@ -1160,9 +1151,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Faixa de Quadros de Latência de Entrada"
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"J2 do Netplay Usa C1"
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Atraso de Quadros do Netplay"
|
||||
)
|
||||
@ -3581,9 +3569,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Ordenar os Estados de Jogo em pastas com o nome do núcleo utilizado."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Ao se tornar cliente do Netplay, use os vínculos de teclas para o Jogador 1."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL para o diretório de atualização de núcleos no buildbot do Libreto."
|
||||
)
|
||||
|
@ -870,10 +870,6 @@ int menu_hash_get_help_pt_pt_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Salva Savestates.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay inverte usuários.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Incrementa o índice de cheats.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Não foi fornecido qualquer argumento e nenhum menu está contido, mostrando ajuda..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Utilizadores do Netplay devolveram"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Definindo disco na bandeja"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Você juntou-se como jogador %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"As implementações são diferentes. Certifique-se de que está a versão do RetroArch e do núcleo são as mesmas."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Este núcleo não suporta inter-arquitetura de Netplay entre estes sistemas"
|
||||
@ -811,8 +803,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Alternar gravação de filme")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Alternar áudio mudo")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Giro de usuários do Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Alternar modo jogar/olhar no Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1005,8 +995,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Entrada de Latência de Quadros")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Alcance da Entrada de latência de Quadros")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"J2 do Netplay Usa C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Atraso de Quadros do Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2749,8 +2737,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Ordenar salvamento de estados em pastas com o nome do Core usado."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Ao se tornar cliente do netplay, use uma lista de teclas para o Jogador 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL para o diretório de atualização do Core no buildbot do Libreto.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -39,10 +39,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"Нет аргументов и встроенного меню, отображается справка..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Пользователи Netplay отключились"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Установка диска в привод"
|
||||
@ -59,10 +55,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"Вы присоединились под именем %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Реализации различаются. Убедитесь, что вы используете одинаковые версии RetroArch и выбранного ядра."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"Выбранное ядро не поддерживает архитектуру netplay между этими системами"
|
||||
@ -834,8 +826,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Переключатель записи видео")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Отключения звука")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Отключить пользователей Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Переключить режим игры/наблюдателя Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1030,8 +1020,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Кадры задержки ввода")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Диапазон кадров задержки ввода")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 использует C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Задержка кадров Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2822,8 +2810,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Сортировать файлы сохранений в каталогах, названные после использования ядра."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Будучи клиентом netplay, использовать привязки клавиш для Игрока 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL каталога обновлений ядра на билдботе Libretro.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -95,10 +95,6 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Toggles onscreen keyboard.");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case RARCH_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"Netplay toggle play/spectate mode.");
|
||||
@ -1753,11 +1749,6 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"The username of the person running RetroArch. \n"
|
||||
"This will be used for playing online games.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"When being client over netplay, use \n"
|
||||
"keybinds for player 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"The port of the host IP address. \n"
|
||||
@ -1873,10 +1864,6 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Saves state.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_GAME_WATCH:
|
||||
snprintf(s, len,
|
||||
"Netplay toggle play/spectate mode.");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"No arguments supplied and no menu builtin, displaying help..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Netplay users have flipped"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Setting disk in tray"
|
||||
@ -52,11 +48,43 @@ MSG_HASH(
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"You have joined as player %d"
|
||||
"You have joined as player %u"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Implementations differ. Make sure you're using the exact same versions of RetroArch and the core."
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_WITH_INPUT_DEVICES_S,
|
||||
"You have joined with input devices %.*s"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_PLAYER_S_LEFT,
|
||||
"Player %.*s has left the game"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_S_HAS_JOINED_AS_PLAYER_N,
|
||||
"%2$.*1$s has joined as player %3$u"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_S_HAS_JOINED_WITH_INPUT_DEVICES_S,
|
||||
"%2$.*1$s has joined with input devices %4$.*3$s"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_NOT_RETROARCH,
|
||||
"A netplay connection attempt failed because the peer is not running RetroArch, or is running an old version of RetroArch."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_OUT_OF_DATE,
|
||||
"The netplay peer is running an old version of RetroArch. Cannot connect."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_DIFFERENT_VERSIONS,
|
||||
"WARNING: A netplay peer is running a different version of RetroArch. If problems occur, use the same version."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_DIFFERENT_CORES,
|
||||
"A netplay peer is running a different core. Cannot connect."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_DIFFERENT_CORE_VERSIONS,
|
||||
"WARNING: A netlpay peer is running a different version of the core. If problems occur, use the same version."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
@ -94,6 +122,10 @@ MSG_HASH(
|
||||
MSG_NETPLAY_CANNOT_PLAY_NO_SLOTS,
|
||||
"There are no free player slots"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_CANNOT_PLAY_NOT_AVAILABLE,
|
||||
"The input devices requested are not available"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_CANNOT_PLAY,
|
||||
"Cannot switch to play mode"
|
||||
@ -843,8 +875,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Movie record toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Audio mute toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay flip users")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Netplay toggle play/spectate mode")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1045,8 +1075,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Input Latency Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Input Latency Frames Range")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 Uses C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay Delay Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -1071,10 +1099,30 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD,
|
||||
"Server Password")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_PUBLIC_ANNOUNCE,
|
||||
"Publicly Announce Netplay")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUEST_DEVICE_I,
|
||||
"Request Device %u")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUIRE_SLAVES,
|
||||
"Disallow Non-Slave-Mode Clients")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SETTINGS,
|
||||
"Netplay settings")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG,
|
||||
"Analog Input Sharing")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_MAX,
|
||||
"Max")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_AVERAGE,
|
||||
"Average")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL,
|
||||
"Digital Input Sharing")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_OR,
|
||||
"Share")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_XOR,
|
||||
"Grapple")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_VOTE,
|
||||
"Vote")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NONE,
|
||||
"None")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NO_PREFERENCE,
|
||||
"No preference")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_START_AS_SPECTATOR,
|
||||
"Netplay Spectator Mode")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_STATELESS_MODE,
|
||||
@ -2875,8 +2923,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_REQUEST_DEVICE_I,
|
||||
"Request to play with the given input device.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -93,10 +93,6 @@ int menu_hash_get_help_vn_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Bật/tắt bàn phím trên màn hình.");
|
||||
break;
|
||||
case RARCH_NETPLAY_FLIP:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case RARCH_SLOWMOTION:
|
||||
snprintf(s, len,
|
||||
"Nhấn để xem chậm.");
|
||||
@ -1671,11 +1667,6 @@ int menu_hash_get_help_vn_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"The username of the person running RetroArch. \n"
|
||||
"This will be used for playing online games.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
snprintf(s, len,
|
||||
"When being client over netplay, use \n"
|
||||
"keybinds for player 1.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT:
|
||||
snprintf(s, len,
|
||||
"The port of the host IP address. \n"
|
||||
@ -1778,10 +1769,6 @@ int menu_hash_get_help_vn_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
snprintf(s, len,
|
||||
"Saves state.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_FLIP_PLAYERS:
|
||||
snprintf(s, len,
|
||||
"Netplay flip users.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CHEAT_INDEX_PLUS:
|
||||
snprintf(s, len,
|
||||
"Increment cheat index.\n");
|
||||
|
@ -34,10 +34,6 @@ MSG_HASH(
|
||||
MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN,
|
||||
"No arguments supplied and no menu builtin, displaying help..."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
"Người dùng Netplay đã flipped"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
"Setting disk in tray"
|
||||
@ -54,10 +50,6 @@ MSG_HASH(
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
"You have joined as player %d"
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
"Implementations differ. Make sure you're using the exact same versions of RetroArch and the core."
|
||||
)
|
||||
MSG_HASH(
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
"This core does not support inter-architecture netplay between these systems"
|
||||
@ -823,8 +815,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MOVIE_RECORD_TOGGLE,
|
||||
"Movie record toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
"Âm thanh mute toggle")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
"Netplay flip users")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
"Netplay toggle play/spectate mode")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
@ -1019,8 +1009,6 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_MIN,
|
||||
"Input Latency Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_INPUT_LATENCY_FRAMES_RANGE,
|
||||
"Input Latency Frames Range")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"Netplay P2 Uses C1")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES,
|
||||
"Netplay Delay Frames")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT,
|
||||
@ -2799,8 +2787,6 @@ MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE,
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE,
|
||||
"Sort save states in folders named after the core used."
|
||||
)
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
"When being client over netplay, use keybinds for Player 1.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL,
|
||||
"URL to core updater directory on the Libretro buildbot.")
|
||||
MSG_HASH(MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL,
|
||||
|
@ -43,6 +43,10 @@
|
||||
#include "../../verbosity.h"
|
||||
#include "../../wifi/wifi_driver.h"
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include "../network/netplay/netplay.h"
|
||||
#endif
|
||||
|
||||
#ifndef BIND_ACTION_GET_VALUE
|
||||
#define BIND_ACTION_GET_VALUE(cbs, name) \
|
||||
cbs->action_get_value = name; \
|
||||
@ -1714,6 +1718,84 @@ static void menu_action_setting_disp_set_label_setting_path(file_list_t* list,
|
||||
strlcpy(s2, path, len2);
|
||||
}
|
||||
|
||||
static void menu_action_setting_disp_set_label_netplay_share_digital(file_list_t* list,
|
||||
unsigned *w, unsigned type, unsigned i,
|
||||
const char *label,
|
||||
char *s, size_t len,
|
||||
const char *entry_label,
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *src;
|
||||
|
||||
if (!settings)
|
||||
return;
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
*w = 19;
|
||||
switch (settings->uints.netplay_share_digital)
|
||||
{
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NO_PREFERENCE);
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_OR:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_OR);
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_XOR:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_XOR);
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_VOTE:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_VOTE);
|
||||
break;
|
||||
|
||||
default:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NONE);
|
||||
break;
|
||||
}
|
||||
strlcpy(s, src, len);
|
||||
}
|
||||
|
||||
static void menu_action_setting_disp_set_label_netplay_share_analog(file_list_t* list,
|
||||
unsigned *w, unsigned type, unsigned i,
|
||||
const char *label,
|
||||
char *s, size_t len,
|
||||
const char *entry_label,
|
||||
const char *path,
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *src;
|
||||
|
||||
if (!settings)
|
||||
return;
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
*w = 19;
|
||||
switch (settings->uints.netplay_share_analog)
|
||||
{
|
||||
case RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NO_PREFERENCE);
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_SHARE_ANALOG_MAX:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_MAX);
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_SHARE_ANALOG_AVERAGE:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_AVERAGE);
|
||||
break;
|
||||
|
||||
default:
|
||||
src = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NONE);
|
||||
break;
|
||||
}
|
||||
strlcpy(s, src, len);
|
||||
}
|
||||
|
||||
static int menu_cbs_init_bind_get_string_representation_compare_label(
|
||||
menu_file_list_cbs_t *cbs)
|
||||
{
|
||||
@ -1817,6 +1899,14 @@ static int menu_cbs_init_bind_get_string_representation_compare_label(
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_menu_input_keyboard_gamepad_mapping_type);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_SHARE_DIGITAL:
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_netplay_share_digital);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_SHARE_ANALOG:
|
||||
BIND_ACTION_GET_VALUE(cbs,
|
||||
menu_action_setting_disp_set_label_netplay_share_analog);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_CONTENT_COLLECTION_LIST:
|
||||
case MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY:
|
||||
case MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST:
|
||||
|
@ -229,7 +229,6 @@ default_sublabel_macro(action_bind_sublabel_scan_directory, MENU_
|
||||
default_sublabel_macro(action_bind_sublabel_video_swap_interval, MENU_ENUM_SUBLABEL_VIDEO_SWAP_INTERVAL)
|
||||
default_sublabel_macro(action_bind_sublabel_sort_savefiles_enable, MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE)
|
||||
default_sublabel_macro(action_bind_sublabel_sort_savestates_enable, MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE)
|
||||
default_sublabel_macro(action_bind_sublabel_netplay_client_swap_input, MENU_ENUM_SUBLABEL_NETPLAY_CLIENT_SWAP_INPUT)
|
||||
default_sublabel_macro(action_bind_sublabel_core_updater_buildbot_url, MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL)
|
||||
default_sublabel_macro(action_bind_sublabel_input_overlay_show_physical_inputs, MENU_ENUM_SUBLABEL_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS)
|
||||
default_sublabel_macro(action_bind_sublabel_input_overlay_show_physical_inputs_port, MENU_ENUM_SUBLABEL_INPUT_OVERLAY_SHOW_PHYSICAL_INPUTS_PORT)
|
||||
@ -886,9 +885,6 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_BUILDBOT_ASSETS_URL:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_updater_buildbot_assets_url);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_client_swap_input);
|
||||
break;
|
||||
case MENU_ENUM_LABEL_SORT_SAVEFILES_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_sort_savefiles_enable);
|
||||
break;
|
||||
|
@ -5544,9 +5544,20 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data)
|
||||
PARSE_ONLY_BOOL, false) != -1)
|
||||
count++;
|
||||
if (menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
PARSE_ONLY_BOOL, false) != -1)
|
||||
MENU_ENUM_LABEL_NETPLAY_SHARE_DIGITAL,
|
||||
PARSE_ONLY_UINT, false) != -1)
|
||||
count++;
|
||||
if (menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_NETPLAY_SHARE_ANALOG,
|
||||
PARSE_ONLY_UINT, false) != -1)
|
||||
count++;
|
||||
for (user = 0; user < MAX_USERS; user++)
|
||||
{
|
||||
if (menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1 + user,
|
||||
PARSE_ONLY_BOOL, false) != -1)
|
||||
count++;
|
||||
}
|
||||
if (menu_displaylist_parse_settings_enum(menu, info,
|
||||
MENU_ENUM_LABEL_NETWORK_CMD_ENABLE,
|
||||
PARSE_ONLY_BOOL, false) != -1)
|
||||
|
@ -86,6 +86,10 @@
|
||||
|
||||
#include "../tasks/tasks_internal.h"
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include "../network/netplay/netplay.h"
|
||||
#endif
|
||||
|
||||
enum settings_list_type
|
||||
{
|
||||
SETTINGS_LIST_NONE = 0,
|
||||
@ -6698,9 +6702,10 @@ static bool setting_append_list(
|
||||
|
||||
{
|
||||
#if defined(HAVE_NETWORKING)
|
||||
#if defined(HAVE_NETWORK_CMD)
|
||||
unsigned user;
|
||||
#endif
|
||||
char dev_req_label[64];
|
||||
char dev_req_value[64];
|
||||
|
||||
CONFIG_BOOL(
|
||||
list, list_info,
|
||||
&settings->bools.netplay_public_announce,
|
||||
@ -6908,21 +6913,55 @@ static bool setting_append_list(
|
||||
SD_FLAG_NONE);
|
||||
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED);
|
||||
|
||||
CONFIG_BOOL(
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->bools.netplay_swap_input,
|
||||
MENU_ENUM_LABEL_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_CLIENT_SWAP_INPUT,
|
||||
netplay_client_swap_input,
|
||||
MENU_ENUM_LABEL_VALUE_OFF,
|
||||
MENU_ENUM_LABEL_VALUE_ON,
|
||||
&settings->uints.netplay_share_digital,
|
||||
MENU_ENUM_LABEL_NETPLAY_SHARE_DIGITAL,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL,
|
||||
0,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE);
|
||||
settings_data_list_current_add_flags(list, list_info, SD_FLAG_ADVANCED);
|
||||
general_read_handler);
|
||||
menu_settings_list_current_add_range(list, list_info, 0, RARCH_NETPLAY_SHARE_DIGITAL_LAST-1, 1, true, true);
|
||||
|
||||
CONFIG_UINT(
|
||||
list, list_info,
|
||||
&settings->uints.netplay_share_analog,
|
||||
MENU_ENUM_LABEL_NETPLAY_SHARE_ANALOG,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG,
|
||||
0,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
menu_settings_list_current_add_range(list, list_info, 0, RARCH_NETPLAY_SHARE_ANALOG_LAST-1, 1, true, true);
|
||||
|
||||
for (user = 0; user < MAX_USERS; user++)
|
||||
{
|
||||
snprintf(dev_req_label, sizeof(dev_req_label),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_I), user + 1);
|
||||
snprintf(dev_req_value, sizeof(dev_req_value),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_REQUEST_DEVICE_I), user + 1);
|
||||
CONFIG_BOOL_ALT(
|
||||
list, list_info,
|
||||
&settings->bools.netplay_request_devices[user],
|
||||
strdup(dev_req_label),
|
||||
strdup(dev_req_value),
|
||||
false,
|
||||
MENU_ENUM_LABEL_VALUE_NO,
|
||||
MENU_ENUM_LABEL_VALUE_YES,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
general_write_handler,
|
||||
general_read_handler,
|
||||
SD_FLAG_ADVANCED);
|
||||
settings_data_list_current_add_free_flags(list, list_info, SD_FREE_FLAG_NAME | SD_FREE_FLAG_SHORT);
|
||||
menu_settings_list_current_add_enum_idx(list, list_info, (enum msg_hash_enums)(MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1 + user));
|
||||
}
|
||||
|
||||
END_SUB_GROUP(list, list_info, parent_group);
|
||||
|
||||
|
28
msg_hash.h
28
msg_hash.h
@ -153,7 +153,6 @@ enum msg_hash_enums
|
||||
MSG_SETTING_DISK_IN_TRAY,
|
||||
MSG_FAILED_TO_SET_DISK,
|
||||
MSG_NETPLAY_FAILED,
|
||||
MSG_NETPLAY_USERS_HAS_FLIPPED,
|
||||
MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED,
|
||||
MSG_CONNECTING_TO_NETPLAY_HOST,
|
||||
MSG_NETPLAY_LAN_SCAN_COMPLETE,
|
||||
@ -161,7 +160,15 @@ enum msg_hash_enums
|
||||
MSG_WAITING_FOR_CLIENT,
|
||||
MSG_NETPLAY_YOU_HAVE_LEFT_THE_GAME,
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N,
|
||||
MSG_NETPLAY_IMPLEMENTATIONS_DIFFER,
|
||||
MSG_NETPLAY_YOU_HAVE_JOINED_WITH_INPUT_DEVICES_S,
|
||||
MSG_NETPLAY_PLAYER_S_LEFT,
|
||||
MSG_NETPLAY_S_HAS_JOINED_AS_PLAYER_N,
|
||||
MSG_NETPLAY_S_HAS_JOINED_WITH_INPUT_DEVICES_S,
|
||||
MSG_NETPLAY_NOT_RETROARCH,
|
||||
MSG_NETPLAY_OUT_OF_DATE,
|
||||
MSG_NETPLAY_DIFFERENT_VERSIONS,
|
||||
MSG_NETPLAY_DIFFERENT_CORES,
|
||||
MSG_NETPLAY_DIFFERENT_CORE_VERSIONS,
|
||||
MSG_NETPLAY_ENDIAN_DEPENDENT,
|
||||
MSG_NETPLAY_PLATFORM_DEPENDENT,
|
||||
MSG_NETPLAY_ENTER_PASSWORD,
|
||||
@ -171,6 +178,7 @@ enum msg_hash_enums
|
||||
MSG_NETPLAY_CLIENT_HANGUP,
|
||||
MSG_NETPLAY_CANNOT_PLAY_UNPRIVILEGED,
|
||||
MSG_NETPLAY_CANNOT_PLAY_NO_SLOTS,
|
||||
MSG_NETPLAY_CANNOT_PLAY_NOT_AVAILABLE,
|
||||
MSG_NETPLAY_CANNOT_PLAY,
|
||||
MSG_NETPLAY_PEER_PAUSED,
|
||||
MSG_NETPLAY_CHANGED_NICK,
|
||||
@ -605,7 +613,6 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_OSK,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FLIP,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY,
|
||||
@ -1103,7 +1110,6 @@ enum msg_hash_enums
|
||||
MENU_LABEL(UNDO_LOAD_STATE),
|
||||
MENU_LABEL(UNDO_SAVE_STATE),
|
||||
|
||||
MENU_LABEL(NETPLAY_FLIP_PLAYERS),
|
||||
MENU_LABEL(NETPLAY_GAME_WATCH),
|
||||
MENU_LABEL(CHEAT_INDEX_MINUS),
|
||||
MENU_LABEL(CHEAT_INDEX_PLUS),
|
||||
@ -1156,7 +1162,6 @@ enum msg_hash_enums
|
||||
MENU_LABEL(SSH_ENABLE),
|
||||
MENU_LABEL(SAMBA_ENABLE),
|
||||
MENU_LABEL(BLUETOOTH_ENABLE),
|
||||
MENU_LABEL(NETPLAY_CLIENT_SWAP_INPUT),
|
||||
MENU_LABEL(NETPLAY_DELAY_FRAMES),
|
||||
MENU_LABEL(NETPLAY_PUBLIC_ANNOUNCE),
|
||||
MENU_LABEL(NETPLAY_START_AS_SPECTATOR),
|
||||
@ -1169,6 +1174,19 @@ enum msg_hash_enums
|
||||
MENU_LABEL(NETPLAY_SPECTATOR_MODE_ENABLE),
|
||||
MENU_LABEL(NETPLAY_TCP_UDP_PORT),
|
||||
MENU_LABEL(NETPLAY_NAT_TRAVERSAL),
|
||||
MENU_LABEL(NETPLAY_REQUEST_DEVICE_I),
|
||||
MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1,
|
||||
MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_LAST = MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1 + MAX_USERS,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_NO_PREFERENCE,
|
||||
MENU_LABEL(NETPLAY_SHARE_DIGITAL),
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_OR,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_XOR,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_DIGITAL_VOTE,
|
||||
MENU_LABEL(NETPLAY_SHARE_ANALOG),
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_MAX,
|
||||
MENU_ENUM_LABEL_VALUE_NETPLAY_SHARE_ANALOG_AVERAGE,
|
||||
|
||||
MENU_LABEL(SORT_SAVEFILES_ENABLE),
|
||||
MENU_LABEL(SORT_SAVESTATES_ENABLE),
|
||||
MENU_LABEL(SAVEFILES_IN_CONTENT_DIR_ENABLE),
|
||||
|
@ -106,6 +106,10 @@ early (i.e., it only forwards data on the frame it's reached), it must also
|
||||
inform all clients of its own current frame even if it has no input. The
|
||||
NOINPUT command is provided for that purpose.
|
||||
|
||||
Each client has a client number, and the server is always client number 0.
|
||||
Client numbers are currently limited to 0-31, as they're used in 32-bit
|
||||
bitmaps.
|
||||
|
||||
The handshake procedure (this part is done by both server and client):
|
||||
1) Send connection header
|
||||
2) Receive and verify connection header
|
||||
@ -155,18 +159,16 @@ Command: INPUT
|
||||
Payload:
|
||||
{
|
||||
frame number: uint32
|
||||
is server data: 1 bit
|
||||
player: 31 bits
|
||||
joypad input: uint32
|
||||
analog 1 input: uint32
|
||||
analog 2 input: uint32
|
||||
client number: uint32
|
||||
input data: variable
|
||||
}
|
||||
Description:
|
||||
Input state for each frame. Netplay must send an INPUT command for every
|
||||
frame in order to function at all. Client's player value is ignored. Server
|
||||
indicates which frames are its own input data because INPUT is a
|
||||
synchronization point: No synchronization events from the given frame may
|
||||
arrive after the server's input for the frame.
|
||||
frame in order to function at all. When sent from the server (client 0),
|
||||
INPUT is a synchronization point: No synchronization events from the given
|
||||
frame may arrive after the server's input for the frame. The actual size of
|
||||
the input data is variable, but must match the expected size for each of
|
||||
the devices the given client controls.
|
||||
|
||||
Command: NOINPUT
|
||||
Payload:
|
||||
@ -213,9 +215,10 @@ Payload:
|
||||
{
|
||||
frame number: uint32
|
||||
paused?: 1 bit
|
||||
connected players: 31 bits
|
||||
flip frame: uint32
|
||||
client number: 31 bits
|
||||
controller devices: uint32[16]
|
||||
share modes: uint8[16]
|
||||
controller-client mapping: uint32[16]
|
||||
client nick: char[32]
|
||||
sram: variable
|
||||
}
|
||||
@ -236,23 +239,31 @@ Description:
|
||||
Command: PLAY
|
||||
Payload:
|
||||
{
|
||||
reserved: 31 bits
|
||||
as slave?: 1 bit
|
||||
reserved: 7 bits
|
||||
preferred share mode: 8 bits
|
||||
requested device(s): 16 bits
|
||||
}
|
||||
Description:
|
||||
Request to enter player mode. The client must wait for a MODE command
|
||||
before sending input. Server may refuse or force slave connections, so the
|
||||
request is not necessarily honored. Payload may be elided if zero.
|
||||
request is not necessarily honored. If no devices are explicitly requested,
|
||||
the server may choose how to assign; the default is to assign the first
|
||||
unassigned device, and share the first device if all devices are assigned
|
||||
and the first device is shareable.
|
||||
|
||||
Command: MODE
|
||||
Payload:
|
||||
{
|
||||
frame number: uint32
|
||||
reserved: 13 bits
|
||||
slave: 1 bit
|
||||
playing: 1 bit
|
||||
you: 1 bit
|
||||
player number: uint16
|
||||
playing: 1 bit
|
||||
slave: 1 bit
|
||||
reserved: 13 bits
|
||||
client number: uint16
|
||||
device bitmap: uint32
|
||||
share modes: uint8[16]
|
||||
nick: char[32]
|
||||
}
|
||||
Description:
|
||||
Inform of a connection mode change (possibly of the receiving client). Only
|
||||
@ -346,3 +357,43 @@ Unused
|
||||
|
||||
Command: CFG_ACK
|
||||
Unused
|
||||
|
||||
|
||||
Input types
|
||||
|
||||
Each input device uses a number of words fixed by the type of device. When
|
||||
buttons are listed, they are listed from lowest bit to highest bit, i.e.,
|
||||
reverse order. When insufficient buttons are present to represent to represent
|
||||
a full 32-bit word, the remainder are reserved and unused.
|
||||
|
||||
JOYPAD
|
||||
{
|
||||
B, Y, Select, Start, Up, Down, Left, Right, A, X, L, R, L2, R2, L3, R3
|
||||
}
|
||||
|
||||
MOUSE
|
||||
{
|
||||
unused, unused, Left, Right, Wheel up, Wheel down, Middle, Horizontal
|
||||
wheel up, Horizontal wheel down
|
||||
Y: int16
|
||||
X: int16
|
||||
}
|
||||
|
||||
KEYBOARD
|
||||
(5 words, see netplay_keys.h)
|
||||
|
||||
LIGHTGUN
|
||||
{
|
||||
unused, unused, Trigger, Cursor, Turbo, Pause, Start
|
||||
Y: int16
|
||||
X: int16
|
||||
}
|
||||
|
||||
ANALOG
|
||||
{
|
||||
buttons: uint32, as JOYPAD
|
||||
Left analog Y: int16
|
||||
Left analog X: int16
|
||||
Right analog Y: int16
|
||||
Right analog X: int16
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ typedef struct netplay netplay_t;
|
||||
enum rarch_netplay_ctl_state
|
||||
{
|
||||
RARCH_NETPLAY_CTL_NONE = 0,
|
||||
RARCH_NETPLAY_CTL_FLIP_PLAYERS,
|
||||
RARCH_NETPLAY_CTL_GAME_WATCH,
|
||||
RARCH_NETPLAY_CTL_POST_FRAME,
|
||||
RARCH_NETPLAY_CTL_PRE_FRAME,
|
||||
@ -53,6 +52,27 @@ enum rarch_netplay_ctl_state
|
||||
RARCH_NETPLAY_CTL_DESYNC_POP
|
||||
};
|
||||
|
||||
/* Preferences for sharing digital devices */
|
||||
enum rarch_netplay_share_digital_preference
|
||||
{
|
||||
RARCH_NETPLAY_SHARE_DIGITAL_NO_SHARING,
|
||||
RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE,
|
||||
RARCH_NETPLAY_SHARE_DIGITAL_OR,
|
||||
RARCH_NETPLAY_SHARE_DIGITAL_XOR,
|
||||
RARCH_NETPLAY_SHARE_DIGITAL_VOTE,
|
||||
RARCH_NETPLAY_SHARE_DIGITAL_LAST
|
||||
};
|
||||
|
||||
/* Preferences for sharing analog devices */
|
||||
enum rarch_netplay_share_analog_preference
|
||||
{
|
||||
RARCH_NETPLAY_SHARE_ANALOG_NO_SHARING,
|
||||
RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE,
|
||||
RARCH_NETPLAY_SHARE_ANALOG_MAX,
|
||||
RARCH_NETPLAY_SHARE_ANALOG_AVERAGE,
|
||||
RARCH_NETPLAY_SHARE_ANALOG_LAST
|
||||
};
|
||||
|
||||
int16_t input_state_net(unsigned port, unsigned device,
|
||||
unsigned idx, unsigned id);
|
||||
|
||||
|
@ -23,6 +23,15 @@
|
||||
|
||||
#include "netplay_private.h"
|
||||
|
||||
static void clear_input(netplay_input_state_t istate)
|
||||
{
|
||||
while (istate)
|
||||
{
|
||||
istate->used = false;
|
||||
istate = istate->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_delta_frame_ready
|
||||
*
|
||||
@ -35,7 +44,7 @@
|
||||
bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta,
|
||||
uint32_t frame)
|
||||
{
|
||||
void *remember_state;
|
||||
size_t i;
|
||||
if (delta->used)
|
||||
{
|
||||
if (delta->frame == frame) return true;
|
||||
@ -45,11 +54,18 @@ bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
remember_state = delta->state;
|
||||
memset(delta, 0, sizeof(struct delta_frame));
|
||||
delta->used = true;
|
||||
delta->frame = frame;
|
||||
delta->state = remember_state;
|
||||
delta->crc = 0;
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
clear_input(delta->resolved_input[i]);
|
||||
clear_input(delta->real_input[i]);
|
||||
clear_input(delta->simlated_input[i]);
|
||||
}
|
||||
delta->have_local = false;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
delta->have_real[i] = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -64,3 +80,110 @@ uint32_t netplay_delta_frame_crc(netplay_t *netplay, struct delta_frame *delta)
|
||||
return 0;
|
||||
return encoding_crc32(0L, (const unsigned char*)delta->state, netplay->state_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free an input state list
|
||||
*/
|
||||
static void free_input_state(netplay_input_state_t *list)
|
||||
{
|
||||
netplay_input_state_t cur, next;
|
||||
cur = *list;
|
||||
while (cur)
|
||||
{
|
||||
next = cur->next;
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
*list = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_delta_frame_free
|
||||
*
|
||||
* Free a delta frame's dependencies
|
||||
*/
|
||||
void netplay_delta_frame_free(struct delta_frame *delta)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (delta->state)
|
||||
{
|
||||
free(delta->state);
|
||||
delta->state = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
free_input_state(&delta->resolved_input[i]);
|
||||
free_input_state(&delta->real_input[i]);
|
||||
free_input_state(&delta->simlated_input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_input_state_for
|
||||
*
|
||||
* Get an input state for a particular client
|
||||
*/
|
||||
netplay_input_state_t netplay_input_state_for(netplay_input_state_t *list,
|
||||
uint32_t client_num, size_t size, bool must_create, bool must_not_create)
|
||||
{
|
||||
netplay_input_state_t ret;
|
||||
while (*list)
|
||||
{
|
||||
ret = *list;
|
||||
if (!ret->used && !must_not_create && ret->size == size)
|
||||
{
|
||||
ret->client_num = client_num;
|
||||
ret->used = true;
|
||||
memset(ret->data, 0, size*sizeof(uint32_t));
|
||||
return ret;
|
||||
}
|
||||
else if (ret->used && ret->client_num == client_num)
|
||||
{
|
||||
if (!must_create && ret->size == size)
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
list = &(ret->next);
|
||||
}
|
||||
|
||||
if (must_not_create)
|
||||
return NULL;
|
||||
|
||||
/* Couldn't find a slot, allocate a fresh one */
|
||||
ret = calloc(1, sizeof(struct netplay_input_state) + (size-1) * sizeof(uint32_t));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
*list = ret;
|
||||
ret->client_num = client_num;
|
||||
ret->used = true;
|
||||
ret->size = size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_expected_input_size
|
||||
*
|
||||
* Size in words for a given set of devices.
|
||||
*/
|
||||
uint32_t netplay_expected_input_size(netplay_t *netplay, uint32_t devices)
|
||||
{
|
||||
uint32_t ret = 0, device;
|
||||
for (device = 0; device < MAX_INPUT_DEVICES; device++)
|
||||
{
|
||||
if (!(devices & (1<<device))) continue;
|
||||
switch (netplay->config_devices[device]&RETRO_DEVICE_MASK)
|
||||
{
|
||||
/* These are all essentially magic numbers, but each device has a
|
||||
* 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 */
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ static bool netplay_is_alive(void)
|
||||
{
|
||||
if (!netplay_data)
|
||||
return false;
|
||||
return (netplay_data->is_server && !!netplay_data->connected_players) ||
|
||||
return (netplay_data->is_server) ||
|
||||
(!netplay_data->is_server && netplay_data->self_mode >= NETPLAY_CONNECTION_CONNECTED);
|
||||
}
|
||||
|
||||
@ -115,8 +115,9 @@ static bool netplay_can_poll(netplay_t *netplay)
|
||||
*/
|
||||
static bool get_self_input_state(netplay_t *netplay)
|
||||
{
|
||||
uint32_t state[WORDS_PER_INPUT] = {0, 0, 0};
|
||||
struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr];
|
||||
netplay_input_state_t istate = NULL;
|
||||
uint32_t devices, used_devices = 0, devi, dev_type, local_device;
|
||||
size_t i;
|
||||
|
||||
if (!netplay_delta_frame_ready(netplay, ptr, netplay->self_frame_count))
|
||||
@ -128,37 +129,110 @@ static bool get_self_input_state(netplay_t *netplay)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!input_driver_is_libretro_input_blocked() && netplay->self_frame_count > 0)
|
||||
devices = netplay->self_devices;
|
||||
used_devices = 0;
|
||||
for (devi = 0; devi < MAX_INPUT_DEVICES; devi++)
|
||||
{
|
||||
if (!(devices & (1<<devi)))
|
||||
continue;
|
||||
|
||||
/* Find an appropriate local device */
|
||||
dev_type = netplay->config_devices[devi]&RETRO_DEVICE_MASK;
|
||||
for (local_device = 0; local_device < MAX_INPUT_DEVICES; local_device++)
|
||||
{
|
||||
if (used_devices & (1<<local_device)) continue;
|
||||
if ((netplay->config_devices[local_device]&RETRO_DEVICE_MASK) == dev_type) break;
|
||||
}
|
||||
if (local_device == MAX_INPUT_DEVICES)
|
||||
local_device = 0;
|
||||
used_devices |= (1<<local_device);
|
||||
|
||||
istate = netplay_input_state_for(&ptr->real_input[devi],
|
||||
/* If we're a slave, we write our own input to MAX_CLIENTS to keep it separate */
|
||||
(netplay->self_mode==NETPLAY_CONNECTION_SLAVE)?MAX_CLIENTS:netplay->self_client_num,
|
||||
netplay_expected_input_size(netplay, 1 << devi),
|
||||
true, false);
|
||||
if (!istate)
|
||||
continue; /* FIXME: More severe? */
|
||||
|
||||
/* First frame we always give zero input since relying on
|
||||
* input from first frame screws up when we use -F 0. */
|
||||
retro_input_state_t cb = netplay->cbs.state_cb;
|
||||
for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
|
||||
if (!input_driver_is_libretro_input_blocked() && netplay->self_frame_count > 0)
|
||||
{
|
||||
int16_t tmp = cb(0,
|
||||
RETRO_DEVICE_JOYPAD, 0, (unsigned)i);
|
||||
state[0] |= tmp ? 1 << i : 0;
|
||||
}
|
||||
uint32_t *state = istate->data;
|
||||
retro_input_state_t cb = netplay->cbs.state_cb;
|
||||
unsigned dtype = netplay->config_devices[devi]&RETRO_DEVICE_MASK;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
int16_t tmp_x = cb(0,
|
||||
RETRO_DEVICE_ANALOG, (unsigned)i, 0);
|
||||
int16_t tmp_y = cb(0,
|
||||
RETRO_DEVICE_ANALOG, (unsigned)i, 1);
|
||||
state[1 + i] = (uint16_t)tmp_x | (((uint16_t)tmp_y) << 16);
|
||||
switch (dtype)
|
||||
{
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
int16_t tmp_x = cb(local_device,
|
||||
RETRO_DEVICE_ANALOG, (unsigned)i, 0);
|
||||
int16_t tmp_y = cb(local_device,
|
||||
RETRO_DEVICE_ANALOG, (unsigned)i, 1);
|
||||
state[1 + i] = (uint16_t)tmp_x | (((uint16_t)tmp_y) << 16);
|
||||
}
|
||||
/* no break */
|
||||
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
for (i = 0; i <= RETRO_DEVICE_ID_JOYPAD_R3; i++)
|
||||
{
|
||||
int16_t tmp = cb(local_device,
|
||||
RETRO_DEVICE_JOYPAD, 0, (unsigned)i);
|
||||
state[0] |= tmp ? 1 << i : 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
{
|
||||
int16_t tmp_x = cb(local_device, dtype, 0, 0);
|
||||
int16_t tmp_y = cb(local_device, dtype, 0, 1);
|
||||
state[1] = (uint16_t)tmp_x | (((uint16_t)tmp_y) << 16);
|
||||
for (i = 2;
|
||||
i <= ((dtype == RETRO_DEVICE_MOUSE) ?
|
||||
RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN :
|
||||
RETRO_DEVICE_ID_LIGHTGUN_START);
|
||||
i++)
|
||||
{
|
||||
int16_t tmp = cb(local_device, dtype, 0,
|
||||
(unsigned) i);
|
||||
state[0] |= tmp ? 1 << i : 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(ptr->self_state, state, sizeof(state));
|
||||
ptr->have_local = true;
|
||||
|
||||
/* If we're playing, copy it in as real input */
|
||||
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING)
|
||||
{
|
||||
memcpy(ptr->real_input_state[netplay->self_player], state,
|
||||
sizeof(state));
|
||||
ptr->have_real[netplay->self_player] = true;
|
||||
ptr->have_real[netplay->self_client_num] = true;
|
||||
netplay->read_ptr[netplay->self_client_num] = NEXT_PTR(netplay->self_ptr);
|
||||
netplay->read_frame_count[netplay->self_client_num] = netplay->self_frame_count + 1;
|
||||
}
|
||||
|
||||
/* And send this input to our peers */
|
||||
@ -203,7 +277,7 @@ bool init_netplay_deferred(const char* server, unsigned port)
|
||||
static bool netplay_poll(void)
|
||||
{
|
||||
int res;
|
||||
uint32_t player;
|
||||
uint32_t client;
|
||||
size_t i;
|
||||
|
||||
netplay_data->can_poll = false;
|
||||
@ -219,7 +293,7 @@ static bool netplay_poll(void)
|
||||
* frame */
|
||||
netplay_update_unread_ptr(netplay_data);
|
||||
if (netplay_data->stateless_mode &&
|
||||
netplay_data->connected_players &&
|
||||
(netplay_data->connected_players>1) &&
|
||||
netplay_data->unread_frame_count <= netplay_data->run_frame_count)
|
||||
res = netplay_poll_net_input(netplay_data, true);
|
||||
else
|
||||
@ -227,8 +301,8 @@ static bool netplay_poll(void)
|
||||
if (res == -1)
|
||||
goto catastrophe;
|
||||
|
||||
/* Simulate the input if we don't have real input */
|
||||
netplay_simulate_input(netplay_data, netplay_data->run_ptr, false);
|
||||
/* Resolve and/or simulate the input if we don't have real input */
|
||||
netplay_resolve_input(netplay_data, netplay_data->run_ptr, false);
|
||||
|
||||
/* Handle any slaves */
|
||||
if (netplay_data->is_server && netplay_data->connected_slaves)
|
||||
@ -369,21 +443,19 @@ static bool netplay_poll(void)
|
||||
/* Figure out who to blame */
|
||||
if (netplay_data->is_server)
|
||||
{
|
||||
for (player = 0; player < MAX_USERS; player++)
|
||||
for (client = 1; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(netplay_data->connected_players & (1<<player))) continue;
|
||||
if (netplay_data->read_frame_count[player] > netplay_data->unread_frame_count) continue;
|
||||
for (i = 0; i < netplay_data->connections_size; i++)
|
||||
struct netplay_connection *connection;
|
||||
if (!(netplay_data->connected_players & (1<<client)))
|
||||
continue;
|
||||
if (netplay_data->read_frame_count[client] > netplay_data->unread_frame_count)
|
||||
continue;
|
||||
connection = &netplay_data->connections[client-1];
|
||||
if (connection->active &&
|
||||
connection->mode == NETPLAY_CONNECTION_PLAYING)
|
||||
{
|
||||
struct netplay_connection *connection = &netplay_data->connections[i];
|
||||
if (connection->active &&
|
||||
connection->mode == NETPLAY_CONNECTION_PLAYING &&
|
||||
connection->player == player)
|
||||
{
|
||||
connection->stall = NETPLAY_STALL_RUNNING_FAST;
|
||||
connection->stall_time = netplay_data->stall_time;
|
||||
break;
|
||||
}
|
||||
connection->stall = NETPLAY_STALL_RUNNING_FAST;
|
||||
connection->stall_time = netplay_data->stall_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -480,32 +552,37 @@ static int16_t netplay_input_state(netplay_t *netplay,
|
||||
{
|
||||
size_t ptr = netplay->is_replay ?
|
||||
netplay->replay_ptr : netplay->run_ptr;
|
||||
struct delta_frame *delta;
|
||||
netplay_input_state_t istate;
|
||||
|
||||
const uint32_t *curr_input_state = NULL;
|
||||
|
||||
if (port <= 1)
|
||||
{
|
||||
/* Possibly flip the port */
|
||||
if (netplay_flip_port(netplay))
|
||||
port ^= 1;
|
||||
}
|
||||
else if (port >= MAX_USERS)
|
||||
{
|
||||
if (port >= MAX_INPUT_DEVICES)
|
||||
return 0;
|
||||
|
||||
/* If the port doesn't seem to correspond to the device, "correct" it. This
|
||||
* 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)
|
||||
{
|
||||
for (port = 0; port < MAX_INPUT_DEVICES; port++)
|
||||
{
|
||||
if ((netplay->config_devices[port]&RETRO_DEVICE_MASK) == device)
|
||||
break;
|
||||
}
|
||||
if (port == MAX_INPUT_DEVICES)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (port > netplay->player_max)
|
||||
netplay->player_max = port;
|
||||
delta = &netplay->buffer[ptr];
|
||||
istate = delta->resolved_input[port];
|
||||
if (!istate || !istate->used)
|
||||
return 0;
|
||||
|
||||
if (netplay->buffer[ptr].have_real[port])
|
||||
{
|
||||
netplay->buffer[ptr].used_real[port] = true;
|
||||
curr_input_state = netplay->buffer[ptr].real_input_state[port];
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_input_state = netplay->buffer[ptr].simulated_input_state[port];
|
||||
}
|
||||
if (istate->size == 0)
|
||||
return 0;
|
||||
curr_input_state = istate->data;
|
||||
|
||||
switch (device)
|
||||
{
|
||||
@ -514,10 +591,36 @@ static int16_t netplay_input_state(netplay_t *netplay,
|
||||
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
{
|
||||
uint32_t state = curr_input_state[1 + idx];
|
||||
uint32_t state;
|
||||
if (istate->size != 3)
|
||||
return 0;
|
||||
state = curr_input_state[1 + idx];
|
||||
return (int16_t)(uint16_t)(state >> (id * 16));
|
||||
}
|
||||
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
{
|
||||
if (istate->size != 2)
|
||||
return 0;
|
||||
if (id <= RETRO_DEVICE_ID_MOUSE_Y)
|
||||
return (int16_t)(uint16_t)(curr_input_state[1] >> (id * 16));
|
||||
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<<bit) & curr_input_state[word]) ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -736,36 +839,7 @@ bool netplay_command(netplay_t* netplay, struct netplay_connection *connection,
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_flip_users:
|
||||
* @netplay : pointer to netplay object
|
||||
*
|
||||
* Flip who controls user 1 and 2.
|
||||
*/
|
||||
static void netplay_flip_users(netplay_t *netplay)
|
||||
{
|
||||
/* Must be in the future because we may have
|
||||
* already sent this frame's data */
|
||||
uint32_t flip_frame = netplay->self_frame_count + 1;
|
||||
uint32_t flip_frame_net = htonl(flip_frame);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < netplay->connections_size; i++)
|
||||
{
|
||||
struct netplay_connection *connection = &netplay->connections[i];
|
||||
if (connection->active && connection->mode >= NETPLAY_CONNECTION_CONNECTED)
|
||||
{
|
||||
netplay_command(netplay, connection, NETPLAY_CMD_FLIP_PLAYERS,
|
||||
&flip_frame_net, sizeof flip_frame_net, "flip users",
|
||||
"Successfully flipped users.\n");
|
||||
}
|
||||
}
|
||||
|
||||
netplay->flip ^= true;
|
||||
netplay->flip_frame = flip_frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_frontend_paused
|
||||
* netplay_frontend_paused
|
||||
* @netplay : pointer to netplay object
|
||||
* @paused : true if frontend is paused
|
||||
*
|
||||
@ -889,7 +963,7 @@ bool netplay_pre_frame(netplay_t *netplay)
|
||||
}
|
||||
|
||||
if (sync_stalled ||
|
||||
((!netplay->is_server || netplay->connected_players) &&
|
||||
((!netplay->is_server || (netplay->connected_players>1)) &&
|
||||
(netplay->stall || netplay->remote_paused)))
|
||||
{
|
||||
/* We may have received data even if we're stalled, so run post-frame
|
||||
@ -942,19 +1016,20 @@ static void netplay_force_future(netplay_t *netplay)
|
||||
netplay->run_ptr = netplay->self_ptr;
|
||||
netplay->run_frame_count = netplay->self_frame_count;
|
||||
|
||||
|
||||
/* We need to ignore any intervening data from the other side,
|
||||
* and never rewind past this */
|
||||
netplay_update_unread_ptr(netplay);
|
||||
if (netplay->unread_frame_count < netplay->run_frame_count)
|
||||
{
|
||||
uint32_t player;
|
||||
for (player = 0; player < MAX_USERS; player++)
|
||||
uint32_t client;
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(netplay->connected_players & (1<<player))) continue;
|
||||
if (netplay->read_frame_count[player] < netplay->run_frame_count)
|
||||
if (!(netplay->connected_players & (1<<client))) continue;
|
||||
if (netplay->read_frame_count[client] < netplay->run_frame_count)
|
||||
{
|
||||
netplay->read_ptr[player] = netplay->run_ptr;
|
||||
netplay->read_frame_count[player] = netplay->run_frame_count;
|
||||
netplay->read_ptr[client] = netplay->run_ptr;
|
||||
netplay->read_frame_count[client] = netplay->run_frame_count;
|
||||
}
|
||||
}
|
||||
if (netplay->server_frame_count < netplay->run_frame_count)
|
||||
@ -1121,6 +1196,49 @@ static void netplay_core_reset(netplay_t *netplay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_settings_share_mode
|
||||
*
|
||||
* Get the preferred share mode
|
||||
*/
|
||||
uint8_t netplay_settings_share_mode(void)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
uint8_t share_mode = 0;
|
||||
|
||||
if (settings->uints.netplay_share_digital
|
||||
|| settings->uints.netplay_share_analog)
|
||||
{
|
||||
switch (settings->uints.netplay_share_digital)
|
||||
{
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_OR:
|
||||
share_mode |= NETPLAY_SHARE_DIGITAL_OR;
|
||||
break;
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_XOR:
|
||||
share_mode |= NETPLAY_SHARE_DIGITAL_XOR;
|
||||
break;
|
||||
case RARCH_NETPLAY_SHARE_DIGITAL_VOTE:
|
||||
share_mode |= NETPLAY_SHARE_DIGITAL_VOTE;
|
||||
break;
|
||||
default:
|
||||
share_mode |= NETPLAY_SHARE_NO_PREFERENCE;
|
||||
}
|
||||
switch (settings->uints.netplay_share_analog)
|
||||
{
|
||||
case RARCH_NETPLAY_SHARE_ANALOG_MAX:
|
||||
share_mode |= NETPLAY_SHARE_ANALOG_MAX;
|
||||
break;
|
||||
case RARCH_NETPLAY_SHARE_ANALOG_AVERAGE:
|
||||
share_mode |= NETPLAY_SHARE_ANALOG_AVERAGE;
|
||||
break;
|
||||
default:
|
||||
share_mode |= NETPLAY_SHARE_NO_PREFERENCE;
|
||||
}
|
||||
}
|
||||
|
||||
return share_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_toggle_play_spectate
|
||||
*
|
||||
@ -1128,67 +1246,24 @@ static void netplay_core_reset(netplay_t *netplay)
|
||||
*/
|
||||
static void netplay_toggle_play_spectate(netplay_t *netplay)
|
||||
{
|
||||
if (netplay->is_server)
|
||||
size_t i;
|
||||
enum rarch_netplay_connection_mode mode;
|
||||
|
||||
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING ||
|
||||
netplay->self_mode == NETPLAY_CONNECTION_SLAVE)
|
||||
{
|
||||
/* FIXME: Duplication */
|
||||
uint32_t payload[2];
|
||||
char msg[512];
|
||||
const char *dmsg = NULL;
|
||||
payload[0] = htonl(netplay->self_frame_count);
|
||||
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING ||
|
||||
netplay->self_mode == NETPLAY_CONNECTION_SLAVE)
|
||||
{
|
||||
/* Mark us as no longer playing */
|
||||
payload[1] = htonl(netplay->self_player);
|
||||
netplay->self_mode = NETPLAY_CONNECTION_SPECTATING;
|
||||
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_YOU_HAVE_LEFT_THE_GAME);
|
||||
|
||||
}
|
||||
else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING)
|
||||
{
|
||||
uint32_t player;
|
||||
|
||||
/* Take a player number */
|
||||
for (player = 0; player < MAX_USERS; player++)
|
||||
if (!(netplay->connected_players & (1<<player))) break;
|
||||
if (player == MAX_USERS) return; /* Failure! */
|
||||
|
||||
payload[1] = htonl(NETPLAY_CMD_MODE_BIT_PLAYING | player);
|
||||
netplay->self_mode = NETPLAY_CONNECTION_PLAYING;
|
||||
netplay->self_player = player;
|
||||
|
||||
dmsg = msg;
|
||||
msg[sizeof(msg)-1] = '\0';
|
||||
snprintf(msg, sizeof(msg)-1, msg_hash_to_str(MSG_NETPLAY_YOU_HAVE_JOINED_AS_PLAYER_N), player+1);
|
||||
}
|
||||
|
||||
RARCH_LOG("[netplay] %s\n", dmsg);
|
||||
runloop_msg_queue_push(dmsg, 1, 180, false);
|
||||
|
||||
netplay_send_raw_cmd_all(netplay, NULL, NETPLAY_CMD_MODE, payload, sizeof(payload));
|
||||
|
||||
/* Switch to spectator mode immediately */
|
||||
netplay->self_mode = NETPLAY_CONNECTION_SPECTATING;
|
||||
mode = NETPLAY_CONNECTION_SPECTATING;
|
||||
}
|
||||
else
|
||||
else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING)
|
||||
{
|
||||
uint32_t cmd;
|
||||
|
||||
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING ||
|
||||
netplay->self_mode == NETPLAY_CONNECTION_SLAVE)
|
||||
{
|
||||
/* Switch to spectator mode immediately */
|
||||
netplay->self_mode = NETPLAY_CONNECTION_SPECTATING;
|
||||
cmd = NETPLAY_CMD_SPECTATE;
|
||||
}
|
||||
else if (netplay->self_mode == NETPLAY_CONNECTION_SPECTATING)
|
||||
{
|
||||
/* Switch only after getting permission */
|
||||
cmd = NETPLAY_CMD_PLAY;
|
||||
}
|
||||
else return;
|
||||
|
||||
netplay_send_raw_cmd_all(netplay, NULL, cmd, NULL, 0);
|
||||
/* Switch only after getting permission */
|
||||
mode = NETPLAY_CONNECTION_PLAYING;
|
||||
}
|
||||
else return;
|
||||
|
||||
netplay_cmd_mode(netplay, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1300,7 +1375,7 @@ bool init_netplay(void *direct_host, const char *server, unsigned port)
|
||||
if (netplay_data)
|
||||
{
|
||||
if (netplay_data->is_server && !settings->bools.netplay_start_as_spectator)
|
||||
netplay_data->self_mode = NETPLAY_CONNECTION_PLAYING;
|
||||
netplay_toggle_play_spectate(netplay_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1388,10 +1463,6 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data)
|
||||
case RARCH_NETPLAY_CTL_PRE_FRAME:
|
||||
ret = netplay_pre_frame(netplay_data);
|
||||
goto done;
|
||||
case RARCH_NETPLAY_CTL_FLIP_PLAYERS:
|
||||
if (netplay_data->is_server)
|
||||
netplay_flip_users(netplay_data);
|
||||
break;
|
||||
case RARCH_NETPLAY_CTL_GAME_WATCH:
|
||||
netplay_toggle_play_spectate(netplay_data);
|
||||
break;
|
||||
|
@ -35,12 +35,13 @@
|
||||
#include "../../content.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../version.h"
|
||||
#include "../../input/input_driver.h"
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#include "../../menu/widgets/menu_input_dialog.h"
|
||||
#endif
|
||||
|
||||
const uint32_t netplay_magic = 0x52414E50; /* RANP */
|
||||
|
||||
/* TODO/FIXME - replace netplay_log_connection with calls
|
||||
* to inet_ntop_compat and move runloop message queue pushing
|
||||
* outside */
|
||||
@ -203,13 +204,15 @@ static uint32_t simple_rand_uint32(void)
|
||||
bool netplay_handshake_init_send(netplay_t *netplay,
|
||||
struct netplay_connection *connection)
|
||||
{
|
||||
uint32_t header[4];
|
||||
uint32_t header[6];
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
header[0] = htonl(netplay_impl_magic());
|
||||
header[0] = htonl(netplay_magic);
|
||||
header[1] = htonl(netplay_platform_magic());
|
||||
header[2] = htonl(NETPLAY_COMPRESSION_SUPPORTED);
|
||||
header[3] = 0;
|
||||
header[4] = htonl(NETPLAY_PROTOCOL_VERSION);
|
||||
header[5] = htonl(netplay_impl_magic());
|
||||
|
||||
if (netplay->is_server &&
|
||||
(settings->paths.netplay_password[0] ||
|
||||
@ -303,30 +306,49 @@ bool netplay_handshake_init(netplay_t *netplay,
|
||||
{
|
||||
ssize_t recvd;
|
||||
struct nick_buf_s nick_buf;
|
||||
uint32_t header[4];
|
||||
uint32_t header[6];
|
||||
uint32_t local_pmagic = 0;
|
||||
uint32_t remote_pmagic = 0;
|
||||
uint32_t remote_version = 0;
|
||||
uint32_t compression = 0;
|
||||
struct compression_transcoder *ctrans = NULL;
|
||||
const char *dmsg = NULL;
|
||||
|
||||
header[0] = 0;
|
||||
header[1] = 0;
|
||||
header[2] = 0;
|
||||
header[3] = 0;
|
||||
memset(header, 0, sizeof(header));
|
||||
|
||||
RECV(header, sizeof(header))
|
||||
RECV(header, sizeof(uint32_t))
|
||||
{
|
||||
dmsg = msg_hash_to_str(MSG_FAILED_TO_RECEIVE_HEADER_FROM_CLIENT);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (netplay_impl_magic() != ntohl(header[0]))
|
||||
if (ntohl(header[0]) != netplay_magic)
|
||||
{
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_IMPLEMENTATIONS_DIFFER);
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_NOT_RETROARCH);
|
||||
goto error;
|
||||
}
|
||||
|
||||
RECV(header + 1, sizeof(header) - sizeof(uint32_t))
|
||||
{
|
||||
dmsg = msg_hash_to_str(MSG_FAILED_TO_RECEIVE_HEADER_FROM_CLIENT);
|
||||
goto error;
|
||||
}
|
||||
|
||||
remote_version = ntohl(header[4]);
|
||||
if (remote_version < NETPLAY_PROTOCOL_VERSION)
|
||||
{
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_OUT_OF_DATE);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ntohl(header[5]) != netplay_impl_magic())
|
||||
{
|
||||
/* We allow the connection but warn that this could cause issues. */
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_VERSIONS);
|
||||
RARCH_WARN("%s\n", dmsg);
|
||||
runloop_msg_queue_push(dmsg, 1, 180, false);
|
||||
}
|
||||
|
||||
/* We only care about platform magic if our core is quirky */
|
||||
local_pmagic = netplay_platform_magic();
|
||||
remote_pmagic = ntohl(header[1]);
|
||||
@ -529,10 +551,10 @@ bool netplay_handshake_sync(netplay_t *netplay,
|
||||
/* If we're the server, now we send sync info */
|
||||
size_t i;
|
||||
int matchct;
|
||||
uint32_t cmd[5];
|
||||
uint32_t cmd[4];
|
||||
retro_ctx_memory_info_t mem_info;
|
||||
uint32_t client_num = 0;
|
||||
uint32_t device = 0;
|
||||
uint32_t connected_players = 0;
|
||||
size_t nicklen, nickmangle = 0;
|
||||
bool nick_matched = false;
|
||||
|
||||
@ -543,30 +565,51 @@ bool netplay_handshake_sync(netplay_t *netplay,
|
||||
|
||||
/* Send basic sync info */
|
||||
cmd[0] = htonl(NETPLAY_CMD_SYNC);
|
||||
cmd[1] = htonl(3*sizeof(uint32_t) + MAX_USERS*sizeof(uint32_t) +
|
||||
NETPLAY_NICK_LEN + mem_info.size);
|
||||
cmd[1] = htonl(2*sizeof(uint32_t)
|
||||
/* Controller devices */
|
||||
+ MAX_INPUT_DEVICES*sizeof(uint32_t)
|
||||
|
||||
/* Share modes */
|
||||
+ MAX_INPUT_DEVICES*sizeof(uint8_t)
|
||||
|
||||
/* Device-client mapping */
|
||||
+ MAX_INPUT_DEVICES*sizeof(uint32_t)
|
||||
|
||||
/* Client nick */
|
||||
+ NETPLAY_NICK_LEN
|
||||
|
||||
/* And finally, sram */
|
||||
+ mem_info.size);
|
||||
cmd[2] = htonl(netplay->self_frame_count);
|
||||
connected_players = netplay->connected_players;
|
||||
if (netplay->self_mode == NETPLAY_CONNECTION_PLAYING)
|
||||
connected_players |= 1<<netplay->self_player;
|
||||
client_num = connection - netplay->connections + 1;
|
||||
if (netplay->local_paused || netplay->remote_paused)
|
||||
connected_players |= NETPLAY_CMD_SYNC_BIT_PAUSED;
|
||||
cmd[3] = htonl(connected_players);
|
||||
if (netplay->flip)
|
||||
cmd[4] = htonl(netplay->flip_frame);
|
||||
else
|
||||
cmd[4] = htonl(0);
|
||||
client_num |= NETPLAY_CMD_SYNC_BIT_PAUSED;
|
||||
cmd[3] = htonl(client_num);
|
||||
|
||||
if (!netplay_send(&connection->send_packet_buffer, connection->fd, cmd,
|
||||
sizeof(cmd)))
|
||||
return false;
|
||||
|
||||
/* Now send the device info */
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
device = htonl(input_config_get_device((unsigned)i));
|
||||
device = htonl(netplay->config_devices[i]);
|
||||
if (!netplay_send(&connection->send_packet_buffer, connection->fd,
|
||||
&device, sizeof(device)))
|
||||
&device, sizeof(device)))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Then the share mode */
|
||||
if (!netplay_send(&connection->send_packet_buffer, connection->fd,
|
||||
netplay->device_share_modes, sizeof(netplay->device_share_modes)))
|
||||
return false;
|
||||
|
||||
/* Then the device-client mapping */
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
device = htonl(netplay->device_clients[i]);
|
||||
if (!netplay_send(&connection->send_packet_buffer, connection->fd,
|
||||
&device, sizeof(device)))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -835,12 +878,21 @@ bool netplay_handshake_pre_info(netplay_t *netplay,
|
||||
if (core_info)
|
||||
{
|
||||
if (strncmp(info_buf.core_name,
|
||||
core_info->info.library_name, sizeof(info_buf.core_name)) ||
|
||||
strncmp(info_buf.core_version,
|
||||
core_info->info.library_name, sizeof(info_buf.core_name)))
|
||||
{
|
||||
/* Wrong core! */
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_CORES);
|
||||
RARCH_ERR("%s\n", dmsg);
|
||||
runloop_msg_queue_push(dmsg, 1, 180, false);
|
||||
/* FIXME: Should still send INFO, so the other side knows what's what */
|
||||
return false;
|
||||
}
|
||||
if (strncmp(info_buf.core_version,
|
||||
core_info->info.library_version, sizeof(info_buf.core_version)))
|
||||
{
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_IMPLEMENTATIONS_DIFFER);
|
||||
goto error;
|
||||
dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_CORE_VERSIONS);
|
||||
RARCH_WARN("%s\n", dmsg);
|
||||
runloop_msg_queue_push(dmsg, 1, 180, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -852,7 +904,8 @@ bool netplay_handshake_pre_info(netplay_t *netplay,
|
||||
if (ntohl(info_buf.content_crc) != content_crc)
|
||||
{
|
||||
dmsg = msg_hash_to_str(MSG_CONTENT_CRC32S_DIFFER);
|
||||
goto error;
|
||||
RARCH_WARN("%s\n", dmsg);
|
||||
runloop_msg_queue_push(dmsg, 1, 180, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -873,24 +926,8 @@ bool netplay_handshake_pre_info(netplay_t *netplay,
|
||||
*had_input = true;
|
||||
netplay_recv_flush(&connection->recv_packet_buffer);
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (dmsg)
|
||||
{
|
||||
RARCH_ERR("%s\n", dmsg);
|
||||
runloop_msg_queue_push(dmsg, 1, 180, false);
|
||||
}
|
||||
|
||||
if (!netplay->is_server)
|
||||
{
|
||||
/* Counter-intuitively, we still want to send our info. This is simply so
|
||||
* that the server knows why we disconnected. */
|
||||
if (!netplay_handshake_info(netplay, connection))
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_handshake_pre_sync
|
||||
*
|
||||
@ -901,10 +938,10 @@ bool netplay_handshake_pre_sync(netplay_t *netplay,
|
||||
struct netplay_connection *connection, bool *had_input)
|
||||
{
|
||||
uint32_t cmd[2];
|
||||
uint32_t new_frame_count, connected_players, flip_frame;
|
||||
uint32_t new_frame_count, client_num, flip_frame;
|
||||
uint32_t device;
|
||||
uint32_t local_sram_size, remote_sram_size;
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
ssize_t recvd;
|
||||
retro_ctx_controller_info_t pad;
|
||||
char new_nick[NETPLAY_NICK_LEN];
|
||||
@ -921,7 +958,7 @@ bool netplay_handshake_pre_sync(netplay_t *netplay,
|
||||
|
||||
/* Only expecting a sync command */
|
||||
if (ntohl(cmd[0]) != NETPLAY_CMD_SYNC ||
|
||||
ntohl(cmd[1]) < 3*sizeof(uint32_t) + MAX_USERS*sizeof(uint32_t) +
|
||||
ntohl(cmd[1]) < (2+2*MAX_INPUT_DEVICES)*sizeof(uint32_t) + (MAX_INPUT_DEVICES)*sizeof(uint8_t) +
|
||||
NETPLAY_NICK_LEN)
|
||||
{
|
||||
RARCH_ERR("%s\n",
|
||||
@ -934,30 +971,23 @@ bool netplay_handshake_pre_sync(netplay_t *netplay,
|
||||
return false;
|
||||
new_frame_count = ntohl(new_frame_count);
|
||||
|
||||
/* Get the connected players and pause mode */
|
||||
RECV(&connected_players, sizeof(connected_players))
|
||||
/* Get our client number and pause mode */
|
||||
RECV(&client_num, sizeof(client_num))
|
||||
return false;
|
||||
connected_players = ntohl(connected_players);
|
||||
if (connected_players & NETPLAY_CMD_SYNC_BIT_PAUSED)
|
||||
client_num = ntohl(client_num);
|
||||
if (client_num & NETPLAY_CMD_SYNC_BIT_PAUSED)
|
||||
{
|
||||
netplay->remote_paused = true;
|
||||
connected_players ^= NETPLAY_CMD_SYNC_BIT_PAUSED;
|
||||
client_num ^= NETPLAY_CMD_SYNC_BIT_PAUSED;
|
||||
}
|
||||
netplay->connected_players = connected_players;
|
||||
|
||||
/* And the flip state */
|
||||
RECV(&flip_frame, sizeof(flip_frame))
|
||||
return false;
|
||||
|
||||
flip_frame = ntohl(flip_frame);
|
||||
netplay->flip = !!flip_frame;
|
||||
netplay->flip_frame = flip_frame;
|
||||
netplay->self_client_num = client_num;
|
||||
|
||||
/* Set our frame counters as requested */
|
||||
netplay->self_frame_count = netplay->run_frame_count =
|
||||
netplay->other_frame_count = netplay->unread_frame_count =
|
||||
netplay->server_frame_count = new_frame_count;
|
||||
|
||||
/* And clear out the framebuffer */
|
||||
for (i = 0; i < netplay->buffer_size; i++)
|
||||
{
|
||||
struct delta_frame *ptr = &netplay->buffer[i];
|
||||
@ -977,27 +1007,55 @@ bool netplay_handshake_pre_sync(netplay_t *netplay,
|
||||
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (connected_players & (1<<i))
|
||||
{
|
||||
netplay->read_ptr[i] = netplay->self_ptr;
|
||||
netplay->read_frame_count[i] = netplay->self_frame_count;
|
||||
}
|
||||
netplay->read_ptr[i] = netplay->self_ptr;
|
||||
netplay->read_frame_count[i] = netplay->self_frame_count;
|
||||
}
|
||||
|
||||
/* Get and set each pad */
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
/* Get and set each input device */
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
RECV(&device, sizeof(device))
|
||||
return false;
|
||||
|
||||
pad.port = (unsigned)i;
|
||||
pad.device = ntohl(device);
|
||||
netplay->config_devices[i] = pad.device;
|
||||
if ((pad.device&RETRO_DEVICE_MASK) == RETRO_DEVICE_KEYBOARD)
|
||||
{
|
||||
netplay->have_updown_device = true;
|
||||
netplay_key_hton_init();
|
||||
}
|
||||
|
||||
core_set_controller_port_device(&pad);
|
||||
}
|
||||
|
||||
/* Get the share modes */
|
||||
RECV(netplay->device_share_modes, sizeof(netplay->device_share_modes))
|
||||
return false;
|
||||
|
||||
/* Get the client-controller mapping */
|
||||
netplay->connected_players =
|
||||
netplay->connected_slaves =
|
||||
netplay->self_devices = 0;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
netplay->client_devices[i] = 0;
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
RECV(&device, sizeof(device))
|
||||
return false;
|
||||
device = ntohl(device);
|
||||
|
||||
netplay->device_clients[i] = device;
|
||||
netplay->connected_players |= device;
|
||||
for (j = 0; j < MAX_CLIENTS; j++)
|
||||
{
|
||||
if (device & (1<<j))
|
||||
netplay->client_devices[j] |= 1<<i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get our nick */
|
||||
RECV(new_nick, NETPLAY_NICK_LEN)
|
||||
return false;
|
||||
@ -1018,8 +1076,8 @@ bool netplay_handshake_pre_sync(netplay_t *netplay,
|
||||
core_get_memory(&mem_info);
|
||||
|
||||
local_sram_size = (unsigned)mem_info.size;
|
||||
remote_sram_size = ntohl(cmd[1]) - 3*sizeof(uint32_t) -
|
||||
MAX_USERS*sizeof(uint32_t) - NETPLAY_NICK_LEN;
|
||||
remote_sram_size = ntohl(cmd[1]) -
|
||||
(2+2*MAX_INPUT_DEVICES)*sizeof(uint32_t) - (MAX_INPUT_DEVICES)*sizeof(uint8_t) - NETPLAY_NICK_LEN;
|
||||
|
||||
if (local_sram_size != 0 && local_sram_size == remote_sram_size)
|
||||
{
|
||||
@ -1063,7 +1121,7 @@ bool netplay_handshake_pre_sync(netplay_t *netplay,
|
||||
|
||||
/* Ask to switch to playing mode if we should */
|
||||
if (!settings->bools.netplay_start_as_spectator)
|
||||
return netplay_cmd_mode(netplay, connection, NETPLAY_CONNECTION_PLAYING);
|
||||
return netplay_cmd_mode(netplay, NETPLAY_CONNECTION_PLAYING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "../../autosave.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../input/input_driver.h"
|
||||
|
||||
#if defined(AF_INET6) && !defined(HAVE_SOCKET_LEGACY)
|
||||
#define HAVE_INET6 1
|
||||
@ -183,12 +184,8 @@ static bool init_tcp_socket(netplay_t *netplay, void *direct_host,
|
||||
|
||||
while (tmp_info)
|
||||
{
|
||||
struct sockaddr_storage sad;
|
||||
int fd;
|
||||
|
||||
memset(&sad, 0, sizeof(sad));
|
||||
|
||||
fd = init_tcp_connection(
|
||||
struct sockaddr_storage sad = {0};
|
||||
int fd = init_tcp_connection(
|
||||
tmp_info,
|
||||
direct_host || server,
|
||||
(struct sockaddr*)&sad,
|
||||
@ -243,7 +240,7 @@ static bool netplay_init_socket_buffers(netplay_t *netplay)
|
||||
* frames of input data, plus the headers for each of them */
|
||||
size_t i;
|
||||
size_t packet_buffer_size = netplay->zbuffer_size +
|
||||
NETPLAY_MAX_STALL_FRAMES * WORDS_PER_FRAME + (NETPLAY_MAX_STALL_FRAMES+1)*3;
|
||||
NETPLAY_MAX_STALL_FRAMES * 16;
|
||||
netplay->packet_buffer_size = packet_buffer_size;
|
||||
|
||||
for (i = 0; i < netplay->connections_size; i++)
|
||||
@ -430,8 +427,6 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port,
|
||||
netplay->listen_fd = -1;
|
||||
netplay->tcp_port = port;
|
||||
netplay->cbs = *cb;
|
||||
netplay->connected_players = 0;
|
||||
netplay->player_max = 1;
|
||||
netplay->is_server = (direct_host == NULL && server == NULL);
|
||||
netplay->is_connected = false;;
|
||||
netplay->nat_traversal = netplay->is_server ? nat_traversal : false;
|
||||
@ -472,8 +467,26 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!netplay->is_server)
|
||||
if (netplay->is_server)
|
||||
{
|
||||
/* Clients get device info from the server */
|
||||
unsigned i;
|
||||
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
uint32_t dtype = input_config_get_device(i);
|
||||
netplay->config_devices[i] = dtype;
|
||||
if ((dtype&RETRO_DEVICE_MASK) == RETRO_DEVICE_KEYBOARD)
|
||||
{
|
||||
netplay->have_updown_device = true;
|
||||
netplay_key_hton_init();
|
||||
}
|
||||
if (dtype != RETRO_DEVICE_NONE && !netplay_expected_input_size(netplay, 1<<i))
|
||||
RARCH_WARN("Netplay does not support input device %u\n", i+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start our handshake */
|
||||
netplay_handshake_init_send(netplay, &netplay->connections[0]);
|
||||
|
||||
netplay->connections[0].mode = NETPLAY_CONNECTION_INIT;
|
||||
@ -539,8 +552,7 @@ void netplay_free(netplay_t *netplay)
|
||||
if (netplay->buffer)
|
||||
{
|
||||
for (i = 0; i < netplay->buffer_size; i++)
|
||||
if (netplay->buffer[i].state)
|
||||
free(netplay->buffer[i].state);
|
||||
netplay_delta_frame_free(&netplay->buffer[i]);
|
||||
|
||||
free(netplay->buffer);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
53
network/netplay/netplay_keyboard.c
Normal file
53
network/netplay/netplay_keyboard.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
169
network/netplay/netplay_keys.h
Normal file
169
network/netplay/netplay_keys.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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)
|
@ -28,10 +28,7 @@
|
||||
#include "../../msg_hash.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
#define WORDS_PER_INPUT 3 /* Buttons, left stick, right stick */
|
||||
#define WORDS_PER_FRAME (WORDS_PER_INPUT+2) /* + frameno, playerno */
|
||||
|
||||
#define NETPLAY_PROTOCOL_VERSION 4
|
||||
#define NETPLAY_PROTOCOL_VERSION 5
|
||||
|
||||
#define RARCH_DEFAULT_PORT 55435
|
||||
#define RARCH_DEFAULT_NICK "Anonymous"
|
||||
@ -45,6 +42,15 @@
|
||||
#define CATCH_UP_CHECK_TIME_USEC (500*1000)
|
||||
#define MAX_RETRIES 16
|
||||
#define RETRY_MS 500
|
||||
#define MAX_INPUT_DEVICES 16
|
||||
|
||||
/* We allow only 32 clients to fit into a 32-bit bitmap */
|
||||
#define MAX_CLIENTS 32
|
||||
typedef uint32_t client_bitmap_t;
|
||||
|
||||
/* Because the callback keyboard reverses some assumptions, when the keyboard
|
||||
* callbacks are in use, we assign a pseudodevice for it */
|
||||
#define RETRO_DEVICE_NETPLAY_KEYBOARD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_KEYBOARD, 65535)
|
||||
|
||||
#define NETPLAY_MAX_STALL_FRAMES 60
|
||||
#define NETPLAY_FRAME_RUN_TIME_WINDOW 120
|
||||
@ -89,6 +95,13 @@
|
||||
#define NETPLAY_COMPRESSION_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
/* Positional snprintf */
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf_p _snprintf_p
|
||||
#else /* sensible systems */
|
||||
#define snprintf_p snprintf
|
||||
#endif
|
||||
|
||||
enum netplay_cmd
|
||||
{
|
||||
/* Basic commands */
|
||||
@ -162,9 +175,6 @@ enum netplay_cmd
|
||||
|
||||
/* Misc. commands */
|
||||
|
||||
/* Swap inputs between player 1 and player 2 */
|
||||
NETPLAY_CMD_FLIP_PLAYERS = 0x0060,
|
||||
|
||||
/* Sends multiple config requests over,
|
||||
* See enum netplay_cmd_cfg */
|
||||
NETPLAY_CMD_CFG = 0x0061,
|
||||
@ -175,12 +185,11 @@ enum netplay_cmd
|
||||
NETPLAY_CMD_CFG_ACK = 0x0062
|
||||
};
|
||||
|
||||
#define NETPLAY_CMD_INPUT_BIT_SERVER (1U<<31)
|
||||
#define NETPLAY_CMD_SYNC_BIT_PAUSED (1U<<31)
|
||||
#define NETPLAY_CMD_PLAY_BIT_SLAVE (1U)
|
||||
#define NETPLAY_CMD_MODE_BIT_SLAVE (1U<<18)
|
||||
#define NETPLAY_CMD_MODE_BIT_PLAYING (1U<<17)
|
||||
#define NETPLAY_CMD_MODE_BIT_YOU (1U<<16)
|
||||
#define NETPLAY_CMD_PLAY_BIT_SLAVE (1U<<31)
|
||||
#define NETPLAY_CMD_MODE_BIT_YOU (1U<<31)
|
||||
#define NETPLAY_CMD_MODE_BIT_PLAYING (1U<<30)
|
||||
#define NETPLAY_CMD_MODE_BIT_SLAVE (1U<<29)
|
||||
|
||||
/* These are the reasons given for mode changes to be rejected */
|
||||
enum netplay_cmd_mode_reasons
|
||||
@ -195,9 +204,35 @@ enum netplay_cmd_mode_reasons
|
||||
NETPLAY_CMD_MODE_REFUSED_REASON_NO_SLOTS,
|
||||
|
||||
/* You're changing modes too fast */
|
||||
NETPLAY_CMD_MODE_REFUSED_REASON_TOO_FAST
|
||||
NETPLAY_CMD_MODE_REFUSED_REASON_TOO_FAST,
|
||||
|
||||
/* You requested a particular port but it's not available */
|
||||
NETPLAY_CMD_MODE_REFUSED_REASON_NOT_AVAILABLE
|
||||
};
|
||||
|
||||
/* Real preferences for sharing devices */
|
||||
enum rarch_netplay_share_preference
|
||||
{
|
||||
/* Prefer not to share, shouldn't be set as a sharing mode for an shared device */
|
||||
NETPLAY_SHARE_NO_SHARING = 0x0,
|
||||
|
||||
/* No preference. Only for requests. Set if sharing is requested but either
|
||||
* digital or analog doesn't have a preference. */
|
||||
NETPLAY_SHARE_NO_PREFERENCE = 0x1,
|
||||
|
||||
/* For digital devices */
|
||||
NETPLAY_SHARE_DIGITAL_BITS = 0x1C,
|
||||
NETPLAY_SHARE_DIGITAL_OR = 0x4,
|
||||
NETPLAY_SHARE_DIGITAL_XOR = 0x8,
|
||||
NETPLAY_SHARE_DIGITAL_VOTE = 0xC,
|
||||
|
||||
/* For analog devices */
|
||||
NETPLAY_SHARE_ANALOG_BITS = 0xE0,
|
||||
NETPLAY_SHARE_ANALOG_MAX = 0x20,
|
||||
NETPLAY_SHARE_ANALOG_AVERAGE = 0x40
|
||||
};
|
||||
|
||||
/* The current status of a connection */
|
||||
enum rarch_netplay_connection_mode
|
||||
{
|
||||
NETPLAY_CONNECTION_NONE = 0,
|
||||
@ -240,7 +275,24 @@ enum rarch_netplay_stall_reason
|
||||
NETPLAY_STALL_NO_CONNECTION
|
||||
};
|
||||
|
||||
typedef uint32_t netplay_input_state_t[WORDS_PER_INPUT];
|
||||
/* Input state for a particular client-device pair */
|
||||
typedef struct netplay_input_state
|
||||
{
|
||||
/* The next input state (forming a list) */
|
||||
struct netplay_input_state *next;
|
||||
|
||||
/* Is this a buffer with real data? */
|
||||
bool used;
|
||||
|
||||
/* Whose data is this? */
|
||||
uint32_t client_num;
|
||||
|
||||
/* How many words of input data do we have? */
|
||||
uint32_t size;
|
||||
|
||||
/* The input data itself (note: should expand beyond 1 by overallocating). */
|
||||
uint32_t data[1];
|
||||
} *netplay_input_state_t;
|
||||
|
||||
struct delta_frame
|
||||
{
|
||||
@ -253,20 +305,22 @@ struct delta_frame
|
||||
/* The CRC-32 of the serialized state if we've calculated it, else 0 */
|
||||
uint32_t crc;
|
||||
|
||||
/* The real, simulated and local input. If we're playing, self_state is
|
||||
* mirrored to the appropriate real_input_state player. */
|
||||
netplay_input_state_t real_input_state[MAX_USERS];
|
||||
netplay_input_state_t simulated_input_state[MAX_USERS];
|
||||
netplay_input_state_t self_state;
|
||||
/* The resolved input, i.e., what's actually going to the core. One input
|
||||
* per device. */
|
||||
netplay_input_state_t resolved_input[MAX_INPUT_DEVICES];
|
||||
|
||||
/* The real input */
|
||||
netplay_input_state_t real_input[MAX_INPUT_DEVICES];
|
||||
|
||||
/* The simulated input. is_real here means the simulation is done, i.e.,
|
||||
* it's a real simulation, not real input. */
|
||||
netplay_input_state_t simlated_input[MAX_INPUT_DEVICES];
|
||||
|
||||
/* Have we read local input? */
|
||||
bool have_local;
|
||||
|
||||
/* Have we read the real (remote) input? */
|
||||
bool have_real[MAX_USERS];
|
||||
|
||||
/* Is the current state as of self_frame_count using the real (remote) data? */
|
||||
bool used_real[MAX_USERS];
|
||||
bool have_real[MAX_CLIENTS];
|
||||
};
|
||||
|
||||
struct socket_buffer
|
||||
@ -309,9 +363,6 @@ struct netplay_connection
|
||||
* to wait for, or 0 if no delay is active. */
|
||||
uint32_t delay_frame;
|
||||
|
||||
/* Player # of connected player */
|
||||
uint32_t player;
|
||||
|
||||
/* What compression does this peer support? */
|
||||
uint32_t compression_supported;
|
||||
|
||||
@ -350,8 +401,8 @@ struct netplay
|
||||
/* TCP connection for listening (server only) */
|
||||
int listen_fd;
|
||||
|
||||
/* Our player number */
|
||||
uint32_t self_player;
|
||||
/* Our client number */
|
||||
uint32_t self_client_num;
|
||||
|
||||
/* Our mode and status */
|
||||
enum rarch_netplay_connection_mode self_mode;
|
||||
@ -361,19 +412,39 @@ struct netplay
|
||||
size_t connections_size;
|
||||
struct netplay_connection one_connection; /* Client only */
|
||||
|
||||
/* Bitmap of players with controllers (low bit is player 1) */
|
||||
/* Bitmap of clients with input devices */
|
||||
uint32_t connected_players;
|
||||
|
||||
/* Bitmap of players playing in slave mode (should be a subset of
|
||||
/* Bitmap of clients playing in slave mode (should be a subset of
|
||||
* connected_players) */
|
||||
uint32_t connected_slaves;
|
||||
|
||||
/* For each client, the bitmap of devices they're connected to */
|
||||
uint32_t client_devices[MAX_CLIENTS];
|
||||
|
||||
/* For each device, the bitmap of clients connected */
|
||||
client_bitmap_t device_clients[MAX_INPUT_DEVICES];
|
||||
|
||||
/* The sharing mode for each device */
|
||||
uint8_t device_share_modes[MAX_INPUT_DEVICES];
|
||||
|
||||
/* Our own device bitmap */
|
||||
uint32_t self_devices;
|
||||
|
||||
/* Number of desync operations we're currently performing. If set, we don't
|
||||
* attempt to stay in sync. */
|
||||
uint32_t desync;
|
||||
|
||||
/* Maximum player number */
|
||||
uint32_t player_max;
|
||||
/* The device types for every connected device. We store them and ignore any
|
||||
* menu changes, as netplay needs fixed devices. */
|
||||
uint32_t config_devices[MAX_INPUT_DEVICES];
|
||||
|
||||
/* Set to true if we have a device that most cores translate to "up/down"
|
||||
* actions, typically a keyboard. We need to keep track of this because with
|
||||
* such a device, we need to "fix" the input state to the frame BEFORE a
|
||||
* state load, then perform the state load, and the up/down states will
|
||||
* proceed as expected */
|
||||
bool have_updown_device;
|
||||
|
||||
struct retro_callbacks cbs;
|
||||
|
||||
@ -418,9 +489,9 @@ struct netplay
|
||||
size_t unread_ptr;
|
||||
uint32_t unread_frame_count;
|
||||
|
||||
/* Pointer to the next frame to read from each player */
|
||||
size_t read_ptr[MAX_USERS];
|
||||
uint32_t read_frame_count[MAX_USERS];
|
||||
/* Pointer to the next frame to read from each client */
|
||||
size_t read_ptr[MAX_CLIENTS];
|
||||
uint32_t read_frame_count[MAX_CLIENTS];
|
||||
|
||||
/* Pointer to the next frame to read from the server (as it might not be a
|
||||
* player but still synchronizes) */
|
||||
@ -441,7 +512,7 @@ struct netplay
|
||||
bool can_poll;
|
||||
|
||||
/* Force a rewind to other_frame_count/other_ptr. This is for synchronized
|
||||
* events, such as player flipping or savestate loading. */
|
||||
* events, such as restarting or savestate loading. */
|
||||
bool force_rewind;
|
||||
|
||||
/* Force a reset */
|
||||
@ -456,21 +527,12 @@ struct netplay
|
||||
/* Have we requested a savestate as a sync point? */
|
||||
bool savestate_request_outstanding;
|
||||
|
||||
/* A buffer for outgoing input packets. */
|
||||
uint32_t input_packet_buffer[2 + WORDS_PER_FRAME];
|
||||
|
||||
/* Our local socket info */
|
||||
struct addrinfo *addr;
|
||||
|
||||
/* Counter for timeouts */
|
||||
unsigned timeout_cnt;
|
||||
|
||||
/* User flipping
|
||||
* Flipping state. If frame >= flip_frame, we apply the flip.
|
||||
* If not, we apply the opposite, effectively creating a trigger point. */
|
||||
bool flip;
|
||||
uint32_t flip_frame;
|
||||
|
||||
/* Netplay pausing */
|
||||
bool local_paused;
|
||||
bool remote_paused;
|
||||
@ -608,6 +670,28 @@ bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta,
|
||||
*/
|
||||
uint32_t netplay_delta_frame_crc(netplay_t *netplay, struct delta_frame *delta);
|
||||
|
||||
/**
|
||||
* netplay_delta_frame_free
|
||||
*
|
||||
* Free a delta frame's dependencies
|
||||
*/
|
||||
void netplay_delta_frame_free(struct delta_frame *delta);
|
||||
|
||||
/**
|
||||
* netplay_input_state_for
|
||||
*
|
||||
* Get an input state for a particular client
|
||||
*/
|
||||
netplay_input_state_t netplay_input_state_for(netplay_input_state_t *list,
|
||||
uint32_t client_num, size_t size, bool must_create, bool must_not_create);
|
||||
|
||||
/**
|
||||
* netplay_expected_input_size
|
||||
*
|
||||
* Size in words for a given set of devices.
|
||||
*/
|
||||
uint32_t netplay_expected_input_size(netplay_t *netplay, uint32_t devices);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* NETPLAY-DISCOVERY.C
|
||||
@ -638,6 +722,13 @@ bool netplay_lan_ad_server(netplay_t *netplay);
|
||||
void netplay_load_savestate(netplay_t *netplay,
|
||||
retro_ctx_serialize_info_t *serial_info, bool save);
|
||||
|
||||
/**
|
||||
* netplay_settings_share_mode
|
||||
*
|
||||
* Get the preferred share mode
|
||||
*/
|
||||
uint8_t netplay_settings_share_mode(void);
|
||||
|
||||
/**
|
||||
* input_poll_net
|
||||
*
|
||||
@ -787,10 +878,10 @@ bool netplay_cmd_request_savestate(netplay_t *netplay);
|
||||
/**
|
||||
* netplay_cmd_mode
|
||||
*
|
||||
* Send a mode request command to either play or spectate.
|
||||
* Send a mode change request. As a server, the request is to ourself, and so
|
||||
* honored instantly.
|
||||
*/
|
||||
bool netplay_cmd_mode(netplay_t *netplay,
|
||||
struct netplay_connection *connection,
|
||||
enum rarch_netplay_connection_mode mode);
|
||||
|
||||
/**
|
||||
@ -816,13 +907,6 @@ int netplay_poll_net_input(netplay_t *netplay, bool block);
|
||||
*/
|
||||
void netplay_handle_slaves(netplay_t *netplay);
|
||||
|
||||
/**
|
||||
* netplay_flip_port
|
||||
*
|
||||
* Should we flip ports 0 and 1?
|
||||
*/
|
||||
bool netplay_flip_port(netplay_t *netplay);
|
||||
|
||||
/**
|
||||
* netplay_announce_nat_traversal
|
||||
*
|
||||
@ -838,6 +922,33 @@ void netplay_announce_nat_traversal(netplay_t *netplay);
|
||||
void netplay_init_nat_traversal(netplay_t *netplay);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* NETPLAY-KEYBOARD.C
|
||||
**************************************************************/
|
||||
|
||||
/* The keys supported by netplay */
|
||||
enum netplay_keys {
|
||||
NETPLAY_KEY_UNKNOWN = 0,
|
||||
#define K(k) NETPLAY_KEY_ ## k,
|
||||
#define KL(k,l) K(k)
|
||||
#include "netplay_keys.h"
|
||||
#undef KL
|
||||
#undef K
|
||||
NETPLAY_KEY_LAST
|
||||
};
|
||||
|
||||
/* The mapping of keys from netplay (network) to libretro (host) */
|
||||
extern const uint16_t netplay_key_ntoh_mapping[];
|
||||
#define netplay_key_ntoh(k) (netplay_key_ntoh_mapping[k])
|
||||
|
||||
/* The mapping of keys from libretro (host) to netplay (network) */
|
||||
uint32_t netplay_key_hton(unsigned key);
|
||||
|
||||
/* Because the hton keymapping has to be generated, call this before using
|
||||
* netplay_key_hton */
|
||||
void netplay_key_hton_init(void);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
* NETPLAY-SYNC.C
|
||||
**************************************************************/
|
||||
@ -851,15 +962,17 @@ void netplay_init_nat_traversal(netplay_t *netplay);
|
||||
void netplay_update_unread_ptr(netplay_t *netplay);
|
||||
|
||||
/**
|
||||
* netplay_simulate_input
|
||||
* netplay_resolve_input
|
||||
* @netplay : pointer to netplay object
|
||||
* @sim_ptr : frame index for which to simulate input
|
||||
* @sim_ptr : frame pointer for which to resolve input
|
||||
* @resim : are we resimulating, or simulating this frame for the
|
||||
* first time?
|
||||
*
|
||||
* "Simulate" input by assuming it hasn't changed since the last read input.
|
||||
* Returns true if the resolved input changed from the last time it was
|
||||
* resolved.
|
||||
*/
|
||||
void netplay_simulate_input(netplay_t *netplay, size_t sim_ptr, bool resim);
|
||||
bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim);
|
||||
|
||||
/**
|
||||
* netplay_sync_pre_frame
|
||||
|
@ -39,7 +39,7 @@
|
||||
*/
|
||||
void netplay_update_unread_ptr(netplay_t *netplay)
|
||||
{
|
||||
if (netplay->is_server && !netplay->connected_players)
|
||||
if (netplay->is_server && netplay->connected_players<=1)
|
||||
{
|
||||
/* Nothing at all to read! */
|
||||
netplay->unread_ptr = netplay->self_ptr;
|
||||
@ -50,16 +50,16 @@ void netplay_update_unread_ptr(netplay_t *netplay)
|
||||
{
|
||||
size_t new_unread_ptr = 0;
|
||||
uint32_t new_unread_frame_count = (uint32_t) -1;
|
||||
uint32_t player;
|
||||
uint32_t client;
|
||||
|
||||
for (player = 0; player < MAX_USERS; player++)
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(netplay->connected_players & (1<<player))) continue;
|
||||
if ((netplay->connected_slaves & (1<<player))) continue;
|
||||
if (netplay->read_frame_count[player] < new_unread_frame_count)
|
||||
if (!(netplay->connected_players & (1<<client))) continue;
|
||||
if ((netplay->connected_slaves & (1<<client))) continue;
|
||||
if (netplay->read_frame_count[client] < new_unread_frame_count)
|
||||
{
|
||||
new_unread_ptr = netplay->read_ptr[player];
|
||||
new_unread_frame_count = netplay->read_frame_count[player];
|
||||
new_unread_ptr = netplay->read_ptr[client];
|
||||
new_unread_frame_count = netplay->read_frame_count[client];
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,63 +82,373 @@ void netplay_update_unread_ptr(netplay_t *netplay)
|
||||
}
|
||||
}
|
||||
|
||||
struct vote_count {
|
||||
uint16_t votes[32];
|
||||
};
|
||||
|
||||
/**
|
||||
* netplay_simulate_input
|
||||
* netplay_device_client_state
|
||||
* @netplay : pointer to netplay object
|
||||
* @sim_ptr : frame index for which to simulate input
|
||||
* @simframe : frame in which merging is being performed
|
||||
* @device : device being merged
|
||||
* @client : client to find state for
|
||||
*/
|
||||
netplay_input_state_t netplay_device_client_state(netplay_t *netplay,
|
||||
struct delta_frame *simframe, uint32_t device, uint32_t client)
|
||||
{
|
||||
uint32_t dsize = netplay_expected_input_size(netplay, 1 << device);
|
||||
netplay_input_state_t simstate =
|
||||
netplay_input_state_for(
|
||||
&simframe->real_input[device], client,
|
||||
dsize, false, true);
|
||||
if (!simstate)
|
||||
{
|
||||
if (netplay->read_frame_count[client] > simframe->frame)
|
||||
return NULL;
|
||||
simstate = netplay_input_state_for(&simframe->simlated_input[device],
|
||||
client, dsize, false, true);
|
||||
}
|
||||
return simstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_merge_digital
|
||||
* @netplay : pointer to netplay object
|
||||
* @resstate : state being resolved
|
||||
* @simframe : frame in which merging is being performed
|
||||
* @device : device being merged
|
||||
* @clients : bitmap of clients being merged
|
||||
* @digital : bitmap of digital bits
|
||||
*/
|
||||
static void netplay_merge_digital(netplay_t *netplay,
|
||||
netplay_input_state_t resstate, struct delta_frame *simframe,
|
||||
uint32_t device, uint32_t clients, const uint32_t *digital)
|
||||
{
|
||||
netplay_input_state_t simstate;
|
||||
uint32_t word, bit, client;
|
||||
uint8_t share_mode = netplay->device_share_modes[device] & NETPLAY_SHARE_DIGITAL_BITS;
|
||||
|
||||
/* Make sure all real clients are accounted for */
|
||||
for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next)
|
||||
{
|
||||
if (!simstate->used || simstate->size != resstate->size) continue;
|
||||
clients |= 1<<simstate->client_num;
|
||||
}
|
||||
|
||||
if (share_mode == NETPLAY_SHARE_DIGITAL_VOTE)
|
||||
{
|
||||
/* Vote mode requires counting all the bits */
|
||||
uint32_t client_count = 0;
|
||||
|
||||
/* This just assumes we have no more than three words, will need to be adjusted for new devices */
|
||||
struct vote_count votes[3] = {0};
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(clients & (1<<client))) continue;
|
||||
simstate = netplay_device_client_state(netplay, simframe, device, client);
|
||||
if (!simstate) continue;
|
||||
client_count++;
|
||||
|
||||
for (word = 0; word < resstate->size; word++)
|
||||
{
|
||||
if (!digital[word]) continue;
|
||||
for (bit = 0; bit < 32; bit++)
|
||||
{
|
||||
if (!(digital[word] & (1<<bit))) continue;
|
||||
if (simstate->data[word] & (1<<bit))
|
||||
votes[word].votes[bit]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now count all the bits */
|
||||
client_count /= 2;
|
||||
for (word = 0; word < resstate->size; word++)
|
||||
{
|
||||
for (bit = 0; bit < 32; bit++)
|
||||
{
|
||||
if (votes[word].votes[bit] > client_count)
|
||||
resstate->data[word] |= (1<<bit);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else /* !VOTE */
|
||||
{
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(clients & (1<<client))) continue;
|
||||
simstate = netplay_device_client_state(netplay, simframe, device, client);
|
||||
if (!simstate) continue;
|
||||
for (word = 0; word < resstate->size; word++)
|
||||
{
|
||||
uint32_t part;
|
||||
if (!digital[word]) continue;
|
||||
part = simstate->data[word];
|
||||
if (digital[word] == (uint32_t) -1)
|
||||
{
|
||||
/* Combine the whole word */
|
||||
switch (share_mode)
|
||||
{
|
||||
case NETPLAY_SHARE_DIGITAL_XOR: resstate->data[word] ^= part; break;
|
||||
default: resstate->data[word] |= part;
|
||||
}
|
||||
|
||||
}
|
||||
else /* !whole word */
|
||||
{
|
||||
for (bit = 0; bit < 32; bit++)
|
||||
{
|
||||
if (!(digital[word] & (1<<bit))) continue;
|
||||
switch (share_mode)
|
||||
{
|
||||
case NETPLAY_SHARE_DIGITAL_XOR: resstate->data[word] ^= part & (1<<bit); break;
|
||||
default: resstate->data[word] |= part & (1<<bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* merge_analog_part
|
||||
* @netplay : pointer to netplay object
|
||||
* @resstate : state being resolved
|
||||
* @simframe : frame in which merging is being performed
|
||||
* @device : device being merged
|
||||
* @clients : bitmap of clients being merged
|
||||
* @word : word to merge
|
||||
* @bit : first bit to merge
|
||||
*/
|
||||
static void merge_analog_part(netplay_t *netplay,
|
||||
netplay_input_state_t resstate, struct delta_frame *simframe,
|
||||
uint32_t device, uint32_t clients, uint32_t word, uint8_t bit)
|
||||
{
|
||||
netplay_input_state_t simstate;
|
||||
uint32_t client, client_count = 0;;
|
||||
uint8_t share_mode = netplay->device_share_modes[device] & NETPLAY_SHARE_ANALOG_BITS;
|
||||
int32_t value = 0, new_value;
|
||||
|
||||
/* Make sure all real clients are accounted for */
|
||||
for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next)
|
||||
{
|
||||
if (!simstate->used || simstate->size != resstate->size) continue;
|
||||
clients |= 1<<simstate->client_num;
|
||||
}
|
||||
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(clients & (1<<client))) continue;
|
||||
simstate = netplay_device_client_state(netplay, simframe, device, client);
|
||||
if (!simstate) continue;
|
||||
client_count++;
|
||||
new_value = (int16_t) ((simstate->data[word]>>bit) & 0xFFFF);
|
||||
switch (share_mode)
|
||||
{
|
||||
case NETPLAY_SHARE_ANALOG_AVERAGE:
|
||||
value += (int32_t) new_value;
|
||||
break;
|
||||
default:
|
||||
if (abs(new_value) > abs(value) ||
|
||||
(abs(new_value) == abs(value) && new_value > value))
|
||||
value = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
if (share_mode == NETPLAY_SHARE_ANALOG_AVERAGE)
|
||||
value /= client_count;
|
||||
|
||||
resstate->data[word] |= ((uint32_t) (uint16_t) value) << bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_merge_analog
|
||||
* @netplay : pointer to netplay object
|
||||
* @resstate : state being resolved
|
||||
* @simframe : frame in which merging is being performed
|
||||
* @device : device being merged
|
||||
* @clients : bitmap of clients being merged
|
||||
* @dtype : device type
|
||||
*/
|
||||
static void netplay_merge_analog(netplay_t *netplay,
|
||||
netplay_input_state_t resstate, struct delta_frame *simframe,
|
||||
uint32_t device, uint32_t clients, unsigned dtype)
|
||||
{
|
||||
/* Devices with no analog parts */
|
||||
if (dtype == RETRO_DEVICE_JOYPAD || dtype == RETRO_DEVICE_KEYBOARD)
|
||||
return;
|
||||
|
||||
/* All other devices have at least one analog word */
|
||||
merge_analog_part(netplay, resstate, simframe, device, clients, 1, 0);
|
||||
merge_analog_part(netplay, resstate, simframe, device, clients, 1, 16);
|
||||
|
||||
/* And the ANALOG device has two (two sticks) */
|
||||
if (dtype == RETRO_DEVICE_ANALOG)
|
||||
{
|
||||
merge_analog_part(netplay, resstate, simframe, device, clients, 2, 0);
|
||||
merge_analog_part(netplay, resstate, simframe, device, clients, 2, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_resolve_input
|
||||
* @netplay : pointer to netplay object
|
||||
* @sim_ptr : frame pointer for which to resolve input
|
||||
* @resim : are we resimulating, or simulating this frame for the
|
||||
* first time?
|
||||
*
|
||||
* "Simulate" input by assuming it hasn't changed since the last read input.
|
||||
* Returns true if the resolved input changed from the last time it was
|
||||
* resolved.
|
||||
*/
|
||||
void netplay_simulate_input(netplay_t *netplay, size_t sim_ptr, bool resim)
|
||||
bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim)
|
||||
{
|
||||
uint32_t player;
|
||||
size_t prev;
|
||||
struct delta_frame *simframe, *pframe;
|
||||
netplay_input_state_t simstate, client_state = NULL, resstate, oldresstate, pstate;
|
||||
uint32_t clients, client, client_count;
|
||||
uint32_t device;
|
||||
bool ret = false;
|
||||
|
||||
simframe = &netplay->buffer[sim_ptr];
|
||||
|
||||
for (player = 0; player < MAX_USERS; player++)
|
||||
for (device = 0; device < MAX_INPUT_DEVICES; device++)
|
||||
{
|
||||
if (!(netplay->connected_players & (1<<player))) continue;
|
||||
if (simframe->have_real[player]) continue;
|
||||
unsigned dtype = netplay->config_devices[device]&RETRO_DEVICE_MASK;
|
||||
uint32_t dsize = netplay_expected_input_size(netplay, 1 << device);
|
||||
clients = netplay->device_clients[device];
|
||||
client_count = 0;
|
||||
|
||||
prev = PREV_PTR(netplay->read_ptr[player]);
|
||||
pframe = &netplay->buffer[prev];
|
||||
|
||||
if (resim)
|
||||
/* Make sure all real clients are accounted for */
|
||||
for (simstate = simframe->real_input[device]; simstate; simstate = simstate->next)
|
||||
{
|
||||
/* In resimulation mode, we only copy the buttons. The reason for this
|
||||
* is nonobvious:
|
||||
*
|
||||
* If we resimulated nothing, then the /duration/ with which any input
|
||||
* was pressed would be approximately correct, since the original
|
||||
* simulation came in as the input came in, but the /number of times/
|
||||
* the input was pressed would be wrong, as there would be an
|
||||
* advancing wavefront of real data overtaking the simulated data
|
||||
* (which is really just real data offset by some frames).
|
||||
*
|
||||
* That's acceptable for arrows in most situations, since the amount
|
||||
* you move is tied to the duration, but unacceptable for buttons,
|
||||
* which will seem to jerkily be pressed numerous times with those
|
||||
* wavefronts.
|
||||
*/
|
||||
const uint32_t keep = (1U<<RETRO_DEVICE_ID_JOYPAD_UP) |
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_DOWN) |
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_LEFT) |
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_RIGHT);
|
||||
uint32_t sim_state = simframe->simulated_input_state[player][0] & keep;
|
||||
sim_state |= pframe->real_input_state[player][0] & ~keep;
|
||||
simframe->simulated_input_state[player][0] = sim_state;
|
||||
if (!simstate->used || simstate->size != dsize) continue;
|
||||
clients |= 1<<simstate->client_num;
|
||||
}
|
||||
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(clients & (1<<client))) continue;
|
||||
|
||||
/* Resolve this client-device */
|
||||
simstate = netplay_input_state_for(&simframe->real_input[device], client, dsize, false, true);
|
||||
if (!simstate)
|
||||
{
|
||||
/* Don't already have this input, so must simulate if we're supposed to have it at all */
|
||||
if (netplay->read_frame_count[client] > simframe->frame)
|
||||
continue;
|
||||
simstate = netplay_input_state_for(&simframe->simlated_input[device], client, dsize, false, false);
|
||||
if (!simstate)
|
||||
continue;
|
||||
|
||||
prev = PREV_PTR(netplay->read_ptr[client]);
|
||||
pframe = &netplay->buffer[prev];
|
||||
pstate = netplay_input_state_for(&pframe->real_input[device], client, dsize, false, true);
|
||||
if (!pstate)
|
||||
continue;
|
||||
|
||||
if (resim && (dtype == RETRO_DEVICE_JOYPAD || dtype == RETRO_DEVICE_ANALOG))
|
||||
{
|
||||
/* In resimulation mode, we only copy the buttons. The reason for this
|
||||
* is nonobvious:
|
||||
*
|
||||
* If we resimulated nothing, then the /duration/ with which any input
|
||||
* was pressed would be approximately correct, since the original
|
||||
* simulation came in as the input came in, but the /number of times/
|
||||
* the input was pressed would be wrong, as there would be an
|
||||
* advancing wavefront of real data overtaking the simulated data
|
||||
* (which is really just real data offset by some frames).
|
||||
*
|
||||
* That's acceptable for arrows in most situations, since the amount
|
||||
* you move is tied to the duration, but unacceptable for buttons,
|
||||
* which will seem to jerkily be pressed numerous times with those
|
||||
* wavefronts.
|
||||
*/
|
||||
const uint32_t keep =
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_UP) |
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_DOWN) |
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_LEFT) |
|
||||
(1U<<RETRO_DEVICE_ID_JOYPAD_RIGHT);
|
||||
simstate->data[0] &= keep;
|
||||
simstate->data[0] |= pstate->data[0] & ~keep;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(simstate->data, pstate->data,
|
||||
dsize * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
client_state = simstate;
|
||||
client_count++;
|
||||
}
|
||||
|
||||
/* The frontend always uses the first resolved input, so make sure it's right */
|
||||
while (simframe->resolved_input[device]
|
||||
&& (simframe->resolved_input[device]->size != dsize
|
||||
|| simframe->resolved_input[device]->client_num != 0))
|
||||
{
|
||||
/* The default resolved input is of the wrong size! */
|
||||
netplay_input_state_t nextistate = simframe->resolved_input[device]->next;
|
||||
free(simframe->resolved_input[device]);
|
||||
simframe->resolved_input[device] = nextistate;
|
||||
}
|
||||
|
||||
/* Now we copy the state, whether real or simulated, out into the resolved state */
|
||||
resstate = netplay_input_state_for(&simframe->resolved_input[device], 0,
|
||||
dsize, false, false);
|
||||
if (!resstate)
|
||||
continue;
|
||||
|
||||
if (client_count == 1)
|
||||
{
|
||||
/* Trivial in the common 1-client case */
|
||||
if (memcmp(resstate->data, client_state->data, dsize * sizeof(uint32_t)))
|
||||
ret = true;
|
||||
memcpy(resstate->data, client_state->data, dsize * sizeof(uint32_t));
|
||||
|
||||
}
|
||||
else if (client_count == 0)
|
||||
{
|
||||
uint32_t word;
|
||||
for (word = 0; word < dsize; word++)
|
||||
{
|
||||
if (resstate->data[word])
|
||||
ret = true;
|
||||
resstate->data[word] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(simframe->simulated_input_state[player],
|
||||
pframe->real_input_state[player],
|
||||
WORDS_PER_INPUT * sizeof(uint32_t));
|
||||
/* Merge them */
|
||||
/* Most devices have all the digital parts in the first word. */
|
||||
static const uint32_t digital_common[3] = {-1, 0, 0};
|
||||
static const uint32_t digital_keyboard[5] = {-1, -1, -1, -1, -1};
|
||||
const uint32_t *digital;
|
||||
if (dtype == RETRO_DEVICE_KEYBOARD)
|
||||
digital = digital_keyboard;
|
||||
else
|
||||
digital = digital_common;
|
||||
oldresstate = netplay_input_state_for(&simframe->resolved_input[device], 1, dsize, false, false);
|
||||
if (!oldresstate)
|
||||
continue;
|
||||
memcpy(oldresstate->data, resstate->data, dsize * sizeof(uint32_t));
|
||||
memset(resstate->data, 0, dsize * sizeof(uint32_t));
|
||||
|
||||
netplay_merge_digital(netplay, resstate, simframe, device, clients, digital);
|
||||
netplay_merge_analog(netplay, resstate, simframe, device, clients, dtype);
|
||||
|
||||
if (memcmp(resstate->data, oldresstate->data, dsize * sizeof(uint32_t)))
|
||||
ret = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void netplay_handle_frame_hash(netplay_t *netplay, struct delta_frame *delta)
|
||||
@ -391,7 +701,7 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
||||
}
|
||||
|
||||
/* Only relevant if we're connected and not in a desynching operation */
|
||||
if ((netplay->is_server && !netplay->connected_players) ||
|
||||
if ((netplay->is_server && (netplay->connected_players<=1)) ||
|
||||
(netplay->self_mode < NETPLAY_CONNECTION_CONNECTED) ||
|
||||
(netplay->desync))
|
||||
{
|
||||
@ -414,43 +724,72 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
||||
netplay->force_reset = false;
|
||||
}
|
||||
|
||||
netplay->replay_ptr = netplay->other_ptr;
|
||||
netplay->replay_frame_count = netplay->other_frame_count;
|
||||
|
||||
#ifndef DEBUG_NONDETERMINISTIC_CORES
|
||||
if (!netplay->force_rewind)
|
||||
{
|
||||
bool cont = true;
|
||||
|
||||
/* Skip ahead if we predicted correctly.
|
||||
* Skip until our simulation failed. */
|
||||
while (netplay->other_frame_count < netplay->unread_frame_count &&
|
||||
netplay->other_frame_count < netplay->run_frame_count)
|
||||
{
|
||||
struct delta_frame *ptr = &netplay->buffer[netplay->other_ptr];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
/* If resolving the input changes it, we used bad input */
|
||||
if (netplay_resolve_input(netplay, netplay->other_ptr, true))
|
||||
{
|
||||
if (memcmp(ptr->simulated_input_state[i], ptr->real_input_state[i],
|
||||
sizeof(ptr->real_input_state[i])) != 0
|
||||
&& !ptr->used_real[i])
|
||||
break;
|
||||
cont = false;
|
||||
break;
|
||||
}
|
||||
if (i != MAX_USERS) break;
|
||||
|
||||
netplay_handle_frame_hash(netplay, ptr);
|
||||
netplay->other_ptr = NEXT_PTR(netplay->other_ptr);
|
||||
netplay->other_frame_count++;
|
||||
}
|
||||
netplay->replay_ptr = netplay->other_ptr;
|
||||
netplay->replay_frame_count = netplay->other_frame_count;
|
||||
|
||||
if (cont)
|
||||
{
|
||||
while (netplay->replay_frame_count < netplay->run_frame_count)
|
||||
{
|
||||
struct delta_frame *ptr = &netplay->buffer[netplay->replay_ptr];
|
||||
if (netplay_resolve_input(netplay, netplay->replay_ptr, true))
|
||||
break;
|
||||
netplay->replay_ptr = NEXT_PTR(netplay->replay_ptr);
|
||||
netplay->replay_frame_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now replay the real input if we've gotten ahead of it */
|
||||
if (netplay->force_rewind ||
|
||||
(netplay->other_frame_count < netplay->unread_frame_count &&
|
||||
netplay->other_frame_count < netplay->run_frame_count))
|
||||
(netplay->replay_frame_count < netplay->unread_frame_count &&
|
||||
netplay->replay_frame_count < netplay->run_frame_count))
|
||||
{
|
||||
retro_ctx_serialize_info_t serial_info;
|
||||
|
||||
/* Replay frames. */
|
||||
netplay->is_replay = true;
|
||||
netplay->replay_ptr = netplay->other_ptr;
|
||||
netplay->replay_frame_count = netplay->other_frame_count;
|
||||
|
||||
/* If we have a keyboard device, we replay the previous frame's input
|
||||
* just to assert that the keydown/keyup events work if the core
|
||||
* translates them in that way */
|
||||
if (netplay->have_updown_device)
|
||||
{
|
||||
netplay->replay_ptr = PREV_PTR(netplay->replay_ptr);
|
||||
netplay->replay_frame_count--;
|
||||
autosave_lock();
|
||||
core_run();
|
||||
autosave_unlock();
|
||||
netplay->replay_ptr = NEXT_PTR(netplay->replay_ptr);
|
||||
netplay->replay_frame_count++;
|
||||
}
|
||||
|
||||
if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
|
||||
/* Make sure we're initialized before we start loading things */
|
||||
@ -483,7 +822,7 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
||||
netplay_handle_frame_hash(netplay, ptr);
|
||||
|
||||
/* Re-simulate this frame's input */
|
||||
netplay_simulate_input(netplay, netplay->replay_ptr, true);
|
||||
netplay_resolve_input(netplay, netplay->replay_ptr, true);
|
||||
|
||||
autosave_lock();
|
||||
core_run();
|
||||
@ -536,16 +875,16 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
||||
|
||||
if (netplay->is_server)
|
||||
{
|
||||
uint32_t player;
|
||||
uint32_t client;
|
||||
|
||||
lo_frame_count = hi_frame_count = netplay->unread_frame_count;
|
||||
|
||||
/* Look for players that are ahead of us */
|
||||
for (player = 0; player < MAX_USERS; player++)
|
||||
for (client = 0; client < MAX_CLIENTS; client++)
|
||||
{
|
||||
if (!(netplay->connected_players & (1<<player))) continue;
|
||||
if (netplay->read_frame_count[player] > hi_frame_count)
|
||||
hi_frame_count = netplay->read_frame_count[player];
|
||||
if (!(netplay->connected_players & (1<<client))) continue;
|
||||
if (netplay->read_frame_count[client] > hi_frame_count)
|
||||
hi_frame_count = netplay->read_frame_count[client];
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -611,14 +950,14 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
||||
for (i = 0; i < netplay->connections_size; i++)
|
||||
{
|
||||
struct netplay_connection *connection = &netplay->connections[i];
|
||||
int player;
|
||||
uint32_t client_num;
|
||||
if (!connection->active ||
|
||||
connection->mode != NETPLAY_CONNECTION_PLAYING)
|
||||
continue;
|
||||
player = connection->player;
|
||||
client_num = i + 1;
|
||||
|
||||
/* Are they ahead? */
|
||||
if (netplay->self_frame_count + 3 < netplay->read_frame_count[player])
|
||||
if (netplay->self_frame_count + 3 < netplay->read_frame_count[client_num])
|
||||
{
|
||||
/* Tell them to stall */
|
||||
if (connection->stall_frame + NETPLAY_MAX_REQ_STALL_FREQUENCY <
|
||||
@ -626,7 +965,7 @@ void netplay_sync_post_frame(netplay_t *netplay, bool stalled)
|
||||
{
|
||||
connection->stall_frame = netplay->self_frame_count;
|
||||
netplay_cmd_stall(netplay, connection,
|
||||
netplay->read_frame_count[player] -
|
||||
netplay->read_frame_count[client_num] -
|
||||
netplay->self_frame_count + 1);
|
||||
}
|
||||
}
|
||||
|
@ -2692,20 +2692,13 @@ static enum runloop_state runloop_check_state(
|
||||
#ifdef HAVE_NETWORKING
|
||||
/* Check Netplay */
|
||||
{
|
||||
static bool old_netplay_flip = false;
|
||||
static bool old_netplay_watch = false;
|
||||
bool netplay_flip = BIT256_GET(
|
||||
current_input, RARCH_NETPLAY_FLIP);
|
||||
bool netplay_watch = BIT256_GET(
|
||||
current_input, RARCH_NETPLAY_GAME_WATCH);
|
||||
|
||||
if (netplay_flip && !old_netplay_flip)
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, NULL);
|
||||
|
||||
if (netplay_watch && !old_netplay_watch)
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_GAME_WATCH, NULL);
|
||||
|
||||
old_netplay_flip = netplay_flip;
|
||||
old_netplay_watch = netplay_watch;
|
||||
}
|
||||
#endif
|
||||
|
@ -120,7 +120,6 @@ uint32_t frame_offset_cmd(bool ntoh)
|
||||
case NETPLAY_CMD_CRC:
|
||||
case NETPLAY_CMD_LOAD_SAVESTATE:
|
||||
case NETPLAY_CMD_RESET:
|
||||
case NETPLAY_CMD_FLIP_PLAYERS:
|
||||
frame = ntohl(payload[0]);
|
||||
if (ntoh)
|
||||
frame -= frame_offset;
|
||||
@ -285,7 +284,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Expect the header */
|
||||
if (!socket_receive_all_blocking(sock, payload, 4*sizeof(uint32_t)))
|
||||
if (!socket_receive_all_blocking(sock, payload, 6*sizeof(uint32_t)))
|
||||
{
|
||||
fprintf(stderr, "Failed to receive connection header.\n");
|
||||
return 1;
|
||||
@ -299,7 +298,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Echo the connection header back */
|
||||
socket_send_all_blocking(sock, payload, 4*sizeof(uint32_t), true);
|
||||
socket_send_all_blocking(sock, payload, 6*sizeof(uint32_t), true);
|
||||
|
||||
/* Send a nickname */
|
||||
cmd = NETPLAY_CMD_NICK;
|
||||
@ -340,7 +339,8 @@ int main(int argc, char **argv)
|
||||
if (playing)
|
||||
{
|
||||
cmd = NETPLAY_CMD_PLAY;
|
||||
cmd_size = 0;
|
||||
cmd_size = sizeof(uint32_t);
|
||||
payload[0] = htonl(1);
|
||||
SEND();
|
||||
}
|
||||
|
||||
@ -397,7 +397,7 @@ int main(int argc, char **argv)
|
||||
/* Only sync based on server time */
|
||||
if (cmd == NETPLAY_CMD_INPUT &&
|
||||
(cmd_size < 2*sizeof(uint32_t) ||
|
||||
!(ntohl(payload[1]) & NETPLAY_CMD_INPUT_BIT_SERVER)))
|
||||
(ntohl(payload[1]) != 0)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user