Skip to content

Commit c97e2c9

Browse files
committed
For Qt Netplay, added code to sync cheats between server and clients.
1 parent 6e69843 commit c97e2c9

File tree

9 files changed

+252
-53
lines changed

9 files changed

+252
-53
lines changed

src/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ if ( ${QT} EQUAL 6 )
3939
message( STATUS "GUI Frontend: Qt6")
4040
set( Qt Qt6 )
4141
find_package( Qt6 REQUIRED COMPONENTS Widgets OpenGL OpenGLWidgets)
42+
find_package( Qt6 REQUIRED COMPONENTS Network)
4243
find_package( Qt6 COMPONENTS Help QUIET)
43-
find_package( Qt6 COMPONENTS Network)
4444
find_package( Qt6 COMPONENTS Qml)
4545
find_package( Qt6 COMPONENTS UiTools)
4646
add_definitions( ${Qt6Widgets_DEFINITIONS} ${Qt6Qml_DEFINITIONS} ${Qt6Network_DEFINITIONS} ${Qt6Help_DEFINITIONS} ${Qt6OpenGLWidgets_DEFINITIONS} )

src/cheat.cpp

+20-3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
5858
CheatRPtrs[AB+x]=p-A;
5959
}
6060

61+
// Cheat change event callback. Called whenever cheat map is changed or recalculated.
62+
static void (*cheatsChangeEventCB)(void*) = nullptr;
63+
static void* cheatsChangeEventUserData = nullptr;
64+
65+
void FCEU_SetCheatChangeEventCallback( void (*func)(void*), void* userData )
66+
{
67+
cheatsChangeEventCB = func;
68+
cheatsChangeEventUserData = userData;
69+
}
6170

6271
CHEATF_SUBFAST SubCheats[256];
6372
uint32 numsubcheats = 0;
@@ -132,6 +141,11 @@ void RebuildSubCheats(void)
132141
}
133142
FrozenAddressCount = numsubcheats; //Update the frozen address list
134143

144+
// Notify the system of a change
145+
if (cheatsChangeEventCB != nullptr)
146+
{
147+
cheatsChangeEventCB( cheatsChangeEventUserData );
148+
}
135149
}
136150

137151
void FCEU_PowerCheats()
@@ -368,12 +382,15 @@ void FCEU_FlushGameCheats(FILE *override, int nosave)
368382
}
369383

370384

371-
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
385+
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type, int status, bool rebuild)
372386
{
373-
AddCheatEntry(name, addr, val, compare, 1, type);
387+
AddCheatEntry(name, addr, val, compare, status, type);
374388
savecheats = 1;
375-
RebuildSubCheats();
376389

390+
if (rebuild)
391+
{
392+
RebuildSubCheats();
393+
}
377394
return 1;
378395
}
379396

src/cheat.h

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ extern int disableAutoLSCheats;
3333
int FCEU_DisableAllCheats(void);
3434
int FCEU_DeleteAllCheats(void);
3535

36+
void FCEU_SetCheatChangeEventCallback( void (*func)(void*) = nullptr, void* userData = nullptr );
37+
3638
struct CHEATF_SUBFAST
3739
{
3840
uint16 addr;

src/driver.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ void FCEU_DispMessage( __FCEU_PRINTF_FORMAT const char *format, int disppos, ...
197197

198198
int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type);
199199
int FCEUI_DecodeGG(const char *str, int *a, int *v, int *c);
200-
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type);
200+
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type, int status = 1, bool rebuild = true);
201201
int FCEUI_DelCheat(uint32 which);
202202
int FCEUI_ToggleCheat(uint32 which);
203203
int FCEUI_GlobalToggleCheat(int global_enable);

src/drivers/Qt/ConsoleWindow.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "../../movie.h"
5656
#include "../../wave.h"
5757
#include "../../state.h"
58+
#include "../../cheat.h"
5859
#include "../../profiler.h"
5960
#include "../../version.h"
6061
#include "common/os_utils.h"
@@ -285,6 +286,19 @@ consoleWin_t::consoleWin_t(QWidget *parent)
285286
}
286287
};
287288
FCEUSS_SetLoadCallback( stateLoadCallback );
289+
290+
// Register Cheat Change Callback
291+
auto cheatChangeCallback = []( void* userData )
292+
{
293+
FCEU_UNUSED(userData);
294+
295+
//printf("Cheats Changed Event!\n");
296+
if (consoleWindow != nullptr)
297+
{
298+
emit consoleWindow->cheatsChanged();
299+
}
300+
};
301+
FCEU_SetCheatChangeEventCallback( cheatChangeCallback, this );
288302
}
289303

290304
consoleWin_t::~consoleWin_t(void)

src/drivers/Qt/ConsoleWindow.h

+1
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ class consoleWin_t : public QMainWindow
332332
void stateLoaded(void);
333333
void nesResetOccurred(void);
334334
void pauseToggled(bool state);
335+
void cheatsChanged(void);
335336

336337
public slots:
337338
void openDebugWindow(void);

src/drivers/Qt/NetPlay.cpp

+142-31
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "../../fceu.h"
2727
#include "../../cart.h"
28+
#include "../../cheat.h"
2829
#include "../../state.h"
2930
#include "../../movie.h"
3031
#include "../../debug.h"
@@ -182,6 +183,7 @@ NetPlayServer::NetPlayServer(QObject *parent)
182183
connect(consoleWindow, SIGNAL(romUnload(void)), this, SLOT(onRomUnload(void)));
183184
connect(consoleWindow, SIGNAL(stateLoaded(void)), this, SLOT(onStateLoad(void)));
184185
connect(consoleWindow, SIGNAL(nesResetOccurred(void)), this, SLOT(onNesReset(void)));
186+
connect(consoleWindow, SIGNAL(cheatsChanged(void)), this, SLOT(onCheatsChanged(void)));
185187
connect(consoleWindow, SIGNAL(pauseToggled(bool)), this, SLOT(onPauseToggled(bool)));
186188

187189
FCEU_WRAPPER_LOCK();
@@ -396,22 +398,53 @@ int NetPlayServer::sendRomLoadReq( NetPlayClient *client )
396398
return 0;
397399
}
398400
//-----------------------------------------------------------------------------
401+
struct NetPlayServerCheatQuery
402+
{
403+
int numLoaded = 0;
404+
405+
netPlayLoadStateResp::CheatData data[netPlayLoadStateResp::MaxCheats];
406+
};
407+
408+
static int serverActiveCheatListCB(const char *name, uint32 a, uint8 v, int c, int s, int type, void *data)
409+
{
410+
NetPlayServerCheatQuery* query = static_cast<NetPlayServerCheatQuery*>(data);
411+
412+
const int i = query->numLoaded;
413+
414+
if (i < netPlayLoadStateResp::MaxCheats)
415+
{
416+
auto& cheat = query->data[i];
417+
cheat.addr = a;
418+
cheat.val = v;
419+
cheat.cmp = c;
420+
cheat.type = type;
421+
cheat.stat = s;
422+
Strlcpy( cheat.name, name, sizeof(cheat.name));
423+
424+
query->numLoaded++;
425+
}
426+
427+
return 1;
428+
}
429+
//-----------------------------------------------------------------------------
399430
int NetPlayServer::sendStateSyncReq( NetPlayClient *client )
400431
{
401432
EMUFILE_MEMORY em;
402-
int compressionLevel = 1;
433+
int numCtrlFrames = 0, numCheats = 0, compressionLevel = 1;
403434
static constexpr size_t maxBytesPerWrite = 32 * 1024;
404435
netPlayLoadStateResp resp;
436+
netPlayLoadStateResp::CtrlData ctrlData[netPlayLoadStateResp::MaxCtrlFrames];
437+
NetPlayServerCheatQuery cheatQuery;
405438

406439
if ( GameInfo == nullptr )
407440
{
408441
return -1;
409442
}
410443
FCEUSS_SaveMS( &em, compressionLevel );
411444

412-
resp.hdr.msgSize += em.size();
413445
resp.stateSize = em.size();
414446
resp.opsCrc32 = opsCrc32;
447+
resp.romCrc32 = romCrc32;
415448

416449
NetPlayFrameData lastFrameData;
417450
netPlayFrameData.getLast( lastFrameData );
@@ -428,20 +461,34 @@ int NetPlayServer::sendStateSyncReq( NetPlayClient *client )
428461
{
429462
if (i < netPlayLoadStateResp::MaxCtrlFrames)
430463
{
431-
resp.ctrlData[i].frameNum = inputFrame.frameCounter;
432-
resp.ctrlData[i].ctrlState[0] = inputFrame.ctrl[0];
433-
resp.ctrlData[i].ctrlState[1] = inputFrame.ctrl[1];
434-
resp.ctrlData[i].ctrlState[2] = inputFrame.ctrl[2];
435-
resp.ctrlData[i].ctrlState[3] = inputFrame.ctrl[3];
464+
ctrlData[i].frameNum = netPlayByteSwap(inputFrame.frameCounter);
465+
ctrlData[i].ctrlState[0] = inputFrame.ctrl[0];
466+
ctrlData[i].ctrlState[1] = inputFrame.ctrl[1];
467+
ctrlData[i].ctrlState[2] = inputFrame.ctrl[2];
468+
ctrlData[i].ctrlState[3] = inputFrame.ctrl[3];
436469
i++;
437470
}
438471
}
439-
resp.numCtrlFrames = i;
472+
resp.numCtrlFrames = numCtrlFrames = i;
440473
}
441474

475+
FCEUI_ListCheats(::serverActiveCheatListCB, (void *)&cheatQuery);
476+
resp.numCheats = numCheats = cheatQuery.numLoaded;
477+
478+
resp.calcTotalSize();
479+
442480
printf("Sending ROM Sync Request: %zu\n", em.size());
443481

444482
sendMsg( client, &resp, sizeof(netPlayLoadStateResp), [&resp]{ resp.toNetworkByteOrder(); } );
483+
484+
if (numCtrlFrames > 0)
485+
{
486+
sendMsg( client, ctrlData, numCtrlFrames * sizeof(netPlayLoadStateResp::CtrlData) );
487+
}
488+
if (numCheats > 0)
489+
{
490+
sendMsg( client, &cheatQuery.data, numCheats * sizeof(netPlayLoadStateResp::CheatData) );
491+
}
445492
//sendMsg( client, em.buf(), em.size() );
446493

447494
const unsigned char* bufPtr = em.buf();
@@ -583,6 +630,7 @@ void NetPlayServer::onRomLoad()
583630
//-----------------------------------------------------------------------------
584631
void NetPlayServer::onRomUnload()
585632
{
633+
//printf("ROM UnLoaded!\n");
586634
netPlayMsgHdr unloadMsg(NETPLAY_UNLOAD_ROM_REQ);
587635

588636
romCrc32 = 0;
@@ -642,6 +690,32 @@ void NetPlayServer::onNesReset()
642690
FCEU_WRAPPER_UNLOCK();
643691
}
644692
//-----------------------------------------------------------------------------
693+
void NetPlayServer::onCheatsChanged()
694+
{
695+
//printf("NES Cheats Event!\n");
696+
if (romCrc32 == 0)
697+
{
698+
return;
699+
}
700+
FCEU_WRAPPER_LOCK();
701+
702+
opsCrc32 = 0;
703+
netPlayFrameData.reset();
704+
705+
inputClear();
706+
inputFrameCount = static_cast<uint32_t>(currFrameCounter);
707+
708+
sendPauseAll();
709+
710+
// NES Reset has occurred on server, signal clients sync
711+
for (auto& client : clientList )
712+
{
713+
//sendRomLoadReq( client );
714+
sendStateSyncReq( client );
715+
}
716+
FCEU_WRAPPER_UNLOCK();
717+
}
718+
//-----------------------------------------------------------------------------
645719
void NetPlayServer::onPauseToggled( bool isPaused )
646720
{
647721
if (isPaused)
@@ -1568,6 +1642,11 @@ int NetPlayClient::requestStateLoad(EMUFILE *is)
15681642
{
15691643
printf("Read Error\n");
15701644
}
1645+
1646+
if (currCartInfo != nullptr)
1647+
{
1648+
resp.romCrc32 = romCrc32;
1649+
}
15711650
printf("Sending Client ROM Sync Request: %u\n", resp.stateSize);
15721651

15731652
resp.toNetworkByteOrder();
@@ -1893,6 +1972,7 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
18931972
netPlayLoadStateResp* msg = static_cast<netPlayLoadStateResp*>(msgBuf);
18941973
msg->toHostByteOrder();
18951974

1975+
const bool romMatch = (msg->romCrc32 = romCrc32);
18961976
char *stateData = msg->stateDataBuf();
18971977
const uint32_t stateDataSize = msg->stateDataSize();
18981978

@@ -1901,34 +1981,64 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
19011981
EMUFILE_MEMORY em( stateData, stateDataSize );
19021982

19031983
FCEU_WRAPPER_LOCK();
1904-
serverRequestedStateLoad = true;
1905-
FCEUSS_LoadFP( &em, SSLOADPARAM_NOBACKUP );
1906-
serverRequestedStateLoad = false;
19071984

1908-
opsCrc32 = msg->opsCrc32;
1909-
netPlayFrameData.reset();
1985+
bool dataValid = romMatch;
19101986

1911-
NetPlayFrameData data;
1912-
data.frameNum = msg->lastFrame.num;
1913-
data.opsCrc32 = msg->lastFrame.opsCrc32;
1914-
data.ramCrc32 = msg->lastFrame.ramCrc32;
1987+
if (dataValid)
1988+
{
1989+
serverRequestedStateLoad = true;
1990+
FCEUSS_LoadFP( &em, SSLOADPARAM_NOBACKUP );
1991+
serverRequestedStateLoad = false;
19151992

1916-
netPlayFrameData.push( data );
1993+
opsCrc32 = msg->opsCrc32;
1994+
netPlayFrameData.reset();
19171995

1918-
inputClear();
1996+
NetPlayFrameData data;
1997+
data.frameNum = msg->lastFrame.num;
1998+
data.opsCrc32 = msg->lastFrame.opsCrc32;
1999+
data.ramCrc32 = msg->lastFrame.ramCrc32;
19192000

1920-
const int numInputFrames = msg->numCtrlFrames;
1921-
for (int i=0; i<numInputFrames; i++)
1922-
{
1923-
NetPlayFrameInput inputFrame;
2001+
netPlayFrameData.push( data );
19242002

1925-
inputFrame.frameCounter = msg->ctrlData[i].frameNum;
1926-
inputFrame.ctrl[0] = msg->ctrlData[i].ctrlState[0];
1927-
inputFrame.ctrl[1] = msg->ctrlData[i].ctrlState[1];
1928-
inputFrame.ctrl[2] = msg->ctrlData[i].ctrlState[2];
1929-
inputFrame.ctrl[3] = msg->ctrlData[i].ctrlState[3];
2003+
inputClear();
19302004

1931-
pushBackInput( inputFrame );
2005+
const int numInputFrames = msg->numCtrlFrames;
2006+
for (int i=0; i<numInputFrames; i++)
2007+
{
2008+
NetPlayFrameInput inputFrame;
2009+
auto ctrlData = msg->ctrlDataBuf();
2010+
2011+
ctrlData[i].toHostByteOrder();
2012+
inputFrame.frameCounter = ctrlData[i].frameNum;
2013+
inputFrame.ctrl[0] = ctrlData[i].ctrlState[0];
2014+
inputFrame.ctrl[1] = ctrlData[i].ctrlState[1];
2015+
inputFrame.ctrl[2] = ctrlData[i].ctrlState[2];
2016+
inputFrame.ctrl[3] = ctrlData[i].ctrlState[3];
2017+
2018+
pushBackInput( inputFrame );
2019+
}
2020+
2021+
const int numCheats = msg->numCheats;
2022+
2023+
if (numCheats > 0)
2024+
{
2025+
const int lastCheatIdx = numCheats - 1;
2026+
2027+
FCEU_FlushGameCheats(0, 1);
2028+
for (int i=0; i<numCheats; i++)
2029+
{
2030+
auto cheatBuf = msg->cheatDataBuf();
2031+
auto& cheatData = cheatBuf[i];
2032+
// Set cheat rebuild flag on last item.
2033+
bool lastItem = (i == lastCheatIdx);
2034+
2035+
FCEUI_AddCheat( cheatData.name, cheatData.addr, cheatData.val, cheatData.cmp, cheatData.type, cheatData.stat, lastItem );
2036+
}
2037+
}
2038+
else
2039+
{
2040+
FCEU_DeleteAllCheats();
2041+
}
19322042
}
19332043
FCEU_WRAPPER_UNLOCK();
19342044

@@ -3009,10 +3119,11 @@ uint64_t netPlayByteSwap(uint64_t in)
30093119
//----------------------------------------------------------------------------
30103120
uint32_t netPlayCalcRamChkSum()
30113121
{
3122+
constexpr int ramSize = 0x800;
30123123
uint32_t crc = 0;
3013-
uint8_t ram[256];
3124+
uint8_t ram[ramSize];
30143125

3015-
for (int i=0; i<256; i++)
3126+
for (int i=0; i<ramSize; i++)
30163127
{
30173128
ram[i] = GetMem(i);
30183129
}

src/drivers/Qt/NetPlay.h

+1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ class NetPlayServer : public QTcpServer
190190
void onStateLoad(void);
191191
void onNesReset(void);
192192
void onPauseToggled(bool);
193+
void onCheatsChanged(void);
193194
void processClientRomLoadRequests(void);
194195
void processClientStateLoadRequests(void);
195196
};

0 commit comments

Comments
 (0)