Skip to content

Commit 59e5b4e

Browse files
authored
[ZH] Fix replay header mismatch between builds using 32 bit or 64 bit wide time_t (#765)
1 parent 933e1de commit 59e5b4e

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,17 @@ Int REPLAY_CRC_INTERVAL = 100;
5656
const char *replayExtention = ".rep";
5757
const char *lastReplayFileName = "00000000"; // a name the user is unlikely to ever type, but won't cause panic & confusion
5858

59+
// TheSuperHackers @tweak helmutbuhler 25/04/2025
60+
// The replay header contains two time fields; startTime and endTime of type time_t.
61+
// time_t is 32 bit wide on VC6, but on newer compilers it is 64 bit wide.
62+
// In order to remain compatible we need to load and save time values with 32 bits.
63+
// Note that this will overflow on January 18, 2038. @todo Upgrade to 64 bits when we break compatibility.
64+
typedef int32_t replay_time_t;
65+
5966
static time_t startTime;
6067
static const UnsignedInt startTimeOffset = 6;
61-
static const UnsignedInt endTimeOffset = startTimeOffset + sizeof(time_t);
62-
static const UnsignedInt framesOffset = endTimeOffset + sizeof(time_t);
68+
static const UnsignedInt endTimeOffset = startTimeOffset + sizeof(replay_time_t);
69+
static const UnsignedInt framesOffset = endTimeOffset + sizeof(replay_time_t);
6370
static const UnsignedInt desyncOffset = framesOffset + sizeof(UnsignedInt);
6471
static const UnsignedInt quitEarlyOffset = desyncOffset + sizeof(Bool);
6572
static const UnsignedInt disconOffset = quitEarlyOffset + sizeof(Bool);
@@ -75,7 +82,8 @@ void RecorderClass::logGameStart(AsciiString options)
7582
if (!fseek(m_file, startTimeOffset, SEEK_SET))
7683
{
7784
// save off start time
78-
fwrite(&startTime, sizeof(time_t), 1, m_file);
85+
replay_time_t tmp = (replay_time_t)startTime;
86+
fwrite(&tmp, sizeof(replay_time_t), 1, m_file);
7987
}
8088
// move back to end of stream
8189
#ifdef DEBUG_CRASHING
@@ -229,7 +237,8 @@ void RecorderClass::logGameEnd( void )
229237
if (!fseek(m_file, endTimeOffset, SEEK_SET))
230238
{
231239
// save off end time
232-
fwrite(&t, sizeof(time_t), 1, m_file);
240+
replay_time_t tmp = (replay_time_t)t;
241+
fwrite(&tmp, sizeof(replay_time_t), 1, m_file);
233242
}
234243
// move to appropriate offset
235244
if (!fseek(m_file, framesOffset, SEEK_SET))
@@ -555,9 +564,9 @@ void RecorderClass::startRecording(GameDifficulty diff, Int originalGameMode, In
555564
//
556565
// **** if this changes, change the LAN Playtest code above ****
557566
//
558-
time_t t = 0;
559-
fwrite(&t, sizeof(time_t), 1, m_file); // reserve space for start time
560-
fwrite(&t, sizeof(time_t), 1, m_file); // reserve space for end time
567+
replay_time_t t = 0;
568+
fwrite(&t, sizeof(replay_time_t), 1, m_file); // reserve space for start time
569+
fwrite(&t, sizeof(replay_time_t), 1, m_file); // reserve space for end time
561570

562571
UnsignedInt frames = 0;
563572
fwrite(&frames, sizeof(UnsignedInt), 1, m_file); // reserve space for duration in frames
@@ -834,8 +843,11 @@ Bool RecorderClass::readReplayHeader(ReplayHeader& header)
834843
}
835844

836845
// read in some stats
837-
fread(&header.startTime, sizeof(time_t), 1, m_file);
838-
fread(&header.endTime, sizeof(time_t), 1, m_file);
846+
replay_time_t tmp;
847+
fread(&tmp, sizeof(replay_time_t), 1, m_file);
848+
header.startTime = tmp;
849+
fread(&tmp, sizeof(replay_time_t), 1, m_file);
850+
header.endTime = tmp;
839851

840852
fread(&header.frameDuration, sizeof(UnsignedInt), 1, m_file);
841853

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,17 @@ Int REPLAY_CRC_INTERVAL = 100;
5656
const char *replayExtention = ".rep";
5757
const char *lastReplayFileName = "00000000"; // a name the user is unlikely to ever type, but won't cause panic & confusion
5858

59+
// TheSuperHackers @tweak helmutbuhler 25/04/2025
60+
// The replay header contains two time fields; startTime and endTime of type time_t.
61+
// time_t is 32 bit wide on VC6, but on newer compilers it is 64 bit wide.
62+
// In order to remain compatible we need to load and save time values with 32 bits.
63+
// Note that this will overflow on January 18, 2038. @todo Upgrade to 64 bits when we break compatibility.
64+
typedef int32_t replay_time_t;
65+
5966
static time_t startTime;
6067
static const UnsignedInt startTimeOffset = 6;
61-
static const UnsignedInt endTimeOffset = startTimeOffset + sizeof(time_t);
62-
static const UnsignedInt framesOffset = endTimeOffset + sizeof(time_t);
68+
static const UnsignedInt endTimeOffset = startTimeOffset + sizeof(replay_time_t);
69+
static const UnsignedInt framesOffset = endTimeOffset + sizeof(replay_time_t);
6370
static const UnsignedInt desyncOffset = framesOffset + sizeof(UnsignedInt);
6471
static const UnsignedInt quitEarlyOffset = desyncOffset + sizeof(Bool);
6572
static const UnsignedInt disconOffset = quitEarlyOffset + sizeof(Bool);
@@ -75,7 +82,8 @@ void RecorderClass::logGameStart(AsciiString options)
7582
if (!fseek(m_file, startTimeOffset, SEEK_SET))
7683
{
7784
// save off start time
78-
fwrite(&startTime, sizeof(time_t), 1, m_file);
85+
replay_time_t tmp = (replay_time_t)startTime;
86+
fwrite(&tmp, sizeof(replay_time_t), 1, m_file);
7987
}
8088
// move back to end of stream
8189
#ifdef DEBUG_CRASHING
@@ -229,7 +237,8 @@ void RecorderClass::logGameEnd( void )
229237
if (!fseek(m_file, endTimeOffset, SEEK_SET))
230238
{
231239
// save off end time
232-
fwrite(&t, sizeof(time_t), 1, m_file);
240+
replay_time_t tmp = (replay_time_t)t;
241+
fwrite(&tmp, sizeof(replay_time_t), 1, m_file);
233242
}
234243
// move to appropriate offset
235244
if (!fseek(m_file, framesOffset, SEEK_SET))
@@ -557,9 +566,9 @@ void RecorderClass::startRecording(GameDifficulty diff, Int originalGameMode, In
557566
//
558567
// **** if this changes, change the LAN code above ****
559568
//
560-
time_t t = 0;
561-
fwrite(&t, sizeof(time_t), 1, m_file); // reserve space for start time
562-
fwrite(&t, sizeof(time_t), 1, m_file); // reserve space for end time
569+
replay_time_t t = 0;
570+
fwrite(&t, sizeof(replay_time_t), 1, m_file); // reserve space for start time
571+
fwrite(&t, sizeof(replay_time_t), 1, m_file); // reserve space for end time
563572

564573
UnsignedInt frames = 0;
565574
fwrite(&frames, sizeof(UnsignedInt), 1, m_file); // reserve space for duration in frames
@@ -836,8 +845,11 @@ Bool RecorderClass::readReplayHeader(ReplayHeader& header)
836845
}
837846

838847
// read in some stats
839-
fread(&header.startTime, sizeof(time_t), 1, m_file);
840-
fread(&header.endTime, sizeof(time_t), 1, m_file);
848+
replay_time_t tmp;
849+
fread(&tmp, sizeof(replay_time_t), 1, m_file);
850+
header.startTime = tmp;
851+
fread(&tmp, sizeof(replay_time_t), 1, m_file);
852+
header.endTime = tmp;
841853

842854
fread(&header.frameDuration, sizeof(UnsignedInt), 1, m_file);
843855

0 commit comments

Comments
 (0)