diff options
Diffstat (limited to 'src')
42 files changed, 616 insertions, 213 deletions
diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index 6fe844ff0..8b9b65214 100644 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -308,7 +308,8 @@ static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, Rever } Common::FixedPoint<50, 14> pre_delay_sample{ - state.pre_delay_line.Read() * Common::FixedPoint<50, 14>::from_base(params.late_gain)}; + state.pre_delay_line.TapOut(state.pre_delay_time) * + Common::FixedPoint<50, 14>::from_base(params.late_gain)}; std::array<Common::FixedPoint<50, 14>, ReverbInfo::MaxDelayLines> mix_matrix{ state.prev_feedback_output[2] + state.prev_feedback_output[1] + pre_delay_sample, diff --git a/src/audio_core/renderer/effect/i3dl2.h b/src/audio_core/renderer/effect/i3dl2.h index 1ebbc5c4c..6e3ffd1d4 100644 --- a/src/audio_core/renderer/effect/i3dl2.h +++ b/src/audio_core/renderer/effect/i3dl2.h @@ -104,7 +104,8 @@ public: } void Write(const Common::FixedPoint<50, 14> sample) { - *(input++) = sample; + *input = sample; + input++; if (input >= buffer_end) { input = buffer.data(); } diff --git a/src/audio_core/renderer/effect/reverb.h b/src/audio_core/renderer/effect/reverb.h index a72475c3c..6cc345ef6 100644 --- a/src/audio_core/renderer/effect/reverb.h +++ b/src/audio_core/renderer/effect/reverb.h @@ -79,12 +79,10 @@ public: return; } sample_count = delay_time; - input = &buffer[(output - buffer.data() + sample_count) % (sample_count_max + 1)]; + input = &buffer[0]; } Common::FixedPoint<50, 14> Tick(const Common::FixedPoint<50, 14> sample) { - Write(sample); - auto out_sample{Read()}; output++; @@ -92,6 +90,7 @@ public: output = buffer.data(); } + Write(sample); return out_sample; } @@ -100,7 +99,8 @@ public: } void Write(const Common::FixedPoint<50, 14> sample) { - *(input++) = sample; + *input = sample; + input++; if (input >= buffer_end) { input = buffer.data(); } diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 56b247ac4..61ab68864 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -91,6 +91,7 @@ add_library(common STATIC multi_level_page_table.h nvidia_flags.cpp nvidia_flags.h + overflow.h page_table.cpp page_table.h param_package.cpp @@ -113,6 +114,8 @@ add_library(common STATIC socket_types.h spin_lock.cpp spin_lock.h + steady_clock.cpp + steady_clock.h stream.cpp stream.h string_util.cpp @@ -142,6 +145,14 @@ add_library(common STATIC zstd_compression.h ) +if (WIN32) + target_sources(common PRIVATE + windows/timer_resolution.cpp + windows/timer_resolution.h + ) + target_link_libraries(common PRIVATE ntdll) +endif() + if(ARCHITECTURE_x86_64) target_sources(common PRIVATE diff --git a/src/common/bit_cast.h b/src/common/bit_cast.h index 535148b4d..c6110c542 100644 --- a/src/common/bit_cast.h +++ b/src/common/bit_cast.h @@ -3,19 +3,21 @@ #pragma once -#include <cstring> -#include <type_traits> +#include <version> + +#ifdef __cpp_lib_bit_cast +#include <bit> +#endif namespace Common { template <typename To, typename From> -[[nodiscard]] std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> && - std::is_trivially_copyable_v<To>, - To> -BitCast(const From& src) noexcept { - To dst; - std::memcpy(&dst, &src, sizeof(To)); - return dst; +constexpr inline To BitCast(const From& from) { +#ifdef __cpp_lib_bit_cast + return std::bit_cast<To>(from); +#else + return __builtin_bit_cast(To, from); +#endif } } // namespace Common diff --git a/src/common/input.h b/src/common/input.h index b5748a6c8..98e934685 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -46,7 +46,7 @@ enum class PollingMode { // Constant polling of buttons, analogs and motion data Active, // Only update on button change, digital analogs - Pasive, + Passive, // Enable near field communication polling NFC, // Enable infrared camera polling diff --git a/src/common/overflow.h b/src/common/overflow.h new file mode 100644 index 000000000..44d8e7e73 --- /dev/null +++ b/src/common/overflow.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <type_traits> +#include "bit_cast.h" + +namespace Common { + +template <typename T> + requires(std::is_integral_v<T> && std::is_signed_v<T>) +inline T WrappingAdd(T lhs, T rhs) { + using U = std::make_unsigned_t<T>; + + U lhs_u = BitCast<U>(lhs); + U rhs_u = BitCast<U>(rhs); + + return BitCast<T>(lhs_u + rhs_u); +} + +} // namespace Common diff --git a/src/common/settings.h b/src/common/settings.h index 512ecff69..1ae28ce93 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -128,7 +128,7 @@ public: /** * Sets a default value, label, and setting value. * - * @param default_val Intial value of the setting, and default value of the setting + * @param default_val Initial value of the setting, and default value of the setting * @param name Label for the setting */ explicit Setting(const Type& default_val, const std::string& name) @@ -139,7 +139,7 @@ public: /** * Sets a default value, minimum value, maximum value, and label. * - * @param default_val Intial value of the setting, and default value of the setting + * @param default_val Initial value of the setting, and default value of the setting * @param min_val Sets the minimum allowed value of the setting * @param max_val Sets the maximum allowed value of the setting * @param name Label for the setting @@ -231,7 +231,7 @@ public: /** * Sets a default value, label, and setting value. * - * @param default_val Intial value of the setting, and default value of the setting + * @param default_val Initial value of the setting, and default value of the setting * @param name Label for the setting */ explicit SwitchableSetting(const Type& default_val, const std::string& name) @@ -242,7 +242,7 @@ public: /** * Sets a default value, minimum value, maximum value, and label. * - * @param default_val Intial value of the setting, and default value of the setting + * @param default_val Initial value of the setting, and default value of the setting * @param min_val Sets the minimum allowed value of the setting * @param max_val Sets the maximum allowed value of the setting * @param name Label for the setting diff --git a/src/common/steady_clock.cpp b/src/common/steady_clock.cpp new file mode 100644 index 000000000..0d5908aa7 --- /dev/null +++ b/src/common/steady_clock.cpp @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#if defined(_WIN32) +#include <windows.h> +#else +#include <time.h> +#endif + +#include "common/steady_clock.h" + +namespace Common { + +#ifdef _WIN32 +static s64 WindowsQueryPerformanceFrequency() { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return frequency.QuadPart; +} + +static s64 WindowsQueryPerformanceCounter() { + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return counter.QuadPart; +} +#endif + +SteadyClock::time_point SteadyClock::Now() noexcept { +#if defined(_WIN32) + static const auto freq = WindowsQueryPerformanceFrequency(); + const auto counter = WindowsQueryPerformanceCounter(); + + // 10 MHz is a very common QPC frequency on modern PCs. + // Optimizing for this specific frequency can double the performance of + // this function by avoiding the expensive frequency conversion path. + static constexpr s64 TenMHz = 10'000'000; + + if (freq == TenMHz) [[likely]] { + static_assert(period::den % TenMHz == 0); + static constexpr s64 Multiplier = period::den / TenMHz; + return time_point{duration{counter * Multiplier}}; + } + + const auto whole = (counter / freq) * period::den; + const auto part = (counter % freq) * period::den / freq; + return time_point{duration{whole + part}}; +#elif defined(__APPLE__) + return time_point{duration{clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)}}; +#else + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}}; +#endif +} + +}; // namespace Common diff --git a/src/common/steady_clock.h b/src/common/steady_clock.h new file mode 100644 index 000000000..9497cf865 --- /dev/null +++ b/src/common/steady_clock.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <chrono> + +#include "common/common_types.h" + +namespace Common { + +struct SteadyClock { + using rep = s64; + using period = std::nano; + using duration = std::chrono::nanoseconds; + using time_point = std::chrono::time_point<SteadyClock>; + + static constexpr bool is_steady = true; + + [[nodiscard]] static time_point Now() noexcept; +}; + +} // namespace Common diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp index ae07f2811..817e71d52 100644 --- a/src/common/wall_clock.cpp +++ b/src/common/wall_clock.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/steady_clock.h" #include "common/uint128.h" #include "common/wall_clock.h" @@ -11,45 +12,32 @@ namespace Common { -using base_timer = std::chrono::steady_clock; -using base_time_point = std::chrono::time_point<base_timer>; - class StandardWallClock final : public WallClock { public: explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_) - : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, false) { - start_time = base_timer::now(); - } + : WallClock{emulated_cpu_frequency_, emulated_clock_frequency_, false}, + start_time{SteadyClock::Now()} {} std::chrono::nanoseconds GetTimeNS() override { - base_time_point current = base_timer::now(); - auto elapsed = current - start_time; - return std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed); + return SteadyClock::Now() - start_time; } std::chrono::microseconds GetTimeUS() override { - base_time_point current = base_timer::now(); - auto elapsed = current - start_time; - return std::chrono::duration_cast<std::chrono::microseconds>(elapsed); + return std::chrono::duration_cast<std::chrono::microseconds>(GetTimeNS()); } std::chrono::milliseconds GetTimeMS() override { - base_time_point current = base_timer::now(); - auto elapsed = current - start_time; - return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed); + return std::chrono::duration_cast<std::chrono::milliseconds>(GetTimeNS()); } u64 GetClockCycles() override { - std::chrono::nanoseconds time_now = GetTimeNS(); - const u128 temporary = - Common::Multiply64Into128(time_now.count(), emulated_clock_frequency); - return Common::Divide128On32(temporary, 1000000000).first; + const u128 temp = Common::Multiply64Into128(GetTimeNS().count(), emulated_clock_frequency); + return Common::Divide128On32(temp, NS_RATIO).first; } u64 GetCPUCycles() override { - std::chrono::nanoseconds time_now = GetTimeNS(); - const u128 temporary = Common::Multiply64Into128(time_now.count(), emulated_cpu_frequency); - return Common::Divide128On32(temporary, 1000000000).first; + const u128 temp = Common::Multiply64Into128(GetTimeNS().count(), emulated_cpu_frequency); + return Common::Divide128On32(temp, NS_RATIO).first; } void Pause([[maybe_unused]] bool is_paused) override { @@ -57,7 +45,7 @@ public: } private: - base_time_point start_time; + SteadyClock::time_point start_time; }; #ifdef ARCHITECTURE_x86_64 @@ -93,4 +81,9 @@ std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency, #endif +std::unique_ptr<WallClock> CreateStandardWallClock(u64 emulated_cpu_frequency, + u64 emulated_clock_frequency) { + return std::make_unique<StandardWallClock>(emulated_cpu_frequency, emulated_clock_frequency); +} + } // namespace Common diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h index 828a523a8..157ec5eae 100644 --- a/src/common/wall_clock.h +++ b/src/common/wall_clock.h @@ -55,4 +55,7 @@ private: [[nodiscard]] std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency); +[[nodiscard]] std::unique_ptr<WallClock> CreateStandardWallClock(u64 emulated_cpu_frequency, + u64 emulated_clock_frequency); + } // namespace Common diff --git a/src/common/windows/timer_resolution.cpp b/src/common/windows/timer_resolution.cpp new file mode 100644 index 000000000..29c6e5c7e --- /dev/null +++ b/src/common/windows/timer_resolution.cpp @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <windows.h> + +#include "common/windows/timer_resolution.h" + +extern "C" { +// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FTime%2FNtQueryTimerResolution.html +NTSYSAPI LONG NTAPI NtQueryTimerResolution(PULONG MinimumResolution, PULONG MaximumResolution, + PULONG CurrentResolution); + +// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FTime%2FNtSetTimerResolution.html +NTSYSAPI LONG NTAPI NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution, + PULONG CurrentResolution); + +// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FThread%2FNtDelayExecution.html +NTSYSAPI LONG NTAPI NtDelayExecution(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval); +} + +// Defines for compatibility with older Windows 10 SDKs. + +#ifndef PROCESS_POWER_THROTTLING_EXECUTION_SPEED +#define PROCESS_POWER_THROTTLING_EXECUTION_SPEED 0x1 +#endif +#ifndef PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION +#define PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION 0x4 +#endif + +namespace Common::Windows { + +namespace { + +using namespace std::chrono; + +constexpr nanoseconds ToNS(ULONG hundred_ns) { + return nanoseconds{hundred_ns * 100}; +} + +constexpr ULONG ToHundredNS(nanoseconds ns) { + return static_cast<ULONG>(ns.count()) / 100; +} + +struct TimerResolution { + std::chrono::nanoseconds minimum; + std::chrono::nanoseconds maximum; + std::chrono::nanoseconds current; +}; + +TimerResolution GetTimerResolution() { + ULONG MinimumTimerResolution; + ULONG MaximumTimerResolution; + ULONG CurrentTimerResolution; + NtQueryTimerResolution(&MinimumTimerResolution, &MaximumTimerResolution, + &CurrentTimerResolution); + return { + .minimum{ToNS(MinimumTimerResolution)}, + .maximum{ToNS(MaximumTimerResolution)}, + .current{ToNS(CurrentTimerResolution)}, + }; +} + +void SetHighQoS() { + // https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service + PROCESS_POWER_THROTTLING_STATE PowerThrottling{ + .Version{PROCESS_POWER_THROTTLING_CURRENT_VERSION}, + .ControlMask{PROCESS_POWER_THROTTLING_EXECUTION_SPEED | + PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION}, + .StateMask{}, + }; + SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling, + sizeof(PROCESS_POWER_THROTTLING_STATE)); +} + +} // Anonymous namespace + +nanoseconds GetMinimumTimerResolution() { + return GetTimerResolution().minimum; +} + +nanoseconds GetMaximumTimerResolution() { + return GetTimerResolution().maximum; +} + +nanoseconds GetCurrentTimerResolution() { + return GetTimerResolution().current; +} + +nanoseconds SetCurrentTimerResolution(nanoseconds timer_resolution) { + // Set the timer resolution, and return the current timer resolution. + const auto DesiredTimerResolution = ToHundredNS(timer_resolution); + ULONG CurrentTimerResolution; + NtSetTimerResolution(DesiredTimerResolution, TRUE, &CurrentTimerResolution); + return ToNS(CurrentTimerResolution); +} + +nanoseconds SetCurrentTimerResolutionToMaximum() { + SetHighQoS(); + return SetCurrentTimerResolution(GetMaximumTimerResolution()); +} + +void SleepForOneTick() { + LARGE_INTEGER DelayInterval{ + .QuadPart{-1}, + }; + NtDelayExecution(FALSE, &DelayInterval); +} + +} // namespace Common::Windows diff --git a/src/common/windows/timer_resolution.h b/src/common/windows/timer_resolution.h new file mode 100644 index 000000000..e1e50a62d --- /dev/null +++ b/src/common/windows/timer_resolution.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <chrono> + +namespace Common::Windows { + +/// Returns the minimum (least precise) supported timer resolution in nanoseconds. +std::chrono::nanoseconds GetMinimumTimerResolution(); + +/// Returns the maximum (most precise) supported timer resolution in nanoseconds. +std::chrono::nanoseconds GetMaximumTimerResolution(); + +/// Returns the current timer resolution in nanoseconds. +std::chrono::nanoseconds GetCurrentTimerResolution(); + +/** + * Sets the current timer resolution. + * + * @param timer_resolution Timer resolution in nanoseconds. + * + * @returns The current timer resolution. + */ +std::chrono::nanoseconds SetCurrentTimerResolution(std::chrono::nanoseconds timer_resolution); + +/** + * Sets the current timer resolution to the maximum supported timer resolution. + * + * @returns The current timer resolution. + */ +std::chrono::nanoseconds SetCurrentTimerResolutionToMaximum(); + +/// Sleep for one tick of the current timer resolution. +void SleepForOneTick(); + +} // namespace Common::Windows diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 8b08332ab..bc1a973b0 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -6,6 +6,7 @@ #include <thread> #include "common/atomic_ops.h" +#include "common/steady_clock.h" #include "common/uint128.h" #include "common/x64/native_clock.h" @@ -39,6 +40,12 @@ static u64 FencedRDTSC() { } #endif +template <u64 Nearest> +static u64 RoundToNearest(u64 value) { + const auto mod = value % Nearest; + return mod >= (Nearest / 2) ? (value - mod + Nearest) : (value - mod); +} + u64 EstimateRDTSCFrequency() { // Discard the first result measuring the rdtsc. FencedRDTSC(); @@ -46,18 +53,18 @@ u64 EstimateRDTSCFrequency() { FencedRDTSC(); // Get the current time. - const auto start_time = std::chrono::steady_clock::now(); + const auto start_time = Common::SteadyClock::Now(); const u64 tsc_start = FencedRDTSC(); - // Wait for 200 milliseconds. - std::this_thread::sleep_for(std::chrono::milliseconds{200}); - const auto end_time = std::chrono::steady_clock::now(); + // Wait for 250 milliseconds. + std::this_thread::sleep_for(std::chrono::milliseconds{250}); + const auto end_time = Common::SteadyClock::Now(); const u64 tsc_end = FencedRDTSC(); // Calculate differences. const u64 timer_diff = static_cast<u64>( std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count()); const u64 tsc_diff = tsc_end - tsc_start; const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff); - return tsc_freq; + return RoundToNearest<1000>(tsc_freq); } namespace X64 { diff --git a/src/core/constants.cpp b/src/core/constants.cpp index 4430173ef..760dc5f23 100644 --- a/src/core/constants.cpp +++ b/src/core/constants.cpp @@ -4,13 +4,24 @@ #include "core/constants.h" namespace Core::Constants { -const std::array<u8, 107> ACCOUNT_BACKUP_JPEG{{ - 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05, - 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, - 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, - 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, - 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, - 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, +const std::array<u8, 287> ACCOUNT_BACKUP_JPEG{{ + 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, + 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, + 0x05, 0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b, 0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, + 0x0a, 0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0e, 0x0f, + 0x10, 0x0f, 0x0e, 0x0c, 0x13, 0x13, 0x14, 0x14, 0x13, 0x13, 0x1c, 0x1b, 0x1b, 0x1b, 0x1c, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x07, 0x07, + 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10, 0x10, 0x18, 0x1a, 0x15, 0x11, 0x15, 0x1a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xff, 0xc0, + 0x00, 0x11, 0x08, 0x00, 0x20, 0x00, 0x20, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, + 0x01, 0xff, 0xc4, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, + 0x14, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, + 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd9, }}; } diff --git a/src/core/constants.h b/src/core/constants.h index f916ce0b6..f1f67d3b8 100644 --- a/src/core/constants.h +++ b/src/core/constants.h @@ -12,6 +12,6 @@ namespace Core::Constants { // ACC Service - Blank JPEG used as user icon in absentia of real one. -extern const std::array<u8, 107> ACCOUNT_BACKUP_JPEG; +extern const std::array<u8, 287> ACCOUNT_BACKUP_JPEG; } // namespace Core::Constants diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 3a63b52e3..742cfb996 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -6,6 +6,10 @@ #include <string> #include <tuple> +#ifdef _WIN32 +#include "common/windows/timer_resolution.h" +#endif + #include "common/microprofile.h" #include "core/core_timing.h" #include "core/core_timing_util.h" @@ -38,7 +42,8 @@ struct CoreTiming::Event { }; CoreTiming::CoreTiming() - : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} + : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)}, + event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} CoreTiming::~CoreTiming() { Reset(); @@ -185,15 +190,15 @@ void CoreTiming::ResetTicks() { } u64 CoreTiming::GetCPUTicks() const { - if (is_multicore) { - return clock->GetCPUCycles(); + if (is_multicore) [[likely]] { + return cpu_clock->GetCPUCycles(); } return ticks; } u64 CoreTiming::GetClockTicks() const { - if (is_multicore) { - return clock->GetClockCycles(); + if (is_multicore) [[likely]] { + return cpu_clock->GetClockCycles(); } return CpuCyclesToClockCycles(ticks); } @@ -252,21 +257,20 @@ void CoreTiming::ThreadLoop() { const auto next_time = Advance(); if (next_time) { // There are more events left in the queue, wait until the next event. - const auto wait_time = *next_time - GetGlobalTimeNs().count(); + auto wait_time = *next_time - GetGlobalTimeNs().count(); if (wait_time > 0) { #ifdef _WIN32 - // Assume a timer resolution of 1ms. - static constexpr s64 TimerResolutionNS = 1000000; + const auto timer_resolution_ns = + Common::Windows::GetCurrentTimerResolution().count(); - // Sleep in discrete intervals of the timer resolution, and spin the rest. - const auto sleep_time = wait_time - (wait_time % TimerResolutionNS); - if (sleep_time > 0) { - event.WaitFor(std::chrono::nanoseconds(sleep_time)); - } + while (!paused && !event.IsSet() && wait_time > 0) { + wait_time = *next_time - GetGlobalTimeNs().count(); - while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) { - // Yield to reduce thread starvation. - std::this_thread::yield(); + if (wait_time >= timer_resolution_ns) { + Common::Windows::SleepForOneTick(); + } else { + std::this_thread::yield(); + } } if (event.IsSet()) { @@ -285,9 +289,9 @@ void CoreTiming::ThreadLoop() { } paused_set = true; - clock->Pause(true); + event_clock->Pause(true); pause_event.Wait(); - clock->Pause(false); + event_clock->Pause(false); } } @@ -303,16 +307,23 @@ void CoreTiming::Reset() { has_started = false; } +std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const { + if (is_multicore) [[likely]] { + return cpu_clock->GetTimeNS(); + } + return CyclesToNs(ticks); +} + std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const { - if (is_multicore) { - return clock->GetTimeNS(); + if (is_multicore) [[likely]] { + return event_clock->GetTimeNS(); } return CyclesToNs(ticks); } std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { - if (is_multicore) { - return clock->GetTimeUS(); + if (is_multicore) [[likely]] { + return event_clock->GetTimeUS(); } return CyclesToUs(ticks); } diff --git a/src/core/core_timing.h b/src/core/core_timing.h index da366637b..4b89c0c39 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -122,6 +122,9 @@ public: /// Returns current time in emulated in Clock cycles u64 GetClockTicks() const; + /// Returns current time in nanoseconds. + std::chrono::nanoseconds GetCPUTimeNs() const; + /// Returns current time in microseconds. std::chrono::microseconds GetGlobalTimeUs() const; @@ -139,7 +142,8 @@ private: void Reset(); - std::unique_ptr<Common::WallClock> clock; + std::unique_ptr<Common::WallClock> cpu_clock; + std::unique_ptr<Common::WallClock> event_clock; s64 global_timer = 0; diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h index 45567b840..191c28bb4 100644 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h @@ -13,11 +13,9 @@ namespace Core { namespace Hardware { -// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz -// The exact value used is of course unverified. -constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked -constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed -constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores +constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz +constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz +constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores // Virtual to Physical core map. constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{ diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 97972ebae..c36eb5dc4 100644 --- a/src/core/hle/kernel/k_address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp @@ -44,11 +44,11 @@ const KAddressSpaceInfo& GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Ty } // namespace -uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) { +std::size_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) { return GetAddressSpaceInfo(width, type).address; } -size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) { +std::size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) { return GetAddressSpaceInfo(width, type).size; } diff --git a/src/core/hle/kernel/k_address_space_info.h b/src/core/hle/kernel/k_address_space_info.h index 69e9d77f2..9a26f6b90 100644 --- a/src/core/hle/kernel/k_address_space_info.h +++ b/src/core/hle/kernel/k_address_space_info.h @@ -18,7 +18,7 @@ struct KAddressSpaceInfo final { Count, }; - static u64 GetAddressSpaceStart(std::size_t width, Type type); + static std::size_t GetAddressSpaceStart(std::size_t width, Type type); static std::size_t GetAddressSpaceSize(std::size_t width, Type type); const std::size_t bit_width{}; diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h index 4709df995..b4a014c38 100644 --- a/src/core/hle/kernel/k_device_address_space.h +++ b/src/core/hle/kernel/k_device_address_space.h @@ -21,9 +21,9 @@ public: ~KDeviceAddressSpace(); Result Initialize(u64 address, u64 size); - void Finalize(); + void Finalize() override; - bool IsInitialized() const { + bool IsInitialized() const override { return m_is_initialized; } static void PostDestroy(uintptr_t arg) {} diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index b9d22b414..626517619 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/assert.h" +#include "common/overflow.h" #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/k_resource_limit.h" @@ -104,7 +105,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { ASSERT(current_hints[index] <= current_values[index]); // If we would overflow, don't allow to succeed. - if (current_values[index] + value <= current_values[index]) { + if (Common::WrappingAdd(current_values[index], value) <= current_values[index]) { break; } diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h index 59b3e32ae..a15640fd2 100644 --- a/src/core/hle/kernel/k_scoped_lock.h +++ b/src/core/hle/kernel/k_scoped_lock.h @@ -4,6 +4,7 @@ #pragma once #include <concepts> +#include <memory> #include <type_traits> namespace Kernel { diff --git a/src/core/hle/service/psc/psc.cpp b/src/core/hle/service/psc/psc.cpp index 25702703e..cd0cc9287 100644 --- a/src/core/hle/service/psc/psc.cpp +++ b/src/core/hle/service/psc/psc.cpp @@ -11,9 +11,9 @@ namespace Service::PSC { -class PSC_C final : public ServiceFramework<PSC_C> { +class IPmControl final : public ServiceFramework<IPmControl> { public: - explicit PSC_C(Core::System& system_) : ServiceFramework{system_, "psc:c"} { + explicit IPmControl(Core::System& system_) : ServiceFramework{system_, "psc:c"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -23,8 +23,8 @@ public: {4, nullptr, "Cancel"}, {5, nullptr, "PrintModuleInformation"}, {6, nullptr, "GetModuleInformation"}, - {10, nullptr, "Unknown10"}, - {11, nullptr, "Unknown11"}, + {10, nullptr, "AcquireStateLock"}, + {11, nullptr, "HasStateLock"}, }; // clang-format on @@ -49,12 +49,12 @@ public: } }; -class PSC_M final : public ServiceFramework<PSC_M> { +class IPmService final : public ServiceFramework<IPmService> { public: - explicit PSC_M(Core::System& system_) : ServiceFramework{system_, "psc:m"} { + explicit IPmService(Core::System& system_) : ServiceFramework{system_, "psc:m"} { // clang-format off static const FunctionInfo functions[] = { - {0, &PSC_M::GetPmModule, "GetPmModule"}, + {0, &IPmService::GetPmModule, "GetPmModule"}, }; // clang-format on @@ -74,8 +74,8 @@ private: void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("psc:c", std::make_shared<PSC_C>(system)); - server_manager->RegisterNamedService("psc:m", std::make_shared<PSC_M>(system)); + server_manager->RegisterNamedService("psc:c", std::make_shared<IPmControl>(system)); + server_manager->RegisterNamedService("psc:m", std::make_shared<IPmService>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index b19bc1b3e..2b99dd7ac 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -8,14 +8,36 @@ namespace Service::SSL { +// This is nn::ssl::sf::CertificateFormat enum class CertificateFormat : u32 { Pem = 1, Der = 2, }; +// This is nn::ssl::sf::ContextOption +enum class ContextOption : u32 { + None = 0, + CrlImportDateCheckEnable = 1, +}; + +// This is nn::ssl::sf::SslVersion +struct SslVersion { + union { + u32 raw{}; + + BitField<0, 1, u32> tls_auto; + BitField<3, 1, u32> tls_v10; + BitField<4, 1, u32> tls_v11; + BitField<5, 1, u32> tls_v12; + BitField<6, 1, u32> tls_v13; + BitField<24, 7, u32> api_version; + }; +}; + class ISslConnection final : public ServiceFramework<ISslConnection> { public: - explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { + explicit ISslConnection(Core::System& system_, SslVersion version) + : ServiceFramework{system_, "ISslConnection"}, ssl_version{version} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetSocketDescriptor"}, @@ -59,11 +81,15 @@ public: RegisterHandlers(functions); } + +private: + SslVersion ssl_version; }; class ISslContext final : public ServiceFramework<ISslContext> { public: - explicit ISslContext(Core::System& system_) : ServiceFramework{system_, "ISslContext"} { + explicit ISslContext(Core::System& system_, SslVersion version) + : ServiceFramework{system_, "ISslContext"}, ssl_version{version} { static const FunctionInfo functions[] = { {0, &ISslContext::SetOption, "SetOption"}, {1, nullptr, "GetOption"}, @@ -84,17 +110,20 @@ public: } private: + SslVersion ssl_version; + void SetOption(HLERequestContext& ctx) { struct Parameters { - u8 enable; - u32 option; + ContextOption option; + s32 value; }; + static_assert(sizeof(Parameters) == 0x8, "Parameters is an invalid size"); IPC::RequestParser rp{ctx}; const auto parameters = rp.PopRaw<Parameters>(); - LOG_WARNING(Service_SSL, "(STUBBED) called. enable={}, option={}", parameters.enable, - parameters.option); + LOG_WARNING(Service_SSL, "(STUBBED) called. option={}, value={}", parameters.option, + parameters.value); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -105,7 +134,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISslConnection>(system); + rb.PushIpcInterface<ISslConnection>(system, ssl_version); } void ImportServerPki(HLERequestContext& ctx) { @@ -142,20 +171,21 @@ private: } }; -class SSL final : public ServiceFramework<SSL> { +class ISslService final : public ServiceFramework<ISslService> { public: - explicit SSL(Core::System& system_) : ServiceFramework{system_, "ssl"} { + explicit ISslService(Core::System& system_) : ServiceFramework{system_, "ssl"} { // clang-format off static const FunctionInfo functions[] = { - {0, &SSL::CreateContext, "CreateContext"}, + {0, &ISslService::CreateContext, "CreateContext"}, {1, nullptr, "GetContextCount"}, {2, nullptr, "GetCertificates"}, {3, nullptr, "GetCertificateBufSize"}, {4, nullptr, "DebugIoctl"}, - {5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"}, + {5, &ISslService::SetInterfaceVersion, "SetInterfaceVersion"}, {6, nullptr, "FlushSessionCache"}, {7, nullptr, "SetDebugOption"}, {8, nullptr, "GetDebugOption"}, + {8, nullptr, "ClearTls12FallbackFlag"}, }; // clang-format on @@ -163,20 +193,30 @@ public: } private: - u32 ssl_version{}; void CreateContext(HLERequestContext& ctx) { - LOG_WARNING(Service_SSL, "(STUBBED) called"); + struct Parameters { + SslVersion ssl_version; + INSERT_PADDING_BYTES(0x4); + u64 pid_placeholder; + }; + static_assert(sizeof(Parameters) == 0x10, "Parameters is an invalid size"); + + IPC::RequestParser rp{ctx}; + const auto parameters = rp.PopRaw<Parameters>(); + + LOG_WARNING(Service_SSL, "(STUBBED) called, api_version={}, pid_placeholder={}", + parameters.ssl_version.api_version, parameters.pid_placeholder); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<ISslContext>(system); + rb.PushIpcInterface<ISslContext>(system, parameters.ssl_version); } void SetInterfaceVersion(HLERequestContext& ctx) { - LOG_DEBUG(Service_SSL, "called"); - IPC::RequestParser rp{ctx}; - ssl_version = rp.Pop<u32>(); + u32 ssl_version = rp.Pop<u32>(); + + LOG_DEBUG(Service_SSL, "called, ssl_version={}", ssl_version); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -186,7 +226,7 @@ private: void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("ssl", std::make_shared<SSL>(system)); + server_manager->RegisterNamedService("ssl", std::make_shared<ISslService>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp index a2855e783..f29fff1dd 100644 --- a/src/core/hle/service/usb/usb.cpp +++ b/src/core/hle/service/usb/usb.cpp @@ -16,19 +16,19 @@ public: explicit IDsInterface(Core::System& system_) : ServiceFramework{system_, "IDsInterface"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "BindDevice"}, - {1, nullptr, "BindClientProcess"}, - {2, nullptr, "AddInterface"}, - {3, nullptr, "GetStateChangeEvent"}, - {4, nullptr, "GetState"}, - {5, nullptr, "ClearDeviceData"}, - {6, nullptr, "AddUsbStringDescriptor"}, - {7, nullptr, "DeleteUsbStringDescriptor"}, - {8, nullptr, "SetUsbDeviceDescriptor"}, - {9, nullptr, "SetBinaryObjectStore"}, - {10, nullptr, "Enable"}, - {11, nullptr, "Disable"}, - {12, nullptr, "Unknown12"}, + {0, nullptr, "AddEndpoint"}, + {1, nullptr, "GetSetupEvent"}, + {2, nullptr, "GetSetupPacket"}, + {3, nullptr, "Enable"}, + {4, nullptr, "Disable"}, + {5, nullptr, "CtrlIn"}, + {6, nullptr, "CtrlOut"}, + {7, nullptr, "GetCtrlInCompletionEvent"}, + {8, nullptr, "GetCtrlInUrbReport"}, + {9, nullptr, "GetCtrlOutCompletionEvent"}, + {10, nullptr, "GetCtrlOutUrbReport"}, + {11, nullptr, "CtrlStall"}, + {12, nullptr, "AppendConfigurationData"}, }; // clang-format on @@ -36,9 +36,9 @@ public: } }; -class USB_DS final : public ServiceFramework<USB_DS> { +class IDsRootSession final : public ServiceFramework<IDsRootSession> { public: - explicit USB_DS(Core::System& system_) : ServiceFramework{system_, "usb:ds"} { + explicit IDsRootSession(Core::System& system_) : ServiceFramework{system_, "usb:ds"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenDsService"}, @@ -94,9 +94,9 @@ public: } }; -class USB_HS final : public ServiceFramework<USB_HS> { +class IClientRootSession final : public ServiceFramework<IClientRootSession> { public: - explicit USB_HS(Core::System& system_) : ServiceFramework{system_, "usb:hs"} { + explicit IClientRootSession(Core::System& system_) : ServiceFramework{system_, "usb:hs"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "BindClientProcess"}, @@ -107,7 +107,7 @@ public: {5, nullptr, "DestroyInterfaceAvailableEvent"}, {6, nullptr, "GetInterfaceStateChangeEvent"}, {7, nullptr, "AcquireUsbIf"}, - {8, nullptr, "ResetDevice"}, + {8, nullptr, "SetTestMode"}, }; // clang-format on @@ -134,12 +134,12 @@ public: } }; -class USB_PD final : public ServiceFramework<USB_PD> { +class IPdManager final : public ServiceFramework<IPdManager> { public: - explicit USB_PD(Core::System& system_) : ServiceFramework{system_, "usb:pd"} { + explicit IPdManager(Core::System& system_) : ServiceFramework{system_, "usb:pd"} { // clang-format off static const FunctionInfo functions[] = { - {0, &USB_PD::GetPdSession, "GetPdSession"}, + {0, &IPdManager::OpenSession, "OpenSession"}, }; // clang-format on @@ -147,7 +147,7 @@ public: } private: - void GetPdSession(HLERequestContext& ctx) { + void OpenSession(HLERequestContext& ctx) { LOG_DEBUG(Service_USB, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -178,12 +178,12 @@ public: } }; -class USB_PD_C final : public ServiceFramework<USB_PD_C> { +class IPdCradleManager final : public ServiceFramework<IPdCradleManager> { public: - explicit USB_PD_C(Core::System& system_) : ServiceFramework{system_, "usb:pd:c"} { + explicit IPdCradleManager(Core::System& system_) : ServiceFramework{system_, "usb:pd:c"} { // clang-format off static const FunctionInfo functions[] = { - {0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"}, + {0, &IPdCradleManager::OpenCradleSession, "OpenCradleSession"}, }; // clang-format on @@ -191,18 +191,18 @@ public: } private: - void GetPdCradleSession(HLERequestContext& ctx) { + void OpenCradleSession(HLERequestContext& ctx) { + LOG_DEBUG(Service_USB, "called"); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); rb.PushIpcInterface<IPdCradleSession>(system); - - LOG_DEBUG(Service_USB, "called"); } }; -class USB_PM final : public ServiceFramework<USB_PM> { +class IPmMainService final : public ServiceFramework<IPmMainService> { public: - explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { + explicit IPmMainService(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetPowerEvent"}, @@ -221,11 +221,11 @@ public: void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("usb:ds", std::make_shared<USB_DS>(system)); - server_manager->RegisterNamedService("usb:hs", std::make_shared<USB_HS>(system)); - server_manager->RegisterNamedService("usb:pd", std::make_shared<USB_PD>(system)); - server_manager->RegisterNamedService("usb:pd:c", std::make_shared<USB_PD_C>(system)); - server_manager->RegisterNamedService("usb:pm", std::make_shared<USB_PM>(system)); + server_manager->RegisterNamedService("usb:ds", std::make_shared<IDsRootSession>(system)); + server_manager->RegisterNamedService("usb:hs", std::make_shared<IClientRootSession>(system)); + server_manager->RegisterNamedService("usb:pd", std::make_shared<IPdManager>(system)); + server_manager->RegisterNamedService("usb:pd:c", std::make_shared<IPdCradleManager>(system)); + server_manager->RegisterNamedService("usb:pm", std::make_shared<IPmMainService>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp index b4cd39a20..8b57ebe07 100644 --- a/src/input_common/drivers/joycon.cpp +++ b/src/input_common/drivers/joycon.cpp @@ -307,8 +307,8 @@ Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identif switch (polling_mode) { case Common::Input::PollingMode::Active: return static_cast<Common::Input::DriverResult>(handle->SetActiveMode()); - case Common::Input::PollingMode::Pasive: - return static_cast<Common::Input::DriverResult>(handle->SetPasiveMode()); + case Common::Input::PollingMode::Passive: + return static_cast<Common::Input::DriverResult>(handle->SetPassiveMode()); case Common::Input::PollingMode::IR: return static_cast<Common::Input::DriverResult>(handle->SetIrMode()); case Common::Input::PollingMode::NFC: diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h index 13cacfc0a..488d00b31 100644 --- a/src/input_common/drivers/virtual_amiibo.h +++ b/src/input_common/drivers/virtual_amiibo.h @@ -60,6 +60,6 @@ private: std::string file_path{}; State state{State::Initialized}; std::vector<u8> nfc_data; - Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; + Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Passive}; }; } // namespace InputCommon diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index e65b6b845..78cc5893c 100644 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -410,7 +410,7 @@ DriverResult JoyconDriver::SetIrsConfig(IrsMode mode_, IrsResolution format_) { return result; } -DriverResult JoyconDriver::SetPasiveMode() { +DriverResult JoyconDriver::SetPassiveMode() { std::scoped_lock lock{mutex}; motion_enabled = false; hidbus_enabled = false; diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index c1e189fa5..b52a13ecf 100644 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -44,7 +44,7 @@ public: DriverResult SetVibration(const VibrationValue& vibration); DriverResult SetLedConfig(u8 led_pattern); DriverResult SetIrsConfig(IrsMode mode_, IrsResolution format_); - DriverResult SetPasiveMode(); + DriverResult SetPassiveMode(); DriverResult SetActiveMode(); DriverResult SetIrMode(); DriverResult SetNfcMode(); diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h index b91934990..dcac0e422 100644 --- a/src/input_common/helpers/joycon_protocol/joycon_types.h +++ b/src/input_common/helpers/joycon_protocol/joycon_types.h @@ -78,7 +78,7 @@ enum class PadButton : u32 { Capture = 0x200000, }; -enum class PasivePadButton : u32 { +enum class PassivePadButton : u32 { Down_A = 0x0001, Right_X = 0x0002, Left_B = 0x0004, @@ -95,6 +95,18 @@ enum class PasivePadButton : u32 { ZL_ZR = 0x8000, }; +enum class PassivePadStick : u8 { + Right = 0x00, + RightDown = 0x01, + Down = 0x02, + DownLeft = 0x03, + Left = 0x04, + LeftUp = 0x05, + Up = 0x06, + UpRight = 0x07, + Neutral = 0x08, +}; + enum class OutputReport : u8 { RUMBLE_AND_SUBCMD = 0x01, FW_UPDATE_PKT = 0x03, diff --git a/src/input_common/helpers/joycon_protocol/poller.cpp b/src/input_common/helpers/joycon_protocol/poller.cpp index 9bb15e935..dca797f7a 100644 --- a/src/input_common/helpers/joycon_protocol/poller.cpp +++ b/src/input_common/helpers/joycon_protocol/poller.cpp @@ -12,7 +12,7 @@ JoyconPoller::JoyconPoller(ControllerType device_type_, JoyStickCalibration left : device_type{device_type_}, left_stick_calibration{left_stick_calibration_}, right_stick_calibration{right_stick_calibration_}, motion_calibration{motion_calibration_} {} -void JoyconPoller::SetCallbacks(const Joycon::JoyconCallbacks& callbacks_) { +void JoyconPoller::SetCallbacks(const JoyconCallbacks& callbacks_) { callbacks = std::move(callbacks_); } @@ -22,13 +22,13 @@ void JoyconPoller::ReadActiveMode(std::span<u8> buffer, const MotionStatus& moti memcpy(&data, buffer.data(), sizeof(InputReportActive)); switch (device_type) { - case Joycon::ControllerType::Left: + case ControllerType::Left: UpdateActiveLeftPadInput(data, motion_status); break; - case Joycon::ControllerType::Right: + case ControllerType::Right: UpdateActiveRightPadInput(data, motion_status); break; - case Joycon::ControllerType::Pro: + case ControllerType::Pro: UpdateActiveProPadInput(data, motion_status); break; default: @@ -47,14 +47,14 @@ void JoyconPoller::ReadPassiveMode(std::span<u8> buffer) { memcpy(&data, buffer.data(), sizeof(InputReportPassive)); switch (device_type) { - case Joycon::ControllerType::Left: - UpdatePasiveLeftPadInput(data); + case ControllerType::Left: + UpdatePassiveLeftPadInput(data); break; - case Joycon::ControllerType::Right: - UpdatePasiveRightPadInput(data); + case ControllerType::Right: + UpdatePassiveRightPadInput(data); break; - case Joycon::ControllerType::Pro: - UpdatePasiveProPadInput(data); + case ControllerType::Pro: + UpdatePassiveProPadInput(data); break; default: break; @@ -210,14 +210,12 @@ void JoyconPoller::UpdateActiveProPadInput(const InputReportActive& input, } } -void JoyconPoller::UpdatePasiveLeftPadInput(const InputReportPassive& input) { - static constexpr std::array<Joycon::PasivePadButton, 11> left_buttons{ - Joycon::PasivePadButton::Down_A, Joycon::PasivePadButton::Right_X, - Joycon::PasivePadButton::Left_B, Joycon::PasivePadButton::Up_Y, - Joycon::PasivePadButton::SL, Joycon::PasivePadButton::SR, - Joycon::PasivePadButton::L_R, Joycon::PasivePadButton::ZL_ZR, - Joycon::PasivePadButton::Minus, Joycon::PasivePadButton::Capture, - Joycon::PasivePadButton::StickL, +void JoyconPoller::UpdatePassiveLeftPadInput(const InputReportPassive& input) { + static constexpr std::array<PassivePadButton, 11> left_buttons{ + PassivePadButton::Down_A, PassivePadButton::Right_X, PassivePadButton::Left_B, + PassivePadButton::Up_Y, PassivePadButton::SL, PassivePadButton::SR, + PassivePadButton::L_R, PassivePadButton::ZL_ZR, PassivePadButton::Minus, + PassivePadButton::Capture, PassivePadButton::StickL, }; for (auto left_button : left_buttons) { @@ -225,16 +223,19 @@ void JoyconPoller::UpdatePasiveLeftPadInput(const InputReportPassive& input) { const int button = static_cast<int>(left_button); callbacks.on_button_data(button, button_status); } + + const auto [left_axis_x, left_axis_y] = + GetPassiveAxisValue(static_cast<PassivePadStick>(input.stick_state)); + callbacks.on_stick_data(static_cast<int>(PadAxes::LeftStickX), left_axis_x); + callbacks.on_stick_data(static_cast<int>(PadAxes::LeftStickY), left_axis_y); } -void JoyconPoller::UpdatePasiveRightPadInput(const InputReportPassive& input) { - static constexpr std::array<Joycon::PasivePadButton, 11> right_buttons{ - Joycon::PasivePadButton::Down_A, Joycon::PasivePadButton::Right_X, - Joycon::PasivePadButton::Left_B, Joycon::PasivePadButton::Up_Y, - Joycon::PasivePadButton::SL, Joycon::PasivePadButton::SR, - Joycon::PasivePadButton::L_R, Joycon::PasivePadButton::ZL_ZR, - Joycon::PasivePadButton::Plus, Joycon::PasivePadButton::Home, - Joycon::PasivePadButton::StickR, +void JoyconPoller::UpdatePassiveRightPadInput(const InputReportPassive& input) { + static constexpr std::array<PassivePadButton, 11> right_buttons{ + PassivePadButton::Down_A, PassivePadButton::Right_X, PassivePadButton::Left_B, + PassivePadButton::Up_Y, PassivePadButton::SL, PassivePadButton::SR, + PassivePadButton::L_R, PassivePadButton::ZL_ZR, PassivePadButton::Plus, + PassivePadButton::Home, PassivePadButton::StickR, }; for (auto right_button : right_buttons) { @@ -242,17 +243,20 @@ void JoyconPoller::UpdatePasiveRightPadInput(const InputReportPassive& input) { const int button = static_cast<int>(right_button); callbacks.on_button_data(button, button_status); } + + const auto [right_axis_x, right_axis_y] = + GetPassiveAxisValue(static_cast<PassivePadStick>(input.stick_state)); + callbacks.on_stick_data(static_cast<int>(PadAxes::RightStickX), right_axis_x); + callbacks.on_stick_data(static_cast<int>(PadAxes::RightStickY), right_axis_y); } -void JoyconPoller::UpdatePasiveProPadInput(const InputReportPassive& input) { - static constexpr std::array<Joycon::PasivePadButton, 14> pro_buttons{ - Joycon::PasivePadButton::Down_A, Joycon::PasivePadButton::Right_X, - Joycon::PasivePadButton::Left_B, Joycon::PasivePadButton::Up_Y, - Joycon::PasivePadButton::SL, Joycon::PasivePadButton::SR, - Joycon::PasivePadButton::L_R, Joycon::PasivePadButton::ZL_ZR, - Joycon::PasivePadButton::Minus, Joycon::PasivePadButton::Plus, - Joycon::PasivePadButton::Capture, Joycon::PasivePadButton::Home, - Joycon::PasivePadButton::StickL, Joycon::PasivePadButton::StickR, +void JoyconPoller::UpdatePassiveProPadInput(const InputReportPassive& input) { + static constexpr std::array<PassivePadButton, 14> pro_buttons{ + PassivePadButton::Down_A, PassivePadButton::Right_X, PassivePadButton::Left_B, + PassivePadButton::Up_Y, PassivePadButton::SL, PassivePadButton::SR, + PassivePadButton::L_R, PassivePadButton::ZL_ZR, PassivePadButton::Minus, + PassivePadButton::Plus, PassivePadButton::Capture, PassivePadButton::Home, + PassivePadButton::StickL, PassivePadButton::StickR, }; for (auto pro_button : pro_buttons) { @@ -260,6 +264,15 @@ void JoyconPoller::UpdatePasiveProPadInput(const InputReportPassive& input) { const int button = static_cast<int>(pro_button); callbacks.on_button_data(button, button_status); } + + const auto [left_axis_x, left_axis_y] = + GetPassiveAxisValue(static_cast<PassivePadStick>(input.stick_state & 0xf)); + const auto [right_axis_x, right_axis_y] = + GetPassiveAxisValue(static_cast<PassivePadStick>(input.stick_state >> 4)); + callbacks.on_stick_data(static_cast<int>(PadAxes::LeftStickX), left_axis_x); + callbacks.on_stick_data(static_cast<int>(PadAxes::LeftStickY), left_axis_y); + callbacks.on_stick_data(static_cast<int>(PadAxes::RightStickX), right_axis_x); + callbacks.on_stick_data(static_cast<int>(PadAxes::RightStickY), right_axis_y); } f32 JoyconPoller::GetAxisValue(u16 raw_value, Joycon::JoyStickAxisCalibration calibration) const { @@ -270,6 +283,30 @@ f32 JoyconPoller::GetAxisValue(u16 raw_value, Joycon::JoyStickAxisCalibration ca return value / calibration.min; } +std::pair<f32, f32> JoyconPoller::GetPassiveAxisValue(PassivePadStick raw_value) const { + switch (raw_value) { + case PassivePadStick::Right: + return {1.0f, 0.0f}; + case PassivePadStick::RightDown: + return {1.0f, -1.0f}; + case PassivePadStick::Down: + return {0.0f, -1.0f}; + case PassivePadStick::DownLeft: + return {-1.0f, -1.0f}; + case PassivePadStick::Left: + return {-1.0f, 0.0f}; + case PassivePadStick::LeftUp: + return {-1.0f, 1.0f}; + case PassivePadStick::Up: + return {0.0f, 1.0f}; + case PassivePadStick::UpRight: + return {1.0f, 1.0f}; + case PassivePadStick::Neutral: + default: + return {0.0f, 0.0f}; + } +} + f32 JoyconPoller::GetAccelerometerValue(s16 raw, const MotionSensorCalibration& cal, AccelerometerSensitivity sensitivity) const { const f32 value = raw * (1.0f / (cal.scale - cal.offset)) * 4; diff --git a/src/input_common/helpers/joycon_protocol/poller.h b/src/input_common/helpers/joycon_protocol/poller.h index 354d41dad..0fa72c6db 100644 --- a/src/input_common/helpers/joycon_protocol/poller.h +++ b/src/input_common/helpers/joycon_protocol/poller.h @@ -22,7 +22,7 @@ public: JoyStickCalibration right_stick_calibration_, MotionCalibration motion_calibration_); - void SetCallbacks(const Joycon::JoyconCallbacks& callbacks_); + void SetCallbacks(const JoyconCallbacks& callbacks_); /// Handles data from passive packages void ReadPassiveMode(std::span<u8> buffer); @@ -46,12 +46,15 @@ private: const MotionStatus& motion_status); void UpdateActiveProPadInput(const InputReportActive& input, const MotionStatus& motion_status); - void UpdatePasiveLeftPadInput(const InputReportPassive& buffer); - void UpdatePasiveRightPadInput(const InputReportPassive& buffer); - void UpdatePasiveProPadInput(const InputReportPassive& buffer); + void UpdatePassiveLeftPadInput(const InputReportPassive& buffer); + void UpdatePassiveRightPadInput(const InputReportPassive& buffer); + void UpdatePassiveProPadInput(const InputReportPassive& buffer); /// Returns a calibrated joystick axis from raw axis data - f32 GetAxisValue(u16 raw_value, Joycon::JoyStickAxisCalibration calibration) const; + f32 GetAxisValue(u16 raw_value, JoyStickAxisCalibration calibration) const; + + /// Returns a digital joystick axis from passive axis data + std::pair<f32, f32> GetPassiveAxisValue(PassivePadStick raw_value) const; /// Returns a calibrated accelerometer axis from raw motion data f32 GetAccelerometerValue(s16 raw, const MotionSensorCalibration& cal, @@ -75,7 +78,7 @@ private: JoyStickCalibration right_stick_calibration{}; MotionCalibration motion_calibration{}; - Joycon::JoyconCallbacks callbacks{}; + JoyconCallbacks callbacks{}; }; } // namespace InputCommon::Joycon diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 7024a19cf..2e7f9c5ed 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -197,7 +197,7 @@ struct GPU::Impl { constexpr u64 gpu_ticks_num = 384; constexpr u64 gpu_ticks_den = 625; - u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count(); + u64 nanoseconds = system.CoreTiming().GetCPUTimeNs().count(); if (Settings::values.use_fast_gpu_time.GetValue()) { nanoseconds /= 256; } diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index b047e7b3d..d3eabd686 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -112,13 +112,17 @@ GLenum ImageTarget(Shader::TextureType type, int num_samples = 1) { return GL_NONE; } -GLenum TextureMode(PixelFormat format, bool is_first) { +GLenum TextureMode(PixelFormat format, std::array<SwizzleSource, 4> swizzle) { + bool any_r = + std::ranges::any_of(swizzle, [](SwizzleSource s) { return s == SwizzleSource::R; }); switch (format) { case PixelFormat::D24_UNORM_S8_UINT: case PixelFormat::D32_FLOAT_S8_UINT: - return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX; + // R = depth, G = stencil + return any_r ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX; case PixelFormat::S8_UINT_D24_UNORM: - return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; + // R = stencil, G = depth + return any_r ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; default: ASSERT(false); return GL_DEPTH_COMPONENT; @@ -208,8 +212,7 @@ void ApplySwizzle(GLuint handle, PixelFormat format, std::array<SwizzleSource, 4 case PixelFormat::D32_FLOAT_S8_UINT: case PixelFormat::S8_UINT_D24_UNORM: UNIMPLEMENTED_IF(swizzle[0] != SwizzleSource::R && swizzle[0] != SwizzleSource::G); - glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE, - TextureMode(format, swizzle[0] == SwizzleSource::R)); + glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE, TextureMode(format, swizzle)); std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed); break; case PixelFormat::A5B5G5R1_UNORM: { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index b0153a502..9cbcb3c8f 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -238,7 +238,7 @@ private: return indices; } - void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) { + void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) override { switch (index_type) { case VK_INDEX_TYPE_UINT8_EXT: std::memcpy(staging_data, MakeIndices<u8>(quad, first).data(), quad_size); @@ -278,7 +278,7 @@ private: return indices; } - void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) { + void MakeAndUpdateIndices(u8* staging_data, size_t quad_size, u32 quad, u32 first) override { switch (index_type) { case VK_INDEX_TYPE_UINT8_EXT: std::memcpy(staging_data, MakeIndices<u8>(quad, first).data(), quad_size); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f085d53a1..25965b684 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1294,7 +1294,7 @@ void RasterizerVulkan::UpdateDepthBoundsTestEnable(Tegra::Engines::Maxwell3D::Re LOG_WARNING(Render_Vulkan, "Depth bounds is enabled but not supported"); enabled = false; } - scheduler.Record([enable = regs.depth_bounds_enable](vk::CommandBuffer cmdbuf) { + scheduler.Record([enable = enabled](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBoundsTestEnableEXT(enable); }); } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 8a204f93f..e013d1c60 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -189,13 +189,16 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { if (info.IsRenderTarget()) { return ImageAspectMask(info.format); } - const bool is_first = info.Swizzle()[0] == SwizzleSource::R; + bool any_r = + std::ranges::any_of(info.Swizzle(), [](SwizzleSource s) { return s == SwizzleSource::R; }); switch (info.format) { case PixelFormat::D24_UNORM_S8_UINT: case PixelFormat::D32_FLOAT_S8_UINT: - return is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; + // R = depth, G = stencil + return any_r ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; case PixelFormat::S8_UINT_D24_UNORM: - return is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; + // R = stencil, G = depth + return any_r ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; case PixelFormat::D16_UNORM: case PixelFormat::D32_FLOAT: return VK_IMAGE_ASPECT_DEPTH_BIT; @@ -1769,7 +1772,7 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(), .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(), .borderColor = - arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color), + arbitrary_borders ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color), .unnormalizedCoordinates = VK_FALSE, }); } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f233b065e..c092507f4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -91,6 +91,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "common/microprofile.h" #include "common/scm_rev.h" #include "common/scope_exit.h" +#ifdef _WIN32 +#include "common/windows/timer_resolution.h" +#endif #ifdef ARCHITECTURE_x86_64 #include "common/x64/cpu_detect.h" #endif @@ -377,6 +380,12 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); +#ifdef _WIN32 + LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", + std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>( + Common::Windows::SetCurrentTimerResolutionToMaximum()) + .count()); +#endif UpdateWindowTitle(); show(); diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 77edd58ca..5f39ece32 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -42,6 +42,8 @@ #include <windows.h> #include <shellapi.h> + +#include "common/windows/timer_resolution.h" #endif #undef _UNICODE @@ -314,6 +316,8 @@ int main(int argc, char** argv) { #ifdef _WIN32 LocalFree(argv_w); + + Common::Windows::SetCurrentTimerResolutionToMaximum(); #endif MicroProfileOnThreadCreate("EmuThread"); |