Unsurprisingly, netplay and runahead are wildly incompatible; both rely
on internal rewinding, without communicating this fact to each other.
Somewhat more surprisingly, netplay already has all the infrastructure
for negative input latency, as it's structurally the same as receiving
delayed input from a peer. This patch makes the two features
"compatible" by disabling runahead per se when netplay is active, and
using runahead's configuration to adjust netplay's own input latency
feature, which is now allowed to be negative. The effect is mostly the
same (modulo the second core support), and it doesn't confuse netplay
peers.
This commit adds support for temporary desync in netplay. When frontend
features that can't be truly synced, in particular rewind, are used,
netplay is momentarily disabled. As soon as the feature finished, e.g. a
rewind ending, netplay resumes with a state load. For rewind, netplay
peers won't actually experience the effect of rewind, but they will load
the rewound state.
This patch transfers core_reset across netplay. Resets effectively
worked before thanks to check_frames, but this makes resets work even
without check_frames, and in particular should allow resets to force
sync in savestateless cores, bringing them one step closer to actually
being usable by non-experts.
The idea:
* Use a fixed number of delay_frames (eventually to be fixed at 120,
currently still uses the config variable, 0 will still be an option)
* Determine how long it takes to simulate a frame.
* Stall only if resimulating the intervening frames would be
sufficiently annoying (currently fixed at three frames worth of
time)
Because clients always try to catch up, the actual frame delay works out
automatically to be minimally zero and maximally the latency. If one
client is underpowered but the other is fine, the powerful one will
automatically take up the slack. Seems like the most reasonable system.
Adding a key to toggle between playing and spectating. This key takes
the place of the previous flip key, although player flipping does
continue to work (and must be rebound if you still want it)