Merge pull request #2608 from ogniK5377/Time_GetSharedMemoryNativeHandle
Implement Time::GetSharedMemoryNativeHandle
This commit is contained in:
commit
e86af37ecb
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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