mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
RTC: Automatically detect timezone
Some checks are pending
🐧 Linux Builds / AppImage (push) Waiting to run
🐧 Linux Builds / Flatpak (push) Waiting to run
🍎 MacOS Builds / Defaults (push) Waiting to run
🖥️ Windows Builds / Lint VS Project Files (push) Waiting to run
🖥️ Windows Builds / SSE4 (push) Blocked by required conditions
🖥️ Windows Builds / AVX2 (push) Blocked by required conditions
🖥️ Windows Builds / CMake (push) Waiting to run
Some checks are pending
🐧 Linux Builds / AppImage (push) Waiting to run
🐧 Linux Builds / Flatpak (push) Waiting to run
🍎 MacOS Builds / Defaults (push) Waiting to run
🖥️ Windows Builds / Lint VS Project Files (push) Waiting to run
🖥️ Windows Builds / SSE4 (push) Blocked by required conditions
🖥️ Windows Builds / AVX2 (push) Blocked by required conditions
🖥️ Windows Builds / CMake (push) Waiting to run
This commit is contained in:
parent
e62e6fb6c3
commit
b688117002
@ -164,7 +164,6 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
|
|||||||
dialog()->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
|
dialog()->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
|
||||||
tr("Real-time clock (RTC) used by the virtual PlayStation 2.<br>"
|
tr("Real-time clock (RTC) used by the virtual PlayStation 2.<br>"
|
||||||
"This time is only applied upon booting the PS2; changing it while in-game will have no effect.<br>"
|
"This time is only applied upon booting the PS2; changing it while in-game will have no effect.<br>"
|
||||||
"NOTE: This assumes you have your PS2 set to the default timezone of GMT+0 and default DST of Summer Time.<br>"
|
|
||||||
"Some games require an RTC date/time set after their release date."));
|
"Some games require an RTC date/time set after their release date."));
|
||||||
dialog()->registerWidgetHelp(m_ui.rtcUseSystemLocaleFormat, tr("Use System Locale Format"), tr("User Preference"),
|
dialog()->registerWidgetHelp(m_ui.rtcUseSystemLocaleFormat, tr("Use System Locale Format"), tr("User Preference"),
|
||||||
tr("Uses the operating system's date/time format rather than \"yyyy-MM-dd HH:mm:ss\". May exclude seconds."));
|
tr("Uses the operating system's date/time format rather than \"yyyy-MM-dd HH:mm:ss\". May exclude seconds."));
|
||||||
|
|||||||
@ -37,6 +37,8 @@ cdvdStruct cdvd;
|
|||||||
|
|
||||||
s64 PSXCLK = 36864000;
|
s64 PSXCLK = 36864000;
|
||||||
|
|
||||||
|
static constexpr s32 GMT9_OFFSET_SECONDS = 9 * 60 * 60; // 32400
|
||||||
|
|
||||||
static constexpr u8 monthmap[13] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
static constexpr u8 monthmap[13] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
|
||||||
static constexpr u8 cdvdParamLength[16] = { 0, 0, 0, 0, 0, 4, 11, 11, 11, 1, 255, 255, 7, 2, 11, 1 };
|
static constexpr u8 cdvdParamLength[16] = { 0, 0, 0, 0, 0, 4, 11, 11, 11, 1, 255, 255, 7, 2, 11, 1 };
|
||||||
@ -920,69 +922,92 @@ void cdvdReset()
|
|||||||
cdvd.ReadTime = cdvdBlockReadTime(MODE_DVDROM);
|
cdvd.ReadTime = cdvdBlockReadTime(MODE_DVDROM);
|
||||||
cdvd.RotSpeed = cdvdRotationTime(MODE_DVDROM);
|
cdvd.RotSpeed = cdvdRotationTime(MODE_DVDROM);
|
||||||
|
|
||||||
|
ReadOSDConfigParames();
|
||||||
|
|
||||||
|
// Print time zone offset, DST, time format, date format, and system time basis.
|
||||||
|
DevCon.WriteLn(Color_StrongGreen, configParams1.timezoneOffset < 0 ? "Time Zone Offset: GMT%03d:%02d" : "Time Zone Offset: GMT+%02d:%02d",
|
||||||
|
configParams1.timezoneOffset / 60, std::abs(configParams1.timezoneOffset % 60));
|
||||||
|
DevCon.WriteLn(Color_StrongGreen, "DST: %s Time", configParams2.daylightSavings ? "Summer" : "Winter");
|
||||||
|
DevCon.WriteLn(Color_StrongGreen, "Time Format: %s-Hour", configParams2.timeFormat ? "12" : "24");
|
||||||
|
DevCon.WriteLn(Color_StrongGreen, "Date Format: %s", configParams2.dateFormat ? (configParams2.dateFormat == 2 ? "DD/MM/YYYY" : "MM/DD/YYYY") : "YYYY/MM/DD");
|
||||||
|
DevCon.WriteLn(Color_StrongGreen, "System Time Basis: %s",
|
||||||
|
EmuConfig.ManuallySetRealTimeClock ? "Manual RTC" : g_InputRecording.isActive() ? "Default Input Recording Time" : "Operating System Time");
|
||||||
|
|
||||||
|
std::tm input_tm{};
|
||||||
|
std::tm resulting_tm{};
|
||||||
|
|
||||||
|
const int bios_settings_offset_seconds = 60 * (configParams1.timezoneOffset + configParams2.daylightSavings * 60);
|
||||||
|
|
||||||
|
// CDVD internally uses GMT+9, 1-indexed months, and year offset of 2000 instead of 1900.
|
||||||
|
// tm struct uses 0-indexed months and year offset of 1900.
|
||||||
if (EmuConfig.ManuallySetRealTimeClock)
|
if (EmuConfig.ManuallySetRealTimeClock)
|
||||||
{
|
{
|
||||||
// Convert to GMT+9 (assumes GMT+0)
|
resulting_tm.tm_sec = EmuConfig.RtcSecond;
|
||||||
std::tm tm{};
|
resulting_tm.tm_min = EmuConfig.RtcMinute;
|
||||||
tm.tm_sec = EmuConfig.RtcSecond;
|
resulting_tm.tm_hour = EmuConfig.RtcHour;
|
||||||
tm.tm_min = EmuConfig.RtcMinute;
|
resulting_tm.tm_mday = EmuConfig.RtcDay;
|
||||||
tm.tm_hour = EmuConfig.RtcHour;
|
resulting_tm.tm_mon = EmuConfig.RtcMonth - 1;
|
||||||
tm.tm_mday = EmuConfig.RtcDay;
|
resulting_tm.tm_year = EmuConfig.RtcYear + 100;
|
||||||
tm.tm_mon = EmuConfig.RtcMonth - 1;
|
resulting_tm.tm_isdst = 0;
|
||||||
tm.tm_year = EmuConfig.RtcYear + 100; // 2000 - 1900
|
|
||||||
tm.tm_isdst = 1;
|
|
||||||
|
|
||||||
// Need this instead of mktime for timezone independence
|
// Work backwards to input time by accounting for BIOS settings and GMT+9 defaultism.
|
||||||
std::time_t t = 0;
|
#if defined(_WIN32)
|
||||||
#if defined(_WIN32)
|
const std::time_t input_time = _mkgmtime(&resulting_tm) + GMT9_OFFSET_SECONDS - bios_settings_offset_seconds;
|
||||||
t = _mkgmtime(&tm) + 32400; //60 * 60 * 9 for GMT+9
|
gmtime_s(&input_tm, &input_time);
|
||||||
gmtime_s(&tm, &t);
|
#else
|
||||||
#else
|
const std::time_t input_time = timegm(&resulting_tm) + GMT9_OFFSET_SECONDS - bios_settings_offset_seconds;
|
||||||
t = timegm(&tm) + 32400;
|
gmtime_r(&input_time, &input_tm);
|
||||||
gmtime_r(&t, &tm);
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
cdvd.RTC.second = tm.tm_sec;
|
|
||||||
cdvd.RTC.minute = tm.tm_min;
|
|
||||||
cdvd.RTC.hour = tm.tm_hour;
|
|
||||||
cdvd.RTC.day = tm.tm_mday;
|
|
||||||
cdvd.RTC.month = tm.tm_mon + 1;
|
|
||||||
cdvd.RTC.year = tm.tm_year - 100;
|
|
||||||
}
|
}
|
||||||
// If we are recording, always use the same RTC setting
|
|
||||||
// for games that use the RTC to seed their RNG -- this is very important to be the same everytime!
|
|
||||||
else if (g_InputRecording.isActive())
|
else if (g_InputRecording.isActive())
|
||||||
{
|
{
|
||||||
Console.WriteLn("Input Recording Active - Using Constant RTC of 04-03-2020 (DD-MM-YYYY)");
|
// Default input recording value (2020-03-04 00:00:00) if manual RTC is off. Well beyond any PS2 game's release date.
|
||||||
// Why not just 0 everything? Some games apparently require the date to be valid in terms of when
|
// Some games require a valid date in terms of when the PS2 / game actually came out (see: MGS3).
|
||||||
// the PS2 / Game actually came out. (MGS3). So set it to a value well beyond any PS2 game's release date.
|
// Changing this will ruin compat with old input recordings (RNG seeding).
|
||||||
cdvd.RTC.second = 0;
|
input_tm.tm_sec = 0;
|
||||||
cdvd.RTC.minute = 0;
|
input_tm.tm_min = 0;
|
||||||
cdvd.RTC.hour = 0;
|
input_tm.tm_hour = 0;
|
||||||
cdvd.RTC.day = 4;
|
input_tm.tm_mday = 4;
|
||||||
cdvd.RTC.month = 3;
|
input_tm.tm_mon = 2;
|
||||||
cdvd.RTC.year = 20;
|
input_tm.tm_year = 120;
|
||||||
|
input_tm.tm_isdst = 0;
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
const std::time_t resulting_time = _mkgmtime(&input_tm) - GMT9_OFFSET_SECONDS + bios_settings_offset_seconds;
|
||||||
|
gmtime_s(&resulting_tm, &resulting_time);
|
||||||
|
#else
|
||||||
|
const std::time_t resulting_time = timegm(&input_tm) - GMT9_OFFSET_SECONDS + bios_settings_offset_seconds;
|
||||||
|
gmtime_r(&resulting_time, &resulting_tm);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// CDVD internally uses GMT+9. If you think the time's wrong, you're wrong.
|
// User must set time zone and winter/summer DST in the BIOS for correct time.
|
||||||
// Set up your time zone and winter/summer in the BIOS. No PS2 BIOS I know of features automatic DST.
|
const std::time_t input_time = std::time(nullptr) + GMT9_OFFSET_SECONDS;
|
||||||
const std::time_t utc_time = std::time(nullptr);
|
const std::time_t resulting_time = input_time - GMT9_OFFSET_SECONDS + bios_settings_offset_seconds;
|
||||||
const std::time_t gmt9_time = (utc_time + 32400); //60 * 60 * 9
|
|
||||||
struct tm curtime = {};
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
gmtime_s(&curtime, &gmt9_time);
|
gmtime_s(&input_tm, &input_time);
|
||||||
|
gmtime_s(&resulting_tm, &resulting_time);
|
||||||
#else
|
#else
|
||||||
gmtime_r(&gmt9_time, &curtime);
|
gmtime_r(&input_time, &input_tm);
|
||||||
|
gmtime_r(&resulting_time, &resulting_tm);
|
||||||
#endif
|
#endif
|
||||||
cdvd.RTC.second = static_cast<u8>(curtime.tm_sec);
|
|
||||||
cdvd.RTC.minute = static_cast<u8>(curtime.tm_min);
|
|
||||||
cdvd.RTC.hour = static_cast<u8>(curtime.tm_hour);
|
|
||||||
cdvd.RTC.day = static_cast<u8>(curtime.tm_mday);
|
|
||||||
cdvd.RTC.month = static_cast<u8>(curtime.tm_mon + 1); // WX returns Jan as "0"
|
|
||||||
cdvd.RTC.year = static_cast<u8>(curtime.tm_year - 100); // offset from 2000
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send completed input time to the CDVD.
|
||||||
|
cdvd.RTC.second = static_cast<u8>(input_tm.tm_sec);
|
||||||
|
cdvd.RTC.minute = static_cast<u8>(input_tm.tm_min);
|
||||||
|
cdvd.RTC.hour = static_cast<u8>(input_tm.tm_hour);
|
||||||
|
cdvd.RTC.day = static_cast<u8>(input_tm.tm_mday);
|
||||||
|
cdvd.RTC.month = static_cast<u8>(input_tm.tm_mon + 1);
|
||||||
|
cdvd.RTC.year = static_cast<u8>(input_tm.tm_year - 100);
|
||||||
|
|
||||||
|
// Print time that will appear in the user's BIOS rather than input time.
|
||||||
|
DevCon.WriteLn(Color_StrongGreen, "Resulting System Time: 20%02u-%02u-%02u %02u:%02u:%02u",
|
||||||
|
resulting_tm.tm_year - 100, resulting_tm.tm_mon + 1, resulting_tm.tm_mday,
|
||||||
|
resulting_tm.tm_hour, resulting_tm.tm_min, resulting_tm.tm_sec);
|
||||||
|
|
||||||
cdvdCtrlTrayClose();
|
cdvdCtrlTrayClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1314,7 +1314,7 @@ struct Pcsx2Config
|
|||||||
InhibitScreensaver : 1,
|
InhibitScreensaver : 1,
|
||||||
BackupSavestate : 1,
|
BackupSavestate : 1,
|
||||||
McdFolderAutoManage : 1,
|
McdFolderAutoManage : 1,
|
||||||
ManuallySetRealTimeClock : 1,
|
ManuallySetRealTimeClock : 1, // passes user-set real-time clock information to cdvd at startup
|
||||||
UseSystemLocaleFormat : 1, // presents OS time format instead of yyyy-MM-dd HH:mm:ss for manual RTC
|
UseSystemLocaleFormat : 1, // presents OS time format instead of yyyy-MM-dd HH:mm:ss for manual RTC
|
||||||
|
|
||||||
HostFs : 1,
|
HostFs : 1,
|
||||||
|
|||||||
@ -68,6 +68,9 @@ void ReadOSDConfigParames()
|
|||||||
|
|
||||||
// Region settings for time/date and extended language
|
// Region settings for time/date and extended language
|
||||||
configParams2.UC[1] = ((u32)params[3] & 0x78) << 1; // Daylight Savings, 24hr clock, Date format
|
configParams2.UC[1] = ((u32)params[3] & 0x78) << 1; // Daylight Savings, 24hr clock, Date format
|
||||||
|
configParams2.daylightSavings = configParams2.UC[1] & 0x10 ? 1 : 0;
|
||||||
|
configParams2.timeFormat = configParams2.UC[1] & 0x20 ? 1 : 0;
|
||||||
|
configParams2.dateFormat = configParams2.UC[1] & 0x80 ? 2 : (configParams2.UC[1] & 0x40 ? 1 : 0);
|
||||||
// FIXME: format, version and language are set manually by the bios. Not sure if any game needs them, but it seems to set version to 2 and duplicate the language value.
|
// FIXME: format, version and language are set manually by the bios. Not sure if any game needs them, but it seems to set version to 2 and duplicate the language value.
|
||||||
configParams2.version = 2;
|
configParams2.version = 2;
|
||||||
configParams2.language = configParams1.language;
|
configParams2.language = configParams1.language;
|
||||||
|
|||||||
@ -43,7 +43,7 @@ typedef struct
|
|||||||
/** LANGUAGE_??? value */
|
/** LANGUAGE_??? value */
|
||||||
/*16*/ u32 language : 5;
|
/*16*/ u32 language : 5;
|
||||||
/** timezone minutes offset from gmt */
|
/** timezone minutes offset from gmt */
|
||||||
/*21*/ u32 timezoneOffset : 11;
|
/*21*/ s32 timezoneOffset : 11;
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 UC[4];
|
u8 UC[4];
|
||||||
@ -63,7 +63,7 @@ typedef struct
|
|||||||
|
|
||||||
/*00*/ u8 reserved : 4;
|
/*00*/ u8 reserved : 4;
|
||||||
/** 0=standard(winter), 1=daylight savings(summer) */
|
/** 0=standard(winter), 1=daylight savings(summer) */
|
||||||
/*04*/ u8 daylightSaving : 1;
|
/*04*/ u8 daylightSavings : 1;
|
||||||
/** 0=24 hour, 1=12 hour */
|
/** 0=24 hour, 1=12 hour */
|
||||||
/*05*/ u8 timeFormat : 1;
|
/*05*/ u8 timeFormat : 1;
|
||||||
/** 0=YYYYMMDD, 1=MMDDYYYY, 2=DDMMYYYY */
|
/** 0=YYYYMMDD, 1=MMDDYYYY, 2=DDMMYYYY */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user