25
25
26
26
#include " ../../fceu.h"
27
27
#include " ../../cart.h"
28
+ #include " ../../cheat.h"
28
29
#include " ../../state.h"
29
30
#include " ../../movie.h"
30
31
#include " ../../debug.h"
@@ -182,6 +183,7 @@ NetPlayServer::NetPlayServer(QObject *parent)
182
183
connect (consoleWindow, SIGNAL (romUnload (void )), this , SLOT (onRomUnload (void )));
183
184
connect (consoleWindow, SIGNAL (stateLoaded (void )), this , SLOT (onStateLoad (void )));
184
185
connect (consoleWindow, SIGNAL (nesResetOccurred (void )), this , SLOT (onNesReset (void )));
186
+ connect (consoleWindow, SIGNAL (cheatsChanged (void )), this , SLOT (onCheatsChanged (void )));
185
187
connect (consoleWindow, SIGNAL (pauseToggled (bool )), this , SLOT (onPauseToggled (bool )));
186
188
187
189
FCEU_WRAPPER_LOCK ();
@@ -396,22 +398,53 @@ int NetPlayServer::sendRomLoadReq( NetPlayClient *client )
396
398
return 0 ;
397
399
}
398
400
// -----------------------------------------------------------------------------
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
+ // -----------------------------------------------------------------------------
399
430
int NetPlayServer::sendStateSyncReq ( NetPlayClient *client )
400
431
{
401
432
EMUFILE_MEMORY em;
402
- int compressionLevel = 1 ;
433
+ int numCtrlFrames = 0 , numCheats = 0 , compressionLevel = 1 ;
403
434
static constexpr size_t maxBytesPerWrite = 32 * 1024 ;
404
435
netPlayLoadStateResp resp;
436
+ netPlayLoadStateResp::CtrlData ctrlData[netPlayLoadStateResp::MaxCtrlFrames];
437
+ NetPlayServerCheatQuery cheatQuery;
405
438
406
439
if ( GameInfo == nullptr )
407
440
{
408
441
return -1 ;
409
442
}
410
443
FCEUSS_SaveMS ( &em, compressionLevel );
411
444
412
- resp.hdr .msgSize += em.size ();
413
445
resp.stateSize = em.size ();
414
446
resp.opsCrc32 = opsCrc32;
447
+ resp.romCrc32 = romCrc32;
415
448
416
449
NetPlayFrameData lastFrameData;
417
450
netPlayFrameData.getLast ( lastFrameData );
@@ -428,20 +461,34 @@ int NetPlayServer::sendStateSyncReq( NetPlayClient *client )
428
461
{
429
462
if (i < netPlayLoadStateResp::MaxCtrlFrames)
430
463
{
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 ];
436
469
i++;
437
470
}
438
471
}
439
- resp.numCtrlFrames = i;
472
+ resp.numCtrlFrames = numCtrlFrames = i;
440
473
}
441
474
475
+ FCEUI_ListCheats (::serverActiveCheatListCB, (void *)&cheatQuery);
476
+ resp.numCheats = numCheats = cheatQuery.numLoaded ;
477
+
478
+ resp.calcTotalSize ();
479
+
442
480
printf (" Sending ROM Sync Request: %zu\n " , em.size ());
443
481
444
482
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
+ }
445
492
// sendMsg( client, em.buf(), em.size() );
446
493
447
494
const unsigned char * bufPtr = em.buf ();
@@ -583,6 +630,7 @@ void NetPlayServer::onRomLoad()
583
630
// -----------------------------------------------------------------------------
584
631
void NetPlayServer::onRomUnload ()
585
632
{
633
+ // printf("ROM UnLoaded!\n");
586
634
netPlayMsgHdr unloadMsg (NETPLAY_UNLOAD_ROM_REQ);
587
635
588
636
romCrc32 = 0 ;
@@ -642,6 +690,32 @@ void NetPlayServer::onNesReset()
642
690
FCEU_WRAPPER_UNLOCK ();
643
691
}
644
692
// -----------------------------------------------------------------------------
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
+ // -----------------------------------------------------------------------------
645
719
void NetPlayServer::onPauseToggled ( bool isPaused )
646
720
{
647
721
if (isPaused)
@@ -1568,6 +1642,11 @@ int NetPlayClient::requestStateLoad(EMUFILE *is)
1568
1642
{
1569
1643
printf (" Read Error\n " );
1570
1644
}
1645
+
1646
+ if (currCartInfo != nullptr )
1647
+ {
1648
+ resp.romCrc32 = romCrc32;
1649
+ }
1571
1650
printf (" Sending Client ROM Sync Request: %u\n " , resp.stateSize );
1572
1651
1573
1652
resp.toNetworkByteOrder ();
@@ -1893,6 +1972,7 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
1893
1972
netPlayLoadStateResp* msg = static_cast <netPlayLoadStateResp*>(msgBuf);
1894
1973
msg->toHostByteOrder ();
1895
1974
1975
+ const bool romMatch = (msg->romCrc32 = romCrc32);
1896
1976
char *stateData = msg->stateDataBuf ();
1897
1977
const uint32_t stateDataSize = msg->stateDataSize ();
1898
1978
@@ -1901,34 +1981,64 @@ void NetPlayClient::clientProcessMessage( void *msgBuf, size_t msgSize )
1901
1981
EMUFILE_MEMORY em ( stateData, stateDataSize );
1902
1982
1903
1983
FCEU_WRAPPER_LOCK ();
1904
- serverRequestedStateLoad = true ;
1905
- FCEUSS_LoadFP ( &em, SSLOADPARAM_NOBACKUP );
1906
- serverRequestedStateLoad = false ;
1907
1984
1908
- opsCrc32 = msg->opsCrc32 ;
1909
- netPlayFrameData.reset ();
1985
+ bool dataValid = romMatch;
1910
1986
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 ;
1915
1992
1916
- netPlayFrameData.push ( data );
1993
+ opsCrc32 = msg->opsCrc32 ;
1994
+ netPlayFrameData.reset ();
1917
1995
1918
- inputClear ();
1996
+ NetPlayFrameData data;
1997
+ data.frameNum = msg->lastFrame .num ;
1998
+ data.opsCrc32 = msg->lastFrame .opsCrc32 ;
1999
+ data.ramCrc32 = msg->lastFrame .ramCrc32 ;
1919
2000
1920
- const int numInputFrames = msg->numCtrlFrames ;
1921
- for (int i=0 ; i<numInputFrames; i++)
1922
- {
1923
- NetPlayFrameInput inputFrame;
2001
+ netPlayFrameData.push ( data );
1924
2002
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 ();
1930
2004
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
+ }
1932
2042
}
1933
2043
FCEU_WRAPPER_UNLOCK ();
1934
2044
@@ -3009,10 +3119,11 @@ uint64_t netPlayByteSwap(uint64_t in)
3009
3119
// ----------------------------------------------------------------------------
3010
3120
uint32_t netPlayCalcRamChkSum ()
3011
3121
{
3122
+ constexpr int ramSize = 0x800 ;
3012
3123
uint32_t crc = 0 ;
3013
- uint8_t ram[256 ];
3124
+ uint8_t ram[ramSize ];
3014
3125
3015
- for (int i=0 ; i<256 ; i++)
3126
+ for (int i=0 ; i<ramSize ; i++)
3016
3127
{
3017
3128
ram[i] = GetMem (i);
3018
3129
}
0 commit comments