Added initial framework for netplay on Qt GUI. Still much TODO here.
This commit is contained in:
parent
2f2279f5ff
commit
84c2591d3f
|
@ -40,11 +40,12 @@ if ( ${QT} EQUAL 6 )
|
|||
set( Qt Qt6 )
|
||||
find_package( Qt6 REQUIRED COMPONENTS Widgets OpenGL OpenGLWidgets)
|
||||
find_package( Qt6 COMPONENTS Help QUIET)
|
||||
find_package( Qt6 COMPONENTS Network)
|
||||
find_package( Qt6 COMPONENTS Qml)
|
||||
find_package( Qt6 COMPONENTS UiTools)
|
||||
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Qml_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Qml_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )
|
||||
# add_definitions(${Qt6UiTools_DEFINITIONS}) # Leave ${Qt6UiTools_DEFINITIONS} out as this is causing a build error
|
||||
include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Qml_INCLUDE_DIRS} ${Qt6UiTools_INCLUDE_DIRS} ${Qt6Help_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS} )
|
||||
include_directories( ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Qml_INCLUDE_DIRS} ${Qt6UiTools_INCLUDE_DIRS} ${Qt6Network_INCLUDE_DIRS} ${Qt6Help_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS} )
|
||||
|
||||
if (${Qt6Help_FOUND})
|
||||
message( STATUS "Qt6 Help Module Found")
|
||||
|
@ -55,6 +56,13 @@ if ( ${QT} EQUAL 6 )
|
|||
message( STATUS "Qt6 Help Module Not Found")
|
||||
endif()
|
||||
|
||||
if (${Qt6Network_FOUND})
|
||||
message( STATUS "Qt6 Network Module Found")
|
||||
add_definitions( -D__FCEU_QNETWORK_ENABLE__ )
|
||||
else()
|
||||
message( STATUS "Qt6 Network Module Not Found")
|
||||
endif()
|
||||
|
||||
if (${Qt6Qml_FOUND})
|
||||
message( STATUS "Qt6 Qml Module Found")
|
||||
add_definitions( -D__FCEU_QSCRIPT_ENABLE__ )
|
||||
|
@ -73,10 +81,11 @@ else()
|
|||
set( Qt Qt5 )
|
||||
find_package( Qt5 REQUIRED COMPONENTS Widgets OpenGL)
|
||||
find_package( Qt5 COMPONENTS Help QUIET)
|
||||
find_package( Qt5 COMPONENTS Network)
|
||||
find_package( Qt5 COMPONENTS Qml)
|
||||
find_package( Qt5 COMPONENTS UiTools)
|
||||
add_definitions( ${Qt5Widgets_DEFINITIONS} ${Qt5Qml_DEFINITIONS} ${Qt5UiTools_DEFINITIONS} ${Qt5Help_DEFINITIONS} )
|
||||
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Qml_INCLUDE_DIRS} ${Qt5UiTools_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
|
||||
add_definitions( ${Qt5Widgets_DEFINITIONS} ${Qt5Qml_DEFINITIONS} ${Qt5UiTools_DEFINITIONS} ${Qt5Network_DEFINITIONS} ${Qt5Help_DEFINITIONS} )
|
||||
include_directories( ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Qml_INCLUDE_DIRS} ${Qt5UiTools_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5Help_INCLUDE_DIRS} )
|
||||
|
||||
if (${Qt5Help_FOUND})
|
||||
message( STATUS "Qt5 Help Module Found")
|
||||
|
@ -87,6 +96,13 @@ else()
|
|||
message( STATUS "Qt5 Help Module Not Found")
|
||||
endif()
|
||||
|
||||
if (${Qt5Network_FOUND})
|
||||
message( STATUS "Qt5 Network Module Found")
|
||||
add_definitions( -D__FCEU_NETWORK_ENABLE__ )
|
||||
else()
|
||||
message( STATUS "Qt5 Network Module Not Found")
|
||||
endif()
|
||||
|
||||
if (${Qt5Qml_FOUND})
|
||||
message( STATUS "Qt5 Qml Module Found")
|
||||
add_definitions( -D__FCEU_QSCRIPT_ENABLE__ )
|
||||
|
@ -661,6 +677,7 @@ set(SRC_DRIVERS_SDL
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-joystick.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/sdl-throttle.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/unix-netplay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/NetPlay.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AviRecord.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AviRiffViewer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/avi/avi-utils.cpp
|
||||
|
@ -733,6 +750,7 @@ target_link_libraries( ${APP_NAME}
|
|||
${${Qt}Help_LIBRARIES}
|
||||
${${Qt}Qml_LIBRARIES}
|
||||
${${Qt}UiTools_LIBRARIES}
|
||||
${${Qt}Network_LIBRARIES}
|
||||
${${Qt}OpenGL_LIBRARIES}
|
||||
${${Qt}OpenGLWidgets_LIBRARIES}
|
||||
${OPENGL_LDFLAGS}
|
||||
|
|
|
@ -275,6 +275,8 @@ void FCEUI_SetEmulationPaused(int val);
|
|||
void FCEUI_ToggleEmulationPause();
|
||||
void FCEUI_PauseForDuration(int secs);
|
||||
int FCEUI_PauseFramesRemaining();
|
||||
void FCEUI_SetNetPlayPause(bool value);
|
||||
bool FCEUI_GetNetPlayPause();
|
||||
|
||||
//indicates whether input aids should be drawn (such as crosshairs, etc; usually in fullscreen mode)
|
||||
bool FCEUD_ShouldDrawInputAids();
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
#include "Qt/RamSearch.h"
|
||||
#include "Qt/keyscan.h"
|
||||
#include "Qt/nes_shm.h"
|
||||
#include "Qt/NetPlay.h"
|
||||
#include "Qt/TasEditor/TasEditorWindow.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -926,13 +927,14 @@ void consoleWin_t::createMainMenu(void)
|
|||
menubar->setNativeMenuBar( useNativeMenuBar ? true : false );
|
||||
|
||||
// Top Level Menu Iterms
|
||||
fileMenu = menubar->addMenu(tr("&File"));
|
||||
movieMenu = menubar->addMenu(tr("&Movie"));
|
||||
optMenu = menubar->addMenu(tr("&Options"));
|
||||
emuMenu = menubar->addMenu(tr("&Emulation"));
|
||||
toolsMenu = menubar->addMenu(tr("&Tools"));
|
||||
debugMenu = menubar->addMenu(tr("&Debug"));
|
||||
helpMenu = menubar->addMenu(tr("&Help"));
|
||||
fileMenu = menubar->addMenu(tr("&File"));
|
||||
movieMenu = menubar->addMenu(tr("&Movie"));
|
||||
optMenu = menubar->addMenu(tr("&Options"));
|
||||
emuMenu = menubar->addMenu(tr("&Emulation"));
|
||||
netPlayMenu = menubar->addMenu(tr("&NetPlay"));
|
||||
toolsMenu = menubar->addMenu(tr("&Tools"));
|
||||
debugMenu = menubar->addMenu(tr("&Debug"));
|
||||
helpMenu = menubar->addMenu(tr("&Help"));
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// File
|
||||
|
@ -1657,6 +1659,29 @@ void consoleWin_t::createMainMenu(void)
|
|||
|
||||
subMenu->addAction(act);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// NetPlay
|
||||
|
||||
connect( netPlayMenu, SIGNAL(aboutToShow(void)), this, SLOT(mainMenuOpen(void)) );
|
||||
connect( netPlayMenu, SIGNAL(aboutToHide(void)), this, SLOT(mainMenuClose(void)) );
|
||||
|
||||
// NetPlay -> Host
|
||||
act = new QAction(tr("&Host"), this);
|
||||
//act->setShortcut( QKeySequence(tr("Shift+F7")));
|
||||
act->setStatusTip(tr("Host Game Window"));
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(openNetPlayHostWindow(void)) );
|
||||
|
||||
netPlayMenu->addAction(act);
|
||||
|
||||
// NetPlay -> Join
|
||||
act = new QAction(tr("&Join"), this);
|
||||
//act->setShortcut( QKeySequence(tr("Shift+F7")));
|
||||
act->setStatusTip(tr("Join Game Window"));
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(openNetPlayJoinWindow(void)) );
|
||||
|
||||
netPlayMenu->addAction(act);
|
||||
|
||||
netPlayMenu->setEnabled(false);
|
||||
//-----------------------------------------------------------------------
|
||||
// Tools
|
||||
|
||||
|
@ -3112,6 +3137,28 @@ void consoleWin_t::openPaletteEditorWin(void)
|
|||
win->show();
|
||||
}
|
||||
|
||||
void consoleWin_t::openNetPlayHostWindow(void)
|
||||
{
|
||||
NetPlayHostDialog *win;
|
||||
|
||||
//printf("Open NetPlay Host Window\n");
|
||||
|
||||
win = new NetPlayHostDialog(this);
|
||||
|
||||
win->show();
|
||||
}
|
||||
|
||||
void consoleWin_t::openNetPlayJoinWindow(void)
|
||||
{
|
||||
NetPlayJoinDialog *win;
|
||||
|
||||
//printf("Open NetPlay Join Window\n");
|
||||
|
||||
win = new NetPlayJoinDialog(this);
|
||||
|
||||
win->show();
|
||||
}
|
||||
|
||||
void consoleWin_t::openAviRiffViewer(void)
|
||||
{
|
||||
AviRiffViewerDialog *win;
|
||||
|
@ -4692,6 +4739,8 @@ void consoleWin_t::updatePeriodic(void)
|
|||
closeRequested = false;
|
||||
}
|
||||
|
||||
NetPlayPeriodicUpdate();
|
||||
|
||||
updateCounter++;
|
||||
|
||||
#ifdef __FCEU_PROFILER_ENABLE__
|
||||
|
|
|
@ -193,6 +193,7 @@ class consoleWin_t : public QMainWindow
|
|||
QMenu *toolsMenu;
|
||||
QMenu *debugMenu;
|
||||
QMenu *movieMenu;
|
||||
QMenu *netPlayMenu;
|
||||
QMenu *helpMenu;
|
||||
QMenu *recentRomMenu;
|
||||
|
||||
|
@ -351,6 +352,8 @@ class consoleWin_t : public QMainWindow
|
|||
void openTimingConfWin(void);
|
||||
void openStateRecorderConfWin(void);
|
||||
void openPaletteEditorWin(void);
|
||||
void openNetPlayHostWindow(void);
|
||||
void openNetPlayJoinWindow(void);
|
||||
void openAviRiffViewer(void);
|
||||
void openTimingStatWin(void);
|
||||
void openMovieOptWin(void);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,275 @@
|
|||
// NetPlay.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#include <QPushButton>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
#include <QFrame>
|
||||
#include <QGroupBox>
|
||||
#include <QCloseEvent>
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QTcpServer>
|
||||
|
||||
#include "utils/mutex.h"
|
||||
|
||||
class NetPlayClient;
|
||||
|
||||
struct NetPlayFrameInput
|
||||
{
|
||||
static constexpr uint32_t ownsData = 0x01;
|
||||
|
||||
NetPlayFrameInput(void)
|
||||
{
|
||||
flags = 0; frameCounter = 0;
|
||||
ctrl[0] = ctrl[1] = ctrl[2] = ctrl[3] = 0;
|
||||
data = nullptr;
|
||||
}
|
||||
|
||||
~NetPlayFrameInput()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
if (flags & ownsData)
|
||||
{
|
||||
::free(data);
|
||||
data = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t frameCounter;
|
||||
uint8_t ctrl[4];
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
class NetPlayServer : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetPlayServer(QObject *parent = 0);
|
||||
~NetPlayServer(void);
|
||||
|
||||
static NetPlayServer *GetInstance(void){ return instance; };
|
||||
|
||||
static int Create(QObject *parent = 0);
|
||||
|
||||
bool removeClient(NetPlayClient *client, bool markForDelete = false);
|
||||
|
||||
int closeAllConnections(void);
|
||||
|
||||
void update(void);
|
||||
|
||||
size_t inputAvailable(void)
|
||||
{
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
return input.size();
|
||||
};
|
||||
|
||||
void pushBackInput( NetPlayFrameInput &in )
|
||||
{
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
input.push_back(in);
|
||||
};
|
||||
|
||||
NetPlayFrameInput getNextInput(void)
|
||||
{
|
||||
NetPlayFrameInput in;
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
if (!input.empty())
|
||||
{
|
||||
in = input.front();
|
||||
input.pop_front();
|
||||
}
|
||||
return in;
|
||||
};
|
||||
|
||||
uint32_t inputFrameBack()
|
||||
{
|
||||
uint32_t frame = 0;
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
if (!input.empty())
|
||||
{
|
||||
NetPlayFrameInput &in = input.back();
|
||||
frame = in.frameCounter;
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
int sendMsg( NetPlayClient *client, void *msg, size_t msgSize);
|
||||
int sendRomLoadReq( NetPlayClient *client );
|
||||
int sendStateSyncReq( NetPlayClient *client );
|
||||
void setRole(int _role);
|
||||
bool claimRole(NetPlayClient* client, int _role);
|
||||
|
||||
void serverProcessMessage( NetPlayClient *client, void *msgBuf, size_t msgSize );
|
||||
|
||||
private:
|
||||
static NetPlayServer *instance;
|
||||
|
||||
void processPendingConnections(void);
|
||||
|
||||
std::list <NetPlayClient*> clientList;
|
||||
std::list <NetPlayFrameInput> input;
|
||||
FCEU::mutex inputMtx;
|
||||
int role = -1;
|
||||
int roleMask = 0;
|
||||
NetPlayClient* clientPlayer[4] = { nullptr };
|
||||
|
||||
public slots:
|
||||
void newConnectionRdy(void);
|
||||
};
|
||||
|
||||
class NetPlayClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetPlayClient(QObject *parent = 0, bool outGoing = false);
|
||||
~NetPlayClient(void);
|
||||
|
||||
static NetPlayClient *GetInstance(void){ return instance; };
|
||||
|
||||
static int Create(QObject *parent = 0);
|
||||
|
||||
int connectToHost( const QString host, int port );
|
||||
|
||||
bool isConnected(void);
|
||||
void disconnect();
|
||||
|
||||
void setSocket(QTcpSocket *s);
|
||||
QTcpSocket* getSocket(void){ return sock; };
|
||||
|
||||
void update(void);
|
||||
int readMessages( void (*msgCallback)( void *userData, void *msgBuf, size_t msgSize ), void *userData );
|
||||
void clientProcessMessage( void *msgBuf, size_t msgSize );
|
||||
|
||||
size_t inputAvailable(void)
|
||||
{
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
return !input.empty();
|
||||
};
|
||||
|
||||
void pushBackInput( NetPlayFrameInput &in )
|
||||
{
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
input.push_back(in);
|
||||
};
|
||||
|
||||
NetPlayFrameInput getNextInput(void)
|
||||
{
|
||||
NetPlayFrameInput in;
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
if (!input.empty())
|
||||
{
|
||||
in = input.front();
|
||||
input.pop_front();
|
||||
}
|
||||
return in;
|
||||
};
|
||||
|
||||
uint32_t inputFrameBack()
|
||||
{
|
||||
uint32_t frame = 0;
|
||||
FCEU::autoScopedLock alock(inputMtx);
|
||||
if (!input.empty())
|
||||
{
|
||||
NetPlayFrameInput &in = input.back();
|
||||
frame = in.frameCounter;
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
QString userName;
|
||||
int role;
|
||||
int state;
|
||||
unsigned int currentFrame;
|
||||
|
||||
private:
|
||||
int createSocket(void);
|
||||
|
||||
static NetPlayClient *instance;
|
||||
|
||||
QTcpSocket *sock;
|
||||
int recvMsgId;
|
||||
int recvMsgSize;
|
||||
int recvMsgBytesLeft;
|
||||
int recvMsgByteIndex;
|
||||
char *recvMsgBuf;
|
||||
|
||||
std::list <NetPlayFrameInput> input;
|
||||
FCEU::mutex inputMtx;
|
||||
|
||||
static constexpr size_t recvMsgBufSize = 2 * 1024 * 1024;
|
||||
|
||||
public slots:
|
||||
void onConnect(void);
|
||||
void onDisconnect(void);
|
||||
};
|
||||
|
||||
|
||||
class NetPlayHostDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetPlayHostDialog(QWidget *parent = 0);
|
||||
~NetPlayHostDialog(void);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
QLineEdit *serverNameEntry;
|
||||
QSpinBox *portEntry;
|
||||
QComboBox *playerRoleBox;
|
||||
|
||||
public slots:
|
||||
void closeWindow(void);
|
||||
void onStartClicked(void);
|
||||
|
||||
};
|
||||
|
||||
class NetPlayJoinDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetPlayJoinDialog(QWidget *parent = 0);
|
||||
~NetPlayJoinDialog(void);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
QLineEdit *hostEntry;
|
||||
QSpinBox *portEntry;
|
||||
QComboBox *playerRoleBox;
|
||||
|
||||
public slots:
|
||||
void closeWindow(void);
|
||||
void onJoinClicked(void);
|
||||
|
||||
};
|
||||
|
||||
bool NetPlayActive(void);
|
||||
void NetPlayPeriodicUpdate(void);
|
||||
bool NetPlaySkipWait(void);
|
||||
int NetPlayFrameWait(void);
|
||||
void NetPlayReadInputFrame(uint8_t* joy);
|
|
@ -0,0 +1,167 @@
|
|||
// NetPlayMsgDef.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma pack(push,4)
|
||||
|
||||
enum netPlayMsgType
|
||||
{
|
||||
NETPLAY_AUTH_REQ,
|
||||
NETPLAY_AUTH_RESP,
|
||||
NETPLAY_LOAD_ROM_REQ,
|
||||
NETPLAY_SYNC_STATE,
|
||||
NETPLAY_RUN_FRAME_REQ,
|
||||
NETPLAY_RUN_FRAME_RESP,
|
||||
NETPLAY_CLIENT_STATE,
|
||||
NETPLAY_ERROR_MSG,
|
||||
};
|
||||
|
||||
enum netPlayerId
|
||||
{
|
||||
NETPLAY_SPECTATOR = -1,
|
||||
NETPLAY_PLAYER1,
|
||||
NETPLAY_PLAYER2,
|
||||
NETPLAY_PLAYER3,
|
||||
NETPLAY_PLAYER4
|
||||
};
|
||||
|
||||
static const uint32_t NETPLAY_MAGIC_NUMBER = 0xaa55aa55;
|
||||
|
||||
struct netPlayMsgHdr
|
||||
{
|
||||
uint32_t magic[2];
|
||||
uint32_t msgId;
|
||||
uint32_t msgSize;
|
||||
|
||||
netPlayMsgHdr( uint32_t id, uint32_t size = sizeof(netPlayMsgHdr) )
|
||||
{
|
||||
magic[0] = NETPLAY_MAGIC_NUMBER;
|
||||
magic[1] = NETPLAY_MAGIC_NUMBER;
|
||||
msgId = id; msgSize = size;
|
||||
}
|
||||
};
|
||||
|
||||
struct netPlayAuthReq
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
uint8_t ctrlMask;
|
||||
|
||||
netPlayAuthReq(void)
|
||||
: hdr(NETPLAY_AUTH_REQ, sizeof(netPlayAuthReq)), ctrlMask(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct netPlayAuthResp
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
char playerId;
|
||||
char pswd[128];
|
||||
|
||||
netPlayAuthResp(void)
|
||||
: hdr(NETPLAY_AUTH_RESP, sizeof(netPlayAuthResp)), playerId(NETPLAY_SPECTATOR)
|
||||
{
|
||||
memset(pswd, 0, sizeof(pswd));
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N=8>
|
||||
struct netPlayErrorMsg
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
char data[N];
|
||||
|
||||
netPlayErrorMsg(void)
|
||||
: hdr(NETPLAY_ERROR_MSG, sizeof(netPlayErrorMsg))
|
||||
{
|
||||
}
|
||||
|
||||
char *getMsgBuffer()
|
||||
{
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
int printf(const char* format, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
retval = ::vsnprintf(data, sizeof(data), format, args);
|
||||
va_end(args);
|
||||
|
||||
hdr.msgSize = sizeof(netPlayMsgHdr) + strlen(data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
struct netPlayLoadRomReq
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
uint32_t fileSize;
|
||||
char fileName[256];
|
||||
|
||||
netPlayLoadRomReq(void)
|
||||
: hdr(NETPLAY_LOAD_ROM_REQ, sizeof(netPlayLoadRomReq)), fileSize(0)
|
||||
{
|
||||
memset(fileName, 0, sizeof(fileName));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct netPlayRunFrameReq
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t frameNum;
|
||||
uint8_t ctrlState[4];
|
||||
|
||||
netPlayRunFrameReq(void)
|
||||
: hdr(NETPLAY_RUN_FRAME_REQ, sizeof(netPlayRunFrameReq)), flags(0), frameNum(0)
|
||||
{
|
||||
memset( ctrlState, 0, sizeof(ctrlState) );
|
||||
}
|
||||
};
|
||||
|
||||
struct netPlayRunFrameResp
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t frameNum;
|
||||
uint32_t frameRun;
|
||||
uint8_t ctrlState[4];
|
||||
|
||||
netPlayRunFrameResp(void)
|
||||
: hdr(NETPLAY_RUN_FRAME_RESP, sizeof(netPlayRunFrameResp)), flags(0), frameNum(0), frameRun(0)
|
||||
{
|
||||
memset( ctrlState, 0, sizeof(ctrlState) );
|
||||
}
|
||||
};
|
||||
|
||||
struct netPlayClientState
|
||||
{
|
||||
netPlayMsgHdr hdr;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t frameRdy;
|
||||
uint32_t frameRun;
|
||||
uint8_t ctrlState[4];
|
||||
|
||||
netPlayClientState(void)
|
||||
: hdr(NETPLAY_CLIENT_STATE, sizeof(netPlayClientState)), flags(0), frameRdy(0), frameRun(0)
|
||||
{
|
||||
memset( ctrlState, 0, sizeof(ctrlState) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(pop)
|
|
@ -77,7 +77,6 @@
|
|||
// File Base Name from Core
|
||||
extern char FileBase[];
|
||||
extern uint8 joy[4];
|
||||
extern uint32 GetGamepadPressedImmediate();
|
||||
|
||||
static thread_local FCEU::JSEngine* currentEngine = nullptr;
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "Qt/sdl-video.h"
|
||||
#include "Qt/nes_shm.h"
|
||||
#include "Qt/unix-netplay.h"
|
||||
#include "Qt/NetPlay.h"
|
||||
#include "Qt/AviRecord.h"
|
||||
#include "Qt/HexEditor.h"
|
||||
#include "Qt/CheatsConf.h"
|
||||
|
@ -1475,6 +1476,23 @@ int fceuWrapperUpdate( void )
|
|||
}
|
||||
mutexLockFail = false;
|
||||
emulatorHasMutex = 1;
|
||||
|
||||
// For netplay, set pause if we do not have input ready for all players
|
||||
if (NetPlayActive())
|
||||
{
|
||||
if (NetPlayFrameWait())
|
||||
{
|
||||
FCEUI_SetNetPlayPause(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
FCEUI_SetNetPlayPause(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FCEUI_SetNetPlayPause(false);
|
||||
}
|
||||
|
||||
if ( GameInfo )
|
||||
{
|
||||
|
|
|
@ -144,6 +144,7 @@ void UpdateInput(Config *config);
|
|||
const char* ButtonName(const ButtConfig* bc);
|
||||
|
||||
void pollEventsSDL();
|
||||
uint32 GetGamepadPressedImmediate(void);
|
||||
int getInputSelection( int port, int *cur, int *usr );
|
||||
int saveInputSettingsToFile( const char *fileBase = NULL );
|
||||
int loadInputSettingsFromFile( const char *filename = NULL );
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
/// \brief Handles emulation speed throttling using the SDL timing functions.
|
||||
|
||||
#include "Qt/sdl.h"
|
||||
#include "Qt/NetPlay.h"
|
||||
#include "Qt/throttle.h"
|
||||
#include "utils/timeStamp.h"
|
||||
|
||||
|
@ -367,7 +368,7 @@ SpeedThrottle(void)
|
|||
{
|
||||
bool isEmuPaused = FCEUI_EmulationPaused() ? true : false;
|
||||
bool noWaitActive = (NoWaiting & 0x01) ? true : false;
|
||||
bool turboActive = (turbo || noWaitActive);
|
||||
bool turboActive = (turbo || noWaitActive || NetPlaySkipWait());
|
||||
|
||||
// If Emulator is paused, don't waste CPU cycles spinning on nothing.
|
||||
if ( !isEmuPaused && ((g_fpsScale >= 32) || turboActive) )
|
||||
|
|
19
src/fceu.cpp
19
src/fceu.cpp
|
@ -806,7 +806,7 @@ void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int ski
|
|||
RefreshThrottleFPS();
|
||||
}
|
||||
#endif
|
||||
if (EmulationPaused & (EMULATIONPAUSED_PAUSED | EMULATIONPAUSED_TIMER) )
|
||||
if (EmulationPaused & (EMULATIONPAUSED_PAUSED | EMULATIONPAUSED_TIMER | EMULATIONPAUSED_NETPLAY) )
|
||||
{
|
||||
// emulator is paused
|
||||
memcpy(XBuf, XBackBuf, 256*256);
|
||||
|
@ -1309,6 +1309,23 @@ int FCEUI_PauseFramesRemaining(void)
|
|||
return (EmulationPaused & EMULATIONPAUSED_TIMER) ? pauseTimer : 0;
|
||||
}
|
||||
|
||||
bool FCEUI_GetNetPlayPause()
|
||||
{
|
||||
return (EmulationPaused & EMULATIONPAUSED_NETPLAY) ? true : false;
|
||||
}
|
||||
|
||||
void FCEUI_SetNetPlayPause(bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
EmulationPaused |= EMULATIONPAUSED_NETPLAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmulationPaused &= ~EMULATIONPAUSED_NETPLAY;
|
||||
}
|
||||
}
|
||||
|
||||
static int AutosaveCounter = 0;
|
||||
|
||||
void UpdateAutosave(void) {
|
||||
|
|
|
@ -184,6 +184,7 @@ extern uint8 vsdip;
|
|||
#define EMULATIONPAUSED_PAUSED 0x01
|
||||
#define EMULATIONPAUSED_TIMER 0x02
|
||||
#define EMULATIONPAUSED_FA 0x04
|
||||
#define EMULATIONPAUSED_NETPLAY 0x08
|
||||
|
||||
#define FRAMEADVANCE_DELAY_DEFAULT 10
|
||||
#define NES_HEADER_SIZE 16
|
||||
|
|
|
@ -274,7 +274,6 @@ static void UpdateGP(int w, void *data, int arg)
|
|||
joy[3]= FCEU_JSReadJoypad(3,joy[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void LogGP(int w, MovieRecord* mr)
|
||||
|
@ -435,6 +434,10 @@ void FCEU_DrawInput(uint8 *buf)
|
|||
portFC.driver->Draw(buf,portFC.attrib);
|
||||
}
|
||||
|
||||
#ifdef __FCEU_QNETWORK_ENABLE__
|
||||
extern bool NetPlayActive(void);
|
||||
void NetPlayReadInputFrame(uint8_t* joy);
|
||||
#endif
|
||||
|
||||
void FCEU_UpdateInput(void)
|
||||
{
|
||||
|
@ -452,6 +455,12 @@ void FCEU_UpdateInput(void)
|
|||
if (coinon2) coinon2--;
|
||||
if (service) service--;
|
||||
}
|
||||
#ifdef __FCEU_QNETWORK_ENABLE__
|
||||
if (NetPlayActive())
|
||||
{
|
||||
NetPlayReadInputFrame(joy);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(FCEUnetplay)
|
||||
NetplayUpdate(joy);
|
||||
|
|
|
@ -61,15 +61,15 @@
|
|||
#endif
|
||||
|
||||
#define FCEU_VERSION_MAJOR 2
|
||||
#define FCEU_VERSION_MINOR 6
|
||||
#define FCEU_VERSION_PATCH 6
|
||||
#define FCEU_VERSION_MINOR 7
|
||||
#define FCEU_VERSION_PATCH 0
|
||||
|
||||
#define FCEU_VERSION_NUMERIC ( (FCEU_VERSION_MAJOR*10000) + (FCEU_VERSION_MINOR*100) + (FCEU_VERSION_PATCH) )
|
||||
#define FCEU_VERSION_MAJOR_DECODE(x) ( (x / 10000) )
|
||||
#define FCEU_VERSION_MINOR_DECODE(x) ( (x / 100) % 100 )
|
||||
#define FCEU_VERSION_PATCH_DECODE(x) (x % 100)
|
||||
|
||||
#define FCEU_VERSION_STRING "2.6.6" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
|
||||
#define FCEU_VERSION_STRING "2.7.0" FCEU_SUBVERSION_STRING FCEU_FEATURE_STRING FCEU_COMPILER
|
||||
#define FCEU_NAME_AND_VERSION FCEU_NAME " " FCEU_VERSION_STRING
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue