shared_page.cpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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/service/ptm/ptm.h"
  9. #include "core/hle/shared_page.h"
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////
  11. namespace SharedPage {
  12. SharedPageDef shared_page;
  13. static int update_time_event;
  14. /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond.
  15. static u64 GetSystemTime() {
  16. auto now = std::chrono::system_clock::now();
  17. // 3DS system does't allow user to set a time before Jan 1 2000,
  18. // so we use it as an auxiliary epoch to calculate the console time.
  19. std::tm epoch_tm;
  20. epoch_tm.tm_sec = 0;
  21. epoch_tm.tm_min = 0;
  22. epoch_tm.tm_hour = 0;
  23. epoch_tm.tm_mday = 1;
  24. epoch_tm.tm_mon = 0;
  25. epoch_tm.tm_year = 100;
  26. epoch_tm.tm_isdst = 0;
  27. auto epoch = std::chrono::system_clock::from_time_t(std::mktime(&epoch_tm));
  28. // 3DS console time uses Jan 1 1900 as internal epoch,
  29. // so we use the milliseconds between 1900 and 2000 as base console time
  30. u64 console_time = 3155673600000ULL;
  31. // Only when system time is after 2000, we set it as 3DS system time
  32. if (now > epoch) {
  33. console_time += std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch).count();
  34. }
  35. // If the system time is in daylight saving, we give an additional hour to console time
  36. std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
  37. std::tm* now_tm = std::localtime(&now_time_t);
  38. if (now_tm && now_tm->tm_isdst > 0)
  39. console_time += 60 * 60 * 1000;
  40. return console_time;
  41. }
  42. static void UpdateTimeCallback(u64 userdata, int cycles_late) {
  43. DateTime& date_time =
  44. shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
  45. date_time.date_time = GetSystemTime();
  46. date_time.update_tick = CoreTiming::GetTicks();
  47. date_time.tick_to_second_coefficient = g_clock_rate_arm11;
  48. date_time.tick_offset = 0;
  49. ++shared_page.date_time_counter;
  50. // system time is updated hourly
  51. CoreTiming::ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event);
  52. }
  53. void Init() {
  54. std::memset(&shared_page, 0, sizeof(shared_page));
  55. shared_page.running_hw = 0x1; // product
  56. // Some games wait until this value becomes 0x1, before asking running_hw
  57. shared_page.unknown_value = 0x1;
  58. // Set to a completely full battery
  59. shared_page.battery_state.charge_level.Assign(
  60. static_cast<u8>(Service::PTM::ChargeLevels::CompletelyFull));
  61. shared_page.battery_state.is_adapter_connected.Assign(1);
  62. shared_page.battery_state.is_charging.Assign(1);
  63. update_time_event =
  64. CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
  65. CoreTiming::ScheduleEvent(0, update_time_event);
  66. }
  67. } // namespace