GB: fix 32/64 bit save/state incompatibility
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>
This commit is contained in:
parent
b9d6f35f8f
commit
98cb298efc
|
@ -2847,7 +2847,7 @@ void gbWriteSaveMBC3(const char* name, bool extendedSave)
|
||||||
if (extendedSave)
|
if (extendedSave)
|
||||||
fwrite(&gbDataMBC3.mapperSeconds,
|
fwrite(&gbDataMBC3.mapperSeconds,
|
||||||
1,
|
1,
|
||||||
10 * sizeof(int) + sizeof(time_t),
|
MBC3_RTC_DATA_SIZE,
|
||||||
gzFile);
|
gzFile);
|
||||||
|
|
||||||
fclose(gzFile);
|
fclose(gzFile);
|
||||||
|
@ -2914,7 +2914,7 @@ void gbWriteSaveTAMA5(const char* name, bool extendedSave)
|
||||||
if (extendedSave)
|
if (extendedSave)
|
||||||
fwrite(&gbDataTAMA5.mapperSeconds,
|
fwrite(&gbDataTAMA5.mapperSeconds,
|
||||||
1,
|
1,
|
||||||
14 * sizeof(int) + sizeof(time_t),
|
TAMA5_RTC_DATA_SIZE,
|
||||||
gzFile);
|
gzFile);
|
||||||
|
|
||||||
fclose(gzFile);
|
fclose(gzFile);
|
||||||
|
@ -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);
|
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;
|
gbBatteryError = true;
|
||||||
res = false;
|
res = false;
|
||||||
} else if ((gbRomType == 0xf) || (gbRomType == 0x10)) {
|
} else if ((gbRomType == 0xf) || (gbRomType == 0x10)) { // read RTC data
|
||||||
read = gzread(gzFile,
|
read = gzread(gzFile,
|
||||||
&gbDataMBC3.mapperSeconds,
|
&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)"),
|
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
|
||||||
name);
|
name);
|
||||||
res = false;
|
res = false;
|
||||||
} else if (read == 0) {
|
}
|
||||||
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
|
else {
|
||||||
name);
|
|
||||||
res = false;
|
|
||||||
} else {
|
|
||||||
// Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
|
// Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
|
||||||
uint8_t data[1];
|
uint8_t data[1];
|
||||||
data[0] = 0;
|
data[0] = 0;
|
||||||
|
@ -3200,13 +3197,9 @@ bool gbReadSaveTAMA5(const char* name)
|
||||||
} else {
|
} else {
|
||||||
read = gzread(gzFile,
|
read = gzread(gzFile,
|
||||||
&gbDataTAMA5.mapperSeconds,
|
&gbDataTAMA5.mapperSeconds,
|
||||||
sizeof(int) * 14 + sizeof(time_t));
|
TAMA5_RTC_DATA_SIZE);
|
||||||
|
|
||||||
if (read != (sizeof(int) * 14 + sizeof(time_t)) && 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;
|
|
||||||
} else if (read == 0) {
|
|
||||||
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
|
systemMessage(MSG_FAILED_TO_READ_RTC, N_("Failed to read RTC from save game %s (continuing)"),
|
||||||
name);
|
name);
|
||||||
res = false;
|
res = false;
|
||||||
|
@ -3736,13 +3729,7 @@ static bool gbReadSaveState(gzFile gzFile)
|
||||||
else
|
else
|
||||||
utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
|
utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
|
||||||
utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
|
utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
|
||||||
if (version < GBSAVE_GAME_VERSION_4)
|
utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
|
||||||
// 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, &gbDataMBC5, sizeof(gbDataMBC5));
|
utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
|
||||||
utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
|
utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
|
||||||
utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
|
utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
|
||||||
|
|
|
@ -308,7 +308,7 @@ mapperMBC3 gbDataMBC3 = {
|
||||||
0, // timer latched hours
|
0, // timer latched hours
|
||||||
0, // timer latched days
|
0, // timer latched days
|
||||||
0, // timer latched control
|
0, // timer latched control
|
||||||
(time_t)-1 // last time
|
0 // last time
|
||||||
};
|
};
|
||||||
|
|
||||||
void memoryUpdateMBC3Clock()
|
void memoryUpdateMBC3Clock()
|
||||||
|
|
|
@ -36,7 +36,10 @@ struct mapperMBC3 {
|
||||||
int mapperLHours;
|
int mapperLHours;
|
||||||
int mapperLDays;
|
int mapperLDays;
|
||||||
int mapperLControl;
|
int mapperLControl;
|
||||||
time_t mapperLastTime;
|
union {
|
||||||
|
time_t mapperLastTime;
|
||||||
|
uint64_t _time_pad; /* so that 32bit and 64bit saves are compatible */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mapperMBC5 {
|
struct mapperMBC5 {
|
||||||
|
@ -118,7 +121,10 @@ struct mapperTAMA5 {
|
||||||
int mapperLMonths;
|
int mapperLMonths;
|
||||||
int mapperLYears;
|
int mapperLYears;
|
||||||
int mapperLControl;
|
int mapperLControl;
|
||||||
time_t mapperLastTime;
|
union {
|
||||||
|
time_t mapperLastTime;
|
||||||
|
uint64_t _time_pad; /* so that 32bit and 64bit saves are compatible */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mapperMMM01 {
|
struct mapperMMM01 {
|
||||||
|
@ -186,4 +192,8 @@ extern void memoryUpdateMapTAMA5();
|
||||||
extern void memoryUpdateMapMMM01();
|
extern void memoryUpdateMapMMM01();
|
||||||
extern void memoryUpdateMapGS3();
|
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
|
#endif // GBMEMORY_H
|
||||||
|
|
|
@ -220,11 +220,11 @@ static size_t gb_rtcdata_size(void)
|
||||||
switch (gbRomType) {
|
switch (gbRomType) {
|
||||||
case 0x0f:
|
case 0x0f:
|
||||||
case 0x10: // MBC3 + extended
|
case 0x10: // MBC3 + extended
|
||||||
return (10 * sizeof(int) + sizeof(time_t));
|
return MBC3_RTC_DATA_SIZE;
|
||||||
break;
|
break;
|
||||||
case 0x13:
|
case 0x13:
|
||||||
case 0xfd: // TAMA5 + extended
|
case 0xfd: // TAMA5 + extended
|
||||||
return (14 * sizeof(int) + sizeof(time_t));
|
return TAMA5_RTC_DATA_SIZE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue