Created
January 26, 2016 20:32
-
-
Save Themaister/efdae15e71b16b00daf3 to your computer and use it in GitHub Desktop.
Blind attempt for analog netplay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 83746a68b4029d207f4eec7d7c3cf3987fa77a71 Mon Sep 17 00:00:00 2001 | |
From: Hans-Kristian Arntzen <[email protected]> | |
Date: Tue, 26 Jan 2016 21:31:58 +0100 | |
Subject: [PATCH] Blind attempt to support RETRO_DEVICE_ANALOG in netplay. | |
--- | |
netplay/netplay.c | 82 ++++++++++++++++++++++++++++++++++------------- | |
netplay/netplay_private.h | 9 +++--- | |
2 files changed, 64 insertions(+), 27 deletions(-) | |
diff --git a/netplay/netplay.c b/netplay/netplay.c | |
index a76dd1e..e14163c 100644 | |
--- a/netplay/netplay.c | |
+++ b/netplay/netplay.c | |
@@ -132,9 +132,9 @@ static bool send_chunk(netplay_t *netplay) | |
**/ | |
static bool get_self_input_state(netplay_t *netplay) | |
{ | |
- uint32_t state = 0; | |
- struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr]; | |
- settings_t *settings = config_get_ptr(); | |
+ uint32_t state[UDP_WORDS_PER_FRAME - 1] = {0}; | |
+ struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr]; | |
+ settings_t *settings = config_get_ptr(); | |
if (!input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL) && netplay->frame_count > 0) | |
{ | |
@@ -148,22 +148,40 @@ static bool get_self_input_state(netplay_t *netplay) | |
int16_t tmp = cb(settings->input.netplay_client_swap_input ? | |
0 : !netplay->port, | |
RETRO_DEVICE_JOYPAD, 0, i); | |
- state |= tmp ? 1 << i : 0; | |
+ state[0] |= tmp ? 1 << i : 0; | |
} | |
- for (i = RARCH_FIRST_CUSTOM_BIND; i < RARCH_FIRST_META_KEY; i++) | |
+ for (i = 0; i < 2; i++) | |
{ | |
- int16_t tmp = cb(settings->input.netplay_client_swap_input ? | |
+ int16_t tmp_x = cb(settings->input.netplay_client_swap_input ? | |
+ 0 : !netplay->port, | |
+ RETRO_DEVICE_ANALOG, i, 0); | |
+ int16_t tmp_y = cb(settings->input.netplay_client_swap_input ? | |
0 : !netplay->port, | |
- RETRO_DEVICE_ANALOG, 0, i); | |
- state |= tmp ? 1 << i : 0; | |
+ RETRO_DEVICE_ANALOG, i, 1); | |
+ state[1 + i] = (uint16_t)tmp_x | (((uint16_t)tmp_y) << 16); | |
} | |
} | |
- memmove(netplay->packet_buffer, netplay->packet_buffer + 2, | |
- sizeof (netplay->packet_buffer) - 2 * sizeof(uint32_t)); | |
- netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * 2] = htonl(netplay->frame_count); | |
- netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * 2 + 1] = htonl(state); | |
+ /* Here we construct the payload format: | |
+ * frame { | |
+ * uint32_t frame_number | |
+ * uint32_t RETRO_DEVICE_JOYPAD state (top 16 bits zero) | |
+ * uint32_t ANALOG state[0] | |
+ * uint32_t ANALOG state[1] | |
+ * } | |
+ * | |
+ * payload { | |
+ * ; To compat packet losses, send input in a sliding window | |
+ * frame redundancy_frames[UDP_FRAME_PACKETS]; | |
+ * } | |
+ */ | |
+ memmove(netplay->packet_buffer, netplay->packet_buffer + UDP_WORDS_PER_FRAME, | |
+ sizeof (netplay->packet_buffer) - UDP_WORDS_PER_FRAME * sizeof(uint32_t)); | |
+ netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME] = htonl(netplay->frame_count); | |
+ netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME + 1] = htonl(state[0]); | |
+ netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME + 2] = htonl(state[1]); | |
+ netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME + 3] = htonl(state[2]); | |
if (!send_chunk(netplay)) | |
{ | |
@@ -172,7 +190,7 @@ static bool get_self_input_state(netplay_t *netplay) | |
return false; | |
} | |
- ptr->self_state = state; | |
+ memcpy(ptr->self_state, state, sizeof(state)); | |
netplay->self_ptr = NEXT_PTR(netplay->self_ptr); | |
return true; | |
} | |
@@ -341,19 +359,21 @@ static void parse_packet(netplay_t *netplay, uint32_t *buffer, unsigned size) | |
{ | |
unsigned i; | |
- for (i = 0; i < size * 2; i++) | |
+ for (i = 0; i < size * UDP_WORDS_PER_FRAME; i++) | |
buffer[i] = ntohl(buffer[i]); | |
for (i = 0; i < size && netplay->read_frame_count <= netplay->frame_count; i++) | |
{ | |
- uint32_t frame = buffer[2 * i + 0]; | |
- uint32_t state = buffer[2 * i + 1]; | |
+ uint32_t frame = buffer[UDP_WORDS_PER_FRAME * i + 0]; | |
+ const uint32_t *state = &buffer[UDP_WORDS_PER_FRAME * i + 1]; | |
if (frame != netplay->read_frame_count) | |
continue; | |
netplay->buffer[netplay->read_ptr].is_simulated = false; | |
- netplay->buffer[netplay->read_ptr].real_input_state = state; | |
+ memcpy(netplay->buffer[netplay->read_ptr].real_input_state, state, | |
+ sizeof(netplay->buffer[netplay->read_ptr].real_input_state)); | |
+ | |
netplay->read_ptr = NEXT_PTR(netplay->read_ptr); | |
netplay->read_frame_count++; | |
netplay->timeout_cnt = 0; | |
@@ -366,8 +386,10 @@ static void simulate_input(netplay_t *netplay) | |
size_t ptr = PREV_PTR(netplay->self_ptr); | |
size_t prev = PREV_PTR(netplay->read_ptr); | |
- netplay->buffer[ptr].simulated_input_state = | |
- netplay->buffer[prev].real_input_state; | |
+ memcpy(netplay->buffer[ptr].simulated_input_state, | |
+ netplay->buffer[prev].real_input_state, | |
+ sizeof(netplay->buffer[prev].real_input_state)); | |
+ | |
netplay->buffer[ptr].is_simulated = true; | |
netplay->buffer[ptr].used_real = false; | |
} | |
@@ -400,7 +422,7 @@ static bool netplay_poll(netplay_t *netplay) | |
{ | |
netplay->buffer[0].used_real = true; | |
netplay->buffer[0].is_simulated = false; | |
- netplay->buffer[0].real_input_state = 0; | |
+ memset(netplay->buffer[0].real_input_state, 0, sizeof(netplay->buffer[0].real_input_state)); | |
netplay->read_ptr = NEXT_PTR(netplay->read_ptr); | |
netplay->read_frame_count++; | |
return true; | |
@@ -421,7 +443,7 @@ static bool netplay_poll(netplay_t *netplay) | |
uint32_t first_read = netplay->read_frame_count; | |
do | |
{ | |
- uint32_t buffer[UDP_FRAME_PACKETS * 2]; | |
+ uint32_t buffer[UDP_FRAME_PACKETS * UDP_WORDS_PER_FRAME]; | |
if (!receive_data(netplay, buffer, sizeof(buffer))) | |
{ | |
warn_hangup(); | |
@@ -515,7 +537,8 @@ static int16_t netplay_input_state(netplay_t *netplay, bool port, unsigned devic | |
{ | |
size_t ptr = netplay->is_replay ? | |
netplay->tmp_ptr : PREV_PTR(netplay->self_ptr); | |
- uint16_t curr_input_state = netplay->buffer[ptr].self_state; | |
+ | |
+ const uint32_t *curr_input_state = netplay->buffer[ptr].self_state; | |
if (netplay->port == (netplay_flip_port(netplay, port) ? 1 : 0)) | |
{ | |
@@ -525,7 +548,20 @@ static int16_t netplay_input_state(netplay_t *netplay, bool port, unsigned devic | |
curr_input_state = netplay->buffer[ptr].real_input_state; | |
} | |
- return ((1 << id) & curr_input_state) ? 1 : 0; | |
+ switch (device) | |
+ { | |
+ case RETRO_DEVICE_JOYPAD: | |
+ return ((1 << id) & curr_input_state[0]) ? 1 : 0; | |
+ | |
+ case RETRO_DEVICE_ANALOG: | |
+ { | |
+ uint32_t state = curr_input_state[1 + idx]; | |
+ return (int16_t)(uint16_t)(state >> (id * 16)); | |
+ } | |
+ | |
+ default: | |
+ return 0; | |
+ } | |
} | |
int16_t input_state_net(unsigned port, unsigned device, | |
diff --git a/netplay/netplay_private.h b/netplay/netplay_private.h | |
index 5025e70..de6497b 100644 | |
--- a/netplay/netplay_private.h | |
+++ b/netplay/netplay_private.h | |
@@ -34,6 +34,7 @@ | |
#endif | |
#define UDP_FRAME_PACKETS 16 | |
+#define UDP_WORDS_PER_FRAME 4 /* Allows us to send 128 bits worth of state per frame. */ | |
#define MAX_SPECTATORS 16 | |
#define RARCH_DEFAULT_PORT 55435 | |
@@ -44,9 +45,9 @@ struct delta_frame | |
{ | |
void *state; | |
- uint16_t real_input_state; | |
- uint16_t simulated_input_state; | |
- uint16_t self_state; | |
+ uint32_t real_input_state[UDP_WORDS_PER_FRAME - 1]; | |
+ uint32_t simulated_input_state[UDP_WORDS_PER_FRAME - 1]; | |
+ uint32_t self_state[UDP_WORDS_PER_FRAME - 1]; | |
bool is_simulated; | |
bool used_real; | |
@@ -95,7 +96,7 @@ struct netplay | |
/* To compat UDP packet loss we also send | |
* old data along with the packets. */ | |
- uint32_t packet_buffer[UDP_FRAME_PACKETS * 2]; | |
+ uint32_t packet_buffer[UDP_FRAME_PACKETS * UDP_WORDS_PER_FRAME]; | |
uint32_t frame_count; | |
uint32_t read_frame_count; | |
uint32_t other_frame_count; | |
-- | |
2.7.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment