diff options
| author | 2016-07-23 04:38:16 -0700 | |
|---|---|---|
| committer | 2016-07-23 04:38:16 -0700 | |
| commit | 2dee47c8277484f0fdc486ec201ed5c25d7b73a3 (patch) | |
| tree | 60611fb27fc92610176216a8f947cf5bd82d9b63 /src | |
| parent | Merge pull request #1964 from Lectem/sdl2_dll_copy_fix (diff) | |
| parent | CoreTiming: avoid overflow (diff) | |
| download | yuzu-2dee47c8277484f0fdc486ec201ed5c25d7b73a3.tar.gz yuzu-2dee47c8277484f0fdc486ec201ed5c25d7b73a3.tar.xz yuzu-2dee47c8277484f0fdc486ec201ed5c25d7b73a3.zip | |
Merge pull request #1963 from wwylele/rtc
Implement actual system time
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/core_timing.h | 2 | ||||
| -rw-r--r-- | src/core/hle/shared_page.cpp | 57 | ||||
| -rw-r--r-- | src/core/hle/shared_page.h | 5 |
3 files changed, 61 insertions, 3 deletions
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 64f5b06d9..3d8a7d0c0 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | extern int g_clock_rate_arm11; | 26 | extern int g_clock_rate_arm11; |
| 27 | 27 | ||
| 28 | inline s64 msToCycles(int ms) { | 28 | inline s64 msToCycles(int ms) { |
| 29 | return g_clock_rate_arm11 / 1000 * ms; | 29 | return (s64)g_clock_rate_arm11 / 1000 * ms; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | inline s64 msToCycles(float ms) { | 32 | inline s64 msToCycles(float ms) { |
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp index 2a1caeaac..4d9272923 100644 --- a/src/core/hle/shared_page.cpp +++ b/src/core/hle/shared_page.cpp | |||
| @@ -2,8 +2,11 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <chrono> | ||
| 5 | #include <cstring> | 6 | #include <cstring> |
| 7 | #include <ctime> | ||
| 6 | 8 | ||
| 9 | #include "core/core_timing.h" | ||
| 7 | #include "core/hle/shared_page.h" | 10 | #include "core/hle/shared_page.h" |
| 8 | 11 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -12,6 +15,57 @@ namespace SharedPage { | |||
| 12 | 15 | ||
| 13 | SharedPageDef shared_page; | 16 | SharedPageDef shared_page; |
| 14 | 17 | ||
| 18 | static int update_time_event; | ||
| 19 | |||
| 20 | /// Gets system time in 3DS format. The epoch is Jan 1900, and the unit is millisecond. | ||
| 21 | static u64 GetSystemTime() { | ||
| 22 | auto now = std::chrono::system_clock::now(); | ||
| 23 | |||
| 24 | // 3DS system does't allow user to set a time before Jan 1 2000, | ||
| 25 | // so we use it as an auxiliary epoch to calculate the console time. | ||
| 26 | std::tm epoch_tm; | ||
| 27 | epoch_tm.tm_sec = 0; | ||
| 28 | epoch_tm.tm_min = 0; | ||
| 29 | epoch_tm.tm_hour = 0; | ||
| 30 | epoch_tm.tm_mday = 1; | ||
| 31 | epoch_tm.tm_mon = 0; | ||
| 32 | epoch_tm.tm_year = 100; | ||
| 33 | epoch_tm.tm_isdst = 0; | ||
| 34 | auto epoch = std::chrono::system_clock::from_time_t(std::mktime(&epoch_tm)); | ||
| 35 | |||
| 36 | // 3DS console time uses Jan 1 1900 as internal epoch, | ||
| 37 | // so we use the milliseconds between 1900 and 2000 as base console time | ||
| 38 | u64 console_time = 3155673600000ULL; | ||
| 39 | |||
| 40 | // Only when system time is after 2000, we set it as 3DS system time | ||
| 41 | if (now > epoch) { | ||
| 42 | console_time += std::chrono::duration_cast<std::chrono::milliseconds>(now - epoch).count(); | ||
| 43 | } | ||
| 44 | |||
| 45 | // If the system time is in daylight saving, we give an additional hour to console time | ||
| 46 | std::time_t now_time_t = std::chrono::system_clock::to_time_t(now); | ||
| 47 | std::tm* now_tm = std::localtime(&now_time_t); | ||
| 48 | if (now_tm && now_tm->tm_isdst > 0) | ||
| 49 | console_time += 60 * 60 * 1000; | ||
| 50 | |||
| 51 | return console_time; | ||
| 52 | } | ||
| 53 | |||
| 54 | static void UpdateTimeCallback(u64 userdata, int cycles_late) { | ||
| 55 | DateTime& date_time = shared_page.date_time_counter % 2 ? | ||
| 56 | shared_page.date_time_0 : shared_page.date_time_1; | ||
| 57 | |||
| 58 | date_time.date_time = GetSystemTime(); | ||
| 59 | date_time.update_tick = CoreTiming::GetTicks(); | ||
| 60 | date_time.tick_to_second_coefficient = g_clock_rate_arm11; | ||
| 61 | date_time.tick_offset = 0; | ||
| 62 | |||
| 63 | ++shared_page.date_time_counter; | ||
| 64 | |||
| 65 | // system time is updated hourly | ||
| 66 | CoreTiming::ScheduleEvent(msToCycles(60 * 60 * 1000) - cycles_late, update_time_event); | ||
| 67 | } | ||
| 68 | |||
| 15 | void Init() { | 69 | void Init() { |
| 16 | std::memset(&shared_page, 0, sizeof(shared_page)); | 70 | std::memset(&shared_page, 0, sizeof(shared_page)); |
| 17 | 71 | ||
| @@ -19,6 +73,9 @@ void Init() { | |||
| 19 | 73 | ||
| 20 | // Some games wait until this value becomes 0x1, before asking running_hw | 74 | // Some games wait until this value becomes 0x1, before asking running_hw |
| 21 | shared_page.unknown_value = 0x1; | 75 | shared_page.unknown_value = 0x1; |
| 76 | |||
| 77 | update_time_event = CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); | ||
| 78 | CoreTiming::ScheduleEvent(0, update_time_event); | ||
| 22 | } | 79 | } |
| 23 | 80 | ||
| 24 | } // namespace | 81 | } // namespace |
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h index 35a07c685..cd9246726 100644 --- a/src/core/hle/shared_page.h +++ b/src/core/hle/shared_page.h | |||
| @@ -25,13 +25,14 @@ namespace SharedPage { | |||
| 25 | struct DateTime { | 25 | struct DateTime { |
| 26 | u64_le date_time; // 0 | 26 | u64_le date_time; // 0 |
| 27 | u64_le update_tick; // 8 | 27 | u64_le update_tick; // 8 |
| 28 | INSERT_PADDING_BYTES(0x20 - 0x10); // 10 | 28 | u64_le tick_to_second_coefficient; // 10 |
| 29 | u64_le tick_offset; // 18 | ||
| 29 | }; | 30 | }; |
| 30 | static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); | 31 | static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong"); |
| 31 | 32 | ||
| 32 | struct SharedPageDef { | 33 | struct SharedPageDef { |
| 33 | // Most of these names are taken from the 3dbrew page linked above. | 34 | // Most of these names are taken from the 3dbrew page linked above. |
| 34 | u32_le date_time_selector; // 0 | 35 | u32_le date_time_counter; // 0 |
| 35 | u8 running_hw; // 4 | 36 | u8 running_hw; // 4 |
| 36 | /// "Microcontroller hardware info" | 37 | /// "Microcontroller hardware info" |
| 37 | u8 mcu_hw_info; // 5 | 38 | u8 mcu_hw_info; // 5 |