diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/time/interface.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/time/interface.h | 5 | ||||
| -rw-r--r-- | src/core/hle/service/time/time.cpp | 115 | ||||
| -rw-r--r-- | src/core/hle/service/time/time.h | 11 | ||||
| -rw-r--r-- | src/core/hle/service/time/time_sharedmemory.cpp | 68 | ||||
| -rw-r--r-- | src/core/hle/service/time/time_sharedmemory.h | 74 |
8 files changed, 260 insertions, 28 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a35e6066a..686262702 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -430,6 +430,8 @@ add_library(core STATIC | |||
| 430 | hle/service/time/interface.h | 430 | hle/service/time/interface.h |
| 431 | hle/service/time/time.cpp | 431 | hle/service/time/time.cpp |
| 432 | hle/service/time/time.h | 432 | hle/service/time/time.h |
| 433 | hle/service/time/time_sharedmemory.cpp | ||
| 434 | hle/service/time/time_sharedmemory.h | ||
| 433 | hle/service/usb/usb.cpp | 435 | hle/service/usb/usb.cpp |
| 434 | hle/service/usb/usb.h | 436 | hle/service/usb/usb.h |
| 435 | hle/service/vi/display/vi_display.cpp | 437 | hle/service/vi/display/vi_display.cpp |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ec9d755b7..5fc7d3cab 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -249,7 +249,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | |||
| 249 | Sockets::InstallInterfaces(*sm); | 249 | Sockets::InstallInterfaces(*sm); |
| 250 | SPL::InstallInterfaces(*sm); | 250 | SPL::InstallInterfaces(*sm); |
| 251 | SSL::InstallInterfaces(*sm); | 251 | SSL::InstallInterfaces(*sm); |
| 252 | Time::InstallInterfaces(*sm); | 252 | Time::InstallInterfaces(system); |
| 253 | USB::InstallInterfaces(*sm); | 253 | USB::InstallInterfaces(*sm); |
| 254 | VI::InstallInterfaces(*sm, nv_flinger); | 254 | VI::InstallInterfaces(*sm, nv_flinger); |
| 255 | WLAN::InstallInterfaces(*sm); | 255 | WLAN::InstallInterfaces(*sm); |
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp index 8d122ae33..1030185e0 100644 --- a/src/core/hle/service/time/interface.cpp +++ b/src/core/hle/service/time/interface.cpp | |||
| @@ -6,8 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::Time { | 7 | namespace Service::Time { |
| 8 | 8 | ||
| 9 | Time::Time(std::shared_ptr<Module> time, const char* name) | 9 | Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, |
| 10 | : Module::Interface(std::move(time), name) { | 10 | const char* name) |
| 11 | : Module::Interface(std::move(time), std::move(shared_memory), name) { | ||
| 11 | // clang-format off | 12 | // clang-format off |
| 12 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
| 13 | {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | 14 | {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, |
| @@ -16,12 +17,12 @@ Time::Time(std::shared_ptr<Module> time, const char* name) | |||
| 16 | {3, &Time::GetTimeZoneService, "GetTimeZoneService"}, | 17 | {3, &Time::GetTimeZoneService, "GetTimeZoneService"}, |
| 17 | {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, | 18 | {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, |
| 18 | {5, nullptr, "GetEphemeralNetworkSystemClock"}, | 19 | {5, nullptr, "GetEphemeralNetworkSystemClock"}, |
| 19 | {20, nullptr, "GetSharedMemoryNativeHandle"}, | 20 | {20, &Time::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, |
| 20 | {30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"}, | 21 | {30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"}, |
| 21 | {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"}, | 22 | {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"}, |
| 22 | {50, nullptr, "SetStandardSteadyClockInternalOffset"}, | 23 | {50, nullptr, "SetStandardSteadyClockInternalOffset"}, |
| 23 | {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, | 24 | {100, &Time::IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, |
| 24 | {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, | 25 | {101, &Time::SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, |
| 25 | {102, nullptr, "GetStandardUserSystemClockInitialYear"}, | 26 | {102, nullptr, "GetStandardUserSystemClockInitialYear"}, |
| 26 | {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, | 27 | {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, |
| 27 | {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, | 28 | {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, |
diff --git a/src/core/hle/service/time/interface.h b/src/core/hle/service/time/interface.h index cd6b44dec..bdf0883e2 100644 --- a/src/core/hle/service/time/interface.h +++ b/src/core/hle/service/time/interface.h | |||
| @@ -8,9 +8,12 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::Time { | 9 | namespace Service::Time { |
| 10 | 10 | ||
| 11 | class SharedMemory; | ||
| 12 | |||
| 11 | class Time final : public Module::Interface { | 13 | class Time final : public Module::Interface { |
| 12 | public: | 14 | public: |
| 13 | explicit Time(std::shared_ptr<Module> time, const char* name); | 15 | explicit Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, |
| 16 | const char* name); | ||
| 14 | ~Time() override; | 17 | ~Time() override; |
| 15 | }; | 18 | }; |
| 16 | 19 | ||
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 346bad80d..ae6446204 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/hle/kernel/client_session.h" | 13 | #include "core/hle/kernel/client_session.h" |
| 14 | #include "core/hle/service/time/interface.h" | 14 | #include "core/hle/service/time/interface.h" |
| 15 | #include "core/hle/service/time/time.h" | 15 | #include "core/hle/service/time/time.h" |
| 16 | #include "core/hle/service/time/time_sharedmemory.h" | ||
| 16 | #include "core/settings.h" | 17 | #include "core/settings.h" |
| 17 | 18 | ||
| 18 | namespace Service::Time { | 19 | namespace Service::Time { |
| @@ -61,9 +62,18 @@ static u64 CalendarToPosix(const CalendarTime& calendar_time, | |||
| 61 | return static_cast<u64>(epoch_time); | 62 | return static_cast<u64>(epoch_time); |
| 62 | } | 63 | } |
| 63 | 64 | ||
| 65 | enum class ClockContextType { | ||
| 66 | StandardSteady, | ||
| 67 | StandardUserSystem, | ||
| 68 | StandardNetworkSystem, | ||
| 69 | StandardLocalSystem, | ||
| 70 | }; | ||
| 71 | |||
| 64 | class ISystemClock final : public ServiceFramework<ISystemClock> { | 72 | class ISystemClock final : public ServiceFramework<ISystemClock> { |
| 65 | public: | 73 | public: |
| 66 | ISystemClock() : ServiceFramework("ISystemClock") { | 74 | ISystemClock(std::shared_ptr<Service::Time::SharedMemory> shared_memory, |
| 75 | ClockContextType clock_type) | ||
| 76 | : ServiceFramework("ISystemClock"), shared_memory(shared_memory), clock_type(clock_type) { | ||
| 67 | static const FunctionInfo functions[] = { | 77 | static const FunctionInfo functions[] = { |
| 68 | {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, | 78 | {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, |
| 69 | {1, nullptr, "SetCurrentTime"}, | 79 | {1, nullptr, "SetCurrentTime"}, |
| @@ -72,6 +82,8 @@ public: | |||
| 72 | 82 | ||
| 73 | }; | 83 | }; |
| 74 | RegisterHandlers(functions); | 84 | RegisterHandlers(functions); |
| 85 | |||
| 86 | UpdateSharedMemoryContext(system_clock_context); | ||
| 75 | } | 87 | } |
| 76 | 88 | ||
| 77 | private: | 89 | private: |
| @@ -87,34 +99,63 @@ private: | |||
| 87 | void GetSystemClockContext(Kernel::HLERequestContext& ctx) { | 99 | void GetSystemClockContext(Kernel::HLERequestContext& ctx) { |
| 88 | LOG_WARNING(Service_Time, "(STUBBED) called"); | 100 | LOG_WARNING(Service_Time, "(STUBBED) called"); |
| 89 | 101 | ||
| 90 | SystemClockContext system_clock_ontext{}; | 102 | // TODO(ogniK): This should be updated periodically however since we have it stubbed we'll |
| 103 | // only update when we get a new context | ||
| 104 | UpdateSharedMemoryContext(system_clock_context); | ||
| 105 | |||
| 91 | IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; | 106 | IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; |
| 92 | rb.Push(RESULT_SUCCESS); | 107 | rb.Push(RESULT_SUCCESS); |
| 93 | rb.PushRaw(system_clock_ontext); | 108 | rb.PushRaw(system_clock_context); |
| 94 | } | 109 | } |
| 110 | |||
| 111 | void UpdateSharedMemoryContext(const SystemClockContext& clock_context) { | ||
| 112 | switch (clock_type) { | ||
| 113 | case ClockContextType::StandardLocalSystem: | ||
| 114 | shared_memory->SetStandardLocalSystemClockContext(clock_context); | ||
| 115 | break; | ||
| 116 | case ClockContextType::StandardNetworkSystem: | ||
| 117 | shared_memory->SetStandardNetworkSystemClockContext(clock_context); | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | SystemClockContext system_clock_context{}; | ||
| 123 | std::shared_ptr<Service::Time::SharedMemory> shared_memory; | ||
| 124 | ClockContextType clock_type; | ||
| 95 | }; | 125 | }; |
| 96 | 126 | ||
| 97 | class ISteadyClock final : public ServiceFramework<ISteadyClock> { | 127 | class ISteadyClock final : public ServiceFramework<ISteadyClock> { |
| 98 | public: | 128 | public: |
| 99 | ISteadyClock() : ServiceFramework("ISteadyClock") { | 129 | ISteadyClock(std::shared_ptr<SharedMemory> shared_memory) |
| 130 | : ServiceFramework("ISteadyClock"), shared_memory(shared_memory) { | ||
| 100 | static const FunctionInfo functions[] = { | 131 | static const FunctionInfo functions[] = { |
| 101 | {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, | 132 | {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, |
| 102 | }; | 133 | }; |
| 103 | RegisterHandlers(functions); | 134 | RegisterHandlers(functions); |
| 135 | |||
| 136 | shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint()); | ||
| 104 | } | 137 | } |
| 105 | 138 | ||
| 106 | private: | 139 | private: |
| 107 | void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { | 140 | void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { |
| 108 | LOG_DEBUG(Service_Time, "called"); | 141 | LOG_DEBUG(Service_Time, "called"); |
| 109 | 142 | ||
| 110 | const auto& core_timing = Core::System::GetInstance().CoreTiming(); | 143 | const auto time_point = GetCurrentTimePoint(); |
| 111 | const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); | 144 | // TODO(ogniK): This should be updated periodically |
| 112 | const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), | 145 | shared_memory->SetStandardSteadyClockTimepoint(time_point); |
| 113 | {}}; | 146 | |
| 114 | IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; | 147 | IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; |
| 115 | rb.Push(RESULT_SUCCESS); | 148 | rb.Push(RESULT_SUCCESS); |
| 116 | rb.PushRaw(steady_clock_time_point); | 149 | rb.PushRaw(time_point); |
| 117 | } | 150 | } |
| 151 | |||
| 152 | SteadyClockTimePoint GetCurrentTimePoint() const { | ||
| 153 | const auto& core_timing = Core::System::GetInstance().CoreTiming(); | ||
| 154 | const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); | ||
| 155 | return {static_cast<u64_le>(ms.count() / 1000), {}}; | ||
| 156 | } | ||
| 157 | |||
| 158 | std::shared_ptr<SharedMemory> shared_memory; | ||
| 118 | }; | 159 | }; |
| 119 | 160 | ||
| 120 | class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { | 161 | class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { |
| @@ -233,7 +274,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct | |||
| 233 | 274 | ||
| 234 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 275 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 235 | rb.Push(RESULT_SUCCESS); | 276 | rb.Push(RESULT_SUCCESS); |
| 236 | rb.PushIpcInterface<ISystemClock>(); | 277 | rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem); |
| 237 | } | 278 | } |
| 238 | 279 | ||
| 239 | void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { | 280 | void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { |
| @@ -241,7 +282,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& | |||
| 241 | 282 | ||
| 242 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 283 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 243 | rb.Push(RESULT_SUCCESS); | 284 | rb.Push(RESULT_SUCCESS); |
| 244 | rb.PushIpcInterface<ISystemClock>(); | 285 | rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem); |
| 245 | } | 286 | } |
| 246 | 287 | ||
| 247 | void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | 288 | void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { |
| @@ -249,7 +290,7 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | |||
| 249 | 290 | ||
| 250 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 291 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 251 | rb.Push(RESULT_SUCCESS); | 292 | rb.Push(RESULT_SUCCESS); |
| 252 | rb.PushIpcInterface<ISteadyClock>(); | 293 | rb.PushIpcInterface<ISteadyClock>(shared_memory); |
| 253 | } | 294 | } |
| 254 | 295 | ||
| 255 | void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { | 296 | void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { |
| @@ -265,7 +306,7 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c | |||
| 265 | 306 | ||
| 266 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 307 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 267 | rb.Push(RESULT_SUCCESS); | 308 | rb.Push(RESULT_SUCCESS); |
| 268 | rb.PushIpcInterface<ISystemClock>(); | 309 | rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem); |
| 269 | } | 310 | } |
| 270 | 311 | ||
| 271 | void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | 312 | void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { |
| @@ -333,16 +374,52 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( | |||
| 333 | rb.PushRaw<u64>(difference); | 374 | rb.PushRaw<u64>(difference); |
| 334 | } | 375 | } |
| 335 | 376 | ||
| 336 | Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) | 377 | void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { |
| 337 | : ServiceFramework(name), time(std::move(time)) {} | 378 | LOG_DEBUG(Service_Time, "called"); |
| 379 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 380 | rb.Push(RESULT_SUCCESS); | ||
| 381 | rb.PushCopyObjects(shared_memory->GetSharedMemoryHolder()); | ||
| 382 | } | ||
| 383 | |||
| 384 | void Module::Interface::IsStandardUserSystemClockAutomaticCorrectionEnabled( | ||
| 385 | Kernel::HLERequestContext& ctx) { | ||
| 386 | // ogniK(TODO): When clock contexts are implemented, the value should be read from the context | ||
| 387 | // instead of our shared memory holder | ||
| 388 | LOG_DEBUG(Service_Time, "called"); | ||
| 389 | |||
| 390 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 391 | rb.Push(RESULT_SUCCESS); | ||
| 392 | rb.Push<u8>(shared_memory->GetStandardUserSystemClockAutomaticCorrectionEnabled()); | ||
| 393 | } | ||
| 394 | |||
| 395 | void Module::Interface::SetStandardUserSystemClockAutomaticCorrectionEnabled( | ||
| 396 | Kernel::HLERequestContext& ctx) { | ||
| 397 | IPC::RequestParser rp{ctx}; | ||
| 398 | const auto enabled = rp.Pop<u8>(); | ||
| 399 | |||
| 400 | LOG_WARNING(Service_Time, "(PARTIAL IMPLEMENTATION) called"); | ||
| 401 | |||
| 402 | // TODO(ogniK): Update clock contexts and correct timespans | ||
| 403 | |||
| 404 | shared_memory->SetStandardUserSystemClockAutomaticCorrectionEnabled(enabled > 0); | ||
| 405 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 406 | rb.Push(RESULT_SUCCESS); | ||
| 407 | } | ||
| 408 | |||
| 409 | Module::Interface::Interface(std::shared_ptr<Module> time, | ||
| 410 | std::shared_ptr<SharedMemory> shared_memory, const char* name) | ||
| 411 | : ServiceFramework(name), time(std::move(time)), shared_memory(std::move(shared_memory)) {} | ||
| 338 | 412 | ||
| 339 | Module::Interface::~Interface() = default; | 413 | Module::Interface::~Interface() = default; |
| 340 | 414 | ||
| 341 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 415 | void InstallInterfaces(Core::System& system) { |
| 342 | auto time = std::make_shared<Module>(); | 416 | auto time = std::make_shared<Module>(); |
| 343 | std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager); | 417 | auto shared_mem = std::make_shared<SharedMemory>(system); |
| 344 | std::make_shared<Time>(time, "time:s")->InstallAsService(service_manager); | 418 | |
| 345 | std::make_shared<Time>(time, "time:u")->InstallAsService(service_manager); | 419 | std::make_shared<Time>(time, shared_mem, "time:a")->InstallAsService(system.ServiceManager()); |
| 420 | std::make_shared<Time>(time, shared_mem, "time:s")->InstallAsService(system.ServiceManager()); | ||
| 421 | std::make_shared<Time>(std::move(time), shared_mem, "time:u") | ||
| 422 | ->InstallAsService(system.ServiceManager()); | ||
| 346 | } | 423 | } |
| 347 | 424 | ||
| 348 | } // namespace Service::Time | 425 | } // namespace Service::Time |
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index f11affe95..e0708f856 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | namespace Service::Time { | 11 | namespace Service::Time { |
| 12 | 12 | ||
| 13 | class SharedMemory; | ||
| 14 | |||
| 13 | struct LocationName { | 15 | struct LocationName { |
| 14 | std::array<u8, 0x24> name; | 16 | std::array<u8, 0x24> name; |
| 15 | }; | 17 | }; |
| @@ -77,7 +79,8 @@ class Module final { | |||
| 77 | public: | 79 | public: |
| 78 | class Interface : public ServiceFramework<Interface> { | 80 | class Interface : public ServiceFramework<Interface> { |
| 79 | public: | 81 | public: |
| 80 | explicit Interface(std::shared_ptr<Module> time, const char* name); | 82 | explicit Interface(std::shared_ptr<Module> time, |
| 83 | std::shared_ptr<SharedMemory> shared_memory, const char* name); | ||
| 81 | ~Interface() override; | 84 | ~Interface() override; |
| 82 | 85 | ||
| 83 | void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); | 86 | void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); |
| @@ -87,13 +90,17 @@ public: | |||
| 87 | void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); | 90 | void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); |
| 88 | void GetClockSnapshot(Kernel::HLERequestContext& ctx); | 91 | void GetClockSnapshot(Kernel::HLERequestContext& ctx); |
| 89 | void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); | 92 | void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); |
| 93 | void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); | ||
| 94 | void IsStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); | ||
| 95 | void SetStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); | ||
| 90 | 96 | ||
| 91 | protected: | 97 | protected: |
| 92 | std::shared_ptr<Module> time; | 98 | std::shared_ptr<Module> time; |
| 99 | std::shared_ptr<SharedMemory> shared_memory; | ||
| 93 | }; | 100 | }; |
| 94 | }; | 101 | }; |
| 95 | 102 | ||
| 96 | /// Registers all Time services with the specified service manager. | 103 | /// Registers all Time services with the specified service manager. |
| 97 | void InstallInterfaces(SM::ServiceManager& service_manager); | 104 | void InstallInterfaces(Core::System& system); |
| 98 | 105 | ||
| 99 | } // namespace Service::Time | 106 | } // namespace Service::Time |
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp new file mode 100644 index 000000000..bfc81b83c --- /dev/null +++ b/src/core/hle/service/time/time_sharedmemory.cpp | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hle/service/time/time_sharedmemory.h" | ||
| 7 | |||
| 8 | namespace Service::Time { | ||
| 9 | const std::size_t SHARED_MEMORY_SIZE = 0x1000; | ||
| 10 | |||
| 11 | SharedMemory::SharedMemory(Core::System& system) : system(system) { | ||
| 12 | shared_memory_holder = Kernel::SharedMemory::Create( | ||
| 13 | system.Kernel(), nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite, | ||
| 14 | Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "Time:SharedMemory"); | ||
| 15 | |||
| 16 | // Seems static from 1.0.0 -> 8.1.0. Specific games seem to check this value and crash | ||
| 17 | // if it's set to anything else | ||
| 18 | shared_memory_format.format_version = 14; | ||
| 19 | std::memcpy(shared_memory_holder->GetPointer(), &shared_memory_format, sizeof(Format)); | ||
| 20 | } | ||
| 21 | |||
| 22 | SharedMemory::~SharedMemory() = default; | ||
| 23 | |||
| 24 | Kernel::SharedPtr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() const { | ||
| 25 | return shared_memory_holder; | ||
| 26 | } | ||
| 27 | |||
| 28 | void SharedMemory::SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint) { | ||
| 29 | shared_memory_format.standard_steady_clock_timepoint.StoreData( | ||
| 30 | shared_memory_holder->GetPointer(), timepoint); | ||
| 31 | } | ||
| 32 | |||
| 33 | void SharedMemory::SetStandardLocalSystemClockContext(const SystemClockContext& context) { | ||
| 34 | shared_memory_format.standard_local_system_clock_context.StoreData( | ||
| 35 | shared_memory_holder->GetPointer(), context); | ||
| 36 | } | ||
| 37 | |||
| 38 | void SharedMemory::SetStandardNetworkSystemClockContext(const SystemClockContext& context) { | ||
| 39 | shared_memory_format.standard_network_system_clock_context.StoreData( | ||
| 40 | shared_memory_holder->GetPointer(), context); | ||
| 41 | } | ||
| 42 | |||
| 43 | void SharedMemory::SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled) { | ||
| 44 | shared_memory_format.standard_user_system_clock_automatic_correction.StoreData( | ||
| 45 | shared_memory_holder->GetPointer(), enabled); | ||
| 46 | } | ||
| 47 | |||
| 48 | SteadyClockTimePoint SharedMemory::GetStandardSteadyClockTimepoint() { | ||
| 49 | return shared_memory_format.standard_steady_clock_timepoint.ReadData( | ||
| 50 | shared_memory_holder->GetPointer()); | ||
| 51 | } | ||
| 52 | |||
| 53 | SystemClockContext SharedMemory::GetStandardLocalSystemClockContext() { | ||
| 54 | return shared_memory_format.standard_local_system_clock_context.ReadData( | ||
| 55 | shared_memory_holder->GetPointer()); | ||
| 56 | } | ||
| 57 | |||
| 58 | SystemClockContext SharedMemory::GetStandardNetworkSystemClockContext() { | ||
| 59 | return shared_memory_format.standard_network_system_clock_context.ReadData( | ||
| 60 | shared_memory_holder->GetPointer()); | ||
| 61 | } | ||
| 62 | |||
| 63 | bool SharedMemory::GetStandardUserSystemClockAutomaticCorrectionEnabled() { | ||
| 64 | return shared_memory_format.standard_user_system_clock_automatic_correction.ReadData( | ||
| 65 | shared_memory_holder->GetPointer()); | ||
| 66 | } | ||
| 67 | |||
| 68 | } // namespace Service::Time | ||
diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h new file mode 100644 index 000000000..cb8253541 --- /dev/null +++ b/src/core/hle/service/time/time_sharedmemory.h | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hle/kernel/shared_memory.h" | ||
| 9 | #include "core/hle/service/time/time.h" | ||
| 10 | |||
| 11 | namespace Service::Time { | ||
| 12 | class SharedMemory { | ||
| 13 | public: | ||
| 14 | explicit SharedMemory(Core::System& system); | ||
| 15 | ~SharedMemory(); | ||
| 16 | |||
| 17 | // Return the shared memory handle | ||
| 18 | Kernel::SharedPtr<Kernel::SharedMemory> GetSharedMemoryHolder() const; | ||
| 19 | |||
| 20 | // Set memory barriers in shared memory and update them | ||
| 21 | void SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint); | ||
| 22 | void SetStandardLocalSystemClockContext(const SystemClockContext& context); | ||
| 23 | void SetStandardNetworkSystemClockContext(const SystemClockContext& context); | ||
| 24 | void SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled); | ||
| 25 | |||
| 26 | // Pull from memory barriers in the shared memory | ||
| 27 | SteadyClockTimePoint GetStandardSteadyClockTimepoint(); | ||
| 28 | SystemClockContext GetStandardLocalSystemClockContext(); | ||
| 29 | SystemClockContext GetStandardNetworkSystemClockContext(); | ||
| 30 | bool GetStandardUserSystemClockAutomaticCorrectionEnabled(); | ||
| 31 | |||
| 32 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? | ||
| 33 | template <typename T, std::size_t Offset> | ||
| 34 | struct MemoryBarrier { | ||
| 35 | static_assert(std::is_trivially_constructible_v<T>, "T must be trivially constructable"); | ||
| 36 | u32_le read_attempt{}; | ||
| 37 | std::array<T, 2> data{}; | ||
| 38 | |||
| 39 | // These are not actually memory barriers at the moment as we don't have multicore and all | ||
| 40 | // HLE is mutexed. This will need to properly be implemented when we start updating the time | ||
| 41 | // points on threads. As of right now, we'll be updated both values synchronously and just | ||
| 42 | // incrementing the read_attempt to indicate that we waited. | ||
| 43 | void StoreData(u8* shared_memory, T data_to_store) { | ||
| 44 | std::memcpy(this, shared_memory + Offset, sizeof(*this)); | ||
| 45 | read_attempt++; | ||
| 46 | data[read_attempt & 1] = data_to_store; | ||
| 47 | std::memcpy(shared_memory + Offset, this, sizeof(*this)); | ||
| 48 | } | ||
| 49 | |||
| 50 | // For reading we're just going to read the last stored value. If there was no value stored | ||
| 51 | // it will just end up reading an empty value as intended. | ||
| 52 | T ReadData(u8* shared_memory) { | ||
| 53 | std::memcpy(this, shared_memory + Offset, sizeof(*this)); | ||
| 54 | return data[(read_attempt - 1) & 1]; | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | |||
| 58 | // Shared memory format | ||
| 59 | struct Format { | ||
| 60 | MemoryBarrier<SteadyClockTimePoint, 0x0> standard_steady_clock_timepoint; | ||
| 61 | MemoryBarrier<SystemClockContext, 0x38> standard_local_system_clock_context; | ||
| 62 | MemoryBarrier<SystemClockContext, 0x80> standard_network_system_clock_context; | ||
| 63 | MemoryBarrier<bool, 0xc8> standard_user_system_clock_automatic_correction; | ||
| 64 | u32_le format_version; | ||
| 65 | }; | ||
| 66 | static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); | ||
| 67 | |||
| 68 | private: | ||
| 69 | Kernel::SharedPtr<Kernel::SharedMemory> shared_memory_holder{}; | ||
| 70 | Core::System& system; | ||
| 71 | Format shared_memory_format{}; | ||
| 72 | }; | ||
| 73 | |||
| 74 | } // namespace Service::Time | ||