101 lines
3.8 KiB
C++
Executable File
101 lines
3.8 KiB
C++
Executable File
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <chrono>
|
|
|
|
#include "core/core.h"
|
|
#include "core/core_timing.h"
|
|
#include "core/hle/service/psc/time/clocks/standard_steady_clock_core.h"
|
|
|
|
namespace Service::PSC::Time {
|
|
|
|
void StandardSteadyClockCore::Initialize(ClockSourceId clock_source_id, s64 rtc_offset,
|
|
s64 internal_offset, s64 test_offset,
|
|
bool is_rtc_reset_detected) {
|
|
m_clock_source_id = clock_source_id;
|
|
m_rtc_offset = rtc_offset;
|
|
m_internal_offset = internal_offset;
|
|
m_test_offset = test_offset;
|
|
if (is_rtc_reset_detected) {
|
|
SetResetDetected();
|
|
}
|
|
SetInitialized();
|
|
}
|
|
|
|
void StandardSteadyClockCore::SetRtcOffset(s64 offset) {
|
|
m_rtc_offset = offset;
|
|
}
|
|
|
|
void StandardSteadyClockCore::SetContinuousAdjustment(ClockSourceId clock_source_id, s64 time) {
|
|
auto ticks{m_system.CoreTiming().GetClockTicks()};
|
|
|
|
m_continuous_adjustment_time_point.rtc_offset = ConvertToTimeSpan(ticks).count();
|
|
m_continuous_adjustment_time_point.diff_scale = 0;
|
|
m_continuous_adjustment_time_point.shift_amount = 0;
|
|
m_continuous_adjustment_time_point.lower = time;
|
|
m_continuous_adjustment_time_point.upper = time;
|
|
m_continuous_adjustment_time_point.clock_source_id = clock_source_id;
|
|
}
|
|
|
|
void StandardSteadyClockCore::GetContinuousAdjustment(
|
|
ContinuousAdjustmentTimePoint& out_time_point) const {
|
|
out_time_point = m_continuous_adjustment_time_point;
|
|
}
|
|
|
|
void StandardSteadyClockCore::UpdateContinuousAdjustmentTime(s64 in_time) {
|
|
auto ticks{m_system.CoreTiming().GetClockTicks()};
|
|
auto global_time_ns{ConvertToTimeSpan(ticks).count()};
|
|
auto expected_time{((global_time_ns - m_continuous_adjustment_time_point.rtc_offset) *
|
|
m_continuous_adjustment_time_point.diff_scale) >>
|
|
m_continuous_adjustment_time_point.shift_amount};
|
|
|
|
auto last_time_point{m_continuous_adjustment_time_point.upper};
|
|
m_continuous_adjustment_time_point.upper = in_time;
|
|
auto t1{std::min<s64>(expected_time, last_time_point)};
|
|
expected_time = std::max<s64>(expected_time, last_time_point);
|
|
expected_time = m_continuous_adjustment_time_point.diff_scale >= 0 ? t1 : expected_time;
|
|
|
|
auto new_diff{in_time < expected_time ? -55 : 55};
|
|
|
|
m_continuous_adjustment_time_point.rtc_offset = global_time_ns;
|
|
m_continuous_adjustment_time_point.shift_amount = expected_time == in_time ? 0 : 14;
|
|
m_continuous_adjustment_time_point.diff_scale = expected_time == in_time ? 0 : new_diff;
|
|
m_continuous_adjustment_time_point.lower = expected_time;
|
|
}
|
|
|
|
Result StandardSteadyClockCore::GetCurrentTimePointImpl(SteadyClockTimePoint& out_time_point) {
|
|
auto current_time_ns = GetCurrentRawTimePointImpl();
|
|
auto current_time_s =
|
|
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::nanoseconds(current_time_ns));
|
|
out_time_point.time_point = current_time_s.count();
|
|
out_time_point.clock_source_id = m_clock_source_id;
|
|
R_SUCCEED();
|
|
}
|
|
|
|
s64 StandardSteadyClockCore::GetCurrentRawTimePointImpl() {
|
|
std::scoped_lock l{m_mutex};
|
|
auto ticks{static_cast<s64>(m_system.CoreTiming().GetClockTicks())};
|
|
auto current_time_ns = m_rtc_offset + ConvertToTimeSpan(ticks).count();
|
|
auto time_point = std::max<s64>(current_time_ns, m_cached_time_point);
|
|
m_cached_time_point = time_point;
|
|
return time_point;
|
|
}
|
|
|
|
s64 StandardSteadyClockCore::GetTestOffsetImpl() const {
|
|
return m_test_offset;
|
|
}
|
|
|
|
void StandardSteadyClockCore::SetTestOffsetImpl(s64 offset) {
|
|
m_test_offset = offset;
|
|
}
|
|
|
|
s64 StandardSteadyClockCore::GetInternalOffsetImpl() const {
|
|
return m_internal_offset;
|
|
}
|
|
|
|
void StandardSteadyClockCore::SetInternalOffsetImpl(s64 offset) {
|
|
m_internal_offset = offset;
|
|
}
|
|
|
|
} // namespace Service::PSC::Time
|