Netplay: Drop-in at any time
This commit is contained in:
parent
68e7fe0209
commit
f8a06969a8
|
@ -201,12 +201,6 @@ typedef struct {
|
|||
* functions during the game. All callback functions must be implemented.
|
||||
*/
|
||||
typedef struct {
|
||||
/*
|
||||
* begin_game callback - This callback has been deprecated. You must
|
||||
* implement it, but should ignore the 'game' parameter.
|
||||
*/
|
||||
bool (__cdecl *begin_game)(void* context, const char *game);
|
||||
|
||||
/*
|
||||
* save_game_state - The client should allocate a buffer, copy the
|
||||
* entire contents of the current game state into it, and copy the
|
||||
|
@ -340,10 +334,8 @@ typedef struct GGPONetworkStats {
|
|||
*/
|
||||
GGPO_API GGPOErrorCode __cdecl ggpo_start_session(GGPOSession **session,
|
||||
GGPOSessionCallbacks *cb,
|
||||
const char *game,
|
||||
int num_players,
|
||||
int input_size,
|
||||
unsigned short localport,
|
||||
int maxPrediction);
|
||||
|
||||
|
||||
|
@ -389,7 +381,6 @@ GGPO_API GGPOErrorCode __cdecl ggpo_add_player(GGPOSession *session,
|
|||
*/
|
||||
GGPO_API GGPOErrorCode __cdecl ggpo_start_synctest(GGPOSession **session,
|
||||
GGPOSessionCallbacks *cb,
|
||||
char *game,
|
||||
int num_players,
|
||||
int input_size,
|
||||
int frames);
|
||||
|
@ -421,12 +412,10 @@ GGPO_API GGPOErrorCode __cdecl ggpo_start_synctest(GGPOSession **session,
|
|||
*/
|
||||
GGPO_API GGPOErrorCode __cdecl ggpo_start_spectating(GGPOSession **session,
|
||||
GGPOSessionCallbacks *cb,
|
||||
const char *game,
|
||||
int num_players,
|
||||
int input_size,
|
||||
unsigned short local_port,
|
||||
char *host_ip,
|
||||
unsigned short host_port);
|
||||
ENetPeer* host);
|
||||
|
||||
|
||||
/*
|
||||
* ggpo_close_session --
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
static const int RECOMMENDATION_INTERVAL = 120;
|
||||
|
||||
Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb,
|
||||
const char *gamename,
|
||||
uint16 localport,
|
||||
int num_players,
|
||||
int input_size, int nframes) :
|
||||
_num_players(num_players),
|
||||
|
@ -39,11 +37,6 @@ Peer2PeerBackend::Peer2PeerBackend(GGPOSessionCallbacks *cb,
|
|||
for (int i = 0; i < ARRAY_SIZE(_local_connect_status); i++) {
|
||||
_local_connect_status[i].last_frame = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preload the ROM
|
||||
*/
|
||||
_callbacks.begin_game(_callbacks.context, gamename);
|
||||
}
|
||||
|
||||
Peer2PeerBackend::~Peer2PeerBackend()
|
||||
|
@ -299,6 +292,11 @@ Peer2PeerBackend::AddPlayer(GGPOPlayer *player,
|
|||
if (player->type == GGPO_PLAYERTYPE_REMOTE) {
|
||||
AddRemotePlayer(player->u.remote.peer, queue);
|
||||
}
|
||||
|
||||
// no other players in this session?
|
||||
if (player->type == GGPO_PLAYERTYPE_LOCAL && _num_players == 1)
|
||||
_synchronizing = false;
|
||||
|
||||
return GGPO_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
class Peer2PeerBackend final : public GGPOSession
|
||||
{
|
||||
public:
|
||||
Peer2PeerBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, int nframes);
|
||||
Peer2PeerBackend(GGPOSessionCallbacks *cb, int num_players, int input_size, int nframes);
|
||||
virtual ~Peer2PeerBackend();
|
||||
|
||||
|
||||
|
|
|
@ -7,16 +7,8 @@
|
|||
|
||||
#include "spectator.h"
|
||||
|
||||
SpectatorBackend::SpectatorBackend(GGPOSessionCallbacks *cb,
|
||||
const char* gamename,
|
||||
uint16 localport,
|
||||
int num_players,
|
||||
int input_size,
|
||||
char *hostip,
|
||||
u_short hostport) :
|
||||
_num_players(num_players),
|
||||
_input_size(input_size),
|
||||
_next_input_to_send(0)
|
||||
SpectatorBackend::SpectatorBackend(GGPOSessionCallbacks* cb, int num_players, int input_size, ENetPeer* peer)
|
||||
: _num_players(num_players), _input_size(input_size), _next_input_to_send(0)
|
||||
{
|
||||
_callbacks = *cb;
|
||||
_synchronizing = true;
|
||||
|
@ -37,11 +29,6 @@ SpectatorBackend::SpectatorBackend(GGPOSessionCallbacks *cb,
|
|||
*/
|
||||
//_host.Init(&_udp, _poll, 0, hostip, hostport, NULL);
|
||||
_host.Synchronize();
|
||||
|
||||
/*
|
||||
* Preload the ROM
|
||||
*/
|
||||
_callbacks.begin_game(_callbacks.context, gamename);
|
||||
}
|
||||
|
||||
SpectatorBackend::~SpectatorBackend()
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
class SpectatorBackend final : public GGPOSession {
|
||||
public:
|
||||
SpectatorBackend(GGPOSessionCallbacks *cb, const char *gamename, uint16 localport, int num_players, int input_size, char *hostip, u_short hostport);
|
||||
SpectatorBackend(GGPOSessionCallbacks *cb, int num_players, int input_size, ENetPeer* peer);
|
||||
virtual ~SpectatorBackend();
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "synctest.h"
|
||||
|
||||
SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb,
|
||||
char *gamename,
|
||||
int frames,
|
||||
int num_players) :
|
||||
_sync(NULL, MAX_PREDICTION_FRAMES)
|
||||
|
@ -21,7 +20,6 @@ SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb,
|
|||
_running = false;
|
||||
_logfp = NULL;
|
||||
_current_input.erase();
|
||||
strcpy_s(_game, gamename);
|
||||
|
||||
/*
|
||||
* Initialize the synchronziation layer
|
||||
|
@ -30,11 +28,6 @@ SyncTestBackend::SyncTestBackend(GGPOSessionCallbacks *cb,
|
|||
config.callbacks = _callbacks;
|
||||
config.num_prediction_frames = MAX_PREDICTION_FRAMES;
|
||||
_sync.Init(config);
|
||||
|
||||
/*
|
||||
* Preload the ROM
|
||||
*/
|
||||
_callbacks.begin_game(_callbacks.context, gamename);
|
||||
}
|
||||
|
||||
SyncTestBackend::~SyncTestBackend()
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
class SyncTestBackend final : public GGPOSession {
|
||||
public:
|
||||
SyncTestBackend(GGPOSessionCallbacks *cb, char *gamename, int frames, int num_players);
|
||||
SyncTestBackend(GGPOSessionCallbacks *cb, int frames, int num_players);
|
||||
virtual ~SyncTestBackend();
|
||||
|
||||
virtual GGPOErrorCode DoPoll();
|
||||
|
@ -52,7 +52,6 @@ protected:
|
|||
bool _rollingback;
|
||||
bool _running;
|
||||
FILE *_logfp;
|
||||
char _game[128];
|
||||
|
||||
GameInput _current_input;
|
||||
GameInput _last_input;
|
||||
|
|
|
@ -28,6 +28,7 @@ void Log(const char *fmt, ...)
|
|||
|
||||
void Logv(const char *fmt, va_list args)
|
||||
{
|
||||
#if 1
|
||||
if (!Platform::GetConfigBool("ggpo.log") || Platform::GetConfigBool("ggpo.log.ignore")) {
|
||||
return;
|
||||
}
|
||||
|
@ -36,6 +37,9 @@ void Logv(const char *fmt, va_list args)
|
|||
fopen_s(&logfile, logbuf, "w");
|
||||
}
|
||||
Logv(logfile, fmt, args);
|
||||
#else
|
||||
vfprintf(stderr, fmt, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Logv(FILE *fp, const char *fmt, va_list args)
|
||||
|
|
|
@ -40,15 +40,11 @@ ggpo_logv(GGPOSession *ggpo, const char *fmt, va_list args)
|
|||
GGPOErrorCode
|
||||
ggpo_start_session(GGPOSession **session,
|
||||
GGPOSessionCallbacks *cb,
|
||||
const char *game,
|
||||
int num_players,
|
||||
int input_size,
|
||||
unsigned short localport,
|
||||
int maxPrediction)
|
||||
{
|
||||
*session= new Peer2PeerBackend(cb,
|
||||
game,
|
||||
localport,
|
||||
num_players,
|
||||
input_size,
|
||||
maxPrediction);
|
||||
|
@ -71,12 +67,11 @@ ggpo_add_player(GGPOSession *ggpo,
|
|||
GGPOErrorCode
|
||||
ggpo_start_synctest(GGPOSession **ggpo,
|
||||
GGPOSessionCallbacks *cb,
|
||||
char *game,
|
||||
int num_players,
|
||||
int input_size,
|
||||
int frames)
|
||||
{
|
||||
*ggpo = new SyncTestBackend(cb, game, frames, num_players);
|
||||
*ggpo = new SyncTestBackend(cb, frames, num_players);
|
||||
return GGPO_OK;
|
||||
}
|
||||
|
||||
|
@ -209,19 +204,10 @@ ggpo_set_disconnect_notify_start(GGPOSession *ggpo, int timeout)
|
|||
|
||||
GGPOErrorCode ggpo_start_spectating(GGPOSession **session,
|
||||
GGPOSessionCallbacks *cb,
|
||||
const char *game,
|
||||
int num_players,
|
||||
int input_size,
|
||||
unsigned short local_port,
|
||||
char *host_ip,
|
||||
unsigned short host_port)
|
||||
ENetPeer* host)
|
||||
{
|
||||
*session= new SpectatorBackend(cb,
|
||||
game,
|
||||
local_port,
|
||||
num_players,
|
||||
input_size,
|
||||
host_ip,
|
||||
host_port);
|
||||
return GGPO_OK;
|
||||
*session = new SpectatorBackend(cb, num_players, input_size, host);
|
||||
return GGPO_OK;
|
||||
}
|
||||
|
|
1071
src/core/netplay.cpp
1071
src/core/netplay.cpp
File diff suppressed because it is too large
Load Diff
|
@ -78,8 +78,6 @@ SystemBootParameters::~SystemBootParameters() = default;
|
|||
|
||||
namespace System {
|
||||
static std::optional<ExtendedSaveStateInfo> InternalGetExtendedSaveStateInfo(ByteStream* stream);
|
||||
static bool InternalSaveState(ByteStream* state, u32 screenshot_size = 256,
|
||||
u32 compression_method = SAVE_STATE_HEADER::COMPRESSION_TYPE_NONE);
|
||||
|
||||
static bool LoadEXE(const char* filename);
|
||||
|
||||
|
@ -95,7 +93,6 @@ static void InternalReset();
|
|||
static void ClearRunningGame();
|
||||
static void DestroySystem();
|
||||
static std::string GetMediaPathFromSaveState(const char* path);
|
||||
static bool DoLoadState(ByteStream* stream, bool force_software_renderer, bool update_display);
|
||||
static bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display, bool is_memory_state);
|
||||
static void WrappedRunFrame();
|
||||
static void RunFramesToNow();
|
||||
|
@ -1019,7 +1016,7 @@ bool System::LoadState(const char* filename)
|
|||
|
||||
SaveUndoLoadState();
|
||||
|
||||
if (!DoLoadState(stream.get(), false, true))
|
||||
if (!LoadStateFromStream(stream.get(), true))
|
||||
{
|
||||
Host::ReportFormattedErrorAsync(
|
||||
"Load State Error", Host::TranslateString("OSDMessage", "Loading state from '%s' failed. Resetting."), filename);
|
||||
|
@ -1057,7 +1054,7 @@ bool System::SaveState(const char* filename, bool backup_existing_save)
|
|||
Log_InfoPrintf("Saving state to '%s'...", filename);
|
||||
|
||||
const u32 screenshot_size = 256;
|
||||
const bool result = InternalSaveState(stream.get(), screenshot_size,
|
||||
const bool result = SaveStateToStream(stream.get(), screenshot_size,
|
||||
g_settings.compress_save_states ? SAVE_STATE_HEADER::COMPRESSION_TYPE_ZSTD :
|
||||
SAVE_STATE_HEADER::COMPRESSION_TYPE_NONE);
|
||||
if (!result)
|
||||
|
@ -1312,7 +1309,7 @@ bool System::BootSystem(SystemBootParameters parameters)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!DoLoadState(stream.get(), false, true))
|
||||
if (!LoadStateFromStream(stream.get(), true))
|
||||
{
|
||||
DestroySystem();
|
||||
return false;
|
||||
|
@ -1573,7 +1570,7 @@ void System::RecreateSystem()
|
|||
|
||||
const bool was_paused = System::IsPaused();
|
||||
std::unique_ptr<ByteStream> stream = ByteStream::CreateGrowableMemoryStream(nullptr, 8 * 1024);
|
||||
if (!System::InternalSaveState(stream.get(), 0, SAVE_STATE_HEADER::COMPRESSION_TYPE_NONE) || !stream->SeekAbsolute(0))
|
||||
if (!System::SaveStateToStream(stream.get(), 0, SAVE_STATE_HEADER::COMPRESSION_TYPE_NONE) || !stream->SeekAbsolute(0))
|
||||
{
|
||||
Host::ReportErrorAsync("Error", "Failed to save state before system recreation. Shutting down.");
|
||||
DestroySystem();
|
||||
|
@ -1589,7 +1586,7 @@ void System::RecreateSystem()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!DoLoadState(stream.get(), false, false))
|
||||
if (!LoadStateFromStream(stream.get(), false))
|
||||
{
|
||||
DestroySystem();
|
||||
return;
|
||||
|
@ -1890,7 +1887,7 @@ std::string System::GetMediaPathFromSaveState(const char* path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool update_display)
|
||||
bool System::LoadStateFromStream(ByteStream* state, bool update_display)
|
||||
{
|
||||
Assert(IsValid());
|
||||
|
||||
|
@ -2043,7 +2040,7 @@ bool System::DoLoadState(ByteStream* state, bool force_software_renderer, bool u
|
|||
return true;
|
||||
}
|
||||
|
||||
bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 */,
|
||||
bool System::SaveStateToStream(ByteStream* state, u32 screenshot_size /* = 256 */,
|
||||
u32 compression_method /* = SAVE_STATE_HEADER::COMPRESSION_TYPE_NONE*/)
|
||||
{
|
||||
if (IsShutdown())
|
||||
|
@ -3801,7 +3798,7 @@ bool System::UndoLoadState()
|
|||
Assert(IsValid());
|
||||
|
||||
m_undo_load_state->SeekAbsolute(0);
|
||||
if (!DoLoadState(m_undo_load_state.get(), false, true))
|
||||
if (!LoadStateFromStream(m_undo_load_state.get(), true))
|
||||
{
|
||||
Host::ReportErrorAsync("Error", "Failed to load undo state, resetting system.");
|
||||
m_undo_load_state.reset();
|
||||
|
@ -3820,7 +3817,7 @@ bool System::SaveUndoLoadState()
|
|||
m_undo_load_state.reset();
|
||||
|
||||
m_undo_load_state = ByteStream::CreateGrowableMemoryStream(nullptr, System::MAX_SAVE_STATE_SIZE);
|
||||
if (!InternalSaveState(m_undo_load_state.get()))
|
||||
if (!SaveStateToStream(m_undo_load_state.get()))
|
||||
{
|
||||
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "Failed to save undo load state."), 15.0f);
|
||||
m_undo_load_state.reset();
|
||||
|
|
|
@ -235,6 +235,8 @@ struct MemorySaveState
|
|||
};
|
||||
bool SaveMemoryState(MemorySaveState* mss);
|
||||
bool LoadMemoryState(const MemorySaveState& mss);
|
||||
bool LoadStateFromStream(ByteStream* stream, bool update_display);
|
||||
bool SaveStateToStream(ByteStream* state, u32 screenshot_size = 256, u32 compression_method = 0);
|
||||
|
||||
/// Runs the VM until the CPU execution is canceled.
|
||||
void Execute();
|
||||
|
|
Loading…
Reference in New Issue