HuC3: Refactoring to avoid breaking savestates

Savestates are broken due to the change in savestate struct size for
HuC3. Since save/load function also includes save data for other
non-active mappers, the change in size breaks every savesfiles being
made.

This PR refactors the HuC3 clock data struct to be separate from the
main struct, and then only added to save/load functions when HuC3 mapper
is used. This still breaks previous HuC3 states but other mappers should
now not get affected

Solution:
Savestate/LoadState should only include mapper data of current active
running rom, not all mappers even if they are inactive. This will break
every savefile but it would be better for the long run when changes are
neede to be done.
This commit is contained in:
negativeExponent 2021-05-25 12:08:08 +08:00
parent 5187d70e30
commit 93084990b2
4 changed files with 62 additions and 39 deletions

View File

@ -5515,6 +5515,8 @@ unsigned int gbWriteSaveState(uint8_t* data, unsigned)
utilWriteMem(data, &gbDataMBC5, sizeof(gbDataMBC5));
utilWriteMem(data, &gbDataHuC1, sizeof(gbDataHuC1));
utilWriteMem(data, &gbDataHuC3, sizeof(gbDataHuC3));
if (gbRomType == 0xfe) // HuC3 rtc data
utilWriteMem(data, &gbRTCHuC3, sizeof(gbRTCHuC3));
utilWriteMem(data, &gbDataTAMA5, sizeof(gbDataTAMA5));
if (gbTAMA5ram != NULL)
utilWriteMem(data, gbTAMA5ram, gbTAMA5ramSize);
@ -5632,6 +5634,8 @@ bool gbReadSaveState(const uint8_t* data, unsigned)
utilReadMem(&gbDataMBC5, data, sizeof(gbDataMBC5));
utilReadMem(&gbDataHuC1, data, sizeof(gbDataHuC1));
utilReadMem(&gbDataHuC3, data, sizeof(gbDataHuC3));
if (gbRomType == 0xfe) // HuC3 rtc data
utilReadMem(&gbRTCHuC3, data, sizeof(gbRTCHuC3));
utilReadMem(&gbDataTAMA5, data, sizeof(gbDataTAMA5));
if (gbTAMA5ram != NULL) {
utilReadMem(gbTAMA5ram, data, gbTAMA5ramSize);

View File

@ -1000,31 +1000,40 @@ mapperHuC3 gbDataHuC3 = {
0, // RAM read value
0, // Register 1
0, // Register 2
0, // Register 3
0, // Register 4
0, // Register 5
0, // Register 6
0, // Register 7
0 // Register 8
};
mapperHuC3RTC gbRTCHuC3 = {
0, // lastTime
0, // DateTime
0, // WritingTime
0, // ModeFlag
0, // ClockShift
0 // lastTime
0 // ClockShift
};
void memoryupdateHuC3Latch() {
uint64_t now = time(NULL);
uint64_t diff = now - gbDataHuC3.mapperLastTime;
uint64_t diff = now - gbRTCHuC3.mapperLastTime;
if (diff > 0) {
unsigned minute = (diff / 60) % 1440;
unsigned day = (diff / 86400) & 0xFFF;
gbDataHuC3.mapperDateTime = (day << 12) | minute;
gbRTCHuC3.mapperDateTime = (day << 12) | minute;
}
}
void memoryupdateHuC3Clock() {
uint64_t now = time(NULL);
unsigned minute = (gbDataHuC3.mapperWritingTime & 0xFFF) % 1440;
unsigned day = (gbDataHuC3.mapperWritingTime & 0xFFF000) >> 12;
unsigned minute = (gbRTCHuC3.mapperWritingTime & 0xFFF) % 1440;
unsigned day = (gbRTCHuC3.mapperWritingTime & 0xFFF000) >> 12;
gbDataHuC3.mapperLastTime = now - minute * 60 - day * 86400;
gbRTCHuC3.mapperLastTime = now - minute * 60 - day * 86400;
}
// HuC3 ROM write registers
@ -1108,11 +1117,11 @@ void mapperHuC3RAM(uint16_t address, uint8_t value)
// read time
memoryupdateHuC3Latch();
if (gbDataHuC3.mapperModeFlag == HUC3_READ) {
gbDataHuC3.mapperRAMValue = (gbDataHuC3.mapperDateTime >> gbDataHuC3.mapperClockShift) & 0x0F;
gbDataHuC3.mapperClockShift += 4;
if (gbDataHuC3.mapperClockShift > 24)
gbDataHuC3.mapperClockShift = 0;
if (gbRTCHuC3.mapperModeFlag == HUC3_READ) {
gbDataHuC3.mapperRAMValue = (gbRTCHuC3.mapperDateTime >> gbRTCHuC3.mapperClockShift) & 0x0F;
gbRTCHuC3.mapperClockShift += 4;
if (gbRTCHuC3.mapperClockShift > 24)
gbRTCHuC3.mapperClockShift = 0;
}
break;
case 0x30:
@ -1123,15 +1132,15 @@ void mapperHuC3RAM(uint16_t address, uint8_t value)
gbDataHuC3.mapperAddress = (gbDataHuC3.mapperRegister6 << 24) | (gbDataHuC3.mapperRegister5 << 16) | (gbDataHuC3.mapperRegister4 << 8) | (gbDataHuC3.mapperRegister3 << 4) | (gbDataHuC3.mapperRegister2);*/
// write time
if (gbDataHuC3.mapperModeFlag == HUC3_WRITE) {
if (gbDataHuC3.mapperClockShift == 0)
gbDataHuC3.mapperWritingTime = 0;
if (gbDataHuC3.mapperClockShift <= 24) {
gbDataHuC3.mapperWritingTime |= (value & 0x0F) << gbDataHuC3.mapperClockShift;
gbDataHuC3.mapperClockShift += 4;
if (gbDataHuC3.mapperClockShift == 24) {
if (gbRTCHuC3.mapperModeFlag == HUC3_WRITE) {
if (gbRTCHuC3.mapperClockShift == 0)
gbRTCHuC3.mapperWritingTime = 0;
if (gbRTCHuC3.mapperClockShift <= 24) {
gbRTCHuC3.mapperWritingTime |= (value & 0x0F) << gbRTCHuC3.mapperClockShift;
gbRTCHuC3.mapperClockShift += 4;
if (gbRTCHuC3.mapperClockShift == 24) {
memoryupdateHuC3Clock();
gbDataHuC3.mapperModeFlag = HUC3_READ;
gbRTCHuC3.mapperModeFlag = HUC3_READ;
}
}
}
@ -1151,16 +1160,16 @@ void mapperHuC3RAM(uint16_t address, uint8_t value)
switch(value & 0x0F) {
case 0x0:
// shift reset?
gbDataHuC3.mapperClockShift = 0;
gbRTCHuC3.mapperClockShift = 0;
break;
case 0x3:
// write time?
gbDataHuC3.mapperModeFlag = HUC3_WRITE;
gbDataHuC3.mapperClockShift = 0;
gbRTCHuC3.mapperModeFlag = HUC3_WRITE;
gbRTCHuC3.mapperClockShift = 0;
break;
case 0x7:
gbDataHuC3.mapperModeFlag = HUC3_READ;
gbDataHuC3.mapperClockShift = 0;
gbRTCHuC3.mapperModeFlag = HUC3_READ;
gbRTCHuC3.mapperClockShift = 0;
break;
// others are unimplemented so far
}
@ -1169,7 +1178,7 @@ void mapperHuC3RAM(uint16_t address, uint8_t value)
//gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) | ((value << 4) & 0x0f);
break;
case 0x60:
gbDataHuC3.mapperModeFlag = HUC3_READ; // ???
gbRTCHuC3.mapperModeFlag = HUC3_READ; // ???
gbDataHuC3.mapperRAMValue = 1;
break;
default:

View File

@ -77,12 +77,6 @@ struct mapperHuC1 {
int mapperRAMAddress;
};
enum {
HUC3_READ = 0,
HUC3_WRITE = 1,
HUC3_NONE = 2
};
struct mapperHuC3 {
int mapperRAMEnable;
int mapperROMBank;
@ -93,14 +87,29 @@ struct mapperHuC3 {
int mapperRAMValue;
int mapperRegister1;
int mapperRegister2;
int mapperDateTime;
int mapperWritingTime;
int mapperModeFlag;
int mapperClockShift;
int mapperRegister3;
int mapperRegister4;
int mapperRegister5;
int mapperRegister6;
int mapperRegister7;
int mapperRegister8;
};
enum {
HUC3_READ = 0,
HUC3_WRITE = 1,
HUC3_NONE = 2
};
struct mapperHuC3RTC {
union {
time_t mapperLastTime;
uint64_t _time_pad; /* so that 32bit and 64bit saves are compatible */
};
uint32_t mapperDateTime;
uint32_t mapperWritingTime;
uint32_t mapperModeFlag;
uint32_t mapperClockShift;
};
struct mapperTAMA5 {
@ -155,6 +164,7 @@ extern mapperMBC3 gbDataMBC3;
extern mapperMBC5 gbDataMBC5;
extern mapperHuC1 gbDataHuC1;
extern mapperHuC3 gbDataHuC3;
extern mapperHuC3RTC gbRTCHuC3;
extern mapperTAMA5 gbDataTAMA5;
extern mapperMMM01 gbDataMMM01;
extern mapperGS3 gbDataGS3;

View File

@ -173,7 +173,7 @@ static void* gb_rtcdata_prt(void)
case 0xfd: // TAMA5 + extended
return &gbDataTAMA5.mapperSeconds;
case 0xfe: // HuC3 + Clock
return &gbDataHuC3.mapperDateTime;
return &gbRTCHuC3.mapperLastTime;
}
return NULL;
}
@ -187,7 +187,7 @@ static size_t gb_rtcdata_size(void)
case 0xfd: // TAMA5 + extended
return TAMA5_RTC_DATA_SIZE;
case 0xfe: // HuC3 + Clock
return HUC3_RTC_DATA_SIZE;
return sizeof(gbRTCHuC3);
}
return 0;
}
@ -1438,7 +1438,7 @@ void retro_run(void)
initRTC = true;
break;
case 0xfe:
if (!gbDataHuC3.mapperLastTime)
if (!gbRTCHuC3.mapperLastTime)
initRTC = true;
break;
}