shared_page.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <chrono>
  5. #include <cstring>
  6. #include <ctime>
  7. #include "core/core_timing.h"
  8. #include "core/hle/shared_page.h"
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////
  10. namespace SharedPage {
  11. SharedPageDef shared_page;
  12. static int update_time_event;
  13. /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond.
  14. static u64 GetSystemTime() {
  15. auto now = std::chrono::system_clock::now();
  16. // 3DS system does't allow user to set a time before Jan 1 2000,
  17. // so we use it as an auxiliary epoch to calculate the console time.
  18. std::tm epoch_tm;
  19. epoch_tm.tm_sec = 0;
  20. epoch_tm.tm_min = 0;
  21. epoch_tm.tm_hour = 0;
  22. epoch_tm.tm_mday = 1;
  23. epoch_tm.tm_mon = 0;
  24. epoch_tm.tm_year = 100;
  25. epoch_tm.tm_isdst = 0;
  26. auto epoch = std::chrono::system_clock::from_time_t(std::mktime(&epoch_tm));
  27. // 3DS console time uses Jan 1 1900 as internal epoch,
  28. // so we use the milliseconds between 1900 and 2000 as base console time
  29. u64 console_time = 3155673600000ULL;
  30. // Only when system time is after 2000, we set it as 3DS system time
  31. if (now > epoch) {
  32. console_time += std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch).count();
  33. }
  34. // If the system time is in daylight saving, we give an additional hour to console time
  35. std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
  36. std::tm* now_tm = std::localtime(&now_time_t);
  37. if (now_tm && now_tm->tm_isdst > 0)
  38. console_time += 60 * 60 * 1000;
  39. return console_time;
  40. }
  41. static void UpdateTimeCallback(u64 userdata, int cycles_late) {
  42. DateTime& date_time =
  43. shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
  44. date_time.date_time = GetSystemTime();
  45. date_time.update_tick = CoreTiming::GetTicks();
  46. date_time.tick_to_second_coefficient = g_clock_rate_arm11;
  47. date_time.tick_offset = 0;
  48. ++shared_page.date_time_counter;
  49. // system time is updated hourly
  50. CoreTiming::ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event);
  51. }
  52. void Init() {
  53. std::memset(&shared_page, 0, sizeof(shared_page));
  54. shared_page.running_hw = 0x1; // product
  55. // Some games wait until this value becomes 0x1, before asking running_hw
  56. shared_page.unknown_value = 0x1;
  57. update_time_event =
  58. CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
  59. CoreTiming::ScheduleEvent(0, update_time_event);
  60. }
  61. } // namespace