Merge pull request #2608 from ogniK5377/Time_GetSharedMemoryNativeHandle
Implement Time::GetSharedMemoryNativeHandle
This commit is contained in:
		| @@ -430,6 +430,8 @@ add_library(core STATIC | |||||||
|     hle/service/time/interface.h |     hle/service/time/interface.h | ||||||
|     hle/service/time/time.cpp |     hle/service/time/time.cpp | ||||||
|     hle/service/time/time.h |     hle/service/time/time.h | ||||||
|  |     hle/service/time/time_sharedmemory.cpp | ||||||
|  |     hle/service/time/time_sharedmemory.h | ||||||
|     hle/service/usb/usb.cpp |     hle/service/usb/usb.cpp | ||||||
|     hle/service/usb/usb.h |     hle/service/usb/usb.h | ||||||
|     hle/service/vi/display/vi_display.cpp |     hle/service/vi/display/vi_display.cpp | ||||||
|   | |||||||
| @@ -249,7 +249,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | |||||||
|     Sockets::InstallInterfaces(*sm); |     Sockets::InstallInterfaces(*sm); | ||||||
|     SPL::InstallInterfaces(*sm); |     SPL::InstallInterfaces(*sm); | ||||||
|     SSL::InstallInterfaces(*sm); |     SSL::InstallInterfaces(*sm); | ||||||
|     Time::InstallInterfaces(*sm); |     Time::InstallInterfaces(system); | ||||||
|     USB::InstallInterfaces(*sm); |     USB::InstallInterfaces(*sm); | ||||||
|     VI::InstallInterfaces(*sm, nv_flinger); |     VI::InstallInterfaces(*sm, nv_flinger); | ||||||
|     WLAN::InstallInterfaces(*sm); |     WLAN::InstallInterfaces(*sm); | ||||||
|   | |||||||
| @@ -6,8 +6,9 @@ | |||||||
|  |  | ||||||
| namespace Service::Time { | namespace Service::Time { | ||||||
|  |  | ||||||
| Time::Time(std::shared_ptr<Module> time, const char* name) | Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, | ||||||
|     : Module::Interface(std::move(time), name) { |            const char* name) | ||||||
|  |     : Module::Interface(std::move(time), std::move(shared_memory), name) { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, |         {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | ||||||
| @@ -16,12 +17,12 @@ Time::Time(std::shared_ptr<Module> time, const char* name) | |||||||
|         {3, &Time::GetTimeZoneService, "GetTimeZoneService"}, |         {3, &Time::GetTimeZoneService, "GetTimeZoneService"}, | ||||||
|         {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, |         {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, | ||||||
|         {5, nullptr, "GetEphemeralNetworkSystemClock"}, |         {5, nullptr, "GetEphemeralNetworkSystemClock"}, | ||||||
|         {20, nullptr, "GetSharedMemoryNativeHandle"}, |         {20, &Time::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, | ||||||
|         {30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"}, |         {30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"}, | ||||||
|         {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"}, |         {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"}, | ||||||
|         {50, nullptr, "SetStandardSteadyClockInternalOffset"}, |         {50, nullptr, "SetStandardSteadyClockInternalOffset"}, | ||||||
|         {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, |         {100, &Time::IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, | ||||||
|         {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, |         {101, &Time::SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, | ||||||
|         {102, nullptr, "GetStandardUserSystemClockInitialYear"}, |         {102, nullptr, "GetStandardUserSystemClockInitialYear"}, | ||||||
|         {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, |         {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, | ||||||
|         {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, |         {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"}, | ||||||
|   | |||||||
| @@ -8,9 +8,12 @@ | |||||||
|  |  | ||||||
| namespace Service::Time { | namespace Service::Time { | ||||||
|  |  | ||||||
|  | class SharedMemory; | ||||||
|  |  | ||||||
| class Time final : public Module::Interface { | class Time final : public Module::Interface { | ||||||
| public: | public: | ||||||
|     explicit Time(std::shared_ptr<Module> time, const char* name); |     explicit Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, | ||||||
|  |                   const char* name); | ||||||
|     ~Time() override; |     ~Time() override; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ | |||||||
| #include "core/hle/kernel/client_session.h" | #include "core/hle/kernel/client_session.h" | ||||||
| #include "core/hle/service/time/interface.h" | #include "core/hle/service/time/interface.h" | ||||||
| #include "core/hle/service/time/time.h" | #include "core/hle/service/time/time.h" | ||||||
|  | #include "core/hle/service/time/time_sharedmemory.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
|  |  | ||||||
| namespace Service::Time { | namespace Service::Time { | ||||||
| @@ -61,9 +62,18 @@ static u64 CalendarToPosix(const CalendarTime& calendar_time, | |||||||
|     return static_cast<u64>(epoch_time); |     return static_cast<u64>(epoch_time); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | enum class ClockContextType { | ||||||
|  |     StandardSteady, | ||||||
|  |     StandardUserSystem, | ||||||
|  |     StandardNetworkSystem, | ||||||
|  |     StandardLocalSystem, | ||||||
|  | }; | ||||||
|  |  | ||||||
| class ISystemClock final : public ServiceFramework<ISystemClock> { | class ISystemClock final : public ServiceFramework<ISystemClock> { | ||||||
| public: | public: | ||||||
|     ISystemClock() : ServiceFramework("ISystemClock") { |     ISystemClock(std::shared_ptr<Service::Time::SharedMemory> shared_memory, | ||||||
|  |                  ClockContextType clock_type) | ||||||
|  |         : ServiceFramework("ISystemClock"), shared_memory(shared_memory), clock_type(clock_type) { | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, |             {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, | ||||||
|             {1, nullptr, "SetCurrentTime"}, |             {1, nullptr, "SetCurrentTime"}, | ||||||
| @@ -72,6 +82,8 @@ public: | |||||||
|  |  | ||||||
|         }; |         }; | ||||||
|         RegisterHandlers(functions); |         RegisterHandlers(functions); | ||||||
|  |  | ||||||
|  |         UpdateSharedMemoryContext(system_clock_context); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -87,34 +99,63 @@ private: | |||||||
|     void GetSystemClockContext(Kernel::HLERequestContext& ctx) { |     void GetSystemClockContext(Kernel::HLERequestContext& ctx) { | ||||||
|         LOG_WARNING(Service_Time, "(STUBBED) called"); |         LOG_WARNING(Service_Time, "(STUBBED) called"); | ||||||
|  |  | ||||||
|         SystemClockContext system_clock_ontext{}; |         // TODO(ogniK): This should be updated periodically however since we have it stubbed we'll | ||||||
|  |         // only update when we get a new context | ||||||
|  |         UpdateSharedMemoryContext(system_clock_context); | ||||||
|  |  | ||||||
|         IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; |         IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; | ||||||
|         rb.Push(RESULT_SUCCESS); |         rb.Push(RESULT_SUCCESS); | ||||||
|         rb.PushRaw(system_clock_ontext); |         rb.PushRaw(system_clock_context); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void UpdateSharedMemoryContext(const SystemClockContext& clock_context) { | ||||||
|  |         switch (clock_type) { | ||||||
|  |         case ClockContextType::StandardLocalSystem: | ||||||
|  |             shared_memory->SetStandardLocalSystemClockContext(clock_context); | ||||||
|  |             break; | ||||||
|  |         case ClockContextType::StandardNetworkSystem: | ||||||
|  |             shared_memory->SetStandardNetworkSystemClockContext(clock_context); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SystemClockContext system_clock_context{}; | ||||||
|  |     std::shared_ptr<Service::Time::SharedMemory> shared_memory; | ||||||
|  |     ClockContextType clock_type; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ISteadyClock final : public ServiceFramework<ISteadyClock> { | class ISteadyClock final : public ServiceFramework<ISteadyClock> { | ||||||
| public: | public: | ||||||
|     ISteadyClock() : ServiceFramework("ISteadyClock") { |     ISteadyClock(std::shared_ptr<SharedMemory> shared_memory) | ||||||
|  |         : ServiceFramework("ISteadyClock"), shared_memory(shared_memory) { | ||||||
|         static const FunctionInfo functions[] = { |         static const FunctionInfo functions[] = { | ||||||
|             {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, |             {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, | ||||||
|         }; |         }; | ||||||
|         RegisterHandlers(functions); |         RegisterHandlers(functions); | ||||||
|  |  | ||||||
|  |         shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { |     void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { | ||||||
|         LOG_DEBUG(Service_Time, "called"); |         LOG_DEBUG(Service_Time, "called"); | ||||||
|  |  | ||||||
|         const auto& core_timing = Core::System::GetInstance().CoreTiming(); |         const auto time_point = GetCurrentTimePoint(); | ||||||
|         const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); |         // TODO(ogniK): This should be updated periodically | ||||||
|         const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), |         shared_memory->SetStandardSteadyClockTimepoint(time_point); | ||||||
|                                                            {}}; |  | ||||||
|         IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; |         IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; | ||||||
|         rb.Push(RESULT_SUCCESS); |         rb.Push(RESULT_SUCCESS); | ||||||
|         rb.PushRaw(steady_clock_time_point); |         rb.PushRaw(time_point); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     SteadyClockTimePoint GetCurrentTimePoint() const { | ||||||
|  |         const auto& core_timing = Core::System::GetInstance().CoreTiming(); | ||||||
|  |         const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); | ||||||
|  |         return {static_cast<u64_le>(ms.count() / 1000), {}}; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::shared_ptr<SharedMemory> shared_memory; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { | class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { | ||||||
| @@ -233,7 +274,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct | |||||||
|  |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushIpcInterface<ISystemClock>(); |     rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { | ||||||
| @@ -241,7 +282,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& | |||||||
|  |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushIpcInterface<ISystemClock>(); |     rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | ||||||
| @@ -249,7 +290,7 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | |||||||
|  |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushIpcInterface<ISteadyClock>(); |     rb.PushIpcInterface<ISteadyClock>(shared_memory); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { | ||||||
| @@ -265,7 +306,7 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c | |||||||
|  |  | ||||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushIpcInterface<ISystemClock>(); |     rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | ||||||
| @@ -333,16 +374,52 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser( | |||||||
|     rb.PushRaw<u64>(difference); |     rb.PushRaw<u64>(difference); | ||||||
| } | } | ||||||
|  |  | ||||||
| Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) | void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { | ||||||
|     : ServiceFramework(name), time(std::move(time)) {} |     LOG_DEBUG(Service_Time, "called"); | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  |     rb.PushCopyObjects(shared_memory->GetSharedMemoryHolder()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Module::Interface::IsStandardUserSystemClockAutomaticCorrectionEnabled( | ||||||
|  |     Kernel::HLERequestContext& ctx) { | ||||||
|  |     // ogniK(TODO): When clock contexts are implemented, the value should be read from the context | ||||||
|  |     // instead of our shared memory holder | ||||||
|  |     LOG_DEBUG(Service_Time, "called"); | ||||||
|  |  | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 3}; | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  |     rb.Push<u8>(shared_memory->GetStandardUserSystemClockAutomaticCorrectionEnabled()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Module::Interface::SetStandardUserSystemClockAutomaticCorrectionEnabled( | ||||||
|  |     Kernel::HLERequestContext& ctx) { | ||||||
|  |     IPC::RequestParser rp{ctx}; | ||||||
|  |     const auto enabled = rp.Pop<u8>(); | ||||||
|  |  | ||||||
|  |     LOG_WARNING(Service_Time, "(PARTIAL IMPLEMENTATION) called"); | ||||||
|  |  | ||||||
|  |     // TODO(ogniK): Update clock contexts and correct timespans | ||||||
|  |  | ||||||
|  |     shared_memory->SetStandardUserSystemClockAutomaticCorrectionEnabled(enabled > 0); | ||||||
|  |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |     rb.Push(RESULT_SUCCESS); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Module::Interface::Interface(std::shared_ptr<Module> time, | ||||||
|  |                              std::shared_ptr<SharedMemory> shared_memory, const char* name) | ||||||
|  |     : ServiceFramework(name), time(std::move(time)), shared_memory(std::move(shared_memory)) {} | ||||||
|  |  | ||||||
| Module::Interface::~Interface() = default; | Module::Interface::~Interface() = default; | ||||||
|  |  | ||||||
| void InstallInterfaces(SM::ServiceManager& service_manager) { | void InstallInterfaces(Core::System& system) { | ||||||
|     auto time = std::make_shared<Module>(); |     auto time = std::make_shared<Module>(); | ||||||
|     std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager); |     auto shared_mem = std::make_shared<SharedMemory>(system); | ||||||
|     std::make_shared<Time>(time, "time:s")->InstallAsService(service_manager); |  | ||||||
|     std::make_shared<Time>(time, "time:u")->InstallAsService(service_manager); |     std::make_shared<Time>(time, shared_mem, "time:a")->InstallAsService(system.ServiceManager()); | ||||||
|  |     std::make_shared<Time>(time, shared_mem, "time:s")->InstallAsService(system.ServiceManager()); | ||||||
|  |     std::make_shared<Time>(std::move(time), shared_mem, "time:u") | ||||||
|  |         ->InstallAsService(system.ServiceManager()); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Service::Time | } // namespace Service::Time | ||||||
|   | |||||||
| @@ -10,6 +10,8 @@ | |||||||
|  |  | ||||||
| namespace Service::Time { | namespace Service::Time { | ||||||
|  |  | ||||||
|  | class SharedMemory; | ||||||
|  |  | ||||||
| struct LocationName { | struct LocationName { | ||||||
|     std::array<u8, 0x24> name; |     std::array<u8, 0x24> name; | ||||||
| }; | }; | ||||||
| @@ -77,7 +79,8 @@ class Module final { | |||||||
| public: | public: | ||||||
|     class Interface : public ServiceFramework<Interface> { |     class Interface : public ServiceFramework<Interface> { | ||||||
|     public: |     public: | ||||||
|         explicit Interface(std::shared_ptr<Module> time, const char* name); |         explicit Interface(std::shared_ptr<Module> time, | ||||||
|  |                            std::shared_ptr<SharedMemory> shared_memory, const char* name); | ||||||
|         ~Interface() override; |         ~Interface() override; | ||||||
|  |  | ||||||
|         void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); |         void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); | ||||||
| @@ -87,13 +90,17 @@ public: | |||||||
|         void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); |         void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); | ||||||
|         void GetClockSnapshot(Kernel::HLERequestContext& ctx); |         void GetClockSnapshot(Kernel::HLERequestContext& ctx); | ||||||
|         void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); |         void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); | ||||||
|  |         void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); | ||||||
|  |         void IsStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); | ||||||
|  |         void SetStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); | ||||||
|  |  | ||||||
|     protected: |     protected: | ||||||
|         std::shared_ptr<Module> time; |         std::shared_ptr<Module> time; | ||||||
|  |         std::shared_ptr<SharedMemory> shared_memory; | ||||||
|     }; |     }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /// Registers all Time services with the specified service manager. | /// Registers all Time services with the specified service manager. | ||||||
| void InstallInterfaces(SM::ServiceManager& service_manager); | void InstallInterfaces(Core::System& system); | ||||||
|  |  | ||||||
| } // namespace Service::Time | } // namespace Service::Time | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								src/core/hle/service/time/time_sharedmemory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/core/hle/service/time/time_sharedmemory.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | // Copyright 2019 yuzu emulator team | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include "core/core.h" | ||||||
|  | #include "core/hle/service/time/time_sharedmemory.h" | ||||||
|  |  | ||||||
|  | namespace Service::Time { | ||||||
|  | const std::size_t SHARED_MEMORY_SIZE = 0x1000; | ||||||
|  |  | ||||||
|  | SharedMemory::SharedMemory(Core::System& system) : system(system) { | ||||||
|  |     shared_memory_holder = Kernel::SharedMemory::Create( | ||||||
|  |         system.Kernel(), nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite, | ||||||
|  |         Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "Time:SharedMemory"); | ||||||
|  |  | ||||||
|  |     // Seems static from 1.0.0 -> 8.1.0. Specific games seem to check this value and crash | ||||||
|  |     // if it's set to anything else | ||||||
|  |     shared_memory_format.format_version = 14; | ||||||
|  |     std::memcpy(shared_memory_holder->GetPointer(), &shared_memory_format, sizeof(Format)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SharedMemory::~SharedMemory() = default; | ||||||
|  |  | ||||||
|  | Kernel::SharedPtr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() const { | ||||||
|  |     return shared_memory_holder; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SharedMemory::SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint) { | ||||||
|  |     shared_memory_format.standard_steady_clock_timepoint.StoreData( | ||||||
|  |         shared_memory_holder->GetPointer(), timepoint); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SharedMemory::SetStandardLocalSystemClockContext(const SystemClockContext& context) { | ||||||
|  |     shared_memory_format.standard_local_system_clock_context.StoreData( | ||||||
|  |         shared_memory_holder->GetPointer(), context); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SharedMemory::SetStandardNetworkSystemClockContext(const SystemClockContext& context) { | ||||||
|  |     shared_memory_format.standard_network_system_clock_context.StoreData( | ||||||
|  |         shared_memory_holder->GetPointer(), context); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SharedMemory::SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled) { | ||||||
|  |     shared_memory_format.standard_user_system_clock_automatic_correction.StoreData( | ||||||
|  |         shared_memory_holder->GetPointer(), enabled); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SteadyClockTimePoint SharedMemory::GetStandardSteadyClockTimepoint() { | ||||||
|  |     return shared_memory_format.standard_steady_clock_timepoint.ReadData( | ||||||
|  |         shared_memory_holder->GetPointer()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SystemClockContext SharedMemory::GetStandardLocalSystemClockContext() { | ||||||
|  |     return shared_memory_format.standard_local_system_clock_context.ReadData( | ||||||
|  |         shared_memory_holder->GetPointer()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SystemClockContext SharedMemory::GetStandardNetworkSystemClockContext() { | ||||||
|  |     return shared_memory_format.standard_network_system_clock_context.ReadData( | ||||||
|  |         shared_memory_holder->GetPointer()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool SharedMemory::GetStandardUserSystemClockAutomaticCorrectionEnabled() { | ||||||
|  |     return shared_memory_format.standard_user_system_clock_automatic_correction.ReadData( | ||||||
|  |         shared_memory_holder->GetPointer()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace Service::Time | ||||||
							
								
								
									
										74
									
								
								src/core/hle/service/time/time_sharedmemory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/core/hle/service/time/time_sharedmemory.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | // Copyright 2019 yuzu emulator team | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/hle/kernel/shared_memory.h" | ||||||
|  | #include "core/hle/service/time/time.h" | ||||||
|  |  | ||||||
|  | namespace Service::Time { | ||||||
|  | class SharedMemory { | ||||||
|  | public: | ||||||
|  |     explicit SharedMemory(Core::System& system); | ||||||
|  |     ~SharedMemory(); | ||||||
|  |  | ||||||
|  |     // Return the shared memory handle | ||||||
|  |     Kernel::SharedPtr<Kernel::SharedMemory> GetSharedMemoryHolder() const; | ||||||
|  |  | ||||||
|  |     // Set memory barriers in shared memory and update them | ||||||
|  |     void SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint); | ||||||
|  |     void SetStandardLocalSystemClockContext(const SystemClockContext& context); | ||||||
|  |     void SetStandardNetworkSystemClockContext(const SystemClockContext& context); | ||||||
|  |     void SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled); | ||||||
|  |  | ||||||
|  |     // Pull from memory barriers in the shared memory | ||||||
|  |     SteadyClockTimePoint GetStandardSteadyClockTimepoint(); | ||||||
|  |     SystemClockContext GetStandardLocalSystemClockContext(); | ||||||
|  |     SystemClockContext GetStandardNetworkSystemClockContext(); | ||||||
|  |     bool GetStandardUserSystemClockAutomaticCorrectionEnabled(); | ||||||
|  |  | ||||||
|  |     // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? | ||||||
|  |     template <typename T, std::size_t Offset> | ||||||
|  |     struct MemoryBarrier { | ||||||
|  |         static_assert(std::is_trivially_constructible_v<T>, "T must be trivially constructable"); | ||||||
|  |         u32_le read_attempt{}; | ||||||
|  |         std::array<T, 2> data{}; | ||||||
|  |  | ||||||
|  |         // These are not actually memory barriers at the moment as we don't have multicore and all | ||||||
|  |         // HLE is mutexed. This will need to properly be implemented when we start updating the time | ||||||
|  |         // points on threads. As of right now, we'll be updated both values synchronously and just | ||||||
|  |         // incrementing the read_attempt to indicate that we waited. | ||||||
|  |         void StoreData(u8* shared_memory, T data_to_store) { | ||||||
|  |             std::memcpy(this, shared_memory + Offset, sizeof(*this)); | ||||||
|  |             read_attempt++; | ||||||
|  |             data[read_attempt & 1] = data_to_store; | ||||||
|  |             std::memcpy(shared_memory + Offset, this, sizeof(*this)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // For reading we're just going to read the last stored value. If there was no value stored | ||||||
|  |         // it will just end up reading an empty value as intended. | ||||||
|  |         T ReadData(u8* shared_memory) { | ||||||
|  |             std::memcpy(this, shared_memory + Offset, sizeof(*this)); | ||||||
|  |             return data[(read_attempt - 1) & 1]; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // Shared memory format | ||||||
|  |     struct Format { | ||||||
|  |         MemoryBarrier<SteadyClockTimePoint, 0x0> standard_steady_clock_timepoint; | ||||||
|  |         MemoryBarrier<SystemClockContext, 0x38> standard_local_system_clock_context; | ||||||
|  |         MemoryBarrier<SystemClockContext, 0x80> standard_network_system_clock_context; | ||||||
|  |         MemoryBarrier<bool, 0xc8> standard_user_system_clock_automatic_correction; | ||||||
|  |         u32_le format_version; | ||||||
|  |     }; | ||||||
|  |     static_assert(sizeof(Format) == 0xd8, "Format is an invalid size"); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     Kernel::SharedPtr<Kernel::SharedMemory> shared_memory_holder{}; | ||||||
|  |     Core::System& system; | ||||||
|  |     Format shared_memory_format{}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace Service::Time | ||||||
		Reference in New Issue
	
	Block a user