diff options
Diffstat (limited to '')
29 files changed, 539 insertions, 231 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f5cf5c16a..7140d0db8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -263,6 +263,8 @@ add_library(core STATIC hle/service/acc/acc_u0.h hle/service/acc/acc_u1.cpp hle/service/acc/acc_u1.h + hle/service/acc/async_context.cpp + hle/service/acc/async_context.h hle/service/acc/errors.h hle/service/acc/profile_manager.cpp hle/service/acc/profile_manager.h @@ -452,6 +454,8 @@ add_library(core STATIC hle/service/nfp/nfp.h hle/service/nfp/nfp_user.cpp hle/service/nfp/nfp_user.h + hle/service/ngct/ngct.cpp + hle/service/ngct/ngct.h hle/service/nifm/nifm.cpp hle/service/nifm/nifm.h hle/service/nim/nim.cpp diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 7e195346b..77efcabf0 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -21,34 +21,25 @@ namespace Core { CpuManager::CpuManager(System& system_) : system{system_} {} CpuManager::~CpuManager() = default; -void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { - cpu_manager.RunThread(core); +void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, + std::size_t core) { + cpu_manager.RunThread(stop_token, core); } void CpuManager::Initialize() { running_mode = true; if (is_multicore) { for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { - core_data[core].host_thread = - std::make_unique<std::thread>(ThreadStart, std::ref(*this), core); + core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); } } else { - core_data[0].host_thread = std::make_unique<std::thread>(ThreadStart, std::ref(*this), 0); + core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0); } } void CpuManager::Shutdown() { running_mode = false; Pause(false); - if (is_multicore) { - for (auto& data : core_data) { - data.host_thread->join(); - data.host_thread.reset(); - } - } else { - core_data[0].host_thread->join(); - core_data[0].host_thread.reset(); - } } std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { @@ -317,7 +308,7 @@ void CpuManager::Pause(bool paused) { } } -void CpuManager::RunThread(std::size_t core) { +void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { /// Initialization system.RegisterCoreThread(core); std::string name; @@ -361,6 +352,10 @@ void CpuManager::RunThread(std::size_t core) { return; } + if (stop_token.stop_requested()) { + break; + } + auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); data.is_running = true; Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext()); diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 140263b09..9d92d4af0 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -78,9 +78,9 @@ private: void SingleCoreRunSuspendThread(); void SingleCorePause(bool paused); - static void ThreadStart(CpuManager& cpu_manager, std::size_t core); + static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core); - void RunThread(std::size_t core); + void RunThread(std::stop_token stop_token, std::size_t core); struct CoreData { std::shared_ptr<Common::Fiber> host_context; @@ -89,7 +89,7 @@ private: std::atomic<bool> is_running; std::atomic<bool> is_paused; std::atomic<bool> initialized; - std::unique_ptr<std::thread> host_thread; + std::jthread host_thread; }; std::atomic<bool> running_mode{}; diff --git a/src/core/file_sys/kernel_executable.h b/src/core/file_sys/kernel_executable.h index 044c554d3..79ca82f8b 100644 --- a/src/core/file_sys/kernel_executable.h +++ b/src/core/file_sys/kernel_executable.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <string> #include <vector> #include "common/common_funcs.h" diff --git a/src/core/hle/api_version.h b/src/core/hle/api_version.h index 43d5670a9..626e30753 100644 --- a/src/core/hle/api_version.h +++ b/src/core/hle/api_version.h @@ -28,13 +28,20 @@ constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0"; // Atmosphere version constants. -constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0; -constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19; -constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 5; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 1; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 0; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 0; + +constexpr u32 AtmosphereTargetFirmwareWithRevision(u8 major, u8 minor, u8 micro, u8 rev) { + return u32{major} << 24 | u32{minor} << 16 | u32{micro} << 8 | u32{rev}; +} + +constexpr u32 AtmosphereTargetFirmware(u8 major, u8 minor, u8 micro) { + return AtmosphereTargetFirmwareWithRevision(major, minor, micro, 0); +} constexpr u32 GetTargetFirmware() { - return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 | - u32{HOS_VERSION_MICRO} << 8 | 0U; + return AtmosphereTargetFirmware(HOS_VERSION_MAJOR, HOS_VERSION_MINOR, HOS_VERSION_MICRO); } } // namespace HLE::ApiVersion diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3a6db0b1c..901d43da9 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <functional> #include <memory> #include <string> #include <unordered_map> diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 882fc1492..6d9ec0a8a 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -23,6 +23,7 @@ #include "core/hle/service/acc/acc_su.h" #include "core/hle/service/acc/acc_u0.h" #include "core/hle/service/acc/acc_u1.h" +#include "core/hle/service/acc/async_context.h" #include "core/hle/service/acc/errors.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/glue/arp.h" @@ -454,22 +455,6 @@ public: : IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {} }; -class IAsyncContext final : public ServiceFramework<IAsyncContext> { -public: - explicit IAsyncContext(Core::System& system_) : ServiceFramework{system_, "IAsyncContext"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetSystemEvent"}, - {1, nullptr, "Cancel"}, - {2, nullptr, "HasDone"}, - {3, nullptr, "GetResult"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - class ISessionObject final : public ServiceFramework<ISessionObject> { public: explicit ISessionObject(Core::System& system_, Common::UUID) @@ -504,16 +489,44 @@ public: } }; +class EnsureTokenIdCacheAsyncInterface final : public IAsyncContext { +public: + explicit EnsureTokenIdCacheAsyncInterface(Core::System& system_) : IAsyncContext{system_} { + MarkComplete(); + } + ~EnsureTokenIdCacheAsyncInterface() = default; + + void LoadIdTokenCache(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + +protected: + bool IsComplete() const override { + return true; + } + + void Cancel() override {} + + ResultCode GetResult() const override { + return ResultSuccess; + } +}; + class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { public: explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_) - : ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} { + : ServiceFramework{system_, "IManagerForApplication"}, + ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)}, + user_id{user_id_} { // clang-format off static const FunctionInfo functions[] = { {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, {1, &IManagerForApplication::GetAccountId, "GetAccountId"}, - {2, nullptr, "EnsureIdTokenCacheAsync"}, - {3, nullptr, "LoadIdTokenCache"}, + {2, &IManagerForApplication::EnsureIdTokenCacheAsync, "EnsureIdTokenCacheAsync"}, + {3, &IManagerForApplication::LoadIdTokenCache, "LoadIdTokenCache"}, {130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"}, {150, nullptr, "CreateAuthorizationRequest"}, {160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"}, @@ -540,6 +553,20 @@ private: rb.PushRaw<u64>(user_id.GetNintendoID()); } + void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(ensure_token_id); + } + + void LoadIdTokenCache(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + + ensure_token_id->LoadIdTokenCache(ctx); + } + void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); @@ -562,6 +589,7 @@ private: rb.Push(ResultSuccess); } + std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{}; Common::UUID user_id{Common::INVALID_UUID}; }; diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp new file mode 100644 index 000000000..459323132 --- /dev/null +++ b/src/core/hle/service/acc/async_context.cpp @@ -0,0 +1,68 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/core.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/acc/async_context.h" + +namespace Service::Account { +IAsyncContext::IAsyncContext(Core::System& system_) + : ServiceFramework{system_, "IAsyncContext"}, compeletion_event{system_.Kernel()} { + + Kernel::KAutoObject::Create(std::addressof(compeletion_event)); + compeletion_event.Initialize("IAsyncContext:CompletionEvent"); + + // clang-format off + static const FunctionInfo functions[] = { + {0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"}, + {1, &IAsyncContext::Cancel, "Cancel"}, + {2, &IAsyncContext::HasDone, "HasDone"}, + {3, &IAsyncContext::GetResult, "GetResult"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(compeletion_event.GetReadableEvent()); +} + +void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + Cancel(); + MarkComplete(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + is_complete.store(IsComplete()); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(is_complete.load()); +} + +void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(GetResult()); +} + +void IAsyncContext::MarkComplete() { + is_complete.store(true); + compeletion_event.GetWritableEvent().Signal(); +} + +} // namespace Service::Account diff --git a/src/core/hle/service/acc/async_context.h b/src/core/hle/service/acc/async_context.h new file mode 100644 index 000000000..c694b4946 --- /dev/null +++ b/src/core/hle/service/acc/async_context.h @@ -0,0 +1,37 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <atomic> +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Account { + +class IAsyncContext : public ServiceFramework<IAsyncContext> { +public: + explicit IAsyncContext(Core::System& system_); + + void GetSystemEvent(Kernel::HLERequestContext& ctx); + void Cancel(Kernel::HLERequestContext& ctx); + void HasDone(Kernel::HLERequestContext& ctx); + void GetResult(Kernel::HLERequestContext& ctx); + +protected: + virtual bool IsComplete() const = 0; + virtual void Cancel() = 0; + virtual ResultCode GetResult() const = 0; + + void MarkComplete(); + + std::atomic<bool> is_complete{false}; + Kernel::KEvent compeletion_event; +}; + +} // namespace Service::Account diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a538f82e3..c3ac73131 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1270,7 +1270,8 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) IApplicationFunctions::IApplicationFunctions(Core::System& system_) : ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()}, friend_invitation_storage_channel_event{system.Kernel()}, - health_warning_disappeared_system_event{system.Kernel()} { + notification_storage_channel_event{system.Kernel()}, health_warning_disappeared_system_event{ + system.Kernel()} { // clang-format off static const FunctionInfo functions[] = { {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, @@ -1322,7 +1323,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, - {150, nullptr, "GetNotificationStorageChannelEvent"}, + {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, {151, nullptr, "TryPopFromNotificationStorageChannel"}, {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, {170, nullptr, "SetHdcpAuthenticationActivated"}, @@ -1340,11 +1341,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event)); Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event)); + Kernel::KAutoObject::Create(std::addressof(notification_storage_channel_event)); Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event)); gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent"); friend_invitation_storage_channel_event.Initialize( "IApplicationFunctions:FriendInvitationStorageChannelEvent"); + notification_storage_channel_event.Initialize( + "IApplicationFunctions:NotificationStorageChannelEvent"); health_warning_disappeared_system_event.Initialize( "IApplicationFunctions:HealthWarningDisappearedSystemEvent"); } @@ -1762,6 +1766,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( rb.Push(ERR_NO_DATA_IN_CHANNEL); } +void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(notification_storage_channel_event.GetReadableEvent()); +} + void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 184030a8e..c13aa5787 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -295,6 +295,7 @@ private: void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); + void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx); void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx); bool launch_popped_application_specific = false; @@ -302,6 +303,7 @@ private: s32 previous_program_index{-1}; Kernel::KEvent gpu_error_detected_event; Kernel::KEvent friend_invitation_storage_channel_event; + Kernel::KEvent notification_storage_channel_event; Kernel::KEvent health_warning_disappeared_system_event; }; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 4a9b13e45..c8d65f328 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -97,14 +97,24 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { std::string path(Common::FS::SanitizePath(path_)); - auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); - if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) { - dir = backing; - } - auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path)); - if (new_dir == nullptr) { - // TODO(DarkLordZach): Find a better error code for this - return ResultUnknown; + + // NOTE: This is inaccurate behavior. CreateDirectory is not recursive. + // CreateDirectory should return PathNotFound if the parent directory does not exist. + // This is here temporarily in order to have UMM "work" in the meantime. + // TODO (Morph): Remove this when a hardware test verifies the correct behavior. + const auto components = Common::FS::SplitPathComponents(path); + std::string relative_path; + for (const auto& component : components) { + // Skip empty path components + if (component.empty()) { + continue; + } + relative_path = Common::FS::SanitizePath(relative_path + '/' + component); + auto new_dir = backing->CreateSubdirectory(relative_path); + if (new_dir == nullptr) { + // TODO(DarkLordZach): Find a better error code for this + return ResultUnknown; + } } return ResultSuccess; } diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index ef2becefd..8e9b40c0a 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -15,6 +15,20 @@ namespace Service::HID { class Controller_Touchscreen final : public ControllerBase { public: + enum class TouchScreenModeForNx : u8 { + UseSystemSetting, + Finger, + Heat2, + }; + + struct TouchScreenConfigurationForNx { + TouchScreenModeForNx mode; + INSERT_PADDING_BYTES_NOINIT(0x7); + INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved + }; + static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17, + "TouchScreenConfigurationForNx is an invalid size"); + explicit Controller_Touchscreen(Core::System& system_); ~Controller_Touchscreen() override; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index b8b80570d..a1707a72a 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -331,7 +331,7 @@ Hid::Hid(Core::System& system_) {529, nullptr, "SetDisallowedPalmaConnection"}, {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"}, {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"}, - {1002, nullptr, "SetTouchScreenConfiguration"}, + {1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"}, {1003, nullptr, "IsFirmwareUpdateNeededForNotification"}, {2000, nullptr, "ActivateDigitizer"}, }; @@ -1631,6 +1631,18 @@ void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { .GetNpadCommunicationMode()); } +void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}", + touchscreen_mode.mode, applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + class HidDbg final : public ServiceFramework<HidDbg> { public: explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 9c5c7f252..b1fe75e94 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -159,6 +159,7 @@ private: void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx); void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); + void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx); enum class VibrationDeviceType : u32 { Unknown = 0, diff --git a/src/core/hle/service/ngct/ngct.cpp b/src/core/hle/service/ngct/ngct.cpp new file mode 100644 index 000000000..deb3abb28 --- /dev/null +++ b/src/core/hle/service/ngct/ngct.cpp @@ -0,0 +1,46 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include "common/string_util.h" +#include "core/core.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/ngct/ngct.h" +#include "core/hle/service/service.h" + +namespace Service::NGCT { + +class IService final : public ServiceFramework<IService> { +public: + explicit IService(Core::System& system_) : ServiceFramework{system_, "ngct:u"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "Match"}, + {1, &IService::Filter, "Filter"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void Filter(Kernel::HLERequestContext& ctx) { + const auto buffer = ctx.ReadBuffer(); + const auto text = Common::StringFromFixedZeroTerminatedBuffer( + reinterpret_cast<const char*>(buffer.data()), buffer.size()); + + LOG_WARNING(Service_NGCT, "(STUBBED) called, text={}", text); + + // Return the same string since we don't censor anything + ctx.WriteBuffer(buffer); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } +}; + +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { + std::make_shared<IService>(system)->InstallAsService(system.ServiceManager()); +} + +} // namespace Service::NGCT diff --git a/src/core/hle/service/ngct/ngct.h b/src/core/hle/service/ngct/ngct.h new file mode 100644 index 000000000..1f2a47b78 --- /dev/null +++ b/src/core/hle/service/ngct/ngct.h @@ -0,0 +1,20 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#pragma once + +namespace Core { +class System; +} + +namespace Service::SM { +class ServiceManager; +} + +namespace Service::NGCT { + +/// Registers all NGCT services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); + +} // namespace Service::NGCT diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 0a53c0c81..9decb9290 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -277,37 +277,45 @@ private: void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); - const SfNetworkProfileData network_profile_data{ - .ip_setting_data{ - .ip_address_setting{ - .is_automatic{true}, - .current_address{192, 168, 1, 100}, - .subnet_mask{255, 255, 255, 0}, - .gateway{192, 168, 1, 1}, - }, - .dns_setting{ - .is_automatic{true}, - .primary_dns{1, 1, 1, 1}, - .secondary_dns{1, 0, 0, 1}, + const auto net_iface = Network::GetSelectedNetworkInterface(); + + const SfNetworkProfileData network_profile_data = [&net_iface] { + if (!net_iface) { + return SfNetworkProfileData{}; + } + + return SfNetworkProfileData{ + .ip_setting_data{ + .ip_address_setting{ + .is_automatic{true}, + .current_address{Network::TranslateIPv4(net_iface->ip_address)}, + .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, + .gateway{Network::TranslateIPv4(net_iface->gateway)}, + }, + .dns_setting{ + .is_automatic{true}, + .primary_dns{1, 1, 1, 1}, + .secondary_dns{1, 0, 0, 1}, + }, + .proxy_setting{ + .enabled{false}, + .port{}, + .proxy_server{}, + .automatic_auth_enabled{}, + .user{}, + .password{}, + }, + .mtu{1500}, }, - .proxy_setting{ - .enabled{false}, - .port{}, - .proxy_server{}, - .automatic_auth_enabled{}, - .user{}, - .password{}, + .uuid{0xdeadbeef, 0xdeadbeef}, + .network_name{"yuzu Network"}, + .wireless_setting_data{ + .ssid_length{12}, + .ssid{"yuzu Network"}, + .passphrase{"yuzupassword"}, }, - .mtu{1500}, - }, - .uuid{0xdeadbeef, 0xdeadbeef}, - .network_name{"yuzu Network"}, - .wireless_setting_data{ - .ssid_length{12}, - .ssid{"yuzu Network"}, - .passphrase{"yuzupassword"}, - }, - }; + }; + }(); ctx.WriteBuffer(network_profile_data); @@ -352,38 +360,33 @@ private: LOG_WARNING(Service_NIFM, "(STUBBED) called"); struct IpConfigInfo { - IpAddressSetting ip_address_setting; - DnsSetting dns_setting; + IpAddressSetting ip_address_setting{}; + DnsSetting dns_setting{}; }; static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), "IpConfigInfo has incorrect size."); - IpConfigInfo ip_config_info{ - .ip_address_setting{ - .is_automatic{true}, - .current_address{0, 0, 0, 0}, - .subnet_mask{255, 255, 255, 0}, - .gateway{192, 168, 1, 1}, - }, - .dns_setting{ - .is_automatic{true}, - .primary_dns{1, 1, 1, 1}, - .secondary_dns{1, 0, 0, 1}, - }, - }; + const auto net_iface = Network::GetSelectedNetworkInterface(); - const auto iface = Network::GetSelectedNetworkInterface(); - if (iface) { - ip_config_info.ip_address_setting = - IpAddressSetting{.is_automatic{true}, - .current_address{Network::TranslateIPv4(iface->ip_address)}, - .subnet_mask{Network::TranslateIPv4(iface->subnet_mask)}, - .gateway{Network::TranslateIPv4(iface->gateway)}}; + const IpConfigInfo ip_config_info = [&net_iface] { + if (!net_iface) { + return IpConfigInfo{}; + } - } else { - LOG_ERROR(Service_NIFM, - "Couldn't get host network configuration info, using default values"); - } + return IpConfigInfo{ + .ip_address_setting{ + .is_automatic{true}, + .current_address{Network::TranslateIPv4(net_iface->ip_address)}, + .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, + .gateway{Network::TranslateIPv4(net_iface->gateway)}, + }, + .dns_setting{ + .is_automatic{true}, + .primary_dns{1, 1, 1, 1}, + .secondary_dns{1, 0, 0, 1}, + }, + }; + }(); IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index ce6065db2..a33e47d0b 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -42,15 +42,14 @@ void nvdisp_disp0::OnClose(DeviceFD fd) {} void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform, const Common::Rectangle<int>& crop_rect) { - VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); + const VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); LOG_TRACE(Service, "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", addr, offset, width, height, stride, format); - using PixelFormat = Tegra::FramebufferConfig::PixelFormat; - const Tegra::FramebufferConfig framebuffer{ - addr, offset, width, height, stride, static_cast<PixelFormat>(format), - transform, crop_rect}; + const auto pixel_format = static_cast<Tegra::FramebufferConfig::PixelFormat>(format); + const Tegra::FramebufferConfig framebuffer{addr, offset, width, height, + stride, pixel_format, transform, crop_rect}; system.GetPerfStats().EndSystemFrame(); system.GPU().SwapBuffers(&framebuffer); diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 59ddf6298..b4c3a6099 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -9,17 +9,20 @@ #include "core/core.h" #include "core/hle/kernel/k_writable_event.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvflinger/buffer_queue.h" namespace Service::NVFlinger { -BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_) - : id(id_), layer_id(layer_id_), buffer_wait_event{kernel} { - Kernel::KAutoObject::Create(std::addressof(buffer_wait_event)); - buffer_wait_event.Initialize("BufferQueue:WaitEvent"); +BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_, + KernelHelpers::ServiceContext& service_context_) + : id(id_), layer_id(layer_id_), service_context{service_context_} { + buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent"); } -BufferQueue::~BufferQueue() = default; +BufferQueue::~BufferQueue() { + service_context.CloseEvent(buffer_wait_event); +} void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) { ASSERT(slot < buffer_slots); @@ -41,7 +44,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) .multi_fence = {}, }; - buffer_wait_event.GetWritableEvent().Signal(); + buffer_wait_event->GetWritableEvent().Signal(); } std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, @@ -119,7 +122,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult } free_buffers_condition.notify_one(); - buffer_wait_event.GetWritableEvent().Signal(); + buffer_wait_event->GetWritableEvent().Signal(); } std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { @@ -154,7 +157,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) { } free_buffers_condition.notify_one(); - buffer_wait_event.GetWritableEvent().Signal(); + buffer_wait_event->GetWritableEvent().Signal(); } void BufferQueue::Connect() { @@ -169,7 +172,7 @@ void BufferQueue::Disconnect() { std::unique_lock lock{queue_sequence_mutex}; queue_sequence.clear(); } - buffer_wait_event.GetWritableEvent().Signal(); + buffer_wait_event->GetWritableEvent().Signal(); is_connect = false; free_buffers_condition.notify_one(); } @@ -189,11 +192,11 @@ u32 BufferQueue::Query(QueryType type) { } Kernel::KWritableEvent& BufferQueue::GetWritableBufferWaitEvent() { - return buffer_wait_event.GetWritableEvent(); + return buffer_wait_event->GetWritableEvent(); } Kernel::KReadableEvent& BufferQueue::GetBufferWaitEvent() { - return buffer_wait_event.GetReadableEvent(); + return buffer_wait_event->GetReadableEvent(); } } // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 61e337ac5..78de3f354 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -24,6 +24,10 @@ class KReadableEvent; class KWritableEvent; } // namespace Kernel +namespace Service::KernelHelpers { +class ServiceContext; +} // namespace Service::KernelHelpers + namespace Service::NVFlinger { constexpr u32 buffer_slots = 0x40; @@ -38,7 +42,9 @@ struct IGBPBuffer { u32_le index; INSERT_PADDING_WORDS(3); u32_le gpu_buffer_id; - INSERT_PADDING_WORDS(17); + INSERT_PADDING_WORDS(6); + u32_le external_format; + INSERT_PADDING_WORDS(10); u32_le nvmap_handle; u32_le offset; INSERT_PADDING_WORDS(60); @@ -54,7 +60,8 @@ public: NativeWindowFormat = 2, }; - explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_); + explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_, + KernelHelpers::ServiceContext& service_context_); ~BufferQueue(); enum class BufferTransformFlags : u32 { @@ -130,12 +137,14 @@ private: std::list<u32> free_buffers; std::array<Buffer, buffer_slots> buffers; std::list<u32> queue_sequence; - Kernel::KEvent buffer_wait_event; + Kernel::KEvent* buffer_wait_event{}; std::mutex free_buffers_mutex; std::condition_variable free_buffers_condition; std::mutex queue_sequence_mutex; + + KernelHelpers::ServiceContext& service_context; }; } // namespace Service::NVFlinger diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 941748970..3ead813b0 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -61,12 +61,13 @@ void NVFlinger::SplitVSync() { } } -NVFlinger::NVFlinger(Core::System& system_) : system(system_) { - displays.emplace_back(0, "Default", system); - displays.emplace_back(1, "External", system); - displays.emplace_back(2, "Edid", system); - displays.emplace_back(3, "Internal", system); - displays.emplace_back(4, "Null", system); +NVFlinger::NVFlinger(Core::System& system_) + : system(system_), service_context(system_, "nvflinger") { + displays.emplace_back(0, "Default", service_context, system); + displays.emplace_back(1, "External", service_context, system); + displays.emplace_back(2, "Edid", service_context, system); + displays.emplace_back(3, "Internal", service_context, system); + displays.emplace_back(4, "Null", service_context, system); guard = std::make_shared<std::mutex>(); // Schedule the screen composition events @@ -146,7 +147,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { const u32 buffer_queue_id = next_buffer_queue_id++; buffer_queues.emplace_back( - std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id)); + std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id, service_context)); display.CreateLayer(layer_id, *buffer_queues.back()); } @@ -297,7 +298,7 @@ void NVFlinger::Compose() { auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); ASSERT(nvdisp); - nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, + nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.external_format, igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->get().transform, buffer->get().crop_rect); diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index d80fd07ef..6d84cafb4 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -15,6 +15,7 @@ #include <vector> #include "common/common_types.h" +#include "core/hle/service/kernel_helpers.h" namespace Common { class Event; @@ -135,6 +136,8 @@ private: std::unique_ptr<std::thread> vsync_thread; std::unique_ptr<Common::Event> wait_event; std::atomic<bool> is_running{}; + + KernelHelpers::ServiceContext service_context; }; } // namespace Service::NVFlinger diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index b3e50433b..065133166 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -46,6 +46,7 @@ #include "core/hle/service/ncm/ncm.h" #include "core/hle/service/nfc/nfc.h" #include "core/hle/service/nfp/nfp.h" +#include "core/hle/service/ngct/ngct.h" #include "core/hle/service/nifm/nifm.h" #include "core/hle/service/nim/nim.h" #include "core/hle/service/npns/npns.h" @@ -271,6 +272,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system NCM::InstallInterfaces(*sm, system); NFC::InstallInterfaces(*sm, system); NFP::InstallInterfaces(*sm, system); + NGCT::InstallInterfaces(*sm, system); NIFM::InstallInterfaces(*sm, system); NIM::InstallInterfaces(*sm, system); NPNS::InstallInterfaces(*sm, system); diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 0dd342dbf..b7705c02a 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -12,18 +12,21 @@ #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_writable_event.h" +#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/vi/display/vi_display.h" #include "core/hle/service/vi/layer/vi_layer.h" namespace Service::VI { -Display::Display(u64 id, std::string name_, Core::System& system) - : display_id{id}, name{std::move(name_)}, vsync_event{system.Kernel()} { - Kernel::KAutoObject::Create(std::addressof(vsync_event)); - vsync_event.Initialize(fmt::format("Display VSync Event {}", id)); +Display::Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_, + Core::System& system_) + : display_id{id}, name{std::move(name_)}, service_context{service_context_} { + vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id)); } -Display::~Display() = default; +Display::~Display() { + service_context.CloseEvent(vsync_event); +} Layer& Display::GetLayer(std::size_t index) { return *layers.at(index); @@ -34,11 +37,11 @@ const Layer& Display::GetLayer(std::size_t index) const { } Kernel::KReadableEvent& Display::GetVSyncEvent() { - return vsync_event.GetReadableEvent(); + return vsync_event->GetReadableEvent(); } void Display::SignalVSyncEvent() { - vsync_event.GetWritableEvent().Signal(); + vsync_event->GetWritableEvent().Signal(); } void Display::CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue) { diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 166f2a4cc..0979fc421 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h @@ -18,6 +18,9 @@ class KEvent; namespace Service::NVFlinger { class BufferQueue; } +namespace Service::KernelHelpers { +class ServiceContext; +} // namespace Service::KernelHelpers namespace Service::VI { @@ -31,10 +34,13 @@ class Display { public: /// Constructs a display with a given unique ID and name. /// - /// @param id The unique ID for this display. + /// @param id The unique ID for this display. + /// @param service_context_ The ServiceContext for the owning service. /// @param name_ The name for this display. + /// @param system_ The global system instance. /// - Display(u64 id, std::string name_, Core::System& system); + Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_, + Core::System& system_); ~Display(); /// Gets the unique ID assigned to this display. @@ -98,9 +104,10 @@ public: private: u64 display_id; std::string name; + KernelHelpers::ServiceContext& service_context; std::vector<std::shared_ptr<Layer>> layers; - Kernel::KEvent vsync_event; + Kernel::KEvent* vsync_event{}; }; } // namespace Service::VI diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp index 4732d4485..72eea52f0 100644 --- a/src/core/network/network.cpp +++ b/src/core/network/network.cpp @@ -7,7 +7,8 @@ #include <limits> #include <utility> #include <vector> -#include "common/common_funcs.h" + +#include "common/error.h" #ifdef _WIN32 #include <winsock2.h> @@ -223,7 +224,7 @@ Errno GetAndLogLastError() { if (err == Errno::AGAIN) { return err; } - LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e)); + LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); return err; } diff --git a/src/core/network/network_interface.cpp b/src/core/network/network_interface.cpp index cecc9aa11..6811f21b1 100644 --- a/src/core/network/network_interface.cpp +++ b/src/core/network/network_interface.cpp @@ -37,73 +37,73 @@ std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { AF_INET, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS, nullptr, adapter_addresses.data(), &buf_size); - if (ret == ERROR_BUFFER_OVERFLOW) { - adapter_addresses.resize((buf_size / sizeof(IP_ADAPTER_ADDRESSES)) + 1); - } else { + if (ret != ERROR_BUFFER_OVERFLOW) { break; } + + adapter_addresses.resize((buf_size / sizeof(IP_ADAPTER_ADDRESSES)) + 1); } - if (ret == NO_ERROR) { - std::vector<NetworkInterface> result; + if (ret != NO_ERROR) { + LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses"); + return {}; + } - for (auto current_address = adapter_addresses.data(); current_address != nullptr; - current_address = current_address->Next) { - if (current_address->FirstUnicastAddress == nullptr || - current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) { - continue; - } + std::vector<NetworkInterface> result; - if (current_address->OperStatus != IfOperStatusUp) { - continue; - } + for (auto current_address = adapter_addresses.data(); current_address != nullptr; + current_address = current_address->Next) { + if (current_address->FirstUnicastAddress == nullptr || + current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) { + continue; + } - const auto ip_addr = Common::BitCast<struct sockaddr_in>( - *current_address->FirstUnicastAddress->Address.lpSockaddr) - .sin_addr; + if (current_address->OperStatus != IfOperStatusUp) { + continue; + } - ULONG mask = 0; - if (ConvertLengthToIpv4Mask(current_address->FirstUnicastAddress->OnLinkPrefixLength, - &mask) != NO_ERROR) { - LOG_ERROR(Network, "Failed to convert IPv4 prefix length to subnet mask"); - continue; - } + const auto ip_addr = Common::BitCast<struct sockaddr_in>( + *current_address->FirstUnicastAddress->Address.lpSockaddr) + .sin_addr; - struct in_addr gateway = {.S_un{.S_addr{0}}}; - if (current_address->FirstGatewayAddress != nullptr && - current_address->FirstGatewayAddress->Address.lpSockaddr != nullptr) { - gateway = Common::BitCast<struct sockaddr_in>( - *current_address->FirstGatewayAddress->Address.lpSockaddr) - .sin_addr; - } + ULONG mask = 0; + if (ConvertLengthToIpv4Mask(current_address->FirstUnicastAddress->OnLinkPrefixLength, + &mask) != NO_ERROR) { + LOG_ERROR(Network, "Failed to convert IPv4 prefix length to subnet mask"); + continue; + } - result.push_back(NetworkInterface{ - .name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})}, - .ip_address{ip_addr}, - .subnet_mask = in_addr{.S_un{.S_addr{mask}}}, - .gateway = gateway}); + struct in_addr gateway = {.S_un{.S_addr{0}}}; + if (current_address->FirstGatewayAddress != nullptr && + current_address->FirstGatewayAddress->Address.lpSockaddr != nullptr) { + gateway = Common::BitCast<struct sockaddr_in>( + *current_address->FirstGatewayAddress->Address.lpSockaddr) + .sin_addr; } - return result; - } else { - LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses"); - return {}; + result.emplace_back(NetworkInterface{ + .name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})}, + .ip_address{ip_addr}, + .subnet_mask = in_addr{.S_un{.S_addr{mask}}}, + .gateway = gateway}); } + + return result; } #else std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { - std::vector<NetworkInterface> result; - struct ifaddrs* ifaddr = nullptr; if (getifaddrs(&ifaddr) != 0) { LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}", std::strerror(errno)); - return result; + return {}; } + std::vector<NetworkInterface> result; + for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) { continue; @@ -117,55 +117,62 @@ std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { continue; } - std::uint32_t gateway{0}; + u32 gateway{}; + std::ifstream file{"/proc/net/route"}; - if (file.is_open()) { + if (!file.is_open()) { + LOG_ERROR(Network, "Failed to open \"/proc/net/route\""); - // ignore header - file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); + result.emplace_back(NetworkInterface{ + .name{ifa->ifa_name}, + .ip_address{Common::BitCast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr}, + .subnet_mask{Common::BitCast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr}, + .gateway{in_addr{.s_addr = gateway}}}); + continue; + } - bool gateway_found = false; + // ignore header + file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); - for (std::string line; std::getline(file, line);) { - std::istringstream iss{line}; + bool gateway_found = false; - std::string iface_name{}; - iss >> iface_name; - if (iface_name != ifa->ifa_name) { - continue; - } + for (std::string line; std::getline(file, line);) { + std::istringstream iss{line}; - iss >> std::hex; + std::string iface_name; + iss >> iface_name; + if (iface_name != ifa->ifa_name) { + continue; + } - std::uint32_t dest{0}; - iss >> dest; - if (dest != 0) { - // not the default route - continue; - } + iss >> std::hex; - iss >> gateway; + u32 dest{}; + iss >> dest; + if (dest != 0) { + // not the default route + continue; + } - std::uint16_t flags{0}; - iss >> flags; + iss >> gateway; - // flag RTF_GATEWAY (defined in <linux/route.h>) - if ((flags & 0x2) == 0) { - continue; - } + u16 flags{}; + iss >> flags; - gateway_found = true; - break; + // flag RTF_GATEWAY (defined in <linux/route.h>) + if ((flags & 0x2) == 0) { + continue; } - if (!gateway_found) { - gateway = 0; - } - } else { - LOG_ERROR(Network, "Failed to open \"/proc/net/route\""); + gateway_found = true; + break; } - result.push_back(NetworkInterface{ + if (!gateway_found) { + gateway = 0; + } + + result.emplace_back(NetworkInterface{ .name{ifa->ifa_name}, .ip_address{Common::BitCast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr}, .subnet_mask{Common::BitCast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr}, @@ -180,11 +187,11 @@ std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { #endif std::optional<NetworkInterface> GetSelectedNetworkInterface() { - const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); + const auto& selected_network_interface = Settings::values.network_interface.GetValue(); const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); if (network_interfaces.size() == 0) { LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces"); - return {}; + return std::nullopt; } const auto res = @@ -192,12 +199,12 @@ std::optional<NetworkInterface> GetSelectedNetworkInterface() { return iface.name == selected_network_interface; }); - if (res != network_interfaces.end()) { - return *res; - } else { + if (res == network_interfaces.end()) { LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); - return {}; + return std::nullopt; } + + return *res; } } // namespace Network diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 5a8cfd301..1f1607998 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -72,6 +72,18 @@ static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) { return "Unknown"; } +static const char* TranslateNvdecEmulation(Settings::NvdecEmulation backend) { + switch (backend) { + case Settings::NvdecEmulation::Off: + return "Off"; + case Settings::NvdecEmulation::CPU: + return "CPU"; + case Settings::NvdecEmulation::GPU: + return "GPU"; + } + return "Unknown"; +} + u64 GetTelemetryId() { u64 telemetry_id{}; const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id"; @@ -229,8 +241,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue())); AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", Settings::values.use_asynchronous_gpu_emulation.GetValue()); - AddField(field_type, "Renderer_UseNvdecEmulation", - Settings::values.use_nvdec_emulation.GetValue()); + AddField(field_type, "Renderer_NvdecEmulation", + TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue())); AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue()); AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); AddField(field_type, "Renderer_ShaderBackend", |