mirror of
https://github.com/libretro/RetroArch
synced 2025-01-31 06:32:48 +00:00
Better netplay input simulation
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.
This commit is contained in:
parent
1c0d8f3927
commit
1245d1b5dd
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user