@@ -37,6 +37,8 @@ cdvdStruct cdvd;
3737
3838s64 PSXCLK = 36864000 ;
3939
40+ static constexpr s32 GMT9_OFFSET_SECONDS = 9 * 60 * 60 ; // 32400
41+
4042static constexpr u8 monthmap[13 ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
4143
4244static 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()
920922 cdvd.ReadTime = cdvdBlockReadTime (MODE_DVDROM);
921923 cdvd.RotSpeed = cdvdRotationTime (MODE_DVDROM);
922924
925+ ReadOSDConfigParames ();
926+
927+ // Print time zone offset, DST, time format, date format, and system time basis.
928+ DevCon.WriteLn (Color_StrongGreen, configParams1.timezoneOffset < 0 ? " Time Zone Offset: GMT%03d:%02d" : " Time Zone Offset: GMT+%02d:%02d" ,
929+ configParams1.timezoneOffset / 60 , std::abs (configParams1.timezoneOffset % 60 ));
930+ DevCon.WriteLn (Color_StrongGreen, " DST: %s Time" , configParams2.daylightSavings ? " Summer" : " Winter" );
931+ DevCon.WriteLn (Color_StrongGreen, " Time Format: %s-Hour" , configParams2.timeFormat ? " 12" : " 24" );
932+ DevCon.WriteLn (Color_StrongGreen, " Date Format: %s" , configParams2.dateFormat ? (configParams2.dateFormat == 2 ? " DD/MM/YYYY" : " MM/DD/YYYY" ) : " YYYY/MM/DD" );
933+ DevCon.WriteLn (Color_StrongGreen, " System Time Basis: %s" ,
934+ EmuConfig.ManuallySetRealTimeClock ? " Manual RTC" : g_InputRecording.isActive () ? " Default Input Recording Time" : " Operating System Time" );
935+
936+ std::tm input_tm{};
937+ std::tm resulting_tm{};
938+
939+ const int bios_settings_offset_seconds = 60 * (configParams1.timezoneOffset + configParams2.daylightSavings * 60 );
940+
941+ // CDVD internally uses GMT+9, 1-indexed months, and year offset of 2000 instead of 1900.
942+ // tm struct uses 0-indexed months and year offset of 1900.
923943 if (EmuConfig.ManuallySetRealTimeClock )
924944 {
925- // Convert to GMT+9 (assumes GMT+0)
926- std::tm tm{};
927- tm.tm_sec = EmuConfig.RtcSecond ;
928- tm.tm_min = EmuConfig.RtcMinute ;
929- tm.tm_hour = EmuConfig.RtcHour ;
930- tm.tm_mday = EmuConfig.RtcDay ;
931- tm.tm_mon = EmuConfig.RtcMonth - 1 ;
932- tm.tm_year = EmuConfig.RtcYear + 100 ; // 2000 - 1900
933- tm.tm_isdst = 1 ;
934-
935- // Need this instead of mktime for timezone independence
936- std::time_t t = 0 ;
937- #if defined(_WIN32)
938- t = _mkgmtime (&tm) + 32400 ; // 60 * 60 * 9 for GMT+9
939- gmtime_s (&tm, &t);
940- #else
941- t = timegm (&tm) + 32400 ;
942- gmtime_r (&t, &tm);
943- #endif
944-
945- cdvd.RTC .second = tm.tm_sec ;
946- cdvd.RTC .minute = tm.tm_min ;
947- cdvd.RTC .hour = tm.tm_hour ;
948- cdvd.RTC .day = tm.tm_mday ;
949- cdvd.RTC .month = tm.tm_mon + 1 ;
950- cdvd.RTC .year = tm.tm_year - 100 ;
951- }
952- // If we are recording, always use the same RTC setting
953- // for games that use the RTC to seed their RNG -- this is very important to be the same everytime!
945+ resulting_tm.tm_sec = EmuConfig.RtcSecond ;
946+ resulting_tm.tm_min = EmuConfig.RtcMinute ;
947+ resulting_tm.tm_hour = EmuConfig.RtcHour ;
948+ resulting_tm.tm_mday = EmuConfig.RtcDay ;
949+ resulting_tm.tm_mon = EmuConfig.RtcMonth - 1 ;
950+ resulting_tm.tm_year = EmuConfig.RtcYear + 100 ;
951+ resulting_tm.tm_isdst = 0 ;
952+
953+ // Work backwards to input time by accounting for BIOS settings and GMT+9 defaultism.
954+ #if defined(_WIN32)
955+ const std::time_t input_time = _mkgmtime (&resulting_tm) + GMT9_OFFSET_SECONDS - bios_settings_offset_seconds;
956+ gmtime_s (&input_tm, &input_time);
957+ #else
958+ const std::time_t input_time = timegm (&resulting_tm) + GMT9_OFFSET_SECONDS - bios_settings_offset_seconds;
959+ gmtime_r (&input_time, &input_tm);
960+ #endif
961+ }
954962 else if (g_InputRecording.isActive ())
955963 {
956- Console.WriteLn (" Input Recording Active - Using Constant RTC of 04-03-2020 (DD-MM-YYYY)" );
957- // Why not just 0 everything? Some games apparently require the date to be valid in terms of when
958- // the PS2 / Game actually came out. (MGS3). So set it to a value well beyond any PS2 game's release date.
959- cdvd.RTC .second = 0 ;
960- cdvd.RTC .minute = 0 ;
961- cdvd.RTC .hour = 0 ;
962- cdvd.RTC .day = 4 ;
963- cdvd.RTC .month = 3 ;
964- cdvd.RTC .year = 20 ;
964+ // Default input recording value (2020-03-04 00:00:00) if manual RTC is off. Well beyond any PS2 game's release date.
965+ // Some games require a valid date in terms of when the PS2 / game actually came out (see: MGS3).
966+ // Changing this will ruin compat with old input recordings (RNG seeding).
967+ input_tm.tm_sec = 0 ;
968+ input_tm.tm_min = 0 ;
969+ input_tm.tm_hour = 0 ;
970+ input_tm.tm_mday = 4 ;
971+ input_tm.tm_mon = 2 ;
972+ input_tm.tm_year = 120 ;
973+ input_tm.tm_isdst = 0 ;
974+
975+ #if defined(_WIN32)
976+ const std::time_t resulting_time = _mkgmtime (&input_tm) - GMT9_OFFSET_SECONDS + bios_settings_offset_seconds;
977+ gmtime_s (&resulting_tm, &resulting_time);
978+ #else
979+ const std::time_t resulting_time = timegm (&input_tm) - GMT9_OFFSET_SECONDS + bios_settings_offset_seconds;
980+ gmtime_r (&resulting_time, &resulting_tm);
981+ #endif
965982 }
966983 else
967984 {
968- // CDVD internally uses GMT+9. If you think the time's wrong, you're wrong.
969- // Set up your time zone and winter/summer in the BIOS. No PS2 BIOS I know of features automatic DST.
970- const std::time_t utc_time = std::time (nullptr );
971- const std::time_t gmt9_time = (utc_time + 32400 ); // 60 * 60 * 9
972- struct tm curtime = {};
985+ // User must set time zone and winter/summer DST in the BIOS for correct time.
986+ const std::time_t input_time = std::time (nullptr ) + GMT9_OFFSET_SECONDS;
987+ const std::time_t resulting_time = input_time - GMT9_OFFSET_SECONDS + bios_settings_offset_seconds;
988+
973989#ifdef _MSC_VER
974- gmtime_s (&curtime, &gmt9_time);
990+ gmtime_s (&input_tm, &input_time);
991+ gmtime_s (&resulting_tm, &resulting_time);
975992#else
976- gmtime_r (&gmt9_time, &curtime);
993+ gmtime_r (&input_time, &input_tm);
994+ gmtime_r (&resulting_time, &resulting_tm);
977995#endif
978- cdvd.RTC .second = static_cast <u8 >(curtime.tm_sec );
979- cdvd.RTC .minute = static_cast <u8 >(curtime.tm_min );
980- cdvd.RTC .hour = static_cast <u8 >(curtime.tm_hour );
981- cdvd.RTC .day = static_cast <u8 >(curtime.tm_mday );
982- cdvd.RTC .month = static_cast <u8 >(curtime.tm_mon + 1 ); // WX returns Jan as "0"
983- cdvd.RTC .year = static_cast <u8 >(curtime.tm_year - 100 ); // offset from 2000
984996 }
985997
998+ // Send completed input time to the CDVD.
999+ cdvd.RTC .second = static_cast <u8 >(input_tm.tm_sec );
1000+ cdvd.RTC .minute = static_cast <u8 >(input_tm.tm_min );
1001+ cdvd.RTC .hour = static_cast <u8 >(input_tm.tm_hour );
1002+ cdvd.RTC .day = static_cast <u8 >(input_tm.tm_mday );
1003+ cdvd.RTC .month = static_cast <u8 >(input_tm.tm_mon + 1 );
1004+ cdvd.RTC .year = static_cast <u8 >(input_tm.tm_year - 100 );
1005+
1006+ // Print time that will appear in the user's BIOS rather than input time.
1007+ DevCon.WriteLn (Color_StrongGreen, " Resulting System Time: 20%02u-%02u-%02u %02u:%02u:%02u" ,
1008+ resulting_tm.tm_year - 100 , resulting_tm.tm_mon + 1 , resulting_tm.tm_mday ,
1009+ resulting_tm.tm_hour , resulting_tm.tm_min , resulting_tm.tm_sec );
1010+
9861011 cdvdCtrlTrayClose ();
9871012}
9881013
0 commit comments