For Qt GUI, added netplay client state load request functionality.
This commit is contained in:
parent
55654f7191
commit
5a0898ccbe
|
@ -42,6 +42,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
static uint32_t opsCrc32 = 0;
|
||||
static void *traceRegistrationHandle = nullptr;
|
||||
static bool serverRequestedStateLoad = false;
|
||||
|
||||
struct NetPlayFrameData
|
||||
{
|
||||
|
@ -678,6 +679,46 @@ void NetPlayServer::serverProcessMessage( NetPlayClient *client, void *msgBuf, s
|
|||
sendMsg( client, &errorMsg, errorMsg.hdr.msgSize, [&errorMsg]{ errorMsg.toNetworkByteOrder(); } );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NETPLAY_SYNC_STATE_RESP:
|
||||
{
|
||||
bool acceptStateLoadReq = false;
|
||||
|
||||
FCEU_printf("Sync state request received from client '%s'\n", client->userName.toLocal8Bit().constData());
|
||||
|
||||
if (allowClientStateLoadReq)
|
||||
{
|
||||
QString msgBoxTxt = tr("Client '") + client->userName + tr("' has requested to load a new state:\n");
|
||||
msgBoxTxt += tr("\nDo you want to load it?");
|
||||
int ans = QMessageBox::question( consoleWindow, tr("Client State Load Request"), msgBoxTxt, QMessageBox::Yes | QMessageBox::No );
|
||||
|
||||
if (ans == QMessageBox::Yes)
|
||||
{
|
||||
acceptStateLoadReq = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptStateLoadReq)
|
||||
{
|
||||
char *stateData = &static_cast<char*>(msgBuf)[ sizeof(netPlayMsgHdr) ];
|
||||
|
||||
FCEU_printf("Sync state request accepted\n");
|
||||
|
||||
EMUFILE_MEMORY em( stateData, msgSize );
|
||||
|
||||
FCEU_WRAPPER_LOCK();
|
||||
serverRequestedStateLoad = true;
|
||||
FCEUSS_LoadFP( &em, SSLOADPARAM_NOBACKUP );
|
||||
serverRequestedStateLoad = false;
|
||||
FCEU_WRAPPER_UNLOCK();
|
||||
|
||||
opsCrc32 = 0;
|
||||
netPlayFrameData.reset();
|
||||
inputClear();
|
||||
resyncAllClients();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Unknown Msg: %08X\n", msgId);
|
||||
break;
|
||||
|
@ -1088,6 +1129,44 @@ int NetPlayClient::requestRomLoad( const char *romPath )
|
|||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int NetPlayClient::requestStateLoad(EMUFILE *is)
|
||||
{
|
||||
size_t dataSize;
|
||||
char *dataBuf;
|
||||
netPlayMsgHdr hdr(NETPLAY_SYNC_STATE_RESP);
|
||||
|
||||
dataSize = is->size();
|
||||
hdr.msgSize += dataSize;
|
||||
|
||||
if (dataSize == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
dataBuf = static_cast<char*>(::malloc(dataSize));
|
||||
|
||||
if (dataBuf == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
is->fseek( 0, SEEK_SET );
|
||||
size_t readResult = is->fread( dataBuf, dataSize );
|
||||
|
||||
if (readResult != dataSize )
|
||||
{
|
||||
printf("Read Error\n");
|
||||
}
|
||||
printf("Sending Client ROM Sync Request\n");
|
||||
|
||||
hdr.toNetworkByteOrder();
|
||||
sock->write( reinterpret_cast<const char*>(&hdr), sizeof(netPlayMsgHdr));
|
||||
sock->write( reinterpret_cast<const char*>(dataBuf), dataSize );
|
||||
|
||||
::free(dataBuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void NetPlayClient::recordPingResult( uint64_t delay_ms )
|
||||
{
|
||||
pingNumSamples++;
|
||||
|
@ -1313,7 +1392,9 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
|
|||
EMUFILE_MEMORY em( stateData, msgSize );
|
||||
|
||||
FCEU_WRAPPER_LOCK();
|
||||
serverRequestedStateLoad = true;
|
||||
FCEUSS_LoadFP( &em, SSLOADPARAM_NOBACKUP );
|
||||
serverRequestedStateLoad = false;
|
||||
FCEU_WRAPPER_UNLOCK();
|
||||
|
||||
opsCrc32 = 0;
|
||||
|
@ -1447,11 +1528,17 @@ NetPlayHostDialog::NetPlayHostDialog(QWidget *parent)
|
|||
grid->addWidget( lbl, 0, 0, 1, 1 );
|
||||
grid->addWidget( frameLeadSpinBox, 0, 1, 1, 1 );
|
||||
|
||||
bool romLoadReqEna = false;
|
||||
allowClientRomReqCBox = new QCheckBox(tr("Allow Client ROM Load Requests"));
|
||||
grid->addWidget( allowClientRomReqCBox, 1, 0, 1, 2 );
|
||||
g_config->getOption("SDL.NetPlayHostAllowClientRomLoadReq", &romLoadReqEna);
|
||||
allowClientRomReqCBox->setChecked(romLoadReqEna);
|
||||
|
||||
bool stateLoadReqEna = false;
|
||||
allowClientStateReqCBox = new QCheckBox(tr("Allow Client State Load Requests"));
|
||||
grid->addWidget( allowClientStateReqCBox, 2, 0, 1, 2 );
|
||||
g_config->getOption("SDL.NetPlayHostAllowClientStateLoadReq", &stateLoadReqEna);
|
||||
allowClientStateReqCBox->setChecked(stateLoadReqEna);
|
||||
|
||||
startButton = new QPushButton( tr("Start") );
|
||||
startButton->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
|
||||
|
@ -1511,6 +1598,9 @@ void NetPlayHostDialog::onStartClicked(void)
|
|||
server->setAllowClientRomLoadRequest( allowClientRomReqCBox->isChecked() );
|
||||
server->setAllowClientStateLoadRequest( allowClientStateReqCBox->isChecked() );
|
||||
|
||||
g_config->setOption("SDL.NetPlayHostAllowClientRomLoadReq", allowClientRomReqCBox->isChecked() );
|
||||
g_config->setOption("SDL.NetPlayHostAllowClientStateLoadReq", allowClientStateReqCBox->isChecked() );
|
||||
|
||||
bool listenSucceeded = server->listen( QHostAddress::Any, netPort );
|
||||
|
||||
if (listenSucceeded)
|
||||
|
@ -2217,3 +2307,18 @@ void NetPlayOnFrameBegin()
|
|||
//printf("Frame: %u Ops:%08X Ram:%08X\n", data.frameNum, data.opsCrc32, data.ramCrc32 );
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
bool NetPlayStateLoadReq(EMUFILE* is)
|
||||
{
|
||||
auto* client = NetPlayClient::GetInstance();
|
||||
|
||||
bool shouldLoad = (client == nullptr) || serverRequestedStateLoad;
|
||||
|
||||
printf("NetPlay Load State: %i\n", shouldLoad);
|
||||
|
||||
if ( (client != nullptr) && !serverRequestedStateLoad)
|
||||
{ // Send state to host
|
||||
client->requestStateLoad(is);
|
||||
}
|
||||
return !shouldLoad;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -164,8 +164,8 @@ class NetPlayServer : public QTcpServer
|
|||
uint32_t maxLeadFrames = 10u;
|
||||
uint32_t clientWaitCounter = 0;
|
||||
uint32_t inputFrameCount = 0;
|
||||
bool allowClientRomLoadReq = true;
|
||||
bool allowClientStateLoadReq = true;
|
||||
bool allowClientRomLoadReq = false;
|
||||
bool allowClientStateLoadReq = false;
|
||||
|
||||
public:
|
||||
signals:
|
||||
|
@ -198,6 +198,7 @@ class NetPlayClient : public QObject
|
|||
void forceDisconnect();
|
||||
bool flushData();
|
||||
int requestRomLoad( const char *romPath );
|
||||
int requestStateLoad(EMUFILE* is);
|
||||
|
||||
QTcpSocket* createSocket(void);
|
||||
void setSocket(QTcpSocket *s);
|
||||
|
@ -426,6 +427,7 @@ int NetPlayFrameWait(void);
|
|||
void NetPlayOnFrameBegin(void);
|
||||
void NetPlayReadInputFrame(uint8_t* joy);
|
||||
void NetPlayCloseSession(void);
|
||||
bool NetPlayStateLoadReq(EMUFILE* is);
|
||||
void NetPlayTraceInstruction(uint8_t *opcode, int size);
|
||||
void openNetPlayHostDialog(QWidget* parent = nullptr);
|
||||
void openNetPlayJoinDialog(QWidget* parent = nullptr);
|
||||
|
|
|
@ -633,6 +633,8 @@ InitConfig()
|
|||
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
|
||||
config->addOption("port", "SDL.NetworkPort", NetPlayServer::DefaultPort);
|
||||
config->addOption("players", "SDL.NetworkPlayers", 1);
|
||||
config->addOption("SDL.NetPlayHostAllowClientRomLoadReq", 0);
|
||||
config->addOption("SDL.NetPlayHostAllowClientStateLoadReq", 0);
|
||||
|
||||
// input configuration options
|
||||
config->addOption("input1", "SDL.Input.0", "GamePad.0");
|
||||
|
|
|
@ -639,6 +639,11 @@ int FCEUSS_LoadFP_old(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
|||
return(x);
|
||||
}
|
||||
|
||||
#ifdef __QT_DRIVER__
|
||||
// Qt Driver NetPlay state load handler. This is to control state loading,
|
||||
// only hosts can load states and clients can request loads.
|
||||
bool NetPlayStateLoadReq(EMUFILE* is);
|
||||
#endif
|
||||
|
||||
bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
||||
{
|
||||
|
@ -665,6 +670,13 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __QT_DRIVER__
|
||||
if ( NetPlayStateLoadReq(is) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t totalsize = FCEU_de32lsb(header + 4);
|
||||
int stateversion = FCEU_de32lsb(header + 8);
|
||||
uint32_t comprlen = FCEU_de32lsb(header + 12);
|
||||
|
@ -687,7 +699,8 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
|||
int error = uncompress(memory_savestate.buf(), &uncomprlen, &compressed_buf[0], comprlen);
|
||||
if(error != Z_OK || uncomprlen != totalsize)
|
||||
return false; // we dont need to restore the backup here because we havent messed with the emulator state yet
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
// the savestate is not compressed: just read from is to memory_savestate.vec
|
||||
is->fread(memory_savestate.buf(), totalsize);
|
||||
|
@ -710,7 +723,8 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
|||
FCEUPPU_LoadState(stateversion);
|
||||
FCEUSND_LoadState(stateversion);
|
||||
x=FCEUMOV_PostLoad();
|
||||
} else if (backup)
|
||||
}
|
||||
else if (backup)
|
||||
{
|
||||
msBackupSavestate.fseek(0,SEEK_SET);
|
||||
FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP);
|
||||
|
|
Loading…
Reference in New Issue