From 10418f551a7841c925afc1831e169c2e865b3e38 Mon Sep 17 00:00:00 2001 From: harry Date: Wed, 3 Apr 2024 04:55:07 -0400 Subject: [PATCH] Added framework for Qt netplay client status dialog. --- src/drivers/Qt/NetPlay.cpp | 137 +++++++++++++++++++++++++++++++-- src/drivers/Qt/NetPlay.h | 26 +++++++ src/drivers/Qt/NetPlayMsgDef.h | 19 ++--- 3 files changed, 167 insertions(+), 15 deletions(-) diff --git a/src/drivers/Qt/NetPlay.cpp b/src/drivers/Qt/NetPlay.cpp index 0ee93dba4..e9e3d3878 100644 --- a/src/drivers/Qt/NetPlay.cpp +++ b/src/drivers/Qt/NetPlay.cpp @@ -646,8 +646,8 @@ void NetPlayServer::serverProcessMessage( NetPlayClient *client, void *msgBuf, s client->gpData[2] = msg->ctrlState[2]; client->gpData[3] = msg->ctrlState[3]; - client->setPaused( (msg->flags & netPlayClientState::PAUSE_FLAG ) ? true : false ); - client->setDesync( (msg->flags & netPlayClientState::DESYNC_FLAG) ? true : false ); + client->setPaused( (msg->flags & netPlayClientState::PauseFlag ) ? true : false ); + client->setDesync( (msg->flags & netPlayClientState::DesyncFlag) ? true : false ); client->romMatch = (romCrc32 == msg->romCrc32); @@ -798,6 +798,13 @@ void NetPlayServer::serverProcessMessage( NetPlayClient *client, void *msgBuf, s } } break; + case NETPLAY_CLIENT_SYNC_REQ: + { + FCEU_WRAPPER_LOCK(); + resyncClient( client ); + FCEU_WRAPPER_UNLOCK(); + } + break; default: printf("Unknown Msg: %08X\n", msgId); break; @@ -1288,6 +1295,15 @@ int NetPlayClient::requestStateLoad(EMUFILE *is) return 0; } //----------------------------------------------------------------------------- +int NetPlayClient::requestSync(void) +{ + netPlayMsgHdr hdr(NETPLAY_CLIENT_SYNC_REQ); + + hdr.toNetworkByteOrder(); + sock->write( reinterpret_cast(&hdr), sizeof(netPlayMsgHdr)); + return 0; +} +//----------------------------------------------------------------------------- void NetPlayClient::recordPingResult( uint64_t delay_ms ) { pingNumSamples++; @@ -1335,11 +1351,11 @@ void NetPlayClient::update(void) statusMsg.flags = 0; if (FCEUI_EmulationPaused()) { - statusMsg.flags |= netPlayClientState::PAUSE_FLAG; + statusMsg.flags |= netPlayClientState::PauseFlag; } if (desyncCount > 0) { - statusMsg.flags |= netPlayClientState::DESYNC_FLAG; + statusMsg.flags |= netPlayClientState::DesyncFlag; } statusMsg.frameRdy = inputFrameBack(); statusMsg.frameRun = currFrame; @@ -1994,7 +2010,116 @@ void NetPlayJoinDialog::onSocketError(const QString& errorMsg) } } //----------------------------------------------------------------------------- -//--- NetPlayJoinDialog +//--- NetPlayClientStatusDialog +//----------------------------------------------------------------------------- +NetPlayClientStatusDialog* NetPlayClientStatusDialog::instance = nullptr; +//----------------------------------------------------------------------------- +NetPlayClientStatusDialog::NetPlayClientStatusDialog(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainLayout; + QHBoxLayout *hbox; + QGridLayout *grid; + QGroupBox *gbox; + QPushButton *closeButton; + //QLabel *lbl; + + instance = this; + mainLayout = new QVBoxLayout(); + grid = new QGridLayout(); + gbox = new QGroupBox(tr("Connection")); + + gbox->setLayout(grid); + mainLayout->addWidget(gbox); + + hostStateLbl = new QLabel(tr("Unknown")); + grid->addWidget( new QLabel(tr("Host Frame:")), 0, 0 ); + grid->addWidget( hostStateLbl, 0, 1 ); + + requestResyncButton = new QPushButton(tr("Resync State")); + grid->addWidget( requestResyncButton, 1, 0, 1, 2 ); + + hbox = new QHBoxLayout(); + mainLayout->addLayout(hbox); + + closeButton = new QPushButton( tr("Close") ); + closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); + connect(closeButton, SIGNAL(clicked(void)), this, SLOT(closeWindow(void))); + + hbox->addStretch(3); + hbox->addWidget(closeButton); + + setWindowTitle("NetPlay Status"); + //resize( 512, 256 ); + + setLayout(mainLayout); + + connect(requestResyncButton, SIGNAL(clicked(void)), this, SLOT(resyncButtonClicked(void))); + + periodicTimer = new QTimer(this); + periodicTimer->start(200); // 5hz + connect(periodicTimer, &QTimer::timeout, this, &NetPlayClientStatusDialog::updatePeriodic); +} +//---------------------------------------------------------------------------- +NetPlayClientStatusDialog::~NetPlayClientStatusDialog(void) +{ + instance = nullptr; + periodicTimer->stop(); + delete periodicTimer; + //printf("Destroy NetPlay Status Window\n"); +} +//---------------------------------------------------------------------------- +void NetPlayClientStatusDialog::closeEvent(QCloseEvent *event) +{ + //printf("NetPlay Client Close Window Event\n"); + done(0); + deleteLater(); + event->accept(); +} +//---------------------------------------------------------------------------- +void NetPlayClientStatusDialog::closeWindow(void) +{ + //printf("Close Window\n"); + done(0); + deleteLater(); +} +//---------------------------------------------------------------------------- +void NetPlayClientStatusDialog::updatePeriodic() +{ + updateStatusDisplay(); +} +//---------------------------------------------------------------------------- +void NetPlayClientStatusDialog::updateStatusDisplay() +{ + NetPlayClient* client = NetPlayClient::GetInstance(); + + if (client == nullptr) + { + return; + } + char stmp[64]; + uint32_t inputFrame = client->inputFrameBack(); + + if (inputFrame == 0) + { + inputFrame = static_cast(currFrameCounter); + } + snprintf( stmp, sizeof(stmp), "%u", inputFrame); + hostStateLbl->setText(tr(stmp)); +} +//---------------------------------------------------------------------------- +void NetPlayClientStatusDialog::resyncButtonClicked() +{ + NetPlayClient* client = NetPlayClient::GetInstance(); + + if (client == nullptr) + { + return; + } + client->requestSync(); +} +//----------------------------------------------------------------------------- +//--- NetPlayHostStatusDialog //----------------------------------------------------------------------------- NetPlayHostStatusDialog* NetPlayHostStatusDialog::instance = nullptr; //----------------------------------------------------------------------------- @@ -2419,7 +2544,7 @@ void openNetPlayHostStatusDialog(QWidget* parent) //---------------------------------------------------------------------------- void openNetPlayClientStatusDialog(QWidget* parent) { - //openSingletonDialog(parent); + openSingletonDialog(parent); } //---------------------------------------------------------------------------- //---- Network Byte Swap Utilities diff --git a/src/drivers/Qt/NetPlay.h b/src/drivers/Qt/NetPlay.h index f3df22757..3ed9390a4 100644 --- a/src/drivers/Qt/NetPlay.h +++ b/src/drivers/Qt/NetPlay.h @@ -204,6 +204,7 @@ class NetPlayClient : public QObject bool flushData(); int requestRomLoad( const char *romPath ); int requestStateLoad(EMUFILE* is); + int requestSync(void); QTcpSocket* createSocket(void); void setSocket(QTcpSocket *s); @@ -403,6 +404,31 @@ class NetPlayClientTreeItem : public QTreeWidgetItem private: }; +class NetPlayClientStatusDialog : public QDialog +{ + Q_OBJECT + +public: + NetPlayClientStatusDialog(QWidget *parent = 0); + ~NetPlayClientStatusDialog(void); + + static NetPlayClientStatusDialog *GetInstance(void){ return instance; }; + +protected: + void closeEvent(QCloseEvent *event); + void updateStatusDisplay(void); + + QLabel *hostStateLbl; + QTimer *periodicTimer; + QPushButton *requestResyncButton; + static NetPlayClientStatusDialog* instance; + +public slots: + void closeWindow(void); + void updatePeriodic(void); + void resyncButtonClicked(void); +}; + class NetPlayHostStatusDialog : public QDialog { Q_OBJECT diff --git a/src/drivers/Qt/NetPlayMsgDef.h b/src/drivers/Qt/NetPlayMsgDef.h index 40d72fd19..b5be23140 100644 --- a/src/drivers/Qt/NetPlayMsgDef.h +++ b/src/drivers/Qt/NetPlayMsgDef.h @@ -15,18 +15,19 @@ uint64_t netPlayByteSwap(uint64_t); enum netPlayMsgType { - NETPLAY_AUTH_REQ, + NETPLAY_AUTH_REQ = 0, NETPLAY_AUTH_RESP, - NETPLAY_LOAD_ROM_REQ, + NETPLAY_LOAD_ROM_REQ = 100, NETPLAY_UNLOAD_ROM_REQ, - NETPLAY_SYNC_STATE_REQ, + NETPLAY_SYNC_STATE_REQ = 200, NETPLAY_SYNC_STATE_RESP, - NETPLAY_RUN_FRAME_REQ, - NETPLAY_CLIENT_STATE, - NETPLAY_INFO_MSG, + NETPLAY_RUN_FRAME_REQ = 300, + NETPLAY_CLIENT_STATE = 400, + NETPLAY_CLIENT_SYNC_REQ, + NETPLAY_INFO_MSG = 500, NETPLAY_ERROR_MSG, NETPLAY_CHAT_MSG, - NETPLAY_PING_REQ, + NETPLAY_PING_REQ = 1000, NETPLAY_PING_RESP, }; @@ -299,8 +300,8 @@ struct netPlayClientState uint32_t romCrc32; uint8_t ctrlState[4]; - static constexpr uint32_t PAUSE_FLAG = 0x0001; - static constexpr uint32_t DESYNC_FLAG = 0x0002; + static constexpr uint32_t PauseFlag = 0x0001; + static constexpr uint32_t DesyncFlag = 0x0002; netPlayClientState(void) : hdr(NETPLAY_CLIENT_STATE, sizeof(netPlayClientState)), flags(0),