diff options
| author | Zach Hilman <DarkLordZach@users.noreply.github.com> | 2019-07-03 20:22:23 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-03 20:22:23 -0400 | 
| commit | e86af37ecbe3b8728a9c92a406bcce5ad419bc29 (patch) | |
| tree | 776514641a5784ad1fdef1f2d0a06d22629bc622 /src/core/hle | |
| parent | da5a537029a374053066a74186228f63b8344943 (diff) | |
| parent | f67039c067282e560175b1b346405e898b40e993 (diff) | |
Merge pull request #2608 from ogniK5377/Time_GetSharedMemoryNativeHandle
Implement Time::GetSharedMemoryNativeHandle
Diffstat (limited to 'src/core/hle')
| -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 | 
7 files changed, 258 insertions, 28 deletions
| 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,      Sockets::InstallInterfaces(*sm);      SPL::InstallInterfaces(*sm);      SSL::InstallInterfaces(*sm); -    Time::InstallInterfaces(*sm); +    Time::InstallInterfaces(system);      USB::InstallInterfaces(*sm);      VI::InstallInterfaces(*sm, nv_flinger);      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 @@  namespace Service::Time { -Time::Time(std::shared_ptr<Module> time, const char* name) -    : Module::Interface(std::move(time), name) { +Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory, +           const char* name) +    : Module::Interface(std::move(time), std::move(shared_memory), name) {      // clang-format off      static const FunctionInfo functions[] = {          {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, @@ -16,12 +17,12 @@ Time::Time(std::shared_ptr<Module> time, const char* name)          {3, &Time::GetTimeZoneService, "GetTimeZoneService"},          {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},          {5, nullptr, "GetEphemeralNetworkSystemClock"}, -        {20, nullptr, "GetSharedMemoryNativeHandle"}, +        {20, &Time::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},          {30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},          {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},          {50, nullptr, "SetStandardSteadyClockInternalOffset"}, -        {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, -        {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, +        {100, &Time::IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, +        {101, &Time::SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},          {102, nullptr, "GetStandardUserSystemClockInitialYear"},          {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},          {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 @@  namespace Service::Time { +class SharedMemory; +  class Time final : public Module::Interface {  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;  }; 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 @@  #include "core/hle/kernel/client_session.h"  #include "core/hle/service/time/interface.h"  #include "core/hle/service/time/time.h" +#include "core/hle/service/time/time_sharedmemory.h"  #include "core/settings.h"  namespace Service::Time { @@ -61,9 +62,18 @@ static u64 CalendarToPosix(const CalendarTime& calendar_time,      return static_cast<u64>(epoch_time);  } +enum class ClockContextType { +    StandardSteady, +    StandardUserSystem, +    StandardNetworkSystem, +    StandardLocalSystem, +}; +  class ISystemClock final : public ServiceFramework<ISystemClock> {  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[] = {              {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},              {1, nullptr, "SetCurrentTime"}, @@ -72,6 +82,8 @@ public:          };          RegisterHandlers(functions); + +        UpdateSharedMemoryContext(system_clock_context);      }  private: @@ -87,34 +99,63 @@ private:      void GetSystemClockContext(Kernel::HLERequestContext& ctx) {          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};          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> {  public: -    ISteadyClock() : ServiceFramework("ISteadyClock") { +    ISteadyClock(std::shared_ptr<SharedMemory> shared_memory) +        : ServiceFramework("ISteadyClock"), shared_memory(shared_memory) {          static const FunctionInfo functions[] = {              {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},          };          RegisterHandlers(functions); + +        shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint());      }  private:      void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {          LOG_DEBUG(Service_Time, "called"); -        const auto& core_timing = Core::System::GetInstance().CoreTiming(); -        const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); -        const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), -                                                           {}}; +        const auto time_point = GetCurrentTimePoint(); +        // TODO(ogniK): This should be updated periodically +        shared_memory->SetStandardSteadyClockTimepoint(time_point); +          IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};          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> { @@ -233,7 +274,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct      IPC::ResponseBuilder rb{ctx, 2, 0, 1};      rb.Push(RESULT_SUCCESS); -    rb.PushIpcInterface<ISystemClock>(); +    rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem);  }  void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { @@ -241,7 +282,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext&      IPC::ResponseBuilder rb{ctx, 2, 0, 1};      rb.Push(RESULT_SUCCESS); -    rb.PushIpcInterface<ISystemClock>(); +    rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem);  }  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};      rb.Push(RESULT_SUCCESS); -    rb.PushIpcInterface<ISteadyClock>(); +    rb.PushIpcInterface<ISteadyClock>(shared_memory);  }  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};      rb.Push(RESULT_SUCCESS); -    rb.PushIpcInterface<ISystemClock>(); +    rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem);  }  void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { @@ -333,16 +374,52 @@ void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(      rb.PushRaw<u64>(difference);  } -Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) -    : ServiceFramework(name), time(std::move(time)) {} +void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { +    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; -void InstallInterfaces(SM::ServiceManager& service_manager) { +void InstallInterfaces(Core::System& system) {      auto time = std::make_shared<Module>(); -    std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager); -    std::make_shared<Time>(time, "time:s")->InstallAsService(service_manager); -    std::make_shared<Time>(time, "time:u")->InstallAsService(service_manager); +    auto shared_mem = std::make_shared<SharedMemory>(system); + +    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 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 @@  namespace Service::Time { +class SharedMemory; +  struct LocationName {      std::array<u8, 0x24> name;  }; @@ -77,7 +79,8 @@ class Module final {  public:      class Interface : public ServiceFramework<Interface> {      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;          void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); @@ -87,13 +90,17 @@ public:          void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx);          void GetClockSnapshot(Kernel::HLERequestContext& ctx);          void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx); +        void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); +        void IsStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx); +        void SetStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx);      protected:          std::shared_ptr<Module> time; +        std::shared_ptr<SharedMemory> shared_memory;      };  };  /// Registers all Time services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(Core::System& system);  } // 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 @@ +// 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 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 @@ +// 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 | 
