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 uint32_t opsCrc32 = 0;
|
||||||
static void *traceRegistrationHandle = nullptr;
|
static void *traceRegistrationHandle = nullptr;
|
||||||
|
static bool serverRequestedStateLoad = false;
|
||||||
|
|
||||||
struct NetPlayFrameData
|
struct NetPlayFrameData
|
||||||
{
|
{
|
||||||
|
@ -678,6 +679,46 @@ void NetPlayServer::serverProcessMessage( NetPlayClient *client, void *msgBuf, s
|
||||||
sendMsg( client, &errorMsg, errorMsg.hdr.msgSize, [&errorMsg]{ errorMsg.toNetworkByteOrder(); } );
|
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:
|
default:
|
||||||
printf("Unknown Msg: %08X\n", msgId);
|
printf("Unknown Msg: %08X\n", msgId);
|
||||||
break;
|
break;
|
||||||
|
@ -1088,6 +1129,44 @@ int NetPlayClient::requestRomLoad( const char *romPath )
|
||||||
return 0;
|
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 )
|
void NetPlayClient::recordPingResult( uint64_t delay_ms )
|
||||||
{
|
{
|
||||||
pingNumSamples++;
|
pingNumSamples++;
|
||||||
|
@ -1313,7 +1392,9 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
|
||||||
EMUFILE_MEMORY em( stateData, msgSize );
|
EMUFILE_MEMORY em( stateData, msgSize );
|
||||||
|
|
||||||
FCEU_WRAPPER_LOCK();
|
FCEU_WRAPPER_LOCK();
|
||||||
|
serverRequestedStateLoad = true;
|
||||||
FCEUSS_LoadFP( &em, SSLOADPARAM_NOBACKUP );
|
FCEUSS_LoadFP( &em, SSLOADPARAM_NOBACKUP );
|
||||||
|
serverRequestedStateLoad = false;
|
||||||
FCEU_WRAPPER_UNLOCK();
|
FCEU_WRAPPER_UNLOCK();
|
||||||
|
|
||||||
opsCrc32 = 0;
|
opsCrc32 = 0;
|
||||||
|
@ -1447,11 +1528,17 @@ NetPlayHostDialog::NetPlayHostDialog(QWidget *parent)
|
||||||
grid->addWidget( lbl, 0, 0, 1, 1 );
|
grid->addWidget( lbl, 0, 0, 1, 1 );
|
||||||
grid->addWidget( frameLeadSpinBox, 0, 1, 1, 1 );
|
grid->addWidget( frameLeadSpinBox, 0, 1, 1, 1 );
|
||||||
|
|
||||||
|
bool romLoadReqEna = false;
|
||||||
allowClientRomReqCBox = new QCheckBox(tr("Allow Client ROM Load Requests"));
|
allowClientRomReqCBox = new QCheckBox(tr("Allow Client ROM Load Requests"));
|
||||||
grid->addWidget( allowClientRomReqCBox, 1, 0, 1, 2 );
|
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"));
|
allowClientStateReqCBox = new QCheckBox(tr("Allow Client State Load Requests"));
|
||||||
grid->addWidget( allowClientStateReqCBox, 2, 0, 1, 2 );
|
grid->addWidget( allowClientStateReqCBox, 2, 0, 1, 2 );
|
||||||
|
g_config->getOption("SDL.NetPlayHostAllowClientStateLoadReq", &stateLoadReqEna);
|
||||||
|
allowClientStateReqCBox->setChecked(stateLoadReqEna);
|
||||||
|
|
||||||
startButton = new QPushButton( tr("Start") );
|
startButton = new QPushButton( tr("Start") );
|
||||||
startButton->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
|
startButton->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
|
||||||
|
@ -1511,6 +1598,9 @@ void NetPlayHostDialog::onStartClicked(void)
|
||||||
server->setAllowClientRomLoadRequest( allowClientRomReqCBox->isChecked() );
|
server->setAllowClientRomLoadRequest( allowClientRomReqCBox->isChecked() );
|
||||||
server->setAllowClientStateLoadRequest( allowClientStateReqCBox->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 );
|
bool listenSucceeded = server->listen( QHostAddress::Any, netPort );
|
||||||
|
|
||||||
if (listenSucceeded)
|
if (listenSucceeded)
|
||||||
|
@ -2217,3 +2307,18 @@ void NetPlayOnFrameBegin()
|
||||||
//printf("Frame: %u Ops:%08X Ram:%08X\n", data.frameNum, data.opsCrc32, data.ramCrc32 );
|
//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 maxLeadFrames = 10u;
|
||||||
uint32_t clientWaitCounter = 0;
|
uint32_t clientWaitCounter = 0;
|
||||||
uint32_t inputFrameCount = 0;
|
uint32_t inputFrameCount = 0;
|
||||||
bool allowClientRomLoadReq = true;
|
bool allowClientRomLoadReq = false;
|
||||||
bool allowClientStateLoadReq = true;
|
bool allowClientStateLoadReq = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
signals:
|
signals:
|
||||||
|
@ -198,6 +198,7 @@ class NetPlayClient : public QObject
|
||||||
void forceDisconnect();
|
void forceDisconnect();
|
||||||
bool flushData();
|
bool flushData();
|
||||||
int requestRomLoad( const char *romPath );
|
int requestRomLoad( const char *romPath );
|
||||||
|
int requestStateLoad(EMUFILE* is);
|
||||||
|
|
||||||
QTcpSocket* createSocket(void);
|
QTcpSocket* createSocket(void);
|
||||||
void setSocket(QTcpSocket *s);
|
void setSocket(QTcpSocket *s);
|
||||||
|
@ -426,6 +427,7 @@ int NetPlayFrameWait(void);
|
||||||
void NetPlayOnFrameBegin(void);
|
void NetPlayOnFrameBegin(void);
|
||||||
void NetPlayReadInputFrame(uint8_t* joy);
|
void NetPlayReadInputFrame(uint8_t* joy);
|
||||||
void NetPlayCloseSession(void);
|
void NetPlayCloseSession(void);
|
||||||
|
bool NetPlayStateLoadReq(EMUFILE* is);
|
||||||
void NetPlayTraceInstruction(uint8_t *opcode, int size);
|
void NetPlayTraceInstruction(uint8_t *opcode, int size);
|
||||||
void openNetPlayHostDialog(QWidget* parent = nullptr);
|
void openNetPlayHostDialog(QWidget* parent = nullptr);
|
||||||
void openNetPlayJoinDialog(QWidget* parent = nullptr);
|
void openNetPlayJoinDialog(QWidget* parent = nullptr);
|
||||||
|
|
|
@ -633,6 +633,8 @@ InitConfig()
|
||||||
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
|
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
|
||||||
config->addOption("port", "SDL.NetworkPort", NetPlayServer::DefaultPort);
|
config->addOption("port", "SDL.NetworkPort", NetPlayServer::DefaultPort);
|
||||||
config->addOption("players", "SDL.NetworkPlayers", 1);
|
config->addOption("players", "SDL.NetworkPlayers", 1);
|
||||||
|
config->addOption("SDL.NetPlayHostAllowClientRomLoadReq", 0);
|
||||||
|
config->addOption("SDL.NetPlayHostAllowClientStateLoadReq", 0);
|
||||||
|
|
||||||
// input configuration options
|
// input configuration options
|
||||||
config->addOption("input1", "SDL.Input.0", "GamePad.0");
|
config->addOption("input1", "SDL.Input.0", "GamePad.0");
|
||||||
|
|
|
@ -639,6 +639,11 @@ int FCEUSS_LoadFP_old(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
||||||
return(x);
|
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)
|
bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
||||||
{
|
{
|
||||||
|
@ -665,6 +670,13 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __QT_DRIVER__
|
||||||
|
if ( NetPlayStateLoadReq(is) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t totalsize = FCEU_de32lsb(header + 4);
|
size_t totalsize = FCEU_de32lsb(header + 4);
|
||||||
int stateversion = FCEU_de32lsb(header + 8);
|
int stateversion = FCEU_de32lsb(header + 8);
|
||||||
uint32_t comprlen = FCEU_de32lsb(header + 12);
|
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);
|
int error = uncompress(memory_savestate.buf(), &uncomprlen, &compressed_buf[0], comprlen);
|
||||||
if(error != Z_OK || uncomprlen != totalsize)
|
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
|
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
|
// the savestate is not compressed: just read from is to memory_savestate.vec
|
||||||
is->fread(memory_savestate.buf(), totalsize);
|
is->fread(memory_savestate.buf(), totalsize);
|
||||||
|
@ -710,7 +723,8 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
|
||||||
FCEUPPU_LoadState(stateversion);
|
FCEUPPU_LoadState(stateversion);
|
||||||
FCEUSND_LoadState(stateversion);
|
FCEUSND_LoadState(stateversion);
|
||||||
x=FCEUMOV_PostLoad();
|
x=FCEUMOV_PostLoad();
|
||||||
} else if (backup)
|
}
|
||||||
|
else if (backup)
|
||||||
{
|
{
|
||||||
msBackupSavestate.fseek(0,SEEK_SET);
|
msBackupSavestate.fseek(0,SEEK_SET);
|
||||||
FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP);
|
FCEUSS_LoadFP(&msBackupSavestate,SSLOADPARAM_NOBACKUP);
|
||||||
|
|
Loading…
Reference in New Issue