shared_page.cpp 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 CoreTiming::EventType* 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 = CoreTiming::BASE_CLOCK_RATE;
  47. date_time.tick_offset = 0;
  48. ++shared_page.date_time_counter;
  49. // system time is updated hourly
  50. CoreTiming::ScheduleEvent(CoreTiming::msToCycles(60 * 60 * 1000) - cycles_late,
  51. 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.is_adapter_connected.Assign(1);
  60. shared_page.battery_state.is_charging.Assign(1);
  61. update_time_event =
  62. CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
  63. CoreTiming::ScheduleEvent(0, update_time_event);
  64. }
  65. } // namespace SharedPage