libretro: Use GB RTC data when available

- Save GB RTC data using retro_get_memory/size and only init using localtime when its unavailable (check is done in retro_run)
This commit is contained in:
retro-wertz 2019-08-10 18:24:32 +08:00
parent b3744b3bd5
commit 03184dd513
3 changed files with 148 additions and 112 deletions

View File

@ -195,6 +195,7 @@ int gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS;
// emulator features // emulator features
int gbBattery = 0; int gbBattery = 0;
int gbRumble = 0; int gbRumble = 0;
int gbRTCPresent = 0;
bool gbBatteryError = false; bool gbBatteryError = false;
int gbCaptureNumber = 0; int gbCaptureNumber = 0;
bool gbCapture = false; bool gbCapture = false;
@ -4360,8 +4361,6 @@ bool gbUpdateSizes()
memset(gbRam, gbRamFill, gbRamSize); memset(gbRam, gbRamFill, gbRamSize);
} }
gbBattery = gbRumble = 0;
switch (gbRomType) { switch (gbRomType) {
case 0x03: case 0x03:
case 0x06: case 0x06:
@ -4377,6 +4376,9 @@ bool gbUpdateSizes()
case 0xff: case 0xff:
gbBattery = 1; gbBattery = 1;
break; break;
default:
gbBattery = 0;
break;
} }
switch (gbRomType) { switch (gbRomType) {
@ -4384,6 +4386,21 @@ bool gbUpdateSizes()
case 0x1d: case 0x1d:
case 0x1e: case 0x1e:
gbRumble = 1; gbRumble = 1;
break;
default:
gbRumble = 0;
break;
}
switch (gbRomType) {
case 0x0f:
case 0x10: // mbc3
case 0xfd: // tama5
gbRTCPresent = 1;
break;
default:
gbRTCPresent = 0;
break;
} }
gbInit(); gbInit();

View File

@ -62,6 +62,7 @@ bool allowColorizerHack(void);
extern int gbHardware; extern int gbHardware;
extern int gbRomType; // gets type from header 0x147 extern int gbRomType; // gets type from header 0x147
extern int gbBattery; // enabled when gbRamSize != 0 extern int gbBattery; // enabled when gbRamSize != 0
extern int gbRTCPresent; // gbROM has RTC support
extern struct EmulatedSystem GBSystem; extern struct EmulatedSystem GBSystem;

View File

@ -216,99 +216,76 @@ static void set_gbPalette(void)
} }
} }
static bool gb_hasrtc(void) static void* gb_rtcdata_prt(void)
{ {
switch (gbRomType) { switch (gbRomType) {
case 0x0f: case 0x0f:
case 0x10: // MBC3 + extended case 0x10: // MBC3 + extended
case 0x13: return &gbDataMBC3.mapperSeconds;
case 0xfd: // TAMA5 + extended case 0xfd: // TAMA5 + extended
return true; return &gbDataTAMA5.mapperSeconds;
}
return false;
}
static void* gb_rtcdata_prt(void)
{
if (gb_hasrtc()) {
switch (gbRomType) {
case 0x0f:
case 0x10: // MBC3 + extended
return &gbDataMBC3.mapperSeconds;
case 0x13:
case 0xfd: // TAMA5 + extended
return &gbDataTAMA5.mapperSeconds;
}
} }
return NULL; return NULL;
} }
static size_t gb_rtcdata_size(void) static size_t gb_rtcdata_size(void)
{ {
if (gb_hasrtc()) { switch (gbRomType) {
switch (gbRomType) { case 0x0f:
case 0x0f: case 0x10: // MBC3 + extended
case 0x10: // MBC3 + extended return MBC3_RTC_DATA_SIZE;
return MBC3_RTC_DATA_SIZE; case 0xfd: // TAMA5 + extended
break; return TAMA5_RTC_DATA_SIZE;
case 0x13:
case 0xfd: // TAMA5 + extended
return TAMA5_RTC_DATA_SIZE;
break;
}
} }
return 0; return 0;
} }
static void gbUpdateRTC(void) static void gbInitRTC(void)
{ {
if (gb_hasrtc()) { struct tm* lt;
struct tm* lt; time_t rawtime;
time_t rawtime; time(&rawtime);
time(&rawtime); lt = localtime(&rawtime);
lt = localtime(&rawtime);
switch (gbRomType) { switch (gbRomType) {
case 0x0f: case 0x0f:
case 0x10: { case 0x10:
gbDataMBC3.mapperSeconds = lt->tm_sec; gbDataMBC3.mapperSeconds = lt->tm_sec;
gbDataMBC3.mapperMinutes = lt->tm_min; gbDataMBC3.mapperMinutes = lt->tm_min;
gbDataMBC3.mapperHours = lt->tm_hour; gbDataMBC3.mapperHours = lt->tm_hour;
gbDataMBC3.mapperDays = lt->tm_yday & 255; gbDataMBC3.mapperDays = lt->tm_yday & 255;
gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | (lt->tm_yday > 255 ? 1 : 0); gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | (lt->tm_yday > 255 ? 1 : 0);
gbDataMBC3.mapperLastTime = rawtime; gbDataMBC3.mapperLastTime = rawtime;
} break;
break; case 0xfd: {
case 0xfd: { uint8_t gbDaysinMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
uint8_t gbDaysinMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int days = lt->tm_yday + 365 * 3;
gbDataTAMA5.mapperSeconds = lt->tm_sec; gbDataTAMA5.mapperSeconds = lt->tm_sec;
gbDataTAMA5.mapperMinutes = lt->tm_min; gbDataTAMA5.mapperMinutes = lt->tm_min;
gbDataTAMA5.mapperHours = lt->tm_hour; gbDataTAMA5.mapperHours = lt->tm_hour;
gbDataTAMA5.mapperDays = 1; gbDataTAMA5.mapperDays = 1;
gbDataTAMA5.mapperMonths = 1; gbDataTAMA5.mapperMonths = 1;
gbDataTAMA5.mapperYears = 1970; gbDataTAMA5.mapperYears = 1970;
gbDataTAMA5.mapperLastTime = rawtime; gbDataTAMA5.mapperLastTime = rawtime;
int days = lt->tm_yday + 365 * 3; while (days) {
while (days) { gbDataTAMA5.mapperDays++;
gbDataTAMA5.mapperDays++; days--;
days--; if (gbDataTAMA5.mapperDays > gbDaysinMonth[gbDataTAMA5.mapperMonths - 1]) {
if (gbDataTAMA5.mapperDays > gbDaysinMonth[gbDataTAMA5.mapperMonths - 1]) { gbDataTAMA5.mapperDays = 1;
gbDataTAMA5.mapperDays = 1; gbDataTAMA5.mapperMonths++;
gbDataTAMA5.mapperMonths++; if (gbDataTAMA5.mapperMonths > 12) {
if (gbDataTAMA5.mapperMonths > 12) { gbDataTAMA5.mapperMonths = 1;
gbDataTAMA5.mapperMonths = 1; gbDataTAMA5.mapperYears++;
gbDataTAMA5.mapperYears++; if ((gbDataTAMA5.mapperYears & 3) == 0)
if ((gbDataTAMA5.mapperYears & 3) == 0) gbDaysinMonth[1] = 29;
gbDaysinMonth[1] = 29; else
else gbDaysinMonth[1] = 28;
gbDaysinMonth[1] = 28;
}
} }
} }
gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) | (lt->tm_yday > 255 ? 1 : 0);
} }
break; gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) | (lt->tm_yday > 255 ? 1 : 0);
} }
break;
} }
} }
@ -343,70 +320,91 @@ static void SetGBBorder(unsigned val)
void* retro_get_memory_data(unsigned id) void* retro_get_memory_data(unsigned id)
{ {
if (type == IMAGE_GBA) { void *data = NULL;
switch (type) {
case IMAGE_GBA:
switch (id) { switch (id) {
case RETRO_MEMORY_SAVE_RAM: case RETRO_MEMORY_SAVE_RAM:
if ((saveType == GBA_SAVE_EEPROM) | (saveType == GBA_SAVE_EEPROM_SENSOR)) if ((saveType == GBA_SAVE_EEPROM) | (saveType == GBA_SAVE_EEPROM_SENSOR))
return eepromData; data = eepromData;
if ((saveType == GBA_SAVE_SRAM) | (saveType == GBA_SAVE_FLASH)) else if ((saveType == GBA_SAVE_SRAM) | (saveType == GBA_SAVE_FLASH))
return flashSaveMemory; data = flashSaveMemory;
return NULL; break;
case RETRO_MEMORY_SYSTEM_RAM: case RETRO_MEMORY_SYSTEM_RAM:
return workRAM; data = workRAM;
break;
case RETRO_MEMORY_VIDEO_RAM: case RETRO_MEMORY_VIDEO_RAM:
return vram; data = vram;
break;
} }
}
if (type == IMAGE_GB) { case IMAGE_GB:
switch (id) { switch (id) {
case RETRO_MEMORY_SAVE_RAM: case RETRO_MEMORY_SAVE_RAM:
if (gbBattery) if (gbBattery)
return gbRam; data = gbRam;
return NULL; break;
case RETRO_MEMORY_SYSTEM_RAM: case RETRO_MEMORY_SYSTEM_RAM:
return (gbCgbMode ? gbWram : (gbMemory + 0xC000)); data = (gbCgbMode ? gbWram : (gbMemory + 0xC000));
break;
case RETRO_MEMORY_VIDEO_RAM: case RETRO_MEMORY_VIDEO_RAM:
return (gbCgbMode ? gbVram : (gbMemory + 0x8000)); data = (gbCgbMode ? gbVram : (gbMemory + 0x8000));
break;
case RETRO_MEMORY_RTC:
if (gbBattery && gbRTCPresent)
data = gb_rtcdata_prt();
break;
} }
}
return NULL; default: break;
}
return data;
} }
size_t retro_get_memory_size(unsigned id) size_t retro_get_memory_size(unsigned id)
{ {
if (type == IMAGE_GBA) { size_t size = 0;
switch (type) {
case IMAGE_GBA:
switch (id) { switch (id) {
case RETRO_MEMORY_SAVE_RAM: case RETRO_MEMORY_SAVE_RAM:
if ((saveType == GBA_SAVE_EEPROM) | (saveType == GBA_SAVE_EEPROM_SENSOR)) if ((saveType == GBA_SAVE_EEPROM) | (saveType == GBA_SAVE_EEPROM_SENSOR))
return eepromSize; size = eepromSize;
if (saveType == GBA_SAVE_FLASH) else if (saveType == GBA_SAVE_FLASH)
return flashSize; size = flashSize;
if (saveType == GBA_SAVE_SRAM) else if (saveType == GBA_SAVE_SRAM)
return SIZE_SRAM; size = SIZE_SRAM;
return 0; break;
case RETRO_MEMORY_SYSTEM_RAM: case RETRO_MEMORY_SYSTEM_RAM:
return SIZE_WRAM; size = SIZE_WRAM;
break;
case RETRO_MEMORY_VIDEO_RAM: case RETRO_MEMORY_VIDEO_RAM:
return SIZE_VRAM - 0x2000; // usuable vram is only 0x18000 size = SIZE_VRAM - 0x2000; // usuable vram is only 0x18000
break;
} }
}
if (type == IMAGE_GB) { case IMAGE_GB:
switch (id) { switch (id) {
case RETRO_MEMORY_SAVE_RAM: case RETRO_MEMORY_SAVE_RAM:
if (gbBattery) if (gbBattery)
return gbRamSize; size = gbRamSize;
return 0; break;
case RETRO_MEMORY_SYSTEM_RAM: case RETRO_MEMORY_SYSTEM_RAM:
return gbCgbMode ? 0x8000 : 0x2000; size = gbCgbMode ? 0x8000 : 0x2000;
break;
case RETRO_MEMORY_VIDEO_RAM: case RETRO_MEMORY_VIDEO_RAM:
return gbCgbMode ? 0x4000 : 0x2000; size = gbCgbMode ? 0x4000 : 0x2000;
break;
case RETRO_MEMORY_RTC:
size = gb_rtcdata_size();
break;
} }
}
return 0; default: break;
}
return size;
} }
unsigned retro_api_version(void) unsigned retro_api_version(void)
@ -932,10 +930,6 @@ static void gb_init(void)
gbReset(); // also resets sound; gbReset(); // also resets sound;
set_gbPalette(); set_gbPalette();
// VBA-M always updates time based on current time and not in-game time.
// No need to add RTC data to RETRO_MEMORY_RTC, so its safe to place this here.
gbUpdateRTC();
log("Rom size : %02x (%dK)\n", gbRom[0x148], (romSize + 1023) / 1024); log("Rom size : %02x (%dK)\n", gbRom[0x148], (romSize + 1023) / 1024);
log("Cartridge type : %02x (%s)\n", gbRom[0x147], gbGetCartridgeType()); log("Cartridge type : %02x (%s)\n", gbRom[0x147], gbGetCartridgeType());
log("Ram size : %02x (%s)\n", gbRom[0x149], gbGetSaveRamSize()); log("Ram size : %02x (%s)\n", gbRom[0x149], gbGetSaveRamSize());
@ -1368,12 +1362,37 @@ void updateInput_SolarSensor(void)
} }
} }
static bool firstrun = true;
static unsigned has_frame; static unsigned has_frame;
void retro_run(void) void retro_run(void)
{ {
bool updated = false; bool updated = false;
if (firstrun) {
bool initRTC = false;
firstrun = false;
/* Check if GB game has RTC data. Has to be check here since this is where the data will be
* available when using libretro api. */
if ((type == IMAGE_GB) && gbRTCPresent) {
switch (gbRomType) {
case 0x0f:
case 0x10:
/* Check if any RTC has been loaded, zero value means nothing has been loaded. */
if (!gbDataMBC3.mapperSeconds && !gbDataMBC3.mapperLSeconds && !gbDataMBC3.mapperLastTime)
initRTC = true;
break;
case 0xfd:
if (!gbDataTAMA5.mapperSeconds && !gbDataTAMA5.mapperLSeconds && !gbDataTAMA5.mapperLastTime)
initRTC = true;
break;
}
/* Initialize RTC using local time if needed */
if (initRTC)
gbInitRTC();
}
}
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
update_variables(false); update_variables(false);
@ -1384,9 +1403,8 @@ void retro_run(void)
has_frame = 0; has_frame = 0;
do { while (!has_frame)
core->emuMain(core->emuCount); core->emuMain(core->emuCount);
} while (!has_frame);
} }
static unsigned serialize_size = 0; static unsigned serialize_size = 0;