Skip to content

Commit

Permalink
GB: fix 32/64 bit save/state incompatibility
Browse files Browse the repository at this point in the history
The MBC3 and TAMA5 battery formats save the RTC data including a
`time_t` field which is the last field.

Since `time_t` is 32 bits for 32 bit builds and 64 bits for 64 bit
builds, pad it in the two battery structs with a `uint64_t` and detect
the 4 byte shorter saves made by older 32 bit builds.

Also remove some pointless code in save state reading that also uses
`sizeof(time_t)`.

Add two new constants for RTC data size in gbMemory.h and use them.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
  • Loading branch information
rkitover committed Feb 23, 2019
1 parent b9d6f35 commit 98cb298
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 28 deletions.
33 changes: 10 additions & 23 deletions src/gb/GB.cpp
Expand Up @@ -2847,7 +2847,7 @@ void gbWriteSaveMBC3(const char* name, bool extendedSave)
if (extendedSave)
fwrite(&gbDataMBC3.mapperSeconds,
1,
10 * sizeof(int) + sizeof(time_t),
MBC3_RTC_DATA_SIZE,
gzFile);

fclose(gzFile);
Expand Down Expand Up @@ -2914,7 +2914,7 @@ void gbWriteSaveTAMA5(const char* name, bool extendedSave)
if (extendedSave)
fwrite(&gbDataTAMA5.mapperSeconds,
1,
14 * sizeof(int) + sizeof(time_t),
TAMA5_RTC_DATA_SIZE,
gzFile);

fclose(gzFile);
Expand Down Expand Up @@ -3049,20 +3049,17 @@ bool gbReadSaveMBC3(const char* name)
N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
gbBatteryError = true;
res = false;
} else if ((gbRomType == 0xf) || (gbRomType == 0x10)) {
} else if ((gbRomType == 0xf) || (gbRomType == 0x10)) { // read RTC data
read = gzread(gzFile,
&gbDataMBC3.mapperSeconds,
sizeof(int) * 10 + sizeof(time_t));
MBC3_RTC_DATA_SIZE);

if (read != (sizeof(int) * 10 + sizeof(time_t)) && read != 0) {
if (!read || (read != MBC3_RTC_DATA_SIZE && read != MBC3_RTC_DATA_SIZE - 4)) { // detect old 32 bit saves
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
name);
res = false;
} else if (read == 0) {
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
name);
res = false;
} else {
}
else {
// Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
uint8_t data[1];
data[0] = 0;
Expand Down Expand Up @@ -3200,13 +3197,9 @@ bool gbReadSaveTAMA5(const char* name)
} else {
read = gzread(gzFile,
&gbDataTAMA5.mapperSeconds,
sizeof(int) * 14 + sizeof(time_t));
TAMA5_RTC_DATA_SIZE);

if (read != (sizeof(int) * 14 + sizeof(time_t)) && read != 0) {
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
name);
res = false;
} else if (read == 0) {
if (!read || (read != TAMA5_RTC_DATA_SIZE && read != TAMA5_RTC_DATA_SIZE - 4)) { // detect old 32 bit saves
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
name);
res = false;
Expand Down Expand Up @@ -3736,13 +3729,7 @@ static bool gbReadSaveState(gzFile gzFile)
else
utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
if (version < GBSAVE_GAME_VERSION_4)
// prior to version 4, there was no adjustment for the time the game
// was last played, so we have less to read. This needs update if the
// structure changes again.
utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3) - sizeof(time_t));
else
utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
Expand Down
2 changes: 1 addition & 1 deletion src/gb/gbMemory.cpp
Expand Up @@ -308,7 +308,7 @@ mapperMBC3 gbDataMBC3 = {
0, // timer latched hours
0, // timer latched days
0, // timer latched control
(time_t)-1 // last time
0 // last time
};

void memoryUpdateMBC3Clock()
Expand Down
14 changes: 12 additions & 2 deletions src/gb/gbMemory.h
Expand Up @@ -36,7 +36,10 @@ struct mapperMBC3 {
int mapperLHours;
int mapperLDays;
int mapperLControl;
time_t mapperLastTime;
union {
time_t mapperLastTime;
uint64_t _time_pad; /* so that 32bit and 64bit saves are compatible */
};
};

struct mapperMBC5 {
Expand Down Expand Up @@ -118,7 +121,10 @@ struct mapperTAMA5 {
int mapperLMonths;
int mapperLYears;
int mapperLControl;
time_t mapperLastTime;
union {
time_t mapperLastTime;
uint64_t _time_pad; /* so that 32bit and 64bit saves are compatible */
};
};

struct mapperMMM01 {
Expand Down Expand Up @@ -186,4 +192,8 @@ extern void memoryUpdateMapTAMA5();
extern void memoryUpdateMapMMM01();
extern void memoryUpdateMapGS3();

#define MBC3_RTC_DATA_SIZE sizeof(int) * 10 + sizeof(uint64_t)

#define TAMA5_RTC_DATA_SIZE sizeof(int) * 14 + sizeof(uint64_t)

#endif // GBMEMORY_H
4 changes: 2 additions & 2 deletions src/libretro/libretro.cpp
Expand Up @@ -220,11 +220,11 @@ static size_t gb_rtcdata_size(void)
switch (gbRomType) {
case 0x0f:
case 0x10: // MBC3 + extended
return (10 * sizeof(int) + sizeof(time_t));
return MBC3_RTC_DATA_SIZE;
break;
case 0x13:
case 0xfd: // TAMA5 + extended
return (14 * sizeof(int) + sizeof(time_t));
return TAMA5_RTC_DATA_SIZE;
break;
}
}
Expand Down

0 comments on commit 98cb298

Please sign in to comment.