Skip to content

Commit 5697465

Browse files
committed
[GEN][ZH] Refactor the recorder class to use a ramfile for replay playback.
1 parent 3bda27a commit 5697465

File tree

4 files changed

+142
-106
lines changed

4 files changed

+142
-106
lines changed

Generals/Code/GameEngine/Include/Common/Recorder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "Common/MessageStream.h"
2929
#include "GameNetwork/GameInfo.h"
3030

31+
class File;
32+
3133
/**
3234
* The ReplayGameInfo class holds information about the replay game and
3335
* the contents of its slot list for reconstructing multiplayer games.
@@ -154,6 +156,7 @@ class RecorderClass : public SubsystemInterface {
154156

155157
CullBadCommandsResult cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
156158

159+
File* m_replayFile;
157160
FILE *m_file;
158161
AsciiString m_fileName;
159162
Int m_currentFilePosition;

Generals/Code/GameEngine/Source/Common/Recorder.cpp

Lines changed: 68 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
2626

2727
#include "Common/Recorder.h"
28+
#include "Common/file.h"
2829
#include "Common/FileSystem.h"
2930
#include "Common/PlayerList.h"
3031
#include "Common/Player.h"
@@ -368,6 +369,7 @@ RecorderClass::RecorderClass()
368369
m_originalGameMode = GAME_NONE;
369370
m_mode = RECORDERMODETYPE_RECORD;
370371
m_file = NULL;
372+
m_replayFile = NULL;
371373
m_fileName.clear();
372374
m_currentFilePosition = 0;
373375
//Added By Sadullah Nader
@@ -397,6 +399,7 @@ void RecorderClass::init() {
397399
m_originalGameMode = GAME_NONE;
398400
m_mode = RECORDERMODETYPE_NONE;
399401
m_file = NULL;
402+
m_replayFile = NULL;
400403
m_fileName.clear();
401404
m_currentFilePosition = 0;
402405
m_gameInfo.clearSlotList();
@@ -419,6 +422,10 @@ void RecorderClass::reset() {
419422
fclose(m_file);
420423
m_file = NULL;
421424
}
425+
if (m_replayFile != NULL) {
426+
m_replayFile->close();
427+
m_replayFile = NULL;
428+
}
422429
m_fileName.clear();
423430

424431
init();
@@ -472,9 +479,9 @@ void RecorderClass::updatePlayback() {
472479
* reaching the end of the playback file.
473480
*/
474481
void RecorderClass::stopPlayback() {
475-
if (m_file != NULL) {
476-
fclose(m_file);
477-
m_file = NULL;
482+
if (m_replayFile != NULL) {
483+
m_replayFile->close();
484+
m_replayFile = NULL;
478485
}
479486
m_fileName.clear();
480487

@@ -828,52 +835,52 @@ Bool RecorderClass::readReplayHeader(ReplayHeader& header)
828835
{
829836
AsciiString filepath = getReplayDir();
830837
filepath.concat(header.filename.str());
831-
m_file = fopen(filepath.str(), "rb");
832-
if (m_file == NULL)
838+
m_replayFile = TheFileSystem->openFile(filepath.str(), File::READ);
839+
if (m_replayFile == NULL)
833840
{
834841
DEBUG_LOG(("Can't open %s (%s)\n", filepath.str(), header.filename.str()));
835842
return FALSE;
836843
}
837844

838845
// Read the GENREP header.
839846
char genrep[7];
840-
fread(&genrep, sizeof(char), 6, m_file);
847+
m_replayFile->read(&genrep, sizeof(char) * 6);
841848
genrep[6] = 0;
842849
if (strncmp(genrep, "GENREP", 6)) {
843850
DEBUG_LOG(("RecorderClass::readReplayHeader - replay file did not have GENREP at the start.\n"));
844-
fclose(m_file);
845-
m_file = NULL;
851+
m_replayFile->close();
852+
m_replayFile = NULL;
846853
return FALSE;
847854
}
848855

849856
// read in some stats
850857
replay_time_t tmp;
851-
fread(&tmp, sizeof(replay_time_t), 1, m_file);
858+
m_replayFile->read(&tmp, sizeof(replay_time_t));
852859
header.startTime = tmp;
853-
fread(&tmp, sizeof(replay_time_t), 1, m_file);
860+
m_replayFile->read(&tmp, sizeof(replay_time_t));
854861
header.endTime = tmp;
855862

856-
fread(&header.frameCount, sizeof(UnsignedInt), 1, m_file);
863+
m_replayFile->read(&header.frameCount, sizeof(UnsignedInt));
857864

858-
fread(&header.desyncGame, sizeof(Bool), 1, m_file);
859-
fread(&header.quitEarly, sizeof(Bool), 1, m_file);
865+
m_replayFile->read(&header.desyncGame, sizeof(Bool));
866+
m_replayFile->read(&header.quitEarly, sizeof(Bool));
860867
for (Int i=0; i<MAX_SLOTS; ++i)
861868
{
862-
fread(&(header.playerDiscons[i]), sizeof(Bool), 1, m_file);
869+
m_replayFile->read(&(header.playerDiscons[i]), sizeof(Bool));
863870
}
864871

865872
// Read the Replay Name. We don't actually do anything with it. Oh well.
866873
header.replayName = readUnicodeString();
867874

868875
// Read the date and time. We don't really do anything with this either. Oh well.
869-
fread(&header.timeVal, sizeof(SYSTEMTIME), 1, m_file);
876+
m_replayFile->read(&header.timeVal, sizeof(SYSTEMTIME));
870877

871878
// Read in the Version info
872879
header.versionString = readUnicodeString();
873880
header.versionTimeString = readUnicodeString();
874-
fread(&header.versionNumber, sizeof(UnsignedInt), 1, m_file);
875-
fread(&header.exeCRC, sizeof(UnsignedInt), 1, m_file);
876-
fread(&header.iniCRC, sizeof(UnsignedInt), 1, m_file);
881+
m_replayFile->read(&header.versionNumber, sizeof(UnsignedInt));
882+
m_replayFile->read(&header.exeCRC, sizeof(UnsignedInt));
883+
m_replayFile->read(&header.iniCRC, sizeof(UnsignedInt));
877884

878885
// Read in the GameInfo
879886
header.gameOptions = readAsciiString();
@@ -883,8 +890,8 @@ Bool RecorderClass::readReplayHeader(ReplayHeader& header)
883890
if (!ParseAsciiStringToGameInfo(&m_gameInfo, header.gameOptions))
884891
{
885892
DEBUG_LOG(("RecorderClass::readReplayHeader - replay file did not have a valid GameInfo string.\n"));
886-
fclose(m_file);
887-
m_file = NULL;
893+
m_replayFile->close();
894+
m_replayFile = NULL;
888895
return FALSE;
889896
}
890897
m_gameInfo.startGame(0);
@@ -896,8 +903,8 @@ Bool RecorderClass::readReplayHeader(ReplayHeader& header)
896903
DEBUG_LOG(("RecorderClass::readReplayHeader - invalid local slot number.\n"));
897904
m_gameInfo.endGame();
898905
m_gameInfo.reset();
899-
fclose(m_file);
900-
m_file = NULL;
906+
m_replayFile->close();
907+
m_replayFile = NULL;
901908
return FALSE;
902909
}
903910
if (header.localPlayerIndex >= 0)
@@ -910,9 +917,13 @@ Bool RecorderClass::readReplayHeader(ReplayHeader& header)
910917
{
911918
m_gameInfo.endGame();
912919
m_gameInfo.reset();
913-
fclose(m_file);
914-
m_file = NULL;
920+
m_replayFile->close();
921+
m_replayFile = NULL;
922+
}
923+
else {
924+
m_replayFile = m_replayFile->convertToRAMFile();
915925
}
926+
916927
return TRUE;
917928
}
918929

@@ -1210,15 +1221,15 @@ Bool RecorderClass::playbackFile(AsciiString filename)
12101221
DEBUG_LOG(("Player index is %d, replay CRC interval is %d\n", m_crcInfo->getLocalPlayer(), REPLAY_CRC_INTERVAL));
12111222

12121223
Int difficulty = 0;
1213-
fread(&difficulty, sizeof(difficulty), 1, m_file);
1224+
m_replayFile->read(&difficulty, sizeof(difficulty));
12141225

1215-
fread(&m_originalGameMode, sizeof(m_originalGameMode), 1, m_file);
1226+
m_replayFile->read(&m_originalGameMode, sizeof(m_originalGameMode));
12161227

12171228
Int rankPoints = 0;
1218-
fread(&rankPoints, sizeof(rankPoints), 1, m_file);
1229+
m_replayFile->read(&rankPoints, sizeof(rankPoints));
12191230

12201231
Int maxFPS = 0;
1221-
fread(&maxFPS, sizeof(maxFPS), 1, m_file);
1232+
m_replayFile->read(&maxFPS, sizeof(maxFPS));
12221233

12231234
DEBUG_LOG(("RecorderClass::playbackFile() - original game was mode %d\n", m_originalGameMode));
12241235

@@ -1259,15 +1270,17 @@ UnicodeString RecorderClass::readUnicodeString() {
12591270
WideChar str[1024] = L"";
12601271
Int index = 0;
12611272

1262-
Int c = fgetwc(m_file);
1273+
Int c;
1274+
m_replayFile->read(&c, sizeof(WideChar));
12631275
if (c == EOF) {
12641276
str[index] = 0;
12651277
}
12661278
str[index] = c;
12671279

12681280
while (index < 1024 && str[index] != 0) {
12691281
++index;
1270-
Int c = fgetwc(m_file);
1282+
Int c;
1283+
m_replayFile->read(&c, sizeof(WideChar));
12711284
if (c == EOF) {
12721285
str[index] = 0;
12731286
break;
@@ -1287,15 +1300,17 @@ AsciiString RecorderClass::readAsciiString() {
12871300
char str[1024] = "";
12881301
Int index = 0;
12891302

1290-
Int c = fgetc(m_file);
1303+
Int c;
1304+
m_replayFile->read(&c, sizeof(Char));
12911305
if (c == EOF) {
12921306
str[index] = 0;
12931307
}
12941308
str[index] = c;
12951309

12961310
while (index < 1024 && str[index] != 0) {
12971311
++index;
1298-
Int c = fgetc(m_file);
1312+
Int c;
1313+
m_replayFile->read(&c, sizeof(Char));
12991314
if (c == EOF) {
13001315
str[index] = 0;
13011316
break;
@@ -1313,9 +1328,9 @@ AsciiString RecorderClass::readAsciiString() {
13131328
* is stopped and the next frame is said to be -1.
13141329
*/
13151330
void RecorderClass::readNextFrame() {
1316-
Int retcode = fread(&m_nextFrame, sizeof(m_nextFrame), 1, m_file);
1317-
if (retcode != 1) {
1318-
DEBUG_LOG(("RecorderClass::readNextFrame - fread failed on frame %d\n", TheGameLogic->getFrame()));
1331+
Int retcode = m_replayFile->read(&m_nextFrame, sizeof(m_nextFrame));
1332+
if (retcode != sizeof(m_nextFrame)) {
1333+
DEBUG_LOG(("RecorderClass::readNextFrame - read failed on frame %d\n", TheGameLogic->getFrame()));
13191334
m_nextFrame = -1;
13201335
stopPlayback();
13211336
}
@@ -1326,9 +1341,9 @@ void RecorderClass::readNextFrame() {
13261341
*/
13271342
void RecorderClass::appendNextCommand() {
13281343
GameMessage::Type type;
1329-
Int retcode = fread(&type, sizeof(type), 1, m_file);
1330-
if (retcode != 1) {
1331-
DEBUG_LOG(("RecorderClass::appendNextCommand - fread failed on frame %d\n", m_nextFrame/*TheGameLogic->getFrame()*/));
1344+
Int retcode = m_replayFile->read(&type, sizeof(type));
1345+
if (retcode != sizeof(type)) {
1346+
DEBUG_LOG(("RecorderClass::appendNextCommand - read failed on frame %d\n", m_nextFrame/*TheGameLogic->getFrame()*/));
13321347
return;
13331348
}
13341349

@@ -1347,7 +1362,7 @@ void RecorderClass::appendNextCommand() {
13471362
#endif // DEBUG_LOGGING
13481363

13491364
Int playerIndex = -1;
1350-
fread(&playerIndex, sizeof(playerIndex), 1, m_file);
1365+
m_replayFile->read(&playerIndex, sizeof(playerIndex));
13511366
msg->friend_setPlayerIndex(playerIndex);
13521367

13531368
// don't debug log this if we're debugging sync errors, as it will cause diff problems between a game and it's replay...
@@ -1366,14 +1381,14 @@ void RecorderClass::appendNextCommand() {
13661381

13671382
UnsignedByte numTypes = 0;
13681383
Int totalArgs = 0;
1369-
fread(&numTypes, sizeof(numTypes), 1, m_file);
1384+
m_replayFile->read(&numTypes, sizeof(numTypes));
13701385

13711386
GameMessageParser *parser = newInstance(GameMessageParser)();
13721387
for (UnsignedByte i = 0; i < numTypes; ++i) {
13731388
UnsignedByte type = (UnsignedByte)ARGUMENTDATATYPE_UNKNOWN;
1374-
fread(&type, sizeof(type), 1, m_file);
1389+
m_replayFile->read(&type, sizeof(type));
13751390
UnsignedByte numArgs = 0;
1376-
fread(&numArgs, sizeof(numArgs), 1, m_file);
1391+
m_replayFile->read(&numArgs, sizeof(numArgs));
13771392
parser->addArgType((GameMessageArgumentDataType)type, numArgs);
13781393
totalArgs += numArgs;
13791394
}
@@ -1421,7 +1436,7 @@ void RecorderClass::appendNextCommand() {
14211436
void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *msg) {
14221437
if (type == ARGUMENTDATATYPE_INTEGER) {
14231438
Int theint;
1424-
fread(&theint, sizeof(theint), 1, m_file);
1439+
m_replayFile->read(&theint, sizeof(theint));
14251440
msg->appendIntegerArgument(theint);
14261441
#ifdef DEBUG_LOGGING
14271442
if (m_doingAnalysis)
@@ -1431,7 +1446,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14311446
#endif
14321447
} else if (type == ARGUMENTDATATYPE_REAL) {
14331448
Real thereal;
1434-
fread(&thereal, sizeof(thereal), 1, m_file);
1449+
m_replayFile->read(&thereal, sizeof(thereal));
14351450
msg->appendRealArgument(thereal);
14361451
#ifdef DEBUG_LOGGING
14371452
if (m_doingAnalysis)
@@ -1441,7 +1456,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14411456
#endif
14421457
} else if (type == ARGUMENTDATATYPE_BOOLEAN) {
14431458
Bool thebool;
1444-
fread(&thebool, sizeof(thebool), 1, m_file);
1459+
m_replayFile->read(&thebool, sizeof(thebool));
14451460
msg->appendBooleanArgument(thebool);
14461461
#ifdef DEBUG_LOGGING
14471462
if (m_doingAnalysis)
@@ -1451,7 +1466,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14511466
#endif
14521467
} else if (type == ARGUMENTDATATYPE_OBJECTID) {
14531468
ObjectID theid;
1454-
fread(&theid, sizeof(theid), 1, m_file);
1469+
m_replayFile->read(&theid, sizeof(theid));
14551470
msg->appendObjectIDArgument(theid);
14561471
#ifdef DEBUG_LOGGING
14571472
if (m_doingAnalysis)
@@ -1461,7 +1476,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14611476
#endif
14621477
} else if (type == ARGUMENTDATATYPE_DRAWABLEID) {
14631478
DrawableID theid;
1464-
fread(&theid, sizeof(theid), 1, m_file);
1479+
m_replayFile->read(&theid, sizeof(theid));
14651480
msg->appendDrawableIDArgument(theid);
14661481
#ifdef DEBUG_LOGGING
14671482
if (m_doingAnalysis)
@@ -1471,7 +1486,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14711486
#endif
14721487
} else if (type == ARGUMENTDATATYPE_TEAMID) {
14731488
UnsignedInt theid;
1474-
fread(&theid, sizeof(theid), 1, m_file);
1489+
m_replayFile->read(&theid, sizeof(theid));
14751490
msg->appendTeamIDArgument(theid);
14761491
#ifdef DEBUG_LOGGING
14771492
if (m_doingAnalysis)
@@ -1481,7 +1496,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14811496
#endif
14821497
} else if (type == ARGUMENTDATATYPE_LOCATION) {
14831498
Coord3D loc;
1484-
fread(&loc, sizeof(loc), 1, m_file);
1499+
m_replayFile->read(&loc, sizeof(loc));
14851500
msg->appendLocationArgument(loc);
14861501
#ifdef DEBUG_LOGGING
14871502
if (m_doingAnalysis)
@@ -1492,7 +1507,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
14921507
#endif
14931508
} else if (type == ARGUMENTDATATYPE_PIXEL) {
14941509
ICoord2D pixel;
1495-
fread(&pixel, sizeof(pixel), 1, m_file);
1510+
m_replayFile->read(&pixel, sizeof(pixel));
14961511
msg->appendPixelArgument(pixel);
14971512
#ifdef DEBUG_LOGGING
14981513
if (m_doingAnalysis)
@@ -1502,7 +1517,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
15021517
#endif
15031518
} else if (type == ARGUMENTDATATYPE_PIXELREGION) {
15041519
IRegion2D reg;
1505-
fread(&reg, sizeof(reg), 1, m_file);
1520+
m_replayFile->read(&reg, sizeof(reg));
15061521
msg->appendPixelRegionArgument(reg);
15071522
#ifdef DEBUG_LOGGING
15081523
if (m_doingAnalysis)
@@ -1512,7 +1527,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
15121527
#endif
15131528
} else if (type == ARGUMENTDATATYPE_TIMESTAMP) { // Not to be confused with Terrance Stamp... Kneel before Zod!!!
15141529
UnsignedInt stamp;
1515-
fread(&stamp, sizeof(stamp), 1, m_file);
1530+
m_replayFile->read(&stamp, sizeof(stamp));
15161531
msg->appendTimestampArgument(stamp);
15171532
#ifdef DEBUG_LOGGING
15181533
if (m_doingAnalysis)
@@ -1522,7 +1537,7 @@ void RecorderClass::readArgument(GameMessageArgumentDataType type, GameMessage *
15221537
#endif
15231538
} else if (type == ARGUMENTDATATYPE_WIDECHAR) {
15241539
WideChar theid;
1525-
fread(&theid, sizeof(theid), 1, m_file);
1540+
m_replayFile->read(&theid, sizeof(theid));
15261541
msg->appendWideCharArgument(theid);
15271542
#ifdef DEBUG_LOGGING
15281543
if (m_doingAnalysis)

GeneralsMD/Code/GameEngine/Include/Common/Recorder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "Common/MessageStream.h"
2929
#include "GameNetwork/GameInfo.h"
3030

31+
class File;
32+
3133
/**
3234
* The ReplayGameInfo class holds information about the replay game and
3335
* the contents of its slot list for reconstructing multiplayer games.
@@ -154,6 +156,7 @@ class RecorderClass : public SubsystemInterface {
154156

155157
CullBadCommandsResult cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
156158

159+
File* m_replayFile;
157160
FILE *m_file;
158161
AsciiString m_fileName;
159162
Int m_currentFilePosition;

0 commit comments

Comments
 (0)