Compare commits

..

27 Commits

Author SHA1 Message Date
german77
e090a1c6bd yuzu: Move audio settings to audio section 2023-03-11 20:04:36 -06:00
german77
e8af3f29d2 yuzu: Remove console id setting 2023-03-11 19:33:31 -06:00
bunnei
4562f7af9a Merge pull request #9906 from german77/metroid2
input_common: Increase mouse sensitivity range
2023-03-08 10:43:38 -08:00
liamwhite
f3f57f90fe Merge pull request #9912 from liamwhite/err
hle: rename legacy errors to Results
2023-03-08 09:16:27 -05:00
liamwhite
b5d61f214d Merge pull request #9904 from liamwhite/ws
kernel: fix WaitSynchronization
2023-03-08 09:16:17 -05:00
liamwhite
3cf88a4d6c Merge pull request #9896 from Kelebek1/d24s8
Check all swizzle components for red, not just [0]
2023-03-08 09:16:06 -05:00
Morph
d72d753b1a Merge pull request #9921 from liamwhite/override
general: fix type inconsistencies
2023-03-07 22:42:40 -05:00
Morph
a3ffea6a64 Merge pull request #9918 from liamwhite/fwrapv
kernel: avoid signed overflow UB on MSVC
2023-03-07 22:42:32 -05:00
Morph
b014fdacdb Merge pull request #9920 from liamwhite/constexpr-bit-cast
common: make BitCast constexpr
2023-03-07 22:42:19 -05:00
Narr the Reg
757aafa582 input_common: Minor typo issues (#9922) 2023-03-08 03:15:46 +01:00
german77
9a9e5844d3 input_common: Increase mouse sensitivity range 2023-03-07 19:31:52 -06:00
Liam
64dcb40db1 common: make BitCast constexpr 2023-03-07 20:26:56 -05:00
Liam
ba4213d956 general: fix type inconsistencies 2023-03-07 20:05:19 -05:00
Liam
d45ac00d48 kernel: avoid signed overflow UB on MSVC 2023-03-07 19:46:48 -05:00
liamwhite
a7792e5ff8 Merge pull request #9889 from Morph1984/time-is-ticking
core_timing: Reduce CPU usage on Windows
2023-03-07 10:54:13 -05:00
Liam
1d0fe75e7c hle: rename legacy errors to Results 2023-03-06 20:58:42 -05:00
Liam
644ee0043e kernel: fix WaitSynchronization 2023-03-05 10:29:10 -05:00
Morph
376a414f5b native_clock: Round RDTSC frequency to the nearest 1000 2023-03-05 02:36:31 -05:00
Morph
026eaddbee timer_resolution: Set current process to High QoS
Ensures that this process is treated as a high performance process by the Windows scheduler.
2023-03-05 02:36:31 -05:00
Morph
3453beb1e0 general: Target Windows 10 SDK
We no longer support operating systems below Windows 10.
2023-03-05 02:36:31 -05:00
Morph
194cf0b497 hardware_properties: Update BASE_CLOCK_RATE to exactly 1020 MHz 2023-03-05 02:36:31 -05:00
Morph
bff1453282 core_timing: Use higher precision sleeps on Windows
The precision of sleep_for and wait_for is limited to 1-1.5ms on Windows.
Using SleepForOneTick() allows us to sleep for exactly one interval of the current timer resolution.
This allows us to take advantage of systems that have a timer resolution of 0.5ms to reduce CPU overhead in the event loop.
2023-03-05 02:36:31 -05:00
Morph
7e353082ac main: (Windows) Set the current timer resolution to the maximum
Increases the precision of thread sleeps on Windows.
2023-03-05 02:36:31 -05:00
Morph
7fffdf83b7 wall_clock: Make use of SteadyClock 2023-03-05 02:36:31 -05:00
Morph
1ed49f92dd common: Implement a method to change the Windows timer resolution
This utilizes undocumented NtDll functions to change the current timer resolution from the default of 1ms.
2023-03-05 01:41:28 -05:00
Morph
bd09c82521 common: Implement a high resolution steady clock
This implementation provides a consistent, high performance, and high resolution clock where/when std::chrono::steady_clock does not provide sufficient precision.
2023-03-05 01:41:19 -05:00
Kelebek1
a7fb80e612 Check all swizzle components for red, not just [0], pass float border color rather than int 2023-03-04 02:33:50 +00:00
84 changed files with 721 additions and 463 deletions

View File

@@ -477,8 +477,8 @@ if (APPLE)
find_library(COCOA_LIBRARY Cocoa)
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
elseif (WIN32)
# WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista)
add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600)
# Target Windows 10
add_definitions(-D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00)
set(PLATFORM_LIBRARIES winmm ws2_32 iphlpapi)
if (MINGW)
# PSAPI is the Process Status API

6
dist/yuzu.manifest vendored
View File

@@ -36,12 +36,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
<trustInfo

View File

@@ -20,7 +20,7 @@ Manager::Manager(Core::System& system_) : system{system_} {
Result Manager::AcquireSessionId(size_t& session_id) {
if (num_free_sessions == 0) {
LOG_ERROR(Service_Audio, "All 4 AudioIn sessions are in use, cannot create any more");
return Service::Audio::ERR_MAXIMUM_SESSIONS_REACHED;
return Service::Audio::ResultOutOfSessions;
}
session_id = session_ids[next_session_id];
next_session_id = (next_session_id + 1) % MaxInSessions;

View File

@@ -19,7 +19,7 @@ void AudioManager::Shutdown() {
Result AudioManager::SetOutManager(BufferEventFunc buffer_func) {
if (!running) {
return Service::Audio::ERR_OPERATION_FAILED;
return Service::Audio::ResultOperationFailed;
}
std::scoped_lock l{lock};
@@ -35,7 +35,7 @@ Result AudioManager::SetOutManager(BufferEventFunc buffer_func) {
Result AudioManager::SetInManager(BufferEventFunc buffer_func) {
if (!running) {
return Service::Audio::ERR_OPERATION_FAILED;
return Service::Audio::ResultOperationFailed;
}
std::scoped_lock l{lock};

View File

@@ -19,7 +19,7 @@ Manager::Manager(Core::System& system_) : system{system_} {
Result Manager::AcquireSessionId(size_t& session_id) {
if (num_free_sessions == 0) {
LOG_ERROR(Service_Audio, "All 12 Audio Out sessions are in use, cannot create any more");
return Service::Audio::ERR_MAXIMUM_SESSIONS_REACHED;
return Service::Audio::ResultOutOfSessions;
}
session_id = session_ids[next_session_id];
next_session_id = (next_session_id + 1) % MaxOutSessions;

View File

@@ -28,7 +28,7 @@ SystemManager& Manager::GetSystemManager() {
Result Manager::GetWorkBufferSize(const AudioRendererParameterInternal& params,
u64& out_count) const {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ERR_INVALID_REVISION;
return Service::Audio::ResultInvalidRevision;
}
out_count = System::GetWorkBufferSize(params);

View File

@@ -46,7 +46,7 @@ Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
if (system.AppendBuffer(buffer, tag)) {
return ResultSuccess;
}
return Service::Audio::ERR_BUFFER_COUNT_EXCEEDED;
return Service::Audio::ResultBufferCountReached;
}
void In::ReleaseAndRegisterBuffers() {

View File

@@ -45,11 +45,11 @@ Result System::IsConfigValid(const std::string_view device_name,
const AudioInParameter& in_params) const {
if ((device_name.size() > 0) &&
(device_name != GetDefaultDeviceName() && device_name != GetDefaultUacDeviceName())) {
return Service::Audio::ERR_INVALID_DEVICE_NAME;
return Service::Audio::ResultNotFound;
}
if (in_params.sample_rate != TargetSampleRate && in_params.sample_rate > 0) {
return Service::Audio::ERR_INVALID_SAMPLE_RATE;
return Service::Audio::ResultInvalidSampleRate;
}
return ResultSuccess;
@@ -80,7 +80,7 @@ Result System::Initialize(std::string device_name, const AudioInParameter& in_pa
Result System::Start() {
if (state != State::Stopped) {
return Service::Audio::ERR_OPERATION_FAILED;
return Service::Audio::ResultOperationFailed;
}
session->Initialize(name, sample_format, channel_count, session_id, handle,

View File

@@ -46,7 +46,7 @@ Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
if (system.AppendBuffer(buffer, tag)) {
return ResultSuccess;
}
return Service::Audio::ERR_BUFFER_COUNT_EXCEEDED;
return Service::Audio::ResultBufferCountReached;
}
void Out::ReleaseAndRegisterBuffers() {

View File

@@ -33,11 +33,11 @@ std::string_view System::GetDefaultOutputDeviceName() const {
Result System::IsConfigValid(std::string_view device_name,
const AudioOutParameter& in_params) const {
if ((device_name.size() > 0) && (device_name != GetDefaultOutputDeviceName())) {
return Service::Audio::ERR_INVALID_DEVICE_NAME;
return Service::Audio::ResultNotFound;
}
if (in_params.sample_rate != TargetSampleRate && in_params.sample_rate > 0) {
return Service::Audio::ERR_INVALID_SAMPLE_RATE;
return Service::Audio::ResultInvalidSampleRate;
}
if (in_params.channel_count == 0 || in_params.channel_count == 2 ||
@@ -45,7 +45,7 @@ Result System::IsConfigValid(std::string_view device_name,
return ResultSuccess;
}
return Service::Audio::ERR_INVALID_CHANNEL_COUNT;
return Service::Audio::ResultInvalidChannelCount;
}
Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle_,
@@ -80,7 +80,7 @@ size_t System::GetSessionId() const {
Result System::Start() {
if (state != State::Stopped) {
return Service::Audio::ERR_OPERATION_FAILED;
return Service::Audio::ResultOperationFailed;
}
session->Initialize(name, sample_format, channel_count, session_id, handle,

View File

@@ -22,7 +22,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio,
"Both Audio Render sessions are in use, cannot create any more");
return Service::Audio::ERR_MAXIMUM_SESSIONS_REACHED;
return Service::Audio::ResultOutOfSessions;
}
system_registered = true;
}

View File

@@ -48,7 +48,7 @@ Result InfoUpdater::UpdateVoiceChannelResources(VoiceContext& voice_context) {
LOG_ERROR(Service_Audio,
"Consumed an incorrect voice resource size, header size={}, consumed={}",
in_header->voice_resources_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += consumed_input_size;
@@ -123,7 +123,7 @@ Result InfoUpdater::UpdateVoices(VoiceContext& voice_context,
if (consumed_input_size != in_header->voices_size) {
LOG_ERROR(Service_Audio, "Consumed an incorrect voices size, header size={}, consumed={}",
in_header->voices_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
out_header->voices_size = consumed_output_size;
@@ -184,7 +184,7 @@ Result InfoUpdater::UpdateEffectsVersion1(EffectContext& effect_context, const b
if (consumed_input_size != in_header->effects_size) {
LOG_ERROR(Service_Audio, "Consumed an incorrect effects size, header size={}, consumed={}",
in_header->effects_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
out_header->effects_size = consumed_output_size;
@@ -239,7 +239,7 @@ Result InfoUpdater::UpdateEffectsVersion2(EffectContext& effect_context, const b
if (consumed_input_size != in_header->effects_size) {
LOG_ERROR(Service_Audio, "Consumed an incorrect effects size, header size={}, consumed={}",
in_header->effects_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
out_header->effects_size = consumed_output_size;
@@ -267,7 +267,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
}
if (mix_buffer_count == 0) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
std::span<const MixInfo::InParameter> in_params{
@@ -281,13 +281,13 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
total_buffer_count += params.buffer_count;
if (params.dest_mix_id > static_cast<s32>(mix_context.GetCount()) &&
params.dest_mix_id != UnusedMixId && params.mix_id != FinalMixId) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
}
}
if (total_buffer_count > mix_buffer_count) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
bool mix_dirty{false};
@@ -317,7 +317,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
if (mix_dirty) {
if (behaviour.IsSplitterSupported() && splitter_context.UsingSplitter()) {
if (!mix_context.TSortInfo(splitter_context)) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
} else {
mix_context.SortInfo();
@@ -327,7 +327,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
if (consumed_input_size != in_header->mix_size) {
LOG_ERROR(Service_Audio, "Consumed an incorrect mixes size, header size={}, consumed={}",
in_header->mix_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += mix_count * sizeof(MixInfo::InParameter);
@@ -384,7 +384,7 @@ Result InfoUpdater::UpdateSinks(SinkContext& sink_context, std::span<MemoryPoolI
if (consumed_input_size != in_header->sinks_size) {
LOG_ERROR(Service_Audio, "Consumed an incorrect sinks size, header size={}, consumed={}",
in_header->sinks_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += consumed_input_size;
@@ -411,7 +411,7 @@ Result InfoUpdater::UpdateMemoryPools(std::span<MemoryPoolInfo> memory_pools,
state != MemoryPoolInfo::ResultState::MapFailed &&
state != MemoryPoolInfo::ResultState::InUse) {
LOG_WARNING(Service_Audio, "Invalid ResultState from updating memory pools");
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
}
@@ -423,7 +423,7 @@ Result InfoUpdater::UpdateMemoryPools(std::span<MemoryPoolInfo> memory_pools,
LOG_ERROR(Service_Audio,
"Consumed an incorrect memory pool size, header size={}, consumed={}",
in_header->memory_pool_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += consumed_input_size;
@@ -453,7 +453,7 @@ Result InfoUpdater::UpdatePerformanceBuffer(std::span<u8> performance_output,
LOG_ERROR(Service_Audio,
"Consumed an incorrect performance size, header size={}, consumed={}",
in_header->performance_buffer_size, consumed_input_size);
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += consumed_input_size;
@@ -467,18 +467,18 @@ Result InfoUpdater::UpdateBehaviorInfo(BehaviorInfo& behaviour_) {
const auto in_params{reinterpret_cast<const BehaviorInfo::InParameter*>(input)};
if (!CheckValidRevision(in_params->revision)) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
if (in_params->revision != behaviour_.GetUserRevision()) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
behaviour_.ClearError();
behaviour_.UpdateFlags(in_params->flags);
if (in_header->behaviour_size != sizeof(BehaviorInfo::InParameter)) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += sizeof(BehaviorInfo::InParameter);
@@ -500,7 +500,7 @@ Result InfoUpdater::UpdateErrorInfo(const BehaviorInfo& behaviour_) {
Result InfoUpdater::UpdateSplitterInfo(SplitterContext& splitter_context) {
u32 consumed_size{0};
if (!splitter_context.Update(input, consumed_size)) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
input += consumed_size;
@@ -529,9 +529,9 @@ Result InfoUpdater::UpdateRendererInfo(const u64 elapsed_frames) {
Result InfoUpdater::CheckConsumedSize() {
if (CpuAddr(input) - CpuAddr(input_origin.data()) != expected_input_size) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
} else if (CpuAddr(output) - CpuAddr(output_origin.data()) != expected_output_size) {
return Service::Audio::ERR_INVALID_UPDATE_DATA;
return Service::Audio::ResultInvalidUpdateInfo;
}
return ResultSuccess;
}

View File

@@ -92,7 +92,7 @@ bool PoolMapper::TryAttachBuffer(BehaviorInfo::ErrorInfo& error_info, AddressInf
address_info.Setup(address, size);
if (!FillDspAddr(address_info)) {
error_info.error_code = Service::Audio::ERR_POOL_MAPPING_FAILED;
error_info.error_code = Service::Audio::ResultInvalidAddressInfo;
error_info.address = address;
return force_map;
}

View File

@@ -101,15 +101,15 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ERR_INVALID_REVISION;
return Service::Audio::ResultInvalidRevision;
}
if (GetWorkBufferSize(params) > transfer_memory_size) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
if (process_handle_ == 0) {
return Service::Audio::ERR_INVALID_PROCESS_HANDLE;
return Service::Audio::ResultInvalidHandle;
}
behavior.SetUserLibRevision(params.revision);
@@ -143,19 +143,19 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
samples_workbuffer =
allocator.Allocate<s32>((voice_channels + mix_buffer_count) * sample_count, 0x10);
if (samples_workbuffer.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
auto upsampler_workbuffer{allocator.Allocate<s32>(
(voice_channels + mix_buffer_count) * TargetSampleCount * upsampler_count, 0x10)};
if (upsampler_workbuffer.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
depop_buffer =
allocator.Allocate<s32>(Common::AlignUp(static_cast<u32>(mix_buffer_count), 0x40), 0x40);
if (depop_buffer.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
// invalidate samples_workbuffer DSP cache
@@ -166,12 +166,12 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
}
if (voice_infos.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
auto sorted_voice_infos{allocator.Allocate<VoiceInfo*>(params.voices, 0x10)};
if (sorted_voice_infos.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::memset(sorted_voice_infos.data(), 0, sorted_voice_infos.size_bytes());
@@ -183,12 +183,12 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
}
if (voice_channel_resources.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
auto voice_cpu_states{allocator.Allocate<VoiceState>(params.voices, 0x10)};
if (voice_cpu_states.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
for (auto& voice_state : voice_cpu_states) {
@@ -198,7 +198,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
auto mix_infos{allocator.Allocate<MixInfo>(params.sub_mixes + 1, 0x10)};
if (mix_infos.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
u32 effect_process_order_count{0};
@@ -208,7 +208,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
effect_process_order_count = params.effects * (params.sub_mixes + 1);
effect_process_order_buffer = allocator.Allocate<s32>(effect_process_order_count, 0x10);
if (effect_process_order_buffer.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
}
@@ -222,7 +222,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
auto sorted_mix_infos{allocator.Allocate<MixInfo*>(params.sub_mixes + 1, 0x10)};
if (sorted_mix_infos.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::memset(sorted_mix_infos.data(), 0, sorted_mix_infos.size_bytes());
@@ -235,7 +235,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
auto edge_matrix_workbuffer{allocator.Allocate<u8>(edge_matrix_size, 1)};
if (node_states_workbuffer.empty() || edge_matrix_workbuffer.size() == 0) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
mix_context.Initialize(sorted_mix_infos, mix_infos, params.sub_mixes + 1,
@@ -250,7 +250,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
upsampler_manager = allocator.Allocate<UpsamplerManager>(1, 0x10).data();
if (upsampler_manager == nullptr) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
memory_pool_workbuffer = allocator.Allocate<MemoryPoolInfo>(memory_pool_count, 0x10);
@@ -259,18 +259,18 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
}
if (memory_pool_workbuffer.empty() && memory_pool_count > 0) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
if (!splitter_context.Initialize(behavior, params, allocator)) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::span<EffectResultState> effect_result_states_cpu{};
if (behavior.IsEffectInfoVersion2Supported() && params.effects > 0) {
effect_result_states_cpu = allocator.Allocate<EffectResultState>(params.effects, 0x10);
if (effect_result_states_cpu.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::memset(effect_result_states_cpu.data(), 0, effect_result_states_cpu.size_bytes());
}
@@ -289,7 +289,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
upsampler_workbuffer);
if (upsampler_infos.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
auto effect_infos{allocator.Allocate<EffectInfoBase>(params.effects, 0x40)};
@@ -298,14 +298,14 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
}
if (effect_infos.empty() && params.effects > 0) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::span<EffectResultState> effect_result_states_dsp{};
if (behavior.IsEffectInfoVersion2Supported() && params.effects > 0) {
effect_result_states_dsp = allocator.Allocate<EffectResultState>(params.effects, 0x40);
if (effect_result_states_dsp.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::memset(effect_result_states_dsp.data(), 0, effect_result_states_dsp.size_bytes());
}
@@ -319,14 +319,14 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
}
if (sinks.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
sink_context.Initialize(sinks, params.sinks);
auto voice_dsp_states{allocator.Allocate<VoiceState>(params.voices, 0x40)};
if (voice_dsp_states.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
for (auto& voice_state : voice_dsp_states) {
@@ -344,7 +344,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
0xC};
performance_workbuffer = allocator.Allocate<u8>(perf_workbuffer_size, 0x40);
if (performance_workbuffer.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
std::memset(performance_workbuffer.data(), 0, performance_workbuffer.size_bytes());
performance_manager.Initialize(performance_workbuffer, performance_workbuffer.size_bytes(),
@@ -360,7 +360,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
command_workbuffer_size = allocator.GetRemainingSize();
command_workbuffer = allocator.Allocate<u8>(command_workbuffer_size, 0x40);
if (command_workbuffer.empty()) {
return Service::Audio::ERR_INSUFFICIENT_BUFFER_SIZE;
return Service::Audio::ResultInsufficientBuffer;
}
command_buffer_size = 0;

View File

@@ -181,7 +181,7 @@ void VoiceInfo::UpdateWaveBuffer(std::span<BehaviorInfo::ErrorInfo> error_info,
if (wave_buffer_internal.start_offset * byte_size > wave_buffer_internal.size ||
wave_buffer_internal.end_offset * byte_size > wave_buffer_internal.size) {
LOG_ERROR(Service_Audio, "Invalid PCM16 start/end wavebuffer sizes!");
error_info[0].error_code = Service::Audio::ERR_INVALID_UPDATE_DATA;
error_info[0].error_code = Service::Audio::ResultInvalidUpdateInfo;
error_info[0].address = wave_buffer_internal.address;
return;
}
@@ -192,7 +192,7 @@ void VoiceInfo::UpdateWaveBuffer(std::span<BehaviorInfo::ErrorInfo> error_info,
if (wave_buffer_internal.start_offset * byte_size > wave_buffer_internal.size ||
wave_buffer_internal.end_offset * byte_size > wave_buffer_internal.size) {
LOG_ERROR(Service_Audio, "Invalid PCMFloat start/end wavebuffer sizes!");
error_info[0].error_code = Service::Audio::ERR_INVALID_UPDATE_DATA;
error_info[0].error_code = Service::Audio::ResultInvalidUpdateInfo;
error_info[0].address = wave_buffer_internal.address;
return;
}
@@ -216,7 +216,7 @@ void VoiceInfo::UpdateWaveBuffer(std::span<BehaviorInfo::ErrorInfo> error_info,
if (start > static_cast<s64>(wave_buffer_internal.size) ||
end > static_cast<s64>(wave_buffer_internal.size)) {
LOG_ERROR(Service_Audio, "Invalid ADPCM start/end wavebuffer sizes!");
error_info[0].error_code = Service::Audio::ERR_INVALID_UPDATE_DATA;
error_info[0].error_code = Service::Audio::ResultInvalidUpdateInfo;
error_info[0].address = wave_buffer_internal.address;
return;
}
@@ -228,7 +228,7 @@ void VoiceInfo::UpdateWaveBuffer(std::span<BehaviorInfo::ErrorInfo> error_info,
if (wave_buffer_internal.start_offset < 0 || wave_buffer_internal.end_offset < 0) {
LOG_ERROR(Service_Audio, "Invalid input start/end wavebuffer sizes!");
error_info[0].error_code = Service::Audio::ERR_INVALID_UPDATE_DATA;
error_info[0].error_code = Service::Audio::ResultInvalidUpdateInfo;
error_info[0].address = wave_buffer_internal.address;
return;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

22
src/common/overflow.h Normal file
View File

@@ -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

View File

@@ -503,7 +503,7 @@ struct Values {
Setting<bool> tas_loop{false, "tas_loop"};
Setting<bool> mouse_panning{false, "mouse_panning"};
Setting<u8, true> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
Setting<u8, true> mouse_panning_sensitivity{50, 1, 100, "mouse_panning_sensitivity"};
Setting<bool> mouse_enabled{false, "mouse_enabled"};
Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};

View File

@@ -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

23
src/common/steady_clock.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -454,7 +454,6 @@ add_library(core STATIC
hle/service/filesystem/fsp_srv.h
hle/service/fgm/fgm.cpp
hle/service/fgm/fgm.h
hle/service/friend/errors.h
hle/service/friend/friend.cpp
hle/service/friend/friend.h
hle/service/friend/friend_interface.cpp

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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{

View File

@@ -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;
}

View File

@@ -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{};

View File

@@ -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) {}

View File

@@ -310,10 +310,10 @@ public:
/// Clears the signaled state of the process if and only if it's signaled.
///
/// @pre The process must not be already terminated. If this is called on a
/// terminated process, then ERR_INVALID_STATE will be returned.
/// terminated process, then ResultInvalidState will be returned.
///
/// @pre The process must be in a signaled state. If this is called on a
/// process instance that is not signaled, ERR_INVALID_STATE will be
/// process instance that is not signaled, ResultInvalidState will be
/// returned.
Result Reset();

View File

@@ -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;
}

View File

@@ -48,19 +48,15 @@ Result ResetSignal(Core::System& system, Handle handle) {
return ResultInvalidHandle;
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
s64 nano_seconds) {
LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}",
handles_address, num_handles, nano_seconds);
static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles,
int32_t num_handles, int64_t timeout_ns) {
// Ensure number of handles is valid.
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
// Get the synchronization context.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
std::vector<KSynchronizationObject*> objs(num_handles);
const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
Handle* handles = system.Memory().GetPointer<Handle>(handles_address);
// Copy user handles.
if (num_handles > 0) {
@@ -68,21 +64,38 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
num_handles),
ResultInvalidHandle);
for (const auto& obj : objs) {
kernel.RegisterInUseObject(obj);
}
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
for (s32 i = 0; i < num_handles; ++i) {
kernel.UnregisterInUseObject(objs[i]);
for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
});
return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()),
nano_seconds);
// Wait on the objects.
Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(),
static_cast<s32>(objs.size()), timeout_ns);
R_SUCCEED_IF(res == ResultSessionClosed);
R_RETURN(res);
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles,
int32_t num_handles, int64_t timeout_ns) {
LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
num_handles, timeout_ns);
// Ensure number of handles is valid.
R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
std::vector<Handle> handles(num_handles);
if (num_handles > 0) {
system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
}
R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
}
/// Resumes a thread waiting on WaitSynchronization

View File

@@ -30,12 +30,6 @@
namespace Service::Account {
constexpr Result ERR_INVALID_USER_ID{ErrorModule::Account, 20};
constexpr Result ERR_INVALID_APPLICATION_ID{ErrorModule::Account, 22};
constexpr Result ERR_INVALID_BUFFER{ErrorModule::Account, 30};
constexpr Result ERR_INVALID_BUFFER_SIZE{ErrorModule::Account, 31};
constexpr Result ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100};
// Thumbnails are hard coded to be at least this size
constexpr std::size_t THUMBNAIL_SIZE = 0x24000;
@@ -384,7 +378,7 @@ protected:
if (user_data.size() < sizeof(UserData)) {
LOG_ERROR(Service_ACC, "UserData buffer too small!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_BUFFER);
rb.Push(Account::ResultInvalidArrayLength);
return;
}
@@ -394,7 +388,7 @@ protected:
if (!profile_manager.SetProfileBaseAndData(user_id, base, data)) {
LOG_ERROR(Service_ACC, "Failed to update user data and base!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_FAILED_SAVE_DATA);
rb.Push(Account::ResultAccountUpdateFailed);
return;
}
@@ -417,7 +411,7 @@ protected:
if (user_data.size() < sizeof(UserData)) {
LOG_ERROR(Service_ACC, "UserData buffer too small!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_BUFFER);
rb.Push(Account::ResultInvalidArrayLength);
return;
}
@@ -432,7 +426,7 @@ protected:
!profile_manager.SetProfileBaseAndData(user_id, base, data)) {
LOG_ERROR(Service_ACC, "Failed to update profile data, base, and image!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_FAILED_SAVE_DATA);
rb.Push(Account::ResultAccountUpdateFailed);
return;
}
@@ -764,7 +758,7 @@ void Module::Interface::InitializeApplicationInfoRestricted(HLERequestContext& c
Result Module::Interface::InitializeApplicationInfoBase() {
if (application_info) {
LOG_ERROR(Service_ACC, "Application already initialized");
return ERR_ACCOUNTINFO_ALREADY_INITIALIZED;
return Account::ResultApplicationInfoAlreadyInitialized;
}
// TODO(ogniK): This should be changed to reflect the target process for when we have multiple
@@ -775,7 +769,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
if (launch_property.Failed()) {
LOG_ERROR(Service_ACC, "Failed to get launch property");
return ERR_ACCOUNTINFO_BAD_APPLICATION;
return Account::ResultInvalidApplication;
}
switch (launch_property->base_game_storage_id) {
@@ -791,7 +785,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
default:
LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}",
launch_property->base_game_storage_id);
return ERR_ACCOUNTINFO_BAD_APPLICATION;
return Account::ResultInvalidApplication;
}
LOG_WARNING(Service_ACC, "ApplicationInfo init required");
@@ -899,20 +893,20 @@ void Module::Interface::StoreSaveDataThumbnail(HLERequestContext& ctx, const Com
if (tid == 0) {
LOG_ERROR(Service_ACC, "TitleID is not valid!");
rb.Push(ERR_INVALID_APPLICATION_ID);
rb.Push(Account::ResultInvalidApplication);
return;
}
if (uuid.IsInvalid()) {
LOG_ERROR(Service_ACC, "User ID is not valid!");
rb.Push(ERR_INVALID_USER_ID);
rb.Push(Account::ResultInvalidUserId);
return;
}
const auto thumbnail_size = ctx.GetReadBufferSize();
if (thumbnail_size != THUMBNAIL_SIZE) {
LOG_ERROR(Service_ACC, "Buffer size is empty! size={:X} expecting {:X}", thumbnail_size,
THUMBNAIL_SIZE);
rb.Push(ERR_INVALID_BUFFER_SIZE);
rb.Push(Account::ResultInvalidArrayLength);
return;
}

View File

@@ -7,7 +7,13 @@
namespace Service::Account {
constexpr Result ERR_ACCOUNTINFO_BAD_APPLICATION{ErrorModule::Account, 22};
constexpr Result ERR_ACCOUNTINFO_ALREADY_INITIALIZED{ErrorModule::Account, 41};
constexpr Result ResultCancelledByUser{ErrorModule::Account, 1};
constexpr Result ResultNoNotifications{ErrorModule::Account, 15};
constexpr Result ResultInvalidUserId{ErrorModule::Account, 20};
constexpr Result ResultInvalidApplication{ErrorModule::Account, 22};
constexpr Result ResultNullptr{ErrorModule::Account, 30};
constexpr Result ResultInvalidArrayLength{ErrorModule::Account, 32};
constexpr Result ResultApplicationInfoAlreadyInitialized{ErrorModule::Account, 41};
constexpr Result ResultAccountUpdateFailed{ErrorModule::Account, 100};
} // namespace Service::Account

View File

@@ -39,9 +39,9 @@
namespace Service::AM {
constexpr Result ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 2};
constexpr Result ERR_NO_MESSAGES{ErrorModule::AM, 3};
constexpr Result ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 503};
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
enum class LaunchParameterKind : u32 {
ApplicationSpecific = 1,
@@ -758,7 +758,7 @@ void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
if (message == AppletMessageQueue::AppletMessage::None) {
LOG_ERROR(Service_AM, "Message queue is empty");
rb.Push(ERR_NO_MESSAGES);
rb.Push(AM::ResultNoMessages);
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
return;
}
@@ -1028,7 +1028,7 @@ private:
LOG_DEBUG(Service_AM,
"storage is a nullptr. There is no data in the current normal channel");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL);
rb.Push(AM::ResultNoDataInChannel);
return;
}
@@ -1059,7 +1059,7 @@ private:
LOG_DEBUG(Service_AM,
"storage is a nullptr. There is no data in the current interactive channel");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL);
rb.Push(AM::ResultNoDataInChannel);
return;
}
@@ -1138,7 +1138,7 @@ void IStorageAccessor::Write(HLERequestContext& ctx) {
backing.GetSize(), size, offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
rb.Push(AM::ResultInvalidOffset);
return;
}
@@ -1161,7 +1161,7 @@ void IStorageAccessor::Read(HLERequestContext& ctx) {
backing.GetSize(), size, offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
rb.Push(AM::ResultInvalidOffset);
return;
}
@@ -1502,7 +1502,7 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL);
rb.Push(AM::ResultNoDataInChannel);
}
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
@@ -1799,7 +1799,7 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestC
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL);
rb.Push(AM::ResultNoDataInChannel);
}
void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {

View File

@@ -19,10 +19,9 @@
namespace Service::AM::Applets {
// This error code (0x183ACA) is thrown when the applet fails to initialize.
[[maybe_unused]] constexpr Result ERR_CONTROLLER_APPLET_3101{ErrorModule::HID, 3101};
// This error code (0x183CCA) is thrown when the u32 result in ControllerSupportResultInfo is 2.
[[maybe_unused]] constexpr Result ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102};
[[maybe_unused]] constexpr Result ResultControllerSupportCanceled{ErrorModule::HID, 3101};
[[maybe_unused]] constexpr Result ResultControllerSupportNotSupportedNpadStyle{ErrorModule::HID,
3102};
static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text,

View File

@@ -7,13 +7,12 @@
#include "common/string_util.h"
#include "core/core.h"
#include "core/frontend/applets/profile_select.h"
#include "core/hle/service/acc/errors.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applet_profile_select.h"
namespace Service::AM::Applets {
constexpr Result ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::ProfileSelectApplet& frontend_)
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
@@ -63,8 +62,8 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
output.result = 0;
output.uuid_selected = *uuid;
} else {
status = ERR_USER_CANCELLED_SELECTION;
output.result = ERR_USER_CANCELLED_SELECTION.raw;
status = Account::ResultCancelledByUser;
output.result = Account::ResultCancelledByUser.raw;
output.uuid_selected = Common::InvalidUUID;
}

View File

@@ -170,7 +170,7 @@ private:
if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_SUPPORTED);
rb.Push(Audio::ResultNotSupported);
return;
}
@@ -448,7 +448,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_MAXIMUM_SESSIONS_REACHED);
rb.Push(Audio::ResultOutOfSessions);
return;
}
@@ -461,7 +461,7 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
if (session_id == -1) {
LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_MAXIMUM_SESSIONS_REACHED);
rb.Push(Audio::ResultOutOfSessions);
return;
}

View File

@@ -7,17 +7,17 @@
namespace Service::Audio {
constexpr Result ERR_INVALID_DEVICE_NAME{ErrorModule::Audio, 1};
constexpr Result ERR_OPERATION_FAILED{ErrorModule::Audio, 2};
constexpr Result ERR_INVALID_SAMPLE_RATE{ErrorModule::Audio, 3};
constexpr Result ERR_INSUFFICIENT_BUFFER_SIZE{ErrorModule::Audio, 4};
constexpr Result ERR_MAXIMUM_SESSIONS_REACHED{ErrorModule::Audio, 5};
constexpr Result ERR_BUFFER_COUNT_EXCEEDED{ErrorModule::Audio, 8};
constexpr Result ERR_INVALID_CHANNEL_COUNT{ErrorModule::Audio, 10};
constexpr Result ERR_INVALID_UPDATE_DATA{ErrorModule::Audio, 41};
constexpr Result ERR_POOL_MAPPING_FAILED{ErrorModule::Audio, 42};
constexpr Result ERR_NOT_SUPPORTED{ErrorModule::Audio, 513};
constexpr Result ERR_INVALID_PROCESS_HANDLE{ErrorModule::Audio, 1536};
constexpr Result ERR_INVALID_REVISION{ErrorModule::Audio, 1537};
constexpr Result ResultNotFound{ErrorModule::Audio, 1};
constexpr Result ResultOperationFailed{ErrorModule::Audio, 2};
constexpr Result ResultInvalidSampleRate{ErrorModule::Audio, 3};
constexpr Result ResultInsufficientBuffer{ErrorModule::Audio, 4};
constexpr Result ResultOutOfSessions{ErrorModule::Audio, 5};
constexpr Result ResultBufferCountReached{ErrorModule::Audio, 8};
constexpr Result ResultInvalidChannelCount{ErrorModule::Audio, 10};
constexpr Result ResultInvalidUpdateInfo{ErrorModule::Audio, 41};
constexpr Result ResultInvalidAddressInfo{ErrorModule::Audio, 42};
constexpr Result ResultNotSupported{ErrorModule::Audio, 513};
constexpr Result ResultInvalidHandle{ErrorModule::Audio, 1536};
constexpr Result ResultInvalidRevision{ErrorModule::Audio, 1537};
} // namespace Service::Audio

View File

@@ -1,11 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/result.h"
namespace Service::Friend {
constexpr Result ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15};
}

View File

@@ -6,7 +6,7 @@
#include "common/uuid.h"
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/friend/errors.h"
#include "core/hle/service/acc/errors.h"
#include "core/hle/service/friend/friend.h"
#include "core/hle/service/friend/friend_interface.h"
#include "core/hle/service/ipc_helpers.h"
@@ -259,7 +259,7 @@ private:
if (notifications.empty()) {
LOG_ERROR(Service_Friend, "No notifications in queue!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_NOTIFICATIONS);
rb.Push(Account::ResultNoNotifications);
return;
}

View File

@@ -61,7 +61,7 @@ void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) {
if (!title_id.has_value()) {
LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_REGISTERED);
rb.Push(Glue::ResultProcessIdNotRegistered);
return;
}
@@ -109,7 +109,7 @@ void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
if (!title_id.has_value()) {
LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_REGISTERED);
rb.Push(Glue::ResultProcessIdNotRegistered);
return;
}
@@ -178,7 +178,7 @@ private:
if (process_id == 0) {
LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_PROCESS_ID);
rb.Push(Glue::ResultInvalidProcessId);
return;
}
@@ -186,7 +186,7 @@ private:
LOG_ERROR(Service_ARP,
"Attempted to issue registrar, but registrar is already issued!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_ACCESS);
rb.Push(Glue::ResultAlreadyBound);
return;
}
@@ -205,7 +205,7 @@ private:
Service_ARP,
"Attempted to set application launch property, but registrar is already issued!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_ACCESS);
rb.Push(Glue::ResultAlreadyBound);
return;
}
@@ -224,7 +224,7 @@ private:
Service_ARP,
"Attempted to set application control property, but registrar is already issued!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_ACCESS);
rb.Push(Glue::ResultAlreadyBound);
return;
}
@@ -263,7 +263,7 @@ void ARP_W::AcquireRegistrar(HLERequestContext& ctx) {
system, [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
const auto res = GetTitleIDForProcessID(system, process_id);
if (!res.has_value()) {
return ERR_NOT_REGISTERED;
return Glue::ResultProcessIdNotRegistered;
}
return manager.Register(*res, launch, std::move(control));
@@ -283,7 +283,7 @@ void ARP_W::UnregisterApplicationInstance(HLERequestContext& ctx) {
if (process_id == 0) {
LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_PROCESS_ID);
rb.Push(Glue::ResultInvalidProcessId);
return;
}
@@ -292,7 +292,7 @@ void ARP_W::UnregisterApplicationInstance(HLERequestContext& ctx) {
if (!title_id.has_value()) {
LOG_ERROR(Service_ARP, "No title ID for process ID!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NOT_REGISTERED);
rb.Push(Glue::ResultProcessIdNotRegistered);
return;
}

View File

@@ -7,9 +7,8 @@
namespace Service::Glue {
constexpr Result ERR_INVALID_RESOURCE{ErrorModule::ARP, 30};
constexpr Result ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 31};
constexpr Result ERR_INVALID_ACCESS{ErrorModule::ARP, 42};
constexpr Result ERR_NOT_REGISTERED{ErrorModule::ARP, 102};
constexpr Result ResultInvalidProcessId{ErrorModule::ARP, 31};
constexpr Result ResultAlreadyBound{ErrorModule::ARP, 42};
constexpr Result ResultProcessIdNotRegistered{ErrorModule::ARP, 102};
} // namespace Service::Glue

View File

@@ -17,12 +17,12 @@ ARPManager::~ARPManager() = default;
ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
if (title_id == 0) {
return ERR_INVALID_PROCESS_ID;
return Glue::ResultInvalidProcessId;
}
const auto iter = entries.find(title_id);
if (iter == entries.end()) {
return ERR_NOT_REGISTERED;
return Glue::ResultProcessIdNotRegistered;
}
return iter->second.launch;
@@ -30,12 +30,12 @@ ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id)
ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
if (title_id == 0) {
return ERR_INVALID_PROCESS_ID;
return Glue::ResultInvalidProcessId;
}
const auto iter = entries.find(title_id);
if (iter == entries.end()) {
return ERR_NOT_REGISTERED;
return Glue::ResultProcessIdNotRegistered;
}
return iter->second.control;
@@ -44,12 +44,12 @@ ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
std::vector<u8> control) {
if (title_id == 0) {
return ERR_INVALID_PROCESS_ID;
return Glue::ResultInvalidProcessId;
}
const auto iter = entries.find(title_id);
if (iter != entries.end()) {
return ERR_INVALID_ACCESS;
return Glue::ResultAlreadyBound;
}
entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)});
@@ -58,12 +58,12 @@ Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
Result ARPManager::Unregister(u64 title_id) {
if (title_id == 0) {
return ERR_INVALID_PROCESS_ID;
return Glue::ResultInvalidProcessId;
}
const auto iter = entries.find(title_id);
if (iter == entries.end()) {
return ERR_NOT_REGISTERED;
return Glue::ResultProcessIdNotRegistered;
}
entries.erase(iter);

View File

@@ -30,23 +30,23 @@ public:
~ARPManager();
// Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was
// previously registered, otherwise ERR_NOT_REGISTERED if it was never registered or
// ERR_INVALID_PROCESS_ID if the title ID is 0.
// previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or
// ResultInvalidProcessId if the title ID is 0.
ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const;
// Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to
// the provided title ID if it was previously registered, otherwise ERR_NOT_REGISTERED if it was
// never registered or ERR_INVALID_PROCESS_ID if the title ID is 0.
// the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered
// if it was never registered or ResultInvalidProcessId if the title ID is 0.
ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const;
// Adds a new entry to the internal database with the provided parameters, returning
// ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister
// step, and ERR_INVALID_PROCESS_ID if the title ID is 0.
// ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate
// Unregister step, and ResultInvalidProcessId if the title ID is 0.
Result Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control);
// Removes the registration for the provided title ID from the database, returning
// ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the
// title ID is 0.
// ResultProcessIdNotRegistered if it doesn't exist in the database and ResultInvalidProcessId
// if the title ID is 0.
Result Unregister(u64 title_id);
// Removes all entries from the database, always succeeds. Should only be used when resetting

View File

@@ -19,7 +19,7 @@
namespace IPC {
constexpr Result ERR_REMOTE_PROCESS_DEAD{ErrorModule::HIPC, 301};
constexpr Result ResultSessionClosed{ErrorModule::HIPC, 301};
class RequestHelperBase {
protected:

View File

@@ -7,5 +7,6 @@
namespace Service::NS {
constexpr Result ERR_APPLICATION_LANGUAGE_NOT_FOUND{ErrorModule::NS, 300};
}
constexpr Result ResultApplicationLanguageNotFound{ErrorModule::NS, 300};
}

View File

@@ -416,14 +416,14 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
if (application_language == std::nullopt) {
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
language_code);
return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
return Service::NS::ResultApplicationLanguageNotFound;
}
const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
if (!priority_list) {
LOG_ERROR(Service_NS,
"Could not find application language priorities! application_language={}",
*application_language);
return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
return Service::NS::ResultApplicationLanguageNotFound;
}
// Try to find a valid language.
@@ -436,7 +436,7 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
supported_languages);
return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
return Service::NS::ResultApplicationLanguageNotFound;
}
void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
@@ -461,7 +461,7 @@ ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguag
ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
if (language_code == std::nullopt) {
LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
return ERR_APPLICATION_LANGUAGE_NOT_FOUND;
return Service::NS::ResultApplicationLanguageNotFound;
}
return static_cast<u64>(*language_code);

View File

@@ -404,7 +404,7 @@ Result ServerManager::CompleteSyncRequest(RequestState&& request) {
rc = request.session->SendReplyHLE();
// If the session has been closed, we're done.
if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) {
if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ResultSessionClosed) {
// Close the session.
request.session->Close();

View File

@@ -176,7 +176,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
case IPC::CommandType::TIPC_Close: {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
result = IPC::ERR_REMOTE_PROCESS_DEAD;
result = IPC::ResultSessionClosed;
break;
}
case IPC::CommandType::ControlWithContext:

View File

@@ -74,7 +74,7 @@ constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_la
constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF;
constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;
constexpr Result ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625};
constexpr Result ResultInvalidLanguage{ErrorModule::Settings, 625};
void PushResponseLanguageCode(HLERequestContext& ctx, std::size_t num_language_codes) {
IPC::ResponseBuilder rb{ctx, 3};
@@ -130,7 +130,7 @@ void SET::MakeLanguageCode(HLERequestContext& ctx) {
if (index >= available_language_codes.size()) {
LOG_ERROR(Service_SET, "Invalid language code index! index={}", index);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_LANGUAGE);
rb.Push(Set::ResultInvalidLanguage);
return;
}

View File

@@ -18,10 +18,10 @@
namespace Service::SM {
constexpr Result ERR_NOT_INITIALIZED(ErrorModule::SM, 2);
constexpr Result ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
constexpr Result ERR_INVALID_NAME(ErrorModule::SM, 6);
constexpr Result ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
constexpr Result ResultInvalidClient(ErrorModule::SM, 2);
constexpr Result ResultAlreadyRegistered(ErrorModule::SM, 4);
constexpr Result ResultInvalidServiceName(ErrorModule::SM, 6);
constexpr Result ResultNotRegistered(ErrorModule::SM, 7);
ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {
controller_interface = std::make_unique<Controller>(kernel.System());
@@ -45,7 +45,7 @@ void ServiceManager::InvokeControlRequest(HLERequestContext& context) {
static Result ValidateServiceName(const std::string& name) {
if (name.empty() || name.size() > 8) {
LOG_ERROR(Service_SM, "Invalid service name! service={}", name);
return ERR_INVALID_NAME;
return Service::SM::ResultInvalidServiceName;
}
return ResultSuccess;
}
@@ -58,7 +58,7 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
std::scoped_lock lk{lock};
if (registered_services.find(name) != registered_services.end()) {
LOG_ERROR(Service_SM, "Service is already registered! service={}", name);
return ERR_ALREADY_REGISTERED;
return Service::SM::ResultAlreadyRegistered;
}
auto* port = Kernel::KPort::Create(kernel);
@@ -80,7 +80,7 @@ Result ServiceManager::UnregisterService(const std::string& name) {
const auto iter = registered_services.find(name);
if (iter == registered_services.end()) {
LOG_ERROR(Service_SM, "Server is not registered! service={}", name);
return ERR_SERVICE_NOT_REGISTERED;
return Service::SM::ResultNotRegistered;
}
registered_services.erase(iter);
@@ -96,7 +96,7 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
auto it = service_ports.find(name);
if (it == service_ports.end()) {
LOG_WARNING(Service_SM, "Server is not registered! service={}", name);
return ERR_SERVICE_NOT_REGISTERED;
return Service::SM::ResultNotRegistered;
}
return it->second;
@@ -160,7 +160,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) {
ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) {
if (!ctx.GetManager()->GetIsInitializedForSm()) {
return ERR_NOT_INITIALIZED;
return Service::SM::ResultInvalidClient;
}
IPC::RequestParser rp{ctx};
@@ -168,15 +168,15 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) {
// Find the named port.
auto port_result = service_manager.GetServicePort(name);
if (port_result.Code() == ERR_INVALID_NAME) {
if (port_result.Code() == Service::SM::ResultInvalidServiceName) {
LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
return ERR_INVALID_NAME;
return Service::SM::ResultInvalidServiceName;
}
if (port_result.Failed()) {
LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
ctx.SetIsDeferred();
return ERR_SERVICE_NOT_REGISTERED;
return Service::SM::ResultNotRegistered;
}
auto& port = port_result.Unwrap();

View File

@@ -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:

View File

@@ -3,6 +3,7 @@
#include <thread>
#include <fmt/format.h>
#include <math.h>
#include "common/param_package.h"
#include "common/settings.h"
@@ -11,8 +12,9 @@
namespace InputCommon {
constexpr int update_time = 10;
constexpr float default_stick_sensitivity = 0.022f;
constexpr float default_motion_sensitivity = 0.008f;
constexpr float default_stick_sensitivity = 0.0044f;
constexpr float default_motion_sensitivity = 0.0003f;
constexpr float maximum_rotation_speed = 2.0f;
constexpr int mouse_axis_x = 0;
constexpr int mouse_axis_y = 1;
constexpr int wheel_axis_x = 2;
@@ -99,11 +101,13 @@ void Mouse::UpdateMotionInput() {
const float sensitivity =
Settings::values.mouse_panning_sensitivity.GetValue() * default_motion_sensitivity;
// Slow movement by 7%
if (Settings::values.mouse_panning) {
last_motion_change *= 0.93f;
} else {
last_motion_change.z *= 0.93f;
const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x +
last_motion_change.y * last_motion_change.y);
if (rotation_velocity > maximum_rotation_speed / sensitivity) {
const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity;
last_motion_change.x = last_motion_change.x * multiplier;
last_motion_change.y = last_motion_change.y * multiplier;
}
const BasicMotion motion_data{
@@ -116,6 +120,12 @@ void Mouse::UpdateMotionInput() {
.delta_timestamp = update_time * 1000,
};
if (Settings::values.mouse_panning) {
last_motion_change.x = 0;
last_motion_change.y = 0;
}
last_motion_change.z = 0;
SetMotion(motion_identifier, 0, motion_data);
}
@@ -125,7 +135,7 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
auto mouse_change =
(Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
Common::Vec3<float> motion_change{-mouse_change.y, -mouse_change.x, last_motion_change.z};
last_motion_change += {-mouse_change.y, -mouse_change.x, last_motion_change.z};
const auto move_distance = mouse_change.Length();
if (move_distance == 0) {
@@ -141,7 +151,6 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
// Average mouse movements
last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f);
last_motion_change = (last_motion_change * 0.69f) + (motion_change * 0.31f);
const auto last_move_distance = last_mouse_change.Length();

View File

@@ -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

View File

@@ -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;

View File

@@ -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();

View File

@@ -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,7 +95,7 @@ enum class PasivePadButton : u32 {
ZL_ZR = 0x8000,
};
enum class PasivePadStick : u8 {
enum class PassivePadStick : u8 {
Right = 0x00,
RightDown = 0x01,
Down = 0x02,

View File

@@ -48,13 +48,13 @@ void JoyconPoller::ReadPassiveMode(std::span<u8> buffer) {
switch (device_type) {
case ControllerType::Left:
UpdatePasiveLeftPadInput(data);
UpdatePassiveLeftPadInput(data);
break;
case ControllerType::Right:
UpdatePasiveRightPadInput(data);
UpdatePassiveRightPadInput(data);
break;
case ControllerType::Pro:
UpdatePasiveProPadInput(data);
UpdatePassiveProPadInput(data);
break;
default:
break;
@@ -210,12 +210,12 @@ void JoyconPoller::UpdateActiveProPadInput(const InputReportActive& input,
}
}
void JoyconPoller::UpdatePasiveLeftPadInput(const InputReportPassive& input) {
static constexpr std::array<PasivePadButton, 11> left_buttons{
PasivePadButton::Down_A, PasivePadButton::Right_X, PasivePadButton::Left_B,
PasivePadButton::Up_Y, PasivePadButton::SL, PasivePadButton::SR,
PasivePadButton::L_R, PasivePadButton::ZL_ZR, PasivePadButton::Minus,
PasivePadButton::Capture, 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,17 +225,17 @@ void JoyconPoller::UpdatePasiveLeftPadInput(const InputReportPassive& input) {
}
const auto [left_axis_x, left_axis_y] =
GetPassiveAxisValue(static_cast<PasivePadStick>(input.stick_state));
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<PasivePadButton, 11> right_buttons{
PasivePadButton::Down_A, PasivePadButton::Right_X, PasivePadButton::Left_B,
PasivePadButton::Up_Y, PasivePadButton::SL, PasivePadButton::SR,
PasivePadButton::L_R, PasivePadButton::ZL_ZR, PasivePadButton::Plus,
PasivePadButton::Home, 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) {
@@ -245,18 +245,18 @@ void JoyconPoller::UpdatePasiveRightPadInput(const InputReportPassive& input) {
}
const auto [right_axis_x, right_axis_y] =
GetPassiveAxisValue(static_cast<PasivePadStick>(input.stick_state));
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<PasivePadButton, 14> pro_buttons{
PasivePadButton::Down_A, PasivePadButton::Right_X, PasivePadButton::Left_B,
PasivePadButton::Up_Y, PasivePadButton::SL, PasivePadButton::SR,
PasivePadButton::L_R, PasivePadButton::ZL_ZR, PasivePadButton::Minus,
PasivePadButton::Plus, PasivePadButton::Capture, PasivePadButton::Home,
PasivePadButton::StickL, 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) {
@@ -266,9 +266,9 @@ void JoyconPoller::UpdatePasiveProPadInput(const InputReportPassive& input) {
}
const auto [left_axis_x, left_axis_y] =
GetPassiveAxisValue(static_cast<PasivePadStick>(input.stick_state && 0xf));
GetPassiveAxisValue(static_cast<PassivePadStick>(input.stick_state & 0xf));
const auto [right_axis_x, right_axis_y] =
GetPassiveAxisValue(static_cast<PasivePadStick>(input.stick_state >> 4));
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);
@@ -283,25 +283,25 @@ f32 JoyconPoller::GetAxisValue(u16 raw_value, Joycon::JoyStickAxisCalibration ca
return value / calibration.min;
}
std::pair<f32, f32> JoyconPoller::GetPassiveAxisValue(PasivePadStick raw_value) const {
std::pair<f32, f32> JoyconPoller::GetPassiveAxisValue(PassivePadStick raw_value) const {
switch (raw_value) {
case PasivePadStick::Right:
case PassivePadStick::Right:
return {1.0f, 0.0f};
case PasivePadStick::RightDown:
case PassivePadStick::RightDown:
return {1.0f, -1.0f};
case PasivePadStick::Down:
case PassivePadStick::Down:
return {0.0f, -1.0f};
case PasivePadStick::DownLeft:
case PassivePadStick::DownLeft:
return {-1.0f, -1.0f};
case PasivePadStick::Left:
case PassivePadStick::Left:
return {-1.0f, 0.0f};
case PasivePadStick::LeftUp:
case PassivePadStick::LeftUp:
return {-1.0f, 1.0f};
case PasivePadStick::Up:
case PassivePadStick::Up:
return {0.0f, 1.0f};
case PasivePadStick::UpRight:
case PassivePadStick::UpRight:
return {1.0f, 1.0f};
case PasivePadStick::Neutral:
case PassivePadStick::Neutral:
default:
return {0.0f, 0.0f};
}

View File

@@ -46,15 +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, JoyStickAxisCalibration calibration) const;
/// Returns a digital joystick axis from passive axis data
std::pair<f32, f32> GetPassiveAxisValue(PasivePadStick raw_value) const;
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,

View File

@@ -146,6 +146,7 @@ void MappingFactory::RegisterMotion(const MappingData& data) {
if (data.engine == "mouse") {
new_input.Set("motion", 0);
new_input.Set("pad", 1);
new_input.Set("threshold", 0.001f);
input_queue.Push(new_input);
return;
}

View File

@@ -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;
}

View File

@@ -27,7 +27,9 @@ bool GLInnerFence::IsSignaled() const {
return true;
}
ASSERT(sync_object.handle != 0);
return sync_object.IsSignaled();
GLint sync_status;
glGetSynciv(sync_object.handle, GL_SYNC_STATUS, 1, nullptr, &sync_status);
return sync_status == GL_SIGNALED;
}
void GLInnerFence::Wait() {

View File

@@ -621,7 +621,10 @@ bool GraphicsPipeline::IsBuilt() noexcept {
if (built_fence.handle == 0) {
return false;
}
is_built = built_fence.IsSignaled();
// Timeout of zero means this is non-blocking
const auto sync_status = glClientWaitSync(built_fence.handle, 0, 0);
ASSERT(sync_status != GL_WAIT_FAILED);
is_built = sync_status != GL_TIMEOUT_EXPIRED;
return is_built;
}

View File

@@ -3,7 +3,6 @@
#include <string_view>
#include <glad/glad.h>
#include "common/assert.h"
#include "common/microprofile.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
@@ -159,15 +158,6 @@ void OGLSync::Release() {
handle = 0;
}
bool OGLSync::IsSignaled() const noexcept {
// At least on Nvidia, glClientWaitSync with a timeout of 0
// is faster than glGetSynciv of GL_SYNC_STATUS.
// Timeout of 0 means this check is non-blocking.
const auto sync_status = glClientWaitSync(handle, 0, 0);
ASSERT(sync_status != GL_WAIT_FAILED);
return sync_status != GL_TIMEOUT_EXPIRED;
}
void OGLFramebuffer::Create() {
if (handle != 0)
return;

View File

@@ -263,9 +263,6 @@ public:
/// Deletes the internal OpenGL resource
void Release();
/// Checks if the sync has been signaled
bool IsSignaled() const noexcept;
GLsync handle = 0;
};

View File

@@ -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: {
@@ -714,7 +717,9 @@ std::optional<size_t> TextureCacheRuntime::StagingBuffers::FindBuffer(size_t req
continue;
}
if (syncs[index].handle != 0) {
if (!syncs[index].IsSignaled()) {
GLint status;
glGetSynciv(syncs[index].handle, GL_SYNC_STATUS, 1, nullptr, &status);
if (status != GL_SIGNALED) {
continue;
}
syncs[index].Release();

View File

@@ -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);

View File

@@ -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);
});
}

View File

@@ -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,
});
}

View File

@@ -10,6 +10,7 @@
#include "ui_configure_audio.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/uisettings.h"
ConfigureAudio::ConfigureAudio(const Core::System& system_, QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()), system{system_} {
@@ -47,17 +48,22 @@ void ConfigureAudio::SetConfiguration() {
const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
ui->volume_slider->setValue(volume_value);
ui->toggle_background_mute->setChecked(UISettings::values.mute_when_in_background.GetValue());
if (!Settings::IsConfiguringGlobal()) {
if (Settings::values.volume.UsingGlobal()) {
ui->volume_combo_box->setCurrentIndex(0);
ui->volume_slider->setEnabled(false);
ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue());
} else {
ui->volume_combo_box->setCurrentIndex(1);
ui->volume_slider->setEnabled(true);
ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index);
}
ConfigurationShared::SetHighlight(ui->volume_layout,
!Settings::values.volume.UsingGlobal());
ConfigurationShared::SetHighlight(ui->mode_label,
!Settings::values.sound_index.UsingGlobal());
}
SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
}
@@ -109,6 +115,8 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) {
}
void ConfigureAudio::ApplyConfiguration() {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
if (Settings::IsConfiguringGlobal()) {
Settings::values.sink_id =
ui->sink_combo_box->itemText(ui->sink_combo_box->currentIndex()).toStdString();
@@ -116,6 +124,7 @@ void ConfigureAudio::ApplyConfiguration() {
ui->output_combo_box->itemText(ui->output_combo_box->currentIndex()).toStdString());
Settings::values.audio_input_device_id.SetValue(
ui->input_combo_box->itemText(ui->input_combo_box->currentIndex()).toStdString());
UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();
// Guard if during game and set to game-specific value
if (Settings::values.volume.UsingGlobal()) {
@@ -174,10 +183,14 @@ void ConfigureAudio::RetranslateUI() {
void ConfigureAudio::SetupPerGameUI() {
if (Settings::IsConfiguringGlobal()) {
ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal());
// ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal());
return;
}
// ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound,
// Settings::values.sound_index.GetValue(true));
connect(ui->volume_combo_box, qOverload<int>(&QComboBox::activated), this, [this](int index) {
ui->volume_slider->setEnabled(index == 1);
ConfigurationShared::SetHighlight(ui->volume_layout, index == 1);

View File

@@ -39,7 +39,7 @@
<item>
<widget class="QLabel" name="output_label">
<property name="text">
<string>Output Device</string>
<string>Output Device:</string>
</property>
</widget>
</item>
@@ -53,7 +53,7 @@
<item>
<widget class="QLabel" name="input_label">
<property name="text">
<string>Input Device</string>
<string>Input Device:</string>
</property>
</widget>
</item>
@@ -61,6 +61,36 @@
<widget class="QComboBox" name="input_combo_box"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="mode_layout">
<item>
<widget class="QLabel" name="mode_label">
<property name="text">
<string>Sound Ouput Mode:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="combo_sound">
<item>
<property name="text">
<string>Mono</string>
</property>
</item>
<item>
<property name="text">
<string>Stereo</string>
</property>
</item>
<item>
<property name="text">
<string>Surround</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="volume_layout" native="true">
@@ -149,6 +179,17 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="mute_layout">
<item>
<widget class="QCheckBox" name="toggle_background_mute">
<property name="text">
<string>Mute audio when in background</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>

View File

@@ -42,7 +42,6 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue());
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue());
ui->toggle_background_mute->setChecked(UISettings::values.mute_when_in_background.GetValue());
ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue());
ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
@@ -88,7 +87,6 @@ void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();
UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
// Guard if during game and set to game-specific value

View File

@@ -89,13 +89,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_background_mute">
<property name="text">
<string>Mute audio when in background</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_hide_mouse">
<property name="text">

View File

@@ -40,8 +40,6 @@ static bool IsValidLocale(u32 region_index, u32 language_index) {
ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
: QWidget(parent), ui{std::make_unique<Ui::ConfigureSystem>()}, system{system_} {
ui->setupUi(this);
connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
&ConfigureSystem::RefreshConsoleID);
connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](int state) {
ui->rng_seed_edit->setEnabled(state == Qt::Checked);
@@ -76,9 +74,6 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
locale_check);
connect(ui->combo_region, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check);
ui->label_console_id->setVisible(Settings::IsConfiguringGlobal());
ui->button_regenerate_console_id->setVisible(Settings::IsConfiguringGlobal());
SetupPerGameUI();
SetConfiguration();
@@ -121,14 +116,12 @@ void ConfigureSystem::SetConfiguration() {
ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue());
ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue());
ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue());
ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue());
} else {
ConfigurationShared::SetPerGameSetting(ui->combo_language,
&Settings::values.language_index);
ConfigurationShared::SetPerGameSetting(ui->combo_region, &Settings::values.region_index);
ConfigurationShared::SetPerGameSetting(ui->combo_time_zone,
&Settings::values.time_zone_index);
ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index);
ConfigurationShared::SetHighlight(ui->label_language,
!Settings::values.language_index.UsingGlobal());
@@ -136,8 +129,6 @@ void ConfigureSystem::SetConfiguration() {
!Settings::values.region_index.UsingGlobal());
ConfigurationShared::SetHighlight(ui->label_timezone,
!Settings::values.time_zone_index.UsingGlobal());
ConfigurationShared::SetHighlight(ui->label_sound,
!Settings::values.sound_index.UsingGlobal());
}
}
@@ -169,7 +160,6 @@ void ConfigureSystem::ApplyConfiguration() {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index,
ui->combo_time_zone);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
if (Settings::IsConfiguringGlobal()) {
// Guard if during game and set to game-specific value
@@ -202,29 +192,11 @@ void ConfigureSystem::ApplyConfiguration() {
}
}
void ConfigureSystem::RefreshConsoleID() {
QMessageBox::StandardButton reply;
QString warning_text = tr("This will replace your current virtual Switch with a new one. "
"Your current virtual Switch will not be recoverable. "
"This might have unexpected effects in games. This might fail, "
"if you use an outdated config savegame. Continue?");
reply = QMessageBox::critical(this, tr("Warning"), warning_text,
QMessageBox::No | QMessageBox::Yes);
if (reply == QMessageBox::No) {
return;
}
u64 console_id{};
ui->label_console_id->setText(
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
}
void ConfigureSystem::SetupPerGameUI() {
if (Settings::IsConfiguringGlobal()) {
ui->combo_language->setEnabled(Settings::values.language_index.UsingGlobal());
ui->combo_region->setEnabled(Settings::values.region_index.UsingGlobal());
ui->combo_time_zone->setEnabled(Settings::values.time_zone_index.UsingGlobal());
ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal());
ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal());
ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal());
@@ -237,8 +209,6 @@ void ConfigureSystem::SetupPerGameUI() {
Settings::values.region_index.GetValue(true));
ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone,
Settings::values.time_zone_index.GetValue(true));
ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound,
Settings::values.sound_index.GetValue(true));
ConfigurationShared::SetColoredTristate(
ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(),

View File

@@ -35,8 +35,6 @@ private:
void ReadSystemSettings();
void RefreshConsoleID();
void SetupPerGameUI();
std::unique_ptr<Ui::ConfigureSystem> ui;

View File

@@ -411,7 +411,7 @@
</item>
</widget>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QCheckBox" name="custom_rtc_checkbox">
<property name="text">
<string>Custom RTC</string>
@@ -425,54 +425,21 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="5" column="0">
<widget class="QCheckBox" name="rng_seed_checkbox">
<property name="text">
<string>RNG Seed</string>
</property>
</widget>
</item>
<item row="7" column="0">
<item row="6" column="0">
<widget class="QLabel" name="device_name_label">
<property name="text">
<string>Device Name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="combo_sound">
<item>
<property name="text">
<string>Mono</string>
</property>
</item>
<item>
<property name="text">
<string>Stereo</string>
</property>
</item>
<item>
<property name="text">
<string>Surround</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_console_id">
<property name="text">
<string>Console ID:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_sound">
<property name="text">
<string>Sound output mode</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="4" column="1">
<widget class="QDateTimeEdit" name="custom_rtc_edit">
<property name="minimumDate">
<date>
@@ -483,14 +450,14 @@
</property>
</widget>
</item>
<item row="7" column="1">
<item row="6" column="1">
<widget class="QLineEdit" name="device_name_edit">
<property name="maxLength">
<number>128</number>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="5" column="1">
<widget class="QLineEdit" name="rng_seed_edit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -511,22 +478,6 @@
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="button_regenerate_console_id">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Regenerate</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@@ -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();

View File

@@ -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");