Netplay: Hand off full buffers to GGPO

This commit is contained in:
Stenzek 2023-04-12 00:26:57 +10:00
parent f104b91a3e
commit 7cf4ed2d30
1 changed files with 30 additions and 27 deletions

View File

@ -21,6 +21,8 @@ Log_SetChannel(Netplay);
namespace Netplay { namespace Netplay {
using SaveStateBuffer = std::unique_ptr<System::MemorySaveState>;
struct Input struct Input
{ {
u32 button_data; u32 button_data;
@ -67,7 +69,7 @@ static GGPOPlayerHandle s_local_handle = GGPO_INVALID_HANDLE;
static GGPONetworkStats s_last_net_stats{}; static GGPONetworkStats s_last_net_stats{};
static GGPOSession* s_ggpo = nullptr; static GGPOSession* s_ggpo = nullptr;
static std::deque<System::MemorySaveState> s_netplay_states; static std::deque<SaveStateBuffer> s_save_buffer_pool;
static std::array<std::array<float, 32>, NUM_CONTROLLER_AND_CARD_PORTS> s_net_input; static std::array<std::array<float, 32>, NUM_CONTROLLER_AND_CARD_PORTS> s_net_input;
@ -139,6 +141,7 @@ void Netplay::Close()
{ {
ggpo_close_session(s_ggpo); ggpo_close_session(s_ggpo);
s_ggpo = nullptr; s_ggpo = nullptr;
s_save_buffer_pool.clear();
s_local_handle = GGPO_INVALID_HANDLE; s_local_handle = GGPO_INVALID_HANDLE;
s_max_pred = 0; s_max_pred = 0;
@ -344,7 +347,7 @@ void Netplay::StopNetplaySession()
{ {
if (!IsActive()) if (!IsActive())
return; return;
s_netplay_states.clear();
Close(); Close();
} }
@ -404,37 +407,42 @@ bool Netplay::NpAdvFrameCb(void* ctx, int flags)
return true; return true;
} }
bool Netplay::NpSaveFrameCb(void* ctx, uint8_t** buffer, int* len, int* checksum, int frame) bool Netplay::NpSaveFrameCb(void* ctx, unsigned char** buffer, int* len, int* checksum, int frame)
{ {
bool result = false; SaveStateBuffer our_buffer;
// give ggpo something so it doesnt complain. if (s_save_buffer_pool.empty())
u8 dummyData = 43;
*len = sizeof(u8);
*buffer = (unsigned char*)malloc(*len);
if (!*buffer)
return false;
memcpy(*buffer, &dummyData, *len);
// store state for later.
int pred = Netplay::GetMaxPrediction();
if (frame < pred && s_netplay_states.size() < pred)
{ {
System::MemorySaveState save; our_buffer = std::make_unique<System::MemorySaveState>();
result = System::SaveMemoryState(&save);
s_netplay_states.push_back(std::move(save));
} }
else else
{ {
// reuse streams our_buffer = std::move(s_save_buffer_pool.back());
result = System::SaveMemoryState(&s_netplay_states[frame % pred]); s_save_buffer_pool.pop_back();
} }
return result;
if (!System::SaveMemoryState(our_buffer.get()))
{
s_save_buffer_pool.push_back(std::move(our_buffer));
return false;
}
*len = sizeof(System::MemorySaveState);
*buffer = reinterpret_cast<unsigned char*>(our_buffer.release());
return true;
} }
bool Netplay::NpLoadFrameCb(void* ctx, uint8_t* buffer, int len, int rb_frames, int frame_to_load) bool Netplay::NpLoadFrameCb(void* ctx, unsigned char* buffer, int len, int rb_frames, int frame_to_load)
{ {
// Disable Audio For upcoming rollback // Disable Audio For upcoming rollback
SPU::SetAudioOutputMuted(true); SPU::SetAudioOutputMuted(true);
return System::LoadMemoryState(s_netplay_states[frame_to_load % Netplay::GetMaxPrediction()]);
return System::LoadMemoryState(*reinterpret_cast<const System::MemorySaveState*>(buffer));
}
void Netplay::NpFreeBuffCb(void* ctx, void* buffer)
{
SaveStateBuffer our_buffer(reinterpret_cast<System::MemorySaveState*>(buffer));
s_save_buffer_pool.push_back(std::move(our_buffer));
} }
bool Netplay::NpOnEventCb(void* ctx, GGPOEvent* ev) bool Netplay::NpOnEventCb(void* ctx, GGPOEvent* ev)
@ -494,8 +502,3 @@ bool Netplay::NpOnEventCb(void* ctx, GGPOEvent* ev)
} }
return true; return true;
} }
void Netplay::NpFreeBuffCb(void* ctx, void* buffer)
{
free(buffer);
}