Merge pull request #4266 from GregorR/netplay-better-simulation

Better netplay input simulation
This commit is contained in:
Twinaphex 2016-12-18 07:13:52 +01:00 committed by GitHub
commit d604441cea
3 changed files with 39 additions and 7 deletions

View File

@ -822,15 +822,47 @@ static int poll_input(netplay_t *netplay, bool block)
* netplay_simulate_input:
* @netplay : pointer to netplay object
* @sim_ptr : frame index for which to simulate 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.
*/
void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr)
void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr, bool resim)
{
size_t prev = PREV_PTR(netplay->read_ptr);
memcpy(netplay->buffer[sim_ptr].simulated_input_state,
netplay->buffer[prev].real_input_state,
sizeof(netplay->buffer[prev].real_input_state));
struct delta_frame *pframe = &netplay->buffer[prev],
*simframe = &netplay->buffer[sim_ptr];
if (resim)
{
/* 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[0] & keep;
sim_state |= pframe->real_input_state[0] & ~keep;
simframe->simulated_input_state[0] = sim_state;
}
else
{
memcpy(simframe->simulated_input_state,
pframe->real_input_state,
sizeof(pframe->real_input_state));
}
}
@ -874,7 +906,7 @@ static bool netplay_poll(void)
/* Simulate the input if we don't have real input */
if (!netplay_data->buffer[netplay_data->self_ptr].have_remote)
netplay_simulate_input(netplay_data, netplay_data->self_ptr);
netplay_simulate_input(netplay_data, netplay_data->self_ptr, false);
/* Consider stalling */
switch (netplay_data->stall)

View File

@ -280,7 +280,7 @@ static void netplay_net_post_frame(netplay_t *netplay)
/* Simulate this frame's input */
if (netplay->replay_frame_count >= netplay->read_frame_count)
netplay_simulate_input(netplay, netplay->replay_ptr);
netplay_simulate_input(netplay, netplay->replay_ptr, true);
autosave_lock();
core_run();

View File

@ -234,7 +234,7 @@ bool netplay_init_serialization(netplay_t *netplay);
/* Force serialization to be ready by fast-forwarding the core */
bool netplay_wait_and_init_serialization(netplay_t *netplay);
void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr);
void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr, bool resim);
void netplay_log_connection(const struct sockaddr_storage *their_addr,
unsigned slot, const char *nick);