Compare commits

...

7 Commits

Author SHA1 Message Date
bunnei
62c6c9f6a6 service: time: Update current time with changes to RTC setting.
- This can be used to advance time, e.g. for Pokemon Sword/Shield pokejobs.
2020-10-12 18:09:15 -07:00
bunnei
4c348f4069 Merge pull request #4766 from ReinUsesLisp/tmml-cube
shader/texture: Implement CUBE texture type for TMML and fix arrays
2020-10-12 12:53:57 -07:00
bunnei
419a59a7b1 Merge pull request #4775 from ReinUsesLisp/enforce-class-memaccess
video_core: Enforce -Wclass-memaccess
2020-10-09 23:38:02 -07:00
bunnei
f250011ba0 Merge pull request #4757 from german77/BetterMotion
InputCommon: Add compatibility with only accelerometer and auto calibrate for drift
2020-10-09 23:37:08 -07:00
ReinUsesLisp
dffaffaac1 shader/texture: Implement CUBE texture type for TMML and fix arrays
TMML takes an array argument that has no known meaning, this one appears
as the first component in gpr8 followed by s, t and r. Skip this
component when arrays are being used. Also implement CUBE texture types.

- Used by Pikmin 3: Deluxe Demo.
2020-10-07 23:17:46 -03:00
german
a54aee290f Address comments 2020-10-04 18:15:53 -05:00
german
a220d8799e Add compatibility with only accelerometer and auto calibrate for drift 2020-10-03 22:22:01 -05:00
12 changed files with 477 additions and 237 deletions

View File

@@ -40,6 +40,7 @@
#include "core/hle/service/lm/manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/time/time_manager.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/memory/cheat_engine.h"
@@ -121,7 +122,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, memory{system},
cpu_manager{system}, reporter{system}, applet_manager{system} {}
cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {}
ResultStatus Run() {
status = ResultStatus::Success;
@@ -189,6 +190,9 @@ struct System::Impl {
return ResultStatus::ErrorVideoCore;
}
// Initialize time manager, which must happen after kernel is created
time_manager.Initialize();
is_powered_on = true;
exit_lock = false;
@@ -387,6 +391,7 @@ struct System::Impl {
/// Service State
Service::Glue::ARPManager arp_manager;
Service::LM::Manager lm_manager{reporter};
Service::Time::TimeManager time_manager;
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -717,6 +722,14 @@ const Service::LM::Manager& System::GetLogManager() const {
return impl->lm_manager;
}
Service::Time::TimeManager& System::GetTimeManager() {
return impl->time_manager;
}
const Service::Time::TimeManager& System::GetTimeManager() const {
return impl->time_manager;
}
void System::SetExitLock(bool locked) {
impl->exit_lock = locked;
}

View File

@@ -69,6 +69,10 @@ namespace SM {
class ServiceManager;
} // namespace SM
namespace Time {
class TimeManager;
} // namespace Time
} // namespace Service
namespace Tegra {
@@ -361,6 +365,10 @@ public:
const Service::LM::Manager& GetLogManager() const;
Service::Time::TimeManager& GetTimeManager();
const Service::Time::TimeManager& GetTimeManager() const;
void SetExitLock(bool locked);
bool GetExitLock() const;

View File

@@ -10,6 +10,7 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/scheduler.h"
#include "core/hle/service/time/interface.h"
#include "core/hle/service/time/time.h"
@@ -125,7 +126,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
Kernel::Thread* thread, Clock::SystemClockContext user_context,
Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) {
auto& time_manager{module->GetTimeManager()};
auto& time_manager{system.GetTimeManager()};
clock_snapshot.is_automatic_correction_enabled =
time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
@@ -182,7 +183,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardUserSystemClockCore(),
rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardUserSystemClockCore(),
system);
}
@@ -190,7 +191,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext&
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardNetworkSystemClockCore(),
rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardNetworkSystemClockCore(),
system);
}
@@ -198,29 +199,28 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISteadyClock>(module->GetTimeManager().GetStandardSteadyClockCore(),
system);
rb.PushIpcInterface<ISteadyClock>(system.GetTimeManager().GetStandardSteadyClockCore(), system);
}
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager());
rb.PushIpcInterface<ITimeZoneService>(system.GetTimeManager().GetTimeZoneContentManager());
}
void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardLocalSystemClockCore(),
rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardLocalSystemClockCore(),
system);
}
void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()};
auto& clock_core{system.GetTimeManager().GetStandardNetworkSystemClockCore()};
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system));
@@ -229,7 +229,7 @@ void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
auto& steady_clock_core{module->GetTimeManager().GetStandardSteadyClockCore()};
auto& steady_clock_core{system.GetTimeManager().GetStandardSteadyClockCore()};
if (!steady_clock_core.IsInitialized()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERROR_UNINITIALIZED_CLOCK);
@@ -262,8 +262,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
Clock::SystemClockContext user_context{};
if (const ResultCode result{
module->GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(
system, user_context)};
system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system,
user_context)};
result.IsError()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
@@ -271,7 +271,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
}
Clock::SystemClockContext network_context{};
if (const ResultCode result{
module->GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
system, network_context)};
result.IsError()) {
IPC::ResponseBuilder rb{ctx, 2};
@@ -372,7 +372,7 @@ void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& c
LOG_DEBUG(Service_Time, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(module->GetTimeManager().GetSharedMemory().GetSharedMemoryHolder());
rb.PushCopyObjects(SharedFrom(&system.Kernel().GetTimeSharedMem()));
}
Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name)
@@ -381,7 +381,7 @@ Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& syste
Module::Interface::~Interface() = default;
void InstallInterfaces(Core::System& system) {
auto module{std::make_shared<Module>(system)};
auto module{std::make_shared<Module>()};
std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager());
std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager());
std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager());

View File

@@ -16,7 +16,7 @@ namespace Service::Time {
class Module final {
public:
Module(Core::System& system) : time_manager{system} {}
Module() = default;
class Interface : public ServiceFramework<Interface> {
public:
@@ -46,13 +46,6 @@ public:
std::shared_ptr<Module> module;
Core::System& system;
};
TimeManager& GetTimeManager() {
return time_manager;
}
private:
TimeManager time_manager;
};
/// Registers all Time services with the specified service manager.

View File

@@ -22,7 +22,277 @@ static std::chrono::seconds GetSecondsSinceEpoch() {
Settings::values.custom_rtc_differential;
}
static s64 GetExternalTimeZoneOffset() {
static s64 GetExternalRtcValue() {
return GetSecondsSinceEpoch().count() + TimeManager::GetExternalTimeZoneOffset();
}
struct TimeManager::Impl final {
explicit Impl(Core::System& system)
: shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
standard_network_system_clock_core{standard_steady_clock_core},
standard_user_system_clock_core{standard_local_system_clock_core,
standard_network_system_clock_core, system},
ephemeral_network_system_clock_core{tick_based_steady_clock_core},
local_system_clock_context_writer{
std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
network_system_clock_context_writer{
std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
ephemeral_network_system_clock_context_writer{
std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
time_zone_content_manager{system} {
const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy);
SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
SetupEphemeralNetworkSystemClock();
}
~Impl() = default;
Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() {
return standard_steady_clock_core;
}
const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const {
return standard_steady_clock_core;
}
Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() {
return standard_local_system_clock_core;
}
const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const {
return standard_local_system_clock_core;
}
Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() {
return standard_network_system_clock_core;
}
const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const {
return standard_network_system_clock_core;
}
Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() {
return standard_user_system_clock_core;
}
const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const {
return standard_user_system_clock_core;
}
TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() {
return time_zone_content_manager;
}
const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const {
return time_zone_content_manager;
}
SharedMemory& GetSharedMemory() {
return shared_memory;
}
const SharedMemory& GetSharedMemory() const {
return shared_memory;
}
void SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
std::size_t total_location_name_count, u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file) {
if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
location_name, vfs_file) != RESULT_SUCCESS) {
UNREACHABLE();
return;
}
time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
total_location_name_count);
time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(
time_zone_rule_version);
time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
}
static s64 GetExternalTimeZoneOffset() {
// With "auto" timezone setting, we use the external system's timezone offset
if (Settings::GetTimeZoneString() == "auto") {
return Common::TimeZone::GetCurrentOffsetSeconds().count();
}
return 0;
}
void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
Clock::TimeSpanType setup_value,
Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) {
standard_steady_clock_core.SetClockSourceId(clock_source_id);
standard_steady_clock_core.SetSetupValue(setup_value);
standard_steady_clock_core.SetInternalOffset(internal_offset);
standard_steady_clock_core.MarkAsInitialized();
const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)};
shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point);
}
void SetupStandardLocalSystemClock(Core::System& system,
Clock::SystemClockContext clock_context, s64 posix_time) {
standard_local_system_clock_core.SetUpdateCallbackInstance(
local_system_clock_context_writer);
const auto current_time_point{
standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)};
if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) {
standard_local_system_clock_core.SetSystemClockContext(clock_context);
} else {
if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) !=
RESULT_SUCCESS) {
UNREACHABLE();
return;
}
}
standard_local_system_clock_core.MarkAsInitialized();
}
void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
Clock::TimeSpanType sufficient_accuracy) {
standard_network_system_clock_core.SetUpdateCallbackInstance(
network_system_clock_context_writer);
if (standard_network_system_clock_core.SetSystemClockContext(clock_context) !=
RESULT_SUCCESS) {
UNREACHABLE();
return;
}
standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy(
sufficient_accuracy);
standard_network_system_clock_core.MarkAsInitialized();
}
void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled,
Clock::SteadyClockTimePoint steady_clock_time_point) {
if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
system, is_automatic_correction_enabled) != RESULT_SUCCESS) {
UNREACHABLE();
return;
}
standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point);
standard_user_system_clock_core.MarkAsInitialized();
shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled);
}
void SetupEphemeralNetworkSystemClock() {
ephemeral_network_system_clock_core.SetUpdateCallbackInstance(
ephemeral_network_system_clock_context_writer);
ephemeral_network_system_clock_core.MarkAsInitialized();
}
void UpdateLocalSystemClockTime(Core::System& system, s64 posix_time) {
const auto timespan{Service::Time::Clock::TimeSpanType::FromSeconds(posix_time)};
if (GetStandardLocalSystemClockCore()
.SetCurrentTime(system, timespan.ToSeconds())
.IsError()) {
UNREACHABLE();
return;
}
}
SharedMemory shared_memory;
Clock::StandardSteadyClockCore standard_steady_clock_core;
Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
Clock::StandardUserSystemClockCore standard_user_system_clock_core;
Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
ephemeral_network_system_clock_context_writer;
TimeZone::TimeZoneContentManager time_zone_content_manager;
};
TimeManager::TimeManager(Core::System& system) : system{system} {}
TimeManager::~TimeManager() = default;
void TimeManager::Initialize() {
impl = std::make_unique<Impl>(system);
// Time zones can only be initialized after impl is valid
impl->time_zone_content_manager.Initialize(*this);
}
Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() {
return impl->standard_steady_clock_core;
}
const Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() const {
return impl->standard_steady_clock_core;
}
Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() {
return impl->standard_local_system_clock_core;
}
const Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() const {
return impl->standard_local_system_clock_core;
}
Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() {
return impl->standard_network_system_clock_core;
}
const Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore()
const {
return impl->standard_network_system_clock_core;
}
Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() {
return impl->standard_user_system_clock_core;
}
const Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() const {
return impl->standard_user_system_clock_core;
}
TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() {
return impl->time_zone_content_manager;
}
const TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() const {
return impl->time_zone_content_manager;
}
SharedMemory& TimeManager::GetSharedMemory() {
return impl->shared_memory;
}
const SharedMemory& TimeManager::GetSharedMemory() const {
return impl->shared_memory;
}
void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
impl->UpdateLocalSystemClockTime(system, posix_time);
}
void TimeManager::SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
std::size_t total_location_name_count,
u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file) {
impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point,
total_location_name_count, time_zone_rule_version, vfs_file);
}
/*static*/ s64 TimeManager::GetExternalTimeZoneOffset() {
// With "auto" timezone setting, we use the external system's timezone offset
if (Settings::GetTimeZoneString() == "auto") {
return Common::TimeZone::GetCurrentOffsetSeconds().count();
@@ -30,117 +300,4 @@ static s64 GetExternalTimeZoneOffset() {
return 0;
}
static s64 GetExternalRtcValue() {
return GetSecondsSinceEpoch().count() + GetExternalTimeZoneOffset();
}
TimeManager::TimeManager(Core::System& system)
: shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
standard_network_system_clock_core{standard_steady_clock_core},
standard_user_system_clock_core{standard_local_system_clock_core,
standard_network_system_clock_core, system},
ephemeral_network_system_clock_core{tick_based_steady_clock_core},
local_system_clock_context_writer{
std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
network_system_clock_context_writer{
std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
ephemeral_network_system_clock_context_writer{
std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
time_zone_content_manager{*this, system} {
const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy);
SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
SetupEphemeralNetworkSystemClock();
}
TimeManager::~TimeManager() = default;
void TimeManager::SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
std::size_t total_location_name_count,
u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file) {
if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
location_name, vfs_file) != RESULT_SUCCESS) {
UNREACHABLE();
return;
}
time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
total_location_name_count);
time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(time_zone_rule_version);
time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
}
void TimeManager::SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
Clock::TimeSpanType setup_value,
Clock::TimeSpanType internal_offset,
bool is_rtc_reset_detected) {
standard_steady_clock_core.SetClockSourceId(clock_source_id);
standard_steady_clock_core.SetSetupValue(setup_value);
standard_steady_clock_core.SetInternalOffset(internal_offset);
standard_steady_clock_core.MarkAsInitialized();
const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)};
shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point);
}
void TimeManager::SetupStandardLocalSystemClock(Core::System& system,
Clock::SystemClockContext clock_context,
s64 posix_time) {
standard_local_system_clock_core.SetUpdateCallbackInstance(local_system_clock_context_writer);
const auto current_time_point{
standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)};
if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) {
standard_local_system_clock_core.SetSystemClockContext(clock_context);
} else {
if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != RESULT_SUCCESS) {
UNREACHABLE();
return;
}
}
standard_local_system_clock_core.MarkAsInitialized();
}
void TimeManager::SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
Clock::TimeSpanType sufficient_accuracy) {
standard_network_system_clock_core.SetUpdateCallbackInstance(
network_system_clock_context_writer);
if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != RESULT_SUCCESS) {
UNREACHABLE();
return;
}
standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy(
sufficient_accuracy);
standard_network_system_clock_core.MarkAsInitialized();
}
void TimeManager::SetupStandardUserSystemClock(
Core::System& system, bool is_automatic_correction_enabled,
Clock::SteadyClockTimePoint steady_clock_time_point) {
if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
system, is_automatic_correction_enabled) != RESULT_SUCCESS) {
UNREACHABLE();
return;
}
standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point);
standard_user_system_clock_core.MarkAsInitialized();
shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled);
}
void TimeManager::SetupEphemeralNetworkSystemClock() {
ephemeral_network_system_clock_core.SetUpdateCallbackInstance(
ephemeral_network_system_clock_context_writer);
ephemeral_network_system_clock_core.MarkAsInitialized();
}
} // namespace Service::Time

View File

@@ -5,6 +5,7 @@
#pragma once
#include "common/common_types.h"
#include "common/time_zone.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/service/time/clock_types.h"
#include "core/hle/service/time/ephemeral_network_system_clock_core.h"
@@ -32,86 +33,46 @@ public:
explicit TimeManager(Core::System& system);
~TimeManager();
Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() {
return standard_steady_clock_core;
}
void Initialize();
const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const {
return standard_steady_clock_core;
}
Clock::StandardSteadyClockCore& GetStandardSteadyClockCore();
Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() {
return standard_local_system_clock_core;
}
const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const;
const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const {
return standard_local_system_clock_core;
}
Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore();
Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() {
return standard_network_system_clock_core;
}
const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const;
const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const {
return standard_network_system_clock_core;
}
Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore();
Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() {
return standard_user_system_clock_core;
}
const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const;
const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const {
return standard_user_system_clock_core;
}
Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore();
TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() {
return time_zone_content_manager;
}
const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const;
const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const {
return time_zone_content_manager;
}
TimeZone::TimeZoneContentManager& GetTimeZoneContentManager();
SharedMemory& GetSharedMemory() {
return shared_memory;
}
const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const;
const SharedMemory& GetSharedMemory() const {
return shared_memory;
}
void UpdateLocalSystemClockTime(s64 posix_time);
SharedMemory& GetSharedMemory();
const SharedMemory& GetSharedMemory() const;
void SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
std::size_t total_location_name_count, u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file);
static s64 GetExternalTimeZoneOffset();
private:
void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
Clock::TimeSpanType setup_value,
Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected);
void SetupStandardLocalSystemClock(Core::System& system,
Clock::SystemClockContext clock_context, s64 posix_time);
void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
Clock::TimeSpanType sufficient_accuracy);
void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled,
Clock::SteadyClockTimePoint steady_clock_time_point);
void SetupEphemeralNetworkSystemClock();
Core::System& system;
SharedMemory shared_memory;
Clock::StandardSteadyClockCore standard_steady_clock_core;
Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
Clock::StandardUserSystemClockCore standard_user_system_clock_core;
Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
ephemeral_network_system_clock_context_writer;
TimeZone::TimeZoneContentManager time_zone_content_manager;
struct Impl;
std::unique_ptr<Impl> impl;
};
} // namespace Service::Time

View File

@@ -68,9 +68,10 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
return location_name_cache;
}
TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::System& system)
: system{system}, location_name_cache{BuildLocationNameCache(system)} {
TimeZoneContentManager::TimeZoneContentManager(Core::System& system)
: system{system}, location_name_cache{BuildLocationNameCache(system)} {}
void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
std::string location_name;
const auto timezone_setting = Settings::GetTimeZoneString();
if (timezone_setting == "auto" || timezone_setting == "default") {

View File

@@ -21,7 +21,9 @@ namespace Service::Time::TimeZone {
class TimeZoneContentManager final {
public:
TimeZoneContentManager(TimeManager& time_manager, Core::System& system);
TimeZoneContentManager(Core::System& system);
void Initialize(TimeManager& time_manager);
TimeZoneManager& GetTimeZoneManager() {
return time_zone_manager;

View File

@@ -17,8 +17,16 @@ void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
gyro = gyroscope - gyro_drift;
// Auto adjust drift to minimize drift
if (!IsMoving(0.1f)) {
gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f);
}
if (gyro.Length2() < gyro_threshold) {
gyro = {};
} else {
only_accelerometer = false;
}
}
@@ -69,7 +77,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
f32 q4 = quat.xyz[2];
const f32 sample_period = elapsed_time / 1000000.0f;
// ignore invalid elapsed time
// Ignore invalid elapsed time
if (sample_period > 0.1f) {
return;
}
@@ -81,6 +89,13 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
rad_gyro.y = -swap;
rad_gyro.z = -rad_gyro.z;
// Clear gyro values if there is no gyro present
if (only_accelerometer) {
rad_gyro.x = 0;
rad_gyro.y = 0;
rad_gyro.z = 0;
}
// Ignore drift correction if acceleration is not reliable
if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) {
const f32 ax = -normal_accel.x;
@@ -93,8 +108,11 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
// Error is cross product between estimated direction and measured direction of gravity
const Common::Vec3f new_real_error = {az * vx - ax * vz, ay * vz - az * vy,
ax * vy - ay * vx};
const Common::Vec3f new_real_error = {
az * vx - ax * vz,
ay * vz - az * vy,
ax * vy - ay * vx,
};
derivative_error = new_real_error - real_error;
real_error = new_real_error;
@@ -107,9 +125,22 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) {
}
// Apply feedback terms
rad_gyro += kp * real_error;
rad_gyro += ki * integral_error;
rad_gyro += kd * derivative_error;
if (!only_accelerometer) {
rad_gyro += kp * real_error;
rad_gyro += ki * integral_error;
rad_gyro += kd * derivative_error;
} else {
// Give more weight to acelerometer values to compensate for the lack of gyro
rad_gyro += 35.0f * kp * real_error;
rad_gyro += 10.0f * ki * integral_error;
rad_gyro += 10.0f * kd * derivative_error;
// Emulate gyro values for games that need them
gyro.x = -rad_gyro.y;
gyro.y = rad_gyro.x;
gyro.z = -rad_gyro.z;
UpdateRotation(elapsed_time);
}
}
const f32 gx = rad_gyro.y;
@@ -192,17 +223,17 @@ Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_m
}
void MotionInput::ResetOrientation() {
if (!reset_enabled) {
if (!reset_enabled || only_accelerometer) {
return;
}
if (!IsMoving(0.5f) && accel.z <= -0.9f) {
++reset_counter;
if (reset_counter > 900) {
// TODO: calculate quaternion from gravity vector
quat.w = 0;
quat.xyz[0] = 0;
quat.xyz[1] = 0;
quat.xyz[2] = -1;
SetOrientationFromAccelerometer();
integral_error = {};
reset_counter = 0;
}
@@ -210,4 +241,65 @@ void MotionInput::ResetOrientation() {
reset_counter = 0;
}
}
void MotionInput::SetOrientationFromAccelerometer() {
int iterations = 0;
const f32 sample_period = 0.015f;
const auto normal_accel = accel.Normalized();
const f32 ax = -normal_accel.x;
const f32 ay = normal_accel.y;
const f32 az = -normal_accel.z;
while (!IsCalibrated(0.01f) && ++iterations < 100) {
// Short name local variable for readability
f32 q1 = quat.w;
f32 q2 = quat.xyz[0];
f32 q3 = quat.xyz[1];
f32 q4 = quat.xyz[2];
Common::Vec3f rad_gyro = {};
const f32 ax = -normal_accel.x;
const f32 ay = normal_accel.y;
const f32 az = -normal_accel.z;
// Estimated direction of gravity
const f32 vx = 2.0f * (q2 * q4 - q1 * q3);
const f32 vy = 2.0f * (q1 * q2 + q3 * q4);
const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
// Error is cross product between estimated direction and measured direction of gravity
const Common::Vec3f new_real_error = {
az * vx - ax * vz,
ay * vz - az * vy,
ax * vy - ay * vx,
};
derivative_error = new_real_error - real_error;
real_error = new_real_error;
rad_gyro += 10.0f * kp * real_error;
rad_gyro += 5.0f * ki * integral_error;
rad_gyro += 10.0f * kd * derivative_error;
const f32 gx = rad_gyro.y;
const f32 gy = rad_gyro.x;
const f32 gz = rad_gyro.z;
// Integrate rate of change of quaternion
const f32 pa = q2;
const f32 pb = q3;
const f32 pc = q4;
q1 = q1 + (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * sample_period);
q2 = pa + (q1 * gx + pb * gz - pc * gy) * (0.5f * sample_period);
q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period);
q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period);
quat.w = q1;
quat.xyz[0] = q2;
quat.xyz[1] = q3;
quat.xyz[2] = q4;
quat = quat.Normalized();
}
}
} // namespace InputCommon

View File

@@ -46,6 +46,7 @@ public:
private:
void ResetOrientation();
void SetOrientationFromAccelerometer();
// PID constants
const f32 kp;
@@ -66,6 +67,7 @@ private:
f32 gyro_threshold = 0.0f;
u32 reset_counter = 0;
bool reset_enabled = true;
bool only_accelerometer = true;
};
} // namespace InputCommon

View File

@@ -292,33 +292,36 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
break;
}
const u64 base_index = is_array ? 1 : 0;
const u64 num_components = [texture_type] {
switch (texture_type) {
case TextureType::Texture1D:
return 1;
case TextureType::Texture2D:
return 2;
case TextureType::TextureCube:
return 3;
default:
UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<int>(texture_type));
return 2;
}
}();
// TODO: What's the array component used for?
std::vector<Node> coords;
// TODO: Add coordinates for different samplers once other texture types are implemented.
switch (texture_type) {
case TextureType::Texture1D:
coords.push_back(GetRegister(instr.gpr8));
break;
case TextureType::Texture2D:
coords.push_back(GetRegister(instr.gpr8.Value() + 0));
coords.push_back(GetRegister(instr.gpr8.Value() + 1));
break;
default:
UNIMPLEMENTED_MSG("Unhandled texture type {}", static_cast<int>(texture_type));
// Fallback to interpreting as a 2D texture for now
coords.push_back(GetRegister(instr.gpr8.Value() + 0));
coords.push_back(GetRegister(instr.gpr8.Value() + 1));
coords.reserve(num_components);
for (u64 component = 0; component < num_components; ++component) {
coords.push_back(GetRegister(instr.gpr8.Value() + base_index + component));
}
u32 indexer = 0;
for (u32 element = 0; element < 2; ++element) {
if (!instr.tmml.IsComponentEnabled(element)) {
continue;
}
auto params = coords;
MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var};
const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params));
SetTemporary(bb, indexer++, value);
Node value = Operation(OperationCode::TextureQueryLod, meta, coords);
SetTemporary(bb, indexer++, std::move(value));
}
for (u32 i = 0; i < indexer; ++i) {
SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));

View File

@@ -12,6 +12,7 @@
#include "common/assert.h"
#include "common/file_util.h"
#include "core/core.h"
#include "core/hle/service/time/time.h"
#include "core/settings.h"
#include "ui_configure_system.h"
#include "yuzu/configuration/configuration_shared.h"
@@ -104,6 +105,22 @@ void ConfigureSystem::SetConfiguration() {
void ConfigureSystem::ReadSystemSettings() {}
void ConfigureSystem::ApplyConfiguration() {
// Allow setting custom RTC even if system is powered on, to allow in-game time to be fast
// forwared
if (Settings::values.custom_rtc.UsingGlobal()) {
if (ui->custom_rtc_checkbox->isChecked()) {
Settings::values.custom_rtc.SetValue(
std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
if (Core::System::GetInstance().IsPoweredOn()) {
const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() +
Service::Time::TimeManager::GetExternalTimeZoneOffset()};
Core::System::GetInstance().GetTimeManager().UpdateLocalSystemClockTime(posix_time);
}
} else {
Settings::values.custom_rtc.SetValue(std::nullopt);
}
}
if (!enabled) {
return;
}
@@ -131,15 +148,6 @@ void ConfigureSystem::ApplyConfiguration() {
Settings::values.rng_seed.SetValue(std::nullopt);
}
}
if (Settings::values.custom_rtc.UsingGlobal()) {
if (ui->custom_rtc_checkbox->isChecked()) {
Settings::values.custom_rtc.SetValue(
std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
} else {
Settings::values.custom_rtc.SetValue(std::nullopt);
}
}
} else {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index,
ui->combo_language);