2015-12-23 13:25:28 -07:00
|
|
|
/* RetroArch - A frontend for libretro.
|
|
|
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
2017-01-22 13:40:32 +01:00
|
|
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
|
|
|
* Copyright (C) 2016-2017 - Gregor Richards
|
2015-12-23 13:25:28 -07:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __RARCH_NETPLAY_PRIVATE_H
|
|
|
|
#define __RARCH_NETPLAY_PRIVATE_H
|
2016-05-12 10:20:14 +02:00
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
#include "netplay.h"
|
2016-05-09 20:30:47 +02:00
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
#include <net/net_compat.h>
|
2016-11-29 22:59:46 -05:00
|
|
|
#include <net/net_natt.h>
|
2016-09-13 17:33:26 -04:00
|
|
|
#include <features/features_cpu.h>
|
2016-11-26 16:06:52 -05:00
|
|
|
#include <streams/trans_stream.h>
|
2016-05-09 20:30:47 +02:00
|
|
|
|
2016-05-19 11:46:54 +02:00
|
|
|
#include "../../msg_hash.h"
|
|
|
|
#include "../../verbosity.h"
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
#define NETPLAY_PROTOCOL_VERSION 5
|
Multitudinous fixes and updates to Netplay. Had to be one commit since
they're mostly related:
(1) Renamed frame_count to self_frame_count to be consistent with all
other names.
(2) Previously, it was possible to overwrite data in the ring buffer
that hadn't yet been used. Now that's not possible, but that just
changes one breakage for another: It's now possible to miss the NEW
data. The final resolution for this will probably be requesting stalls.
This is accomplished simply by storing frame numbers in the ring buffer
and checking them against the 'other' head.
(3) In TCP packets, separated cmd_size from cmd. It was beyond pointless
for these to be combined, and restricted cmd_size to 16 bits, which
will probably fail when/if state loading is supported.
(4) Readahead is now allowed. In the past, if the peer got ahead of us,
we would simply ignore their data. Thus, if they got too far ahead of
us, we'd stop reading their data altogether. Fabulous. Now, we're happy
to read future input.
(5) If the peer gets too far ahead of us (currently an unconfigurable 10
frames), fast forward to catch up. This should prevent desync due to
clock drift or stutter.
(6) Used frame_count in a few places where ptr was used. Doing a
comparison of pointers on a ring buffer is a far more dangerous way to
assure we're done with a task than simply using the count, since the
ring buffer is... well, a ring.
(7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for
clarity.
(8) Slightly changed the protocol version hash, just to assure that
other clients wouldn't think they were compatible with this one.
(9) There was an off-by-one error which, under some circumstances, could
allow the replay engine to run a complete round through the ring buffer,
replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
|
|
|
|
2016-12-10 20:36:57 -05:00
|
|
|
#define RARCH_DEFAULT_PORT 55435
|
|
|
|
#define RARCH_DEFAULT_NICK "Anonymous"
|
|
|
|
|
2016-12-13 17:07:49 -05:00
|
|
|
#define NETPLAY_NICK_LEN 32
|
|
|
|
#define NETPLAY_PASS_LEN 128
|
2018-11-23 08:15:22 -05:00
|
|
|
#define NETPLAY_PASS_HASH_LEN 64 /* length of a SHA-256 hash */
|
2016-12-13 17:07:49 -05:00
|
|
|
|
2016-12-14 21:28:20 -05:00
|
|
|
#define MAX_SERVER_STALL_TIME_USEC (5*1000*1000)
|
|
|
|
#define MAX_CLIENT_STALL_TIME_USEC (10*1000*1000)
|
2017-02-23 19:05:43 -05:00
|
|
|
#define CATCH_UP_CHECK_TIME_USEC (500*1000)
|
2016-12-13 20:42:53 -05:00
|
|
|
#define MAX_RETRIES 16
|
|
|
|
#define RETRY_MS 500
|
2017-08-25 14:38:21 -04:00
|
|
|
#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;
|
|
|
|
|
2017-09-13 20:51:57 -04:00
|
|
|
/* 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)
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 23:09:55 -05:00
|
|
|
#define NETPLAY_MAX_STALL_FRAMES 60
|
|
|
|
#define NETPLAY_FRAME_RUN_TIME_WINDOW 120
|
2016-12-24 15:25:03 -05:00
|
|
|
#define NETPLAY_MAX_REQ_STALL_TIME 60
|
|
|
|
#define NETPLAY_MAX_REQ_STALL_FREQUENCY 120
|
2016-12-15 22:34:18 -05:00
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
#define PREV_PTR(x) ((x) == 0 ? netplay->buffer_size - 1 : (x) - 1)
|
|
|
|
#define NEXT_PTR(x) ((x + 1) % netplay->buffer_size)
|
|
|
|
|
2016-09-30 13:31:58 -04:00
|
|
|
/* Quirks mandated by how particular cores save states. This is distilled from
|
|
|
|
* the larger set of quirks that the quirks environment can communicate. */
|
|
|
|
#define NETPLAY_QUIRK_NO_SAVESTATES (1<<0)
|
|
|
|
#define NETPLAY_QUIRK_NO_TRANSMISSION (1<<1)
|
|
|
|
#define NETPLAY_QUIRK_INITIALIZATION (1<<2)
|
2016-10-05 21:12:42 -04:00
|
|
|
#define NETPLAY_QUIRK_ENDIAN_DEPENDENT (1<<3)
|
|
|
|
#define NETPLAY_QUIRK_PLATFORM_DEPENDENT (1<<4)
|
2016-09-30 13:31:58 -04:00
|
|
|
|
|
|
|
/* Mapping of serialization quirks to netplay quirks. */
|
|
|
|
#define NETPLAY_QUIRK_MAP_UNDERSTOOD \
|
|
|
|
(RETRO_SERIALIZATION_QUIRK_INCOMPLETE \
|
2016-12-20 22:17:15 -05:00
|
|
|
|RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE \
|
2016-09-30 13:31:58 -04:00
|
|
|
|RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE \
|
|
|
|
|RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION \
|
2016-10-03 16:38:38 -04:00
|
|
|
|RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT \
|
|
|
|
|RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT)
|
2016-09-30 13:31:58 -04:00
|
|
|
#define NETPLAY_QUIRK_MAP_NO_SAVESTATES \
|
|
|
|
(RETRO_SERIALIZATION_QUIRK_INCOMPLETE)
|
|
|
|
#define NETPLAY_QUIRK_MAP_NO_TRANSMISSION \
|
2016-10-05 21:12:42 -04:00
|
|
|
(RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION)
|
2016-09-30 13:31:58 -04:00
|
|
|
#define NETPLAY_QUIRK_MAP_INITIALIZATION \
|
|
|
|
(RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE)
|
2016-10-05 21:12:42 -04:00
|
|
|
#define NETPLAY_QUIRK_MAP_ENDIAN_DEPENDENT \
|
|
|
|
(RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT)
|
|
|
|
#define NETPLAY_QUIRK_MAP_PLATFORM_DEPENDENT \
|
|
|
|
(RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT)
|
2016-09-30 13:31:58 -04:00
|
|
|
|
2016-11-25 11:03:12 -05:00
|
|
|
/* Compression protocols supported */
|
|
|
|
#define NETPLAY_COMPRESSION_ZLIB (1<<0)
|
|
|
|
#if HAVE_ZLIB
|
|
|
|
#define NETPLAY_COMPRESSION_SUPPORTED NETPLAY_COMPRESSION_ZLIB
|
|
|
|
#else
|
|
|
|
#define NETPLAY_COMPRESSION_SUPPORTED 0
|
|
|
|
#endif
|
|
|
|
|
2016-12-03 17:01:19 -05:00
|
|
|
enum netplay_cmd
|
|
|
|
{
|
|
|
|
/* Basic commands */
|
|
|
|
|
|
|
|
/* Acknowlegement response */
|
|
|
|
NETPLAY_CMD_ACK = 0x0000,
|
|
|
|
|
|
|
|
/* Failed acknowlegement response */
|
|
|
|
NETPLAY_CMD_NAK = 0x0001,
|
|
|
|
|
|
|
|
/* Gracefully disconnects from host */
|
|
|
|
NETPLAY_CMD_DISCONNECT = 0x0002,
|
|
|
|
|
|
|
|
/* Input data */
|
|
|
|
NETPLAY_CMD_INPUT = 0x0003,
|
|
|
|
|
2016-12-12 21:57:14 -05:00
|
|
|
/* Non-input data */
|
|
|
|
NETPLAY_CMD_NOINPUT = 0x0004,
|
|
|
|
|
2016-12-03 17:01:19 -05:00
|
|
|
/* Initialization commands */
|
|
|
|
|
|
|
|
/* Inform the other side of our nick (must be first command) */
|
|
|
|
NETPLAY_CMD_NICK = 0x0020,
|
|
|
|
|
2016-12-13 15:26:20 -05:00
|
|
|
/* Give the connection password */
|
|
|
|
NETPLAY_CMD_PASSWORD = 0x0021,
|
|
|
|
|
2016-12-17 14:48:07 -05:00
|
|
|
/* Give core/content info */
|
|
|
|
NETPLAY_CMD_INFO = 0x0022,
|
|
|
|
|
2016-12-03 18:53:57 -05:00
|
|
|
/* Initial synchronization info (frame, sram, player info) */
|
2016-12-17 14:48:07 -05:00
|
|
|
NETPLAY_CMD_SYNC = 0x0023,
|
2016-12-03 17:22:50 -05:00
|
|
|
|
2016-12-03 17:01:19 -05:00
|
|
|
/* Join spectator mode */
|
2016-12-17 14:48:07 -05:00
|
|
|
NETPLAY_CMD_SPECTATE = 0x0024,
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/* Join play mode */
|
2016-12-17 14:48:07 -05:00
|
|
|
NETPLAY_CMD_PLAY = 0x0025,
|
2016-12-03 18:53:57 -05:00
|
|
|
|
|
|
|
/* Report player mode */
|
2016-12-17 14:48:07 -05:00
|
|
|
NETPLAY_CMD_MODE = 0x0026,
|
2016-12-03 17:01:19 -05:00
|
|
|
|
2016-12-15 11:56:47 -05:00
|
|
|
/* Report player mode refused */
|
2016-12-17 14:48:07 -05:00
|
|
|
NETPLAY_CMD_MODE_REFUSED = 0x0027,
|
2016-12-15 11:56:47 -05:00
|
|
|
|
2016-12-03 17:01:19 -05:00
|
|
|
/* Loading and synchronization */
|
|
|
|
|
|
|
|
/* Send the CRC hash of a frame's state */
|
|
|
|
NETPLAY_CMD_CRC = 0x0040,
|
|
|
|
|
|
|
|
/* Request a savestate */
|
|
|
|
NETPLAY_CMD_REQUEST_SAVESTATE = 0x0041,
|
|
|
|
|
|
|
|
/* Send a savestate for the client to load */
|
|
|
|
NETPLAY_CMD_LOAD_SAVESTATE = 0x0042,
|
|
|
|
|
|
|
|
/* Pauses the game, takes no arguments */
|
|
|
|
NETPLAY_CMD_PAUSE = 0x0043,
|
|
|
|
|
|
|
|
/* Resumes the game, takes no arguments */
|
|
|
|
NETPLAY_CMD_RESUME = 0x0044,
|
|
|
|
|
2016-12-24 15:25:03 -05:00
|
|
|
/* Request that a client stall because it's running fast */
|
|
|
|
NETPLAY_CMD_STALL = 0x0045,
|
|
|
|
|
2017-02-15 14:40:37 -05:00
|
|
|
/* Request a core reset */
|
|
|
|
NETPLAY_CMD_RESET = 0x0046,
|
|
|
|
|
2016-12-03 17:01:19 -05:00
|
|
|
/* Sends over cheats enabled on client (unsupported) */
|
2017-02-15 14:40:37 -05:00
|
|
|
NETPLAY_CMD_CHEATS = 0x0047,
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/* Misc. commands */
|
|
|
|
|
|
|
|
/* Sends multiple config requests over,
|
|
|
|
* See enum netplay_cmd_cfg */
|
|
|
|
NETPLAY_CMD_CFG = 0x0061,
|
|
|
|
|
|
|
|
/* CMD_CFG streamlines sending multiple
|
|
|
|
configurations. This acknowledges
|
|
|
|
each one individually */
|
|
|
|
NETPLAY_CMD_CFG_ACK = 0x0062
|
|
|
|
};
|
|
|
|
|
2016-12-17 22:41:34 -05:00
|
|
|
#define NETPLAY_CMD_SYNC_BIT_PAUSED (1U<<31)
|
2017-08-25 14:38:21 -04:00
|
|
|
#define NETPLAY_CMD_PLAY_BIT_SLAVE (1U<<31)
|
2017-09-10 19:42:32 -04:00
|
|
|
#define NETPLAY_CMD_MODE_BIT_YOU (1U<<31)
|
|
|
|
#define NETPLAY_CMD_MODE_BIT_PLAYING (1U<<30)
|
|
|
|
#define NETPLAY_CMD_MODE_BIT_SLAVE (1U<<29)
|
2016-12-10 20:36:57 -05:00
|
|
|
|
2016-12-15 11:56:47 -05:00
|
|
|
/* These are the reasons given for mode changes to be rejected */
|
|
|
|
enum netplay_cmd_mode_reasons
|
|
|
|
{
|
|
|
|
/* Other/unknown reason */
|
|
|
|
NETPLAY_CMD_MODE_REFUSED_REASON_OTHER,
|
|
|
|
|
|
|
|
/* You don't have permission to play */
|
|
|
|
NETPLAY_CMD_MODE_REFUSED_REASON_UNPRIVILEGED,
|
|
|
|
|
|
|
|
/* There are no free player slots */
|
2017-06-06 21:35:09 -04:00
|
|
|
NETPLAY_CMD_MODE_REFUSED_REASON_NO_SLOTS,
|
|
|
|
|
|
|
|
/* You're changing modes too fast */
|
2017-09-10 19:42:32 -04:00
|
|
|
NETPLAY_CMD_MODE_REFUSED_REASON_TOO_FAST,
|
|
|
|
|
|
|
|
/* You requested a particular port but it's not available */
|
|
|
|
NETPLAY_CMD_MODE_REFUSED_REASON_NOT_AVAILABLE
|
|
|
|
};
|
|
|
|
|
2017-09-10 22:49:25 -04:00
|
|
|
/* 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
|
|
|
|
};
|
|
|
|
|
2017-09-10 19:42:32 -04:00
|
|
|
/* The current status of a connection */
|
2016-12-03 18:53:57 -05:00
|
|
|
enum rarch_netplay_connection_mode
|
2016-12-03 17:01:19 -05:00
|
|
|
{
|
2016-12-03 18:53:57 -05:00
|
|
|
NETPLAY_CONNECTION_NONE = 0,
|
|
|
|
|
2017-06-06 21:35:09 -04:00
|
|
|
NETPLAY_CONNECTION_DELAYED_DISCONNECT, /* The connection is dead, but data
|
|
|
|
is still waiting to be forwarded */
|
|
|
|
|
2016-12-03 18:53:57 -05:00
|
|
|
/* Initialization: */
|
|
|
|
NETPLAY_CONNECTION_INIT, /* Waiting for header */
|
|
|
|
NETPLAY_CONNECTION_PRE_NICK, /* Waiting for nick */
|
2016-12-13 15:26:20 -05:00
|
|
|
NETPLAY_CONNECTION_PRE_PASSWORD, /* Waiting for password */
|
2016-12-17 14:48:07 -05:00
|
|
|
NETPLAY_CONNECTION_PRE_INFO, /* Waiting for core/content info */
|
2016-12-03 18:53:57 -05:00
|
|
|
NETPLAY_CONNECTION_PRE_SYNC, /* Waiting for sync */
|
|
|
|
|
|
|
|
/* Ready: */
|
|
|
|
NETPLAY_CONNECTION_CONNECTED, /* Modes above this are connected */
|
|
|
|
NETPLAY_CONNECTION_SPECTATING, /* Spectator mode */
|
2017-02-22 20:34:17 -05:00
|
|
|
NETPLAY_CONNECTION_SLAVE, /* Playing in slave mode */
|
2016-12-03 18:53:57 -05:00
|
|
|
NETPLAY_CONNECTION_PLAYING /* Normal ready state */
|
2016-12-03 17:01:19 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
enum rarch_netplay_stall_reason
|
|
|
|
{
|
2016-12-09 13:32:04 -05:00
|
|
|
NETPLAY_STALL_NONE = 0,
|
2017-02-22 23:19:22 -05:00
|
|
|
|
|
|
|
/* We're so far ahead that we can't read more data without overflowing the
|
|
|
|
* buffer */
|
2016-12-09 13:32:04 -05:00
|
|
|
NETPLAY_STALL_RUNNING_FAST,
|
2017-02-22 23:19:22 -05:00
|
|
|
|
|
|
|
/* We're in spectator or slave mode and are running ahead at all */
|
|
|
|
NETPLAY_STALL_SPECTATOR_WAIT,
|
|
|
|
|
|
|
|
/* Our actual execution is catching up with latency-adjusted input frames */
|
2017-01-18 16:07:17 -05:00
|
|
|
NETPLAY_STALL_INPUT_LATENCY,
|
2017-02-22 23:19:22 -05:00
|
|
|
|
|
|
|
/* The server asked us to stall */
|
2016-12-24 15:25:03 -05:00
|
|
|
NETPLAY_STALL_SERVER_REQUESTED,
|
2017-02-22 23:19:22 -05:00
|
|
|
|
|
|
|
/* We have no connection and must have one to proceed */
|
2016-12-09 13:32:04 -05:00
|
|
|
NETPLAY_STALL_NO_CONNECTION
|
2016-12-03 17:01:19 -05:00
|
|
|
};
|
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/* 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;
|
|
|
|
|
|
|
|
/* 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];
|
2020-08-15 18:53:52 +02:00
|
|
|
|
|
|
|
/* Is this a buffer with real data? */
|
|
|
|
bool used;
|
2017-08-25 14:38:21 -04:00
|
|
|
} *netplay_input_state_t;
|
2016-12-10 20:36:57 -05:00
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
struct delta_frame
|
|
|
|
{
|
2020-08-15 18:53:52 +02:00
|
|
|
/* 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]; /* ptr alignment */
|
|
|
|
|
|
|
|
/* The real input */
|
|
|
|
netplay_input_state_t real_input[MAX_INPUT_DEVICES]; /* ptr alignment */
|
Multitudinous fixes and updates to Netplay. Had to be one commit since
they're mostly related:
(1) Renamed frame_count to self_frame_count to be consistent with all
other names.
(2) Previously, it was possible to overwrite data in the ring buffer
that hadn't yet been used. Now that's not possible, but that just
changes one breakage for another: It's now possible to miss the NEW
data. The final resolution for this will probably be requesting stalls.
This is accomplished simply by storing frame numbers in the ring buffer
and checking them against the 'other' head.
(3) In TCP packets, separated cmd_size from cmd. It was beyond pointless
for these to be combined, and restricted cmd_size to 16 bits, which
will probably fail when/if state loading is supported.
(4) Readahead is now allowed. In the past, if the peer got ahead of us,
we would simply ignore their data. Thus, if they got too far ahead of
us, we'd stop reading their data altogether. Fabulous. Now, we're happy
to read future input.
(5) If the peer gets too far ahead of us (currently an unconfigurable 10
frames), fast forward to catch up. This should prevent desync due to
clock drift or stutter.
(6) Used frame_count in a few places where ptr was used. Doing a
comparison of pointers on a ring buffer is a far more dangerous way to
assure we're done with a task than simply using the count, since the
ring buffer is... well, a ring.
(7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for
clarity.
(8) Slightly changed the protocol version hash, just to assure that
other clients wouldn't think they were compatible with this one.
(9) There was an off-by-one error which, under some circumstances, could
allow the replay engine to run a complete round through the ring buffer,
replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
|
|
|
|
2016-09-14 23:19:47 -04:00
|
|
|
/* The serialized state of the core at this frame, before input */
|
2015-12-23 13:25:28 -07:00
|
|
|
void *state;
|
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
uint32_t frame;
|
|
|
|
|
2016-09-14 23:19:47 -04:00
|
|
|
/* The CRC-32 of the serialized state if we've calculated it, else 0 */
|
|
|
|
uint32_t crc;
|
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/* The simulated input. is_real here means the simulation is done, i.e.,
|
|
|
|
* it's a real simulation, not real input. */
|
2017-09-10 09:15:06 -04:00
|
|
|
netplay_input_state_t simlated_input[MAX_INPUT_DEVICES];
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2016-09-12 09:13:26 -04:00
|
|
|
/* Have we read local input? */
|
Multitudinous fixes and updates to Netplay. Had to be one commit since
they're mostly related:
(1) Renamed frame_count to self_frame_count to be consistent with all
other names.
(2) Previously, it was possible to overwrite data in the ring buffer
that hadn't yet been used. Now that's not possible, but that just
changes one breakage for another: It's now possible to miss the NEW
data. The final resolution for this will probably be requesting stalls.
This is accomplished simply by storing frame numbers in the ring buffer
and checking them against the 'other' head.
(3) In TCP packets, separated cmd_size from cmd. It was beyond pointless
for these to be combined, and restricted cmd_size to 16 bits, which
will probably fail when/if state loading is supported.
(4) Readahead is now allowed. In the past, if the peer got ahead of us,
we would simply ignore their data. Thus, if they got too far ahead of
us, we'd stop reading their data altogether. Fabulous. Now, we're happy
to read future input.
(5) If the peer gets too far ahead of us (currently an unconfigurable 10
frames), fast forward to catch up. This should prevent desync due to
clock drift or stutter.
(6) Used frame_count in a few places where ptr was used. Doing a
comparison of pointers on a ring buffer is a far more dangerous way to
assure we're done with a task than simply using the count, since the
ring buffer is... well, a ring.
(7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for
clarity.
(8) Slightly changed the protocol version hash, just to assure that
other clients wouldn't think they were compatible with this one.
(9) There was an off-by-one error which, under some circumstances, could
allow the replay engine to run a complete round through the ring buffer,
replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
|
|
|
bool have_local;
|
2016-09-12 09:13:26 -04:00
|
|
|
|
2016-12-12 12:34:41 -05:00
|
|
|
/* Have we read the real (remote) input? */
|
2017-08-25 14:38:21 -04:00
|
|
|
bool have_real[MAX_CLIENTS];
|
2020-08-15 18:53:52 +02:00
|
|
|
|
|
|
|
bool used; /* a bit derpy, but this is how we know if the delta's been used at all */
|
2015-12-23 13:25:28 -07:00
|
|
|
};
|
|
|
|
|
2016-09-25 11:05:50 -04:00
|
|
|
struct socket_buffer
|
|
|
|
{
|
|
|
|
unsigned char *data;
|
|
|
|
size_t bufsz;
|
2020-08-15 18:53:52 +02:00
|
|
|
size_t start;
|
|
|
|
size_t end;
|
2016-09-25 11:05:50 -04:00
|
|
|
size_t read;
|
|
|
|
};
|
|
|
|
|
2016-12-05 00:04:01 -05:00
|
|
|
/* Each connection gets a connection struct */
|
|
|
|
struct netplay_connection
|
|
|
|
{
|
2020-08-15 18:53:52 +02:00
|
|
|
/* Is this connection stalling? */
|
|
|
|
retro_time_t stall_time;
|
2016-12-09 14:14:54 -05:00
|
|
|
|
2016-12-09 22:29:02 -05:00
|
|
|
/* Address of peer */
|
|
|
|
struct sockaddr_storage addr;
|
|
|
|
|
2016-12-09 14:14:54 -05:00
|
|
|
/* Buffers for sending and receiving data */
|
|
|
|
struct socket_buffer send_packet_buffer, recv_packet_buffer;
|
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
/* fd associated with this connection */
|
|
|
|
int fd;
|
2016-12-09 14:14:54 -05:00
|
|
|
|
2017-06-06 21:35:09 -04:00
|
|
|
/* If the mode is a DELAYED_DISCONNECT or SPECTATOR, the transmission of the
|
|
|
|
* mode change may have to wait for data to be forwarded. This is the frame
|
|
|
|
* to wait for, or 0 if no delay is active. */
|
|
|
|
uint32_t delay_frame;
|
|
|
|
|
2016-12-18 16:52:21 -05:00
|
|
|
/* What compression does this peer support? */
|
|
|
|
uint32_t compression_supported;
|
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
/* For the server: When was the last time we requested this client to stall?
|
|
|
|
* For the client: How many frames of stall do we have left? */
|
|
|
|
uint32_t stall_frame;
|
|
|
|
|
|
|
|
/* Salt associated with password transaction */
|
|
|
|
uint32_t salt;
|
2016-12-14 21:28:20 -05:00
|
|
|
|
|
|
|
/* Is this connection stalling? */
|
|
|
|
enum rarch_netplay_stall_reason stall;
|
2016-12-24 15:25:03 -05:00
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
/* Mode of the connection */
|
|
|
|
enum rarch_netplay_connection_mode mode;
|
|
|
|
|
|
|
|
/* Nickname of peer */
|
|
|
|
char nick[NETPLAY_NICK_LEN];
|
|
|
|
|
|
|
|
/* Is this player paused? */
|
|
|
|
bool paused;
|
|
|
|
|
|
|
|
/* Is this connection allowed to play (server only)? */
|
|
|
|
bool can_play;
|
|
|
|
|
|
|
|
/* Is this connection buffer in use? */
|
|
|
|
bool active;
|
2016-12-05 00:04:01 -05:00
|
|
|
};
|
|
|
|
|
2016-12-18 16:52:21 -05:00
|
|
|
/* Compression transcoder */
|
|
|
|
struct compression_transcoder
|
|
|
|
{
|
|
|
|
const struct trans_stream_backend *compression_backend;
|
|
|
|
void *compression_stream;
|
|
|
|
const struct trans_stream_backend *decompression_backend;
|
|
|
|
void *decompression_stream;
|
|
|
|
};
|
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
struct netplay
|
|
|
|
{
|
2020-08-15 18:53:52 +02:00
|
|
|
/* When did we start falling behind? */
|
|
|
|
retro_time_t catch_up_time;
|
|
|
|
/* How long have we been stalled? */
|
|
|
|
retro_time_t stall_time;
|
2016-12-09 23:04:39 -05:00
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
/* We stall if we're far enough ahead that we couldn't transparently rewind.
|
|
|
|
* To know if we could transparently rewind, we need to know how long
|
|
|
|
* running a frame takes. We record that every frame and get a running
|
|
|
|
* (window) average */
|
|
|
|
retro_time_t frame_run_time[NETPLAY_FRAME_RUN_TIME_WINDOW];
|
|
|
|
retro_time_t frame_run_time_sum, frame_run_time_avg;
|
2017-05-16 00:15:06 -05:00
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
struct netplay_connection one_connection; /* Client only */ /* retro_time_t alignment */
|
2016-12-09 14:14:54 -05:00
|
|
|
|
2016-12-05 00:04:01 -05:00
|
|
|
/* TCP connection for listening (server only) */
|
|
|
|
int listen_fd;
|
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/* Our client number */
|
|
|
|
uint32_t self_client_num;
|
2016-12-03 23:08:31 -05:00
|
|
|
|
2016-12-05 00:04:01 -05:00
|
|
|
/* All of our connections */
|
|
|
|
struct netplay_connection *connections;
|
|
|
|
size_t connections_size;
|
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/* Bitmap of clients with input devices */
|
2017-09-10 09:15:06 -04:00
|
|
|
uint32_t connected_players;
|
2016-12-14 22:02:01 -05:00
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/* Bitmap of clients playing in slave mode (should be a subset of
|
2017-02-22 20:34:17 -05:00
|
|
|
* connected_players) */
|
2017-09-10 09:15:06 -04:00
|
|
|
uint32_t connected_slaves;
|
2017-08-25 14:38:21 -04:00
|
|
|
|
|
|
|
/* 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];
|
|
|
|
|
|
|
|
/* Our own device bitmap */
|
|
|
|
uint32_t self_devices;
|
2017-02-22 20:34:17 -05:00
|
|
|
|
2017-04-18 15:25:58 -04:00
|
|
|
/* Number of desync operations we're currently performing. If set, we don't
|
|
|
|
* attempt to stay in sync. */
|
|
|
|
uint32_t desync;
|
|
|
|
|
2017-09-13 11:39:41 -04:00
|
|
|
/* 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];
|
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
struct retro_callbacks cbs;
|
2016-12-09 14:14:54 -05:00
|
|
|
|
2016-11-29 22:59:46 -05:00
|
|
|
/* NAT traversal info (if NAT traversal is used and serving) */
|
|
|
|
struct natt_status nat_traversal_state;
|
2016-12-09 14:14:54 -05:00
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
struct delta_frame *buffer;
|
|
|
|
size_t buffer_size;
|
|
|
|
|
2016-11-26 16:06:52 -05:00
|
|
|
/* Compression transcoder */
|
2016-12-18 16:52:21 -05:00
|
|
|
struct compression_transcoder compress_nil,
|
|
|
|
compress_zlib;
|
2016-11-25 11:03:12 -05:00
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
/* Size of savestates */
|
|
|
|
size_t state_size;
|
|
|
|
|
2016-10-30 14:27:43 -04:00
|
|
|
/* A buffer into which to compress frames for transfer */
|
|
|
|
uint8_t *zbuffer;
|
|
|
|
size_t zbuffer_size;
|
|
|
|
|
2016-12-09 14:14:54 -05:00
|
|
|
/* The size of our packet buffers */
|
|
|
|
size_t packet_buffer_size;
|
|
|
|
|
2017-01-18 16:07:17 -05:00
|
|
|
/* The frame we're currently inputting */
|
2017-01-20 14:28:18 -05:00
|
|
|
size_t self_ptr;
|
|
|
|
uint32_t self_frame_count;
|
2017-01-18 16:07:17 -05:00
|
|
|
|
2017-01-20 14:28:18 -05:00
|
|
|
/* The frame we're currently running, which may be behind the frame we're
|
|
|
|
* currently inputting if we're using input latency */
|
2017-01-18 16:07:17 -05:00
|
|
|
size_t run_ptr;
|
|
|
|
uint32_t run_frame_count;
|
2016-12-09 22:37:50 -05:00
|
|
|
|
|
|
|
/* The first frame at which some data might be unreliable */
|
2015-12-23 13:25:28 -07:00
|
|
|
size_t other_ptr;
|
2016-12-09 22:37:50 -05:00
|
|
|
uint32_t other_frame_count;
|
|
|
|
|
2016-12-10 20:36:57 -05:00
|
|
|
/* Pointer to the first frame for which we're missing the data of at least
|
|
|
|
* one connected player excluding ourself.
|
|
|
|
* Generally, other_ptr <= unread_ptr <= self_ptr, but unread_ptr can get ahead
|
2016-12-09 22:37:50 -05:00
|
|
|
* of self_ptr if the peer is running fast. */
|
2016-12-10 20:36:57 -05:00
|
|
|
size_t unread_ptr;
|
|
|
|
uint32_t unread_frame_count;
|
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/* Pointer to the next frame to read from each client */
|
2017-09-11 10:40:34 -04:00
|
|
|
size_t read_ptr[MAX_CLIENTS];
|
|
|
|
uint32_t read_frame_count[MAX_CLIENTS];
|
2016-12-10 20:36:57 -05:00
|
|
|
|
|
|
|
/* Pointer to the next frame to read from the server (as it might not be a
|
|
|
|
* player but still synchronizes) */
|
|
|
|
size_t server_ptr;
|
|
|
|
uint32_t server_frame_count;
|
2016-12-09 22:37:50 -05:00
|
|
|
|
Multitudinous fixes and updates to Netplay. Had to be one commit since
they're mostly related:
(1) Renamed frame_count to self_frame_count to be consistent with all
other names.
(2) Previously, it was possible to overwrite data in the ring buffer
that hadn't yet been used. Now that's not possible, but that just
changes one breakage for another: It's now possible to miss the NEW
data. The final resolution for this will probably be requesting stalls.
This is accomplished simply by storing frame numbers in the ring buffer
and checking them against the 'other' head.
(3) In TCP packets, separated cmd_size from cmd. It was beyond pointless
for these to be combined, and restricted cmd_size to 16 bits, which
will probably fail when/if state loading is supported.
(4) Readahead is now allowed. In the past, if the peer got ahead of us,
we would simply ignore their data. Thus, if they got too far ahead of
us, we'd stop reading their data altogether. Fabulous. Now, we're happy
to read future input.
(5) If the peer gets too far ahead of us (currently an unconfigurable 10
frames), fast forward to catch up. This should prevent desync due to
clock drift or stutter.
(6) Used frame_count in a few places where ptr was used. Doing a
comparison of pointers on a ring buffer is a far more dangerous way to
assure we're done with a task than simply using the count, since the
ring buffer is... well, a ring.
(7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for
clarity.
(8) Slightly changed the protocol version hash, just to assure that
other clients wouldn't think they were compatible with this one.
(9) There was an off-by-one error which, under some circumstances, could
allow the replay engine to run a complete round through the ring buffer,
replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
|
|
|
/* A pointer used temporarily for replay. */
|
|
|
|
size_t replay_ptr;
|
2016-12-09 22:37:50 -05:00
|
|
|
uint32_t replay_frame_count;
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2020-08-15 18:53:52 +02:00
|
|
|
/* Our local socket info */
|
|
|
|
struct addrinfo *addr;
|
|
|
|
|
|
|
|
/* Counter for timeouts */
|
|
|
|
unsigned timeout_cnt;
|
|
|
|
|
|
|
|
int frame_run_time_ptr;
|
|
|
|
|
|
|
|
/* Latency frames; positive to hide network latency, negative to hide input latency */
|
|
|
|
int input_latency_frames;
|
|
|
|
|
|
|
|
/* Frequency with which to check CRCs */
|
|
|
|
int check_frames;
|
|
|
|
|
|
|
|
/* How far behind did we fall? */
|
|
|
|
uint32_t catch_up_behind;
|
|
|
|
|
|
|
|
/* Are we stalled? */
|
|
|
|
enum rarch_netplay_stall_reason stall;
|
|
|
|
|
|
|
|
/* Our mode and status */
|
|
|
|
enum rarch_netplay_connection_mode self_mode;
|
|
|
|
|
|
|
|
/* TCP port (only set if serving) */
|
|
|
|
uint16_t tcp_port;
|
|
|
|
|
|
|
|
/* The sharing mode for each device */
|
|
|
|
uint8_t device_share_modes[MAX_INPUT_DEVICES];
|
|
|
|
|
|
|
|
/* Our nickname */
|
|
|
|
char nick[NETPLAY_NICK_LEN];
|
|
|
|
|
|
|
|
bool nat_traversal, nat_traversal_task_oustanding;
|
|
|
|
|
|
|
|
/* 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;
|
2015-12-23 13:25:28 -07:00
|
|
|
|
|
|
|
/* Are we replaying old frames? */
|
|
|
|
bool is_replay;
|
2016-09-14 18:03:40 -04:00
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
/* We don't want to poll several times on a frame. */
|
|
|
|
bool can_poll;
|
2016-09-14 18:03:40 -04:00
|
|
|
|
|
|
|
/* Force a rewind to other_frame_count/other_ptr. This is for synchronized
|
2017-09-12 17:16:50 -04:00
|
|
|
* events, such as restarting or savestate loading. */
|
2016-09-14 18:03:40 -04:00
|
|
|
bool force_rewind;
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2017-02-15 14:40:37 -05:00
|
|
|
/* Force a reset */
|
|
|
|
bool force_reset;
|
|
|
|
|
2016-09-30 13:31:58 -04:00
|
|
|
/* Quirks in the savestate implementation */
|
2016-09-30 15:37:02 -04:00
|
|
|
uint64_t quirks;
|
2016-09-21 17:23:36 -04:00
|
|
|
|
2016-12-12 19:34:50 -05:00
|
|
|
/* Force our state to be sent to all connections */
|
|
|
|
bool force_send_savestate;
|
2016-09-14 23:19:47 -04:00
|
|
|
|
|
|
|
/* Have we requested a savestate as a sync point? */
|
|
|
|
bool savestate_request_outstanding;
|
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2016-12-15 22:34:18 -05:00
|
|
|
/* Netplay pausing */
|
2016-09-14 14:25:54 -04:00
|
|
|
bool local_paused;
|
|
|
|
bool remote_paused;
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2016-12-15 23:09:55 -05:00
|
|
|
/* If true, never progress without peer input (stateless/rewindless mode) */
|
|
|
|
bool stateless_mode;
|
2016-12-15 22:34:18 -05:00
|
|
|
|
2016-09-12 09:13:26 -04:00
|
|
|
|
2016-12-15 11:04:05 -05:00
|
|
|
/* Opposite of stalling, should we be catching up? */
|
|
|
|
bool catch_up;
|
|
|
|
|
2016-12-15 12:43:29 -05:00
|
|
|
/* Have we checked whether CRCs are valid at all? */
|
|
|
|
bool crc_validity_checked;
|
|
|
|
|
|
|
|
/* Are they valid? */
|
|
|
|
bool crcs_valid;
|
2020-08-15 18:53:52 +02:00
|
|
|
|
|
|
|
/* Are we the server? */
|
|
|
|
bool is_server;
|
|
|
|
|
|
|
|
/* Are we the connected? */
|
|
|
|
bool is_connected;
|
|
|
|
|
2015-12-23 13:25:28 -07:00
|
|
|
};
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-BUF.C
|
|
|
|
**************************************************************/
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_init_socket_buffer
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Initialize a new socket buffer.
|
|
|
|
*/
|
|
|
|
bool netplay_init_socket_buffer(struct socket_buffer *sbuf, size_t size);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* netplay_resize_socket_buffer
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Resize the given socket_buffer's buffer to the requested size.
|
|
|
|
*/
|
|
|
|
bool netplay_resize_socket_buffer(struct socket_buffer *sbuf, size_t newsize);
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_deinit_socket_buffer
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Free a socket buffer.
|
|
|
|
*/
|
|
|
|
void netplay_deinit_socket_buffer(struct socket_buffer *sbuf);
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_send
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Queue the given data for sending.
|
|
|
|
*/
|
|
|
|
bool netplay_send(struct socket_buffer *sbuf, int sockfd, const void *buf,
|
|
|
|
size_t len);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* netplay_send_flush
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Flush unsent data in the given socket buffer, blocking to do so if
|
|
|
|
* requested.
|
|
|
|
*
|
|
|
|
* Returns false only on socket failures, true otherwise.
|
|
|
|
*/
|
|
|
|
bool netplay_send_flush(struct socket_buffer *sbuf, int sockfd, bool block);
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_recv
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Receive buffered or fresh data.
|
|
|
|
*
|
|
|
|
* Returns number of bytes returned, which may be short or 0, or -1 on error.
|
|
|
|
*/
|
|
|
|
ssize_t netplay_recv(struct socket_buffer *sbuf, int sockfd, void *buf,
|
|
|
|
size_t len, bool block);
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_recv_reset
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Reset our recv buffer so that future netplay_recvs will read the same data
|
|
|
|
* again.
|
|
|
|
*/
|
|
|
|
void netplay_recv_reset(struct socket_buffer *sbuf);
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_recv_flush
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Flush our recv buffer, so a future netplay_recv_reset will reset to this
|
|
|
|
* point.
|
|
|
|
*/
|
|
|
|
void netplay_recv_flush(struct socket_buffer *sbuf);
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-DELTA.C
|
|
|
|
**************************************************************/
|
2016-12-03 17:01:19 -05:00
|
|
|
|
|
|
|
/**
|
2016-12-15 08:42:03 -05:00
|
|
|
* netplay_delta_frame_ready
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Prepares, if possible, a delta frame for input, and reports whether it is
|
|
|
|
* ready.
|
2016-12-03 17:01:19 -05:00
|
|
|
*
|
2016-12-15 08:42:03 -05:00
|
|
|
* Returns: True if the delta frame is ready for input at the given frame,
|
|
|
|
* false otherwise.
|
|
|
|
*/
|
|
|
|
bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta,
|
|
|
|
uint32_t frame);
|
2016-12-03 17:01:19 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_delta_frame_crc
|
|
|
|
*
|
|
|
|
* Get the CRC for the serialization of this frame.
|
|
|
|
*/
|
|
|
|
uint32_t netplay_delta_frame_crc(netplay_t *netplay, struct delta_frame *delta);
|
2016-12-09 23:11:18 -05:00
|
|
|
|
2017-09-09 20:44:12 -04:00
|
|
|
/**
|
|
|
|
* netplay_delta_frame_free
|
|
|
|
*
|
|
|
|
* Free a delta frame's dependencies
|
|
|
|
*/
|
|
|
|
void netplay_delta_frame_free(struct delta_frame *delta);
|
|
|
|
|
2017-08-25 14:38:21 -04:00
|
|
|
/**
|
|
|
|
* 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,
|
2017-09-10 09:12:32 -04:00
|
|
|
uint32_t client_num, size_t size, bool must_create, bool must_not_create);
|
2017-09-09 20:44:12 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* netplay_expected_input_size
|
|
|
|
*
|
|
|
|
* Size in words for a given set of devices.
|
|
|
|
*/
|
2017-09-13 11:39:41 -04:00
|
|
|
uint32_t netplay_expected_input_size(netplay_t *netplay, uint32_t devices);
|
2017-08-25 14:38:21 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-DISCOVERY.C
|
|
|
|
**************************************************************/
|
2016-09-30 14:03:18 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_lan_ad_server
|
|
|
|
*
|
|
|
|
* Respond to any LAN ad queries that the netplay server has received.
|
|
|
|
*/
|
|
|
|
bool netplay_lan_ad_server(netplay_t *netplay);
|
2016-09-30 14:03:18 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-FRONTEND.C
|
|
|
|
**************************************************************/
|
2015-12-23 13:25:28 -07:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_load_savestate
|
|
|
|
* @netplay : pointer to netplay object
|
2017-12-11 23:55:31 -08:00
|
|
|
* @serial_info : the savestate being loaded, NULL means
|
2016-12-15 08:42:03 -05:00
|
|
|
* "load it yourself"
|
2017-12-11 23:55:31 -08:00
|
|
|
* @save : Whether to save the provided serial_info
|
2016-12-15 08:42:03 -05:00
|
|
|
* into the frame buffer
|
|
|
|
*
|
|
|
|
* Inform Netplay of a savestate load and send it to the other side
|
|
|
|
**/
|
|
|
|
void netplay_load_savestate(netplay_t *netplay,
|
|
|
|
retro_ctx_serialize_info_t *serial_info, bool save);
|
2016-09-03 07:48:25 +02:00
|
|
|
|
2017-09-10 22:49:25 -04:00
|
|
|
/**
|
|
|
|
* netplay_settings_share_mode
|
|
|
|
*
|
|
|
|
* Get the preferred share mode
|
|
|
|
*/
|
2020-01-02 17:07:03 +01:00
|
|
|
uint8_t netplay_settings_share_mode(unsigned share_digital, unsigned share_analog);
|
2017-09-10 22:49:25 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* input_poll_net
|
|
|
|
*
|
|
|
|
* Poll the network if necessary.
|
|
|
|
*/
|
2020-05-10 00:57:59 +02:00
|
|
|
void input_poll_net(void);
|
2016-09-03 07:48:25 +02:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-HANDSHAKE.C
|
|
|
|
**************************************************************/
|
2016-09-03 07:48:25 +02:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_handshake_init_send
|
|
|
|
*
|
|
|
|
* Initialize our handshake and send the first part of the handshake protocol.
|
|
|
|
*/
|
|
|
|
bool netplay_handshake_init_send(netplay_t *netplay,
|
2020-05-10 00:57:59 +02:00
|
|
|
struct netplay_connection *connection);
|
2016-09-03 07:48:25 +02:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
2016-12-17 14:48:07 -05:00
|
|
|
* netplay_handshake
|
2016-12-15 08:42:03 -05:00
|
|
|
*
|
2016-12-17 14:48:07 -05:00
|
|
|
* Data receiver for all handshake states.
|
2016-12-15 08:42:03 -05:00
|
|
|
*/
|
2016-12-17 14:48:07 -05:00
|
|
|
bool netplay_handshake(netplay_t *netplay,
|
2016-12-15 08:42:03 -05:00
|
|
|
struct netplay_connection *connection, bool *had_input);
|
2016-09-14 23:19:47 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-INIT.C
|
|
|
|
**************************************************************/
|
2016-12-10 20:36:57 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_try_init_serialization
|
|
|
|
*
|
|
|
|
* Try to initialize serialization. For quirky cores.
|
|
|
|
*
|
|
|
|
* Returns true if serialization is now ready, false otherwise.
|
|
|
|
*/
|
|
|
|
bool netplay_try_init_serialization(netplay_t *netplay);
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_wait_and_init_serialization
|
|
|
|
*
|
|
|
|
* Try very hard to initialize serialization, simulating multiple frames if
|
|
|
|
* necessary. For quirky cores.
|
|
|
|
*
|
|
|
|
* Returns true if serialization is now ready, false otherwise.
|
|
|
|
*/
|
|
|
|
bool netplay_wait_and_init_serialization(netplay_t *netplay);
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_new:
|
|
|
|
* @direct_host : Netplay host discovered from scanning.
|
|
|
|
* @server : IP address of server.
|
|
|
|
* @port : Port of server.
|
2016-12-15 23:09:55 -05:00
|
|
|
* @stateless_mode : Shall we run in stateless mode?
|
2016-12-15 08:42:03 -05:00
|
|
|
* @check_frames : Frequency with which to check CRCs.
|
|
|
|
* @cb : Libretro callbacks.
|
|
|
|
* @nat_traversal : If true, attempt NAT traversal.
|
|
|
|
* @nick : Nickname of user.
|
|
|
|
* @quirks : Netplay quirks required for this session.
|
|
|
|
*
|
2017-12-11 23:55:31 -08:00
|
|
|
* Creates a new netplay handle. A NULL server means we're
|
2016-12-15 08:42:03 -05:00
|
|
|
* hosting.
|
|
|
|
*
|
|
|
|
* Returns: new netplay data.
|
|
|
|
*/
|
|
|
|
netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port,
|
2016-12-18 19:27:51 -05:00
|
|
|
bool stateless_mode, int check_frames,
|
2016-12-15 08:42:03 -05:00
|
|
|
const struct retro_callbacks *cb, bool nat_traversal, const char *nick,
|
|
|
|
uint64_t quirks);
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_free
|
|
|
|
* @netplay : pointer to netplay object
|
|
|
|
*
|
|
|
|
* Frees netplay data/
|
|
|
|
*/
|
|
|
|
void netplay_free(netplay_t *netplay);
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-IO.C
|
|
|
|
**************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* netplay_hangup:
|
|
|
|
*
|
|
|
|
* Disconnects an active Netplay connection due to an error
|
|
|
|
*/
|
|
|
|
void netplay_hangup(netplay_t *netplay, struct netplay_connection *connection);
|
|
|
|
|
2017-06-06 21:35:09 -04:00
|
|
|
/**
|
|
|
|
* netplay_delayed_state_change:
|
|
|
|
*
|
|
|
|
* Handle any pending state changes which are ready as of the beginning of the
|
|
|
|
* current frame.
|
|
|
|
*/
|
|
|
|
void netplay_delayed_state_change(netplay_t *netplay);
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_send_cur_input
|
|
|
|
*
|
|
|
|
* Send the current input frame to a given connection.
|
|
|
|
*
|
|
|
|
* Returns true if successful, false otherwise.
|
|
|
|
*/
|
|
|
|
bool netplay_send_cur_input(netplay_t *netplay,
|
|
|
|
struct netplay_connection *connection);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* netplay_send_raw_cmd
|
|
|
|
*
|
|
|
|
* Send a raw Netplay command to the given connection.
|
|
|
|
*
|
|
|
|
* Returns true on success, false on failure.
|
|
|
|
*/
|
2016-12-13 20:16:22 -05:00
|
|
|
bool netplay_send_raw_cmd(netplay_t *netplay,
|
|
|
|
struct netplay_connection *connection, uint32_t cmd, const void *data,
|
|
|
|
size_t size);
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_send_raw_cmd_all
|
|
|
|
*
|
|
|
|
* Send a raw Netplay command to all connections, optionally excluding one
|
|
|
|
* (typically the client that the relevant command came from)
|
|
|
|
*/
|
2016-12-13 20:16:22 -05:00
|
|
|
void netplay_send_raw_cmd_all(netplay_t *netplay,
|
|
|
|
struct netplay_connection *except, uint32_t cmd, const void *data,
|
|
|
|
size_t size);
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_cmd_crc
|
|
|
|
*
|
|
|
|
* Send a CRC command to all active clients.
|
|
|
|
*/
|
|
|
|
bool netplay_cmd_crc(netplay_t *netplay, struct delta_frame *delta);
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_cmd_request_savestate
|
|
|
|
*
|
|
|
|
* Send a savestate request command.
|
|
|
|
*/
|
|
|
|
bool netplay_cmd_request_savestate(netplay_t *netplay);
|
2016-12-13 20:16:22 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_cmd_mode
|
|
|
|
*
|
2017-09-12 16:45:38 -04:00
|
|
|
* Send a mode change request. As a server, the request is to ourself, and so
|
|
|
|
* honored instantly.
|
2016-12-15 08:42:03 -05:00
|
|
|
*/
|
|
|
|
bool netplay_cmd_mode(netplay_t *netplay,
|
|
|
|
enum rarch_netplay_connection_mode mode);
|
2016-12-02 19:49:42 -05:00
|
|
|
|
2016-12-24 15:25:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_cmd_stall
|
|
|
|
*
|
|
|
|
* Send a stall command.
|
|
|
|
*/
|
|
|
|
bool netplay_cmd_stall(netplay_t *netplay,
|
|
|
|
struct netplay_connection *connection,
|
|
|
|
uint32_t frames);
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_poll_net_input
|
|
|
|
*
|
|
|
|
* Poll input from the network
|
|
|
|
*/
|
|
|
|
int netplay_poll_net_input(netplay_t *netplay, bool block);
|
2016-10-10 11:52:54 -04:00
|
|
|
|
2017-02-22 20:34:17 -05:00
|
|
|
/**
|
|
|
|
* netplay_handle_slaves
|
|
|
|
*
|
|
|
|
* Handle any slave connections
|
|
|
|
*/
|
|
|
|
void netplay_handle_slaves(netplay_t *netplay);
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_announce_nat_traversal
|
|
|
|
*
|
|
|
|
* Announce successful NAT traversal.
|
|
|
|
*/
|
|
|
|
void netplay_announce_nat_traversal(netplay_t *netplay);
|
2016-11-30 23:21:34 -05:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_init_nat_traversal
|
|
|
|
*
|
|
|
|
* Initialize the NAT traversal library and try to open a port
|
|
|
|
*/
|
|
|
|
void netplay_init_nat_traversal(netplay_t *netplay);
|
2016-09-25 11:05:50 -04:00
|
|
|
|
2017-09-13 20:51:57 -04:00
|
|
|
/***************************************************************
|
|
|
|
* 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);
|
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/***************************************************************
|
|
|
|
* NETPLAY-SYNC.C
|
|
|
|
**************************************************************/
|
2016-09-25 11:05:50 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_update_unread_ptr
|
|
|
|
*
|
|
|
|
* Update the global unread_ptr and unread_frame_count to correspond to the
|
|
|
|
* earliest unread frame count of any connected player
|
|
|
|
*/
|
|
|
|
void netplay_update_unread_ptr(netplay_t *netplay);
|
2016-09-25 11:05:50 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
2017-09-09 20:44:12 -04:00
|
|
|
* netplay_resolve_input
|
2016-12-15 08:42:03 -05:00
|
|
|
* @netplay : pointer to netplay object
|
2017-09-09 20:44:12 -04:00
|
|
|
* @sim_ptr : frame pointer for which to resolve input
|
2016-12-15 08:42:03 -05:00
|
|
|
* @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.
|
2017-09-09 20:44:12 -04:00
|
|
|
* Returns true if the resolved input changed from the last time it was
|
|
|
|
* resolved.
|
2016-12-15 08:42:03 -05:00
|
|
|
*/
|
2017-09-09 20:44:12 -04:00
|
|
|
bool netplay_resolve_input(netplay_t *netplay, size_t sim_ptr, bool resim);
|
2016-09-25 11:05:50 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_sync_pre_frame
|
|
|
|
* @netplay : pointer to netplay object
|
|
|
|
*
|
|
|
|
* Pre-frame for Netplay synchronization.
|
|
|
|
*/
|
2020-05-10 00:57:59 +02:00
|
|
|
bool netplay_sync_pre_frame(netplay_t *netplay);
|
2016-09-25 11:05:50 -04:00
|
|
|
|
2016-12-15 08:42:03 -05:00
|
|
|
/**
|
|
|
|
* netplay_sync_post_frame
|
|
|
|
* @netplay : pointer to netplay object
|
2016-12-17 16:50:06 -05:00
|
|
|
* @stalled : true if we're currently stalled
|
2016-12-15 08:42:03 -05:00
|
|
|
*
|
|
|
|
* Post-frame for Netplay synchronization.
|
|
|
|
* We check if we have new input and replay from recorded input.
|
|
|
|
*/
|
2016-12-17 16:50:06 -05:00
|
|
|
void netplay_sync_post_frame(netplay_t *netplay, bool stalled);
|
2016-09-25 11:05:50 -04:00
|
|
|
|
2015-12-26 08:10:37 +01:00
|
|
|
#endif
|