diff options
Diffstat (limited to 'src/core/hle/service')
307 files changed, 14115 insertions, 11740 deletions
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 29a10ad13..ee9795532 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -329,9 +329,8 @@ bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& /// Returns if the system is allowing user registrations or not bool ProfileManager::CanSystemRegisterUser() const { - return false; // TODO(ogniK): Games shouldn't have - // access to user registration, when we - // emulate qlaunch. Update this to dynamically change. + // TODO: Both games and applets can register users. Determine when this condition is not meet. + return true; } bool ProfileManager::RemoveUser(UUID uuid) { diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 8f90eba34..8c4e14f08 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -2,25 +2,19 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/am/am.h" -#include "core/hle/service/am/applet_ae.h" -#include "core/hle/service/am/applet_oe.h" -#include "core/hle/service/am/idle.h" -#include "core/hle/service/am/omm.h" -#include "core/hle/service/am/spsm.h" +#include "core/hle/service/am/service/all_system_applet_proxies_service.h" +#include "core/hle/service/am/service/application_proxy_service.h" #include "core/hle/service/server_manager.h" namespace Service::AM { -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { +void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); server_manager->RegisterNamedService("appletAE", - std::make_shared<AppletAE>(nvnflinger, system)); + std::make_shared<IAllSystemAppletProxiesService>(system)); server_manager->RegisterNamedService("appletOE", - std::make_shared<AppletOE>(nvnflinger, system)); - server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system)); - server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system)); - server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system)); + std::make_shared<IApplicationProxyService>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 4a2d797bd..1afe253ae 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -7,12 +7,8 @@ namespace Core { class System; } -namespace Service::Nvnflinger { -class Nvnflinger; -} - namespace Service::AM { -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::AM diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h index 8c33feb15..46afb3996 100644 --- a/src/core/hle/service/am/am_types.h +++ b/src/core/hle/service/am/am_types.h @@ -18,7 +18,7 @@ enum class AppletType { SystemApplet, }; -enum class GameplayRecordingState : u32 { +enum class GamePlayRecordingState : u32 { Disabled, Enabled, }; @@ -67,10 +67,9 @@ enum class ScreenshotPermission : u32 { }; struct FocusHandlingMode { - bool unknown0; - bool unknown1; - bool unknown2; - bool unknown3; + bool notify; + bool background; + bool suspend; }; enum class IdleTimeDetectionExtension : u32 { @@ -128,6 +127,40 @@ enum class AppletProgramId : u64 { MaxProgramId = 0x0100000000001FFFull, }; +// This is nn::am::AppletMessage +enum class AppletMessage : u32 { + None = 0, + ChangeIntoForeground = 1, + ChangeIntoBackground = 2, + Exit = 4, + ApplicationExited = 6, + FocusStateChanged = 15, + Resume = 16, + DetectShortPressingHomeButton = 20, + DetectLongPressingHomeButton = 21, + DetectShortPressingPowerButton = 22, + DetectMiddlePressingPowerButton = 23, + DetectLongPressingPowerButton = 24, + RequestToPrepareSleep = 25, + FinishedSleepSequence = 26, + SleepRequiredByHighTemperature = 27, + SleepRequiredByLowBattery = 28, + AutoPowerDown = 29, + OperationModeChanged = 30, + PerformanceModeChanged = 31, + DetectReceivingCecSystemStandby = 32, + SdCardRemoved = 33, + LaunchApplicationRequested = 50, + RequestToDisplay = 51, + ShowApplicationLogo = 55, + HideApplicationLogo = 56, + ForceHideApplicationLogo = 57, + FloatingApplicationDetected = 60, + DetectShortPressingCaptureButton = 90, + AlbumScreenShotTaken = 92, + AlbumRecordingSaved = 93, +}; + enum class LibraryAppletMode : u32 { AllForeground = 0, PartialForeground = 1, @@ -136,6 +169,11 @@ enum class LibraryAppletMode : u32 { AllForegroundInitiallyHidden = 4, }; +enum class LaunchParameterKind : u32 { + UserChannel = 1, + AccountPreselectedUser = 2, +}; + enum class CommonArgumentVersion : u32 { Version0, Version1, @@ -152,6 +190,22 @@ enum class ThemeColor : u32 { BasicBlack = 3, }; +enum class InputDetectionPolicy : u32 { + Unknown0 = 0, + Unknown1 = 1, +}; + +enum class WindowOriginMode : u32 { + LowerLeft = 0, + UpperLeft = 1, +}; + +enum class ProgramSpecifyKind : u32 { + ExecuteProgram = 0, + JumpToSubApplicationProgramForDevelopment = 1, + RestartProgram = 2, +}; + struct CommonArguments { CommonArgumentVersion arguments_version; CommonArgumentSize size; @@ -169,6 +223,27 @@ struct AppletIdentityInfo { }; static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); +struct AppletAttribute { + u8 flag; + INSERT_PADDING_BYTES_NOINIT(0x7F); +}; +static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size."); + +// This is nn::oe::DisplayVersion +struct DisplayVersion { + std::array<char, 0x10> string; +}; +static_assert(sizeof(DisplayVersion) == 0x10, "DisplayVersion has incorrect size."); + +// This is nn::pdm::ApplicationPlayStatistics +struct ApplicationPlayStatistics { + u64 application_id; + u64 play_time_ns; + u64 launch_count; +}; +static_assert(sizeof(ApplicationPlayStatistics) == 0x18, + "ApplicationPlayStatistics has incorrect size."); + using AppletResourceUserId = u64; using ProgramId = u64; diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h index b29ecdfed..ad602153e 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h @@ -3,7 +3,6 @@ #pragma once -#include <list> #include <mutex> #include "common/math_util.h" @@ -15,11 +14,9 @@ #include "core/hle/service/am/am_types.h" #include "core/hle/service/am/applet_message_queue.h" +#include "core/hle/service/am/display_layer_manager.h" #include "core/hle/service/am/hid_registration.h" -#include "core/hle/service/am/managed_layer_holder.h" #include "core/hle/service/am/process.h" -#include "core/hle/service/am/storage.h" -#include "core/hle/service/am/system_buffer_manager.h" namespace Service::AM { @@ -56,8 +53,7 @@ struct Applet { HidRegistration hid_registration; // vi state - SystemBufferManager system_buffer_manager{}; - ManagedLayerHolder managed_layer_holder{}; + DisplayLayerManager display_layer_manager{}; // Applet common functions Result terminate_result{}; @@ -76,8 +72,8 @@ struct Applet { u32 application_core_usage_mode{}; // Application functions - bool gameplay_recording_supported{}; - GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled}; + bool game_play_recording_supported{}; + GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled}; bool jit_service_launched{}; bool is_running{}; bool application_crash_report_enabled{}; diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp deleted file mode 100644 index 1b715dea6..000000000 --- a/src/core/hle/service/am/applet_ae.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet_ae.h" -#include "core/hle/service/am/applet_manager.h" -#include "core/hle/service/am/library_applet_proxy.h" -#include "core/hle/service/am/system_applet_proxy.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_) - : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} { - // clang-format off - static const FunctionInfo functions[] = { - {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, - {200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"}, - {201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"}, - {300, nullptr, "OpenOverlayAppletProxy"}, - {350, nullptr, "OpenSystemApplicationProxy"}, - {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, - {410, nullptr, "GetSystemAppletControllerForDebug"}, - {1000, nullptr, "GetDebugFunctions"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -AppletAE::~AppletAE() = default; - -void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - if (const auto applet = GetAppletFromContext(ctx)) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, applet, system); - } else { - UNIMPLEMENTED(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - } -} - -void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - if (const auto applet = GetAppletFromContext(ctx)) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, applet, system); - } else { - UNIMPLEMENTED(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - } -} - -void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - return OpenLibraryAppletProxy(ctx); -} - -std::shared_ptr<Applet> AppletAE::GetAppletFromContext(HLERequestContext& ctx) { - const auto aruid = ctx.GetPID(); - return system.GetAppletManager().GetByAppletResourceUserId(aruid); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h deleted file mode 100644 index 3d7961fa1..000000000 --- a/src/core/hle/service/am/applet_ae.h +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> - -#include "core/hle/service/service.h" - -namespace Service { -namespace FileSystem { -class FileSystemController; -} - -namespace Nvnflinger { -class Nvnflinger; -} - -namespace AM { - -struct Applet; - -class AppletAE final : public ServiceFramework<AppletAE> { -public: - explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_); - ~AppletAE() override; - -private: - void OpenSystemAppletProxy(HLERequestContext& ctx); - void OpenLibraryAppletProxy(HLERequestContext& ctx); - void OpenLibraryAppletProxyOld(HLERequestContext& ctx); - - std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nvnflinger; -}; - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp deleted file mode 100644 index 130614ae5..000000000 --- a/src/core/hle/service/am/applet_common_functions.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet.h" -#include "core/hle/service/am/applet_common_functions.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, - std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "SetTerminateResult"}, - {10, nullptr, "ReadThemeStorage"}, - {11, nullptr, "WriteThemeStorage"}, - {20, nullptr, "PushToAppletBoundChannel"}, - {21, nullptr, "TryPopFromAppletBoundChannel"}, - {40, nullptr, "GetDisplayLogicalResolution"}, - {42, nullptr, "SetDisplayMagnification"}, - {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, - {51, nullptr, "GetHomeButtonDoubleClickEnabled"}, - {52, nullptr, "IsHomeButtonShortPressedBlocked"}, - {60, nullptr, "IsVrModeCurtainRequired"}, - {61, nullptr, "IsSleepRequiredByHighTemperature"}, - {62, nullptr, "IsSleepRequiredByLowBattery"}, - {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"}, - {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"}, - {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"}, - {90, nullptr, "OpenNamedChannelAsParent"}, - {91, nullptr, "OpenNamedChannelAsChild"}, - {100, nullptr, "SetApplicationCoreUsageMode"}, - {300, &IAppletCommonFunctions::GetCurrentApplicationId, "GetCurrentApplicationId"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IAppletCommonFunctions::~IAppletCommonFunctions() = default; - -void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::RequestParser rp{ctx}; - - std::scoped_lock lk{applet->lock}; - applet->cpu_boost_request_priority = rp.Pop<s32>(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IAppletCommonFunctions::GetCurrentApplicationId(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(system.GetApplicationProcessProgramID() & ~0xFFFULL); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h deleted file mode 100644 index b86adf5cb..000000000 --- a/src/core/hle/service/am/applet_common_functions.h +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { -public: - explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_); - ~IAppletCommonFunctions() override; - -private: - void SetCpuBoostRequestPriority(HLERequestContext& ctx); - void GetCurrentApplicationId(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp index 4d58c4db5..9057244a9 100644 --- a/src/core/hle/service/am/applet_data_broker.cpp +++ b/src/core/hle/service/am/applet_data_broker.cpp @@ -24,11 +24,11 @@ void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) { Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) { std::scoped_lock lk{m_lock}; - SCOPE_EXIT({ + SCOPE_EXIT { if (m_data.empty()) { m_event.Clear(); } - }); + }; R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel); diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index 52200d5b2..2e109181d 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -12,6 +12,7 @@ #include "core/hle/service/am/frontend/applet_controller.h" #include "core/hle/service/am/frontend/applet_mii_edit_types.h" #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" +#include "core/hle/service/am/service/storage.h" #include "hid_core/hid_types.h" namespace Service::AM { @@ -34,6 +35,21 @@ AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, return applet->caller_applet_broker->GetInData(); } +void PushInShowQlaunch(Core::System& system, AppletStorageChannel& channel) { + const CommonArguments arguments{ + .arguments_version = CommonArgumentVersion::Version3, + .size = CommonArgumentSize::Version3, + .library_version = 0, + .theme_color = ThemeColor::BasicBlack, + .play_startup_sound = true, + .system_tick = system.CoreTiming().GetClockTicks(), + }; + + std::vector<u8> argument_data(sizeof(arguments)); + std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); + channel.Push(std::make_shared<IStorage>(system, std::move(argument_data))); +} + void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { const CommonArguments arguments{ .arguments_version = CommonArgumentVersion::Version3, @@ -283,6 +299,9 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters( // Starting from frontend, some applets require input data. switch (applet->applet_id) { + case AppletId::QLaunch: + PushInShowQlaunch(m_system, InitializeFakeCallerApplet(m_system, applet)); + break; case AppletId::Cabinet: PushInShowCabinetData(m_system, InitializeFakeCallerApplet(m_system, applet)); break; @@ -303,8 +322,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters( } // Applet was started by frontend, so it is foreground. - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); + applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground); + applet->message_queue.PushMessage(AppletMessage::FocusStateChanged); applet->focus_state = FocusState::InFocus; this->InsertApplet(std::move(applet)); diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp index 5ed996b70..83c3c5a55 100644 --- a/src/core/hle/service/am/applet_message_queue.cpp +++ b/src/core/hle/service/am/applet_message_queue.cpp @@ -33,7 +33,7 @@ void AppletMessageQueue::PushMessage(AppletMessage msg) { on_new_message->Signal(); } -AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { +AppletMessage AppletMessageQueue::PopMessage() { std::scoped_lock lk{lock}; if (messages.empty()) { on_new_message->Clear(); diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h index 5cb236d47..429b77d37 100644 --- a/src/core/hle/service/am/applet_message_queue.h +++ b/src/core/hle/service/am/applet_message_queue.h @@ -5,6 +5,7 @@ #include <queue> +#include "core/hle/service/am/am_types.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/service.h" @@ -16,40 +17,6 @@ namespace Service::AM { class AppletMessageQueue { public: - // This is nn::am::AppletMessage - enum class AppletMessage : u32 { - None = 0, - ChangeIntoForeground = 1, - ChangeIntoBackground = 2, - Exit = 4, - ApplicationExited = 6, - FocusStateChanged = 15, - Resume = 16, - DetectShortPressingHomeButton = 20, - DetectLongPressingHomeButton = 21, - DetectShortPressingPowerButton = 22, - DetectMiddlePressingPowerButton = 23, - DetectLongPressingPowerButton = 24, - RequestToPrepareSleep = 25, - FinishedSleepSequence = 26, - SleepRequiredByHighTemperature = 27, - SleepRequiredByLowBattery = 28, - AutoPowerDown = 29, - OperationModeChanged = 30, - PerformanceModeChanged = 31, - DetectReceivingCecSystemStandby = 32, - SdCardRemoved = 33, - LaunchApplicationRequested = 50, - RequestToDisplay = 51, - ShowApplicationLogo = 55, - HideApplicationLogo = 56, - ForceHideApplicationLogo = 57, - FloatingApplicationDetected = 60, - DetectShortPressingCaptureButton = 90, - AlbumScreenShotTaken = 92, - AlbumRecordingSaved = 93, - }; - explicit AppletMessageQueue(Core::System& system); ~AppletMessageQueue(); diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp deleted file mode 100644 index 56bafd162..000000000 --- a/src/core/hle/service/am/applet_oe.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/applet_manager.h" -#include "core/hle/service/am/applet_oe.h" -#include "core/hle/service/am/application_proxy.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_) - : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} { - static const FunctionInfo functions[] = { - {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, - }; - RegisterHandlers(functions); -} - -AppletOE::~AppletOE() = default; - -void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - if (const auto applet = GetAppletFromContext(ctx)) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationProxy>(nvnflinger, applet, system); - } else { - UNIMPLEMENTED(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - } -} - -std::shared_ptr<Applet> AppletOE::GetAppletFromContext(HLERequestContext& ctx) { - const auto aruid = ctx.GetPID(); - return system.GetAppletManager().GetByAppletResourceUserId(aruid); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h deleted file mode 100644 index f2ba1c924..000000000 --- a/src/core/hle/service/am/applet_oe.h +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> - -#include "core/hle/service/service.h" - -namespace Service { -namespace FileSystem { -class FileSystemController; -} - -namespace Nvnflinger { -class Nvnflinger; -} - -namespace AM { - -struct Applet; - -class AppletOE final : public ServiceFramework<AppletOE> { -public: - explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_); - ~AppletOE() override; - -private: - void OpenApplicationProxy(HLERequestContext& ctx); - - std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nvnflinger; -}; - -} // namespace AM -} // namespace Service diff --git a/src/core/hle/service/am/application_creator.cpp b/src/core/hle/service/am/application_creator.cpp deleted file mode 100644 index 79ea045a3..000000000 --- a/src/core/hle/service/am/application_creator.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/application_creator.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IApplicationCreator::IApplicationCreator(Core::System& system_) - : ServiceFramework{system_, "IApplicationCreator"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "CreateApplication"}, - {1, nullptr, "PopLaunchRequestedApplication"}, - {10, nullptr, "CreateSystemApplication"}, - {100, nullptr, "PopFloatingApplicationForDevelopment"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IApplicationCreator::~IApplicationCreator() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/application_creator.h b/src/core/hle/service/am/application_creator.h deleted file mode 100644 index 375a3c476..000000000 --- a/src/core/hle/service/am/application_creator.h +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { -public: - explicit IApplicationCreator(Core::System& system_); - ~IApplicationCreator() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp deleted file mode 100644 index 51c5be2d1..000000000 --- a/src/core/hle/service/am/application_functions.cpp +++ /dev/null @@ -1,594 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "common/uuid.h" -#include "core/file_sys/control_metadata.h" -#include "core/file_sys/patch_manager.h" -#include "core/file_sys/registered_cache.h" -#include "core/file_sys/savedata_factory.h" -#include "core/hle/service/acc/profile_manager.h" -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/applet.h" -#include "core/hle/service/am/application_functions.h" -#include "core/hle/service/am/storage.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/filesystem/save_data_controller.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/ns.h" -#include "core/hle/service/sm/sm.h" - -namespace Service::AM { - -enum class LaunchParameterKind : u32 { - UserChannel = 1, - AccountPreselectedUser = 2, -}; - -IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, - {10, nullptr, "CreateApplicationAndPushAndRequestToStart"}, - {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, - {12, nullptr, "CreateApplicationAndRequestToStart"}, - {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"}, - {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"}, - {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"}, - {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"}, - {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, - {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, - {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"}, - {24, nullptr, "GetLaunchStorageInfoForDebug"}, - {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, - {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, - {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"}, - {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"}, - {29, nullptr, "GetCacheStorageMax"}, - {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, - {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, - {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, - {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, - {34, nullptr, "SelectApplicationLicense"}, - {35, nullptr, "GetDeviceSaveDataSizeMax"}, - {36, nullptr, "GetLimitedApplicationLicense"}, - {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, - {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, - {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, - {60, nullptr, "SetMediaPlaybackStateForApplication"}, - {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"}, - {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, - {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, - {68, nullptr, "RequestFlushGamePlayingMovieForDebug"}, - {70, nullptr, "RequestToShutdown"}, - {71, nullptr, "RequestToReboot"}, - {72, nullptr, "RequestToSleep"}, - {80, nullptr, "ExitAndRequestToShowThanksMessage"}, - {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, - {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"}, - {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"}, - {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, - {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, - {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, - {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, - {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, - {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, - {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, - {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, - {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, - {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, - {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, - {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, - {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, - {151, nullptr, "TryPopFromNotificationStorageChannel"}, - {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, - {170, nullptr, "SetHdcpAuthenticationActivated"}, - {180, nullptr, "GetLaunchRequiredVersion"}, - {181, nullptr, "UpgradeLaunchRequiredVersion"}, - {190, nullptr, "SendServerMaintenanceOverlayNotification"}, - {200, nullptr, "GetLastApplicationExitReason"}, - {500, nullptr, "StartContinuousRecordingFlushForDebug"}, - {1000, nullptr, "CreateMovieMaker"}, - {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IApplicationFunctions::~IApplicationFunctions() = default; - -void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->application_crash_report_enabled = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto is_visible = rp.Pop<bool>(); - - LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->home_button_long_pressed_blocked = true; - applet->home_button_short_pressed_blocked = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->home_button_long_pressed_blocked = false; - applet->home_button_short_pressed_blocked = false; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->home_button_long_pressed_blocked = true; - applet->home_button_short_pressed_blocked = true; - applet->home_button_double_click_enabled = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->home_button_long_pressed_blocked = false; - applet->home_button_short_pressed_blocked = false; - applet->home_button_double_click_enabled = false; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto kind = rp.PopEnum<LaunchParameterKind>(); - - LOG_INFO(Service_AM, "called, kind={:08X}", kind); - - std::scoped_lock lk{applet->lock}; - - auto& channel = kind == LaunchParameterKind::UserChannel - ? applet->user_channel_launch_parameter - : applet->preselected_user_launch_parameter; - - if (channel.empty()) { - LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultNoDataInChannel); - return; - } - - auto data = channel.back(); - channel.pop_back(); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IStorage>(system, std::move(data)); -} - -void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - u128 user_id = rp.PopRaw<u128>(); - - LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]); - - FileSys::SaveDataAttribute attribute{}; - attribute.title_id = applet->program_id; - attribute.user_id = user_id; - attribute.type = FileSys::SaveDataType::SaveData; - - FileSys::VirtualDir save_data{}; - const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( - &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push<u64>(0); -} - -void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) { - // Takes an input u32 Result, no output. - // For example, in some cases official apps use this with error 0x2A2 then - // uses svcBreak. - - IPC::RequestParser rp{ctx}; - u32 result = rp.Pop<u32>(); - LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result); - - std::scoped_lock lk{applet->lock}; - applet->terminate_result = Result(result); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - std::array<u8, 0x10> version_string{}; - - const auto res = [this] { - const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(), - system.GetContentProvider()}; - auto metadata = pm.GetControlMetadata(); - if (metadata.first != nullptr) { - return metadata; - } - - const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id), - system.GetFileSystemController(), - system.GetContentProvider()}; - return pm_update.GetControlMetadata(); - }(); - - if (res.first != nullptr) { - const auto& version = res.first->GetVersionString(); - std::copy(version.begin(), version.end(), version_string.begin()); - } else { - static constexpr char default_version[]{"1.0.0"}; - std::memcpy(version_string.data(), default_version, sizeof(default_version)); - } - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.PushRaw(version_string); -} - -void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { - // TODO(bunnei): This should be configurable - LOG_DEBUG(Service_AM, "called"); - - // Get supported languages from NACP, if possible - // Default to 0 (all languages supported) - u32 supported_languages = 0; - - const auto res = [this] { - const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(), - system.GetContentProvider()}; - auto metadata = pm.GetControlMetadata(); - if (metadata.first != nullptr) { - return metadata; - } - - const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id), - system.GetFileSystemController(), - system.GetContentProvider()}; - return pm_update.GetControlMetadata(); - }(); - - if (res.first != nullptr) { - supported_languages = res.first->GetSupportedLanguages(); - } - - // Call IApplicationManagerInterface implementation. - auto& service_manager = system.ServiceManager(); - auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); - auto app_man = ns_am2->GetApplicationManagerInterface(); - - // Get desired application language - u8 desired_language{}; - const auto res_lang = - app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); - if (res_lang != ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res_lang); - return; - } - - // Convert to settings language code. - u64 language_code{}; - const auto res_code = - app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); - if (res_code != ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res_code); - return; - } - - LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(language_code); -} - -void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(applet->gameplay_recording_supported); -} - -void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::RequestParser rp{ctx}; - - std::scoped_lock lk{applet->lock}; - applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->is_running = true; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(0); // Unknown, seems to be ignored by official processes -} - -void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - - // Returns a 128-bit UUID - rb.Push<u64>(0); - rb.Push<u64>(0); -} - -void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) { - struct Parameters { - FileSys::SaveDataType type; - u128 user_id; - u64 new_normal_size; - u64 new_journal_size; - }; - static_assert(sizeof(Parameters) == 40); - - IPC::RequestParser rp{ctx}; - const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>(); - - LOG_DEBUG(Service_AM, - "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, " - "new_journal={:016X}", - static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size); - - system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( - type, applet->program_id, user_id, {new_normal_size, new_journal_size}); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - - // The following value is used upon failure to help the system recover. - // Since we always succeed, this should be 0. - rb.Push<u64>(0); -} - -void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) { - struct Parameters { - FileSys::SaveDataType type; - u128 user_id; - }; - static_assert(sizeof(Parameters) == 24); - - IPC::RequestParser rp{ctx}; - const auto [type, user_id] = rp.PopRaw<Parameters>(); - - LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1], - user_id[0]); - - const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( - type, applet->program_id, user_id); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(size.normal); - rb.Push(size.journal); -} - -void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) { - struct InputParameters { - u16 index; - s64 size; - s64 journal_size; - }; - static_assert(sizeof(InputParameters) == 24); - - struct OutputParameters { - u32 storage_target; - u64 required_size; - }; - static_assert(sizeof(OutputParameters) == 16); - - IPC::RequestParser rp{ctx}; - const auto params = rp.PopRaw<InputParameters>(); - - LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}", - params.index, params.size, params.journal_size); - - const OutputParameters resp{ - .storage_target = 1, - .required_size = 0, - }; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.PushRaw(resp); -} - -void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - constexpr u64 size_max_normal = 0xFFFFFFF; - constexpr u64 size_max_journal = 0xFFFFFFF; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(size_max_normal); - rb.Push(size_max_journal); -} - -void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(0); -} - -void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(0); -} - -void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::RequestParser rp{ctx}; - [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); - [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); - const auto program_index = rp.Pop<u64>(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - - // Swap user channel ownership into the system so that it will be preserved - system.GetUserChannel().swap(applet->user_channel_launch_parameter); - system.ExecuteProgram(program_index); -} - -void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - applet->user_channel_launch_parameter.clear(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::RequestParser rp{ctx}; - const auto storage = rp.PopIpcInterface<IStorage>().lock(); - if (storage) { - applet->user_channel_launch_parameter.push_back(storage->GetData()); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<s32>(applet->previous_program_index); -} - -void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle()); -} - -void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle()); -} - -void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultNoDataInChannel); -} - -void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle()); -} - -void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle()); -} - -void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->jit_service_launched = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h deleted file mode 100644 index 55eb21d39..000000000 --- a/src/core/hle/service/am/application_functions.h +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { -public: - explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_); - ~IApplicationFunctions() override; - -private: - void PopLaunchParameter(HLERequestContext& ctx); - void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx); - void EnsureSaveData(HLERequestContext& ctx); - void SetTerminateResult(HLERequestContext& ctx); - void GetDisplayVersion(HLERequestContext& ctx); - void GetDesiredLanguage(HLERequestContext& ctx); - void IsGamePlayRecordingSupported(HLERequestContext& ctx); - void InitializeGamePlayRecording(HLERequestContext& ctx); - void SetGamePlayRecordingState(HLERequestContext& ctx); - void NotifyRunning(HLERequestContext& ctx); - void GetPseudoDeviceId(HLERequestContext& ctx); - void ExtendSaveData(HLERequestContext& ctx); - void GetSaveDataSize(HLERequestContext& ctx); - void CreateCacheStorage(HLERequestContext& ctx); - void GetSaveDataSizeMax(HLERequestContext& ctx); - void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); - void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx); - void BeginBlockingHomeButton(HLERequestContext& ctx); - void EndBlockingHomeButton(HLERequestContext& ctx); - void EnableApplicationCrashReport(HLERequestContext& ctx); - void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx); - void SetApplicationCopyrightImage(HLERequestContext& ctx); - void SetApplicationCopyrightVisibility(HLERequestContext& ctx); - void QueryApplicationPlayStatistics(HLERequestContext& ctx); - void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx); - void ExecuteProgram(HLERequestContext& ctx); - void ClearUserChannel(HLERequestContext& ctx); - void UnpopToUserChannel(HLERequestContext& ctx); - void GetPreviousProgramIndex(HLERequestContext& ctx); - void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx); - void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx); - void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx); - void GetNotificationStorageChannelEvent(HLERequestContext& ctx); - void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx); - void PrepareForJit(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp deleted file mode 100644 index a6fd6d37f..000000000 --- a/src/core/hle/service/am/application_proxy.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet_common_functions.h" -#include "core/hle/service/am/application_functions.h" -#include "core/hle/service/am/application_proxy.h" -#include "core/hle/service/am/audio_controller.h" -#include "core/hle/service/am/common_state_getter.h" -#include "core/hle/service/am/debug_functions.h" -#include "core/hle/service/am/display_controller.h" -#include "core/hle/service/am/library_applet_creator.h" -#include "core/hle/service/am/library_applet_self_accessor.h" -#include "core/hle/service/am/process_winding_controller.h" -#include "core/hle/service/am/self_controller.h" -#include "core/hle/service/am/window_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr<Applet> applet_, Core::System& system_) - : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move( - applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, - {1, &IApplicationProxy::GetSelfController, "GetSelfController"}, - {2, &IApplicationProxy::GetWindowController, "GetWindowController"}, - {3, &IApplicationProxy::GetAudioController, "GetAudioController"}, - {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"}, - {10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"}, - {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, - {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"}, - {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IApplicationProxy::~IApplicationProxy() = default; - -void IApplicationProxy::GetAudioController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IAudioController>(system); -} - -void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDisplayController>(system, applet); -} - -void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IProcessWindingController>(system, applet); -} - -void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDebugFunctions>(system); -} - -void IApplicationProxy::GetWindowController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IWindowController>(system, applet); -} - -void IApplicationProxy::GetSelfController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger); -} - -void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ICommonStateGetter>(system, applet); -} - -void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletCreator>(system, applet); -} - -void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationFunctions>(system, applet); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h deleted file mode 100644 index eb98b095c..000000000 --- a/src/core/hle/service/am/application_proxy.h +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { -public: - explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr<Applet> msg_queue_, Core::System& system_); - ~IApplicationProxy(); - -private: - void GetAudioController(HLERequestContext& ctx); - void GetDisplayController(HLERequestContext& ctx); - void GetProcessWindingController(HLERequestContext& ctx); - void GetDebugFunctions(HLERequestContext& ctx); - void GetWindowController(HLERequestContext& ctx); - void GetSelfController(HLERequestContext& ctx); - void GetCommonStateGetter(HLERequestContext& ctx); - void GetLibraryAppletCreator(HLERequestContext& ctx); - void GetApplicationFunctions(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/audio_controller.cpp b/src/core/hle/service/am/audio_controller.cpp deleted file mode 100644 index ae75db174..000000000 --- a/src/core/hle/service/am/audio_controller.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/audio_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IAudioController::IAudioController(Core::System& system_) - : ServiceFramework{system_, "IAudioController"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, - {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"}, - {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"}, - {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"}, - {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IAudioController::~IAudioController() = default; - -void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const float main_applet_volume_tmp = rp.Pop<float>(); - const float library_applet_volume_tmp = rp.Pop<float>(); - - LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}", - main_applet_volume_tmp, library_applet_volume_tmp); - - // Ensure the volume values remain within the 0-100% range - main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume); - library_applet_volume = - std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(main_applet_volume); -} - -void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(library_applet_volume); -} - -void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) { - struct Parameters { - float volume; - s64 fade_time_ns; - }; - static_assert(sizeof(Parameters) == 16); - - IPC::RequestParser rp{ctx}; - const auto parameters = rp.PopRaw<Parameters>(); - - LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume, - parameters.fade_time_ns); - - main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume); - fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns}; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const float transparent_volume_rate_tmp = rp.Pop<float>(); - - LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp); - - // Clamp volume range to 0-100%. - transparent_volume_rate = - std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/audio_controller.h b/src/core/hle/service/am/audio_controller.h deleted file mode 100644 index a47e3bad8..000000000 --- a/src/core/hle/service/am/audio_controller.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -class IAudioController final : public ServiceFramework<IAudioController> { -public: - explicit IAudioController(Core::System& system_); - ~IAudioController() override; - -private: - void SetExpectedMasterVolume(HLERequestContext& ctx); - void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx); - void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx); - void ChangeMainAppletMasterVolume(HLERequestContext& ctx); - void SetTransparentAudioRate(HLERequestContext& ctx); - - static constexpr float min_allowed_volume = 0.0f; - static constexpr float max_allowed_volume = 1.0f; - - float main_applet_volume{0.25f}; - float library_applet_volume{max_allowed_volume}; - float transparent_volume_rate{min_allowed_volume}; - - // Volume transition fade time in nanoseconds. - // e.g. If the main applet volume was 0% and was changed to 50% - // with a fade of 50ns, then over the course of 50ns, - // the volume will gradually fade up to 50% - std::chrono::nanoseconds fade_time_ns{0}; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp deleted file mode 100644 index 937ac0beb..000000000 --- a/src/core/hle/service/am/common_state_getter.cpp +++ /dev/null @@ -1,314 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/applet.h" -#include "core/hle/service/am/common_state_getter.h" -#include "core/hle/service/am/lock_accessor.h" -#include "core/hle/service/apm/apm_controller.h" -#include "core/hle/service/apm/apm_interface.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/pm/pm.h" -#include "core/hle/service/sm/sm.h" -#include "core/hle/service/vi/vi.h" - -namespace Service::AM { - -ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, - {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, - {2, nullptr, "GetThisAppletKind"}, - {3, nullptr, "AllowToEnterSleep"}, - {4, nullptr, "DisallowToEnterSleep"}, - {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, - {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, - {7, nullptr, "GetCradleStatus"}, - {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, - {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, - {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"}, - {11, nullptr, "ReleaseSleepLock"}, - {12, nullptr, "ReleaseSleepLockTransiently"}, - {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"}, - {14, nullptr, "GetWakeupCount"}, - {20, nullptr, "PushToGeneralChannel"}, - {30, nullptr, "GetHomeButtonReaderLockAccessor"}, - {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"}, - {32, nullptr, "GetWriterLockAccessorEx"}, - {40, nullptr, "GetCradleFwVersion"}, - {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, - {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, - {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"}, - {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, - {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, - {55, nullptr, "IsInControllerFirmwareUpdateSection"}, - {59, nullptr, "SetVrPositionForDebug"}, - {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, - {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, - {62, nullptr, "GetHdcpAuthenticationState"}, - {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, - {64, nullptr, "SetTvPowerStateMatchingMode"}, - {65, nullptr, "GetApplicationIdByContentActionName"}, - {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, - {67, nullptr, "CancelCpuBoostMode"}, - {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"}, - {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"}, - {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, - {91, nullptr, "GetCurrentPerformanceConfiguration"}, - {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, - {110, nullptr, "OpenMyGpuErrorHandler"}, - {120, &ICommonStateGetter::GetAppletLaunchedHistory, "GetAppletLaunchedHistory"}, - {200, nullptr, "GetOperationModeSystemInfo"}, - {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"}, - {400, nullptr, "ActivateMigrationService"}, - {401, nullptr, "DeactivateMigrationService"}, - {500, nullptr, "DisableSleepTillShutdown"}, - {501, nullptr, "SuppressDisablingSleepTemporarily"}, - {502, nullptr, "IsSleepEnabled"}, - {503, nullptr, "IsDisablingSleepSuppressed"}, - {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ICommonStateGetter::~ICommonStateGetter() = default; - -void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode -} - -void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent()); -} - -void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - const auto message = applet->message_queue.PopMessage(); - IPC::ResponseBuilder rb{ctx, 3}; - - if (message == AppletMessageQueue::AppletMessage::None) { - LOG_ERROR(Service_AM, "Message queue is empty"); - rb.Push(AM::ResultNoMessages); - rb.PushEnum<AppletMessageQueue::AppletMessage>(message); - return; - } - - rb.Push(ResultSuccess); - rb.PushEnum<AppletMessageQueue::AppletMessage>(message); -} - -void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u8>(applet->focus_state)); -} - -void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) { - const bool use_docked_mode{Settings::IsDockedMode()}; - LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); -} - -void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode()); -} - -void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - // Sleep lock is acquired immediately. - applet->sleep_lock_event.Signal(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto unknown = rp.Pop<u32>(); - - LOG_INFO(Service_AM, "called, unknown={}", unknown); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILockAccessor>(system); -} - -void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->sleep_lock_event.GetHandle()); -} - -void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - std::scoped_lock lk{applet->lock}; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(applet->vr_mode_enabled); -} - -void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - std::scoped_lock lk{applet->lock}; - applet->vr_mode_enabled = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "on" : "off"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); - - LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}", - is_lcd_backlight_off_enabled); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->vr_mode_enabled = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->vr_mode_enabled = false; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent()); -} - -void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - - if (Settings::IsDockedMode()) { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); - } else { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); - } -} - -void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); - - const auto& sm = system.ServiceManager(); - const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys"); - ASSERT(apm_sys != nullptr); - - apm_sys->SetCpuBoostMode(ctx); -} - -void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(0); -} - -void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto system_button{rp.PopEnum<SystemButtonType>()}; - - LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ICommonStateGetter::GetAppletLaunchedHistory(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::shared_ptr<Applet> current_applet = applet; - std::vector<AppletId> result; - - const size_t count = ctx.GetWriteBufferNumElements<AppletId>(); - size_t i; - - for (i = 0; i < count && current_applet != nullptr; i++) { - result.push_back(current_applet->applet_id); - current_applet = current_applet->caller_applet.lock(); - } - - ctx.WriteBuffer(result); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(i)); -} - -void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(SysPlatformRegion::Global); -} - -void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( - HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->request_exit_to_library_applet_at_execute_next_program_enabled = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h deleted file mode 100644 index bf652790c..000000000 --- a/src/core/hle/service/am/common_state_getter.h +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -#include "core/hle/service/am/applet_message_queue.h" - -namespace Service::AM { - -struct Applet; - -class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { -public: - explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_); - ~ICommonStateGetter() override; - -private: - // This is nn::oe::FocusState - enum class FocusState : u8 { - InFocus = 1, - NotInFocus = 2, - Background = 3, - }; - - // This is nn::oe::OperationMode - enum class OperationMode : u8 { - Handheld = 0, - Docked = 1, - }; - - // This is nn::am::service::SystemButtonType - enum class SystemButtonType { - None, - HomeButtonShortPressing, - HomeButtonLongPressing, - PowerButtonShortPressing, - PowerButtonLongPressing, - ShutdownSystem, - CaptureButtonShortPressing, - CaptureButtonLongPressing, - }; - - enum class SysPlatformRegion : s32 { - Global = 1, - Terra = 2, - }; - - void GetEventHandle(HLERequestContext& ctx); - void ReceiveMessage(HLERequestContext& ctx); - void GetCurrentFocusState(HLERequestContext& ctx); - void RequestToAcquireSleepLock(HLERequestContext& ctx); - void GetAcquiredSleepLockEvent(HLERequestContext& ctx); - void GetReaderLockAccessorEx(HLERequestContext& ctx); - void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); - void GetOperationMode(HLERequestContext& ctx); - void GetPerformanceMode(HLERequestContext& ctx); - void GetBootMode(HLERequestContext& ctx); - void IsVrModeEnabled(HLERequestContext& ctx); - void SetVrModeEnabled(HLERequestContext& ctx); - void SetLcdBacklighOffEnabled(HLERequestContext& ctx); - void BeginVrModeEx(HLERequestContext& ctx); - void EndVrModeEx(HLERequestContext& ctx); - void GetDefaultDisplayResolution(HLERequestContext& ctx); - void SetCpuBoostMode(HLERequestContext& ctx); - void GetBuiltInDisplayType(HLERequestContext& ctx); - void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx); - void GetAppletLaunchedHistory(HLERequestContext& ctx); - void GetSettingsPlatformRegion(HLERequestContext& ctx); - void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/debug_functions.cpp b/src/core/hle/service/am/debug_functions.cpp deleted file mode 100644 index f80b970f2..000000000 --- a/src/core/hle/service/am/debug_functions.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/debug_functions.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IDebugFunctions::IDebugFunctions(Core::System& system_) - : ServiceFramework{system_, "IDebugFunctions"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, - {1, nullptr, "OpenMainApplication"}, - {10, nullptr, "PerformSystemButtonPressing"}, - {20, nullptr, "InvalidateTransitionLayer"}, - {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, - {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, - {40, nullptr, "GetAppletResourceUsageInfo"}, - {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, - {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, - {100, nullptr, "SetCpuBoostModeForApplet"}, - {101, nullptr, "CancelCpuBoostModeForApplet"}, - {110, nullptr, "PushToAppletBoundChannelForDebug"}, - {111, nullptr, "TryPopFromAppletBoundChannelForDebug"}, - {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"}, - {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"}, - {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"}, - {130, nullptr, "FriendInvitationSetApplicationParameter"}, - {131, nullptr, "FriendInvitationClearApplicationParameter"}, - {132, nullptr, "FriendInvitationPushApplicationParameter"}, - {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, - {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, - {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, - {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IDebugFunctions::~IDebugFunctions() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp deleted file mode 100644 index 4d6858348..000000000 --- a/src/core/hle/service/am/display_controller.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet.h" -#include "core/hle/service/am/display_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -namespace { -struct OutputParameters { - bool was_written; - s32 fbshare_layer_index; -}; - -static_assert(sizeof(OutputParameters) == 8, "OutputParameters has wrong size"); -} // namespace - -IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetLastForegroundCaptureImage"}, - {1, nullptr, "UpdateLastForegroundCaptureImage"}, - {2, nullptr, "GetLastApplicationCaptureImage"}, - {3, nullptr, "GetCallerAppletCaptureImage"}, - {4, nullptr, "UpdateCallerAppletCaptureImage"}, - {5, nullptr, "GetLastForegroundCaptureImageEx"}, - {6, nullptr, "GetLastApplicationCaptureImageEx"}, - {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"}, - {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, - {9, nullptr, "CopyBetweenCaptureBuffers"}, - {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, - {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, - {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, - {13, nullptr, "ReleaseLastForegroundCaptureBuffer"}, - {14, nullptr, "AcquireCallerAppletCaptureBuffer"}, - {15, nullptr, "ReleaseCallerAppletCaptureBuffer"}, - {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, - {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, - {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, - {20, nullptr, "ClearCaptureBuffer"}, - {21, nullptr, "ClearAppletTransitionBuffer"}, - {22, &IDisplayController::AcquireLastApplicationCaptureSharedBuffer, "AcquireLastApplicationCaptureSharedBuffer"}, - {23, &IDisplayController::ReleaseLastApplicationCaptureSharedBuffer, "ReleaseLastApplicationCaptureSharedBuffer"}, - {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"}, - {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"}, - {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, - {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"}, - {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IDisplayController::~IDisplayController() = default; - -void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - OutputParameters params{}; - const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( - ¶ms.was_written, ¶ms.fbshare_layer_index); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.PushRaw(params); -} - -void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - OutputParameters params{}; - const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( - ¶ms.was_written, ¶ms.fbshare_layer_index); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.PushRaw(params); -} - -void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - OutputParameters params{}; - const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( - ¶ms.was_written, ¶ms.fbshare_layer_index); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.PushRaw(params); -} - -void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - OutputParameters params{}; - const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer( - ¶ms.was_written, ¶ms.fbshare_layer_index); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.PushRaw(params); -} - -void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h deleted file mode 100644 index 75172580c..000000000 --- a/src/core/hle/service/am/display_controller.h +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class IDisplayController final : public ServiceFramework<IDisplayController> { -public: - explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_); - ~IDisplayController() override; - -private: - void GetCallerAppletCaptureImageEx(HLERequestContext& ctx); - void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); - void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); - void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx); - void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); - void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); - void AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx); - void ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/display_layer_manager.cpp b/src/core/hle/service/am/display_layer_manager.cpp new file mode 100644 index 000000000..85ff6fb88 --- /dev/null +++ b/src/core/hle/service/am/display_layer_manager.cpp @@ -0,0 +1,151 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/am/display_layer_manager.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/manager_display_service.h" +#include "core/hle/service/vi/manager_root_service.h" +#include "core/hle/service/vi/shared_buffer_manager.h" +#include "core/hle/service/vi/vi_results.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::AM { + +DisplayLayerManager::DisplayLayerManager() = default; +DisplayLayerManager::~DisplayLayerManager() { + this->Finalize(); +} + +void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process, + AppletId applet_id, LibraryAppletMode mode) { + R_ASSERT(system.ServiceManager() + .GetService<VI::IManagerRootService>("vi:m", true) + ->GetDisplayService(&m_display_service, VI::Policy::Compositor)); + R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service)); + + m_process = process; + m_system_shared_buffer_id = 0; + m_system_shared_layer_id = 0; + m_applet_id = applet_id; + m_buffer_sharing_enabled = false; + m_blending_enabled = mode == LibraryAppletMode::PartialForeground || + mode == LibraryAppletMode::PartialForegroundIndirectDisplay; +} + +void DisplayLayerManager::Finalize() { + if (!m_manager_display_service) { + return; + } + + // Clean up managed layers. + for (const auto& layer : m_managed_display_layers) { + m_manager_display_service->DestroyManagedLayer(layer); + } + + for (const auto& layer : m_managed_display_recording_layers) { + m_manager_display_service->DestroyManagedLayer(layer); + } + + // Clean up shared layers. + if (m_buffer_sharing_enabled) { + m_manager_display_service->DestroySharedLayerSession(m_process); + } + + m_manager_display_service = nullptr; + m_display_service = nullptr; +} + +Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) { + R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); + + // TODO(Subv): Find out how AM determines the display to use, for now just + // create the layer in the Default display. + u64 display_id; + R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"})); + R_TRY(m_manager_display_service->CreateManagedLayer( + out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()})); + + m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id); + m_managed_display_layers.emplace(*out_layer_id); + + R_SUCCEED(); +} + +Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id, + u64* out_recording_layer_id) { + R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); + + // TODO(Subv): Find out how AM determines the display to use, for now just + // create the layer in the Default display. + // This calls nn::vi::CreateRecordingLayer() which creates another layer. + // Currently we do not support more than 1 layer per display, output 1 layer id for now. + // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse + // side effects. + *out_recording_layer_id = 0; + R_RETURN(this->CreateManagedDisplayLayer(out_layer_id)); +} + +Result DisplayLayerManager::IsSystemBufferSharingEnabled() { + // Succeed if already enabled. + R_SUCCEED_IF(m_buffer_sharing_enabled); + + // Ensure we can access shared layers. + R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); + R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied); + + // Create the shared layer. + u64 display_id; + R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"})); + R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id, + &m_system_shared_layer_id, display_id, + m_blending_enabled)); + + // We succeeded, so set up remaining state. + m_buffer_sharing_enabled = true; + m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); + R_SUCCEED(); +} + +Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, + u64* out_system_shared_layer_id) { + R_TRY(this->IsSystemBufferSharingEnabled()); + + *out_system_shared_buffer_id = m_system_shared_buffer_id; + *out_system_shared_layer_id = m_system_shared_layer_id; + + R_SUCCEED(); +} + +void DisplayLayerManager::SetWindowVisibility(bool visible) { + if (m_visible == visible) { + return; + } + + m_visible = visible; + + if (m_manager_display_service) { + if (m_system_shared_layer_id) { + m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); + } + + for (const auto layer_id : m_managed_display_layers) { + m_manager_display_service->SetLayerVisibility(m_visible, layer_id); + } + } +} + +bool DisplayLayerManager::GetWindowVisibility() const { + return m_visible; +} + +Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written, + s32* out_fbshare_layer_index) { + R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied); + R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer( + out_was_written, out_fbshare_layer_index)); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/display_layer_manager.h b/src/core/hle/service/am/display_layer_manager.h new file mode 100644 index 000000000..a66509c04 --- /dev/null +++ b/src/core/hle/service/am/display_layer_manager.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <set> + +#include "common/common_types.h" +#include "core/hle/result.h" +#include "core/hle/service/am/am_types.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KProcess; +} + +namespace Service::VI { +class IApplicationDisplayService; +class IManagerDisplayService; +} // namespace Service::VI + +namespace Service::AM { + +class DisplayLayerManager { +public: + explicit DisplayLayerManager(); + ~DisplayLayerManager(); + + void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id, + LibraryAppletMode mode); + void Finalize(); + + Result CreateManagedDisplayLayer(u64* out_layer_id); + Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id); + + Result IsSystemBufferSharingEnabled(); + Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, + u64* out_system_shared_layer_id); + + void SetWindowVisibility(bool visible); + bool GetWindowVisibility() const; + + Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); + +private: + Kernel::KProcess* m_process{}; + std::shared_ptr<VI::IApplicationDisplayService> m_display_service{}; + std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{}; + std::set<u64> m_managed_display_layers{}; + std::set<u64> m_managed_display_recording_layers{}; + u64 m_system_shared_buffer_id{}; + u64 m_system_shared_layer_id{}; + AppletId m_applet_id{}; + bool m_buffer_sharing_enabled{}; + bool m_blending_enabled{}; + bool m_visible{true}; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/frontend/applet_cabinet.cpp b/src/core/hle/service/am/frontend/applet_cabinet.cpp index 0862c81b6..4cbc80d63 100644 --- a/src/core/hle/service/am/frontend/applet_cabinet.cpp +++ b/src/core/hle/service/am/frontend/applet_cabinet.cpp @@ -9,7 +9,7 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_cabinet.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/nfc/common/device.h" #include "hid_core/hid_core.h" diff --git a/src/core/hle/service/am/frontend/applet_controller.cpp b/src/core/hle/service/am/frontend/applet_controller.cpp index bd3e49fc4..66f52686d 100644 --- a/src/core/hle/service/am/frontend/applet_controller.cpp +++ b/src/core/hle/service/am/frontend/applet_controller.cpp @@ -12,7 +12,7 @@ #include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_controller.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "hid_core/frontend/emulated_controller.h" #include "hid_core/hid_core.h" #include "hid_core/hid_types.h" diff --git a/src/core/hle/service/am/frontend/applet_error.cpp b/src/core/hle/service/am/frontend/applet_error.cpp index b97a5f3ea..34ec7013b 100644 --- a/src/core/hle/service/am/frontend/applet_error.cpp +++ b/src/core/hle/service/am/frontend/applet_error.cpp @@ -10,7 +10,7 @@ #include "core/frontend/applets/error.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_error.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "core/reporter.h" namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/frontend/applet_general.cpp b/src/core/hle/service/am/frontend/applet_general.cpp index 3c091a602..d2cabb7b5 100644 --- a/src/core/hle/service/am/frontend/applet_general.cpp +++ b/src/core/hle/service/am/frontend/applet_general.cpp @@ -10,7 +10,7 @@ #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_data_broker.h" #include "core/hle/service/am/frontend/applet_general.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "core/reporter.h" namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/frontend/applet_mii_edit.cpp b/src/core/hle/service/am/frontend/applet_mii_edit.cpp index e3d19fb3d..0180ab761 100644 --- a/src/core/hle/service/am/frontend/applet_mii_edit.cpp +++ b/src/core/hle/service/am/frontend/applet_mii_edit.cpp @@ -7,7 +7,7 @@ #include "core/frontend/applets/mii_edit.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_mii_edit.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "core/hle/service/mii/mii.h" #include "core/hle/service/mii/mii_manager.h" #include "core/hle/service/sm/sm.h" diff --git a/src/core/hle/service/am/frontend/applet_profile_select.cpp b/src/core/hle/service/am/frontend/applet_profile_select.cpp index efb4053b8..89b5a1eab 100644 --- a/src/core/hle/service/am/frontend/applet_profile_select.cpp +++ b/src/core/hle/service/am/frontend/applet_profile_select.cpp @@ -10,7 +10,7 @@ #include "core/hle/service/acc/errors.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_profile_select.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp index 034c62f32..d1bc03018 100644 --- a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp +++ b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp @@ -6,7 +6,7 @@ #include "core/frontend/applets/software_keyboard.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_software_keyboard.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/frontend/applet_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp index 6ee4caf34..835c20c4e 100644 --- a/src/core/hle/service/am/frontend/applet_web_browser.cpp +++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp @@ -20,9 +20,9 @@ #include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/frontend/applet_web_browser.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/ns/iplatform_service_manager.h" +#include "core/hle/service/ns/platform_service_manager.h" #include "core/loader/loader.h" namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp index db2b04575..e662c6cd6 100644 --- a/src/core/hle/service/am/frontend/applets.cpp +++ b/src/core/hle/service/am/frontend/applets.cpp @@ -15,11 +15,8 @@ #include "core/frontend/applets/web_browser.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/am/am.h" -#include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_data_broker.h" #include "core/hle/service/am/applet_manager.h" -#include "core/hle/service/am/applet_message_queue.h" -#include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/frontend/applet_cabinet.h" #include "core/hle/service/am/frontend/applet_controller.h" #include "core/hle/service/am/frontend/applet_error.h" @@ -29,7 +26,7 @@ #include "core/hle/service/am/frontend/applet_software_keyboard.h" #include "core/hle/service/am/frontend/applet_web_browser.h" #include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/am/storage.h" +#include "core/hle/service/am/service/storage.h" #include "core/hle/service/sm/sm.h" namespace Service::AM::Frontend { diff --git a/src/core/hle/service/am/global_state_controller.cpp b/src/core/hle/service/am/global_state_controller.cpp deleted file mode 100644 index ed0eb7108..000000000 --- a/src/core/hle/service/am/global_state_controller.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/global_state_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IGlobalStateController::IGlobalStateController(Core::System& system_) - : ServiceFramework{system_, "IGlobalStateController"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestToEnterSleep"}, - {1, nullptr, "EnterSleep"}, - {2, nullptr, "StartSleepSequence"}, - {3, nullptr, "StartShutdownSequence"}, - {4, nullptr, "StartRebootSequence"}, - {9, nullptr, "IsAutoPowerDownRequested"}, - {10, nullptr, "LoadAndApplyIdlePolicySettings"}, - {11, nullptr, "NotifyCecSettingsChanged"}, - {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, - {13, nullptr, "UpdateDefaultDisplayResolution"}, - {14, nullptr, "ShouldSleepOnBoot"}, - {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, - {30, nullptr, "OpenCradleFirmwareUpdater"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IGlobalStateController::~IGlobalStateController() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/global_state_controller.h b/src/core/hle/service/am/global_state_controller.h deleted file mode 100644 index 7125464a1..000000000 --- a/src/core/hle/service/am/global_state_controller.h +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { -public: - explicit IGlobalStateController(Core::System& system_); - ~IGlobalStateController() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/home_menu_functions.cpp b/src/core/hle/service/am/home_menu_functions.cpp deleted file mode 100644 index 640e9fbb7..000000000 --- a/src/core/hle/service/am/home_menu_functions.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/home_menu_functions.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) - : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system, - "IHomeMenuFunctions"} { - // clang-format off - static const FunctionInfo functions[] = { - {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, - {11, nullptr, "LockForeground"}, - {12, nullptr, "UnlockForeground"}, - {20, nullptr, "PopFromGeneralChannel"}, - {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, - {30, nullptr, "GetHomeButtonWriterLockAccessor"}, - {31, nullptr, "GetWriterLockAccessorEx"}, - {40, nullptr, "IsSleepEnabled"}, - {41, nullptr, "IsRebootEnabled"}, - {50, nullptr, "LaunchSystemApplet"}, - {51, nullptr, "LaunchStarter"}, - {100, nullptr, "PopRequestLaunchApplicationForDebug"}, - {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, - {200, nullptr, "LaunchDevMenu"}, - {1000, nullptr, "SetLastApplicationExitReason"}, - }; - // clang-format on - - RegisterHandlers(functions); - - pop_from_general_channel_event = - service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent"); -} - -IHomeMenuFunctions::~IHomeMenuFunctions() { - service_context.CloseEvent(pop_from_general_channel_event); -} - -void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent()); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/home_menu_functions.h b/src/core/hle/service/am/home_menu_functions.h deleted file mode 100644 index e082d5d73..000000000 --- a/src/core/hle/service/am/home_menu_functions.h +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::AM { - -class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { -public: - explicit IHomeMenuFunctions(Core::System& system_); - ~IHomeMenuFunctions() override; - -private: - void RequestToGetForeground(HLERequestContext& ctx); - void GetPopFromGeneralChannelEvent(HLERequestContext& ctx); - - KernelHelpers::ServiceContext service_context; - - Kernel::KEvent* pop_from_general_channel_event; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp deleted file mode 100644 index 603515284..000000000 --- a/src/core/hle/service/am/idle.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/idle.h" - -namespace Service::AM { - -IdleSys::IdleSys(Core::System& system_) : ServiceFramework{system_, "idle:sys"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetAutoPowerDownEvent"}, - {1, nullptr, "IsAutoPowerDownRequested"}, - {2, nullptr, "Unknown2"}, - {3, nullptr, "SetHandlingContext"}, - {4, nullptr, "LoadAndApplySettings"}, - {5, nullptr, "ReportUserIsActive"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IdleSys::~IdleSys() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h deleted file mode 100644 index 15b31f67e..000000000 --- a/src/core/hle/service/am/idle.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::AM { - -class IdleSys final : public ServiceFramework<IdleSys> { -public: - explicit IdleSys(Core::System& system_); - ~IdleSys() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp deleted file mode 100644 index 6b20814f8..000000000 --- a/src/core/hle/service/am/library_applet_accessor.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/scope_exit.h" -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/applet_data_broker.h" -#include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/am/library_applet_accessor.h" -#include "core/hle/service/am/storage.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, - std::shared_ptr<AppletDataBroker> broker_, - std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "ILibraryAppletAccessor"}, broker{std::move(broker_)}, - applet{std::move(applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, - {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, - {10, &ILibraryAppletAccessor::Start, "Start"}, - {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"}, - {25, nullptr, "Terminate"}, - {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, - {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, - {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"}, - {100, &ILibraryAppletAccessor::PushInData, "PushInData"}, - {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"}, - {102, nullptr, "PushExtraStorage"}, - {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, - {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, - {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, - {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, - {110, nullptr, "NeedsToExitProcess"}, - {120, nullptr, "GetLibraryAppletInfo"}, - {150, nullptr, "RequestForAppletToGetForeground"}, - {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ILibraryAppletAccessor::~ILibraryAppletAccessor() = default; - -void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(broker->GetStateChangedEvent().GetHandle()); -} - -void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - std::scoped_lock lk{applet->lock}; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(broker->IsCompleted()); -} - -void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(applet->terminate_result); -} - -void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletAccessor::Start(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - applet->process->Run(); - FrontendExecute(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - ASSERT(applet != nullptr); - applet->message_queue.RequestExit(); - FrontendRequestExit(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::RequestParser rp{ctx}; - broker->GetInData().Push(rp.PopIpcInterface<IStorage>().lock()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - std::shared_ptr<IStorage> data; - const auto res = broker->GetOutData().Pop(&data); - - if (res.IsSuccess()) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(data)); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); - } -} - -void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::RequestParser rp{ctx}; - broker->GetInteractiveInData().Push(rp.PopIpcInterface<IStorage>().lock()); - FrontendExecuteInteractive(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - std::shared_ptr<IStorage> data; - const auto res = broker->GetInteractiveOutData().Pop(&data); - - if (res.IsSuccess()) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(data)); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); - } -} - -void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(broker->GetOutData().GetEvent()); -} - -void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(broker->GetInteractiveOutData().GetEvent()); -} - -void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is - // actually used anywhere - constexpr u64 handle = 0xdeadbeef; - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(handle); -} - -void ILibraryAppletAccessor::FrontendExecute() { - if (applet->frontend) { - applet->frontend->Initialize(); - applet->frontend->Execute(); - } -} - -void ILibraryAppletAccessor::FrontendExecuteInteractive() { - if (applet->frontend) { - applet->frontend->ExecuteInteractive(); - applet->frontend->Execute(); - } -} - -void ILibraryAppletAccessor::FrontendRequestExit() { - if (applet->frontend) { - applet->frontend->RequestExit(); - } -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h deleted file mode 100644 index 8be29e003..000000000 --- a/src/core/hle/service/am/library_applet_accessor.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -class AppletDataBroker; -struct Applet; - -class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { -public: - explicit ILibraryAppletAccessor(Core::System& system_, - std::shared_ptr<AppletDataBroker> broker_, - std::shared_ptr<Applet> applet_); - ~ILibraryAppletAccessor(); - -protected: - void GetAppletStateChangedEvent(HLERequestContext& ctx); - void IsCompleted(HLERequestContext& ctx); - void GetResult(HLERequestContext& ctx); - void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx); - void Start(HLERequestContext& ctx); - void RequestExit(HLERequestContext& ctx); - void PushInData(HLERequestContext& ctx); - void PopOutData(HLERequestContext& ctx); - void PushInteractiveInData(HLERequestContext& ctx); - void PopInteractiveOutData(HLERequestContext& ctx); - void GetPopOutDataEvent(HLERequestContext& ctx); - void GetPopInteractiveOutDataEvent(HLERequestContext& ctx); - void GetIndirectLayerConsumerHandle(HLERequestContext& ctx); - - void FrontendExecute(); - void FrontendExecuteInteractive(); - void FrontendRequestExit(); - - const std::shared_ptr<AppletDataBroker> broker; - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp deleted file mode 100644 index 00d5a0705..000000000 --- a/src/core/hle/service/am/library_applet_creator.cpp +++ /dev/null @@ -1,310 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/service/am/applet_data_broker.h" -#include "core/hle/service/am/applet_manager.h" -#include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/am/library_applet_accessor.h" -#include "core/hle/service/am/library_applet_creator.h" -#include "core/hle/service/am/library_applet_storage.h" -#include "core/hle/service/am/storage.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/sm/sm.h" - -namespace Service::AM { - -namespace { - -bool ShouldCreateGuestApplet(AppletId applet_id) { -#define X(Name, name) \ - if (applet_id == AppletId::Name && \ - Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \ - return false; \ - } - - X(Cabinet, cabinet) - X(Controller, controller) - X(DataErase, data_erase) - X(Error, error) - X(NetConnect, net_connect) - X(ProfileSelect, player_select) - X(SoftwareKeyboard, swkbd) - X(MiiEdit, mii_edit) - X(Web, web) - X(Shop, shop) - X(PhotoViewer, photo_viewer) - X(OfflineWeb, offline_web) - X(LoginShare, login_share) - X(WebAuth, wifi_web_auth) - X(MyPage, my_page) - -#undef X - - return true; -} - -AppletProgramId AppletIdToProgramId(AppletId applet_id) { - switch (applet_id) { - case AppletId::OverlayDisplay: - return AppletProgramId::OverlayDisplay; - case AppletId::QLaunch: - return AppletProgramId::QLaunch; - case AppletId::Starter: - return AppletProgramId::Starter; - case AppletId::Auth: - return AppletProgramId::Auth; - case AppletId::Cabinet: - return AppletProgramId::Cabinet; - case AppletId::Controller: - return AppletProgramId::Controller; - case AppletId::DataErase: - return AppletProgramId::DataErase; - case AppletId::Error: - return AppletProgramId::Error; - case AppletId::NetConnect: - return AppletProgramId::NetConnect; - case AppletId::ProfileSelect: - return AppletProgramId::ProfileSelect; - case AppletId::SoftwareKeyboard: - return AppletProgramId::SoftwareKeyboard; - case AppletId::MiiEdit: - return AppletProgramId::MiiEdit; - case AppletId::Web: - return AppletProgramId::Web; - case AppletId::Shop: - return AppletProgramId::Shop; - case AppletId::PhotoViewer: - return AppletProgramId::PhotoViewer; - case AppletId::Settings: - return AppletProgramId::Settings; - case AppletId::OfflineWeb: - return AppletProgramId::OfflineWeb; - case AppletId::LoginShare: - return AppletProgramId::LoginShare; - case AppletId::WebAuth: - return AppletProgramId::WebAuth; - case AppletId::MyPage: - return AppletProgramId::MyPage; - default: - return static_cast<AppletProgramId>(0); - } -} - -std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, - std::shared_ptr<Applet> caller_applet, - AppletId applet_id, - LibraryAppletMode mode) { - const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); - if (program_id == 0) { - // Unknown applet - return {}; - } - - // TODO: enable other versions of applets - enum : u8 { - Firmware1400 = 14, - Firmware1500 = 15, - Firmware1600 = 16, - Firmware1700 = 17, - }; - - auto process = std::make_unique<Process>(system); - if (!process->Initialize(program_id, Firmware1400, Firmware1700)) { - // Couldn't initialize the guest process - return {}; - } - - const auto applet = std::make_shared<Applet>(system, std::move(process)); - applet->program_id = program_id; - applet->applet_id = applet_id; - applet->type = AppletType::LibraryApplet; - applet->library_applet_mode = mode; - - // Set focus state - switch (mode) { - case LibraryAppletMode::AllForeground: - case LibraryAppletMode::NoUi: - case LibraryAppletMode::PartialForeground: - case LibraryAppletMode::PartialForegroundIndirectDisplay: - applet->hid_registration.EnableAppletToGetInput(true); - applet->focus_state = FocusState::InFocus; - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); - break; - case LibraryAppletMode::AllForegroundInitiallyHidden: - applet->hid_registration.EnableAppletToGetInput(false); - applet->focus_state = FocusState::NotInFocus; - applet->system_buffer_manager.SetWindowVisibility(false); - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground); - break; - } - - auto broker = std::make_shared<AppletDataBroker>(system); - applet->caller_applet = caller_applet; - applet->caller_applet_broker = broker; - - system.GetAppletManager().InsertApplet(applet); - - return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); -} - -std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system, - std::shared_ptr<Applet> caller_applet, - AppletId applet_id, - LibraryAppletMode mode) { - const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); - - auto process = std::make_unique<Process>(system); - auto applet = std::make_shared<Applet>(system, std::move(process)); - applet->program_id = program_id; - applet->applet_id = applet_id; - applet->type = AppletType::LibraryApplet; - applet->library_applet_mode = mode; - - auto storage = std::make_shared<AppletDataBroker>(system); - applet->caller_applet = caller_applet; - applet->caller_applet_broker = storage; - applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode); - - return std::make_shared<ILibraryAppletAccessor>(system, storage, applet); -} - -} // namespace - -ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} { - static const FunctionInfo functions[] = { - {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, - {1, nullptr, "TerminateAllLibraryApplets"}, - {2, nullptr, "AreAnyLibraryAppletsLeft"}, - {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"}, - {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"}, - {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"}, - }; - RegisterHandlers(functions); -} - -ILibraryAppletCreator::~ILibraryAppletCreator() = default; - -void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto applet_id = rp.PopRaw<AppletId>(); - const auto applet_mode = rp.PopRaw<LibraryAppletMode>(); - - LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, - applet_mode); - - std::shared_ptr<ILibraryAppletAccessor> library_applet; - if (ShouldCreateGuestApplet(applet_id)) { - library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode); - } - if (!library_applet) { - library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode); - } - if (!library_applet) { - LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - // Applet is created, can now be launched. - applet->library_applet_launchable_event.Signal(); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet); -} - -void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const s64 size{rp.Pop<s64>()}; - - LOG_DEBUG(Service_AM, "called, size={}", size); - - if (size <= 0) { - LOG_ERROR(Service_AM, "size is less than or equal to 0"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - std::vector<u8> data(size); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IStorage>(system, AM::CreateStorage(std::move(data))); -} - -void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - struct Parameters { - bool is_writable; - s64 size; - }; - - const auto params{rp.PopRaw<Parameters>()}; - const auto handle{ctx.GetCopyHandle(0)}; - - LOG_DEBUG(Service_AM, "called, is_writable={}, size={}, handle={:08X}", params.is_writable, - params.size, handle); - - if (params.size <= 0) { - LOG_ERROR(Service_AM, "size is less than or equal to 0"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); - - if (transfer_mem.IsNull()) { - LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IStorage>( - system, AM::CreateTransferMemoryStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), - params.is_writable, params.size)); -} - -void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const s64 size{rp.Pop<s64>()}; - const auto handle{ctx.GetCopyHandle(0)}; - - LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle); - - if (size <= 0) { - LOG_ERROR(Service_AM, "size is less than or equal to 0"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); - - if (transfer_mem.IsNull()) { - LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IStorage>( - system, AM::CreateHandleStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), size)); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h deleted file mode 100644 index 551f287bd..000000000 --- a/src/core/hle/service/am/library_applet_creator.h +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { -public: - explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_); - ~ILibraryAppletCreator() override; - -private: - void CreateLibraryApplet(HLERequestContext& ctx); - void CreateStorage(HLERequestContext& ctx); - void CreateTransferMemoryStorage(HLERequestContext& ctx); - void CreateHandleStorage(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp deleted file mode 100644 index d6108fba3..000000000 --- a/src/core/hle/service/am/library_applet_proxy.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet_common_functions.h" -#include "core/hle/service/am/audio_controller.h" -#include "core/hle/service/am/common_state_getter.h" -#include "core/hle/service/am/debug_functions.h" -#include "core/hle/service/am/display_controller.h" -#include "core/hle/service/am/global_state_controller.h" -#include "core/hle/service/am/home_menu_functions.h" -#include "core/hle/service/am/library_applet_creator.h" -#include "core/hle/service/am/library_applet_proxy.h" -#include "core/hle/service/am/library_applet_self_accessor.h" -#include "core/hle/service/am/process_winding_controller.h" -#include "core/hle/service/am/self_controller.h" -#include "core/hle/service/am/window_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr<Applet> applet_, Core::System& system_) - : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move( - applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, - {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, - {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"}, - {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"}, - {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, - {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, - {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, - {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, - {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, - {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, - {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, - {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ILibraryAppletProxy::~ILibraryAppletProxy() = default; - -void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ICommonStateGetter>(system, applet); -} - -void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger); -} - -void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IWindowController>(system, applet); -} - -void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IAudioController>(system); -} - -void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDisplayController>(system, applet); -} - -void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IProcessWindingController>(system, applet); -} - -void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletCreator>(system, applet); -} - -void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet); -} - -void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IAppletCommonFunctions>(system, applet); -} - -void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IHomeMenuFunctions>(system); -} - -void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IGlobalStateController>(system); -} - -void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDebugFunctions>(system); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h deleted file mode 100644 index 8f7a25897..000000000 --- a/src/core/hle/service/am/library_applet_proxy.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { -public: - explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr<Applet> applet_, Core::System& system_); - ~ILibraryAppletProxy(); - -private: - void GetCommonStateGetter(HLERequestContext& ctx); - void GetSelfController(HLERequestContext& ctx); - void GetWindowController(HLERequestContext& ctx); - void GetAudioController(HLERequestContext& ctx); - void GetDisplayController(HLERequestContext& ctx); - void GetProcessWindingController(HLERequestContext& ctx); - void GetLibraryAppletCreator(HLERequestContext& ctx); - void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx); - void GetAppletCommonFunctions(HLERequestContext& ctx); - void GetHomeMenuFunctions(HLERequestContext& ctx); - void GetGlobalStateController(HLERequestContext& ctx); - void GetDebugFunctions(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_self_accessor.cpp b/src/core/hle/service/am/library_applet_self_accessor.cpp deleted file mode 100644 index b560f580b..000000000 --- a/src/core/hle/service/am/library_applet_self_accessor.cpp +++ /dev/null @@ -1,338 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/scope_exit.h" -#include "core/core_timing.h" -#include "core/file_sys/control_metadata.h" -#include "core/file_sys/patch_manager.h" -#include "core/file_sys/registered_cache.h" -#include "core/hle/service/acc/profile_manager.h" -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/applet_data_broker.h" -#include "core/hle/service/am/applet_manager.h" -#include "core/hle/service/am/frontend/applet_cabinet.h" -#include "core/hle/service/am/frontend/applet_controller.h" -#include "core/hle/service/am/frontend/applet_mii_edit_types.h" -#include "core/hle/service/am/frontend/applet_software_keyboard_types.h" -#include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/am/library_applet_self_accessor.h" -#include "core/hle/service/am/storage.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/ns.h" -#include "core/hle/service/sm/sm.h" -#include "hid_core/hid_types.h" - -namespace Service::AM { - -namespace { - -AppletIdentityInfo GetCallerIdentity(std::shared_ptr<Applet> applet) { - if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) { - // TODO: is this actually the application ID? - return { - .applet_id = caller_applet->applet_id, - .application_id = caller_applet->program_id, - }; - } else { - return { - .applet_id = AppletId::QLaunch, - .application_id = 0x0100000000001000ull, - }; - } -} - -} // namespace - -ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, - std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)}, - broker{applet->caller_applet_broker} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"}, - {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"}, - {2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"}, - {3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"}, - {5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"}, - {6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"}, - {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"}, - {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"}, - {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"}, - {13, &ILibraryAppletSelfAccessor::CanUseApplicationCore, "CanUseApplicationCore"}, - {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"}, - {15, nullptr, "GetMainAppletApplicationControlProperty"}, - {16, nullptr, "GetMainAppletStorageId"}, - {17, nullptr, "GetCallerAppletIdentityInfoStack"}, - {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, - {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"}, - {20, nullptr, "PopExtraStorage"}, - {25, nullptr, "GetPopExtraStorageEvent"}, - {30, nullptr, "UnpopInData"}, - {31, nullptr, "UnpopExtraStorage"}, - {40, nullptr, "GetIndirectLayerProducerHandle"}, - {50, nullptr, "ReportVisibleError"}, - {51, nullptr, "ReportVisibleErrorWithErrorContext"}, - {60, &ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage, "GetMainAppletApplicationDesiredLanguage"}, - {70, &ILibraryAppletSelfAccessor::GetCurrentApplicationId, "GetCurrentApplicationId"}, - {80, nullptr, "RequestExitToSelf"}, - {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, - {100, nullptr, "CreateGameMovieTrimmer"}, - {101, nullptr, "ReserveResourceForMovieOperation"}, - {102, nullptr, "UnreserveResourceForMovieOperation"}, - {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"}, - {120, nullptr, "GetLaunchStorageInfoForDebug"}, - {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, - {140, nullptr, "SetApplicationMemoryReservation"}, - {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"}, - {160, &ILibraryAppletSelfAccessor::Cmd160, "Cmd160"}, - }; - // clang-format on - RegisterHandlers(functions); -} - -ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; - -void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - std::shared_ptr<IStorage> data; - const auto res = broker->GetInData().Pop(&data); - - if (res.IsSuccess()) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(data)); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); - } -} - -void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - IPC::RequestParser rp{ctx}; - broker->GetOutData().Push(rp.PopIpcInterface<IStorage>().lock()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - std::shared_ptr<IStorage> data; - const auto res = broker->GetInteractiveInData().Pop(&data); - - if (res.IsSuccess()) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(res); - rb.PushIpcInterface(std::move(data)); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); - } -} - -void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - IPC::RequestParser rp{ctx}; - broker->GetInteractiveOutData().Push(rp.PopIpcInterface<IStorage>().lock()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(broker->GetInData().GetEvent()); -} - -void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(broker->GetInteractiveInData().GetEvent()); -} - -void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid); - broker->SignalCompletion(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { - struct LibraryAppletInfo { - AppletId applet_id; - LibraryAppletMode library_applet_mode; - }; - - LOG_WARNING(Service_AM, "(STUBBED) called"); - - const LibraryAppletInfo applet_info{ - .applet_id = applet->applet_id, - .library_applet_mode = applet->library_applet_mode, - }; - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushRaw(applet_info); -} - -void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - const AppletIdentityInfo applet_info{ - .applet_id = AppletId::QLaunch, - .application_id = 0x0100000000001000ull, - }; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.PushRaw(applet_info); -} - -void ILibraryAppletSelfAccessor::CanUseApplicationCore(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - // TODO: This appears to read the NPDM from state and check the core mask of the applet. - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(0); -} - -void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.PushRaw(GetCallerIdentity(applet)); -} - -void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(0); -} - -void ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx) { - // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage - auto identity = GetCallerIdentity(applet); - - // TODO(bunnei): This should be configurable - LOG_DEBUG(Service_AM, "called"); - - // Get supported languages from NACP, if possible - // Default to 0 (all languages supported) - u32 supported_languages = 0; - - const auto res = [this, identity] { - const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(), - system.GetContentProvider()}; - auto metadata = pm.GetControlMetadata(); - if (metadata.first != nullptr) { - return metadata; - } - - const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id), - system.GetFileSystemController(), - system.GetContentProvider()}; - return pm_update.GetControlMetadata(); - }(); - - if (res.first != nullptr) { - supported_languages = res.first->GetSupportedLanguages(); - } - - // Call IApplicationManagerInterface implementation. - auto& service_manager = system.ServiceManager(); - auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2"); - auto app_man = ns_am2->GetApplicationManagerInterface(); - - // Get desired application language - u8 desired_language{}; - const auto res_lang = - app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); - if (res_lang != ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res_lang); - return; - } - - // Convert to settings language code. - u64 language_code{}; - const auto res_code = - app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); - if (res_code != ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res_code); - return; - } - - LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(language_code); -} - -void ILibraryAppletSelfAccessor::GetCurrentApplicationId(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - u64 application_id = 0; - if (auto caller_applet = applet->caller_applet.lock(); caller_applet) { - application_id = caller_applet->program_id; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(application_id); -} - -void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { - const Service::Account::ProfileManager manager{}; - bool is_empty{true}; - s32 user_count{-1}; - - LOG_INFO(Service_AM, "called"); - - if (manager.GetUserCount() > 0) { - is_empty = false; - user_count = static_cast<s32>(manager.GetUserCount()); - ctx.WriteBuffer(manager.GetAllUsers()); - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u8>(is_empty); - rb.Push(user_count); -} - -void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(0); -} - -void ILibraryAppletSelfAccessor::Cmd160(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(0); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h deleted file mode 100644 index 8717a989a..000000000 --- a/src/core/hle/service/am/library_applet_self_accessor.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <deque> -#include <vector> - -#include "core/hle/service/service.h" - -namespace Service::AM { - -class AppletDataBroker; -struct Applet; - -class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { -public: - explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_); - ~ILibraryAppletSelfAccessor() override; - -private: - void PopInData(HLERequestContext& ctx); - void PushOutData(HLERequestContext& ctx); - void PopInteractiveInData(HLERequestContext& ctx); - void PushInteractiveOutData(HLERequestContext& ctx); - void GetPopInDataEvent(HLERequestContext& ctx); - void GetPopInteractiveInDataEvent(HLERequestContext& ctx); - void GetLibraryAppletInfo(HLERequestContext& ctx); - void GetMainAppletIdentityInfo(HLERequestContext& ctx); - void CanUseApplicationCore(HLERequestContext& ctx); - void ExitProcessAndReturn(HLERequestContext& ctx); - void GetCallerAppletIdentityInfo(HLERequestContext& ctx); - void GetDesirableKeyboardLayout(HLERequestContext& ctx); - void GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx); - void GetCurrentApplicationId(HLERequestContext& ctx); - void GetMainAppletAvailableUsers(HLERequestContext& ctx); - void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx); - void Cmd160(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; - const std::shared_ptr<AppletDataBroker> broker; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp index 46e6c0111..0412c215d 100644 --- a/src/core/hle/service/am/library_applet_storage.cpp +++ b/src/core/hle/service/am/library_applet_storage.cpp @@ -70,7 +70,7 @@ public: Result Read(s64 offset, void* buffer, size_t size) override { R_TRY(ValidateOffset(offset, size, m_size)); - m_memory.ReadBlock(m_trmem->GetSourceAddress(), buffer, size); + m_memory.ReadBlock(m_trmem->GetSourceAddress() + offset, buffer, size); R_SUCCEED(); } @@ -79,7 +79,7 @@ public: R_UNLESS(m_is_writable, ResultUnknown); R_TRY(ValidateOffset(offset, size, m_size)); - m_memory.WriteBlock(m_trmem->GetSourceAddress(), buffer, size); + m_memory.WriteBlock(m_trmem->GetSourceAddress() + offset, buffer, size); R_SUCCEED(); } diff --git a/src/core/hle/service/am/lock_accessor.cpp b/src/core/hle/service/am/lock_accessor.cpp deleted file mode 100644 index d0bd8d95e..000000000 --- a/src/core/hle/service/am/lock_accessor.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/lock_accessor.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -ILockAccessor::ILockAccessor(Core::System& system_) - : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} { - // clang-format off - static const FunctionInfo functions[] = { - {1, &ILockAccessor::TryLock, "TryLock"}, - {2, &ILockAccessor::Unlock, "Unlock"}, - {3, &ILockAccessor::GetEvent, "GetEvent"}, - {4,&ILockAccessor::IsLocked, "IsLocked"}, - }; - // clang-format on - - RegisterHandlers(functions); - - lock_event = service_context.CreateEvent("ILockAccessor::LockEvent"); -} - -ILockAccessor::~ILockAccessor() { - service_context.CloseEvent(lock_event); -}; - -void ILockAccessor::TryLock(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto return_handle = rp.Pop<bool>(); - - LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle); - - // TODO: When return_handle is true this function should return the lock handle - - is_locked = true; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(is_locked); -} - -void ILockAccessor::Unlock(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - is_locked = false; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ILockAccessor::GetEvent(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - lock_event->Signal(); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(lock_event->GetReadableEvent()); -} - -void ILockAccessor::IsLocked(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - rb.Push<u8>(is_locked); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/lock_accessor.h b/src/core/hle/service/am/lock_accessor.h deleted file mode 100644 index 626f60e07..000000000 --- a/src/core/hle/service/am/lock_accessor.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::AM { - -class ILockAccessor final : public ServiceFramework<ILockAccessor> { -public: - explicit ILockAccessor(Core::System& system_); - ~ILockAccessor() override; - -private: - void TryLock(HLERequestContext& ctx); - void Unlock(HLERequestContext& ctx); - void GetEvent(HLERequestContext& ctx); - void IsLocked(HLERequestContext& ctx); - - bool is_locked{}; - - Kernel::KEvent* lock_event; - KernelHelpers::ServiceContext service_context; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp deleted file mode 100644 index 61eb8641a..000000000 --- a/src/core/hle/service/am/managed_layer_holder.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/managed_layer_holder.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" - -namespace Service::AM { - -ManagedLayerHolder::ManagedLayerHolder() = default; -ManagedLayerHolder::~ManagedLayerHolder() { - if (!m_nvnflinger) { - return; - } - - for (const auto& layer : m_managed_display_layers) { - m_nvnflinger->DestroyLayer(layer); - } - - for (const auto& layer : m_managed_display_recording_layers) { - m_nvnflinger->DestroyLayer(layer); - } - - m_nvnflinger = nullptr; -} - -void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) { - m_nvnflinger = nvnflinger; -} - -void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) { - // TODO(Subv): Find out how AM determines the display to use, for now just - // create the layer in the Default display. - const auto display_id = m_nvnflinger->OpenDisplay("Default"); - const auto layer_id = m_nvnflinger->CreateLayer(*display_id); - - m_managed_display_layers.emplace(*layer_id); - - *out_layer = *layer_id; -} - -void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer, - u64* out_recording_layer) { - // TODO(Subv): Find out how AM determines the display to use, for now just - // create the layer in the Default display. - // This calls nn::vi::CreateRecordingLayer() which creates another layer. - // Currently we do not support more than 1 layer per display, output 1 layer id for now. - // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse - // side effects. - // TODO: Support multiple layers - const auto display_id = m_nvnflinger->OpenDisplay("Default"); - const auto layer_id = m_nvnflinger->CreateLayer(*display_id); - - m_managed_display_layers.emplace(*layer_id); - - *out_layer = *layer_id; - *out_recording_layer = 0; -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h deleted file mode 100644 index f7fe03f24..000000000 --- a/src/core/hle/service/am/managed_layer_holder.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <set> - -#include "common/common_funcs.h" -#include "common/common_types.h" - -namespace Service::Nvnflinger { -class Nvnflinger; -} - -namespace Service::AM { - -class ManagedLayerHolder { -public: - ManagedLayerHolder(); - ~ManagedLayerHolder(); - - void Initialize(Nvnflinger::Nvnflinger* nvnflinger); - void CreateManagedDisplayLayer(u64* out_layer); - void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer); - -private: - Nvnflinger::Nvnflinger* m_nvnflinger{}; - std::set<u64> m_managed_display_layers{}; - std::set<u64> m_managed_display_recording_layers{}; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/omm.cpp b/src/core/hle/service/am/omm.cpp deleted file mode 100644 index 66824e495..000000000 --- a/src/core/hle/service/am/omm.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/omm.h" - -namespace Service::AM { - -OMM::OMM(Core::System& system_) : ServiceFramework{system_, "omm"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetOperationMode"}, - {1, nullptr, "GetOperationModeChangeEvent"}, - {2, nullptr, "EnableAudioVisual"}, - {3, nullptr, "DisableAudioVisual"}, - {4, nullptr, "EnterSleepAndWait"}, - {5, nullptr, "GetCradleStatus"}, - {6, nullptr, "FadeInDisplay"}, - {7, nullptr, "FadeOutDisplay"}, - {8, nullptr, "GetCradleFwVersion"}, - {9, nullptr, "NotifyCecSettingsChanged"}, - {10, nullptr, "SetOperationModePolicy"}, - {11, nullptr, "GetDefaultDisplayResolution"}, - {12, nullptr, "GetDefaultDisplayResolutionChangeEvent"}, - {13, nullptr, "UpdateDefaultDisplayResolution"}, - {14, nullptr, "ShouldSleepOnBoot"}, - {15, nullptr, "NotifyHdcpApplicationExecutionStarted"}, - {16, nullptr, "NotifyHdcpApplicationExecutionFinished"}, - {17, nullptr, "NotifyHdcpApplicationDrawingStarted"}, - {18, nullptr, "NotifyHdcpApplicationDrawingFinished"}, - {19, nullptr, "GetHdcpAuthenticationFailedEvent"}, - {20, nullptr, "GetHdcpAuthenticationFailedEmulationEnabled"}, - {21, nullptr, "SetHdcpAuthenticationFailedEmulation"}, - {22, nullptr, "GetHdcpStateChangeEvent"}, - {23, nullptr, "GetHdcpState"}, - {24, nullptr, "ShowCardUpdateProcessing"}, - {25, nullptr, "SetApplicationCecSettingsAndNotifyChanged"}, - {26, nullptr, "GetOperationModeSystemInfo"}, - {27, nullptr, "GetAppletFullAwakingSystemEvent"}, - {28, nullptr, "CreateCradleFirmwareUpdater"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -OMM::~OMM() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h deleted file mode 100644 index 73d0c82d5..000000000 --- a/src/core/hle/service/am/omm.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::AM { - -class OMM final : public ServiceFramework<OMM> { -public: - explicit OMM(Core::System& system_); - ~OMM() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/process.cpp b/src/core/hle/service/am/process.cpp index 992c50713..388d2045c 100644 --- a/src/core/hle/service/am/process.cpp +++ b/src/core/hle/service/am/process.cpp @@ -68,7 +68,9 @@ bool Process::Initialize(u64 program_id, u8 minimum_key_generation, u8 maximum_k Kernel::KProcess::Register(m_system.Kernel(), process); // On exit, ensure we free the additional reference to the process. - SCOPE_EXIT({ process->Close(); }); + SCOPE_EXIT { + process->Close(); + }; // Insert process modules into memory. const auto [load_result, load_parameters] = app_loader->Load(*process, m_system); diff --git a/src/core/hle/service/am/process_winding_controller.cpp b/src/core/hle/service/am/process_winding_controller.cpp deleted file mode 100644 index b48b52797..000000000 --- a/src/core/hle/service/am/process_winding_controller.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/am/library_applet_accessor.h" -#include "core/hle/service/am/process_winding_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IProcessWindingController::IProcessWindingController(Core::System& system_, - std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"}, - {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"}, - {21, nullptr, "PushContext"}, - {22, nullptr, "PopContext"}, - {23, nullptr, "CancelWindingReservation"}, - {30, nullptr, "WindAndDoReserved"}, - {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, - {41, nullptr, "ReserveToStartAndWait"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IProcessWindingController::~IProcessWindingController() = default; - -void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushRaw(applet->launch_reason); -} - -void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { - const auto caller_applet = applet->caller_applet.lock(); - if (caller_applet == nullptr) { - LOG_ERROR(Service_AM, "No calling applet available"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_broker, - caller_applet); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/process_winding_controller.h b/src/core/hle/service/am/process_winding_controller.h deleted file mode 100644 index 71ae4c4f5..000000000 --- a/src/core/hle/service/am/process_winding_controller.h +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { -public: - explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_); - ~IProcessWindingController() override; - -private: - void GetLaunchReason(HLERequestContext& ctx); - void OpenCallingLibraryApplet(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp deleted file mode 100644 index 65e249c0c..000000000 --- a/src/core/hle/service/am/self_controller.cpp +++ /dev/null @@ -1,470 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/hle/result.h" -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/frontend/applets.h" -#include "core/hle/service/am/self_controller.h" -#include "core/hle/service/caps/caps_su.h" -#include "core/hle/service/hle_ipc.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/sm/sm.h" -#include "core/hle/service/vi/vi_results.h" - -namespace Service::AM { - -ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_, - Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move( - applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ISelfController::Exit, "Exit"}, - {1, &ISelfController::LockExit, "LockExit"}, - {2, &ISelfController::UnlockExit, "UnlockExit"}, - {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, - {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, - {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, - {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, - {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, - {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, - {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, - {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, - {15, &ISelfController::SetScreenShotAppletIdentityInfo, "SetScreenShotAppletIdentityInfo"}, - {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, - {17, nullptr, "SetControllerFirmwareUpdateSection"}, - {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, - {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, - {20, nullptr, "SetDesirableKeyboardLayout"}, - {21, nullptr, "GetScreenShotProgramId"}, - {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, - {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, - {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, - {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, - {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, - {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, - {46, nullptr, "SetRecordingLayerCompositionEnabled"}, - {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, - {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, - {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, - {61, &ISelfController::SetMediaPlaybackState, "SetMediaPlaybackState"}, - {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, - {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, - {64, nullptr, "SetInputDetectionSourceSet"}, - {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"}, - {66, nullptr, "GetCurrentIlluminance"}, - {67, nullptr, "IsIlluminanceAvailable"}, - {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, - {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, - {70, nullptr, "ReportMultimediaError"}, - {71, nullptr, "GetCurrentIlluminanceEx"}, - {72, nullptr, "SetInputDetectionPolicy"}, - {80, nullptr, "SetWirelessPriorityMode"}, - {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, - {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, - {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, - {110, nullptr, "SetApplicationAlbumUserData"}, - {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, - {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"}, - {1000, nullptr, "GetDebugStorageChannel"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ISelfController::~ISelfController() = default; - -void ISelfController::Exit(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - - // TODO - system.Exit(); -} - -void ISelfController::LockExit(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - system.SetExitLocked(true); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::UnlockExit(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - system.SetExitLocked(false); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - - if (system.GetExitRequested()) { - system.Exit(); - } -} - -void ISelfController::EnterFatalSection(HLERequestContext& ctx) { - - std::scoped_lock lk{applet->lock}; - applet->fatal_section_count++; - LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called."); - - // Entry and exit of fatal sections must be balanced. - std::scoped_lock lk{applet->lock}; - if (applet->fatal_section_count == 0) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultFatalSectionCountImbalance); - return; - } - - applet->fatal_section_count--; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - applet->library_applet_launchable_event.Signal(); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle()); -} - -void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto permission = rp.PopEnum<ScreenshotPermission>(); - LOG_DEBUG(Service_AM, "called, permission={}", permission); - - std::scoped_lock lk{applet->lock}; - applet->screenshot_permission = permission; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const bool notification_enabled = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); - - std::scoped_lock lk{applet->lock}; - applet->operation_mode_changed_notification_enabled = notification_enabled; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const bool notification_enabled = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); - - std::scoped_lock lk{applet->lock}; - applet->performance_mode_changed_notification_enabled = notification_enabled; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto flags = rp.PopRaw<FocusHandlingMode>(); - - LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", - flags.unknown0, flags.unknown1, flags.unknown2); - - std::scoped_lock lk{applet->lock}; - applet->focus_handling_mode = flags; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - applet->restart_message_enabled = true; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::RequestParser rp{ctx}; - std::scoped_lock lk{applet->lock}; - applet->screen_shot_identity = rp.PopRaw<AppletIdentityInfo>(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const bool enabled = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); - - std::scoped_lock lk{applet->lock}; - ASSERT(applet->type == AppletType::Application); - applet->out_of_focus_suspension_enabled = enabled; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto orientation = rp.PopRaw<Capture::AlbumImageOrientation>(); - LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(orientation)); - - std::scoped_lock lk{applet->lock}; - applet->album_image_orientation = orientation; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - u64 layer_id{}; - applet->managed_layer_holder.Initialize(&nvnflinger); - applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(layer_id); -} - -void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); -} - -void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - u64 buffer_id, layer_id; - applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); - rb.Push<s64>(buffer_id); - rb.Push<s64>(layer_id); -} - -void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - u64 buffer_id, layer_id; - applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); - rb.Push<s64>(buffer_id); -} - -Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { - if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id, - applet->library_applet_mode)) { - return ResultSuccess; - } - - return VI::ResultOperationFailed; -} - -void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - u64 layer_id{}; - u64 recording_layer_id{}; - applet->managed_layer_holder.Initialize(&nvnflinger); - applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(layer_id); - rb.Push(recording_layer_id); -} - -void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetMediaPlaybackState(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u8 state = rp.Pop<u8>(); - - LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto extension = rp.PopRaw<IdleTimeDetectionExtension>(); - LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension); - - std::scoped_lock lk{applet->lock}; - applet->idle_time_detection_extension = extension; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - std::scoped_lock lk{applet->lock}; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushRaw<IdleTimeDetectionExtension>(applet->idle_time_detection_extension); -} - -void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - std::scoped_lock lk{applet->lock}; - applet->auto_sleep_disabled = rp.Pop<bool>(); - - // On the system itself, if the previous state of is_auto_sleep_disabled - // differed from the current value passed in, it'd signify the internal - // window manager to update (and also increment some statistics like update counts) - // - // It'd also indicate this change to an idle handling context. - // - // However, given we're emulating this behavior, most of this can be ignored - // and it's sufficient to simply set the member variable for querying via - // IsAutoSleepDisabled(). - - LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called."); - - std::scoped_lock lk{applet->lock}; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(applet->auto_sleep_disabled); -} - -void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called."); - - std::scoped_lock lk{applet->lock}; - // This command returns the total number of system ticks since ISelfController creation - // where the game was suspended. Since Yuzu doesn't implement game suspension, this command - // can just always return 0 ticks. - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(applet->suspended_ticks); -} - -void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called."); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle()); -} - -void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - // This service call sets an internal flag whether a notification is shown when an image is - // captured. Currently we do not support capturing images via the capture button, so this can be - // stubbed for now. - const bool enabled = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); - - std::scoped_lock lk{applet->lock}; - applet->album_image_taken_notification_enabled = enabled; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto report_option = rp.PopEnum<Capture::AlbumReportOption>(); - - LOG_INFO(Service_AM, "called, report_option={}", report_option); - - const auto screenshot_service = - system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( - "caps:su"); - - if (screenshot_service) { - screenshot_service->CaptureAndSaveScreenshot(report_option); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto enabled = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); - - std::scoped_lock lk{applet->lock}; - applet->record_volume_muted = enabled; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h deleted file mode 100644 index ab21a1881..000000000 --- a/src/core/hle/service/am/self_controller.h +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/hle_ipc.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class ISelfController final : public ServiceFramework<ISelfController> { -public: - explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_, - Nvnflinger::Nvnflinger& nvnflinger_); - ~ISelfController() override; - -private: - void Exit(HLERequestContext& ctx); - void LockExit(HLERequestContext& ctx); - void UnlockExit(HLERequestContext& ctx); - void EnterFatalSection(HLERequestContext& ctx); - void LeaveFatalSection(HLERequestContext& ctx); - void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx); - void SetScreenShotPermission(HLERequestContext& ctx); - void SetOperationModeChangedNotification(HLERequestContext& ctx); - void SetPerformanceModeChangedNotification(HLERequestContext& ctx); - void SetFocusHandlingMode(HLERequestContext& ctx); - void SetRestartMessageEnabled(HLERequestContext& ctx); - void SetScreenShotAppletIdentityInfo(HLERequestContext& ctx); - void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); - void SetAlbumImageOrientation(HLERequestContext& ctx); - void IsSystemBufferSharingEnabled(HLERequestContext& ctx); - void GetSystemSharedBufferHandle(HLERequestContext& ctx); - void GetSystemSharedLayerHandle(HLERequestContext& ctx); - void CreateManagedDisplayLayer(HLERequestContext& ctx); - void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); - void SetHandlesRequestToDisplay(HLERequestContext& ctx); - void ApproveToDisplay(HLERequestContext& ctx); - void SetMediaPlaybackState(HLERequestContext& ctx); - void SetIdleTimeDetectionExtension(HLERequestContext& ctx); - void GetIdleTimeDetectionExtension(HLERequestContext& ctx); - void ReportUserIsActive(HLERequestContext& ctx); - void SetAutoSleepDisabled(HLERequestContext& ctx); - void IsAutoSleepDisabled(HLERequestContext& ctx); - void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx); - void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx); - void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx); - void SaveCurrentScreenshot(HLERequestContext& ctx); - void SetRecordVolumeMuted(HLERequestContext& ctx); - - Result EnsureBufferSharingEnabled(Kernel::KProcess* process); - - Nvnflinger::Nvnflinger& nvnflinger; - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp new file mode 100644 index 000000000..21747783a --- /dev/null +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/service/all_system_applet_proxies_service.h" +#include "core/hle/service/am/service/library_applet_proxy.h" +#include "core/hle/service/am/service/system_applet_proxy.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_) + : ServiceFramework{system_, "appletAE"} { + // clang-format off + static const FunctionInfo functions[] = { + {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, + {200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"}, + {201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"}, + {300, nullptr, "OpenOverlayAppletProxy"}, + {350, nullptr, "OpenSystemApplicationProxy"}, + {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, + {410, nullptr, "GetSystemAppletControllerForDebug"}, + {1000, nullptr, "GetDebugFunctions"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAllSystemAppletProxiesService::~IAllSystemAppletProxiesService() = default; + +Result IAllSystemAppletProxiesService::OpenSystemAppletProxy( + Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy, ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle) { + LOG_DEBUG(Service_AM, "called"); + + if (const auto applet = this->GetAppletFromProcessId(pid); applet) { + *out_system_applet_proxy = + std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get()); + R_SUCCEED(); + } else { + UNIMPLEMENTED(); + R_THROW(ResultUnknown); + } +} + +Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy( + Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle, + InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) { + LOG_DEBUG(Service_AM, "called"); + + if (const auto applet = this->GetAppletFromProcessId(pid); applet) { + *out_library_applet_proxy = + std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get()); + R_SUCCEED(); + } else { + UNIMPLEMENTED(); + R_THROW(ResultUnknown); + } +} + +Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld( + Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle) { + LOG_DEBUG(Service_AM, "called"); + + AppletAttribute attribute{}; + R_RETURN( + this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute)); +} + +std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId( + ProcessId process_id) { + return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.h b/src/core/hle/service/am/service/all_system_applet_proxies_service.h new file mode 100644 index 000000000..0e2dcb86d --- /dev/null +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service { + +namespace AM { + +struct Applet; +struct AppletAttribute; +class ILibraryAppletProxy; +class ISystemAppletProxy; + +class IAllSystemAppletProxiesService final + : public ServiceFramework<IAllSystemAppletProxiesService> { +public: + explicit IAllSystemAppletProxiesService(Core::System& system_); + ~IAllSystemAppletProxiesService() override; + +private: + Result OpenSystemAppletProxy(Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy, + ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle); + Result OpenLibraryAppletProxy(Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, + ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle, + InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute); + Result OpenLibraryAppletProxyOld( + Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle); + +private: + std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); +}; + +} // namespace AM +} // namespace Service diff --git a/src/core/hle/service/am/service/applet_common_functions.cpp b/src/core/hle/service/am/service/applet_common_functions.cpp new file mode 100644 index 000000000..0f29ab285 --- /dev/null +++ b/src/core/hle/service/am/service/applet_common_functions.cpp @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/service/applet_common_functions.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, + std::shared_ptr<Applet> applet_) + : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "SetTerminateResult"}, + {10, nullptr, "ReadThemeStorage"}, + {11, nullptr, "WriteThemeStorage"}, + {20, nullptr, "PushToAppletBoundChannel"}, + {21, nullptr, "TryPopFromAppletBoundChannel"}, + {40, nullptr, "GetDisplayLogicalResolution"}, + {42, nullptr, "SetDisplayMagnification"}, + {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, + {51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"}, + {52, nullptr, "IsHomeButtonShortPressedBlocked"}, + {60, nullptr, "IsVrModeCurtainRequired"}, + {61, nullptr, "IsSleepRequiredByHighTemperature"}, + {62, nullptr, "IsSleepRequiredByLowBattery"}, + {70, D<&IAppletCommonFunctions::SetCpuBoostRequestPriority>, "SetCpuBoostRequestPriority"}, + {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"}, + {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"}, + {90, nullptr, "OpenNamedChannelAsParent"}, + {91, nullptr, "OpenNamedChannelAsChild"}, + {100, nullptr, "SetApplicationCoreUsageMode"}, + {300, D<&IAppletCommonFunctions::GetCurrentApplicationId>, "GetCurrentApplicationId"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAppletCommonFunctions::~IAppletCommonFunctions() = default; + +Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled( + Out<bool> out_home_button_double_click_enabled) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_home_button_double_click_enabled = false; + R_SUCCEED(); +} + +Result IAppletCommonFunctions::SetCpuBoostRequestPriority(s32 priority) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->cpu_boost_request_priority = priority; + R_SUCCEED(); +} + +Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_application_id = system.GetApplicationProcessProgramID() & ~0xFFFULL; + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/applet_common_functions.h b/src/core/hle/service/am/service/applet_common_functions.h new file mode 100644 index 000000000..4424fc83d --- /dev/null +++ b/src/core/hle/service/am/service/applet_common_functions.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; + +class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> { +public: + explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_); + ~IAppletCommonFunctions() override; + +private: + Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled); + Result SetCpuBoostRequestPriority(s32 priority); + Result GetCurrentApplicationId(Out<u64> out_application_id); + + const std::shared_ptr<Applet> applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp new file mode 100644 index 000000000..6e7d110e8 --- /dev/null +++ b/src/core/hle/service/am/service/application_accessor.cpp @@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/result.h" +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/applet_data_broker.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/service/application_accessor.h" +#include "core/hle/service/am/service/library_applet_accessor.h" +#include "core/hle/service/am/service/storage.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"}, + {1, nullptr, "IsCompleted"}, + {10, D<&IApplicationAccessor::Start>, "Start"}, + {20, D<&IApplicationAccessor::RequestExit>, "RequestExit"}, + {25, D<&IApplicationAccessor::Terminate>, "Terminate"}, + {30, D<&IApplicationAccessor::GetResult>, "GetResult"}, + {101, D<&IApplicationAccessor::RequestForApplicationToGetForeground>, "RequestForApplicationToGetForeground"}, + {110, nullptr, "TerminateAllLibraryApplets"}, + {111, nullptr, "AreAnyLibraryAppletsLeft"}, + {112, D<&IApplicationAccessor::GetCurrentLibraryApplet>, "GetCurrentLibraryApplet"}, + {120, nullptr, "GetApplicationId"}, + {121, D<&IApplicationAccessor::PushLaunchParameter>, "PushLaunchParameter"}, + {122, D<&IApplicationAccessor::GetApplicationControlProperty>, "GetApplicationControlProperty"}, + {123, nullptr, "GetApplicationLaunchProperty"}, + {124, nullptr, "GetApplicationLaunchRequestInfo"}, + {130, D<&IApplicationAccessor::SetUsers>, "SetUsers"}, + {131, D<&IApplicationAccessor::CheckRightsEnvironmentAvailable>, "CheckRightsEnvironmentAvailable"}, + {132, D<&IApplicationAccessor::GetNsRightsEnvironmentHandle>, "GetNsRightsEnvironmentHandle"}, + {140, nullptr, "GetDesirableUids"}, + {150, D<&IApplicationAccessor::ReportApplicationExitTimeout>, "ReportApplicationExitTimeout"}, + {160, nullptr, "SetApplicationAttribute"}, + {170, nullptr, "HasSaveDataAccessPermission"}, + {180, nullptr, "PushToFriendInvitationStorageChannel"}, + {190, nullptr, "PushToNotificationStorageChannel"}, + {200, nullptr, "RequestApplicationSoftReset"}, + {201, nullptr, "RestartApplicationTimer"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationAccessor::~IApplicationAccessor() = default; + +Result IApplicationAccessor::Start() { + LOG_INFO(Service_AM, "called"); + m_applet->process->Run(); + R_SUCCEED(); +} + +Result IApplicationAccessor::RequestExit() { + LOG_INFO(Service_AM, "called"); + m_applet->message_queue.RequestExit(); + R_SUCCEED(); +} + +Result IApplicationAccessor::Terminate() { + LOG_INFO(Service_AM, "called"); + m_applet->process->Terminate(); + R_SUCCEED(); +} + +Result IApplicationAccessor::GetResult() { + LOG_INFO(Service_AM, "called"); + R_SUCCEED(); +} + +Result IApplicationAccessor::GetAppletStateChangedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle(); + R_SUCCEED(); +} + +Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind, + SharedPointer<IStorage> storage) { + LOG_INFO(Service_AM, "called, kind={}", kind); + + switch (kind) { + case LaunchParameterKind::AccountPreselectedUser: + m_applet->preselected_user_launch_parameter.push_back(storage->GetData()); + R_SUCCEED(); + default: + R_THROW(ResultUnknown); + } +} + +Result IApplicationAccessor::GetApplicationControlProperty( + OutBuffer<BufferAttr_HipcMapAlias> out_control_property) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_THROW(ResultUnknown); +} + +Result IApplicationAccessor::SetUsers(bool enable, + InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids) { + LOG_INFO(Service_AM, "called, enable={} user_id_count={}", enable, user_ids.size()); + R_SUCCEED(); +} + +Result IApplicationAccessor::GetCurrentLibraryApplet( + Out<SharedPointer<ILibraryAppletAccessor>> out_accessor) { + LOG_INFO(Service_AM, "(STUBBED) called"); + *out_accessor = nullptr; + R_SUCCEED(); +} + +Result IApplicationAccessor::RequestForApplicationToGetForeground() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_THROW(ResultUnknown); +} + +Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_is_available = true; + R_SUCCEED(); +} + +Result IApplicationAccessor::GetNsRightsEnvironmentHandle(Out<u64> out_handle) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_handle = 0xdeadbeef; + R_SUCCEED(); +} + +Result IApplicationAccessor::ReportApplicationExitTimeout() { + LOG_ERROR(Service_AM, "called"); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_accessor.h b/src/core/hle/service/am/service/application_accessor.h new file mode 100644 index 000000000..39a9b2153 --- /dev/null +++ b/src/core/hle/service/am/service/application_accessor.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/uuid.h" +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; +class ILibraryAppletAccessor; +class IStorage; + +class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> { +public: + explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet); + ~IApplicationAccessor() override; + +private: + Result Start(); + Result RequestExit(); + Result Terminate(); + Result GetResult(); + Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result PushLaunchParameter(LaunchParameterKind kind, SharedPointer<IStorage> storage); + Result GetApplicationControlProperty(OutBuffer<BufferAttr_HipcMapAlias> out_control_property); + Result SetUsers(bool enable, InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids); + Result GetCurrentLibraryApplet(Out<SharedPointer<ILibraryAppletAccessor>> out_accessor); + Result RequestForApplicationToGetForeground(); + Result CheckRightsEnvironmentAvailable(Out<bool> out_is_available); + Result GetNsRightsEnvironmentHandle(Out<u64> out_handle); + Result ReportApplicationExitTimeout(); + + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_creator.cpp b/src/core/hle/service/am/service/application_creator.cpp new file mode 100644 index 000000000..568bb0122 --- /dev/null +++ b/src/core/hle/service/am/service/application_creator.cpp @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/service/application_accessor.h" +#include "core/hle/service/am/service/application_creator.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IApplicationCreator::IApplicationCreator(Core::System& system_) + : ServiceFramework{system_, "IApplicationCreator"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"}, + {1, nullptr, "PopLaunchRequestedApplication"}, + {10, nullptr, "CreateSystemApplication"}, + {100, nullptr, "PopFloatingApplicationForDevelopment"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationCreator::~IApplicationCreator() = default; + +Result IApplicationCreator::CreateApplication( + Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) { + LOG_ERROR(Service_NS, "called, application_id={:x}", application_id); + R_THROW(ResultUnknown); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_creator.h b/src/core/hle/service/am/service/application_creator.h new file mode 100644 index 000000000..9f939ebf6 --- /dev/null +++ b/src/core/hle/service/am/service/application_creator.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class IApplicationAccessor; +struct Applet; + +class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { +public: + explicit IApplicationCreator(Core::System& system_); + ~IApplicationCreator() override; + +private: + Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id); +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp new file mode 100644 index 000000000..cb53b07e0 --- /dev/null +++ b/src/core/hle/service/am/service/application_functions.cpp @@ -0,0 +1,485 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "common/uuid.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/file_sys/savedata_factory.h" +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/service/application_functions.h" +#include "core/hle/service/am/service/storage.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/filesystem/save_data_controller.h" +#include "core/hle/service/glue/glue_manager.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/service_getter_interface.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::AM { + +IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"}, + {10, nullptr, "CreateApplicationAndPushAndRequestToStart"}, + {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, + {12, nullptr, "CreateApplicationAndRequestToStart"}, + {13, nullptr, "CreateApplicationAndRequestToStartForQuest"}, + {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"}, + {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"}, + {20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"}, + {21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"}, + {22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"}, + {23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"}, + {24, nullptr, "GetLaunchStorageInfoForDebug"}, + {25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"}, + {26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"}, + {27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"}, + {28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"}, + {29, D<&IApplicationFunctions::GetCacheStorageMax>, "GetCacheStorageMax"}, + {30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"}, + {31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"}, + {32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"}, + {33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"}, + {34, nullptr, "SelectApplicationLicense"}, + {35, nullptr, "GetDeviceSaveDataSizeMax"}, + {36, nullptr, "GetLimitedApplicationLicense"}, + {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, + {40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"}, + {50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"}, + {60, nullptr, "SetMediaPlaybackStateForApplication"}, + {65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"}, + {66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"}, + {67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"}, + {68, nullptr, "RequestFlushGamePlayingMovieForDebug"}, + {70, nullptr, "RequestToShutdown"}, + {71, nullptr, "RequestToReboot"}, + {72, nullptr, "RequestToSleep"}, + {80, nullptr, "ExitAndRequestToShowThanksMessage"}, + {90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"}, + {100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"}, + {101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"}, + {102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"}, + {110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"}, + {111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"}, + {120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"}, + {121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"}, + {122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"}, + {123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"}, + {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, + {130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"}, + {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, + {140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"}, + {141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"}, + {150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"}, + {151, nullptr, "TryPopFromNotificationStorageChannel"}, + {160, D<&IApplicationFunctions::GetHealthWarningDisappearedSystemEvent>, "GetHealthWarningDisappearedSystemEvent"}, + {170, nullptr, "SetHdcpAuthenticationActivated"}, + {180, nullptr, "GetLaunchRequiredVersion"}, + {181, nullptr, "UpgradeLaunchRequiredVersion"}, + {190, nullptr, "SendServerMaintenanceOverlayNotification"}, + {200, nullptr, "GetLastApplicationExitReason"}, + {500, nullptr, "StartContinuousRecordingFlushForDebug"}, + {1000, nullptr, "CreateMovieMaker"}, + {1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationFunctions::~IApplicationFunctions() = default; + +Result IApplicationFunctions::PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage, + LaunchParameterKind launch_parameter_kind) { + LOG_INFO(Service_AM, "called, kind={}", launch_parameter_kind); + + std::scoped_lock lk{m_applet->lock}; + + auto& channel = launch_parameter_kind == LaunchParameterKind::UserChannel + ? m_applet->user_channel_launch_parameter + : m_applet->preselected_user_launch_parameter; + + if (channel.empty()) { + LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", + launch_parameter_kind); + R_THROW(AM::ResultNoDataInChannel); + } + + auto data = channel.back(); + channel.pop_back(); + + *out_storage = std::make_shared<IStorage>(system, std::move(data)); + R_SUCCEED(); +} + +Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID user_id) { + LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString()); + + FileSys::SaveDataAttribute attribute{}; + attribute.title_id = m_applet->program_id; + attribute.user_id = user_id.AsU128(); + attribute.type = FileSys::SaveDataType::SaveData; + + FileSys::VirtualDir save_data{}; + R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( + &save_data, FileSys::SaveDataSpaceId::NandUser, attribute)); + + *out_size = 0; + R_SUCCEED(); +} + +Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) { + // FIXME: all of this stuff belongs to ns + // TODO(bunnei): This should be configurable + LOG_DEBUG(Service_AM, "called"); + + // Get supported languages from NACP, if possible + // Default to 0 (all languages supported) + u32 supported_languages = 0; + + const auto res = [this] { + const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(), + system.GetContentProvider()}; + auto metadata = pm.GetControlMetadata(); + if (metadata.first != nullptr) { + return metadata; + } + + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id), + system.GetFileSystemController(), + system.GetContentProvider()}; + return pm_update.GetControlMetadata(); + }(); + + if (res.first != nullptr) { + supported_languages = res.first->GetSupportedLanguages(); + } + + // Call IApplicationManagerInterface implementation. + auto& service_manager = system.ServiceManager(); + auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2"); + + std::shared_ptr<NS::IApplicationManagerInterface> app_man; + R_TRY(ns_am2->GetApplicationManagerInterface(&app_man)); + + // Get desired application language + NS::ApplicationLanguage desired_language{}; + R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages)); + + // Convert to settings language code. + R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(out_language_code, desired_language)); + + LOG_DEBUG(Service_AM, "got desired_language={:016X}", *out_language_code); + R_SUCCEED(); +} + +Result IApplicationFunctions::SetTerminateResult(Result terminate_result) { + LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(), + static_cast<u32>(terminate_result.GetModule()) + 2000, + terminate_result.GetDescription()); + + std::scoped_lock lk{m_applet->lock}; + m_applet->terminate_result = terminate_result; + + R_SUCCEED(); +} + +Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) { + LOG_DEBUG(Service_AM, "called"); + + const auto res = [this] { + const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(), + system.GetContentProvider()}; + auto metadata = pm.GetControlMetadata(); + if (metadata.first != nullptr) { + return metadata; + } + + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id), + system.GetFileSystemController(), + system.GetContentProvider()}; + return pm_update.GetControlMetadata(); + }(); + + if (res.first != nullptr) { + const auto& version = res.first->GetVersionString(); + std::memcpy(out_display_version->string.data(), version.data(), + std::min(version.size(), out_display_version->string.size())); + } else { + static constexpr char default_version[]{"1.0.0"}; + std::memcpy(out_display_version->string.data(), default_version, sizeof(default_version)); + } + + out_display_version->string[out_display_version->string.size() - 1] = '\0'; + R_SUCCEED(); +} + +Result IApplicationFunctions::ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type, + Common::UUID user_id, u64 normal_size, + u64 journal_size) { + LOG_DEBUG(Service_AM, "called with type={} user_id={} normal={:#x} journal={:#x}", + static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size); + + system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize( + type, m_applet->program_id, user_id.AsU128(), {normal_size, journal_size}); + + // The following value is used to indicate the amount of space remaining on failure + // due to running out of space. Since we always succeed, this should be 0. + *out_required_size = 0; + + R_SUCCEED(); +} + +Result IApplicationFunctions::GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size, + FileSys::SaveDataType type, Common::UUID user_id) { + LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString()); + + const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize( + type, m_applet->program_id, user_id.AsU128()); + + *out_normal_size = size.normal; + *out_journal_size = size.journal; + R_SUCCEED(); +} + +Result IApplicationFunctions::CreateCacheStorage(Out<u32> out_target_media, + Out<u64> out_required_size, u16 index, + u64 normal_size, u64 journal_size) { + LOG_WARNING(Service_AM, "(STUBBED) called with index={} size={:#x} journal_size={:#x}", index, + normal_size, journal_size); + + *out_target_media = 1; // Nand + *out_required_size = 0; + + R_SUCCEED(); +} + +Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size, + Out<u64> out_max_journal_size) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + *out_max_normal_size = 0xFFFFFFF; + *out_max_journal_size = 0xFFFFFFF; + + R_SUCCEED(); +} + +Result IApplicationFunctions::GetCacheStorageMax(Out<u32> out_cache_storage_index_max, + Out<u64> out_max_journal_size) { + LOG_DEBUG(Service_AM, "called"); + + std::vector<u8> nacp; + R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id)); + + auto raw_nacp = std::make_unique<FileSys::RawNACP>(); + std::memcpy(raw_nacp.get(), nacp.data(), std::min(sizeof(*raw_nacp), nacp.size())); + + *out_cache_storage_index_max = static_cast<u32>(raw_nacp->cache_storage_max_index); + *out_max_journal_size = static_cast<u64>(raw_nacp->cache_storage_data_and_journal_max_size); + + R_SUCCEED(); +} + +Result IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(s64 unused) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->home_button_long_pressed_blocked = true; + m_applet->home_button_short_pressed_blocked = true; + + R_SUCCEED(); +} + +Result IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->home_button_long_pressed_blocked = false; + m_applet->home_button_short_pressed_blocked = false; + + R_SUCCEED(); +} + +Result IApplicationFunctions::BeginBlockingHomeButton(s64 timeout_ns) { + LOG_WARNING(Service_AM, "(STUBBED) called, timeout_ns={}", timeout_ns); + + std::scoped_lock lk{m_applet->lock}; + m_applet->home_button_long_pressed_blocked = true; + m_applet->home_button_short_pressed_blocked = true; + m_applet->home_button_double_click_enabled = true; + + R_SUCCEED(); +} + +Result IApplicationFunctions::EndBlockingHomeButton() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->home_button_long_pressed_blocked = false; + m_applet->home_button_short_pressed_blocked = false; + m_applet->home_button_double_click_enabled = false; + + R_SUCCEED(); +} + +Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_became_running = true; + R_SUCCEED(); +} + +Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_pseudo_device_id = {}; + R_SUCCEED(); +} + +Result IApplicationFunctions::IsGamePlayRecordingSupported( + Out<bool> out_is_game_play_recording_supported) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_is_game_play_recording_supported = m_applet->game_play_recording_supported; + R_SUCCEED(); +} + +Result IApplicationFunctions::InitializeGamePlayRecording( + u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IApplicationFunctions::SetGamePlayRecordingState( + GamePlayRecordingState game_play_recording_state) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->game_play_recording_state = game_play_recording_state; + + R_SUCCEED(); +} + +Result IApplicationFunctions::EnableApplicationCrashReport(bool enabled) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->application_crash_report_enabled = enabled; + + R_SUCCEED(); +} + +Result IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer( + s32 width, s32 height, u64 transfer_memory_size, + InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IApplicationFunctions::SetApplicationCopyrightImage( + s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode, + InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IApplicationFunctions::SetApplicationCopyrightVisibility(bool visible) { + LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", visible); + R_SUCCEED(); +} + +Result IApplicationFunctions::QueryApplicationPlayStatistics( + Out<s32> out_entries, + OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics, + InArray<u64, BufferAttr_HipcMapAlias> application_ids) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_entries = 0; + R_SUCCEED(); +} + +Result IApplicationFunctions::QueryApplicationPlayStatisticsByUid( + Out<s32> out_entries, + OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics, + Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_entries = 0; + R_SUCCEED(); +} + +Result IApplicationFunctions::ExecuteProgram(ProgramSpecifyKind kind, u64 value) { + LOG_WARNING(Service_AM, "(STUBBED) called, kind={}, value={}", kind, value); + ASSERT(kind == ProgramSpecifyKind::ExecuteProgram || + kind == ProgramSpecifyKind::RestartProgram); + + // Copy user channel ownership into the system so that it will be preserved + system.GetUserChannel() = m_applet->user_channel_launch_parameter; + system.ExecuteProgram(value); + R_SUCCEED(); +} + +Result IApplicationFunctions::ClearUserChannel() { + LOG_DEBUG(Service_AM, "called"); + m_applet->user_channel_launch_parameter.clear(); + R_SUCCEED(); +} + +Result IApplicationFunctions::UnpopToUserChannel(SharedPointer<IStorage> storage) { + LOG_DEBUG(Service_AM, "called"); + m_applet->user_channel_launch_parameter.push_back(storage->GetData()); + R_SUCCEED(); +} + +Result IApplicationFunctions::GetPreviousProgramIndex(Out<s32> out_previous_program_index) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_previous_program_index = m_applet->previous_program_index; + R_SUCCEED(); +} + +Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_event = m_applet->gpu_error_detected_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationFunctions::GetFriendInvitationStorageChannelEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = m_applet->friend_invitation_storage_channel_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( + Out<SharedPointer<IStorage>> out_storage) { + LOG_INFO(Service_AM, "(STUBBED) called"); + R_THROW(AM::ResultNoDataInChannel); +} + +Result IApplicationFunctions::GetNotificationStorageChannelEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = m_applet->notification_storage_channel_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = m_applet->health_warning_disappeared_system_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationFunctions::PrepareForJit() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->jit_service_launched = true; + + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h new file mode 100644 index 000000000..10025a152 --- /dev/null +++ b/src/core/hle/service/am/service/application_functions.h @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/uuid.h" +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace FileSys { +enum class SaveDataType : u8; +} + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::AM { + +struct Applet; +class IStorage; + +class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { +public: + explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet); + ~IApplicationFunctions() override; + +private: + Result PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage, + LaunchParameterKind launch_parameter_kind); + Result EnsureSaveData(Out<u64> out_size, Common::UUID user_id); + Result GetDesiredLanguage(Out<u64> out_language_code); + Result SetTerminateResult(Result terminate_result); + Result GetDisplayVersion(Out<DisplayVersion> out_display_version); + Result ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type, + Common::UUID user_id, u64 normal_size, u64 journal_size); + Result GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size, + FileSys::SaveDataType type, Common::UUID user_id); + Result CreateCacheStorage(Out<u32> out_target_media, Out<u64> out_required_size, u16 index, + u64 normal_size, u64 journal_size); + Result GetSaveDataSizeMax(Out<u64> out_max_normal_size, Out<u64> out_max_journal_size); + Result GetCacheStorageMax(Out<u32> out_cache_storage_index_max, Out<u64> out_max_journal_size); + Result BeginBlockingHomeButtonShortAndLongPressed(s64 unused); + Result EndBlockingHomeButtonShortAndLongPressed(); + Result BeginBlockingHomeButton(s64 timeout_ns); + Result EndBlockingHomeButton(); + Result NotifyRunning(Out<bool> out_became_running); + Result GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id); + Result IsGamePlayRecordingSupported(Out<bool> out_is_game_play_recording_supported); + Result InitializeGamePlayRecording( + u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle); + Result SetGamePlayRecordingState(GamePlayRecordingState game_play_recording_state); + Result EnableApplicationCrashReport(bool enabled); + Result InitializeApplicationCopyrightFrameBuffer( + s32 width, s32 height, u64 transfer_memory_size, + InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle); + Result SetApplicationCopyrightImage( + s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode, + InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data); + Result SetApplicationCopyrightVisibility(bool visible); + Result QueryApplicationPlayStatistics( + Out<s32> out_entries, + OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics, + InArray<u64, BufferAttr_HipcMapAlias> application_ids); + Result QueryApplicationPlayStatisticsByUid( + Out<s32> out_entries, + OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics, + Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids); + Result ExecuteProgram(ProgramSpecifyKind kind, u64 value); + Result ClearUserChannel(); + Result UnpopToUserChannel(SharedPointer<IStorage> storage); + Result GetPreviousProgramIndex(Out<s32> out_previous_program_index); + Result GetGpuErrorDetectedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetFriendInvitationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage); + Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result PrepareForJit(); + + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp new file mode 100644 index 000000000..19d6a3b89 --- /dev/null +++ b/src/core/hle/service/am/service/application_proxy.cpp @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/applet_common_functions.h" +#include "core/hle/service/am/service/application_functions.h" +#include "core/hle/service/am/service/application_proxy.h" +#include "core/hle/service/am/service/audio_controller.h" +#include "core/hle/service/am/service/common_state_getter.h" +#include "core/hle/service/am/service/debug_functions.h" +#include "core/hle/service/am/service/display_controller.h" +#include "core/hle/service/am/service/library_applet_creator.h" +#include "core/hle/service/am/service/process_winding_controller.h" +#include "core/hle/service/am/service/self_controller.h" +#include "core/hle/service/am/service/window_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process) + : ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{ + std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, + {1, D<&IApplicationProxy::GetSelfController>, "GetSelfController"}, + {2, D<&IApplicationProxy::GetWindowController>, "GetWindowController"}, + {3, D<&IApplicationProxy::GetAudioController>, "GetAudioController"}, + {4, D<&IApplicationProxy::GetDisplayController>, "GetDisplayController"}, + {10, D<&IApplicationProxy::GetProcessWindingController>, "GetProcessWindingController"}, + {11, D<&IApplicationProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"}, + {20, D<&IApplicationProxy::GetApplicationFunctions>, "GetApplicationFunctions"}, + {1000, D<&IApplicationProxy::GetDebugFunctions>, "GetDebugFunctions"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationProxy::~IApplicationProxy() = default; + +Result IApplicationProxy::GetAudioController( + Out<SharedPointer<IAudioController>> out_audio_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_audio_controller = std::make_shared<IAudioController>(system); + R_SUCCEED(); +} + +Result IApplicationProxy::GetDisplayController( + Out<SharedPointer<IDisplayController>> out_display_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_display_controller = std::make_shared<IDisplayController>(system, m_applet); + R_SUCCEED(); +} + +Result IApplicationProxy::GetProcessWindingController( + Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet); + R_SUCCEED(); +} + +Result IApplicationProxy::GetDebugFunctions( + Out<SharedPointer<IDebugFunctions>> out_debug_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_debug_functions = std::make_shared<IDebugFunctions>(system); + R_SUCCEED(); +} + +Result IApplicationProxy::GetWindowController( + Out<SharedPointer<IWindowController>> out_window_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_window_controller = std::make_shared<IWindowController>(system, m_applet); + R_SUCCEED(); +} + +Result IApplicationProxy::GetSelfController( + Out<SharedPointer<ISelfController>> out_self_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process); + R_SUCCEED(); +} + +Result IApplicationProxy::GetCommonStateGetter( + Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) { + LOG_DEBUG(Service_AM, "called"); + *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet); + R_SUCCEED(); +} + +Result IApplicationProxy::GetLibraryAppletCreator( + Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { + LOG_DEBUG(Service_AM, "called"); + *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet); + R_SUCCEED(); +} + +Result IApplicationProxy::GetApplicationFunctions( + Out<SharedPointer<IApplicationFunctions>> out_application_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_application_functions = std::make_shared<IApplicationFunctions>(system, m_applet); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h new file mode 100644 index 000000000..6da350df7 --- /dev/null +++ b/src/core/hle/service/am/service/application_proxy.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; +class IAudioController; +class IApplicationFunctions; +class ICommonStateGetter; +class IDebugFunctions; +class IDisplayController; +class ILibraryAppletCreator; +class IProcessWindingController; +class ISelfController; +class IWindowController; + +class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { +public: + explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process); + ~IApplicationProxy(); + +private: + Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller); + Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller); + Result GetProcessWindingController( + Out<SharedPointer<IProcessWindingController>> out_process_winding_controller); + Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions); + Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller); + Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller); + Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter); + Result GetLibraryAppletCreator( + Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator); + Result GetApplicationFunctions( + Out<SharedPointer<IApplicationFunctions>> out_application_functions); + +private: + Kernel::KProcess* const m_process; + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp new file mode 100644 index 000000000..fd66e77b9 --- /dev/null +++ b/src/core/hle/service/am/service/application_proxy_service.cpp @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/service/application_proxy.h" +#include "core/hle/service/am/service/application_proxy_service.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IApplicationProxyService::IApplicationProxyService(Core::System& system_) + : ServiceFramework{system_, "appletOE"} { + static const FunctionInfo functions[] = { + {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"}, + }; + RegisterHandlers(functions); +} + +IApplicationProxyService::~IApplicationProxyService() = default; + +Result IApplicationProxyService::OpenApplicationProxy( + Out<SharedPointer<IApplicationProxy>> out_application_proxy, ClientProcessId pid, + InCopyHandle<Kernel::KProcess> process_handle) { + LOG_DEBUG(Service_AM, "called"); + + if (const auto applet = this->GetAppletFromProcessId(pid)) { + *out_application_proxy = + std::make_shared<IApplicationProxy>(system, applet, process_handle.Get()); + R_SUCCEED(); + } else { + UNIMPLEMENTED(); + R_THROW(ResultUnknown); + } +} + +std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) { + return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h new file mode 100644 index 000000000..8efafa31a --- /dev/null +++ b/src/core/hle/service/am/service/application_proxy_service.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service { + +namespace AM { + +struct Applet; +class IApplicationProxy; + +class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> { +public: + explicit IApplicationProxyService(Core::System& system_); + ~IApplicationProxyService() override; + +private: + Result OpenApplicationProxy(Out<SharedPointer<IApplicationProxy>> out_application_proxy, + ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle); + +private: + std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); +}; + +} // namespace AM +} // namespace Service diff --git a/src/core/hle/service/am/service/audio_controller.cpp b/src/core/hle/service/am/service/audio_controller.cpp new file mode 100644 index 000000000..ad731c7bd --- /dev/null +++ b/src/core/hle/service/am/service/audio_controller.cpp @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/audio_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IAudioController::IAudioController(Core::System& system_) + : ServiceFramework{system_, "IAudioController"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IAudioController::SetExpectedMasterVolume>, "SetExpectedMasterVolume"}, + {1, D<&IAudioController::GetMainAppletExpectedMasterVolume>, "GetMainAppletExpectedMasterVolume"}, + {2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"}, + {3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"}, + {4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAudioController::~IAudioController() = default; + +Result IAudioController::SetExpectedMasterVolume(f32 main_applet_volume, + f32 library_applet_volume) { + LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}", + main_applet_volume, library_applet_volume); + + // Ensure the volume values remain within the 0-100% range + m_main_applet_volume = std::clamp(main_applet_volume, MinAllowedVolume, MaxAllowedVolume); + m_library_applet_volume = std::clamp(library_applet_volume, MinAllowedVolume, MaxAllowedVolume); + + R_SUCCEED(); +} + +Result IAudioController::GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume) { + LOG_DEBUG(Service_AM, "called. main_applet_volume={}", m_main_applet_volume); + *out_main_applet_volume = m_main_applet_volume; + R_SUCCEED(); +} + +Result IAudioController::GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume) { + LOG_DEBUG(Service_AM, "called. library_applet_volume={}", m_library_applet_volume); + *out_library_applet_volume = m_library_applet_volume; + R_SUCCEED(); +} + +Result IAudioController::ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns) { + LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", volume, fade_time_ns); + + m_main_applet_volume = std::clamp(volume, MinAllowedVolume, MaxAllowedVolume); + m_fade_time_ns = std::chrono::nanoseconds{fade_time_ns}; + + R_SUCCEED(); +} + +Result IAudioController::SetTransparentVolumeRate(f32 transparent_volume_rate) { + LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate); + + // Clamp volume range to 0-100%. + m_transparent_volume_rate = + std::clamp(transparent_volume_rate, MinAllowedVolume, MaxAllowedVolume); + + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/audio_controller.h b/src/core/hle/service/am/service/audio_controller.h new file mode 100644 index 000000000..4b0f3f9ae --- /dev/null +++ b/src/core/hle/service/am/service/audio_controller.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class IAudioController final : public ServiceFramework<IAudioController> { +public: + explicit IAudioController(Core::System& system_); + ~IAudioController() override; + +private: + Result SetExpectedMasterVolume(f32 main_applet_volume, f32 library_applet_volume); + Result GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume); + Result GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume); + Result ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns); + Result SetTransparentVolumeRate(f32 transparent_volume_rate); + + static constexpr float MinAllowedVolume = 0.0f; + static constexpr float MaxAllowedVolume = 1.0f; + + float m_main_applet_volume{0.25f}; + float m_library_applet_volume{MaxAllowedVolume}; + float m_transparent_volume_rate{MinAllowedVolume}; + + // Volume transition fade time in nanoseconds. + // e.g. If the main applet volume was 0% and was changed to 50% + // with a fade of 50ns, then over the course of 50ns, + // the volume will gradually fade up to 50% + std::chrono::nanoseconds m_fade_time_ns{0}; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp new file mode 100644 index 000000000..548498e83 --- /dev/null +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -0,0 +1,278 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/service/common_state_getter.h" +#include "core/hle/service/am/service/lock_accessor.h" +#include "core/hle/service/apm/apm_interface.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/pm/pm.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/vi.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::AM { + +ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "ICommonStateGetter"}, m_applet{std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ICommonStateGetter::GetEventHandle>, "GetEventHandle"}, + {1, D<&ICommonStateGetter::ReceiveMessage>, "ReceiveMessage"}, + {2, nullptr, "GetThisAppletKind"}, + {3, nullptr, "AllowToEnterSleep"}, + {4, nullptr, "DisallowToEnterSleep"}, + {5, D<&ICommonStateGetter::GetOperationMode>, "GetOperationMode"}, + {6, D<&ICommonStateGetter::GetPerformanceMode>, "GetPerformanceMode"}, + {7, nullptr, "GetCradleStatus"}, + {8, D<&ICommonStateGetter::GetBootMode>, "GetBootMode"}, + {9, D<&ICommonStateGetter::GetCurrentFocusState>, "GetCurrentFocusState"}, + {10, D<&ICommonStateGetter::RequestToAcquireSleepLock>, "RequestToAcquireSleepLock"}, + {11, nullptr, "ReleaseSleepLock"}, + {12, nullptr, "ReleaseSleepLockTransiently"}, + {13, D<&ICommonStateGetter::GetAcquiredSleepLockEvent>, "GetAcquiredSleepLockEvent"}, + {14, nullptr, "GetWakeupCount"}, + {20, nullptr, "PushToGeneralChannel"}, + {30, nullptr, "GetHomeButtonReaderLockAccessor"}, + {31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"}, + {32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"}, + {40, nullptr, "GetCradleFwVersion"}, + {50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled"}, + {51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled"}, + {52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled"}, + {53, D<&ICommonStateGetter::BeginVrModeEx>, "BeginVrModeEx"}, + {54, D<&ICommonStateGetter::EndVrModeEx>, "EndVrModeEx"}, + {55, D<&ICommonStateGetter::IsInControllerFirmwareUpdateSection>, "IsInControllerFirmwareUpdateSection"}, + {59, nullptr, "SetVrPositionForDebug"}, + {60, D<&ICommonStateGetter::GetDefaultDisplayResolution>, "GetDefaultDisplayResolution"}, + {61, D<&ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent>, "GetDefaultDisplayResolutionChangeEvent"}, + {62, nullptr, "GetHdcpAuthenticationState"}, + {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, + {64, nullptr, "SetTvPowerStateMatchingMode"}, + {65, nullptr, "GetApplicationIdByContentActionName"}, + {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, + {67, nullptr, "CancelCpuBoostMode"}, + {68, D<&ICommonStateGetter::GetBuiltInDisplayType>, "GetBuiltInDisplayType"}, + {80, D<&ICommonStateGetter::PerformSystemButtonPressingIfInFocus>, "PerformSystemButtonPressingIfInFocus"}, + {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, + {91, nullptr, "GetCurrentPerformanceConfiguration"}, + {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, + {110, nullptr, "OpenMyGpuErrorHandler"}, + {120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"}, + {200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"}, + {300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"}, + {400, nullptr, "ActivateMigrationService"}, + {401, nullptr, "DeactivateMigrationService"}, + {500, nullptr, "DisableSleepTillShutdown"}, + {501, nullptr, "SuppressDisablingSleepTemporarily"}, + {502, nullptr, "IsSleepEnabled"}, + {503, nullptr, "IsDisablingSleepSuppressed"}, + {900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ICommonStateGetter::~ICommonStateGetter() = default; + +Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = &m_applet->message_queue.GetMessageReceiveEvent(); + R_SUCCEED(); +} + +Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) { + LOG_DEBUG(Service_AM, "called"); + + *out_applet_message = m_applet->message_queue.PopMessage(); + if (*out_applet_message == AppletMessage::None) { + LOG_ERROR(Service_AM, "Tried to pop message but none was available!"); + R_THROW(AM::ResultNoMessages); + } + + R_SUCCEED(); +} + +Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state) { + LOG_DEBUG(Service_AM, "called"); + + std::scoped_lock lk{m_applet->lock}; + *out_focus_state = m_applet->focus_state; + + R_SUCCEED(); +} + +Result ICommonStateGetter::RequestToAcquireSleepLock() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // Sleep lock is acquired immediately. + m_applet->sleep_lock_event.Signal(); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetAcquiredSleepLockEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AM, "called"); + *out_event = m_applet->sleep_lock_event.GetHandle(); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetReaderLockAccessorEx( + Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) { + LOG_INFO(Service_AM, "called, button_type={}", button_type); + *out_lock_accessor = std::make_shared<ILockAccessor>(system); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetWriterLockAccessorEx( + Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) { + LOG_INFO(Service_AM, "called, button_type={}", button_type); + *out_lock_accessor = std::make_shared<ILockAccessor>(system); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = &m_applet->message_queue.GetOperationModeChangedEvent(); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetOperationMode(Out<OperationMode> out_operation_mode) { + const bool use_docked_mode{Settings::IsDockedMode()}; + LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); + *out_operation_mode = use_docked_mode ? OperationMode::Docked : OperationMode::Handheld; + R_SUCCEED(); +} + +Result ICommonStateGetter::GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode) { + LOG_DEBUG(Service_AM, "called"); + *out_performance_mode = system.GetAPMController().GetCurrentPerformanceMode(); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetBootMode(Out<PM::SystemBootMode> out_boot_mode) { + LOG_DEBUG(Service_AM, "called"); + *out_boot_mode = Service::PM::SystemBootMode::Normal; + R_SUCCEED(); +} + +Result ICommonStateGetter::IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled) { + LOG_DEBUG(Service_AM, "called"); + + std::scoped_lock lk{m_applet->lock}; + *out_is_vr_mode_enabled = m_applet->vr_mode_enabled; + R_SUCCEED(); +} + +Result ICommonStateGetter::SetVrModeEnabled(bool is_vr_mode_enabled) { + std::scoped_lock lk{m_applet->lock}; + m_applet->vr_mode_enabled = is_vr_mode_enabled; + LOG_WARNING(Service_AM, "VR Mode is {}", m_applet->vr_mode_enabled ? "on" : "off"); + R_SUCCEED(); +} + +Result ICommonStateGetter::SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled) { + LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}", + is_lcd_backlight_off_enabled); + R_SUCCEED(); +} + +Result ICommonStateGetter::BeginVrModeEx() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{m_applet->lock}; + m_applet->vr_mode_enabled = true; + R_SUCCEED(); +} + +Result ICommonStateGetter::EndVrModeEx() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{m_applet->lock}; + m_applet->vr_mode_enabled = false; + R_SUCCEED(); +} + +Result ICommonStateGetter::IsInControllerFirmwareUpdateSection( + Out<bool> out_is_in_controller_firmware_update_section) { + LOG_INFO(Service_AM, "called"); + *out_is_in_controller_firmware_update_section = false; + R_SUCCEED(); +} + +Result ICommonStateGetter::GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height) { + LOG_DEBUG(Service_AM, "called"); + + if (Settings::IsDockedMode()) { + *out_width = static_cast<u32>(Service::VI::DisplayResolution::DockedWidth); + *out_height = static_cast<u32>(Service::VI::DisplayResolution::DockedHeight); + } else { + *out_width = static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth); + *out_height = static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight); + } + + R_SUCCEED(); +} + +void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS"); + + const auto& sm = system.ServiceManager(); + const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys"); + ASSERT(apm_sys != nullptr); + + apm_sys->SetCpuBoostMode(ctx); +} + +Result ICommonStateGetter::GetBuiltInDisplayType(Out<s32> out_display_type) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_display_type = 0; + R_SUCCEED(); +} + +Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType type) { + LOG_WARNING(Service_AM, "(STUBBED) called, type={}", type); + R_SUCCEED(); +} + +Result ICommonStateGetter::GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_operation_mode_system_info = 0; + R_SUCCEED(); +} + +Result ICommonStateGetter::GetAppletLaunchedHistory( + Out<s32> out_count, OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids) { + LOG_INFO(Service_AM, "called"); + + std::shared_ptr<Applet> current_applet = m_applet; + + for (*out_count = 0; + *out_count < static_cast<s32>(out_applet_ids.size()) && current_applet != nullptr; + /* ... */) { + out_applet_ids[(*out_count)++] = current_applet->applet_id; + current_applet = current_applet->caller_applet.lock(); + } + + R_SUCCEED(); +} + +Result ICommonStateGetter::GetSettingsPlatformRegion( + Out<SysPlatformRegion> out_settings_platform_region) { + LOG_INFO(Service_AM, "called"); + *out_settings_platform_region = SysPlatformRegion::Global; + R_SUCCEED(); +} + +Result ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->request_exit_to_library_applet_at_execute_next_program_enabled = true; + + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/common_state_getter.h b/src/core/hle/service/am/service/common_state_getter.h new file mode 100644 index 000000000..5a8dca3d6 --- /dev/null +++ b/src/core/hle/service/am/service/common_state_getter.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/apm/apm_controller.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/pm/pm.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::AM { + +struct Applet; +class ILockAccessor; + +class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { +public: + explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_); + ~ICommonStateGetter() override; + +private: + Result GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result ReceiveMessage(Out<AppletMessage> out_applet_message); + Result GetCurrentFocusState(Out<FocusState> out_focus_state); + Result RequestToAcquireSleepLock(); + Result GetAcquiredSleepLockEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetReaderLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor, + u32 button_type); + Result GetWriterLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor, + u32 button_type); + Result GetDefaultDisplayResolutionChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetOperationMode(Out<OperationMode> out_operation_mode); + Result GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode); + Result GetBootMode(Out<PM::SystemBootMode> out_boot_mode); + Result IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled); + Result SetVrModeEnabled(bool is_vr_mode_enabled); + Result SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled); + Result BeginVrModeEx(); + Result EndVrModeEx(); + Result IsInControllerFirmwareUpdateSection( + Out<bool> out_is_in_controller_firmware_update_section); + Result GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height); + Result GetBuiltInDisplayType(Out<s32> out_display_type); + Result PerformSystemButtonPressingIfInFocus(SystemButtonType type); + Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info); + Result GetAppletLaunchedHistory(Out<s32> out_count, + OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids); + Result GetSettingsPlatformRegion(Out<SysPlatformRegion> out_settings_platform_region); + Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(); + + void SetCpuBoostMode(HLERequestContext& ctx); + + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/cradle_firmware_updater.cpp b/src/core/hle/service/am/service/cradle_firmware_updater.cpp new file mode 100644 index 000000000..0a8af0858 --- /dev/null +++ b/src/core/hle/service/am/service/cradle_firmware_updater.cpp @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/cradle_firmware_updater.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +ICradleFirmwareUpdater::ICradleFirmwareUpdater(Core::System& system_) + : ServiceFramework{system_, "ICradleFirmwareUpdater"}, + m_context{system, "ICradleFirmwareUpdater"}, m_cradle_device_info_event{m_context} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ICradleFirmwareUpdater::StartUpdate>, "StartUpdate"}, + {1, D<&ICradleFirmwareUpdater::FinishUpdate>, "FinishUpdate"}, + {2, D<&ICradleFirmwareUpdater::GetCradleDeviceInfo>, "GetCradleDeviceInfo"}, + {3, D<&ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent>, "GetCradleDeviceInfoChangeEvent"}, + {4, nullptr, "GetUpdateProgressInfo"}, + {5, nullptr, "GetLastInternalResult"}, + + }; + // clang-format on + + RegisterHandlers(functions); +} + +ICradleFirmwareUpdater::~ICradleFirmwareUpdater() = default; + +Result ICradleFirmwareUpdater::StartUpdate() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ICradleFirmwareUpdater::FinishUpdate() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ICradleFirmwareUpdater::GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_cradle_device_info = {}; + R_SUCCEED(); +} + +Result ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_event = m_cradle_device_info_event.GetHandle(); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/cradle_firmware_updater.h b/src/core/hle/service/am/service/cradle_firmware_updater.h new file mode 100644 index 000000000..3e803f0ae --- /dev/null +++ b/src/core/hle/service/am/service/cradle_firmware_updater.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct CradleDeviceInfo { + bool unknown0; + bool unknown1; + bool unknown2; + u64 unknown3; +}; +static_assert(sizeof(CradleDeviceInfo) == 0x10, "CradleDeviceInfo has incorrect size"); + +class ICradleFirmwareUpdater final : public ServiceFramework<ICradleFirmwareUpdater> { +public: + explicit ICradleFirmwareUpdater(Core::System& system_); + ~ICradleFirmwareUpdater() override; + +private: + Result StartUpdate(); + Result FinishUpdate(); + Result GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info); + Result GetCradleDeviceInfoChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + +private: + KernelHelpers::ServiceContext m_context; + Event m_cradle_device_info_event; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/debug_functions.cpp b/src/core/hle/service/am/service/debug_functions.cpp new file mode 100644 index 000000000..fcac4776d --- /dev/null +++ b/src/core/hle/service/am/service/debug_functions.cpp @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/debug_functions.h" + +namespace Service::AM { + +IDebugFunctions::IDebugFunctions(Core::System& system_) + : ServiceFramework{system_, "IDebugFunctions"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, + {1, nullptr, "OpenMainApplication"}, + {10, nullptr, "PerformSystemButtonPressing"}, + {20, nullptr, "InvalidateTransitionLayer"}, + {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, + {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"}, + {40, nullptr, "GetAppletResourceUsageInfo"}, + {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"}, + {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"}, + {100, nullptr, "SetCpuBoostModeForApplet"}, + {101, nullptr, "CancelCpuBoostModeForApplet"}, + {110, nullptr, "PushToAppletBoundChannelForDebug"}, + {111, nullptr, "TryPopFromAppletBoundChannelForDebug"}, + {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"}, + {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"}, + {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"}, + {130, nullptr, "FriendInvitationSetApplicationParameter"}, + {131, nullptr, "FriendInvitationClearApplicationParameter"}, + {132, nullptr, "FriendInvitationPushApplicationParameter"}, + {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"}, + {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"}, + {300, nullptr, "TerminateAllRunningApplicationsForDebug"}, + {900, nullptr, "GetGrcProcessLaunchedSystemEvent"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDebugFunctions::~IDebugFunctions() = default; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/debug_functions.h b/src/core/hle/service/am/service/debug_functions.h index d55968743..d55968743 100644 --- a/src/core/hle/service/am/debug_functions.h +++ b/src/core/hle/service/am/service/debug_functions.h diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp new file mode 100644 index 000000000..ed71f9093 --- /dev/null +++ b/src/core/hle/service/am/service/display_controller.cpp @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/result.h" +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/service/display_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_) + : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetLastForegroundCaptureImage"}, + {1, nullptr, "UpdateLastForegroundCaptureImage"}, + {2, nullptr, "GetLastApplicationCaptureImage"}, + {3, nullptr, "GetCallerAppletCaptureImage"}, + {4, nullptr, "UpdateCallerAppletCaptureImage"}, + {5, nullptr, "GetLastForegroundCaptureImageEx"}, + {6, nullptr, "GetLastApplicationCaptureImageEx"}, + {7, D<&IDisplayController::GetCallerAppletCaptureImageEx>, "GetCallerAppletCaptureImageEx"}, + {8, D<&IDisplayController::TakeScreenShotOfOwnLayer>, "TakeScreenShotOfOwnLayer"}, + {9, nullptr, "CopyBetweenCaptureBuffers"}, + {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, + {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, + {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, + {13, nullptr, "ReleaseLastForegroundCaptureBuffer"}, + {14, nullptr, "AcquireCallerAppletCaptureBuffer"}, + {15, nullptr, "ReleaseCallerAppletCaptureBuffer"}, + {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, + {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, + {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, + {20, D<&IDisplayController::ClearCaptureBuffer>, "ClearCaptureBuffer"}, + {21, nullptr, "ClearAppletTransitionBuffer"}, + {22, D<&IDisplayController::AcquireLastApplicationCaptureSharedBuffer>, "AcquireLastApplicationCaptureSharedBuffer"}, + {23, D<&IDisplayController::ReleaseLastApplicationCaptureSharedBuffer>, "ReleaseLastApplicationCaptureSharedBuffer"}, + {24, D<&IDisplayController::AcquireLastForegroundCaptureSharedBuffer>, "AcquireLastForegroundCaptureSharedBuffer"}, + {25, D<&IDisplayController::ReleaseLastForegroundCaptureSharedBuffer>, "ReleaseLastForegroundCaptureSharedBuffer"}, + {26, D<&IDisplayController::AcquireCallerAppletCaptureSharedBuffer>, "AcquireCallerAppletCaptureSharedBuffer"}, + {27, D<&IDisplayController::ReleaseCallerAppletCaptureSharedBuffer>, "ReleaseCallerAppletCaptureSharedBuffer"}, + {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDisplayController::~IDisplayController() = default; + +Result IDisplayController::GetCallerAppletCaptureImageEx( + Out<bool> out_was_written, OutBuffer<BufferAttr_HipcMapAlias> out_image_data) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_was_written = true; + R_SUCCEED(); +} + +Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) { + LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}", + unknown0, fbshare_layer_index, color); + R_SUCCEED(); +} + +Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( + Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, + out_fbshare_layer_index)); +} + +Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( + Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, + out_fbshare_layer_index)); +} + +Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( + Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, + out_fbshare_layer_index)); +} + +Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/display_controller.h b/src/core/hle/service/am/service/display_controller.h new file mode 100644 index 000000000..406fae21a --- /dev/null +++ b/src/core/hle/service/am/service/display_controller.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; + +class IDisplayController final : public ServiceFramework<IDisplayController> { +public: + explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_); + ~IDisplayController() override; + +private: + Result GetCallerAppletCaptureImageEx(Out<bool> out_was_written, + OutBuffer<BufferAttr_HipcMapAlias> out_image_data); + Result TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index); + Result ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color); + Result AcquireLastForegroundCaptureSharedBuffer(Out<bool> out_was_written, + Out<s32> out_fbshare_layer_index); + Result ReleaseLastForegroundCaptureSharedBuffer(); + Result AcquireCallerAppletCaptureSharedBuffer(Out<bool> out_was_written, + Out<s32> out_fbshare_layer_index); + Result ReleaseCallerAppletCaptureSharedBuffer(); + Result AcquireLastApplicationCaptureSharedBuffer(Out<bool> out_was_written, + Out<s32> out_fbshare_layer_index); + Result ReleaseLastApplicationCaptureSharedBuffer(); + + const std::shared_ptr<Applet> applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/global_state_controller.cpp b/src/core/hle/service/am/service/global_state_controller.cpp new file mode 100644 index 000000000..dba5d3613 --- /dev/null +++ b/src/core/hle/service/am/service/global_state_controller.cpp @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/cradle_firmware_updater.h" +#include "core/hle/service/am/service/global_state_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IGlobalStateController::IGlobalStateController(Core::System& system_) + : ServiceFramework{system_, "IGlobalStateController"}, + m_context{system_, "IGlobalStateController"}, m_hdcp_authentication_failed_event{m_context} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "RequestToEnterSleep"}, + {1, nullptr, "EnterSleep"}, + {2, nullptr, "StartSleepSequence"}, + {3, nullptr, "StartShutdownSequence"}, + {4, nullptr, "StartRebootSequence"}, + {9, nullptr, "IsAutoPowerDownRequested"}, + {10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"}, + {11, nullptr, "NotifyCecSettingsChanged"}, + {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, + {13, nullptr, "UpdateDefaultDisplayResolution"}, + {14, D<&IGlobalStateController::ShouldSleepOnBoot>, "ShouldSleepOnBoot"}, + {15, D<&IGlobalStateController::GetHdcpAuthenticationFailedEvent>, "GetHdcpAuthenticationFailedEvent"}, + {30, D<&IGlobalStateController::OpenCradleFirmwareUpdater>, "OpenCradleFirmwareUpdater"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IGlobalStateController::~IGlobalStateController() = default; + +Result IGlobalStateController::LoadAndApplyIdlePolicySettings() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IGlobalStateController::ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot) { + LOG_INFO(Service_AM, "called"); + *out_should_sleep_on_boot = false; + R_SUCCEED(); +} + +Result IGlobalStateController::GetHdcpAuthenticationFailedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_hdcp_authentication_failed_event.GetHandle(); + R_SUCCEED(); +} + +Result IGlobalStateController::OpenCradleFirmwareUpdater( + Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater) { + LOG_INFO(Service_AM, "called"); + *out_cradle_firmware_updater = std::make_shared<ICradleFirmwareUpdater>(system); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/global_state_controller.h b/src/core/hle/service/am/service/global_state_controller.h new file mode 100644 index 000000000..67c753513 --- /dev/null +++ b/src/core/hle/service/am/service/global_state_controller.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class ICradleFirmwareUpdater; + +class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { +public: + explicit IGlobalStateController(Core::System& system_); + ~IGlobalStateController() override; + +private: + Result LoadAndApplyIdlePolicySettings(); + Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot); + Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result OpenCradleFirmwareUpdater( + Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater); + + KernelHelpers::ServiceContext m_context; + Event m_hdcp_authentication_failed_event; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/home_menu_functions.cpp b/src/core/hle/service/am/service/home_menu_functions.cpp new file mode 100644 index 000000000..0c4d24b58 --- /dev/null +++ b/src/core/hle/service/am/service/home_menu_functions.cpp @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/result.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/service/home_menu_functions.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)}, + m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} { + // clang-format off + static const FunctionInfo functions[] = { + {10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"}, + {11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"}, + {12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"}, + {20, nullptr, "PopFromGeneralChannel"}, + {21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"}, + {30, nullptr, "GetHomeButtonWriterLockAccessor"}, + {31, nullptr, "GetWriterLockAccessorEx"}, + {40, nullptr, "IsSleepEnabled"}, + {41, D<&IHomeMenuFunctions::IsRebootEnabled>, "IsRebootEnabled"}, + {50, nullptr, "LaunchSystemApplet"}, + {51, nullptr, "LaunchStarter"}, + {100, nullptr, "PopRequestLaunchApplicationForDebug"}, + {110, D<&IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug>, "IsForceTerminateApplicationDisabledForDebug"}, + {200, nullptr, "LaunchDevMenu"}, + {1000, nullptr, "SetLastApplicationExitReason"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IHomeMenuFunctions::~IHomeMenuFunctions() = default; + +Result IHomeMenuFunctions::RequestToGetForeground() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IHomeMenuFunctions::LockForeground() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IHomeMenuFunctions::UnlockForeground() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IHomeMenuFunctions::GetPopFromGeneralChannelEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_pop_from_general_channel_event.GetHandle(); + R_SUCCEED(); +} + +Result IHomeMenuFunctions::IsRebootEnabled(Out<bool> out_is_reboot_enbaled) { + LOG_INFO(Service_AM, "called"); + *out_is_reboot_enbaled = true; + R_SUCCEED(); +} + +Result IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug( + Out<bool> out_is_force_terminate_application_disabled_for_debug) { + LOG_INFO(Service_AM, "called"); + *out_is_force_terminate_application_disabled_for_debug = false; + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/home_menu_functions.h b/src/core/hle/service/am/service/home_menu_functions.h new file mode 100644 index 000000000..caf6fbaab --- /dev/null +++ b/src/core/hle/service/am/service/home_menu_functions.h @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; + +class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { +public: + explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet); + ~IHomeMenuFunctions() override; + +private: + Result RequestToGetForeground(); + Result LockForeground(); + Result UnlockForeground(); + Result GetPopFromGeneralChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result IsRebootEnabled(Out<bool> out_is_reboot_enbaled); + Result IsForceTerminateApplicationDisabledForDebug( + Out<bool> out_is_force_terminate_application_disabled_for_debug); + + const std::shared_ptr<Applet> m_applet; + KernelHelpers::ServiceContext m_context; + Event m_pop_from_general_channel_event; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp new file mode 100644 index 000000000..0c2426d4b --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -0,0 +1,157 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/applet_data_broker.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/service/library_applet_accessor.h" +#include "core/hle/service/am/service/storage.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_, + std::shared_ptr<AppletDataBroker> broker, + std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "ILibraryAppletAccessor"}, m_broker{std::move(broker)}, + m_applet{std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ILibraryAppletAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"}, + {1, D<&ILibraryAppletAccessor::IsCompleted>, "IsCompleted"}, + {10, D<&ILibraryAppletAccessor::Start>, "Start"}, + {20, D<&ILibraryAppletAccessor::RequestExit>, "RequestExit"}, + {25, D<&ILibraryAppletAccessor::Terminate>, "Terminate"}, + {30, D<&ILibraryAppletAccessor::GetResult>, "GetResult"}, + {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, + {60, D<&ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero>, "PresetLibraryAppletGpuTimeSliceZero"}, + {100, D<&ILibraryAppletAccessor::PushInData>, "PushInData"}, + {101, D<&ILibraryAppletAccessor::PopOutData>, "PopOutData"}, + {102, nullptr, "PushExtraStorage"}, + {103, D<&ILibraryAppletAccessor::PushInteractiveInData>, "PushInteractiveInData"}, + {104, D<&ILibraryAppletAccessor::PopInteractiveOutData>, "PopInteractiveOutData"}, + {105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"}, + {106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"}, + {110, nullptr, "NeedsToExitProcess"}, + {120, nullptr, "GetLibraryAppletInfo"}, + {150, nullptr, "RequestForAppletToGetForeground"}, + {160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ILibraryAppletAccessor::~ILibraryAppletAccessor() = default; + +Result ILibraryAppletAccessor::GetAppletStateChangedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = m_broker->GetStateChangedEvent().GetHandle(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) { + LOG_DEBUG(Service_AM, "called"); + *out_is_completed = m_broker->IsCompleted(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) { + LOG_DEBUG(Service_AM, "called"); + *out_result = m_applet->terminate_result; + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() { + LOG_INFO(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::Start() { + LOG_DEBUG(Service_AM, "called"); + m_applet->process->Run(); + FrontendExecute(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::RequestExit() { + LOG_DEBUG(Service_AM, "called"); + m_applet->message_queue.RequestExit(); + FrontendRequestExit(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::Terminate() { + LOG_DEBUG(Service_AM, "called"); + m_applet->process->Terminate(); + FrontendRequestExit(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::PushInData(SharedPointer<IStorage> storage) { + LOG_DEBUG(Service_AM, "called"); + m_broker->GetInData().Push(storage); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::PopOutData(Out<SharedPointer<IStorage>> out_storage) { + LOG_DEBUG(Service_AM, "called"); + R_RETURN(m_broker->GetOutData().Pop(out_storage.Get())); +} + +Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer<IStorage> storage) { + LOG_DEBUG(Service_AM, "called"); + m_broker->GetInteractiveInData().Push(storage); + FrontendExecuteInteractive(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage) { + LOG_DEBUG(Service_AM, "called"); + R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get())); +} + +Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = m_broker->GetOutData().GetEvent(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::GetPopInteractiveOutDataEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called"); + *out_event = m_broker->GetInteractiveOutData().GetEvent(); + R_SUCCEED(); +} + +Result ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(Out<u64> out_handle) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is + // actually used anywhere + *out_handle = 0xdeadbeef; + R_SUCCEED(); +} + +void ILibraryAppletAccessor::FrontendExecute() { + if (m_applet->frontend) { + m_applet->frontend->Initialize(); + m_applet->frontend->Execute(); + } +} + +void ILibraryAppletAccessor::FrontendExecuteInteractive() { + if (m_applet->frontend) { + m_applet->frontend->ExecuteInteractive(); + m_applet->frontend->Execute(); + } +} + +void ILibraryAppletAccessor::FrontendRequestExit() { + if (m_applet->frontend) { + m_applet->frontend->RequestExit(); + } +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_accessor.h b/src/core/hle/service/am/service/library_applet_accessor.h new file mode 100644 index 000000000..97d3b6c8a --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_accessor.h @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class AppletDataBroker; +struct Applet; +class IStorage; + +class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { +public: + explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<AppletDataBroker> broker, + std::shared_ptr<Applet> applet); + ~ILibraryAppletAccessor(); + +private: + Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result IsCompleted(Out<bool> out_is_completed); + Result GetResult(Out<Result> out_result); + Result PresetLibraryAppletGpuTimeSliceZero(); + Result Start(); + Result RequestExit(); + Result Terminate(); + Result PushInData(SharedPointer<IStorage> storage); + Result PopOutData(Out<SharedPointer<IStorage>> out_storage); + Result PushInteractiveInData(SharedPointer<IStorage> storage); + Result PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage); + Result GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetPopInteractiveOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetIndirectLayerConsumerHandle(Out<u64> out_handle); + + void FrontendExecute(); + void FrontendExecuteInteractive(); + void FrontendRequestExit(); + + const std::shared_ptr<AppletDataBroker> m_broker; + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp new file mode 100644 index 000000000..c97358d81 --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -0,0 +1,268 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/am/applet_data_broker.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/library_applet_storage.h" +#include "core/hle/service/am/service/library_applet_accessor.h" +#include "core/hle/service/am/service/library_applet_creator.h" +#include "core/hle/service/am/service/storage.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::AM { + +namespace { + +bool ShouldCreateGuestApplet(AppletId applet_id) { +#define X(Name, name) \ + if (applet_id == AppletId::Name && \ + Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \ + return false; \ + } + + X(Cabinet, cabinet) + X(Controller, controller) + X(DataErase, data_erase) + X(Error, error) + X(NetConnect, net_connect) + X(ProfileSelect, player_select) + X(SoftwareKeyboard, swkbd) + X(MiiEdit, mii_edit) + X(Web, web) + X(Shop, shop) + X(PhotoViewer, photo_viewer) + X(OfflineWeb, offline_web) + X(LoginShare, login_share) + X(WebAuth, wifi_web_auth) + X(MyPage, my_page) + +#undef X + + return true; +} + +AppletProgramId AppletIdToProgramId(AppletId applet_id) { + switch (applet_id) { + case AppletId::OverlayDisplay: + return AppletProgramId::OverlayDisplay; + case AppletId::QLaunch: + return AppletProgramId::QLaunch; + case AppletId::Starter: + return AppletProgramId::Starter; + case AppletId::Auth: + return AppletProgramId::Auth; + case AppletId::Cabinet: + return AppletProgramId::Cabinet; + case AppletId::Controller: + return AppletProgramId::Controller; + case AppletId::DataErase: + return AppletProgramId::DataErase; + case AppletId::Error: + return AppletProgramId::Error; + case AppletId::NetConnect: + return AppletProgramId::NetConnect; + case AppletId::ProfileSelect: + return AppletProgramId::ProfileSelect; + case AppletId::SoftwareKeyboard: + return AppletProgramId::SoftwareKeyboard; + case AppletId::MiiEdit: + return AppletProgramId::MiiEdit; + case AppletId::Web: + return AppletProgramId::Web; + case AppletId::Shop: + return AppletProgramId::Shop; + case AppletId::PhotoViewer: + return AppletProgramId::PhotoViewer; + case AppletId::Settings: + return AppletProgramId::Settings; + case AppletId::OfflineWeb: + return AppletProgramId::OfflineWeb; + case AppletId::LoginShare: + return AppletProgramId::LoginShare; + case AppletId::WebAuth: + return AppletProgramId::WebAuth; + case AppletId::MyPage: + return AppletProgramId::MyPage; + default: + return static_cast<AppletProgramId>(0); + } +} + +std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, + std::shared_ptr<Applet> caller_applet, + AppletId applet_id, + LibraryAppletMode mode) { + const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); + if (program_id == 0) { + // Unknown applet + return {}; + } + + // TODO: enable other versions of applets + enum : u8 { + Firmware1400 = 14, + Firmware1500 = 15, + Firmware1600 = 16, + Firmware1700 = 17, + }; + + auto process = std::make_unique<Process>(system); + if (!process->Initialize(program_id, Firmware1400, Firmware1700)) { + // Couldn't initialize the guest process + return {}; + } + + const auto applet = std::make_shared<Applet>(system, std::move(process)); + applet->program_id = program_id; + applet->applet_id = applet_id; + applet->type = AppletType::LibraryApplet; + applet->library_applet_mode = mode; + + // Set focus state + switch (mode) { + case LibraryAppletMode::AllForeground: + case LibraryAppletMode::NoUi: + case LibraryAppletMode::PartialForeground: + case LibraryAppletMode::PartialForegroundIndirectDisplay: + applet->hid_registration.EnableAppletToGetInput(true); + applet->focus_state = FocusState::InFocus; + applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground); + break; + case LibraryAppletMode::AllForegroundInitiallyHidden: + applet->hid_registration.EnableAppletToGetInput(false); + applet->focus_state = FocusState::NotInFocus; + applet->display_layer_manager.SetWindowVisibility(false); + applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground); + break; + } + + auto broker = std::make_shared<AppletDataBroker>(system); + applet->caller_applet = caller_applet; + applet->caller_applet_broker = broker; + + system.GetAppletManager().InsertApplet(applet); + + return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); +} + +std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system, + std::shared_ptr<Applet> caller_applet, + AppletId applet_id, + LibraryAppletMode mode) { + const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); + + auto process = std::make_unique<Process>(system); + auto applet = std::make_shared<Applet>(system, std::move(process)); + applet->program_id = program_id; + applet->applet_id = applet_id; + applet->type = AppletType::LibraryApplet; + applet->library_applet_mode = mode; + + auto storage = std::make_shared<AppletDataBroker>(system); + applet->caller_applet = caller_applet; + applet->caller_applet_broker = storage; + applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode); + + return std::make_shared<ILibraryAppletAccessor>(system, storage, applet); +} + +} // namespace + +ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} { + static const FunctionInfo functions[] = { + {0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"}, + {1, nullptr, "TerminateAllLibraryApplets"}, + {2, nullptr, "AreAnyLibraryAppletsLeft"}, + {10, D<&ILibraryAppletCreator::CreateStorage>, "CreateStorage"}, + {11, D<&ILibraryAppletCreator::CreateTransferMemoryStorage>, "CreateTransferMemoryStorage"}, + {12, D<&ILibraryAppletCreator::CreateHandleStorage>, "CreateHandleStorage"}, + }; + RegisterHandlers(functions); +} + +ILibraryAppletCreator::~ILibraryAppletCreator() = default; + +Result ILibraryAppletCreator::CreateLibraryApplet( + Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id, + LibraryAppletMode library_applet_mode) { + LOG_DEBUG(Service_AM, "called with applet_id={} applet_mode={}", applet_id, + library_applet_mode); + + std::shared_ptr<ILibraryAppletAccessor> library_applet; + if (ShouldCreateGuestApplet(applet_id)) { + library_applet = CreateGuestApplet(system, m_applet, applet_id, library_applet_mode); + } + if (!library_applet) { + library_applet = CreateFrontendApplet(system, m_applet, applet_id, library_applet_mode); + } + if (!library_applet) { + LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); + R_THROW(ResultUnknown); + } + + // Applet is created, can now be launched. + m_applet->library_applet_launchable_event.Signal(); + *out_library_applet_accessor = library_applet; + R_SUCCEED(); +} + +Result ILibraryAppletCreator::CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size) { + LOG_DEBUG(Service_AM, "called, size={}", size); + + if (size <= 0) { + LOG_ERROR(Service_AM, "size is less than or equal to 0"); + R_THROW(ResultUnknown); + } + + *out_storage = std::make_shared<IStorage>(system, AM::CreateStorage(std::vector<u8>(size))); + R_SUCCEED(); +} + +Result ILibraryAppletCreator::CreateTransferMemoryStorage( + Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size, + InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) { + LOG_DEBUG(Service_AM, "called, is_writable={} size={}", is_writable, size); + + if (size <= 0) { + LOG_ERROR(Service_AM, "size is less than or equal to 0"); + R_THROW(ResultUnknown); + } + + if (!transfer_memory_handle) { + LOG_ERROR(Service_AM, "transfer_memory_handle is null"); + R_THROW(ResultUnknown); + } + + *out_storage = std::make_shared<IStorage>( + system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(), + transfer_memory_handle.Get(), is_writable, size)); + R_SUCCEED(); +} + +Result ILibraryAppletCreator::CreateHandleStorage( + Out<SharedPointer<IStorage>> out_storage, s64 size, + InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) { + LOG_DEBUG(Service_AM, "called, size={}", size); + + if (size <= 0) { + LOG_ERROR(Service_AM, "size is less than or equal to 0"); + R_THROW(ResultUnknown); + } + + if (!transfer_memory_handle) { + LOG_ERROR(Service_AM, "transfer_memory_handle is null"); + R_THROW(ResultUnknown); + } + + *out_storage = std::make_shared<IStorage>( + system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(), + transfer_memory_handle.Get(), size)); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_creator.h b/src/core/hle/service/am/service/library_applet_creator.h new file mode 100644 index 000000000..fe6d40eb3 --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_creator.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; +class ILibraryAppletAccessor; +class IStorage; + +class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { +public: + explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet); + ~ILibraryAppletCreator() override; + +private: + Result CreateLibraryApplet( + Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id, + LibraryAppletMode library_applet_mode); + Result CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size); + Result CreateTransferMemoryStorage( + Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size, + InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle); + Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size, + InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle); + + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp new file mode 100644 index 000000000..58e709347 --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_proxy.cpp @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/applet_common_functions.h" +#include "core/hle/service/am/service/audio_controller.h" +#include "core/hle/service/am/service/common_state_getter.h" +#include "core/hle/service/am/service/debug_functions.h" +#include "core/hle/service/am/service/display_controller.h" +#include "core/hle/service/am/service/global_state_controller.h" +#include "core/hle/service/am/service/home_menu_functions.h" +#include "core/hle/service/am/service/library_applet_creator.h" +#include "core/hle/service/am/service/library_applet_proxy.h" +#include "core/hle/service/am/service/library_applet_self_accessor.h" +#include "core/hle/service/am/service/process_winding_controller.h" +#include "core/hle/service/am/service/self_controller.h" +#include "core/hle/service/am/service/window_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process) + : ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{ + std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, + {1, D<&ILibraryAppletProxy::GetSelfController>, "GetSelfController"}, + {2, D<&ILibraryAppletProxy::GetWindowController>, "GetWindowController"}, + {3, D<&ILibraryAppletProxy::GetAudioController>, "GetAudioController"}, + {4, D<&ILibraryAppletProxy::GetDisplayController>, "GetDisplayController"}, + {10, D<&ILibraryAppletProxy::GetProcessWindingController>, "GetProcessWindingController"}, + {11, D<&ILibraryAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"}, + {20, D<&ILibraryAppletProxy::OpenLibraryAppletSelfAccessor>, "OpenLibraryAppletSelfAccessor"}, + {21, D<&ILibraryAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"}, + {22, D<&ILibraryAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"}, + {23, D<&ILibraryAppletProxy::GetGlobalStateController>, "GetGlobalStateController"}, + {1000, D<&ILibraryAppletProxy::GetDebugFunctions>, "GetDebugFunctions"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ILibraryAppletProxy::~ILibraryAppletProxy() = default; + +Result ILibraryAppletProxy::GetAudioController( + Out<SharedPointer<IAudioController>> out_audio_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_audio_controller = std::make_shared<IAudioController>(system); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetDisplayController( + Out<SharedPointer<IDisplayController>> out_display_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_display_controller = std::make_shared<IDisplayController>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetProcessWindingController( + Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetDebugFunctions( + Out<SharedPointer<IDebugFunctions>> out_debug_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_debug_functions = std::make_shared<IDebugFunctions>(system); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetWindowController( + Out<SharedPointer<IWindowController>> out_window_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_window_controller = std::make_shared<IWindowController>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetSelfController( + Out<SharedPointer<ISelfController>> out_self_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetCommonStateGetter( + Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) { + LOG_DEBUG(Service_AM, "called"); + *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetLibraryAppletCreator( + Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { + LOG_DEBUG(Service_AM, "called"); + *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::OpenLibraryAppletSelfAccessor( + Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor) { + LOG_DEBUG(Service_AM, "called"); + *out_library_applet_self_accessor = + std::make_shared<ILibraryAppletSelfAccessor>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetAppletCommonFunctions( + Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetHomeMenuFunctions( + Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletProxy::GetGlobalStateController( + Out<SharedPointer<IGlobalStateController>> out_global_state_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_global_state_controller = std::make_shared<IGlobalStateController>(system); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h new file mode 100644 index 000000000..7d0714b85 --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_proxy.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; +class IAppletCommonFunctions; +class IAudioController; +class ICommonStateGetter; +class IDebugFunctions; +class IDisplayController; +class IHomeMenuFunctions; +class IGlobalStateController; +class ILibraryAppletCreator; +class ILibraryAppletSelfAccessor; +class IProcessWindingController; +class ISelfController; +class IWindowController; + +class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { +public: + explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process); + ~ILibraryAppletProxy(); + +private: + Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller); + Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller); + Result GetProcessWindingController( + Out<SharedPointer<IProcessWindingController>> out_process_winding_controller); + Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions); + Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller); + Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller); + Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter); + Result GetLibraryAppletCreator( + Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator); + Result OpenLibraryAppletSelfAccessor( + Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor); + Result GetAppletCommonFunctions( + Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions); + Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions); + Result GetGlobalStateController( + Out<SharedPointer<IGlobalStateController>> out_global_state_controller); + + Kernel::KProcess* const m_process; + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp new file mode 100644 index 000000000..330eb26f0 --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -0,0 +1,325 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core_timing.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/am/applet_data_broker.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/service/library_applet_self_accessor.h" +#include "core/hle/service/am/service/storage.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/glue/glue_manager.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/service_getter_interface.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::AM { + +namespace { + +AppletIdentityInfo GetCallerIdentity(Applet& applet) { + if (const auto caller_applet = applet.caller_applet.lock(); caller_applet) { + // TODO: is this actually the application ID? + return { + .applet_id = caller_applet->applet_id, + .application_id = caller_applet->program_id, + }; + } else { + return { + .applet_id = AppletId::QLaunch, + .application_id = 0x0100000000001000ull, + }; + } +} + +} // namespace + +ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_, + std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)}, + m_broker{m_applet->caller_applet_broker} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ILibraryAppletSelfAccessor::PopInData>, "PopInData"}, + {1, D<&ILibraryAppletSelfAccessor::PushOutData>, "PushOutData"}, + {2, D<&ILibraryAppletSelfAccessor::PopInteractiveInData>, "PopInteractiveInData"}, + {3, D<&ILibraryAppletSelfAccessor::PushInteractiveOutData>, "PushInteractiveOutData"}, + {5, D<&ILibraryAppletSelfAccessor::GetPopInDataEvent>, "GetPopInDataEvent"}, + {6, D<&ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent>, "GetPopInteractiveInDataEvent"}, + {10, D<&ILibraryAppletSelfAccessor::ExitProcessAndReturn>, "ExitProcessAndReturn"}, + {11, D<&ILibraryAppletSelfAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"}, + {12, D<&ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo>, "GetMainAppletIdentityInfo"}, + {13, D<&ILibraryAppletSelfAccessor::CanUseApplicationCore>, "CanUseApplicationCore"}, + {14, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo>, "GetCallerAppletIdentityInfo"}, + {15, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty>, "GetMainAppletApplicationControlProperty"}, + {16, D<&ILibraryAppletSelfAccessor::GetMainAppletStorageId>, "GetMainAppletStorageId"}, + {17, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack>, "GetCallerAppletIdentityInfoStack"}, + {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, + {19, D<&ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout>, "GetDesirableKeyboardLayout"}, + {20, nullptr, "PopExtraStorage"}, + {25, nullptr, "GetPopExtraStorageEvent"}, + {30, nullptr, "UnpopInData"}, + {31, nullptr, "UnpopExtraStorage"}, + {40, nullptr, "GetIndirectLayerProducerHandle"}, + {50, D<&ILibraryAppletSelfAccessor::ReportVisibleError>, "ReportVisibleError"}, + {51, D<&ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext>, "ReportVisibleErrorWithErrorContext"}, + {60, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage>, "GetMainAppletApplicationDesiredLanguage"}, + {70, D<&ILibraryAppletSelfAccessor::GetCurrentApplicationId>, "GetCurrentApplicationId"}, + {80, nullptr, "RequestExitToSelf"}, + {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, + {100, nullptr, "CreateGameMovieTrimmer"}, + {101, nullptr, "ReserveResourceForMovieOperation"}, + {102, nullptr, "UnreserveResourceForMovieOperation"}, + {110, D<&ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers>, "GetMainAppletAvailableUsers"}, + {120, nullptr, "GetLaunchStorageInfoForDebug"}, + {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, + {140, nullptr, "SetApplicationMemoryReservation"}, + {150, D<&ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually>, "ShouldSetGpuTimeSliceManually"}, + {160, D<&ILibraryAppletSelfAccessor::Cmd160>, "Cmd160"}, + }; + // clang-format on + RegisterHandlers(functions); +} + +ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; + +Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_storage) { + LOG_INFO(Service_AM, "called"); + R_RETURN(m_broker->GetInData().Pop(out_storage)); +} + +Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) { + LOG_INFO(Service_AM, "called"); + m_broker->GetOutData().Push(storage); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage) { + LOG_INFO(Service_AM, "called"); + R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage)); +} + +Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer<IStorage> storage) { + LOG_INFO(Service_AM, "called"); + m_broker->GetInteractiveOutData().Push(storage); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetPopInDataEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_broker->GetInData().GetEvent(); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_AM, "called"); + *out_event = m_broker->GetInteractiveInData().GetEvent(); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetLibraryAppletInfo( + Out<LibraryAppletInfo> out_library_applet_info) { + LOG_INFO(Service_AM, "called"); + *out_library_applet_info = { + .applet_id = m_applet->applet_id, + .library_applet_mode = m_applet->library_applet_mode, + }; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo( + Out<AppletIdentityInfo> out_identity_info) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_identity_info = { + .applet_id = AppletId::QLaunch, + .application_id = 0x0100000000001000ull, + }; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::CanUseApplicationCore(Out<bool> out_can_use_application_core) { + // TODO: This appears to read the NPDM from state and check the core mask of the applet. + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_can_use_application_core = false; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty( + OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO: this should be the main applet, not the caller applet + const auto application = GetCallerIdentity(*m_applet); + std::vector<u8> nacp; + const auto result = + system.GetARPManager().GetControlProperty(&nacp, application.application_id); + + if (R_SUCCEEDED(result)) { + std::memcpy(out_nacp->data(), nacp.data(), std::min(nacp.size(), out_nacp->size())); + } + + R_RETURN(result); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id) { + LOG_INFO(Service_AM, "(STUBBED) called"); + *out_storage_id = FileSys::StorageId::NandUser; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() { + LOG_INFO(Service_AM, "called"); + system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid); + m_broker->SignalCompletion(); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo( + Out<AppletIdentityInfo> out_identity_info) { + LOG_INFO(Service_AM, "called"); + *out_identity_info = GetCallerIdentity(*m_applet); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack( + Out<s32> out_count, OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info) { + LOG_INFO(Service_AM, "called"); + + std::shared_ptr<Applet> applet = m_applet; + *out_count = 0; + + do { + if (*out_count >= static_cast<s32>(out_identity_info.size())) { + break; + } + out_identity_info[(*out_count)++] = GetCallerIdentity(*applet); + } while ((applet = applet->caller_applet.lock())); + + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(Out<u32> out_desirable_layout) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_desirable_layout = 0; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ReportVisibleError(ErrorCode error_code) { + LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category, + error_code.number); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext( + ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context) { + LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category, + error_code.number); + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage( + Out<u64> out_desired_language) { + // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage + // FIXME: all of this stuff belongs to ns + auto identity = GetCallerIdentity(*m_applet); + + // TODO(bunnei): This should be configurable + LOG_DEBUG(Service_AM, "called"); + + // Get supported languages from NACP, if possible + // Default to 0 (all languages supported) + u32 supported_languages = 0; + + const auto res = [this, identity] { + const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(), + system.GetContentProvider()}; + auto metadata = pm.GetControlMetadata(); + if (metadata.first != nullptr) { + return metadata; + } + + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id), + system.GetFileSystemController(), + system.GetContentProvider()}; + return pm_update.GetControlMetadata(); + }(); + + if (res.first != nullptr) { + supported_languages = res.first->GetSupportedLanguages(); + } + + // Call IApplicationManagerInterface implementation. + auto& service_manager = system.ServiceManager(); + auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2"); + + std::shared_ptr<NS::IApplicationManagerInterface> app_man; + R_TRY(ns_am2->GetApplicationManagerInterface(&app_man)); + + // Get desired application language + NS::ApplicationLanguage desired_language{}; + R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages)); + + // Convert to settings language code. + u64 language_code{}; + R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language)); + + LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); + + *out_desired_language = language_code; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_application_id) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO: this should be the main applet, not the caller applet + const auto main_applet = GetCallerIdentity(*m_applet); + *out_application_id = main_applet.application_id; + + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers( + Out<bool> out_can_select_any_user, Out<s32> out_users_count, + OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) { + const Service::Account::ProfileManager manager{}; + + *out_can_select_any_user = false; + *out_users_count = -1; + + LOG_INFO(Service_AM, "called"); + + if (manager.GetUserCount() > 0) { + *out_can_select_any_user = true; + *out_users_count = static_cast<s32>(manager.GetUserCount()); + + const auto users = manager.GetAllUsers(); + for (size_t i = 0; i < users.size() && i < out_users.size(); i++) { + out_users[i] = users[i]; + } + } + + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually( + Out<bool> out_should_set_gpu_time_slice_manually) { + LOG_INFO(Service_AM, "(STUBBED) called"); + *out_should_set_gpu_time_slice_manually = false; + R_SUCCEED(); +} + +Result ILibraryAppletSelfAccessor::Cmd160(Out<u64> out_unknown0) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_unknown0 = 0; + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.h b/src/core/hle/service/am/service/library_applet_self_accessor.h new file mode 100644 index 000000000..3e60393c2 --- /dev/null +++ b/src/core/hle/service/am/service/library_applet_self_accessor.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/uuid.h" +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace FileSys { +enum class StorageId : u8; +} + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::AM { + +class AppletDataBroker; +struct Applet; +class IStorage; + +struct LibraryAppletInfo { + AppletId applet_id; + LibraryAppletMode library_applet_mode; +}; +static_assert(sizeof(LibraryAppletInfo) == 0x8, "LibraryAppletInfo has incorrect size."); + +struct ErrorCode { + u32 category; + u32 number; +}; +static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size."); + +struct ErrorContext { + u8 type; + INSERT_PADDING_BYTES_NOINIT(0x7); + std::array<u8, 0x1f4> data; + Result result; +}; +static_assert(sizeof(ErrorContext) == 0x200, "ErrorContext has incorrect size."); + +class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { +public: + explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet); + ~ILibraryAppletSelfAccessor() override; + +private: + Result PopInData(Out<SharedPointer<IStorage>> out_storage); + Result PushOutData(SharedPointer<IStorage> storage); + Result PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage); + Result PushInteractiveOutData(SharedPointer<IStorage> storage); + Result GetPopInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetPopInteractiveInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetLibraryAppletInfo(Out<LibraryAppletInfo> out_library_applet_info); + Result GetMainAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info); + Result CanUseApplicationCore(Out<bool> out_can_use_application_core); + Result GetMainAppletApplicationControlProperty( + OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp); + Result GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id); + Result ExitProcessAndReturn(); + Result GetCallerAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info); + Result GetCallerAppletIdentityInfoStack( + Out<s32> out_count, + OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info); + Result GetDesirableKeyboardLayout(Out<u32> out_desirable_layout); + Result ReportVisibleError(ErrorCode error_code); + Result ReportVisibleErrorWithErrorContext( + ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context); + Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language); + Result GetCurrentApplicationId(Out<u64> out_application_id); + Result GetMainAppletAvailableUsers(Out<bool> out_can_select_any_user, Out<s32> out_users_count, + OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users); + Result ShouldSetGpuTimeSliceManually(Out<bool> out_should_set_gpu_time_slice_manually); + Result Cmd160(Out<u64> out_unknown0); + + const std::shared_ptr<Applet> m_applet; + const std::shared_ptr<AppletDataBroker> m_broker; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/lock_accessor.cpp b/src/core/hle/service/am/service/lock_accessor.cpp new file mode 100644 index 000000000..8e556fdd6 --- /dev/null +++ b/src/core/hle/service/am/service/lock_accessor.cpp @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/lock_accessor.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +ILockAccessor::ILockAccessor(Core::System& system_) + : ServiceFramework{system_, "ILockAccessor"}, m_context{system_, "ILockAccessor"}, + m_event{m_context} { + // clang-format off + static const FunctionInfo functions[] = { + {1, D<&ILockAccessor::TryLock>, "TryLock"}, + {2, D<&ILockAccessor::Unlock>, "Unlock"}, + {3, D<&ILockAccessor::GetEvent>, "GetEvent"}, + {4, D<&ILockAccessor::IsLocked>, "IsLocked"}, + }; + // clang-format on + + RegisterHandlers(functions); + + m_event.Signal(); +} + +ILockAccessor::~ILockAccessor() = default; + +Result ILockAccessor::TryLock(Out<bool> out_is_locked, + OutCopyHandle<Kernel::KReadableEvent> out_handle, + bool return_handle) { + LOG_INFO(Service_AM, "called, return_handle={}", return_handle); + + { + std::scoped_lock lk{m_mutex}; + if (m_is_locked) { + *out_is_locked = false; + } else { + m_is_locked = true; + *out_is_locked = true; + } + } + + if (return_handle) { + *out_handle = m_event.GetHandle(); + } + + R_SUCCEED(); +} + +Result ILockAccessor::Unlock() { + LOG_INFO(Service_AM, "called"); + + { + std::scoped_lock lk{m_mutex}; + m_is_locked = false; + } + + m_event.Signal(); + R_SUCCEED(); +} + +Result ILockAccessor::GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle) { + LOG_INFO(Service_AM, "called"); + *out_handle = m_event.GetHandle(); + R_SUCCEED(); +} + +Result ILockAccessor::IsLocked(Out<bool> out_is_locked) { + LOG_INFO(Service_AM, "called"); + std::scoped_lock lk{m_mutex}; + *out_is_locked = m_is_locked; + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/lock_accessor.h b/src/core/hle/service/am/service/lock_accessor.h new file mode 100644 index 000000000..9bfb5c050 --- /dev/null +++ b/src/core/hle/service/am/service/lock_accessor.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class ILockAccessor final : public ServiceFramework<ILockAccessor> { +public: + explicit ILockAccessor(Core::System& system_); + ~ILockAccessor() override; + +private: + Result TryLock(Out<bool> out_is_locked, OutCopyHandle<Kernel::KReadableEvent> out_handle, + bool return_handle); + Result Unlock(); + Result GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle); + Result IsLocked(Out<bool> out_is_locked); + +private: + KernelHelpers::ServiceContext m_context; + Event m_event; + std::mutex m_mutex{}; + bool m_is_locked{}; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/process_winding_controller.cpp b/src/core/hle/service/am/service/process_winding_controller.cpp new file mode 100644 index 000000000..10df830d7 --- /dev/null +++ b/src/core/hle/service/am/service/process_winding_controller.cpp @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/service/library_applet_accessor.h" +#include "core/hle/service/am/service/process_winding_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IProcessWindingController::IProcessWindingController(Core::System& system_, + std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "IProcessWindingController"}, m_applet{std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"}, + {11, D<&IProcessWindingController::OpenCallingLibraryApplet>, "OpenCallingLibraryApplet"}, + {21, nullptr, "PushContext"}, + {22, nullptr, "PopContext"}, + {23, nullptr, "CancelWindingReservation"}, + {30, nullptr, "WindAndDoReserved"}, + {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, + {41, nullptr, "ReserveToStartAndWait"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IProcessWindingController::~IProcessWindingController() = default; + +Result IProcessWindingController::GetLaunchReason( + Out<AppletProcessLaunchReason> out_launch_reason) { + LOG_INFO(Service_AM, "called"); + *out_launch_reason = m_applet->launch_reason; + R_SUCCEED(); +} + +Result IProcessWindingController::OpenCallingLibraryApplet( + Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet) { + LOG_INFO(Service_AM, "called"); + + const auto caller_applet = m_applet->caller_applet.lock(); + if (caller_applet == nullptr) { + LOG_ERROR(Service_AM, "No caller applet available"); + R_THROW(ResultUnknown); + } + + *out_calling_library_applet = std::make_shared<ILibraryAppletAccessor>( + system, m_applet->caller_applet_broker, caller_applet); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/process_winding_controller.h b/src/core/hle/service/am/service/process_winding_controller.h new file mode 100644 index 000000000..4408af1f1 --- /dev/null +++ b/src/core/hle/service/am/service/process_winding_controller.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; +class ILibraryAppletAccessor; + +class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { +public: + explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_); + ~IProcessWindingController() override; + +private: + Result GetLaunchReason(Out<AppletProcessLaunchReason> out_launch_reason); + Result OpenCallingLibraryApplet( + Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet); + + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp new file mode 100644 index 000000000..06314407c --- /dev/null +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -0,0 +1,394 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/hle/result.h" +#include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/am/service/self_controller.h" +#include "core/hle/service/caps/caps_su.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::AM { + +ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process) + : ServiceFramework{system_, "ISelfController"}, m_process{process}, m_applet{ + std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ISelfController::Exit>, "Exit"}, + {1, D<&ISelfController::LockExit>, "LockExit"}, + {2, D<&ISelfController::UnlockExit>, "UnlockExit"}, + {3, D<&ISelfController::EnterFatalSection>, "EnterFatalSection"}, + {4, D<&ISelfController::LeaveFatalSection>, "LeaveFatalSection"}, + {9, D<&ISelfController::GetLibraryAppletLaunchableEvent>, "GetLibraryAppletLaunchableEvent"}, + {10, D<&ISelfController::SetScreenShotPermission>, "SetScreenShotPermission"}, + {11, D<&ISelfController::SetOperationModeChangedNotification>, "SetOperationModeChangedNotification"}, + {12, D<&ISelfController::SetPerformanceModeChangedNotification>, "SetPerformanceModeChangedNotification"}, + {13, D<&ISelfController::SetFocusHandlingMode>, "SetFocusHandlingMode"}, + {14, D<&ISelfController::SetRestartMessageEnabled>, "SetRestartMessageEnabled"}, + {15, D<&ISelfController::SetScreenShotAppletIdentityInfo>, "SetScreenShotAppletIdentityInfo"}, + {16, D<&ISelfController::SetOutOfFocusSuspendingEnabled>, "SetOutOfFocusSuspendingEnabled"}, + {17, nullptr, "SetControllerFirmwareUpdateSection"}, + {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, + {19, D<&ISelfController::SetAlbumImageOrientation>, "SetAlbumImageOrientation"}, + {20, nullptr, "SetDesirableKeyboardLayout"}, + {21, nullptr, "GetScreenShotProgramId"}, + {40, D<&ISelfController::CreateManagedDisplayLayer>, "CreateManagedDisplayLayer"}, + {41, D<&ISelfController::IsSystemBufferSharingEnabled>, "IsSystemBufferSharingEnabled"}, + {42, D<&ISelfController::GetSystemSharedLayerHandle>, "GetSystemSharedLayerHandle"}, + {43, D<&ISelfController::GetSystemSharedBufferHandle>, "GetSystemSharedBufferHandle"}, + {44, D<&ISelfController::CreateManagedDisplaySeparableLayer>, "CreateManagedDisplaySeparableLayer"}, + {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, + {46, nullptr, "SetRecordingLayerCompositionEnabled"}, + {50, D<&ISelfController::SetHandlesRequestToDisplay>, "SetHandlesRequestToDisplay"}, + {51, D<&ISelfController::ApproveToDisplay>, "ApproveToDisplay"}, + {60, D<&ISelfController::OverrideAutoSleepTimeAndDimmingTime>, "OverrideAutoSleepTimeAndDimmingTime"}, + {61, D<&ISelfController::SetMediaPlaybackState>, "SetMediaPlaybackState"}, + {62, D<&ISelfController::SetIdleTimeDetectionExtension>, "SetIdleTimeDetectionExtension"}, + {63, D<&ISelfController::GetIdleTimeDetectionExtension>, "GetIdleTimeDetectionExtension"}, + {64, nullptr, "SetInputDetectionSourceSet"}, + {65, D<&ISelfController::ReportUserIsActive>, "ReportUserIsActive"}, + {66, nullptr, "GetCurrentIlluminance"}, + {67, nullptr, "IsIlluminanceAvailable"}, + {68, D<&ISelfController::SetAutoSleepDisabled>, "SetAutoSleepDisabled"}, + {69, D<&ISelfController::IsAutoSleepDisabled>, "IsAutoSleepDisabled"}, + {70, nullptr, "ReportMultimediaError"}, + {71, nullptr, "GetCurrentIlluminanceEx"}, + {72, D<&ISelfController::SetInputDetectionPolicy>, "SetInputDetectionPolicy"}, + {80, nullptr, "SetWirelessPriorityMode"}, + {90, D<&ISelfController::GetAccumulatedSuspendedTickValue>, "GetAccumulatedSuspendedTickValue"}, + {91, D<&ISelfController::GetAccumulatedSuspendedTickChangedEvent>, "GetAccumulatedSuspendedTickChangedEvent"}, + {100, D<&ISelfController::SetAlbumImageTakenNotificationEnabled>, "SetAlbumImageTakenNotificationEnabled"}, + {110, nullptr, "SetApplicationAlbumUserData"}, + {120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"}, + {130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"}, + {1000, nullptr, "GetDebugStorageChannel"}, + }; + // clang-format on + + RegisterHandlers(functions); + + std::scoped_lock lk{m_applet->lock}; + m_applet->display_layer_manager.Initialize(system, m_process, m_applet->applet_id, + m_applet->library_applet_mode); +} + +ISelfController::~ISelfController() { + std::scoped_lock lk{m_applet->lock}; + m_applet->display_layer_manager.Finalize(); +} + +Result ISelfController::Exit() { + LOG_DEBUG(Service_AM, "called"); + + // TODO + system.Exit(); + + R_SUCCEED(); +} + +Result ISelfController::LockExit() { + LOG_DEBUG(Service_AM, "called"); + + system.SetExitLocked(true); + + R_SUCCEED(); +} + +Result ISelfController::UnlockExit() { + LOG_DEBUG(Service_AM, "called"); + + system.SetExitLocked(false); + + if (system.GetExitRequested()) { + system.Exit(); + } + + R_SUCCEED(); +} + +Result ISelfController::EnterFatalSection() { + std::scoped_lock lk{m_applet->lock}; + + m_applet->fatal_section_count++; + LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", m_applet->fatal_section_count); + + R_SUCCEED(); +} + +Result ISelfController::LeaveFatalSection() { + LOG_DEBUG(Service_AM, "called"); + + // Entry and exit of fatal sections must be balanced. + std::scoped_lock lk{m_applet->lock}; + R_UNLESS(m_applet->fatal_section_count > 0, AM::ResultFatalSectionCountImbalance); + m_applet->fatal_section_count--; + + R_SUCCEED(); +} + +Result ISelfController::GetLibraryAppletLaunchableEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + m_applet->library_applet_launchable_event.Signal(); + *out_event = m_applet->library_applet_launchable_event.GetHandle(); + + R_SUCCEED(); +} + +Result ISelfController::SetScreenShotPermission(ScreenshotPermission screen_shot_permission) { + LOG_DEBUG(Service_AM, "called, permission={}", screen_shot_permission); + + std::scoped_lock lk{m_applet->lock}; + m_applet->screenshot_permission = screen_shot_permission; + + R_SUCCEED(); +} + +Result ISelfController::SetOperationModeChangedNotification(bool enabled) { + LOG_INFO(Service_AM, "called, enabled={}", enabled); + + std::scoped_lock lk{m_applet->lock}; + m_applet->operation_mode_changed_notification_enabled = enabled; + + R_SUCCEED(); +} + +Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) { + LOG_INFO(Service_AM, "called, enabled={}", enabled); + + std::scoped_lock lk{m_applet->lock}; + m_applet->performance_mode_changed_notification_enabled = enabled; + + R_SUCCEED(); +} + +Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) { + LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify, + background, suspend); + + std::scoped_lock lk{m_applet->lock}; + m_applet->focus_handling_mode = {notify, background, suspend}; + + R_SUCCEED(); +} + +Result ISelfController::SetRestartMessageEnabled(bool enabled) { + LOG_INFO(Service_AM, "called, enabled={}", enabled); + + std::scoped_lock lk{m_applet->lock}; + m_applet->restart_message_enabled = enabled; + + R_SUCCEED(); +} + +Result ISelfController::SetScreenShotAppletIdentityInfo( + AppletIdentityInfo screen_shot_applet_identity_info) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + m_applet->screen_shot_identity = screen_shot_applet_identity_info; + + R_SUCCEED(); +} + +Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) { + LOG_INFO(Service_AM, "called, enabled={}", enabled); + + std::scoped_lock lk{m_applet->lock}; + m_applet->out_of_focus_suspension_enabled = enabled; + + R_SUCCEED(); +} + +Result ISelfController::SetAlbumImageOrientation( + Capture::AlbumImageOrientation album_image_orientation) { + LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", album_image_orientation); + + std::scoped_lock lk{m_applet->lock}; + m_applet->album_image_orientation = album_image_orientation; + + R_SUCCEED(); +} + +Result ISelfController::IsSystemBufferSharingEnabled() { + LOG_INFO(Service_AM, "called"); + + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled()); +} + +Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) { + LOG_INFO(Service_AM, "called"); + + u64 layer_id; + + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id)); +} + +Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) { + LOG_INFO(Service_AM, "called"); + + std::scoped_lock lk{m_applet->lock}; + R_RETURN( + m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id)); +} + +Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) { + LOG_INFO(Service_AM, "called"); + + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.CreateManagedDisplayLayer(out_layer_id)); +} + +Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id, + Out<u64> out_recording_layer_id) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.CreateManagedDisplaySeparableLayer( + out_layer_id, out_recording_layer_id)); +} + +Result ISelfController::SetHandlesRequestToDisplay(bool enable) { + LOG_WARNING(Service_AM, "(STUBBED) called, enable={}", enable); + R_SUCCEED(); +} + +Result ISelfController::ApproveToDisplay() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ISelfController::SetMediaPlaybackState(bool state) { + LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state); + R_SUCCEED(); +} + +Result ISelfController::OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d) { + LOG_WARNING(Service_AM, "(STUBBED) called, a={}, b={}, c={}, d={}", a, b, c, d); + R_SUCCEED(); +} + +Result ISelfController::SetIdleTimeDetectionExtension( + IdleTimeDetectionExtension idle_time_detection_extension) { + LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", idle_time_detection_extension); + + std::scoped_lock lk{m_applet->lock}; + m_applet->idle_time_detection_extension = idle_time_detection_extension; + + R_SUCCEED(); +} + +Result ISelfController::GetIdleTimeDetectionExtension( + Out<IdleTimeDetectionExtension> out_idle_time_detection_extension) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + std::scoped_lock lk{m_applet->lock}; + *out_idle_time_detection_extension = m_applet->idle_time_detection_extension; + + R_SUCCEED(); +} + +Result ISelfController::ReportUserIsActive() { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ISelfController::SetAutoSleepDisabled(bool is_auto_sleep_disabled) { + LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); + + // On the system itself, if the previous state of is_auto_sleep_disabled + // differed from the current value passed in, it'd signify the internal + // window manager to update (and also increment some statistics like update counts) + // + // It'd also indicate this change to an idle handling context. + // + // However, given we're emulating this behavior, most of this can be ignored + // and it's sufficient to simply set the member variable for querying via + // IsAutoSleepDisabled(). + + std::scoped_lock lk{m_applet->lock}; + m_applet->auto_sleep_disabled = is_auto_sleep_disabled; + + R_SUCCEED(); +} + +Result ISelfController::IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled) { + LOG_DEBUG(Service_AM, "called."); + + std::scoped_lock lk{m_applet->lock}; + *out_is_auto_sleep_disabled = m_applet->auto_sleep_disabled; + + R_SUCCEED(); +} + +Result ISelfController::SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result ISelfController::GetAccumulatedSuspendedTickValue( + Out<u64> out_accumulated_suspended_tick_value) { + LOG_DEBUG(Service_AM, "called."); + + // This command returns the total number of system ticks since ISelfController creation + // where the game was suspended. Since Yuzu doesn't implement game suspension, this command + // can just always return 0 ticks. + std::scoped_lock lk{m_applet->lock}; + *out_accumulated_suspended_tick_value = m_applet->suspended_ticks; + + R_SUCCEED(); +} + +Result ISelfController::GetAccumulatedSuspendedTickChangedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_DEBUG(Service_AM, "called."); + + *out_event = m_applet->accumulated_suspended_tick_changed_event.GetHandle(); + R_SUCCEED(); +} + +Result ISelfController::SetAlbumImageTakenNotificationEnabled(bool enabled) { + LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); + + // This service call sets an internal flag whether a notification is shown when an image is + // captured. Currently we do not support capturing images via the capture button, so this can be + // stubbed for now. + std::scoped_lock lk{m_applet->lock}; + m_applet->album_image_taken_notification_enabled = enabled; + + R_SUCCEED(); +} + +Result ISelfController::SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option) { + LOG_INFO(Service_AM, "called, report_option={}", album_report_option); + + const auto screenshot_service = + system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( + "caps:su"); + + if (screenshot_service) { + screenshot_service->CaptureAndSaveScreenshot(album_report_option); + } + + R_SUCCEED(); +} + +Result ISelfController::SetRecordVolumeMuted(bool muted) { + LOG_WARNING(Service_AM, "(STUBBED) called. muted={}", muted); + + std::scoped_lock lk{m_applet->lock}; + m_applet->record_volume_muted = muted; + + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h new file mode 100644 index 000000000..eca083cfe --- /dev/null +++ b/src/core/hle/service/am/service/self_controller.h @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/am/am_types.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::Capture { +enum class AlbumImageOrientation; +enum class AlbumReportOption; +} // namespace Service::Capture + +namespace Service::AM { + +struct Applet; + +class ISelfController final : public ServiceFramework<ISelfController> { +public: + explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process); + ~ISelfController() override; + +private: + Result Exit(); + Result LockExit(); + Result UnlockExit(); + Result EnterFatalSection(); + Result LeaveFatalSection(); + Result GetLibraryAppletLaunchableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result SetScreenShotPermission(ScreenshotPermission screen_shot_permission); + Result SetOperationModeChangedNotification(bool enabled); + Result SetPerformanceModeChangedNotification(bool enabled); + Result SetFocusHandlingMode(bool notify, bool background, bool suspend); + Result SetRestartMessageEnabled(bool enabled); + Result SetScreenShotAppletIdentityInfo(AppletIdentityInfo screen_shot_applet_identity_info); + Result SetOutOfFocusSuspendingEnabled(bool enabled); + Result SetAlbumImageOrientation(Capture::AlbumImageOrientation album_image_orientation); + Result IsSystemBufferSharingEnabled(); + Result GetSystemSharedBufferHandle(Out<u64> out_buffer_id); + Result GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id); + Result CreateManagedDisplayLayer(Out<u64> out_layer_id); + Result CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id, + Out<u64> out_recording_layer_id); + Result SetHandlesRequestToDisplay(bool enable); + Result ApproveToDisplay(); + Result SetMediaPlaybackState(bool state); + Result OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d); + Result SetIdleTimeDetectionExtension(IdleTimeDetectionExtension idle_time_detection_extension); + Result GetIdleTimeDetectionExtension( + Out<IdleTimeDetectionExtension> out_idle_time_detection_extension); + Result ReportUserIsActive(); + Result SetAutoSleepDisabled(bool is_auto_sleep_disabled); + Result IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled); + Result SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy); + Result GetAccumulatedSuspendedTickValue(Out<u64> out_accumulated_suspended_tick_value); + Result GetAccumulatedSuspendedTickChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result SetAlbumImageTakenNotificationEnabled(bool enabled); + Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option); + Result SetRecordVolumeMuted(bool muted); + + Kernel::KProcess* const m_process; + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/storage.cpp b/src/core/hle/service/am/service/storage.cpp new file mode 100644 index 000000000..25ee0afbd --- /dev/null +++ b/src/core/hle/service/am/service/storage.cpp @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/library_applet_storage.h" +#include "core/hle/service/am/service/storage.h" +#include "core/hle/service/am/service/storage_accessor.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl) + : ServiceFramework{system_, "IStorage"}, m_impl{std::move(impl)} { + static const FunctionInfo functions[] = { + {0, D<&IStorage::Open>, "Open"}, + {1, D<&IStorage::OpenTransferStorage>, "OpenTransferStorage"}, + }; + + RegisterHandlers(functions); +} + +IStorage::IStorage(Core::System& system_, std::vector<u8>&& data) + : IStorage(system_, CreateStorage(std::move(data))) {} + +IStorage::~IStorage() = default; + +Result IStorage::Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor) { + LOG_DEBUG(Service_AM, "called"); + + R_UNLESS(m_impl->GetHandle() == nullptr, AM::ResultInvalidStorageType); + + *out_storage_accessor = std::make_shared<IStorageAccessor>(system, m_impl); + R_SUCCEED(); +} + +Result IStorage::OpenTransferStorage( + Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor) { + R_UNLESS(m_impl->GetHandle() != nullptr, AM::ResultInvalidStorageType); + + *out_transfer_storage_accessor = std::make_shared<ITransferStorageAccessor>(system, m_impl); + R_SUCCEED(); +} + +std::vector<u8> IStorage::GetData() const { + return m_impl->GetData(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/storage.h b/src/core/hle/service/am/service/storage.h new file mode 100644 index 000000000..cde2ed0ea --- /dev/null +++ b/src/core/hle/service/am/service/storage.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class LibraryAppletStorage; +class IStorageAccessor; +class ITransferStorageAccessor; + +class IStorage final : public ServiceFramework<IStorage> { +public: + explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl); + explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); + ~IStorage() override; + + std::shared_ptr<LibraryAppletStorage> GetImpl() const { + return m_impl; + } + + std::vector<u8> GetData() const; + +private: + Result Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor); + Result OpenTransferStorage( + Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor); + + const std::shared_ptr<LibraryAppletStorage> m_impl; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/storage_accessor.cpp b/src/core/hle/service/am/service/storage_accessor.cpp new file mode 100644 index 000000000..84577fee4 --- /dev/null +++ b/src/core/hle/service/am/service/storage_accessor.cpp @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/am/library_applet_storage.h" +#include "core/hle/service/am/service/storage_accessor.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IStorageAccessor::IStorageAccessor(Core::System& system_, + std::shared_ptr<LibraryAppletStorage> impl) + : ServiceFramework{system_, "IStorageAccessor"}, m_impl{std::move(impl)} { + static const FunctionInfo functions[] = { + {0, D<&IStorageAccessor::GetSize>, "GetSize"}, + {10, D<&IStorageAccessor::Write>, "Write"}, + {11, D<&IStorageAccessor::Read>, "Read"}, + }; + + RegisterHandlers(functions); +} + +IStorageAccessor::~IStorageAccessor() = default; + +Result IStorageAccessor::GetSize(Out<s64> out_size) { + LOG_DEBUG(Service_AM, "called"); + *out_size = m_impl->GetSize(); + R_SUCCEED(); +} + +Result IStorageAccessor::Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset) { + LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, buffer.size()); + R_RETURN(m_impl->Write(offset, buffer.data(), buffer.size())); +} + +Result IStorageAccessor::Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset) { + LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, out_buffer.size()); + R_RETURN(m_impl->Read(offset, out_buffer.data(), out_buffer.size())); +} + +ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_, + std::shared_ptr<LibraryAppletStorage> impl) + : ServiceFramework{system_, "ITransferStorageAccessor"}, m_impl{std::move(impl)} { + static const FunctionInfo functions[] = { + {0, D<&ITransferStorageAccessor::GetSize>, "GetSize"}, + {1, D<&ITransferStorageAccessor::GetHandle>, "GetHandle"}, + }; + + RegisterHandlers(functions); +} + +ITransferStorageAccessor::~ITransferStorageAccessor() = default; + +Result ITransferStorageAccessor::GetSize(Out<s64> out_size) { + LOG_DEBUG(Service_AM, "called"); + *out_size = m_impl->GetSize(); + R_SUCCEED(); +} + +Result ITransferStorageAccessor::GetHandle(Out<s64> out_size, + OutCopyHandle<Kernel::KTransferMemory> out_handle) { + LOG_INFO(Service_AM, "called"); + *out_size = m_impl->GetSize(); + *out_handle = m_impl->GetHandle(); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/storage_accessor.h b/src/core/hle/service/am/service/storage_accessor.h new file mode 100644 index 000000000..1a01730e0 --- /dev/null +++ b/src/core/hle/service/am/service/storage_accessor.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/am/library_applet_storage.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { +public: + explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl); + ~IStorageAccessor() override; + +private: + Result GetSize(Out<s64> out_size); + Result Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset); + Result Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset); + + const std::shared_ptr<LibraryAppletStorage> m_impl; +}; + +class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> { +public: + explicit ITransferStorageAccessor(Core::System& system_, + std::shared_ptr<LibraryAppletStorage> impl); + ~ITransferStorageAccessor() override; + +private: + Result GetSize(Out<s64> out_size); + Result GetHandle(Out<s64> out_size, OutCopyHandle<Kernel::KTransferMemory> out_handle); + + const std::shared_ptr<LibraryAppletStorage> m_impl; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp new file mode 100644 index 000000000..d1871ef9b --- /dev/null +++ b/src/core/hle/service/am/service/system_applet_proxy.cpp @@ -0,0 +1,131 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/service/applet_common_functions.h" +#include "core/hle/service/am/service/application_creator.h" +#include "core/hle/service/am/service/audio_controller.h" +#include "core/hle/service/am/service/common_state_getter.h" +#include "core/hle/service/am/service/debug_functions.h" +#include "core/hle/service/am/service/display_controller.h" +#include "core/hle/service/am/service/global_state_controller.h" +#include "core/hle/service/am/service/home_menu_functions.h" +#include "core/hle/service/am/service/library_applet_creator.h" +#include "core/hle/service/am/service/process_winding_controller.h" +#include "core/hle/service/am/service/self_controller.h" +#include "core/hle/service/am/service/system_applet_proxy.h" +#include "core/hle/service/am/service/window_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, + Kernel::KProcess* process) + : ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{ + std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, + {1, D<&ISystemAppletProxy::GetSelfController>, "GetSelfController"}, + {2, D<&ISystemAppletProxy::GetWindowController>, "GetWindowController"}, + {3, D<&ISystemAppletProxy::GetAudioController>, "GetAudioController"}, + {4, D<&ISystemAppletProxy::GetDisplayController>, "GetDisplayController"}, + {10, D<&ISystemAppletProxy::GetProcessWindingController>, "GetProcessWindingController"}, + {11, D<&ISystemAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"}, + {20, D<&ISystemAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"}, + {21, D<&ISystemAppletProxy::GetGlobalStateController>, "GetGlobalStateController"}, + {22, D<&ISystemAppletProxy::GetApplicationCreator>, "GetApplicationCreator"}, + {23, D<&ISystemAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"}, + {1000, D<&ISystemAppletProxy::GetDebugFunctions>, "GetDebugFunctions"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISystemAppletProxy::~ISystemAppletProxy() = default; + +Result ISystemAppletProxy::GetAudioController( + Out<SharedPointer<IAudioController>> out_audio_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_audio_controller = std::make_shared<IAudioController>(system); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetDisplayController( + Out<SharedPointer<IDisplayController>> out_display_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_display_controller = std::make_shared<IDisplayController>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetProcessWindingController( + Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetDebugFunctions( + Out<SharedPointer<IDebugFunctions>> out_debug_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_debug_functions = std::make_shared<IDebugFunctions>(system); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetWindowController( + Out<SharedPointer<IWindowController>> out_window_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_window_controller = std::make_shared<IWindowController>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetSelfController( + Out<SharedPointer<ISelfController>> out_self_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetCommonStateGetter( + Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) { + LOG_DEBUG(Service_AM, "called"); + *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetLibraryAppletCreator( + Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { + LOG_DEBUG(Service_AM, "called"); + *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetApplicationCreator( + Out<SharedPointer<IApplicationCreator>> out_application_creator) { + LOG_DEBUG(Service_AM, "called"); + *out_application_creator = std::make_shared<IApplicationCreator>(system); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetAppletCommonFunctions( + Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetHomeMenuFunctions( + Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) { + LOG_DEBUG(Service_AM, "called"); + *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet); + R_SUCCEED(); +} + +Result ISystemAppletProxy::GetGlobalStateController( + Out<SharedPointer<IGlobalStateController>> out_global_state_controller) { + LOG_DEBUG(Service_AM, "called"); + *out_global_state_controller = std::make_shared<IGlobalStateController>(system); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h new file mode 100644 index 000000000..67cd50e03 --- /dev/null +++ b/src/core/hle/service/am/service/system_applet_proxy.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; +class IAppletCommonFunctions; +class IApplicationCreator; +class IAudioController; +class ICommonStateGetter; +class IDebugFunctions; +class IDisplayController; +class IHomeMenuFunctions; +class IGlobalStateController; +class ILibraryAppletCreator; +class IProcessWindingController; +class ISelfController; +class IWindowController; + +class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { +public: + explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet, + Kernel::KProcess* process); + ~ISystemAppletProxy(); + +private: + Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller); + Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller); + Result GetProcessWindingController( + Out<SharedPointer<IProcessWindingController>> out_process_winding_controller); + Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions); + Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller); + Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller); + Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter); + Result GetLibraryAppletCreator( + Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator); + Result GetApplicationCreator(Out<SharedPointer<IApplicationCreator>> out_application_creator); + Result GetAppletCommonFunctions( + Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions); + Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions); + Result GetGlobalStateController( + Out<SharedPointer<IGlobalStateController>> out_global_state_controller); + + Kernel::KProcess* const m_process; + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp new file mode 100644 index 000000000..99a4f50a2 --- /dev/null +++ b/src/core/hle/service/am/service/window_controller.cpp @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/applet.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/service/window_controller.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AM { + +IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet) + : ServiceFramework{system_, "IWindowController"}, m_applet{std::move(applet)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "CreateWindow"}, + {1, D<&IWindowController::GetAppletResourceUserId>, "GetAppletResourceUserId"}, + {2, D<&IWindowController::GetAppletResourceUserIdOfCallerApplet>, "GetAppletResourceUserIdOfCallerApplet"}, + {10, D<&IWindowController::AcquireForegroundRights>, "AcquireForegroundRights"}, + {11, D<&IWindowController::ReleaseForegroundRights>, "ReleaseForegroundRights"}, + {12, D<&IWindowController::RejectToChangeIntoBackground>, "RejectToChangeIntoBackground"}, + {20, D<&IWindowController::SetAppletWindowVisibility>, "SetAppletWindowVisibility"}, + {21, D<&IWindowController::SetAppletGpuTimeSlice>, "SetAppletGpuTimeSlice"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IWindowController::~IWindowController() = default; + +Result IWindowController::GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid) { + LOG_INFO(Service_AM, "called"); + *out_aruid = m_applet->aruid; + R_SUCCEED(); +} + +Result IWindowController::GetAppletResourceUserIdOfCallerApplet( + Out<AppletResourceUserId> out_aruid) { + LOG_INFO(Service_AM, "called"); + + if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet != nullptr) { + *out_aruid = caller_applet->aruid; + } else { + *out_aruid = AppletResourceUserId{}; + } + + R_SUCCEED(); +} + +Result IWindowController::AcquireForegroundRights() { + LOG_INFO(Service_AM, "called"); + R_SUCCEED(); +} + +Result IWindowController::ReleaseForegroundRights() { + LOG_INFO(Service_AM, "called"); + R_SUCCEED(); +} + +Result IWindowController::RejectToChangeIntoBackground() { + LOG_INFO(Service_AM, "called"); + R_SUCCEED(); +} + +Result IWindowController::SetAppletWindowVisibility(bool visible) { + m_applet->display_layer_manager.SetWindowVisibility(visible); + m_applet->hid_registration.EnableAppletToGetInput(visible); + + if (visible) { + m_applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground); + m_applet->focus_state = FocusState::InFocus; + } else { + m_applet->focus_state = FocusState::NotInFocus; + } + + m_applet->message_queue.PushMessage(AppletMessage::FocusStateChanged); + + R_SUCCEED(); +} + +Result IWindowController::SetAppletGpuTimeSlice(s64 time_slice) { + LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice); + R_SUCCEED(); +} + +} // namespace Service::AM diff --git a/src/core/hle/service/am/service/window_controller.h b/src/core/hle/service/am/service/window_controller.h new file mode 100644 index 000000000..bfbad9bcc --- /dev/null +++ b/src/core/hle/service/am/service/window_controller.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::AM { + +struct Applet; + +class IWindowController final : public ServiceFramework<IWindowController> { +public: + explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet); + ~IWindowController() override; + +private: + Result GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid); + Result GetAppletResourceUserIdOfCallerApplet(Out<AppletResourceUserId> out_aruid); + Result AcquireForegroundRights(); + Result ReleaseForegroundRights(); + Result RejectToChangeIntoBackground(); + Result SetAppletWindowVisibility(bool visible); + Result SetAppletGpuTimeSlice(s64 time_slice); + + const std::shared_ptr<Applet> m_applet; +}; + +} // namespace Service::AM diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp deleted file mode 100644 index ec581e32b..000000000 --- a/src/core/hle/service/am/spsm.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/spsm.h" - -namespace Service::AM { - -SPSM::SPSM(Core::System& system_) : ServiceFramework{system_, "spsm"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetState"}, - {1, nullptr, "EnterSleep"}, - {2, nullptr, "GetLastWakeReason"}, - {3, nullptr, "Shutdown"}, - {4, nullptr, "GetNotificationMessageEventHandle"}, - {5, nullptr, "ReceiveNotificationMessage"}, - {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"}, - {7, nullptr, "ResetEventLog"}, - {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, - {9, nullptr, "ChangeHomeButtonLongPressingTime"}, - {10, nullptr, "PutErrorState"}, - {11, nullptr, "InvalidateCurrentHomeButtonPressing"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -SPSM::~SPSM() = default; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h deleted file mode 100644 index 922f8863e..000000000 --- a/src/core/hle/service/am/spsm.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::AM { - -class SPSM final : public ServiceFramework<SPSM> { -public: - explicit SPSM(Core::System& system_); - ~SPSM() override; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/storage.cpp b/src/core/hle/service/am/storage.cpp deleted file mode 100644 index 4e82afd1c..000000000 --- a/src/core/hle/service/am/storage.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/library_applet_storage.h" -#include "core/hle/service/am/storage.h" -#include "core/hle/service/am/storage_accessor.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_) - : ServiceFramework{system_, "IStorage"}, impl{std::move(impl_)} { - static const FunctionInfo functions[] = { - {0, &IStorage::Open, "Open"}, - {1, &IStorage::OpenTransferStorage, "OpenTransferStorage"}, - }; - - RegisterHandlers(functions); -} - -IStorage::IStorage(Core::System& system_, std::vector<u8>&& data) - : IStorage(system_, CreateStorage(std::move(data))) {} - -IStorage::~IStorage() = default; - -void IStorage::Open(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - if (impl->GetHandle() != nullptr) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultInvalidStorageType); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IStorageAccessor>(system, impl); -} - -void IStorage::OpenTransferStorage(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - if (impl->GetHandle() == nullptr) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(AM::ResultInvalidStorageType); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ITransferStorageAccessor>(system, impl); -} - -std::vector<u8> IStorage::GetData() const { - return impl->GetData(); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/storage.h b/src/core/hle/service/am/storage.h deleted file mode 100644 index 10d00b141..000000000 --- a/src/core/hle/service/am/storage.h +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -class LibraryAppletStorage; - -class IStorage final : public ServiceFramework<IStorage> { -public: - explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_); - explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); - ~IStorage() override; - - std::shared_ptr<LibraryAppletStorage> GetImpl() const { - return impl; - } - - std::vector<u8> GetData() const; - -private: - void Open(HLERequestContext& ctx); - void OpenTransferStorage(HLERequestContext& ctx); - - const std::shared_ptr<LibraryAppletStorage> impl; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/storage_accessor.cpp b/src/core/hle/service/am/storage_accessor.cpp deleted file mode 100644 index a1184b065..000000000 --- a/src/core/hle/service/am/storage_accessor.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/service/am/am_results.h" -#include "core/hle/service/am/library_applet_storage.h" -#include "core/hle/service/am/storage_accessor.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IStorageAccessor::IStorageAccessor(Core::System& system_, - std::shared_ptr<LibraryAppletStorage> impl_) - : ServiceFramework{system_, "IStorageAccessor"}, impl{std::move(impl_)} { - static const FunctionInfo functions[] = { - {0, &IStorageAccessor::GetSize, "GetSize"}, - {10, &IStorageAccessor::Write, "Write"}, - {11, &IStorageAccessor::Read, "Read"}, - }; - - RegisterHandlers(functions); -} - -IStorageAccessor::~IStorageAccessor() = default; - -void IStorageAccessor::GetSize(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 4}; - - rb.Push(ResultSuccess); - rb.Push(impl->GetSize()); -} - -void IStorageAccessor::Write(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const s64 offset{rp.Pop<s64>()}; - const auto data{ctx.ReadBuffer()}; - LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); - - const auto res{impl->Write(offset, data.data(), data.size())}; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void IStorageAccessor::Read(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const s64 offset{rp.Pop<s64>()}; - std::vector<u8> data(ctx.GetWriteBufferSize()); - - LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); - - const auto res{impl->Read(offset, data.data(), data.size())}; - - ctx.WriteBuffer(data); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_, - std::shared_ptr<LibraryAppletStorage> impl_) - : ServiceFramework{system_, "ITransferStorageAccessor"}, impl{std::move(impl_)} { - static const FunctionInfo functions[] = { - {0, &ITransferStorageAccessor::GetSize, "GetSize"}, - {1, &ITransferStorageAccessor::GetHandle, "GetHandle"}, - }; - - RegisterHandlers(functions); -} - -ITransferStorageAccessor::~ITransferStorageAccessor() = default; - -void ITransferStorageAccessor::GetSize(HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(impl->GetSize()); -} - -void ITransferStorageAccessor::GetHandle(HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 4, 1}; - rb.Push(ResultSuccess); - rb.Push(impl->GetSize()); - rb.PushCopyObjects(impl->GetHandle()); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/storage_accessor.h b/src/core/hle/service/am/storage_accessor.h deleted file mode 100644 index b9aa85a66..000000000 --- a/src/core/hle/service/am/storage_accessor.h +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/am/storage.h" -#include "core/hle/service/service.h" - -namespace Service::AM { - -class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { -public: - explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_); - ~IStorageAccessor() override; - -private: - void GetSize(HLERequestContext& ctx); - void Write(HLERequestContext& ctx); - void Read(HLERequestContext& ctx); - - const std::shared_ptr<LibraryAppletStorage> impl; -}; - -class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> { -public: - explicit ITransferStorageAccessor(Core::System& system_, - std::shared_ptr<LibraryAppletStorage> impl_); - ~ITransferStorageAccessor() override; - -private: - void GetSize(HLERequestContext& ctx); - void GetHandle(HLERequestContext& ctx); - - const std::shared_ptr<LibraryAppletStorage> impl; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp deleted file mode 100644 index 38643408e..000000000 --- a/src/core/hle/service/am/system_applet_proxy.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet_common_functions.h" -#include "core/hle/service/am/application_creator.h" -#include "core/hle/service/am/audio_controller.h" -#include "core/hle/service/am/common_state_getter.h" -#include "core/hle/service/am/debug_functions.h" -#include "core/hle/service/am/display_controller.h" -#include "core/hle/service/am/global_state_controller.h" -#include "core/hle/service/am/home_menu_functions.h" -#include "core/hle/service/am/library_applet_creator.h" -#include "core/hle/service/am/library_applet_self_accessor.h" -#include "core/hle/service/am/process_winding_controller.h" -#include "core/hle/service/am/self_controller.h" -#include "core/hle/service/am/system_applet_proxy.h" -#include "core/hle/service/am/window_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr<Applet> applet_, Core::System& system_) - : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move( - applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, - {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, - {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"}, - {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"}, - {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"}, - {10, nullptr, "GetProcessWindingController"}, - {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, - {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, - {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, - {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"}, - {23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"}, - {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -ISystemAppletProxy::~ISystemAppletProxy() = default; - -void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ICommonStateGetter>(system, applet); -} - -void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger); -} - -void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IWindowController>(system, applet); -} - -void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IAudioController>(system); -} - -void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDisplayController>(system, applet); -} - -void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ILibraryAppletCreator>(system, applet); -} - -void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IHomeMenuFunctions>(system); -} - -void ISystemAppletProxy::GetGlobalStateController(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IGlobalStateController>(system); -} - -void ISystemAppletProxy::GetApplicationCreator(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationCreator>(system); -} - -void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IAppletCommonFunctions>(system, applet); -} - -void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) { - LOG_DEBUG(Service_AM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IDebugFunctions>(system); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h deleted file mode 100644 index 0390cd1e5..000000000 --- a/src/core/hle/service/am/system_applet_proxy.h +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/am/applet_message_queue.h" -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { -public: - explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_, - std::shared_ptr<Applet> applet_, Core::System& system_); - ~ISystemAppletProxy(); - -private: - void GetCommonStateGetter(HLERequestContext& ctx); - void GetSelfController(HLERequestContext& ctx); - void GetWindowController(HLERequestContext& ctx); - void GetAudioController(HLERequestContext& ctx); - void GetDisplayController(HLERequestContext& ctx); - void GetLibraryAppletCreator(HLERequestContext& ctx); - void GetHomeMenuFunctions(HLERequestContext& ctx); - void GetGlobalStateController(HLERequestContext& ctx); - void GetApplicationCreator(HLERequestContext& ctx); - void GetAppletCommonFunctions(HLERequestContext& ctx); - void GetDebugFunctions(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nvnflinger; - std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp deleted file mode 100644 index 48923fe41..000000000 --- a/src/core/hle/service/am/system_buffer_manager.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/system_buffer_manager.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/vi/vi_results.h" - -namespace Service::AM { - -SystemBufferManager::SystemBufferManager() = default; - -SystemBufferManager::~SystemBufferManager() { - if (!m_nvnflinger) { - return; - } - - // Clean up shared layers. - if (m_buffer_sharing_enabled) { - m_nvnflinger->GetSystemBufferManager().Finalize(m_process); - } -} - -bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, - AppletId applet_id, LibraryAppletMode mode) { - if (m_nvnflinger) { - return m_buffer_sharing_enabled; - } - - m_process = process; - m_nvnflinger = nvnflinger; - m_buffer_sharing_enabled = false; - m_system_shared_buffer_id = 0; - m_system_shared_layer_id = 0; - - if (applet_id <= AppletId::Application) { - return false; - } - - Nvnflinger::LayerBlending blending = Nvnflinger::LayerBlending::None; - if (mode == LibraryAppletMode::PartialForeground || - mode == LibraryAppletMode::PartialForegroundIndirectDisplay) { - blending = Nvnflinger::LayerBlending::Coverage; - } - - const auto display_id = m_nvnflinger->OpenDisplay("Default").value(); - const auto res = m_nvnflinger->GetSystemBufferManager().Initialize( - m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending); - - if (res.IsSuccess()) { - m_buffer_sharing_enabled = true; - m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); - } - - return m_buffer_sharing_enabled; -} - -void SystemBufferManager::SetWindowVisibility(bool visible) { - if (m_visible == visible) { - return; - } - - m_visible = visible; - - if (m_nvnflinger) { - m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); - } -} - -Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, - s32* out_fbshare_layer_index) { - if (!m_buffer_sharing_enabled) { - return VI::ResultPermissionDenied; - } - - return m_nvnflinger->GetSystemBufferManager().WriteAppletCaptureBuffer(out_was_written, - out_fbshare_layer_index); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h deleted file mode 100644 index 0690f68b6..000000000 --- a/src/core/hle/service/am/system_buffer_manager.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <set> - -#include "common/common_funcs.h" -#include "common/common_types.h" - -#include "core/hle/service/am/am_types.h" - -namespace Kernel { -class KProcess; -} - -namespace Service::Nvnflinger { -class Nvnflinger; -} - -union Result; - -namespace Service::AM { - -class SystemBufferManager { -public: - SystemBufferManager(); - ~SystemBufferManager(); - - bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id, - LibraryAppletMode mode); - - void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, - u64* out_system_shared_layer_id) { - *out_system_shared_buffer_id = m_system_shared_buffer_id; - *out_system_shared_layer_id = m_system_shared_layer_id; - } - - void SetWindowVisibility(bool visible); - - Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); - -private: - Kernel::KProcess* m_process{}; - Nvnflinger::Nvnflinger* m_nvnflinger{}; - bool m_buffer_sharing_enabled{}; - bool m_visible{true}; - u64 m_system_shared_buffer_id{}; - u64 m_system_shared_layer_id{}; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp deleted file mode 100644 index c07ef228b..000000000 --- a/src/core/hle/service/am/window_controller.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/am/applet.h" -#include "core/hle/service/am/window_controller.h" -#include "core/hle/service/ipc_helpers.h" - -namespace Service::AM { - -IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_) - : ServiceFramework{system_, "IWindowController"}, applet{std::move(applet_)} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "CreateWindow"}, - {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, - {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"}, - {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, - {11, nullptr, "ReleaseForegroundRights"}, - {12, nullptr, "RejectToChangeIntoBackground"}, - {20, &IWindowController::SetAppletWindowVisibility, "SetAppletWindowVisibility"}, - {21, &IWindowController::SetAppletGpuTimeSlice, "SetAppletGpuTimeSlice"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IWindowController::~IWindowController() = default; - -void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(applet->aruid); -} - -void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) { - u64 aruid = 0; - if (auto caller = applet->caller_applet.lock(); caller) { - aruid = caller->aruid; - } - - LOG_WARNING(Service_AM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(aruid); -} - -void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IWindowController::SetAppletWindowVisibility(HLERequestContext& ctx) { - LOG_INFO(Service_AM, "called"); - - IPC::RequestParser rp{ctx}; - const bool visible = rp.Pop<bool>(); - - applet->system_buffer_manager.SetWindowVisibility(visible); - applet->hid_registration.EnableAppletToGetInput(visible); - - if (visible) { - applet->focus_state = FocusState::InFocus; - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); - } else { - applet->focus_state = FocusState::NotInFocus; - applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IWindowController::SetAppletGpuTimeSlice(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto time_slice = rp.Pop<s64>(); - - LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -} // namespace Service::AM diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h deleted file mode 100644 index a28219abe..000000000 --- a/src/core/hle/service/am/window_controller.h +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::AM { - -struct Applet; - -class IWindowController final : public ServiceFramework<IWindowController> { -public: - explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_); - ~IWindowController() override; - -private: - void GetAppletResourceUserId(HLERequestContext& ctx); - void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx); - void AcquireForegroundRights(HLERequestContext& ctx); - void SetAppletWindowVisibility(HLERequestContext& ctx); - void SetAppletGpuTimeSlice(HLERequestContext& ctx); - - const std::shared_ptr<Applet> applet; -}; - -} // namespace Service::AM diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp deleted file mode 100644 index 3101cf447..000000000 --- a/src/core/hle/service/audio/audctl.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/hle/service/audio/audctl.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/set/system_settings_server.h" -#include "core/hle/service/sm/sm.h" - -namespace Service::Audio { - -AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetTargetVolume"}, - {1, nullptr, "SetTargetVolume"}, - {2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"}, - {3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"}, - {4, nullptr, "IsTargetMute"}, - {5, nullptr, "SetTargetMute"}, - {6, nullptr, "IsTargetConnected"}, - {7, nullptr, "SetDefaultTarget"}, - {8, nullptr, "GetDefaultTarget"}, - {9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"}, - {10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"}, - {11, nullptr, "SetForceMutePolicy"}, - {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, - {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, - {14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"}, - {15, nullptr, "SetOutputTarget"}, - {16, nullptr, "SetInputTargetForceEnabled"}, - {17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"}, - {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, - {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, - {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, - {21, nullptr, "GetAudioOutputTargetForPlayReport"}, - {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"}, - {23, nullptr, "SetSystemOutputMasterVolume"}, - {24, nullptr, "GetSystemOutputMasterVolume"}, - {25, nullptr, "GetAudioVolumeDataForPlayReport"}, - {26, nullptr, "UpdateHeadphoneSettings"}, - {27, nullptr, "SetVolumeMappingTableForDev"}, - {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, - {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, - {30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"}, - {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, - {32, nullptr, "GetActiveOutputTarget"}, - {33, nullptr, "GetTargetDeviceInfo"}, - {34, nullptr, "AcquireTargetNotification"}, - {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, - {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, - {37, nullptr, "SetHearingProtectionSafeguardEnabled"}, - {38, nullptr, "IsHearingProtectionSafeguardEnabled"}, - {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"}, - {40, nullptr, "GetSystemInformationForDebug"}, - {41, nullptr, "SetVolumeButtonLongPressTime"}, - {42, nullptr, "SetNativeVolumeForDebug"}, - {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, - {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, - {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, - {10100, nullptr, "GetAudioVolumeDataForPlayReport"}, - {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"}, - {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"}, - {10103, nullptr, "GetAudioOutputTargetForPlayReport"}, - {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"}, - {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, - {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, - {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, - }; - // clang-format on - - RegisterHandlers(functions); - - m_set_sys = - system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); -} - -AudCtl::~AudCtl() = default; - -void AudCtl::GetTargetVolumeMin(HLERequestContext& ctx) { - LOG_DEBUG(Audio, "called."); - - // This service function is currently hardcoded on the - // actual console to this value (as of 8.0.0). - constexpr s32 target_min_volume = 0; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(target_min_volume); -} - -void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) { - LOG_DEBUG(Audio, "called."); - - // This service function is currently hardcoded on the - // actual console to this value (as of 8.0.0). - constexpr s32 target_max_volume = 15; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(target_max_volume); -} - -void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; - - Set::AudioOutputMode output_mode{}; - const auto result = m_set_sys->GetAudioOutputMode(output_mode, target); - - LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.PushEnum(output_mode); -} - -void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; - const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()}; - - const auto result = m_set_sys->SetAudioOutputMode(target, output_mode); - - LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { - LOG_WARNING(Audio, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(ForceMutePolicy::Disable); -} - -void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; - - LOG_WARNING(Audio, "(STUBBED) called, target={}", target); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(Set::AudioOutputMode::ch_7_1); -} - -void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; - const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()}; - - LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) { - LOG_WARNING(Audio, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { - LOG_WARNING(Audio, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(HeadphoneOutputLevelMode::Normal); -} - -void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()}; - - LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", - is_speaker_auto_mute_enabled); - - const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { - bool is_speaker_auto_mute_enabled{}; - const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled); - - LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", - is_speaker_auto_mute_enabled); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push<u8>(is_speaker_auto_mute_enabled); -} - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h deleted file mode 100644 index 4c90ead70..000000000 --- a/src/core/hle/service/audio/audctl.h +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Set { -class ISystemSettingsServer; -} - -namespace Service::Audio { - -class AudCtl final : public ServiceFramework<AudCtl> { -public: - explicit AudCtl(Core::System& system_); - ~AudCtl() override; - -private: - enum class ForceMutePolicy { - Disable, - SpeakerMuteOnHeadphoneUnplugged, - }; - - enum class HeadphoneOutputLevelMode { - Normal, - HighPower, - }; - - void GetTargetVolumeMin(HLERequestContext& ctx); - void GetTargetVolumeMax(HLERequestContext& ctx); - void GetAudioOutputMode(HLERequestContext& ctx); - void SetAudioOutputMode(HLERequestContext& ctx); - void GetForceMutePolicy(HLERequestContext& ctx); - void GetOutputModeSetting(HLERequestContext& ctx); - void SetOutputModeSetting(HLERequestContext& ctx); - void SetHeadphoneOutputLevelMode(HLERequestContext& ctx); - void GetHeadphoneOutputLevelMode(HLERequestContext& ctx); - void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx); - void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx); - void AcquireTargetNotification(HLERequestContext& ctx); - - std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; -}; - -} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp index dccd16309..44af030eb 100644 --- a/src/core/hle/service/audio/audio.cpp +++ b/src/core/hle/service/audio/audio.cpp @@ -2,9 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" -#include "core/hle/service/audio/audctl.h" #include "core/hle/service/audio/audin_u.h" #include "core/hle/service/audio/audio.h" +#include "core/hle/service/audio/audio_controller.h" #include "core/hle/service/audio/audout_u.h" #include "core/hle/service/audio/audrec_a.h" #include "core/hle/service/audio/audrec_u.h" @@ -18,7 +18,7 @@ namespace Service::Audio { void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system)); + server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system)); server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system)); server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system)); server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system)); diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp new file mode 100644 index 000000000..a6da66d0f --- /dev/null +++ b/src/core/hle/service/audio/audio_controller.cpp @@ -0,0 +1,174 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/audio/audio_controller.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::Audio { + +IAudioController::IAudioController(Core::System& system_) + : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetTargetVolume"}, + {1, nullptr, "SetTargetVolume"}, + {2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"}, + {3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"}, + {4, nullptr, "IsTargetMute"}, + {5, nullptr, "SetTargetMute"}, + {6, nullptr, "IsTargetConnected"}, + {7, nullptr, "SetDefaultTarget"}, + {8, nullptr, "GetDefaultTarget"}, + {9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"}, + {10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"}, + {11, nullptr, "SetForceMutePolicy"}, + {12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"}, + {13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"}, + {14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"}, + {15, nullptr, "SetOutputTarget"}, + {16, nullptr, "SetInputTargetForceEnabled"}, + {17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"}, + {18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"}, + {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, + {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, + {21, nullptr, "GetAudioOutputTargetForPlayReport"}, + {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"}, + {23, nullptr, "SetSystemOutputMasterVolume"}, + {24, nullptr, "GetSystemOutputMasterVolume"}, + {25, nullptr, "GetAudioVolumeDataForPlayReport"}, + {26, nullptr, "UpdateHeadphoneSettings"}, + {27, nullptr, "SetVolumeMappingTableForDev"}, + {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, + {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, + {30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"}, + {31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"}, + {32, nullptr, "GetActiveOutputTarget"}, + {33, nullptr, "GetTargetDeviceInfo"}, + {34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"}, + {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, + {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, + {37, nullptr, "SetHearingProtectionSafeguardEnabled"}, + {38, nullptr, "IsHearingProtectionSafeguardEnabled"}, + {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"}, + {40, nullptr, "GetSystemInformationForDebug"}, + {41, nullptr, "SetVolumeButtonLongPressTime"}, + {42, nullptr, "SetNativeVolumeForDebug"}, + {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, + {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, + {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, + {10100, nullptr, "GetAudioVolumeDataForPlayReport"}, + {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"}, + {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"}, + {10103, nullptr, "GetAudioOutputTargetForPlayReport"}, + {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"}, + {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, + {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"}, + {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"}, + }; + // clang-format on + + RegisterHandlers(functions); + + m_set_sys = + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); + notification_event = service_context.CreateEvent("IAudioController:NotificationEvent"); +} + +IAudioController::~IAudioController() { + service_context.CloseEvent(notification_event); +}; + +Result IAudioController::GetTargetVolumeMin(Out<s32> out_target_min_volume) { + LOG_DEBUG(Audio, "called."); + + // This service function is currently hardcoded on the + // actual console to this value (as of 8.0.0). + *out_target_min_volume = 0; + R_SUCCEED(); +} + +Result IAudioController::GetTargetVolumeMax(Out<s32> out_target_max_volume) { + LOG_DEBUG(Audio, "called."); + + // This service function is currently hardcoded on the + // actual console to this value (as of 8.0.0). + *out_target_max_volume = 15; + R_SUCCEED(); +} + +Result IAudioController::GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode, + Set::AudioOutputModeTarget target) { + const auto result = m_set_sys->GetAudioOutputMode(out_output_mode, target); + + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode); + R_RETURN(result); +} + +Result IAudioController::SetAudioOutputMode(Set::AudioOutputModeTarget target, + Set::AudioOutputMode output_mode) { + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + + R_RETURN(m_set_sys->SetAudioOutputMode(target, output_mode)); +} + +Result IAudioController::GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy) { + LOG_WARNING(Audio, "(STUBBED) called"); + + // Removed on FW 13.2.1+ + *out_mute_policy = ForceMutePolicy::Disable; + R_SUCCEED(); +} + +Result IAudioController::GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode, + Set::AudioOutputModeTarget target) { + LOG_WARNING(Audio, "(STUBBED) called, target={}", target); + + *out_output_mode = Set::AudioOutputMode::ch_7_1; + R_SUCCEED(); +} + +Result IAudioController::SetOutputModeSetting(Set::AudioOutputModeTarget target, + Set::AudioOutputMode output_mode) { + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); + R_SUCCEED(); +} + +Result IAudioController::SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode) { + LOG_WARNING(Audio, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IAudioController::GetHeadphoneOutputLevelMode( + Out<HeadphoneOutputLevelMode> out_output_level_mode) { + LOG_INFO(Audio, "called"); + + *out_output_level_mode = HeadphoneOutputLevelMode::Normal; + R_SUCCEED(); +} + +Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) { + LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled); + + R_RETURN(m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled)); +} + +Result IAudioController::IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled) { + const auto result = m_set_sys->GetSpeakerAutoMuteFlag(out_is_speaker_auto_mute_enabled); + + LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", *out_is_speaker_auto_mute_enabled); + R_RETURN(result); +} + +Result IAudioController::AcquireTargetNotification( + OutCopyHandle<Kernel::KReadableEvent> out_notification_event) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + *out_notification_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); +} + +} // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_controller.h b/src/core/hle/service/audio/audio_controller.h new file mode 100644 index 000000000..9e8514373 --- /dev/null +++ b/src/core/hle/service/audio/audio_controller.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" +#include "core/hle/service/set/settings_types.h" + +namespace Core { +class System; +} + +namespace Service::Set { +class ISystemSettingsServer; +} + +namespace Service::Audio { + +class IAudioController final : public ServiceFramework<IAudioController> { +public: + explicit IAudioController(Core::System& system_); + ~IAudioController() override; + +private: + enum class ForceMutePolicy { + Disable, + SpeakerMuteOnHeadphoneUnplugged, + }; + + enum class HeadphoneOutputLevelMode { + Normal, + HighPower, + }; + + Result GetTargetVolumeMin(Out<s32> out_target_min_volume); + Result GetTargetVolumeMax(Out<s32> out_target_max_volume); + Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode, + Set::AudioOutputModeTarget target); + Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode); + Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy); + Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode, + Set::AudioOutputModeTarget target); + Result SetOutputModeSetting(Set::AudioOutputModeTarget target, + Set::AudioOutputMode output_mode); + Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode); + Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode); + Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled); + Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled); + Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event); + + KernelHelpers::ServiceContext service_context; + + Kernel::KEvent* notification_event; + std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; +}; + +} // namespace Service::Audio diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 2dc23e674..d120dade8 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -3,141 +3,18 @@ #include <memory> -#include "common/logging/log.h" -#include "core/core.h" -#include "core/hle/kernel/k_event.h" #include "core/hle/service/btm/btm.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/btm/btm_debug.h" +#include "core/hle/service/btm/btm_system.h" +#include "core/hle/service/btm/btm_user.h" #include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::BTM { -class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { +class IBtm final : public ServiceFramework<IBtm> { public: - explicit IBtmUserCore(Core::System& system_) - : ServiceFramework{system_, "IBtmUserCore"}, service_context{system_, "IBtmUserCore"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"}, - {1, nullptr, "GetBleScanFilterParameter"}, - {2, nullptr, "GetBleScanFilterParameter2"}, - {3, nullptr, "StartBleScanForGeneral"}, - {4, nullptr, "StopBleScanForGeneral"}, - {5, nullptr, "GetBleScanResultsForGeneral"}, - {6, nullptr, "StartBleScanForPaired"}, - {7, nullptr, "StopBleScanForPaired"}, - {8, nullptr, "StartBleScanForSmartDevice"}, - {9, nullptr, "StopBleScanForSmartDevice"}, - {10, nullptr, "GetBleScanResultsForSmartDevice"}, - {17, &IBtmUserCore::AcquireBleConnectionEvent, "AcquireBleConnectionEvent"}, - {18, nullptr, "BleConnect"}, - {19, nullptr, "BleDisconnect"}, - {20, nullptr, "BleGetConnectionState"}, - {21, nullptr, "AcquireBlePairingEvent"}, - {22, nullptr, "BlePairDevice"}, - {23, nullptr, "BleUnPairDevice"}, - {24, nullptr, "BleUnPairDevice2"}, - {25, nullptr, "BleGetPairedDevices"}, - {26, &IBtmUserCore::AcquireBleServiceDiscoveryEvent, "AcquireBleServiceDiscoveryEvent"}, - {27, nullptr, "GetGattServices"}, - {28, nullptr, "GetGattService"}, - {29, nullptr, "GetGattIncludedServices"}, - {30, nullptr, "GetBelongingGattService"}, - {31, nullptr, "GetGattCharacteristics"}, - {32, nullptr, "GetGattDescriptors"}, - {33, &IBtmUserCore::AcquireBleMtuConfigEvent, "AcquireBleMtuConfigEvent"}, - {34, nullptr, "ConfigureBleMtu"}, - {35, nullptr, "GetBleMtu"}, - {36, nullptr, "RegisterBleGattDataPath"}, - {37, nullptr, "UnregisterBleGattDataPath"}, - }; - // clang-format on - RegisterHandlers(functions); - - scan_event = service_context.CreateEvent("IBtmUserCore:ScanEvent"); - connection_event = service_context.CreateEvent("IBtmUserCore:ConnectionEvent"); - service_discovery_event = service_context.CreateEvent("IBtmUserCore:DiscoveryEvent"); - config_event = service_context.CreateEvent("IBtmUserCore:ConfigEvent"); - } - - ~IBtmUserCore() override { - service_context.CloseEvent(scan_event); - service_context.CloseEvent(connection_event); - service_context.CloseEvent(service_discovery_event); - service_context.CloseEvent(config_event); - } - -private: - void AcquireBleScanEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3, 1}; - rb.Push(ResultSuccess); - rb.Push(true); - rb.PushCopyObjects(scan_event->GetReadableEvent()); - } - - void AcquireBleConnectionEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3, 1}; - rb.Push(ResultSuccess); - rb.Push(true); - rb.PushCopyObjects(connection_event->GetReadableEvent()); - } - - void AcquireBleServiceDiscoveryEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3, 1}; - rb.Push(ResultSuccess); - rb.Push(true); - rb.PushCopyObjects(service_discovery_event->GetReadableEvent()); - } - - void AcquireBleMtuConfigEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3, 1}; - rb.Push(ResultSuccess); - rb.Push(true); - rb.PushCopyObjects(config_event->GetReadableEvent()); - } - - KernelHelpers::ServiceContext service_context; - - Kernel::KEvent* scan_event; - Kernel::KEvent* connection_event; - Kernel::KEvent* service_discovery_event; - Kernel::KEvent* config_event; -}; - -class BTM_USR final : public ServiceFramework<BTM_USR> { -public: - explicit BTM_USR(Core::System& system_) : ServiceFramework{system_, "btm:u"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &BTM_USR::GetCore, "GetCore"}, - }; - // clang-format on - RegisterHandlers(functions); - } - -private: - void GetCore(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IBtmUserCore>(system); - } -}; - -class BTM final : public ServiceFramework<BTM> { -public: - explicit BTM(Core::System& system_) : ServiceFramework{system_, "btm"} { + explicit IBtm(Core::System& system_) : ServiceFramework{system_, "btm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetState"}, @@ -232,144 +109,13 @@ public: } }; -class BTM_DBG final : public ServiceFramework<BTM_DBG> { -public: - explicit BTM_DBG(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "AcquireDiscoveryEvent"}, - {1, nullptr, "StartDiscovery"}, - {2, nullptr, "CancelDiscovery"}, - {3, nullptr, "GetDeviceProperty"}, - {4, nullptr, "CreateBond"}, - {5, nullptr, "CancelBond"}, - {6, nullptr, "SetTsiMode"}, - {7, nullptr, "GeneralTest"}, - {8, nullptr, "HidConnect"}, - {9, nullptr, "GeneralGet"}, - {10, nullptr, "GetGattClientDisconnectionReason"}, - {11, nullptr, "GetBleConnectionParameter"}, - {12, nullptr, "GetBleConnectionParameterRequest"}, - {13, nullptr, "Unknown13"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> { -public: - explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IBtmSystemCore::StartGamepadPairing, "StartGamepadPairing"}, - {1, &IBtmSystemCore::CancelGamepadPairing, "CancelGamepadPairing"}, - {2, nullptr, "ClearGamepadPairingDatabase"}, - {3, nullptr, "GetPairedGamepadCount"}, - {4, nullptr, "EnableRadio"}, - {5, nullptr, "DisableRadio"}, - {6, &IBtmSystemCore::IsRadioEnabled, "IsRadioEnabled"}, - {7, nullptr, "AcquireRadioEvent"}, - {8, nullptr, "AcquireGamepadPairingEvent"}, - {9, nullptr, "IsGamepadPairingStarted"}, - {10, nullptr, "StartAudioDeviceDiscovery"}, - {11, nullptr, "StopAudioDeviceDiscovery"}, - {12, nullptr, "IsDiscoveryingAudioDevice"}, - {13, nullptr, "GetDiscoveredAudioDevice"}, - {14, nullptr, "AcquireAudioDeviceConnectionEvent"}, - {15, nullptr, "ConnectAudioDevice"}, - {16, nullptr, "IsConnectingAudioDevice"}, - {17, &IBtmSystemCore::GetConnectedAudioDevices, "GetConnectedAudioDevices"}, - {18, nullptr, "DisconnectAudioDevice"}, - {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"}, - {20, &IBtmSystemCore::GetPairedAudioDevices, "GetPairedAudioDevices"}, - {21, nullptr, "RemoveAudioDevicePairing"}, - {22, &IBtmSystemCore::RequestAudioDeviceConnectionRejection, "RequestAudioDeviceConnectionRejection"}, - {23, &IBtmSystemCore::CancelAudioDeviceConnectionRejection, "CancelAudioDeviceConnectionRejection"} - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void IsRadioEnabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_BTM, "(STUBBED) called"); // Spams a lot when controller applet is running - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(true); - } - - void StartGamepadPairing(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void CancelGamepadPairing(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void CancelAudioDeviceConnectionRejection(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetConnectedAudioDevices(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(0); - } - - void GetPairedAudioDevices(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(0); - } - - void RequestAudioDeviceConnectionRejection(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } -}; - -class BTM_SYS final : public ServiceFramework<BTM_SYS> { -public: - explicit BTM_SYS(Core::System& system_) : ServiceFramework{system_, "btm:sys"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &BTM_SYS::GetCore, "GetCore"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void GetCore(HLERequestContext& ctx) { - LOG_WARNING(Service_BTM, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IBtmSystemCore>(system); - } -}; - void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("btm", std::make_shared<BTM>(system)); - server_manager->RegisterNamedService("btm:dbg", std::make_shared<BTM_DBG>(system)); - server_manager->RegisterNamedService("btm:sys", std::make_shared<BTM_SYS>(system)); - server_manager->RegisterNamedService("btm:u", std::make_shared<BTM_USR>(system)); + server_manager->RegisterNamedService("btm", std::make_shared<IBtm>(system)); + server_manager->RegisterNamedService("btm:dbg", std::make_shared<IBtmDebug>(system)); + server_manager->RegisterNamedService("btm:sys", std::make_shared<IBtmSystem>(system)); + server_manager->RegisterNamedService("btm:u", std::make_shared<IBtmUser>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h index a99b34364..0bf77d053 100644 --- a/src/core/hle/service/btm/btm.h +++ b/src/core/hle/service/btm/btm.h @@ -3,10 +3,6 @@ #pragma once -namespace Service::SM { -class ServiceManager; -} - namespace Core { class System; }; diff --git a/src/core/hle/service/btm/btm_debug.cpp b/src/core/hle/service/btm/btm_debug.cpp new file mode 100644 index 000000000..4d61d2641 --- /dev/null +++ b/src/core/hle/service/btm/btm_debug.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/btm/btm_debug.h" + +namespace Service::BTM { + +IBtmDebug::IBtmDebug(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "AcquireDiscoveryEvent"}, + {1, nullptr, "StartDiscovery"}, + {2, nullptr, "CancelDiscovery"}, + {3, nullptr, "GetDeviceProperty"}, + {4, nullptr, "CreateBond"}, + {5, nullptr, "CancelBond"}, + {6, nullptr, "SetTsiMode"}, + {7, nullptr, "GeneralTest"}, + {8, nullptr, "HidConnect"}, + {9, nullptr, "GeneralGet"}, + {10, nullptr, "GetGattClientDisconnectionReason"}, + {11, nullptr, "GetBleConnectionParameter"}, + {12, nullptr, "GetBleConnectionParameterRequest"}, + {13, nullptr, "Unknown13"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IBtmDebug::~IBtmDebug() = default; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_debug.h b/src/core/hle/service/btm/btm_debug.h new file mode 100644 index 000000000..bf4f7e14f --- /dev/null +++ b/src/core/hle/service/btm/btm_debug.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::BTM { + +class IBtmDebug final : public ServiceFramework<IBtmDebug> { +public: + explicit IBtmDebug(Core::System& system_); + ~IBtmDebug() override; +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system.cpp b/src/core/hle/service/btm/btm_system.cpp new file mode 100644 index 000000000..99718a7b0 --- /dev/null +++ b/src/core/hle/service/btm/btm_system.cpp @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/btm/btm_system.h" +#include "core/hle/service/btm/btm_system_core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/service.h" + +namespace Service::BTM { + +IBtmSystem::IBtmSystem(Core::System& system_) : ServiceFramework{system_, "btm:sys"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IBtmSystem::GetCore>, "GetCore"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IBtmSystem::~IBtmSystem() = default; + +Result IBtmSystem::GetCore(OutInterface<IBtmSystemCore> out_interface) { + LOG_WARNING(Service_BTM, "called"); + + *out_interface = std::make_shared<IBtmSystemCore>(system); + R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system.h b/src/core/hle/service/btm/btm_system.h new file mode 100644 index 000000000..fe1c6dbd7 --- /dev/null +++ b/src/core/hle/service/btm/btm_system.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::BTM { +class IBtmSystemCore; + +class IBtmSystem final : public ServiceFramework<IBtmSystem> { +public: + explicit IBtmSystem(Core::System& system_); + ~IBtmSystem() override; + +private: + Result GetCore(OutInterface<IBtmSystemCore> out_interface); +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system_core.cpp b/src/core/hle/service/btm/btm_system_core.cpp new file mode 100644 index 000000000..4bc8a9e8b --- /dev/null +++ b/src/core/hle/service/btm/btm_system_core.cpp @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/btm/btm_system_core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::BTM { + +IBtmSystemCore::IBtmSystemCore(Core::System& system_) + : ServiceFramework{system_, "IBtmSystemCore"}, service_context{system_, "IBtmSystemCore"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IBtmSystemCore::StartGamepadPairing>, "StartGamepadPairing"}, + {1, C<&IBtmSystemCore::CancelGamepadPairing>, "CancelGamepadPairing"}, + {2, nullptr, "ClearGamepadPairingDatabase"}, + {3, nullptr, "GetPairedGamepadCount"}, + {4, C<&IBtmSystemCore::EnableRadio>, "EnableRadio"}, + {5, C<&IBtmSystemCore::DisableRadio>, "DisableRadio"}, + {6, C<&IBtmSystemCore::IsRadioEnabled>, "IsRadioEnabled"}, + {7, C<&IBtmSystemCore::AcquireRadioEvent>, "AcquireRadioEvent"}, + {8, nullptr, "AcquireGamepadPairingEvent"}, + {9, nullptr, "IsGamepadPairingStarted"}, + {10, nullptr, "StartAudioDeviceDiscovery"}, + {11, nullptr, "StopAudioDeviceDiscovery"}, + {12, nullptr, "IsDiscoveryingAudioDevice"}, + {13, nullptr, "GetDiscoveredAudioDevice"}, + {14, C<&IBtmSystemCore::AcquireAudioDeviceConnectionEvent>, "AcquireAudioDeviceConnectionEvent"}, + {15, nullptr, "ConnectAudioDevice"}, + {16, nullptr, "IsConnectingAudioDevice"}, + {17, C<&IBtmSystemCore::GetConnectedAudioDevices>, "GetConnectedAudioDevices"}, + {18, nullptr, "DisconnectAudioDevice"}, + {19, nullptr, "AcquirePairedAudioDeviceInfoChangedEvent"}, + {20, C<&IBtmSystemCore::GetPairedAudioDevices>, "GetPairedAudioDevices"}, + {21, nullptr, "RemoveAudioDevicePairing"}, + {22, C<&IBtmSystemCore::RequestAudioDeviceConnectionRejection>, "RequestAudioDeviceConnectionRejection"}, + {23, C<&IBtmSystemCore::CancelAudioDeviceConnectionRejection>, "CancelAudioDeviceConnectionRejection"} + }; + // clang-format on + + RegisterHandlers(functions); + radio_event = service_context.CreateEvent("IBtmSystemCore::RadioEvent"); + audio_device_connection_event = + service_context.CreateEvent("IBtmSystemCore::AudioDeviceConnectionEvent"); + + m_set_sys = + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); +} + +IBtmSystemCore::~IBtmSystemCore() { + service_context.CloseEvent(radio_event); + service_context.CloseEvent(audio_device_connection_event); +} + +Result IBtmSystemCore::StartGamepadPairing() { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IBtmSystemCore::CancelGamepadPairing() { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IBtmSystemCore::EnableRadio() { + LOG_DEBUG(Service_BTM, "called"); + + R_RETURN(m_set_sys->SetBluetoothEnableFlag(true)); +} +Result IBtmSystemCore::DisableRadio() { + LOG_DEBUG(Service_BTM, "called"); + + R_RETURN(m_set_sys->SetBluetoothEnableFlag(false)); +} + +Result IBtmSystemCore::IsRadioEnabled(Out<bool> out_is_enabled) { + LOG_DEBUG(Service_BTM, "called"); + + R_RETURN(m_set_sys->GetBluetoothEnableFlag(out_is_enabled)); +} + +Result IBtmSystemCore::AcquireRadioEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_is_valid = true; + *out_event = &radio_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IBtmSystemCore::AcquireAudioDeviceConnectionEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_event = &audio_device_connection_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IBtmSystemCore::GetConnectedAudioDevices( + Out<s32> out_count, OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_count = 0; + R_SUCCEED(); +} + +Result IBtmSystemCore::GetPairedAudioDevices( + Out<s32> out_count, OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_count = 0; + R_SUCCEED(); +} + +Result IBtmSystemCore::RequestAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid) { + LOG_WARNING(Service_BTM, "(STUBBED) called, applet_resource_user_id={}", aruid.pid); + R_SUCCEED(); +} + +Result IBtmSystemCore::CancelAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid) { + LOG_WARNING(Service_BTM, "(STUBBED) called, applet_resource_user_id={}", aruid.pid); + R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_system_core.h b/src/core/hle/service/btm/btm_system_core.h new file mode 100644 index 000000000..06498b21e --- /dev/null +++ b/src/core/hle/service/btm/btm_system_core.h @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} + +namespace Service::Set { +class ISystemSettingsServer; +} + +namespace Service::BTM { + +class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> { +public: + explicit IBtmSystemCore(Core::System& system_); + ~IBtmSystemCore() override; + +private: + Result StartGamepadPairing(); + Result CancelGamepadPairing(); + Result EnableRadio(); + Result DisableRadio(); + Result IsRadioEnabled(Out<bool> out_is_enabled); + + Result AcquireRadioEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event); + + Result AcquireAudioDeviceConnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + + Result GetConnectedAudioDevices( + Out<s32> out_count, + OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices); + + Result GetPairedAudioDevices( + Out<s32> out_count, + OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices); + + Result RequestAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid); + Result CancelAudioDeviceConnectionRejection(ClientAppletResourceUserId aruid); + + KernelHelpers::ServiceContext service_context; + + Kernel::KEvent* radio_event; + Kernel::KEvent* audio_device_connection_event; + std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user.cpp b/src/core/hle/service/btm/btm_user.cpp new file mode 100644 index 000000000..d2e228f8d --- /dev/null +++ b/src/core/hle/service/btm/btm_user.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/logging/log.h" +#include "core/hle/service/btm/btm_user.h" +#include "core/hle/service/btm/btm_user_core.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::BTM { + +IBtmUser::IBtmUser(Core::System& system_) : ServiceFramework{system_, "btm:u"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IBtmUser::GetCore>, "GetCore"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IBtmUser::~IBtmUser() = default; + +Result IBtmUser::GetCore(OutInterface<IBtmUserCore> out_interface) { + LOG_WARNING(Service_BTM, "called"); + + *out_interface = std::make_shared<IBtmUserCore>(system); + R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user.h b/src/core/hle/service/btm/btm_user.h new file mode 100644 index 000000000..d9ee5db45 --- /dev/null +++ b/src/core/hle/service/btm/btm_user.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::BTM { +class IBtmUserCore; + +class IBtmUser final : public ServiceFramework<IBtmUser> { +public: + explicit IBtmUser(Core::System& system_); + ~IBtmUser() override; + +private: + Result GetCore(OutInterface<IBtmUserCore> out_interface); +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user_core.cpp b/src/core/hle/service/btm/btm_user_core.cpp new file mode 100644 index 000000000..6f9fa589b --- /dev/null +++ b/src/core/hle/service/btm/btm_user_core.cpp @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <memory> + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/btm/btm_user_core.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::BTM { + +IBtmUserCore::IBtmUserCore(Core::System& system_) + : ServiceFramework{system_, "IBtmUserCore"}, service_context{system_, "IBtmUserCore"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IBtmUserCore::AcquireBleScanEvent>, "AcquireBleScanEvent"}, + {1, nullptr, "GetBleScanFilterParameter"}, + {2, nullptr, "GetBleScanFilterParameter2"}, + {3, nullptr, "StartBleScanForGeneral"}, + {4, nullptr, "StopBleScanForGeneral"}, + {5, nullptr, "GetBleScanResultsForGeneral"}, + {6, nullptr, "StartBleScanForPaired"}, + {7, nullptr, "StopBleScanForPaired"}, + {8, nullptr, "StartBleScanForSmartDevice"}, + {9, nullptr, "StopBleScanForSmartDevice"}, + {10, nullptr, "GetBleScanResultsForSmartDevice"}, + {17, C<&IBtmUserCore::AcquireBleConnectionEvent>, "AcquireBleConnectionEvent"}, + {18, nullptr, "BleConnect"}, + {19, nullptr, "BleDisconnect"}, + {20, nullptr, "BleGetConnectionState"}, + {21, nullptr, "AcquireBlePairingEvent"}, + {22, nullptr, "BlePairDevice"}, + {23, nullptr, "BleUnPairDevice"}, + {24, nullptr, "BleUnPairDevice2"}, + {25, nullptr, "BleGetPairedDevices"}, + {26, C<&IBtmUserCore::AcquireBleServiceDiscoveryEvent>, "AcquireBleServiceDiscoveryEvent"}, + {27, nullptr, "GetGattServices"}, + {28, nullptr, "GetGattService"}, + {29, nullptr, "GetGattIncludedServices"}, + {30, nullptr, "GetBelongingGattService"}, + {31, nullptr, "GetGattCharacteristics"}, + {32, nullptr, "GetGattDescriptors"}, + {33, C<&IBtmUserCore::AcquireBleMtuConfigEvent>, "AcquireBleMtuConfigEvent"}, + {34, nullptr, "ConfigureBleMtu"}, + {35, nullptr, "GetBleMtu"}, + {36, nullptr, "RegisterBleGattDataPath"}, + {37, nullptr, "UnregisterBleGattDataPath"}, + }; + // clang-format on + RegisterHandlers(functions); + + scan_event = service_context.CreateEvent("IBtmUserCore:ScanEvent"); + connection_event = service_context.CreateEvent("IBtmUserCore:ConnectionEvent"); + service_discovery_event = service_context.CreateEvent("IBtmUserCore:DiscoveryEvent"); + config_event = service_context.CreateEvent("IBtmUserCore:ConfigEvent"); +} + +IBtmUserCore::~IBtmUserCore() { + service_context.CloseEvent(scan_event); + service_context.CloseEvent(connection_event); + service_context.CloseEvent(service_discovery_event); + service_context.CloseEvent(config_event); +} + +Result IBtmUserCore::AcquireBleScanEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_is_valid = true; + *out_event = &scan_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IBtmUserCore::AcquireBleConnectionEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_is_valid = true; + *out_event = &connection_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IBtmUserCore::AcquireBleServiceDiscoveryEvent( + Out<bool> out_is_valid, OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_is_valid = true; + *out_event = &service_discovery_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IBtmUserCore::AcquireBleMtuConfigEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_BTM, "(STUBBED) called"); + + *out_is_valid = true; + *out_event = &config_event->GetReadableEvent(); + R_SUCCEED(); +} + +} // namespace Service::BTM diff --git a/src/core/hle/service/btm/btm_user_core.h b/src/core/hle/service/btm/btm_user_core.h new file mode 100644 index 000000000..dc0a22e81 --- /dev/null +++ b/src/core/hle/service/btm/btm_user_core.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KEvent; +class KReadableEvent; +} // namespace Kernel + +namespace Core { +class System; +} + +namespace Service::BTM { + +class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { +public: + explicit IBtmUserCore(Core::System& system_); + ~IBtmUserCore() override; + +private: + Result AcquireBleScanEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event); + + Result AcquireBleConnectionEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event); + + Result AcquireBleServiceDiscoveryEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event); + + Result AcquireBleMtuConfigEvent(Out<bool> out_is_valid, + OutCopyHandle<Kernel::KReadableEvent> out_event); + + KernelHelpers::ServiceContext service_context; + + Kernel::KEvent* scan_event; + Kernel::KEvent* connection_event; + Kernel::KEvent* service_discovery_event; + Kernel::KEvent* config_event; +}; + +} // namespace Service::BTM diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index 47ff072c5..52228b830 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp @@ -16,7 +16,7 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_, // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetAlbumFileCount"}, - {1, nullptr, "GetAlbumFileList"}, + {1, C<&IAlbumAccessorService::GetAlbumFileList>, "GetAlbumFileList"}, {2, nullptr, "LoadAlbumFile"}, {3, C<&IAlbumAccessorService::DeleteAlbumFile>, "DeleteAlbumFile"}, {4, nullptr, "StorageCopyAlbumFile"}, @@ -62,6 +62,15 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_, IAlbumAccessorService::~IAlbumAccessorService() = default; +Result IAlbumAccessorService::GetAlbumFileList( + Out<u64> out_count, AlbumStorage storage, + OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries) { + LOG_INFO(Service_Capture, "called, storage={}", storage); + + const Result result = manager->GetAlbumFileList(out_entries, *out_count, storage, 0); + R_RETURN(TranslateResult(result)); +} + Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) { LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}", file_id.application_id, file_id.storage, file_id.type); diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h index 2cb9b4547..c7a5208e3 100644 --- a/src/core/hle/service/caps/caps_a.h +++ b/src/core/hle/service/caps/caps_a.h @@ -21,6 +21,9 @@ public: ~IAlbumAccessorService() override; private: + Result GetAlbumFileList(Out<u64> out_count, AlbumStorage storage, + OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries); + Result DeleteAlbumFile(AlbumFileId file_id); Result IsAlbumMounted(Out<bool> out_is_mounted, AlbumStorage storage); diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index 3ea862fad..39ae3a723 100644 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp @@ -3,6 +3,8 @@ #include <memory> +#include "common/logging/log.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/erpt/erpt.h" #include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" @@ -15,7 +17,7 @@ public: explicit ErrorReportContext(Core::System& system_) : ServiceFramework{system_, "erpt:c"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "SubmitContext"}, + {0, C<&ErrorReportContext::SubmitContext>, "SubmitContext"}, {1, nullptr, "CreateReportV0"}, {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, @@ -36,6 +38,14 @@ public: RegisterHandlers(functions); } + +private: + Result SubmitContext(InBuffer<BufferAttr_HipcMapAlias> buffer_a, + InBuffer<BufferAttr_HipcMapAlias> buffer_b) { + LOG_WARNING(Service_SET, "(STUBBED) called, buffer_a_size={}, buffer_b_size={}", + buffer_a.size(), buffer_b.size()); + R_SUCCEED(); + } }; class ErrorReportSession final : public ServiceFramework<ErrorReportSession> { diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp index 63c2d3a58..2d49f30c8 100644 --- a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp @@ -336,7 +336,7 @@ FSP_SRV::FSP_SRV(Core::System& system_) {1012, nullptr, "GetFsStackUsage"}, {1013, nullptr, "UnsetSaveDataRootPath"}, {1014, nullptr, "OutputMultiProgramTagAccessLog"}, - {1016, nullptr, "FlushAccessLogOnSdCard"}, + {1016, &FSP_SRV::FlushAccessLogOnSdCard, "FlushAccessLogOnSdCard"}, {1017, nullptr, "OutputApplicationInfoAccessLog"}, {1018, nullptr, "SetDebugOption"}, {1019, nullptr, "UnsetDebugOption"}, @@ -706,6 +706,13 @@ void FSP_SRV::GetProgramIndexForAccessLog(HLERequestContext& ctx) { rb.Push(access_log_program_index); } +void FSP_SRV::FlushAccessLogOnSdCard(HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void FSP_SRV::GetCacheStorageSize(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto index{rp.Pop<s32>()}; diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.h b/src/core/hle/service/filesystem/fsp/fsp_srv.h index 26980af99..59406e6f9 100644 --- a/src/core/hle/service/filesystem/fsp/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.h @@ -58,6 +58,7 @@ private: void SetGlobalAccessLogMode(HLERequestContext& ctx); void GetGlobalAccessLogMode(HLERequestContext& ctx); void OutputAccessLogToSdCard(HLERequestContext& ctx); + void FlushAccessLogOnSdCard(HLERequestContext& ctx); void GetProgramIndexForAccessLog(HLERequestContext& ctx); void OpenMultiCommitManager(HLERequestContext& ctx); void GetCacheStorageSize(HLERequestContext& ctx); diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index 0c27e8029..059ac3fc9 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp @@ -21,19 +21,6 @@ namespace Service::Glue::Time { namespace { - -template <typename T> -T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, - const char* category, const char* name) { - std::vector<u8> interval_buf; - auto res = set_sys->GetSettingsItemValue(interval_buf, category, name); - ASSERT(res == ResultSuccess); - - T v{}; - std::memcpy(&v, interval_buf.data(), sizeof(T)); - return v; -} - s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) { constexpr auto is_leap = [](s32 year) -> bool { return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)); @@ -65,13 +52,15 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) { s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) { Service::PSC::Time::CalendarTime calendar{ - .year = GetSettingsItemValue<s16>(set_sys, "time", "standard_user_clock_initial_year"), + .year = 2000, .month = 1, .day = 1, .hour = 0, .minute = 0, .second = 0, }; + set_sys->GetSettingsItemValueImpl<s16>(calendar.year, "time", + "standard_user_clock_initial_year"); return CalendarTimeToEpoch(calendar); } @@ -124,7 +113,7 @@ TimeManager::TimeManager(Core::System& system) ASSERT(res == ResultSuccess); Service::PSC::Time::SystemClockContext user_clock_context{}; - res = m_set_sys->GetUserSystemClockContext(user_clock_context); + res = m_set_sys->GetUserSystemClockContext(&user_clock_context); ASSERT(res == ResultSuccess); // TODO the local clock should initialise with this epoch time, and be updated somewhere else on @@ -140,11 +129,12 @@ TimeManager::TimeManager(Core::System& system) ASSERT(res == ResultSuccess); Service::PSC::Time::SystemClockContext network_clock_context{}; - res = m_set_sys->GetNetworkSystemClockContext(network_clock_context); + res = m_set_sys->GetNetworkSystemClockContext(&network_clock_context); ASSERT(res == ResultSuccess); - auto network_accuracy_m{GetSettingsItemValue<s32>( - m_set_sys, "time", "standard_network_clock_sufficient_accuracy_minutes")}; + s32 network_accuracy_m{}; + m_set_sys->GetSettingsItemValueImpl<s32>(network_accuracy_m, "time", + "standard_network_clock_sufficient_accuracy_minutes"); auto one_minute_ns{ std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()}; s64 network_accuracy_ns{network_accuracy_m * one_minute_ns}; @@ -153,12 +143,12 @@ TimeManager::TimeManager(Core::System& system) ASSERT(res == ResultSuccess); bool is_automatic_correction_enabled{}; - res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(is_automatic_correction_enabled); + res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(&is_automatic_correction_enabled); ASSERT(res == ResultSuccess); Service::PSC::Time::SteadyClockTimePoint automatic_correction_time_point{}; res = m_set_sys->GetUserSystemClockAutomaticCorrectionUpdatedTime( - automatic_correction_time_point); + &automatic_correction_time_point); ASSERT(res == ResultSuccess); res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled, @@ -196,13 +186,17 @@ TimeManager::TimeManager(Core::System& system) } } +TimeManager::~TimeManager() { + ResetTimeZoneBinary(); +} + Result TimeManager::SetupStandardSteadyClockCore() { Common::UUID external_clock_source_id{}; - auto res = m_set_sys->GetExternalSteadyClockSourceId(external_clock_source_id); + auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id); ASSERT(res == ResultSuccess); s64 external_steady_clock_internal_offset_s{}; - res = m_set_sys->GetExternalSteadyClockInternalOffset(external_steady_clock_internal_offset_s); + res = m_set_sys->GetExternalSteadyClockInternalOffset(&external_steady_clock_internal_offset_s); ASSERT(res == ResultSuccess); auto one_second_ns{ @@ -210,8 +204,9 @@ Result TimeManager::SetupStandardSteadyClockCore() { s64 external_steady_clock_internal_offset_ns{external_steady_clock_internal_offset_s * one_second_ns}; - s32 standard_steady_clock_test_offset_m{ - GetSettingsItemValue<s32>(m_set_sys, "time", "standard_steady_clock_test_offset_minutes")}; + s32 standard_steady_clock_test_offset_m{}; + m_set_sys->GetSettingsItemValueImpl<s32>(standard_steady_clock_test_offset_m, "time", + "standard_steady_clock_test_offset_minutes"); auto one_minute_ns{ std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()}; s64 standard_steady_clock_test_offset_ns{standard_steady_clock_test_offset_m * one_minute_ns}; @@ -237,7 +232,7 @@ Result TimeManager::SetupStandardSteadyClockCore() { Result TimeManager::SetupTimeZoneServiceCore() { Service::PSC::Time::LocationName name{}; - auto res = m_set_sys->GetDeviceTimeZoneLocationName(name); + auto res = m_set_sys->GetDeviceTimeZoneLocationName(&name); ASSERT(res == ResultSuccess); auto configured_zone = GetTimeZoneString(name); @@ -255,7 +250,7 @@ Result TimeManager::SetupTimeZoneServiceCore() { } Service::PSC::Time::SteadyClockTimePoint time_point{}; - res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(time_point); + res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(&time_point); ASSERT(res == ResultSuccess); auto location_count = GetTimeZoneCount(); diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h index 1de93f8f9..bb4b65049 100644 --- a/src/core/hle/service/glue/time/manager.h +++ b/src/core/hle/service/glue/time/manager.h @@ -26,6 +26,7 @@ namespace Service::Glue::Time { class TimeManager { public: explicit TimeManager(Core::System& system); + ~TimeManager(); std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp index f8c1218f3..b801faef2 100644 --- a/src/core/hle/service/glue/time/static.cpp +++ b/src/core/hle/service/glue/time/static.cpp @@ -20,19 +20,6 @@ #include "core/hle/service/sm/sm.h" namespace Service::Glue::Time { -namespace { -template <typename T> -T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, - const char* category, const char* name) { - std::vector<u8> interval_buf; - auto res = set_sys->GetSettingsItemValue(interval_buf, category, name); - ASSERT(res == ResultSuccess); - - T v{}; - std::memcpy(&v, interval_buf.data(), sizeof(T)); - return v; -} -} // namespace StaticService::StaticService(Core::System& system_, Service::PSC::Time::StaticServiceSetupInfo setup_info, @@ -155,16 +142,18 @@ Result StaticService::SetStandardSteadyClockInternalOffset(s64 offset_ns) { } Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); + }; R_RETURN(m_standard_steady_clock_resource.GetRtcTimeInSeconds(*out_rtc_value)); } Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( Out<bool> out_automatic_correction) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. out_automatic_correction={}", *out_automatic_correction); - }); + }; R_RETURN(m_wrapped_service->IsStandardUserSystemClockAutomaticCorrectionEnabled( out_automatic_correction)); @@ -179,21 +168,27 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( } Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); + }; - *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); - R_SUCCEED(); + R_RETURN(m_set_sys->GetSettingsItemValueImpl<s32>(*out_year, "time", + "standard_user_clock_initial_year")); } Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); + }; R_RETURN(m_wrapped_service->IsStandardNetworkSystemClockAccuracySufficient(out_is_sufficient)); } Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); + }; R_RETURN(m_wrapped_service->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( out_time_point)); @@ -201,15 +196,18 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( Out<s64> out_time, const Service::PSC::Time::SystemClockContext& context) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); + }; R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context)); } Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type) { - SCOPE_EXIT( - { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); + }; R_RETURN(m_wrapped_service->GetClockSnapshot(out_snapshot, type)); } @@ -218,11 +216,11 @@ Result StaticService::GetClockSnapshotFromSystemClockContext( Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, const Service::PSC::Time::SystemClockContext& user_context, const Service::PSC::Time::SystemClockContext& network_context) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={} user_context={} network_context={}", type, *out_snapshot, user_context, network_context); - }); + }; R_RETURN(m_wrapped_service->GetClockSnapshotFromSystemClockContext( type, out_snapshot, user_context, network_context)); @@ -231,14 +229,18 @@ Result StaticService::GetClockSnapshotFromSystemClockContext( Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); + }; R_RETURN(m_wrapped_service->CalculateStandardUserSystemClockDifferenceByUser(out_time, a, b)); } Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); + }; R_RETURN(m_wrapped_service->CalculateSpanBetween(out_time, a, b)); } diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 36f163419..f4d0c87d5 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -57,7 +57,9 @@ TimeZoneService::~TimeZoneService() = default; Result TimeZoneService::GetDeviceLocationName( Out<Service::PSC::Time::LocationName> out_location_name) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); + }; R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name)); } @@ -94,7 +96,9 @@ Result TimeZoneService::SetDeviceLocationName( } Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); + }; R_RETURN(m_wrapped_service->GetTotalLocationNameCount(out_count)); } @@ -102,10 +106,10 @@ Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { Result TimeZoneService::LoadLocationNameList( Out<u32> out_count, OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}", index, *out_count, out_names[0], out_names[1]); - }); + }; std::scoped_lock l{m_mutex}; R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index)); @@ -124,7 +128,9 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Result TimeZoneService::GetTimeZoneRuleVersion( Out<Service::PSC::Time::RuleVersion> out_rule_version) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); + }; R_RETURN(m_wrapped_service->GetTimeZoneRuleVersion(out_rule_version)); } @@ -132,10 +138,10 @@ Result TimeZoneService::GetTimeZoneRuleVersion( Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( Out<Service::PSC::Time::LocationName> location_name, Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. location_name={} out_time_point={}", *location_name, *out_time_point); - }); + }; R_RETURN(m_wrapped_service->GetDeviceLocationNameAndUpdatedTime(location_name, out_time_point)); } @@ -178,10 +184,10 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( Result TimeZoneService::ToCalendarTime( Out<Service::PSC::Time::CalendarTime> out_calendar_time, Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, *out_calendar_time, *out_additional_info); - }); + }; R_RETURN(m_wrapped_service->ToCalendarTime(out_calendar_time, out_additional_info, time, rule)); } @@ -189,10 +195,10 @@ Result TimeZoneService::ToCalendarTime( Result TimeZoneService::ToCalendarTimeWithMyRule( Out<Service::PSC::Time::CalendarTime> out_calendar_time, Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, *out_calendar_time, *out_additional_info); - }); + }; R_RETURN( m_wrapped_service->ToCalendarTimeWithMyRule(out_calendar_time, out_additional_info, time)); @@ -202,11 +208,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, const Service::PSC::Time::CalendarTime& calendar_time, InRule rule) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", calendar_time, *out_count, out_times[0], out_times[1]); - }); + }; R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule)); } @@ -214,11 +220,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count, Result TimeZoneService::ToPosixTimeWithMyRule( Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, const Service::PSC::Time::CalendarTime& calendar_time) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", calendar_time, *out_count, out_times[0], out_times[1]); - }); + }; R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time)); } diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index 8787f2dcd..b28569b68 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp @@ -27,7 +27,7 @@ template <typename T> T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, const char* category, const char* name) { std::vector<u8> interval_buf; - auto res = set_sys->GetSettingsItemValue(interval_buf, category, name); + auto res = set_sys->GetSettingsItemValueImpl(interval_buf, category, name); ASSERT(res == ResultSuccess); T v{}; diff --git a/src/core/hle/service/ldn/lan_discovery.cpp b/src/core/hle/service/ldn/lan_discovery.cpp index 8f3c04550..b9db19618 100644 --- a/src/core/hle/service/ldn/lan_discovery.cpp +++ b/src/core/hle/service/ldn/lan_discovery.cpp @@ -85,15 +85,14 @@ Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network) const { } Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network, - std::vector<NodeLatestUpdate>& out_updates, - std::size_t buffer_count) { - if (buffer_count > NodeCountMax) { + std::span<NodeLatestUpdate> out_updates) { + if (out_updates.size() > NodeCountMax) { return ResultInvalidBufferCount; } if (state == State::AccessPointCreated || state == State::StationConnected) { std::memcpy(&out_network, &network_info, sizeof(network_info)); - for (std::size_t i = 0; i < buffer_count; i++) { + for (std::size_t i = 0; i < out_updates.size(); i++) { out_updates[i].state_change = node_changes[i].state_change; node_changes[i].state_change = NodeStateChange::None; } @@ -107,15 +106,8 @@ DisconnectReason LANDiscovery::GetDisconnectReason() const { return disconnect_reason; } -Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count, +Result LANDiscovery::Scan(std::span<NetworkInfo> out_networks, s16& out_count, const ScanFilter& filter) { - if (!IsFlagSet(filter.flag, ScanFilterFlag::NetworkType) || - filter.network_type <= NetworkType::All) { - if (!IsFlagSet(filter.flag, ScanFilterFlag::Ssid) && filter.ssid.length >= SsidLengthMax) { - return ResultBadInput; - } - } - { std::scoped_lock lock{packet_mutex}; scan_results.clear(); @@ -128,7 +120,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count, std::scoped_lock lock{packet_mutex}; for (const auto& [key, info] : scan_results) { - if (count >= networks.size()) { + if (out_count >= static_cast<s16>(out_networks.size())) { break; } @@ -159,7 +151,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count, } } - networks[count++] = info; + out_networks[out_count++] = info; } return ResultSuccess; diff --git a/src/core/hle/service/ldn/lan_discovery.h b/src/core/hle/service/ldn/lan_discovery.h index 3833cd764..8f7a8dfc4 100644 --- a/src/core/hle/service/ldn/lan_discovery.h +++ b/src/core/hle/service/ldn/lan_discovery.h @@ -54,11 +54,10 @@ public: void SetState(State new_state); Result GetNetworkInfo(NetworkInfo& out_network) const; - Result GetNetworkInfo(NetworkInfo& out_network, std::vector<NodeLatestUpdate>& out_updates, - std::size_t buffer_count); + Result GetNetworkInfo(NetworkInfo& out_network, std::span<NodeLatestUpdate> out_updates); DisconnectReason GetDisconnectReason() const; - Result Scan(std::vector<NetworkInfo>& networks, u16& count, const ScanFilter& filter); + Result Scan(std::span<NetworkInfo> out_networks, s16& out_count, const ScanFilter& filter); Result SetAdvertiseData(std::span<const u8> data); Result OpenAccessPoint(); diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index 961f89a14..f2d638c30 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -1,36 +1,24 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <memory> - #include "core/core.h" -#include "core/hle/service/ldn/lan_discovery.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/ldn/ldn.h" -#include "core/hle/service/ldn/ldn_results.h" -#include "core/hle/service/ldn/ldn_types.h" -#include "core/hle/service/server_manager.h" -#include "core/internal_network/network.h" -#include "core/internal_network/network_interface.h" -#include "network/network.h" - -// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent -#undef CreateEvent +#include "core/hle/service/ldn/monitor_service.h" +#include "core/hle/service/ldn/sf_monitor_service.h" +#include "core/hle/service/ldn/sf_service.h" +#include "core/hle/service/ldn/sf_service_monitor.h" +#include "core/hle/service/ldn/system_local_communication_service.h" +#include "core/hle/service/ldn/user_local_communication_service.h" namespace Service::LDN { -class IMonitorService final : public ServiceFramework<IMonitorService> { +class IMonitorServiceCreator final : public ServiceFramework<IMonitorServiceCreator> { public: - explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} { + explicit IMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:m"} { // clang-format off static const FunctionInfo functions[] = { - {0, &IMonitorService::GetStateForMonitor, "GetStateForMonitor"}, - {1, nullptr, "GetNetworkInfoForMonitor"}, - {2, nullptr, "GetIpv4AddressForMonitor"}, - {3, nullptr, "GetDisconnectReasonForMonitor"}, - {4, nullptr, "GetSecurityParameterForMonitor"}, - {5, nullptr, "GetNetworkConfigForMonitor"}, - {100, &IMonitorService::InitializeMonitor, "InitializeMonitor"}, - {101, nullptr, "FinalizeMonitor"}, + {0, C<&IMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"} }; // clang-format on @@ -38,84 +26,20 @@ public: } private: - void GetStateForMonitor(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); - } - - void InitializeMonitor(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - state = State::Initialized; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - State state{State::None}; -}; - -class LDNM final : public ServiceFramework<LDNM> { -public: - explicit LDNM(Core::System& system_) : ServiceFramework{system_, "ldn:m"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &LDNM::CreateMonitorService, "CreateMonitorService"} - }; - // clang-format on - - RegisterHandlers(functions); - } - - void CreateMonitorService(HLERequestContext& ctx) { + Result CreateMonitorService(OutInterface<IMonitorService> out_interface) { LOG_DEBUG(Service_LDN, "called"); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IMonitorService>(system); + *out_interface = std::make_shared<IMonitorService>(system); + R_SUCCEED(); } }; -class ISystemLocalCommunicationService final - : public ServiceFramework<ISystemLocalCommunicationService> { +class ISystemServiceCreator final : public ServiceFramework<ISystemServiceCreator> { public: - explicit ISystemLocalCommunicationService(Core::System& system_) - : ServiceFramework{system_, "ISystemLocalCommunicationService"} { + explicit ISystemServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:s"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "GetState"}, - {1, nullptr, "GetNetworkInfo"}, - {2, nullptr, "GetIpv4Address"}, - {3, nullptr, "GetDisconnectReason"}, - {4, nullptr, "GetSecurityParameter"}, - {5, nullptr, "GetNetworkConfig"}, - {100, nullptr, "AttachStateChangeEvent"}, - {101, nullptr, "GetNetworkInfoLatestUpdate"}, - {102, nullptr, "Scan"}, - {103, nullptr, "ScanPrivate"}, - {104, nullptr, "SetWirelessControllerRestriction"}, - {200, nullptr, "OpenAccessPoint"}, - {201, nullptr, "CloseAccessPoint"}, - {202, nullptr, "CreateNetwork"}, - {203, nullptr, "CreateNetworkPrivate"}, - {204, nullptr, "DestroyNetwork"}, - {205, nullptr, "Reject"}, - {206, nullptr, "SetAdvertiseData"}, - {207, nullptr, "SetStationAcceptPolicy"}, - {208, nullptr, "AddAcceptFilterEntry"}, - {209, nullptr, "ClearAcceptFilter"}, - {300, nullptr, "OpenStation"}, - {301, nullptr, "CloseStation"}, - {302, nullptr, "Connect"}, - {303, nullptr, "ConnectPrivate"}, - {304, nullptr, "Disconnect"}, - {400, nullptr, "InitializeSystem"}, - {401, nullptr, "FinalizeSystem"}, - {402, nullptr, "SetOperationMode"}, - {403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"}, + {0, C<&ISystemServiceCreator::CreateSystemLocalCommunicationService>, "CreateSystemLocalCommunicationService"}, }; // clang-format on @@ -123,687 +47,78 @@ public: } private: - void InitializeSystem2(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } -}; - -class IUserLocalCommunicationService final - : public ServiceFramework<IUserLocalCommunicationService> { -public: - explicit IUserLocalCommunicationService(Core::System& system_) - : ServiceFramework{system_, "IUserLocalCommunicationService"}, - service_context{system, "IUserLocalCommunicationService"}, - room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IUserLocalCommunicationService::GetState, "GetState"}, - {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"}, - {2, &IUserLocalCommunicationService::GetIpv4Address, "GetIpv4Address"}, - {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"}, - {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"}, - {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"}, - {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"}, - {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"}, - {102, &IUserLocalCommunicationService::Scan, "Scan"}, - {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"}, - {104, &IUserLocalCommunicationService::SetWirelessControllerRestriction, "SetWirelessControllerRestriction"}, - {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"}, - {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"}, - {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"}, - {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"}, - {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"}, - {205, nullptr, "Reject"}, - {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"}, - {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"}, - {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"}, - {209, nullptr, "ClearAcceptFilter"}, - {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"}, - {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"}, - {302, &IUserLocalCommunicationService::Connect, "Connect"}, - {303, nullptr, "ConnectPrivate"}, - {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"}, - {400, &IUserLocalCommunicationService::Initialize, "Initialize"}, - {401, &IUserLocalCommunicationService::Finalize, "Finalize"}, - {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"}, - }; - // clang-format on - - RegisterHandlers(functions); - - state_change_event = - service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent"); - } - - ~IUserLocalCommunicationService() { - if (is_initialized) { - if (auto room_member = room_network.GetRoomMember().lock()) { - room_member->Unbind(ldn_packet_received); - } - } - - service_context.CloseEvent(state_change_event); - } - - /// Callback to parse and handle a received LDN packet. - void OnLDNPacketReceived(const Network::LDNPacket& packet) { - lan_discovery.ReceivePacket(packet); - } - - void OnEventFired() { - state_change_event->Signal(); - } - - void GetState(HLERequestContext& ctx) { - State state = State::Error; - - if (is_initialized) { - state = lan_discovery.GetState(); - } - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(state); - } - - void GetNetworkInfo(HLERequestContext& ctx) { - const auto write_buffer_size = ctx.GetWriteBufferSize(); - - if (write_buffer_size != sizeof(NetworkInfo)) { - LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultBadInput); - return; - } - - NetworkInfo network_info{}; - const auto rc = lan_discovery.GetNetworkInfo(network_info); - if (rc.IsError()) { - LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - return; - } - - ctx.WriteBuffer<NetworkInfo>(network_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetIpv4Address(HLERequestContext& ctx) { - const auto network_interface = Network::GetSelectedNetworkInterface(); - - if (!network_interface) { - LOG_ERROR(Service_LDN, "No network interface available"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNoIpAddress); - return; - } - - Ipv4Address current_address{Network::TranslateIPv4(network_interface->ip_address)}; - Ipv4Address subnet_mask{Network::TranslateIPv4(network_interface->subnet_mask)}; - - // When we're connected to a room, spoof the hosts IP address - if (auto room_member = room_network.GetRoomMember().lock()) { - if (room_member->IsConnected()) { - current_address = room_member->GetFakeIpAddress(); - } - } - - std::reverse(std::begin(current_address), std::end(current_address)); // ntohl - std::reverse(std::begin(subnet_mask), std::end(subnet_mask)); // ntohl - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushRaw(current_address); - rb.PushRaw(subnet_mask); - } - - void GetDisconnectReason(HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(lan_discovery.GetDisconnectReason()); - } - - void GetSecurityParameter(HLERequestContext& ctx) { - SecurityParameter security_parameter{}; - NetworkInfo info{}; - const Result rc = lan_discovery.GetNetworkInfo(info); - - if (rc.IsError()) { - LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - return; - } - - security_parameter.session_id = info.network_id.session_id; - std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(), - sizeof(SecurityParameter::data)); - - IPC::ResponseBuilder rb{ctx, 10}; - rb.Push(rc); - rb.PushRaw<SecurityParameter>(security_parameter); - } - - void GetNetworkConfig(HLERequestContext& ctx) { - NetworkConfig config{}; - NetworkInfo info{}; - const Result rc = lan_discovery.GetNetworkInfo(info); - - if (rc.IsError()) { - LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - return; - } - - config.intent_id = info.network_id.intent_id; - config.channel = info.common.channel; - config.node_count_max = info.ldn.node_count_max; - config.local_communication_version = info.ldn.nodes[0].local_communication_version; - - IPC::ResponseBuilder rb{ctx, 10}; - rb.Push(rc); - rb.PushRaw<NetworkConfig>(config); - } - - void AttachStateChangeEvent(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(state_change_event->GetReadableEvent()); - } - - void GetNetworkInfoLatestUpdate(HLERequestContext& ctx) { - const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0); - const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1); - - if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) { - LOG_ERROR(Service_LDN, "Invalid buffer, size = {}, count = {}", network_buffer_size, - node_buffer_count); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultBadInput); - return; - } - - NetworkInfo info{}; - std::vector<NodeLatestUpdate> latest_update(node_buffer_count); - - const auto rc = lan_discovery.GetNetworkInfo(info, latest_update, latest_update.size()); - if (rc.IsError()) { - LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - return; - } - - ctx.WriteBuffer(info, 0); - ctx.WriteBuffer(latest_update, 1); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void Scan(HLERequestContext& ctx) { - ScanImpl(ctx); - } - - void ScanPrivate(HLERequestContext& ctx) { - ScanImpl(ctx, true); - } - - void ScanImpl(HLERequestContext& ctx, bool is_private = false) { - IPC::RequestParser rp{ctx}; - const auto channel{rp.PopEnum<WifiChannel>()}; - const auto scan_filter{rp.PopRaw<ScanFilter>()}; - - const std::size_t network_info_size = ctx.GetWriteBufferNumElements<NetworkInfo>(); - - if (network_info_size == 0) { - LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultBadInput); - return; - } - - u16 count = 0; - std::vector<NetworkInfo> network_infos(network_info_size); - Result rc = lan_discovery.Scan(network_infos, count, scan_filter); - - LOG_INFO(Service_LDN, - "called, channel={}, filter_scan_flag={}, filter_network_type={}, is_private={}", - channel, scan_filter.flag, scan_filter.network_type, is_private); - - ctx.WriteBuffer(network_infos); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(rc); - rb.Push<u32>(count); - } - - void SetWirelessControllerRestriction(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void OpenAccessPoint(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.OpenAccessPoint()); - } - - void CloseAccessPoint(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.CloseAccessPoint()); - } - - void CreateNetwork(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - CreateNetworkImpl(ctx); - } - - void CreateNetworkPrivate(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - CreateNetworkImpl(ctx, true); - } - - void CreateNetworkImpl(HLERequestContext& ctx, bool is_private = false) { - IPC::RequestParser rp{ctx}; - - const auto security_config{rp.PopRaw<SecurityConfig>()}; - [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>() - : SecurityParameter{}}; - const auto user_config{rp.PopRaw<UserConfig>()}; - rp.Pop<u32>(); // Padding - const auto network_Config{rp.PopRaw<NetworkConfig>()}; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.CreateNetwork(security_config, user_config, network_Config)); - } - - void DestroyNetwork(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.DestroyNetwork()); - } - - void SetAdvertiseData(HLERequestContext& ctx) { - const auto read_buffer = ctx.ReadBuffer(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.SetAdvertiseData(read_buffer)); - } - - void SetStationAcceptPolicy(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void AddAcceptFilterEntry(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void OpenStation(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.OpenStation()); - } - - void CloseStation(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.CloseStation()); - } - - void Connect(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - struct Parameters { - SecurityConfig security_config; - UserConfig user_config; - u32 local_communication_version; - u32 option; - }; - static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size."); - - const auto parameters{rp.PopRaw<Parameters>()}; - - LOG_INFO(Service_LDN, - "called, passphrase_size={}, security_mode={}, " - "local_communication_version={}", - parameters.security_config.passphrase_size, - parameters.security_config.security_mode, parameters.local_communication_version); - - const auto read_buffer = ctx.ReadBuffer(); - if (read_buffer.size() != sizeof(NetworkInfo)) { - LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultBadInput); - return; - } - - NetworkInfo network_info{}; - std::memcpy(&network_info, read_buffer.data(), read_buffer.size()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.Connect(network_info, parameters.user_config, - static_cast<u16>(parameters.local_communication_version))); - } - - void Disconnect(HLERequestContext& ctx) { - LOG_INFO(Service_LDN, "called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.Disconnect()); - } - - void Initialize(HLERequestContext& ctx) { - const auto rc = InitializeImpl(ctx); - if (rc.IsError()) { - LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - } - - void Finalize(HLERequestContext& ctx) { - if (auto room_member = room_network.GetRoomMember().lock()) { - room_member->Unbind(ldn_packet_received); - } - - is_initialized = false; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(lan_discovery.Finalize()); - } - - void Initialize2(HLERequestContext& ctx) { - const auto rc = InitializeImpl(ctx); - if (rc.IsError()) { - LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - } - - Result InitializeImpl(HLERequestContext& ctx) { - const auto network_interface = Network::GetSelectedNetworkInterface(); - if (!network_interface) { - LOG_ERROR(Service_LDN, "No network interface is set"); - return ResultAirplaneModeEnabled; - } - - if (auto room_member = room_network.GetRoomMember().lock()) { - ldn_packet_received = room_member->BindOnLdnPacketReceived( - [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); }); - } else { - LOG_ERROR(Service_LDN, "Couldn't bind callback!"); - return ResultAirplaneModeEnabled; - } - - lan_discovery.Initialize([&]() { OnEventFired(); }); - is_initialized = true; - return ResultSuccess; - } - - KernelHelpers::ServiceContext service_context; - Kernel::KEvent* state_change_event; - Network::RoomNetwork& room_network; - LANDiscovery lan_discovery; - - // Callback identifier for the OnLDNPacketReceived event. - Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received; - - bool is_initialized{}; -}; - -class LDNS final : public ServiceFramework<LDNS> { -public: - explicit LDNS(Core::System& system_) : ServiceFramework{system_, "ldn:s"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - - void CreateSystemLocalCommunicationService(HLERequestContext& ctx) { + Result CreateSystemLocalCommunicationService( + OutInterface<ISystemLocalCommunicationService> out_interface) { LOG_DEBUG(Service_LDN, "called"); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISystemLocalCommunicationService>(system); + *out_interface = std::make_shared<ISystemLocalCommunicationService>(system); + R_SUCCEED(); } }; -class LDNU final : public ServiceFramework<LDNU> { +class IUserServiceCreator final : public ServiceFramework<IUserServiceCreator> { public: - explicit LDNU(Core::System& system_) : ServiceFramework{system_, "ldn:u"} { + explicit IUserServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:u"} { // clang-format off static const FunctionInfo functions[] = { - {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"}, + {0, C<&IUserServiceCreator::CreateUserLocalCommunicationService>, "CreateUserLocalCommunicationService"}, }; // clang-format on RegisterHandlers(functions); } - void CreateUserLocalCommunicationService(HLERequestContext& ctx) { +private: + Result CreateUserLocalCommunicationService( + OutInterface<IUserLocalCommunicationService> out_interface) { LOG_DEBUG(Service_LDN, "called"); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IUserLocalCommunicationService>(system); + *out_interface = std::make_shared<IUserLocalCommunicationService>(system); + R_SUCCEED(); } }; -class INetworkService final : public ServiceFramework<INetworkService> { +class ISfServiceCreator final : public ServiceFramework<ISfServiceCreator> { public: - explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} { + explicit ISfServiceCreator(Core::System& system_, bool is_system_, const char* name_) + : ServiceFramework{system_, name_}, is_system{is_system_} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, - {264, nullptr, "GetNetworkInterfaceLastError"}, - {272, nullptr, "GetRole"}, - {280, nullptr, "GetAdvertiseData"}, - {288, nullptr, "GetGroupInfo"}, - {296, nullptr, "GetGroupInfo2"}, - {304, nullptr, "GetGroupOwner"}, - {312, nullptr, "GetIpConfig"}, - {320, nullptr, "GetLinkLevel"}, - {512, nullptr, "Scan"}, - {768, nullptr, "CreateGroup"}, - {776, nullptr, "DestroyGroup"}, - {784, nullptr, "SetAdvertiseData"}, - {1536, nullptr, "SendToOtherGroup"}, - {1544, nullptr, "RecvFromOtherGroup"}, - {1552, nullptr, "AddAcceptableGroupId"}, - {1560, nullptr, "ClearAcceptableGroupId"}, + {0, C<&ISfServiceCreator::CreateNetworkService>, "CreateNetworkService"}, + {8, C<&ISfServiceCreator::CreateNetworkServiceMonitor>, "CreateNetworkServiceMonitor"}, }; // clang-format on RegisterHandlers(functions); } -}; - -class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> { -public: - explicit INetworkServiceMonitor(Core::System& system_) - : ServiceFramework{system_, "INetworkServiceMonitor"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &INetworkServiceMonitor::Initialize, "Initialize"}, - {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, - {264, nullptr, "GetNetworkInterfaceLastError"}, - {272, nullptr, "GetRole"}, - {280, nullptr, "GetAdvertiseData"}, - {281, nullptr, "GetAdvertiseData2"}, - {288, nullptr, "GetGroupInfo"}, - {296, nullptr, "GetGroupInfo2"}, - {304, nullptr, "GetGroupOwner"}, - {312, nullptr, "GetIpConfig"}, - {320, nullptr, "GetLinkLevel"}, - {328, nullptr, "AttachJoinEvent"}, - {336, nullptr, "GetMembers"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - - void Initialize(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultDisabled); - } -}; - -class LP2PAPP final : public ServiceFramework<LP2PAPP> { -public: - explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"}, - {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - - void CreateNetworkervice(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 reserved_input = rp.Pop<u64>(); - const u32 input = rp.Pop<u32>(); - - LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input, - input); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<INetworkService>(system); - } - - void CreateMonitorService(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 reserved_input = rp.Pop<u64>(); - - LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<INetworkServiceMonitor>(system); - } -}; - -class LP2PSYS final : public ServiceFramework<LP2PSYS> { -public: - explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"}, - {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - - void CreateNetworkervice(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 reserved_input = rp.Pop<u64>(); - const u32 input = rp.Pop<u32>(); +private: + Result CreateNetworkService(OutInterface<ISfService> out_interface, u32 input, + u64 reserved_input) { LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input, input); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<INetworkService>(system); + *out_interface = std::make_shared<ISfService>(system); + R_SUCCEED(); } - void CreateMonitorService(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 reserved_input = rp.Pop<u64>(); - + Result CreateNetworkServiceMonitor(OutInterface<ISfServiceMonitor> out_interface, + u64 reserved_input) { LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<INetworkServiceMonitor>(system); + *out_interface = std::make_shared<ISfServiceMonitor>(system); + R_SUCCEED(); } -}; -class ISfMonitorService final : public ServiceFramework<ISfMonitorService> { -public: - explicit ISfMonitorService(Core::System& system_) - : ServiceFramework{system_, "ISfMonitorService"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &ISfMonitorService::Initialize, "Initialize"}, - {288, &ISfMonitorService::GetGroupInfo, "GetGroupInfo"}, - {320, nullptr, "GetLinkLevel"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void Initialize(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(0); - } - - void GetGroupInfo(HLERequestContext& ctx) { - LOG_WARNING(Service_LDN, "(STUBBED) called"); - - struct GroupInfo { - std::array<u8, 0x200> info; - }; - - GroupInfo group_info{}; - - ctx.WriteBuffer(group_info); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } + bool is_system{}; }; -class LP2PM final : public ServiceFramework<LP2PM> { +class ISfMonitorServiceCreator final : public ServiceFramework<ISfMonitorServiceCreator> { public: - explicit LP2PM(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} { + explicit ISfMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} { // clang-format off static const FunctionInfo functions[] = { - {0, &LP2PM::CreateMonitorService, "CreateMonitorService"}, + {0, C<&ISfMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"}, }; // clang-format on @@ -811,28 +126,27 @@ public: } private: - void CreateMonitorService(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 reserved_input = rp.Pop<u64>(); - + Result CreateMonitorService(OutInterface<ISfMonitorService> out_interface, u64 reserved_input) { LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISfMonitorService>(system); + *out_interface = std::make_shared<ISfMonitorService>(system); + R_SUCCEED(); } }; void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system)); - server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system)); - server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system)); + server_manager->RegisterNamedService("ldn:m", std::make_shared<IMonitorServiceCreator>(system)); + server_manager->RegisterNamedService("ldn:s", std::make_shared<ISystemServiceCreator>(system)); + server_manager->RegisterNamedService("ldn:u", std::make_shared<IUserServiceCreator>(system)); - server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system)); - server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system)); - server_manager->RegisterNamedService("lp2p:m", std::make_shared<LP2PM>(system)); + server_manager->RegisterNamedService( + "lp2p:app", std::make_shared<ISfServiceCreator>(system, false, "lp2p:app")); + server_manager->RegisterNamedService( + "lp2p:sys", std::make_shared<ISfServiceCreator>(system, true, "lp2p:sys")); + server_manager->RegisterNamedService("lp2p:m", + std::make_shared<ISfMonitorServiceCreator>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h index f4a319168..dae037fa8 100644 --- a/src/core/hle/service/ldn/ldn.h +++ b/src/core/hle/service/ldn/ldn.h @@ -3,12 +3,6 @@ #pragma once -#include "core/hle/kernel/k_event.h" -#include "core/hle/result.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/sm/sm.h" - namespace Core { class System; } diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h index 44c2c773b..6198aa07b 100644 --- a/src/core/hle/service/ldn/ldn_types.h +++ b/src/core/hle/service/ldn/ldn_types.h @@ -123,6 +123,18 @@ enum class NodeStatus : u8 { Connected, }; +enum class WirelessControllerRestriction : u32 { + None, + Default, +}; + +struct ConnectOption { + union { + u32 raw; + }; +}; +static_assert(sizeof(ConnectOption) == 0x4, "ConnectOption is an invalid size"); + struct NodeLatestUpdate { NodeStateChange state_change; INSERT_PADDING_BYTES(0x7); // Unknown @@ -139,9 +151,9 @@ static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size"); struct IntentId { u64 local_communication_id; - INSERT_PADDING_BYTES(0x2); // Reserved + INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved u16 scene_id; - INSERT_PADDING_BYTES(0x4); // Reserved + INSERT_PADDING_BYTES_NOINIT(0x4); // Reserved }; static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size"); @@ -152,13 +164,14 @@ struct NetworkId { static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); struct Ssid { - u8 length{}; - std::array<char, SsidLengthMax + 1> raw{}; + u8 length; + std::array<char, SsidLengthMax + 1> raw; Ssid() = default; constexpr explicit Ssid(std::string_view data) { length = static_cast<u8>(std::min(data.size(), SsidLengthMax)); + raw = {}; data.copy(raw.data(), length); raw[length] = 0; } @@ -181,7 +194,7 @@ using Ipv4Address = std::array<u8, 4>; static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size"); struct MacAddress { - std::array<u8, 6> raw{}; + std::array<u8, 6> raw; friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default; }; @@ -211,7 +224,7 @@ struct CommonNetworkInfo { WifiChannel channel; LinkLevel link_level; PackedNetworkType network_type; - INSERT_PADDING_BYTES(0x4); + INSERT_PADDING_BYTES_NOINIT(0x4); }; static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size"); @@ -221,9 +234,9 @@ struct NodeInfo { s8 node_id; u8 is_connected; std::array<u8, UserNameBytesMax + 1> user_name; - INSERT_PADDING_BYTES(0x1); // Reserved + INSERT_PADDING_BYTES_NOINIT(0x1); // Reserved s16 local_communication_version; - INSERT_PADDING_BYTES(0x10); // Reserved + INSERT_PADDING_BYTES_NOINIT(0x10); // Reserved }; static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size"); @@ -232,14 +245,14 @@ struct LdnNetworkInfo { SecurityMode security_mode; AcceptPolicy station_accept_policy; u8 has_action_frame; - INSERT_PADDING_BYTES(0x2); // Padding + INSERT_PADDING_BYTES_NOINIT(0x2); // Padding u8 node_count_max; u8 node_count; std::array<NodeInfo, NodeCountMax> nodes; - INSERT_PADDING_BYTES(0x2); // Reserved + INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved u16 advertise_data_size; std::array<u8, AdvertiseDataSizeMax> advertise_data; - INSERT_PADDING_BYTES(0x8C); // Reserved + INSERT_PADDING_BYTES_NOINIT(0x8C); // Reserved u64 random_authentication_id; }; static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size"); @@ -250,6 +263,7 @@ struct NetworkInfo { LdnNetworkInfo ldn; }; static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size"); +static_assert(std::is_trivial_v<NetworkInfo>, "NetworkInfo type must be trivially copyable."); struct SecurityConfig { SecurityMode security_mode; @@ -303,4 +317,36 @@ struct AddressList { }; static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size"); +struct GroupInfo { + std::array<u8, 0x200> info; +}; + +struct CreateNetworkConfig { + SecurityConfig security_config; + UserConfig user_config; + INSERT_PADDING_BYTES(0x4); + NetworkConfig network_config; +}; +static_assert(sizeof(CreateNetworkConfig) == 0x98, "CreateNetworkConfig is an invalid size"); + +#pragma pack(push, 4) +struct CreateNetworkConfigPrivate { + SecurityConfig security_config; + SecurityParameter security_parameter; + UserConfig user_config; + INSERT_PADDING_BYTES(0x4); + NetworkConfig network_config; +}; +#pragma pack(pop) +static_assert(sizeof(CreateNetworkConfigPrivate) == 0xB8, + "CreateNetworkConfigPrivate is an invalid size"); + +struct ConnectNetworkData { + SecurityConfig security_config; + UserConfig user_config; + s32 local_communication_version; + ConnectOption option; +}; +static_assert(sizeof(ConnectNetworkData) == 0x7c, "ConnectNetworkData is an invalid size"); + } // namespace Service::LDN diff --git a/src/core/hle/service/ldn/monitor_service.cpp b/src/core/hle/service/ldn/monitor_service.cpp new file mode 100644 index 000000000..3471f69da --- /dev/null +++ b/src/core/hle/service/ldn/monitor_service.cpp @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ldn/monitor_service.h" + +namespace Service::LDN { + +IMonitorService::IMonitorService(Core::System& system_) + : ServiceFramework{system_, "IMonitorService"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IMonitorService::GetStateForMonitor>, "GetStateForMonitor"}, + {1, nullptr, "GetNetworkInfoForMonitor"}, + {2, nullptr, "GetIpv4AddressForMonitor"}, + {3, nullptr, "GetDisconnectReasonForMonitor"}, + {4, nullptr, "GetSecurityParameterForMonitor"}, + {5, nullptr, "GetNetworkConfigForMonitor"}, + {100, C<&IMonitorService::InitializeMonitor>, "InitializeMonitor"}, + {101, nullptr, "FinalizeMonitor"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IMonitorService::~IMonitorService() = default; + +Result IMonitorService::GetStateForMonitor(Out<State> out_state) { + LOG_INFO(Service_LDN, "called"); + + *out_state = state; + R_SUCCEED(); +} + +Result IMonitorService::InitializeMonitor() { + LOG_INFO(Service_LDN, "called"); + + state = State::Initialized; + R_SUCCEED(); +} + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/monitor_service.h b/src/core/hle/service/ldn/monitor_service.h new file mode 100644 index 000000000..61aacef30 --- /dev/null +++ b/src/core/hle/service/ldn/monitor_service.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ldn/ldn_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::LDN { + +class IMonitorService final : public ServiceFramework<IMonitorService> { +public: + explicit IMonitorService(Core::System& system_); + ~IMonitorService() override; + +private: + Result GetStateForMonitor(Out<State> out_state); + Result InitializeMonitor(); + + State state{State::None}; +}; + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/sf_monitor_service.cpp b/src/core/hle/service/ldn/sf_monitor_service.cpp new file mode 100644 index 000000000..9e6736ff2 --- /dev/null +++ b/src/core/hle/service/ldn/sf_monitor_service.cpp @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ldn/ldn_types.h" +#include "core/hle/service/ldn/sf_monitor_service.h" + +namespace Service::LDN { + +ISfMonitorService::ISfMonitorService(Core::System& system_) + : ServiceFramework{system_, "ISfMonitorService"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&ISfMonitorService::Initialize>, "Initialize"}, + {288, C<&ISfMonitorService::GetGroupInfo>, "GetGroupInfo"}, + {320, nullptr, "GetLinkLevel"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISfMonitorService::~ISfMonitorService() = default; + +Result ISfMonitorService::Initialize(Out<u32> out_value) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + + *out_value = 0; + R_SUCCEED(); +} + +Result ISfMonitorService::GetGroupInfo( + OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + + *out_group_info = GroupInfo{}; + R_SUCCEED(); +} + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/sf_monitor_service.h b/src/core/hle/service/ldn/sf_monitor_service.h new file mode 100644 index 000000000..d02115201 --- /dev/null +++ b/src/core/hle/service/ldn/sf_monitor_service.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::LDN { +struct GroupInfo; + +class ISfMonitorService final : public ServiceFramework<ISfMonitorService> { +public: + explicit ISfMonitorService(Core::System& system_); + ~ISfMonitorService() override; + +private: + Result Initialize(Out<u32> out_value); + Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info); +}; + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/sf_service.cpp b/src/core/hle/service/ldn/sf_service.cpp new file mode 100644 index 000000000..61cabe219 --- /dev/null +++ b/src/core/hle/service/ldn/sf_service.cpp @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/ldn/sf_service.h" + +namespace Service::LDN { + +ISfService::ISfService(Core::System& system_) : ServiceFramework{system_, "ISfService"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "Initialize"}, + {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, + {264, nullptr, "GetNetworkInterfaceLastError"}, + {272, nullptr, "GetRole"}, + {280, nullptr, "GetAdvertiseData"}, + {288, nullptr, "GetGroupInfo"}, + {296, nullptr, "GetGroupInfo2"}, + {304, nullptr, "GetGroupOwner"}, + {312, nullptr, "GetIpConfig"}, + {320, nullptr, "GetLinkLevel"}, + {512, nullptr, "Scan"}, + {768, nullptr, "CreateGroup"}, + {776, nullptr, "DestroyGroup"}, + {784, nullptr, "SetAdvertiseData"}, + {1536, nullptr, "SendToOtherGroup"}, + {1544, nullptr, "RecvFromOtherGroup"}, + {1552, nullptr, "AddAcceptableGroupId"}, + {1560, nullptr, "ClearAcceptableGroupId"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISfService::~ISfService() = default; + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/sf_service.h b/src/core/hle/service/ldn/sf_service.h new file mode 100644 index 000000000..05534b567 --- /dev/null +++ b/src/core/hle/service/ldn/sf_service.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::LDN { + +class ISfService final : public ServiceFramework<ISfService> { +public: + explicit ISfService(Core::System& system_); + ~ISfService() override; +}; + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/sf_service_monitor.cpp b/src/core/hle/service/ldn/sf_service_monitor.cpp new file mode 100644 index 000000000..33e3c1d69 --- /dev/null +++ b/src/core/hle/service/ldn/sf_service_monitor.cpp @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ldn/ldn_types.h" +#include "core/hle/service/ldn/sf_service_monitor.h" + +namespace Service::LDN { + +ISfServiceMonitor::ISfServiceMonitor(Core::System& system_) + : ServiceFramework{system_, "ISfServiceMonitor"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&ISfServiceMonitor::Initialize>, "Initialize"}, + {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, + {264, nullptr, "GetNetworkInterfaceLastError"}, + {272, nullptr, "GetRole"}, + {280, nullptr, "GetAdvertiseData"}, + {281, nullptr, "GetAdvertiseData2"}, + {288, C<&ISfServiceMonitor::GetGroupInfo>, "GetGroupInfo"}, + {296, nullptr, "GetGroupInfo2"}, + {304, nullptr, "GetGroupOwner"}, + {312, nullptr, "GetIpConfig"}, + {320, nullptr, "GetLinkLevel"}, + {328, nullptr, "AttachJoinEvent"}, + {336, nullptr, "GetMembers"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISfServiceMonitor::~ISfServiceMonitor() = default; + +Result ISfServiceMonitor::Initialize(Out<u32> out_value) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + + *out_value = 0; + R_SUCCEED(); +} + +Result ISfServiceMonitor::GetGroupInfo( + OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + + *out_group_info = GroupInfo{}; + R_SUCCEED(); +} + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/sf_service_monitor.h b/src/core/hle/service/ldn/sf_service_monitor.h new file mode 100644 index 000000000..3cfc5005e --- /dev/null +++ b/src/core/hle/service/ldn/sf_service_monitor.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::LDN { +struct GroupInfo; + +class ISfServiceMonitor final : public ServiceFramework<ISfServiceMonitor> { +public: + explicit ISfServiceMonitor(Core::System& system_); + ~ISfServiceMonitor() override; + +private: + Result Initialize(Out<u32> out_value); + Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info); +}; + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/system_local_communication_service.cpp b/src/core/hle/service/ldn/system_local_communication_service.cpp new file mode 100644 index 000000000..7b52223cd --- /dev/null +++ b/src/core/hle/service/ldn/system_local_communication_service.cpp @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ldn/system_local_communication_service.h" + +namespace Service::LDN { + +ISystemLocalCommunicationService::ISystemLocalCommunicationService(Core::System& system_) + : ServiceFramework{system_, "ISystemLocalCommunicationService"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetState"}, + {1, nullptr, "GetNetworkInfo"}, + {2, nullptr, "GetIpv4Address"}, + {3, nullptr, "GetDisconnectReason"}, + {4, nullptr, "GetSecurityParameter"}, + {5, nullptr, "GetNetworkConfig"}, + {100, nullptr, "AttachStateChangeEvent"}, + {101, nullptr, "GetNetworkInfoLatestUpdate"}, + {102, nullptr, "Scan"}, + {103, nullptr, "ScanPrivate"}, + {104, nullptr, "SetWirelessControllerRestriction"}, + {200, nullptr, "OpenAccessPoint"}, + {201, nullptr, "CloseAccessPoint"}, + {202, nullptr, "CreateNetwork"}, + {203, nullptr, "CreateNetworkPrivate"}, + {204, nullptr, "DestroyNetwork"}, + {205, nullptr, "Reject"}, + {206, nullptr, "SetAdvertiseData"}, + {207, nullptr, "SetStationAcceptPolicy"}, + {208, nullptr, "AddAcceptFilterEntry"}, + {209, nullptr, "ClearAcceptFilter"}, + {300, nullptr, "OpenStation"}, + {301, nullptr, "CloseStation"}, + {302, nullptr, "Connect"}, + {303, nullptr, "ConnectPrivate"}, + {304, nullptr, "Disconnect"}, + {400, nullptr, "InitializeSystem"}, + {401, nullptr, "FinalizeSystem"}, + {402, nullptr, "SetOperationMode"}, + {403, C<&ISystemLocalCommunicationService::InitializeSystem2>, "InitializeSystem2"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISystemLocalCommunicationService::~ISystemLocalCommunicationService() = default; + +Result ISystemLocalCommunicationService::InitializeSystem2() { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + R_SUCCEED(); +} + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/system_local_communication_service.h b/src/core/hle/service/ldn/system_local_communication_service.h new file mode 100644 index 000000000..a02b097ea --- /dev/null +++ b/src/core/hle/service/ldn/system_local_communication_service.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::LDN { + +class ISystemLocalCommunicationService final + : public ServiceFramework<ISystemLocalCommunicationService> { +public: + explicit ISystemLocalCommunicationService(Core::System& system_); + ~ISystemLocalCommunicationService() override; + +private: + Result InitializeSystem2(); +}; + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp new file mode 100644 index 000000000..f28368962 --- /dev/null +++ b/src/core/hle/service/ldn/user_local_communication_service.cpp @@ -0,0 +1,320 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <memory> + +#include "core/core.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ldn/ldn_results.h" +#include "core/hle/service/ldn/ldn_types.h" +#include "core/hle/service/ldn/user_local_communication_service.h" +#include "core/hle/service/server_manager.h" +#include "core/internal_network/network.h" +#include "core/internal_network/network_interface.h" +#include "network/network.h" + +// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent +#undef CreateEvent + +namespace Service::LDN { + +IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_) + : ServiceFramework{system_, "IUserLocalCommunicationService"}, + service_context{system, "IUserLocalCommunicationService"}, + room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IUserLocalCommunicationService::GetState>, "GetState"}, + {1, C<&IUserLocalCommunicationService::GetNetworkInfo>, "GetNetworkInfo"}, + {2, C<&IUserLocalCommunicationService::GetIpv4Address>, "GetIpv4Address"}, + {3, C<&IUserLocalCommunicationService::GetDisconnectReason>, "GetDisconnectReason"}, + {4, C<&IUserLocalCommunicationService::GetSecurityParameter>, "GetSecurityParameter"}, + {5, C<&IUserLocalCommunicationService::GetNetworkConfig>, "GetNetworkConfig"}, + {100, C<&IUserLocalCommunicationService::AttachStateChangeEvent>, "AttachStateChangeEvent"}, + {101, C<&IUserLocalCommunicationService::GetNetworkInfoLatestUpdate>, "GetNetworkInfoLatestUpdate"}, + {102, C<&IUserLocalCommunicationService::Scan>, "Scan"}, + {103, C<&IUserLocalCommunicationService::ScanPrivate>, "ScanPrivate"}, + {104, C<&IUserLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"}, + {200, C<&IUserLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"}, + {201, C<&IUserLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"}, + {202, C<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"}, + {203, C<&IUserLocalCommunicationService::CreateNetworkPrivate>, "CreateNetworkPrivate"}, + {204, C<&IUserLocalCommunicationService::DestroyNetwork>, "DestroyNetwork"}, + {205, nullptr, "Reject"}, + {206, C<&IUserLocalCommunicationService::SetAdvertiseData>, "SetAdvertiseData"}, + {207, C<&IUserLocalCommunicationService::SetStationAcceptPolicy>, "SetStationAcceptPolicy"}, + {208, C<&IUserLocalCommunicationService::AddAcceptFilterEntry>, "AddAcceptFilterEntry"}, + {209, nullptr, "ClearAcceptFilter"}, + {300, C<&IUserLocalCommunicationService::OpenStation>, "OpenStation"}, + {301, C<&IUserLocalCommunicationService::CloseStation>, "CloseStation"}, + {302, C<&IUserLocalCommunicationService::Connect>, "Connect"}, + {303, nullptr, "ConnectPrivate"}, + {304, C<&IUserLocalCommunicationService::Disconnect>, "Disconnect"}, + {400, C<&IUserLocalCommunicationService::Initialize>, "Initialize"}, + {401, C<&IUserLocalCommunicationService::Finalize>, "Finalize"}, + {402, C<&IUserLocalCommunicationService::Initialize2>, "Initialize2"}, + }; + // clang-format on + + RegisterHandlers(functions); + + state_change_event = + service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent"); +} + +IUserLocalCommunicationService::~IUserLocalCommunicationService() { + if (is_initialized) { + if (auto room_member = room_network.GetRoomMember().lock()) { + room_member->Unbind(ldn_packet_received); + } + } + + service_context.CloseEvent(state_change_event); +} + +Result IUserLocalCommunicationService::GetState(Out<State> out_state) { + *out_state = State::Error; + + if (is_initialized) { + *out_state = lan_discovery.GetState(); + } + + LOG_INFO(Service_LDN, "called, state={}", *out_state); + + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::GetNetworkInfo( + OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info) { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info)); +} + +Result IUserLocalCommunicationService::GetIpv4Address(Out<Ipv4Address> out_current_address, + Out<Ipv4Address> out_subnet_mask) { + LOG_INFO(Service_LDN, "called"); + const auto network_interface = Network::GetSelectedNetworkInterface(); + + R_UNLESS(network_interface.has_value(), ResultNoIpAddress); + + *out_current_address = {Network::TranslateIPv4(network_interface->ip_address)}; + *out_subnet_mask = {Network::TranslateIPv4(network_interface->subnet_mask)}; + + // When we're connected to a room, spoof the hosts IP address + if (auto room_member = room_network.GetRoomMember().lock()) { + if (room_member->IsConnected()) { + *out_current_address = room_member->GetFakeIpAddress(); + } + } + + std::reverse(std::begin(*out_current_address), std::end(*out_current_address)); // ntohl + std::reverse(std::begin(*out_subnet_mask), std::end(*out_subnet_mask)); // ntohl + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::GetDisconnectReason( + Out<DisconnectReason> out_disconnect_reason) { + LOG_INFO(Service_LDN, "called"); + + *out_disconnect_reason = lan_discovery.GetDisconnectReason(); + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::GetSecurityParameter( + Out<SecurityParameter> out_security_parameter) { + LOG_INFO(Service_LDN, "called"); + + NetworkInfo info{}; + R_TRY(lan_discovery.GetNetworkInfo(info)); + + out_security_parameter->session_id = info.network_id.session_id; + std::memcpy(out_security_parameter->data.data(), info.ldn.security_parameter.data(), + sizeof(SecurityParameter::data)); + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::GetNetworkConfig(Out<NetworkConfig> out_network_config) { + LOG_INFO(Service_LDN, "called"); + + NetworkInfo info{}; + R_TRY(lan_discovery.GetNetworkInfo(info)); + + out_network_config->intent_id = info.network_id.intent_id; + out_network_config->channel = info.common.channel; + out_network_config->node_count_max = info.ldn.node_count_max; + out_network_config->local_communication_version = info.ldn.nodes[0].local_communication_version; + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::AttachStateChangeEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_INFO(Service_LDN, "called"); + + *out_event = &state_change_event->GetReadableEvent(); + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::GetNetworkInfoLatestUpdate( + OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info, + OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update) { + LOG_INFO(Service_LDN, "called"); + + R_UNLESS(!out_node_latest_update.empty(), ResultBadInput); + + R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info, out_node_latest_update)); +} + +Result IUserLocalCommunicationService::Scan( + Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter, + OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) { + LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}", + channel, scan_filter.flag, scan_filter.network_type); + + R_UNLESS(!out_network_info.empty(), ResultBadInput); + R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter)); +} + +Result IUserLocalCommunicationService::ScanPrivate( + Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter, + OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) { + LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}", + channel, scan_filter.flag, scan_filter.network_type); + + R_UNLESS(out_network_info.empty(), ResultBadInput); + R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter)); +} + +Result IUserLocalCommunicationService::SetWirelessControllerRestriction( + WirelessControllerRestriction wireless_restriction) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::OpenAccessPoint() { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.OpenAccessPoint()); +} + +Result IUserLocalCommunicationService::CloseAccessPoint() { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.CloseAccessPoint()); +} + +Result IUserLocalCommunicationService::CreateNetwork(const CreateNetworkConfig& create_config) { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config, + create_config.network_config)); +} + +Result IUserLocalCommunicationService::CreateNetworkPrivate( + const CreateNetworkConfigPrivate& create_config, + InArray<AddressEntry, BufferAttr_HipcPointer> address_list) { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config, + create_config.network_config)); +} + +Result IUserLocalCommunicationService::DestroyNetwork() { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.DestroyNetwork()); +} + +Result IUserLocalCommunicationService::SetAdvertiseData( + InBuffer<BufferAttr_HipcAutoSelect> buffer_data) { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.SetAdvertiseData(buffer_data)); +} + +Result IUserLocalCommunicationService::SetStationAcceptPolicy(AcceptPolicy accept_policy) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::AddAcceptFilterEntry(MacAddress mac_address) { + LOG_WARNING(Service_LDN, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::OpenStation() { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.OpenStation()); +} + +Result IUserLocalCommunicationService::CloseStation() { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.CloseStation()); +} + +Result IUserLocalCommunicationService::Connect( + const ConnectNetworkData& connect_data, + InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info) { + LOG_INFO(Service_LDN, + "called, passphrase_size={}, security_mode={}, " + "local_communication_version={}", + connect_data.security_config.passphrase_size, + connect_data.security_config.security_mode, connect_data.local_communication_version); + + R_RETURN(lan_discovery.Connect(*network_info, connect_data.user_config, + static_cast<u16>(connect_data.local_communication_version))); +} + +Result IUserLocalCommunicationService::Disconnect() { + LOG_INFO(Service_LDN, "called"); + + R_RETURN(lan_discovery.Disconnect()); +} + +Result IUserLocalCommunicationService::Initialize(ClientProcessId aruid) { + LOG_INFO(Service_LDN, "called, process_id={}", aruid.pid); + + const auto network_interface = Network::GetSelectedNetworkInterface(); + R_UNLESS(network_interface, ResultAirplaneModeEnabled); + + if (auto room_member = room_network.GetRoomMember().lock()) { + ldn_packet_received = room_member->BindOnLdnPacketReceived( + [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); }); + } else { + LOG_ERROR(Service_LDN, "Couldn't bind callback!"); + R_RETURN(ResultAirplaneModeEnabled); + } + + lan_discovery.Initialize([&]() { OnEventFired(); }); + is_initialized = true; + R_SUCCEED(); +} + +Result IUserLocalCommunicationService::Finalize() { + LOG_INFO(Service_LDN, "called"); + if (auto room_member = room_network.GetRoomMember().lock()) { + room_member->Unbind(ldn_packet_received); + } + + is_initialized = false; + + R_RETURN(lan_discovery.Finalize()); +} + +Result IUserLocalCommunicationService::Initialize2(u32 version, ClientProcessId process_id) { + LOG_INFO(Service_LDN, "called, version={}, process_id={}", version, process_id.pid); + R_RETURN(Initialize(process_id)); +} + +void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacket& packet) { + lan_discovery.ReceivePacket(packet); +} + +void IUserLocalCommunicationService::OnEventFired() { + state_change_event->Signal(); +} + +} // namespace Service::LDN diff --git a/src/core/hle/service/ldn/user_local_communication_service.h b/src/core/hle/service/ldn/user_local_communication_service.h new file mode 100644 index 000000000..6698d10d2 --- /dev/null +++ b/src/core/hle/service/ldn/user_local_communication_service.h @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/ldn/lan_discovery.h" +#include "core/hle/service/ldn/ldn_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Network { +class RoomNetwork; +} + +namespace Service::LDN { + +class IUserLocalCommunicationService final + : public ServiceFramework<IUserLocalCommunicationService> { +public: + explicit IUserLocalCommunicationService(Core::System& system_); + ~IUserLocalCommunicationService() override; + +private: + Result GetState(Out<State> out_state); + + Result GetNetworkInfo(OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info); + + Result GetIpv4Address(Out<Ipv4Address> out_current_address, Out<Ipv4Address> out_subnet_mask); + + Result GetDisconnectReason(Out<DisconnectReason> out_disconnect_reason); + + Result GetSecurityParameter(Out<SecurityParameter> out_security_parameter); + + Result GetNetworkConfig(Out<NetworkConfig> out_network_config); + + Result AttachStateChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + + Result GetNetworkInfoLatestUpdate( + OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info, + OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update); + + Result Scan(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter, + OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info); + + Result ScanPrivate(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter, + OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info); + + Result SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction); + + Result OpenAccessPoint(); + + Result CloseAccessPoint(); + + Result CreateNetwork(const CreateNetworkConfig& create_network_Config); + + Result CreateNetworkPrivate(const CreateNetworkConfigPrivate& create_network_Config, + InArray<AddressEntry, BufferAttr_HipcPointer> address_list); + + Result DestroyNetwork(); + + Result SetAdvertiseData(InBuffer<BufferAttr_HipcAutoSelect> buffer_data); + + Result SetStationAcceptPolicy(AcceptPolicy accept_policy); + + Result AddAcceptFilterEntry(MacAddress mac_address); + + Result OpenStation(); + + Result CloseStation(); + + Result Connect(const ConnectNetworkData& connect_data, + InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info); + + Result Disconnect(); + + Result Initialize(ClientProcessId aruid); + + Result Finalize(); + + Result Initialize2(u32 version, ClientProcessId aruid); + +private: + /// Callback to parse and handle a received LDN packet. + void OnLDNPacketReceived(const Network::LDNPacket& packet); + void OnEventFired(); + + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* state_change_event; + Network::RoomNetwork& room_network; + LANDiscovery lan_discovery; + + // Callback identifier for the OnLDNPacketReceived event. + Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received; + + bool is_initialized{}; +}; + +} // namespace Service::LDN diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 0086f82c5..adaaea571 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -207,7 +207,8 @@ private: Result DestroyFile() { bool is_db_test_mode_enabled{}; - m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); + m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii", + "is_db_test_mode_enabled"); LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); @@ -217,7 +218,8 @@ private: Result DeleteFile() { bool is_db_test_mode_enabled{}; - m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); + m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii", + "is_db_test_mode_enabled"); LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); @@ -227,7 +229,8 @@ private: Result Format() { bool is_db_test_mode_enabled{}; - m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); + m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii", + "is_db_test_mode_enabled"); LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); diff --git a/src/core/hle/service/ns/account_proxy_interface.cpp b/src/core/hle/service/ns/account_proxy_interface.cpp new file mode 100644 index 000000000..e5041af66 --- /dev/null +++ b/src/core/hle/service/ns/account_proxy_interface.cpp @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/account_proxy_interface.h" + +namespace Service::NS { + +IAccountProxyInterface::IAccountProxyInterface(Core::System& system_) + : ServiceFramework{system_, "IAccountProxyInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "CreateUserAccount"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IAccountProxyInterface::~IAccountProxyInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/account_proxy_interface.h b/src/core/hle/service/ns/account_proxy_interface.h new file mode 100644 index 000000000..e944d2a75 --- /dev/null +++ b/src/core/hle/service/ns/account_proxy_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { +public: + explicit IAccountProxyInterface(Core::System& system_); + ~IAccountProxyInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp new file mode 100644 index 000000000..7a91727f9 --- /dev/null +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -0,0 +1,519 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/file_sys/nca_metadata.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/content_management_interface.h" +#include "core/hle/service/ns/read_only_application_control_data_interface.h" + +namespace Service::NS { + +IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_) + : ServiceFramework{system_, "IApplicationManagerInterface"}, + service_context{system, "IApplicationManagerInterface"}, + record_update_system_event{service_context}, sd_card_mount_status_event{service_context}, + gamecard_update_detection_event{service_context}, + gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IApplicationManagerInterface::ListApplicationRecord>, "ListApplicationRecord"}, + {1, nullptr, "GenerateApplicationRecordCount"}, + {2, D<&IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent>, "GetApplicationRecordUpdateSystemEvent"}, + {3, nullptr, "GetApplicationViewDeprecated"}, + {4, nullptr, "DeleteApplicationEntity"}, + {5, nullptr, "DeleteApplicationCompletely"}, + {6, nullptr, "IsAnyApplicationEntityRedundant"}, + {7, nullptr, "DeleteRedundantApplicationEntity"}, + {8, nullptr, "IsApplicationEntityMovable"}, + {9, nullptr, "MoveApplicationEntity"}, + {11, nullptr, "CalculateApplicationOccupiedSize"}, + {16, nullptr, "PushApplicationRecord"}, + {17, nullptr, "ListApplicationRecordContentMeta"}, + {19, nullptr, "LaunchApplicationOld"}, + {21, nullptr, "GetApplicationContentPath"}, + {22, nullptr, "TerminateApplication"}, + {23, nullptr, "ResolveApplicationContentPath"}, + {26, nullptr, "BeginInstallApplication"}, + {27, nullptr, "DeleteApplicationRecord"}, + {30, nullptr, "RequestApplicationUpdateInfo"}, + {31, nullptr, "Unknown31"}, + {32, nullptr, "CancelApplicationDownload"}, + {33, nullptr, "ResumeApplicationDownload"}, + {35, nullptr, "UpdateVersionList"}, + {36, nullptr, "PushLaunchVersion"}, + {37, nullptr, "ListRequiredVersion"}, + {38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"}, + {39, nullptr, "CheckApplicationLaunchRights"}, + {40, nullptr, "GetApplicationLogoData"}, + {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, + {42, nullptr, "CleanupSdCard"}, + {43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"}, + {44, D<&IApplicationManagerInterface::GetSdCardMountStatusChangedEvent>, "GetSdCardMountStatusChangedEvent"}, + {45, nullptr, "GetGameCardAttachmentEvent"}, + {46, nullptr, "GetGameCardAttachmentInfo"}, + {47, nullptr, "GetTotalSpaceSize"}, + {48, D<&IApplicationManagerInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"}, + {49, nullptr, "GetSdCardRemovedEvent"}, + {52, D<&IApplicationManagerInterface::GetGameCardUpdateDetectionEvent>, "GetGameCardUpdateDetectionEvent"}, + {53, nullptr, "DisableApplicationAutoDelete"}, + {54, nullptr, "EnableApplicationAutoDelete"}, + {55, D<&IApplicationManagerInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"}, + {56, nullptr, "SetApplicationTerminateResult"}, + {57, nullptr, "ClearApplicationTerminateResult"}, + {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, + {59, D<&IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"}, + {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, + {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, + {62, nullptr, "GetGameCardStopper"}, + {63, nullptr, "IsSystemProgramInstalled"}, + {64, nullptr, "StartApplyDeltaTask"}, + {65, nullptr, "GetRequestServerStopper"}, + {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, + {67, nullptr, "CancelApplicationApplyDelta"}, + {68, nullptr, "ResumeApplicationApplyDelta"}, + {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, + {70, D<&IApplicationManagerInterface::ResumeAll>, "ResumeAll"}, + {71, D<&IApplicationManagerInterface::GetStorageSize>, "GetStorageSize"}, + {80, nullptr, "RequestDownloadApplication"}, + {81, nullptr, "RequestDownloadAddOnContent"}, + {82, nullptr, "DownloadApplication"}, + {83, nullptr, "CheckApplicationResumeRights"}, + {84, nullptr, "GetDynamicCommitEvent"}, + {85, nullptr, "RequestUpdateApplication2"}, + {86, nullptr, "EnableApplicationCrashReport"}, + {87, nullptr, "IsApplicationCrashReportEnabled"}, + {90, nullptr, "BoostSystemMemoryResourceLimit"}, + {91, nullptr, "DeprecatedLaunchApplication"}, + {92, nullptr, "GetRunningApplicationProgramId"}, + {93, nullptr, "GetMainApplicationProgramIndex"}, + {94, nullptr, "LaunchApplication"}, + {95, nullptr, "GetApplicationLaunchInfo"}, + {96, nullptr, "AcquireApplicationLaunchInfo"}, + {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"}, + {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, + {99, nullptr, "LaunchDevMenu"}, + {100, nullptr, "ResetToFactorySettings"}, + {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, + {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, + {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, + {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, + {105, nullptr, "RequestResetToFactorySettingsSecurely"}, + {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, + {200, nullptr, "CalculateUserSaveDataStatistics"}, + {201, nullptr, "DeleteUserSaveDataAll"}, + {210, nullptr, "DeleteUserSystemSaveData"}, + {211, nullptr, "DeleteSaveData"}, + {220, nullptr, "UnregisterNetworkServiceAccount"}, + {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, + {300, nullptr, "GetApplicationShellEvent"}, + {301, nullptr, "PopApplicationShellEventInfo"}, + {302, nullptr, "LaunchLibraryApplet"}, + {303, nullptr, "TerminateLibraryApplet"}, + {304, nullptr, "LaunchSystemApplet"}, + {305, nullptr, "TerminateSystemApplet"}, + {306, nullptr, "LaunchOverlayApplet"}, + {307, nullptr, "TerminateOverlayApplet"}, + {400, D<&IApplicationManagerInterface::GetApplicationControlData>, "GetApplicationControlData"}, + {401, nullptr, "InvalidateAllApplicationControlCache"}, + {402, nullptr, "RequestDownloadApplicationControlData"}, + {403, nullptr, "GetMaxApplicationControlCacheCount"}, + {404, nullptr, "InvalidateApplicationControlCache"}, + {405, nullptr, "ListApplicationControlCacheEntryInfo"}, + {406, nullptr, "GetApplicationControlProperty"}, + {407, nullptr, "ListApplicationTitle"}, + {408, nullptr, "ListApplicationIcon"}, + {502, nullptr, "RequestCheckGameCardRegistration"}, + {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, + {504, nullptr, "RequestRegisterGameCard"}, + {505, D<&IApplicationManagerInterface::GetGameCardMountFailureEvent>, "GetGameCardMountFailureEvent"}, + {506, nullptr, "IsGameCardInserted"}, + {507, nullptr, "EnsureGameCardAccess"}, + {508, nullptr, "GetLastGameCardMountFailureResult"}, + {509, nullptr, "ListApplicationIdOnGameCard"}, + {510, nullptr, "GetGameCardPlatformRegion"}, + {600, nullptr, "CountApplicationContentMeta"}, + {601, nullptr, "ListApplicationContentMetaStatus"}, + {602, nullptr, "ListAvailableAddOnContent"}, + {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, + {604, nullptr, "RegisterContentsExternalKey"}, + {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, + {606, nullptr, "GetContentMetaStorage"}, + {607, nullptr, "ListAvailableAddOnContent"}, + {609, nullptr, "ListAvailabilityAssuredAddOnContent"}, + {610, nullptr, "GetInstalledContentMetaStorage"}, + {611, nullptr, "PrepareAddOnContent"}, + {700, nullptr, "PushDownloadTaskList"}, + {701, nullptr, "ClearTaskStatusList"}, + {702, nullptr, "RequestDownloadTaskList"}, + {703, nullptr, "RequestEnsureDownloadTask"}, + {704, nullptr, "ListDownloadTaskStatus"}, + {705, nullptr, "RequestDownloadTaskListData"}, + {800, nullptr, "RequestVersionList"}, + {801, nullptr, "ListVersionList"}, + {802, nullptr, "RequestVersionListData"}, + {900, nullptr, "GetApplicationRecord"}, + {901, nullptr, "GetApplicationRecordProperty"}, + {902, nullptr, "EnableApplicationAutoUpdate"}, + {903, nullptr, "DisableApplicationAutoUpdate"}, + {904, nullptr, "TouchApplication"}, + {905, nullptr, "RequestApplicationUpdate"}, + {906, D<&IApplicationManagerInterface::IsApplicationUpdateRequested>, "IsApplicationUpdateRequested"}, + {907, nullptr, "WithdrawApplicationUpdateRequest"}, + {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, + {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, + {910, nullptr, "HasApplicationRecord"}, + {911, nullptr, "SetPreInstalledApplication"}, + {912, nullptr, "ClearPreInstalledApplicationFlag"}, + {913, nullptr, "ListAllApplicationRecord"}, + {914, nullptr, "HideApplicationRecord"}, + {915, nullptr, "ShowApplicationRecord"}, + {916, nullptr, "IsApplicationAutoDeleteDisabled"}, + {1000, nullptr, "RequestVerifyApplicationDeprecated"}, + {1001, nullptr, "CorruptApplicationForDebug"}, + {1002, nullptr, "RequestVerifyAddOnContentsRights"}, + {1003, nullptr, "RequestVerifyApplication"}, + {1004, nullptr, "CorruptContentForDebug"}, + {1200, nullptr, "NeedsUpdateVulnerability"}, + {1300, D<&IApplicationManagerInterface::IsAnyApplicationEntityInstalled>, "IsAnyApplicationEntityInstalled"}, + {1301, nullptr, "DeleteApplicationContentEntities"}, + {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, + {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, + {1304, nullptr, "DeleteApplicationContentEntity"}, + {1305, nullptr, "TryDeleteRunningApplicationEntity"}, + {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, + {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, + {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, + {1309, nullptr, "CleanupUnavailableAddOnContents"}, + {1310, nullptr, "RequestMoveApplicationEntity"}, + {1311, nullptr, "EstimateSizeToMove"}, + {1312, nullptr, "HasMovableEntity"}, + {1313, nullptr, "CleanupOrphanContents"}, + {1314, nullptr, "CheckPreconditionSatisfiedToMove"}, + {1400, nullptr, "PrepareShutdown"}, + {1500, nullptr, "FormatSdCard"}, + {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, + {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, + {1504, nullptr, "InsertSdCard"}, + {1505, nullptr, "RemoveSdCard"}, + {1506, nullptr, "GetSdCardStartupStatus"}, + {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, + {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, + {1700, nullptr, "ListApplicationDownloadingContentMeta"}, + {1701, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"}, + {1702, nullptr, "GetApplicationDownloadTaskStatus"}, + {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, + {1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"}, + {1705, nullptr, "IsPatchAutoDeletableApplication"}, + {1800, nullptr, "IsNotificationSetupCompleted"}, + {1801, nullptr, "GetLastNotificationInfoCount"}, + {1802, nullptr, "ListLastNotificationInfo"}, + {1803, nullptr, "ListNotificationTask"}, + {1900, nullptr, "IsActiveAccount"}, + {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, + {1902, nullptr, "GetApplicationTicketInfo"}, + {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"}, + {2000, nullptr, "GetSystemDeliveryInfo"}, + {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, + {2002, nullptr, "VerifyDeliveryProtocolVersion"}, + {2003, nullptr, "GetApplicationDeliveryInfo"}, + {2004, nullptr, "HasAllContentsToDeliver"}, + {2005, nullptr, "CompareApplicationDeliveryInfo"}, + {2006, nullptr, "CanDeliverApplication"}, + {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, + {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, + {2009, nullptr, "EstimateRequiredSize"}, + {2010, nullptr, "RequestReceiveApplication"}, + {2011, nullptr, "CommitReceiveApplication"}, + {2012, nullptr, "GetReceiveApplicationProgress"}, + {2013, nullptr, "RequestSendApplication"}, + {2014, nullptr, "GetSendApplicationProgress"}, + {2015, nullptr, "CompareSystemDeliveryInfo"}, + {2016, nullptr, "ListNotCommittedContentMeta"}, + {2017, nullptr, "CreateDownloadTask"}, + {2018, nullptr, "GetApplicationDeliveryInfoHash"}, + {2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"}, + {2051, nullptr, "InvalidateRightsIdCache"}, + {2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"}, + {2101, nullptr, "GetRawApplicationTerminateResult"}, + {2150, nullptr, "CreateRightsEnvironment"}, + {2151, nullptr, "DestroyRightsEnvironment"}, + {2152, nullptr, "ActivateRightsEnvironment"}, + {2153, nullptr, "DeactivateRightsEnvironment"}, + {2154, nullptr, "ForceActivateRightsContextForExit"}, + {2155, nullptr, "UpdateRightsEnvironmentStatus"}, + {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"}, + {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, + {2161, nullptr, "SetUsersToRightsEnvironment"}, + {2170, nullptr, "GetRightsEnvironmentStatus"}, + {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, + {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, + {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"}, + {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, + {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, + {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, + {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, + {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, + {2250, nullptr, "RequestReportActiveELicence"}, + {2300, nullptr, "ListEventLog"}, + {2350, nullptr, "PerformAutoUpdateByApplicationId"}, + {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, + {2352, nullptr, "RequestResolveNoDownloadRightsError"}, + {2353, nullptr, "GetApplicationDownloadTaskInfo"}, + {2354, nullptr, "PrioritizeApplicationBackgroundTask"}, + {2355, nullptr, "PreferStorageEfficientUpdate"}, + {2356, nullptr, "RequestStorageEfficientUpdatePreferable"}, + {2357, nullptr, "EnableMultiCoreDownload"}, + {2358, nullptr, "DisableMultiCoreDownload"}, + {2359, nullptr, "IsMultiCoreDownloadEnabled"}, + {2400, nullptr, "GetPromotionInfo"}, + {2401, nullptr, "CountPromotionInfo"}, + {2402, nullptr, "ListPromotionInfo"}, + {2403, nullptr, "ImportPromotionJsonForDebug"}, + {2404, nullptr, "ClearPromotionInfoForDebug"}, + {2500, nullptr, "ConfirmAvailableTime"}, + {2510, nullptr, "CreateApplicationResource"}, + {2511, nullptr, "GetApplicationResource"}, + {2513, nullptr, "LaunchMicroApplication"}, + {2514, nullptr, "ClearTaskOfAsyncTaskManager"}, + {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, + {2516, nullptr, "EnsureApplicationCertificate"}, + {2517, nullptr, "CreateApplicationInstance"}, + {2518, nullptr, "UpdateQualificationForDebug"}, + {2519, nullptr, "IsQualificationTransitionSupported"}, + {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"}, + {2521, nullptr, "GetRightsUserChangedEvent"}, + {2522, nullptr, "IsRomRedirectionAvailable"}, + {2800, nullptr, "GetApplicationIdOfPreomia"}, + {3000, nullptr, "RegisterDeviceLockKey"}, + {3001, nullptr, "UnregisterDeviceLockKey"}, + {3002, nullptr, "VerifyDeviceLockKey"}, + {3003, nullptr, "HideApplicationIcon"}, + {3004, nullptr, "ShowApplicationIcon"}, + {3005, nullptr, "HideApplicationTitle"}, + {3006, nullptr, "ShowApplicationTitle"}, + {3007, nullptr, "EnableGameCard"}, + {3008, nullptr, "DisableGameCard"}, + {3009, nullptr, "EnableLocalContentShare"}, + {3010, nullptr, "DisableLocalContentShare"}, + {3011, nullptr, "IsApplicationIconHidden"}, + {3012, nullptr, "IsApplicationTitleHidden"}, + {3013, nullptr, "IsGameCardEnabled"}, + {3014, nullptr, "IsLocalContentShareEnabled"}, + {3050, nullptr, "ListAssignELicenseTaskResult"}, + {9999, nullptr, "GetApplicationCertificate"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationManagerInterface::~IApplicationManagerInterface() = default; + +Result IApplicationManagerInterface::GetApplicationControlData( + OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size, + ApplicationControlSource application_control_source, u64 application_id) { + LOG_DEBUG(Service_NS, "called"); + R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData( + out_buffer, out_actual_size, application_control_source, application_id)); +} + +Result IApplicationManagerInterface::GetApplicationDesiredLanguage( + Out<ApplicationLanguage> out_desired_language, u32 supported_languages) { + LOG_DEBUG(Service_NS, "called"); + R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationDesiredLanguage( + out_desired_language, supported_languages)); +} + +Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( + Out<u64> out_language_code, ApplicationLanguage application_language) { + LOG_DEBUG(Service_NS, "called"); + R_RETURN( + IReadOnlyApplicationControlDataInterface(system).ConvertApplicationLanguageToLanguageCode( + out_language_code, application_language)); +} + +Result IApplicationManagerInterface::ListApplicationRecord( + OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, Out<s32> out_count, + s32 offset) { + const auto limit = out_records.size(); + + LOG_WARNING(Service_NS, "(STUBBED) called"); + const auto& cache = system.GetContentProviderUnion(); + const auto installed_games = cache.ListEntriesFilterOrigin( + std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program); + + size_t i = 0; + u8 ii = 24; + + for (const auto& [slot, game] : installed_games) { + if (i >= limit) { + break; + } + if (game.title_id == 0 || game.title_id < 0x0100000000001FFFull) { + continue; + } + if (offset > 0) { + offset--; + continue; + } + + ApplicationRecord record{}; + record.application_id = game.title_id; + record.type = ApplicationRecordType::Installed; + record.unknown = 0; // 2 = needs update + record.unknown2 = ii++; + + out_records[i++] = record; + } + + *out_count = static_cast<s32>(i); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + + record_update_system_event.Signal(); + *out_event = record_update_system_event.GetHandle(); + + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetGameCardMountFailureEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_event = gamecard_mount_failure_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled( + Out<bool> out_is_any_application_entity_installed) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_is_any_application_entity_installed = true; + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationView( + OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views, + InArray<u64, BufferAttr_HipcMapAlias> application_ids) { + const auto size = std::min(out_application_views.size(), application_ids.size()); + LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size()); + + for (size_t i = 0; i < size; i++) { + ApplicationView view{}; + view.application_id = application_ids[i]; + view.unk = 0x70000; + view.flags = 0x401f17; + + out_application_views[i] = view; + } + + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo( + OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views, + InArray<u64, BufferAttr_HipcMapAlias> application_ids) { + const auto size = std::min(out_application_views.size(), application_ids.size()); + LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size()); + + for (size_t i = 0; i < size; i++) { + ApplicationViewWithPromotionInfo view{}; + view.view.application_id = application_ids[i]; + view.view.unk = 0x70000; + view.view.flags = 0x401f17; + view.promotion = {}; + + out_application_views[i] = view; + } + + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationRightsOnClient( + OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count, + u32 flags, u64 application_id, Uid account_id) { + LOG_WARNING(Service_NS, "(STUBBED) called, flags={}, application_id={:016X}, account_id={}", + flags, application_id, account_id.uuid.FormattedString()); + + if (!out_rights.empty()) { + ApplicationRightsOnClient rights{}; + rights.application_id = application_id; + rights.uid = account_id.uuid; + rights.flags = 0; + rights.flags2 = 0; + + out_rights[0] = rights; + *out_count = 1; + } else { + *out_count = 0; + } + + R_SUCCEED(); +} + +Result IApplicationManagerInterface::CheckSdCardMountStatus() { + LOG_DEBUG(Service_NS, "called"); + R_RETURN(IContentManagementInterface(system).CheckSdCardMountStatus()); +} + +Result IApplicationManagerInterface::GetSdCardMountStatusChangedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_event = sd_card_mount_status_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetFreeSpaceSize(Out<s64> out_free_space_size, + FileSys::StorageId storage_id) { + LOG_DEBUG(Service_NS, "called"); + R_RETURN(IContentManagementInterface(system).GetFreeSpaceSize(out_free_space_size, storage_id)); +} + +Result IApplicationManagerInterface::GetGameCardUpdateDetectionEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_event = gamecard_update_detection_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::ResumeAll() { + LOG_WARNING(Service_NS, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetStorageSize(Out<s64> out_total_space_size, + Out<s64> out_free_space_size, + FileSys::StorageId storage_id) { + LOG_INFO(Service_NS, "called, storage_id={}", storage_id); + *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id); + *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::IsApplicationUpdateRequested(Out<bool> out_update_required, + Out<u32> out_update_version, + u64 application_id) { + LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id); + *out_update_required = false; + *out_update_version = 0; + R_SUCCEED(); +} + +Result IApplicationManagerInterface::CheckApplicationLaunchVersion(u64 application_id) { + LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> out_result, + u64 application_id) { + LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id); + *out_result = ResultSuccess; + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_manager_interface.h b/src/core/hle/service/ns/application_manager_interface.h new file mode 100644 index 000000000..f33d269b3 --- /dev/null +++ b/src/core/hle/service/ns/application_manager_interface.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { +public: + explicit IApplicationManagerInterface(Core::System& system_); + ~IApplicationManagerInterface() override; + + Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, + Out<u32> out_actual_size, + ApplicationControlSource application_control_source, + u64 application_id); + Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language, + u32 supported_languages); + Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code, + ApplicationLanguage application_language); + Result ListApplicationRecord(OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, + Out<s32> out_count, s32 offset); + Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed); + Result GetApplicationView( + OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views, + InArray<u64, BufferAttr_HipcMapAlias> application_ids); + Result GetApplicationViewWithPromotionInfo( + OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views, + InArray<u64, BufferAttr_HipcMapAlias> application_ids); + Result GetApplicationRightsOnClient( + OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count, + u32 flags, u64 application_id, Uid account_id); + Result CheckSdCardMountStatus(); + Result GetSdCardMountStatusChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id); + Result GetGameCardUpdateDetectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result ResumeAll(); + Result GetStorageSize(Out<s64> out_total_space_size, Out<s64> out_free_space_size, + FileSys::StorageId storage_id); + Result IsApplicationUpdateRequested(Out<bool> out_update_required, Out<u32> out_update_version, + u64 application_id); + Result CheckApplicationLaunchVersion(u64 application_id); + Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id); + +private: + KernelHelpers::ServiceContext service_context; + Event record_update_system_event; + Event sd_card_mount_status_event; + Event gamecard_update_detection_event; + Event gamecard_mount_status_event; + Event gamecard_mount_failure_event; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_version_interface.cpp b/src/core/hle/service/ns/application_version_interface.cpp new file mode 100644 index 000000000..b89e127db --- /dev/null +++ b/src/core/hle/service/ns/application_version_interface.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/application_version_interface.h" + +namespace Service::NS { + +IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) + : ServiceFramework{system_, "IApplicationVersionInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetLaunchRequiredVersion"}, + {1, nullptr, "UpgradeLaunchRequiredVersion"}, + {35, nullptr, "UpdateVersionList"}, + {36, nullptr, "PushLaunchVersion"}, + {37, nullptr, "ListRequiredVersion"}, + {800, nullptr, "RequestVersionList"}, + {801, nullptr, "ListVersionList"}, + {802, nullptr, "RequestVersionListData"}, + {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"}, + {901, nullptr, "ListDefaultAutoUpdatePolicy"}, + {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"}, + {1000, nullptr, "PerformAutoUpdate"}, + {1001, nullptr, "ListAutoUpdateSchedule"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationVersionInterface::~IApplicationVersionInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/application_version_interface.h b/src/core/hle/service/ns/application_version_interface.h new file mode 100644 index 000000000..b288cff1b --- /dev/null +++ b/src/core/hle/service/ns/application_version_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { +public: + explicit IApplicationVersionInterface(Core::System& system_); + ~IApplicationVersionInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/content_management_interface.cpp b/src/core/hle/service/ns/content_management_interface.cpp new file mode 100644 index 000000000..69bb3f6e4 --- /dev/null +++ b/src/core/hle/service/ns/content_management_interface.cpp @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/common_funcs.h" +#include "core/core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/content_management_interface.h" +#include "core/hle/service/ns/ns_types.h" + +namespace Service::NS { + +IContentManagementInterface::IContentManagementInterface(Core::System& system_) + : ServiceFramework{system_, "IContentManagementInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {11, D<&IContentManagementInterface::CalculateApplicationOccupiedSize>, "CalculateApplicationOccupiedSize"}, + {43, D<&IContentManagementInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"}, + {47, D<&IContentManagementInterface::GetTotalSpaceSize>, "GetTotalSpaceSize"}, + {48, D<&IContentManagementInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"}, + {600, nullptr, "CountApplicationContentMeta"}, + {601, nullptr, "ListApplicationContentMetaStatus"}, + {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, + {607, nullptr, "IsAnyApplicationRunning"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IContentManagementInterface::~IContentManagementInterface() = default; + +Result IContentManagementInterface::CalculateApplicationOccupiedSize( + Out<ApplicationOccupiedSize> out_size, u64 application_id) { + LOG_WARNING(Service_NS, "(STUBBED) called, application_id={:016X}", application_id); + + using namespace Common::Literals; + + constexpr ApplicationOccupiedSizeEntity stub_entity{ + .storage_id = FileSys::StorageId::SdCard, + .app_size = 8_GiB, + .patch_size = 2_GiB, + .aoc_size = 12_MiB, + }; + + for (auto& entity : out_size->entities) { + entity = stub_entity; + } + + R_SUCCEED(); +} + +Result IContentManagementInterface::CheckSdCardMountStatus() { + LOG_WARNING(Service_NS, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IContentManagementInterface::GetTotalSpaceSize(Out<s64> out_total_space_size, + FileSys::StorageId storage_id) { + LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id); + *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id); + R_SUCCEED(); +} + +Result IContentManagementInterface::GetFreeSpaceSize(Out<s64> out_free_space_size, + FileSys::StorageId storage_id) { + LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id); + *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/content_management_interface.h b/src/core/hle/service/ns/content_management_interface.h new file mode 100644 index 000000000..2894628e5 --- /dev/null +++ b/src/core/hle/service/ns/content_management_interface.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> { +public: + explicit IContentManagementInterface(Core::System& system_); + ~IContentManagementInterface() override; + +public: + Result CalculateApplicationOccupiedSize(Out<ApplicationOccupiedSize> out_size, + u64 application_id); + Result CheckSdCardMountStatus(); + Result GetTotalSpaceSize(Out<s64> out_total_space_size, FileSys::StorageId storage_id); + Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/develop_interface.cpp b/src/core/hle/service/ns/develop_interface.cpp new file mode 100644 index 000000000..880bdbebb --- /dev/null +++ b/src/core/hle/service/ns/develop_interface.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/develop_interface.h" + +namespace Service::NS { + +IDevelopInterface::IDevelopInterface(Core::System& system_) : ServiceFramework{system_, "ns:dev"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "LaunchProgram"}, + {1, nullptr, "TerminateProcess"}, + {2, nullptr, "TerminateProgram"}, + {4, nullptr, "GetShellEvent"}, + {5, nullptr, "GetShellEventInfo"}, + {6, nullptr, "TerminateApplication"}, + {7, nullptr, "PrepareLaunchProgramFromHost"}, + {8, nullptr, "LaunchApplicationFromHost"}, + {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, + {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, + {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, + {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"}, + {13, nullptr, "CreateApplicationResourceForDevelop"}, + {14, nullptr, "IsPreomiaForDevelop"}, + {15, nullptr, "GetApplicationProgramIdFromHost"}, + {16, nullptr, "RefreshCachedDebugValues"}, + {17, nullptr, "PrepareLaunchApplicationFromHost"}, + {18, nullptr, "GetLaunchEvent"}, + {19, nullptr, "GetLaunchResult"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDevelopInterface::~IDevelopInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/develop_interface.h b/src/core/hle/service/ns/develop_interface.h new file mode 100644 index 000000000..a9f81ccd6 --- /dev/null +++ b/src/core/hle/service/ns/develop_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDevelopInterface final : public ServiceFramework<IDevelopInterface> { +public: + explicit IDevelopInterface(Core::System& system_); + ~IDevelopInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/document_interface.cpp b/src/core/hle/service/ns/document_interface.cpp new file mode 100644 index 000000000..51a1e46c0 --- /dev/null +++ b/src/core/hle/service/ns/document_interface.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/document_interface.h" + +namespace Service::NS { + +IDocumentInterface::IDocumentInterface(Core::System& system_) + : ServiceFramework{system_, "IDocumentInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {21, nullptr, "GetApplicationContentPath"}, + {23, D<&IDocumentInterface::ResolveApplicationContentPath>, "ResolveApplicationContentPath"}, + {92, D<&IDocumentInterface::GetRunningApplicationProgramId>, "GetRunningApplicationProgramId"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDocumentInterface::~IDocumentInterface() = default; + +Result IDocumentInterface::ResolveApplicationContentPath(ContentPath content_path) { + LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}", + content_path.file_system_proxy_type, content_path.program_id); + R_SUCCEED(); +} + +Result IDocumentInterface::GetRunningApplicationProgramId(Out<u64> out_program_id, + u64 caller_program_id) { + LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); + *out_program_id = system.GetApplicationProcessProgramID(); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/document_interface.h b/src/core/hle/service/ns/document_interface.h new file mode 100644 index 000000000..cd461652c --- /dev/null +++ b/src/core/hle/service/ns/document_interface.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { +public: + explicit IDocumentInterface(Core::System& system_); + ~IDocumentInterface() override; + +private: + Result ResolveApplicationContentPath(ContentPath content_path); + Result GetRunningApplicationProgramId(Out<u64> out_program_id, u64 caller_program_id); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/download_task_interface.cpp b/src/core/hle/service/ns/download_task_interface.cpp new file mode 100644 index 000000000..62dc7f187 --- /dev/null +++ b/src/core/hle/service/ns/download_task_interface.cpp @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/download_task_interface.h" + +namespace Service::NS { + +IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) + : ServiceFramework{system_, "IDownloadTaskInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {701, nullptr, "ClearTaskStatusList"}, + {702, nullptr, "RequestDownloadTaskList"}, + {703, nullptr, "RequestEnsureDownloadTask"}, + {704, nullptr, "ListDownloadTaskStatus"}, + {705, nullptr, "RequestDownloadTaskListData"}, + {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, + {707, D<&IDownloadTaskInterface::EnableAutoCommit>, "EnableAutoCommit"}, + {708, D<&IDownloadTaskInterface::DisableAutoCommit>, "DisableAutoCommit"}, + {709, nullptr, "TriggerDynamicCommitEvent"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDownloadTaskInterface::~IDownloadTaskInterface() = default; + +Result IDownloadTaskInterface::EnableAutoCommit() { + LOG_WARNING(Service_NS, "(STUBBED) called"); + R_SUCCEED(); +} +Result IDownloadTaskInterface::DisableAutoCommit() { + LOG_WARNING(Service_NS, "(STUBBED) called"); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/download_task_interface.h b/src/core/hle/service/ns/download_task_interface.h new file mode 100644 index 000000000..b1cb69cb8 --- /dev/null +++ b/src/core/hle/service/ns/download_task_interface.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { +public: + explicit IDownloadTaskInterface(Core::System& system_); + ~IDownloadTaskInterface() override; + +private: + Result EnableAutoCommit(); + Result DisableAutoCommit(); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/dynamic_rights_interface.cpp b/src/core/hle/service/ns/dynamic_rights_interface.cpp new file mode 100644 index 000000000..ce81e203f --- /dev/null +++ b/src/core/hle/service/ns/dynamic_rights_interface.cpp @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/dynamic_rights_interface.h" + +namespace Service::NS { + +IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_) + : ServiceFramework{system_, "DynamicRightsInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "RequestApplicationRightsOnServer"}, + {1, nullptr, "RequestAssignRights"}, + {4, nullptr, "DeprecatedRequestAssignRightsToResume"}, + {5, D<&IDynamicRightsInterface::VerifyActivatedRightsOwners>, "VerifyActivatedRightsOwners"}, + {6, nullptr, "DeprecatedGetApplicationRightsStatus"}, + {7, nullptr, "RequestPrefetchForDynamicRights"}, + {8, nullptr, "GetDynamicRightsState"}, + {9, nullptr, "RequestApplicationRightsOnServerToResume"}, + {10, nullptr, "RequestAssignRightsToResume"}, + {11, nullptr, "GetActivatedRightsUsers"}, + {12, nullptr, "GetApplicationRightsStatus"}, + {13, D<&IDynamicRightsInterface::GetRunningApplicationStatus>, "GetRunningApplicationStatus"}, + {14, nullptr, "SelectApplicationLicense"}, + {15, nullptr, "RequestContentsAuthorizationToken"}, + {16, nullptr, "QualifyUser"}, + {17, nullptr, "QualifyUserWithProcessId"}, + {18, D<&IDynamicRightsInterface::NotifyApplicationRightsCheckStart>, "NotifyApplicationRightsCheckStart"}, + {19, nullptr, "UpdateUserList"}, + {20, nullptr, "IsRightsLostUser"}, + {21, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"}, + {22, nullptr, "GetLimitedApplicationLicense"}, + {23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"}, + {24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"}, + {25, nullptr, "RequestProceedDynamicRightsState"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IDynamicRightsInterface::~IDynamicRightsInterface() = default; + +Result IDynamicRightsInterface::NotifyApplicationRightsCheckStart() { + LOG_WARNING(Service_NS, "(STUBBED) called"); + R_SUCCEED(); +} + +Result IDynamicRightsInterface::GetRunningApplicationStatus(Out<u32> out_status, + u64 rights_handle) { + LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle); + *out_status = 0; + R_SUCCEED(); +} + +Result IDynamicRightsInterface::VerifyActivatedRightsOwners(u64 rights_handle) { + LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/dynamic_rights_interface.h b/src/core/hle/service/ns/dynamic_rights_interface.h new file mode 100644 index 000000000..877e009b0 --- /dev/null +++ b/src/core/hle/service/ns/dynamic_rights_interface.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDynamicRightsInterface final : public ServiceFramework<IDynamicRightsInterface> { +public: + explicit IDynamicRightsInterface(Core::System& system_); + ~IDynamicRightsInterface() override; + +private: + Result NotifyApplicationRightsCheckStart(); + Result GetRunningApplicationStatus(Out<u32> out_status, u64 rights_handle); + Result VerifyActivatedRightsOwners(u64 rights_handle); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ecommerce_interface.cpp b/src/core/hle/service/ns/ecommerce_interface.cpp new file mode 100644 index 000000000..76fc425f0 --- /dev/null +++ b/src/core/hle/service/ns/ecommerce_interface.cpp @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/ecommerce_interface.h" + +namespace Service::NS { + +IECommerceInterface::IECommerceInterface(Core::System& system_) + : ServiceFramework{system_, "IECommerceInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "RequestLinkDevice"}, + {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, + {2, nullptr, "RequestCleanupPreInstalledApplication"}, + {3, nullptr, "RequestSyncRights"}, + {4, nullptr, "RequestUnlinkDevice"}, + {5, nullptr, "RequestRevokeAllELicense"}, + {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IECommerceInterface::~IECommerceInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ecommerce_interface.h b/src/core/hle/service/ns/ecommerce_interface.h new file mode 100644 index 000000000..4352101f4 --- /dev/null +++ b/src/core/hle/service/ns/ecommerce_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { +public: + explicit IECommerceInterface(Core::System& system_); + ~IECommerceInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/factory_reset_interface.cpp b/src/core/hle/service/ns/factory_reset_interface.cpp new file mode 100644 index 000000000..fd5cf7e1f --- /dev/null +++ b/src/core/hle/service/ns/factory_reset_interface.cpp @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ns/factory_reset_interface.h" + +namespace Service::NS { + +IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) + : ServiceFramework{system_, "IFactoryResetInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {100, nullptr, "ResetToFactorySettings"}, + {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, + {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, + {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, + {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, + {105, nullptr, "RequestResetToFactorySettingsSecurely"}, + {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IFactoryResetInterface::~IFactoryResetInterface() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/factory_reset_interface.h b/src/core/hle/service/ns/factory_reset_interface.h new file mode 100644 index 000000000..50d125123 --- /dev/null +++ b/src/core/hle/service/ns/factory_reset_interface.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { +public: + explicit IFactoryResetInterface(Core::System& system_); + ~IFactoryResetInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/iplatform_service_manager.cpp b/src/core/hle/service/ns/iplatform_service_manager.cpp deleted file mode 100644 index 46268be95..000000000 --- a/src/core/hle/service/ns/iplatform_service_manager.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <cstring> -#include <vector> - -#include "common/assert.h" -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/swap.h" -#include "core/core.h" -#include "core/file_sys/content_archive.h" -#include "core/file_sys/nca_metadata.h" -#include "core/file_sys/registered_cache.h" -#include "core/file_sys/romfs.h" -#include "core/file_sys/system_archive/system_archive.h" -#include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/physical_memory.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/iplatform_service_manager.h" - -namespace Service::NS { - -struct FontRegion { - u32 offset; - u32 size; -}; - -// The below data is specific to shared font data dumped from Switch on f/w 2.2 -// Virtual address and offsets/sizes likely will vary by dump -[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL}; -constexpr u32 EXPECTED_RESULT{0x7f9a0218}; // What we expect the decrypted bfttf first 4 bytes to be -constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf first 4 bytes to be -constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000}; -constexpr FontRegion EMPTY_REGION{0, 0}; - -enum class LoadState : u32 { - Loading = 0, - Done = 1, -}; - -static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMemory& output, - std::size_t& offset) { - ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, - "Shared fonts exceeds 17mb!"); - ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); - - const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor - std::vector<u32> transformed_font(input.size()); - // TODO(ogniK): Figure out a better way to do this - std::transform(input.begin(), input.end(), transformed_font.begin(), - [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); - transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size - std::memcpy(output.data() + offset, transformed_font.data(), - transformed_font.size() * sizeof(u32)); - offset += transformed_font.size() * sizeof(u32); -} - -void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) { - ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); - - if (input.size() < 2) { - LOG_ERROR(Service_NS, "Input font is empty"); - return; - } - - const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor - std::vector<u32> transformed_font(input.size()); - // TODO(ogniK): Figure out a better way to do this - std::transform(input.begin(), input.end(), transformed_font.begin(), - [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); - std::memcpy(output.data(), transformed_font.data() + 2, - (transformed_font.size() - 2) * sizeof(u32)); -} - -void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, - std::size_t& offset) { - ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, - "Shared fonts exceeds 17mb!"); - - const auto key = Common::swap32(EXPECTED_RESULT ^ EXPECTED_MAGIC); - std::vector<u32> transformed_font(input.size() + 2); - transformed_font[0] = Common::swap32(EXPECTED_MAGIC); - transformed_font[1] = Common::swap32(static_cast<u32>(input.size() * sizeof(u32))) ^ key; - std::transform(input.begin(), input.end(), transformed_font.begin() + 2, - [key](u32 in) { return in ^ key; }); - std::memcpy(output.data() + offset, transformed_font.data(), - transformed_font.size() * sizeof(u32)); - offset += transformed_font.size() * sizeof(u32); -} - -// Helper function to make BuildSharedFontsRawRegions a bit nicer -static u32 GetU32Swapped(const u8* data) { - u32 value; - std::memcpy(&value, data, sizeof(value)); - return Common::swap32(value); -} - -struct IPlatformServiceManager::Impl { - const FontRegion& GetSharedFontRegion(std::size_t index) const { - if (index >= shared_font_regions.size() || shared_font_regions.empty()) { - // No font fallback - return EMPTY_REGION; - } - return shared_font_regions.at(index); - } - - void BuildSharedFontsRawRegions(const Kernel::PhysicalMemory& input) { - // As we can derive the xor key we can just populate the offsets - // based on the shared memory dump - unsigned cur_offset = 0; - - for (std::size_t i = 0; i < SHARED_FONTS.size(); i++) { - // Out of shared fonts/invalid font - if (GetU32Swapped(input.data() + cur_offset) != EXPECTED_RESULT) { - break; - } - - // Derive key within inverse xor - const u32 KEY = GetU32Swapped(input.data() + cur_offset) ^ EXPECTED_MAGIC; - const u32 SIZE = GetU32Swapped(input.data() + cur_offset + 4) ^ KEY; - shared_font_regions.push_back(FontRegion{cur_offset + 8, SIZE}); - cur_offset += SIZE + 8; - } - } - - /// Backing memory for the shared font data - std::shared_ptr<Kernel::PhysicalMemory> shared_font; - - // Automatically populated based on shared_fonts dump or system archives. - std::vector<FontRegion> shared_font_regions; -}; - -IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_) - : ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IPlatformServiceManager::RequestLoad, "RequestLoad"}, - {1, &IPlatformServiceManager::GetLoadState, "GetLoadState"}, - {2, &IPlatformServiceManager::GetSize, "GetSize"}, - {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"}, - {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"}, - {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"}, - {6, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriorityForSystem"}, - {100, nullptr, "RequestApplicationFunctionAuthorization"}, - {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, - {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, - {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"}, - {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"}, - {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"}, - {106, nullptr, "GetFunctionBlackListVersion"}, - {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"}, - {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"}, - }; - // clang-format on - RegisterHandlers(functions); - - auto& fsc = system.GetFileSystemController(); - - // Attempt to load shared font data from disk - const auto* nand = fsc.GetSystemNANDContents(); - std::size_t offset = 0; - // Rebuild shared fonts from data ncas or synthesize - - impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE); - for (auto font : SHARED_FONTS) { - FileSys::VirtualFile romfs; - const auto nca = - nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data); - if (nca) { - romfs = nca->GetRomFS(); - } - - if (!romfs) { - romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast<u64>(font.first)); - } - - if (!romfs) { - LOG_ERROR(Service_NS, "Failed to find or synthesize {:016X}! Skipping", font.first); - continue; - } - - const auto extracted_romfs = FileSys::ExtractRomFS(romfs); - if (!extracted_romfs) { - LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping", font.first); - continue; - } - const auto font_fp = extracted_romfs->GetFile(font.second); - if (!font_fp) { - LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping", font.first, font.second); - continue; - } - std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32)); - font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize()); - // We need to be BigEndian as u32s for the xor encryption - std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(), - Common::swap32); - // Font offset and size do not account for the header - const FontRegion region{static_cast<u32>(offset + 8), - static_cast<u32>((font_data_u32.size() * sizeof(u32)) - 8)}; - DecryptSharedFont(font_data_u32, *impl->shared_font, offset); - impl->shared_font_regions.push_back(region); - } -} - -IPlatformServiceManager::~IPlatformServiceManager() = default; - -void IPlatformServiceManager::RequestLoad(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 shared_font_type{rp.Pop<u32>()}; - // Games don't call this so all fonts should be loaded - LOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IPlatformServiceManager::GetLoadState(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 font_id{rp.Pop<u32>()}; - LOG_DEBUG(Service_NS, "called, font_id={}", font_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(static_cast<u32>(LoadState::Done)); -} - -void IPlatformServiceManager::GetSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 font_id{rp.Pop<u32>()}; - LOG_DEBUG(Service_NS, "called, font_id={}", font_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(impl->GetSharedFontRegion(font_id).size); -} - -void IPlatformServiceManager::GetSharedMemoryAddressOffset(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 font_id{rp.Pop<u32>()}; - LOG_DEBUG(Service_NS, "called, font_id={}", font_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset); -} - -void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx) { - // Map backing memory for the font data - LOG_DEBUG(Service_NS, "called"); - - // Create shared font memory object - std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(), - impl->shared_font->size()); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(&kernel.GetFontSharedMem()); -} - -void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) { - // The maximum number of elements that can be returned is 6. Regardless of the available fonts - // or buffer size. - constexpr std::size_t MaxElementCount = 6; - IPC::RequestParser rp{ctx}; - const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for - const std::size_t font_codes_count = - std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(0)); - const std::size_t font_offsets_count = - std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(1)); - const std::size_t font_sizes_count = - std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(2)); - LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code); - - IPC::ResponseBuilder rb{ctx, 4}; - std::vector<u32> font_codes; - std::vector<u32> font_offsets; - std::vector<u32> font_sizes; - - // TODO(ogniK): Have actual priority order - for (std::size_t i = 0; i < impl->shared_font_regions.size(); i++) { - font_codes.push_back(static_cast<u32>(i)); - auto region = impl->GetSharedFontRegion(i); - font_offsets.push_back(region.offset); - font_sizes.push_back(region.size); - } - - // Resize buffers if game requests smaller size output - font_codes.resize(std::min(font_codes.size(), font_codes_count)); - font_offsets.resize(std::min(font_offsets.size(), font_offsets_count)); - font_sizes.resize(std::min(font_sizes.size(), font_sizes_count)); - - ctx.WriteBuffer(font_codes, 0); - ctx.WriteBuffer(font_offsets, 1); - ctx.WriteBuffer(font_sizes, 2); - - rb.Push(ResultSuccess); - rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded - rb.Push<u32>(static_cast<u32>(font_codes.size())); -} - -} // namespace Service::NS diff --git a/src/core/hle/service/ns/iplatform_service_manager.h b/src/core/hle/service/ns/iplatform_service_manager.h deleted file mode 100644 index 03071e02b..000000000 --- a/src/core/hle/service/ns/iplatform_service_manager.h +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <vector> -#include "core/hle/service/service.h" - -namespace Service { - -namespace FileSystem { -class FileSystemController; -} // namespace FileSystem - -namespace NS { - -enum class FontArchives : u64 { - Extension = 0x0100000000000810, - Standard = 0x0100000000000811, - Korean = 0x0100000000000812, - ChineseTraditional = 0x0100000000000813, - ChineseSimple = 0x0100000000000814, -}; - -constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{ - std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"), - std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"), - std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"), - std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"), - std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"), - std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"), - std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"), -}; - -void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output); -void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); - -class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> { -public: - explicit IPlatformServiceManager(Core::System& system_, const char* service_name_); - ~IPlatformServiceManager() override; - -private: - void RequestLoad(HLERequestContext& ctx); - void GetLoadState(HLERequestContext& ctx); - void GetSize(HLERequestContext& ctx); - void GetSharedMemoryAddressOffset(HLERequestContext& ctx); - void GetSharedMemoryNativeHandle(HLERequestContext& ctx); - void GetSharedFontInOrderOfPriority(HLERequestContext& ctx); - - struct Impl; - std::unique_ptr<Impl> impl; -}; - -} // namespace NS - -} // namespace Service diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 19c3ff01b..8402e83cb 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -1,893 +1,38 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/arm/debug.h" -#include "core/core.h" -#include "core/file_sys/control_metadata.h" -#include "core/file_sys/patch_manager.h" -#include "core/file_sys/vfs/vfs.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/glue/glue_manager.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/errors.h" -#include "core/hle/service/ns/iplatform_service_manager.h" -#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/develop_interface.h" #include "core/hle/service/ns/ns.h" -#include "core/hle/service/ns/pdm_qry.h" +#include "core/hle/service/ns/platform_service_manager.h" +#include "core/hle/service/ns/query_service.h" +#include "core/hle/service/ns/service_getter_interface.h" +#include "core/hle/service/ns/system_update_interface.h" +#include "core/hle/service/ns/vulnerability_manager_interface.h" #include "core/hle/service/server_manager.h" -#include "core/hle/service/set/settings_server.h" namespace Service::NS { -IAccountProxyInterface::IAccountProxyInterface(Core::System& system_) - : ServiceFramework{system_, "IAccountProxyInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "CreateUserAccount"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IAccountProxyInterface::~IAccountProxyInterface() = default; - -IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_) - : ServiceFramework{system_, "IApplicationManagerInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "ListApplicationRecord"}, - {1, nullptr, "GenerateApplicationRecordCount"}, - {2, nullptr, "GetApplicationRecordUpdateSystemEvent"}, - {3, nullptr, "GetApplicationViewDeprecated"}, - {4, nullptr, "DeleteApplicationEntity"}, - {5, nullptr, "DeleteApplicationCompletely"}, - {6, nullptr, "IsAnyApplicationEntityRedundant"}, - {7, nullptr, "DeleteRedundantApplicationEntity"}, - {8, nullptr, "IsApplicationEntityMovable"}, - {9, nullptr, "MoveApplicationEntity"}, - {11, nullptr, "CalculateApplicationOccupiedSize"}, - {16, nullptr, "PushApplicationRecord"}, - {17, nullptr, "ListApplicationRecordContentMeta"}, - {19, nullptr, "LaunchApplicationOld"}, - {21, nullptr, "GetApplicationContentPath"}, - {22, nullptr, "TerminateApplication"}, - {23, nullptr, "ResolveApplicationContentPath"}, - {26, nullptr, "BeginInstallApplication"}, - {27, nullptr, "DeleteApplicationRecord"}, - {30, nullptr, "RequestApplicationUpdateInfo"}, - {31, nullptr, "Unknown31"}, - {32, nullptr, "CancelApplicationDownload"}, - {33, nullptr, "ResumeApplicationDownload"}, - {35, nullptr, "UpdateVersionList"}, - {36, nullptr, "PushLaunchVersion"}, - {37, nullptr, "ListRequiredVersion"}, - {38, nullptr, "CheckApplicationLaunchVersion"}, - {39, nullptr, "CheckApplicationLaunchRights"}, - {40, nullptr, "GetApplicationLogoData"}, - {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, - {42, nullptr, "CleanupSdCard"}, - {43, nullptr, "CheckSdCardMountStatus"}, - {44, nullptr, "GetSdCardMountStatusChangedEvent"}, - {45, nullptr, "GetGameCardAttachmentEvent"}, - {46, nullptr, "GetGameCardAttachmentInfo"}, - {47, nullptr, "GetTotalSpaceSize"}, - {48, nullptr, "GetFreeSpaceSize"}, - {49, nullptr, "GetSdCardRemovedEvent"}, - {52, nullptr, "GetGameCardUpdateDetectionEvent"}, - {53, nullptr, "DisableApplicationAutoDelete"}, - {54, nullptr, "EnableApplicationAutoDelete"}, - {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"}, - {56, nullptr, "SetApplicationTerminateResult"}, - {57, nullptr, "ClearApplicationTerminateResult"}, - {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, - {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"}, - {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, - {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, - {62, nullptr, "GetGameCardStopper"}, - {63, nullptr, "IsSystemProgramInstalled"}, - {64, nullptr, "StartApplyDeltaTask"}, - {65, nullptr, "GetRequestServerStopper"}, - {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, - {67, nullptr, "CancelApplicationApplyDelta"}, - {68, nullptr, "ResumeApplicationApplyDelta"}, - {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, - {70, nullptr, "ResumeAll"}, - {71, nullptr, "GetStorageSize"}, - {80, nullptr, "RequestDownloadApplication"}, - {81, nullptr, "RequestDownloadAddOnContent"}, - {82, nullptr, "DownloadApplication"}, - {83, nullptr, "CheckApplicationResumeRights"}, - {84, nullptr, "GetDynamicCommitEvent"}, - {85, nullptr, "RequestUpdateApplication2"}, - {86, nullptr, "EnableApplicationCrashReport"}, - {87, nullptr, "IsApplicationCrashReportEnabled"}, - {90, nullptr, "BoostSystemMemoryResourceLimit"}, - {91, nullptr, "DeprecatedLaunchApplication"}, - {92, nullptr, "GetRunningApplicationProgramId"}, - {93, nullptr, "GetMainApplicationProgramIndex"}, - {94, nullptr, "LaunchApplication"}, - {95, nullptr, "GetApplicationLaunchInfo"}, - {96, nullptr, "AcquireApplicationLaunchInfo"}, - {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"}, - {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, - {99, nullptr, "LaunchDevMenu"}, - {100, nullptr, "ResetToFactorySettings"}, - {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, - {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, - {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, - {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, - {105, nullptr, "RequestResetToFactorySettingsSecurely"}, - {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, - {200, nullptr, "CalculateUserSaveDataStatistics"}, - {201, nullptr, "DeleteUserSaveDataAll"}, - {210, nullptr, "DeleteUserSystemSaveData"}, - {211, nullptr, "DeleteSaveData"}, - {220, nullptr, "UnregisterNetworkServiceAccount"}, - {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, - {300, nullptr, "GetApplicationShellEvent"}, - {301, nullptr, "PopApplicationShellEventInfo"}, - {302, nullptr, "LaunchLibraryApplet"}, - {303, nullptr, "TerminateLibraryApplet"}, - {304, nullptr, "LaunchSystemApplet"}, - {305, nullptr, "TerminateSystemApplet"}, - {306, nullptr, "LaunchOverlayApplet"}, - {307, nullptr, "TerminateOverlayApplet"}, - {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, - {401, nullptr, "InvalidateAllApplicationControlCache"}, - {402, nullptr, "RequestDownloadApplicationControlData"}, - {403, nullptr, "GetMaxApplicationControlCacheCount"}, - {404, nullptr, "InvalidateApplicationControlCache"}, - {405, nullptr, "ListApplicationControlCacheEntryInfo"}, - {406, nullptr, "GetApplicationControlProperty"}, - {407, nullptr, "ListApplicationTitle"}, - {408, nullptr, "ListApplicationIcon"}, - {502, nullptr, "RequestCheckGameCardRegistration"}, - {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, - {504, nullptr, "RequestRegisterGameCard"}, - {505, nullptr, "GetGameCardMountFailureEvent"}, - {506, nullptr, "IsGameCardInserted"}, - {507, nullptr, "EnsureGameCardAccess"}, - {508, nullptr, "GetLastGameCardMountFailureResult"}, - {509, nullptr, "ListApplicationIdOnGameCard"}, - {510, nullptr, "GetGameCardPlatformRegion"}, - {600, nullptr, "CountApplicationContentMeta"}, - {601, nullptr, "ListApplicationContentMetaStatus"}, - {602, nullptr, "ListAvailableAddOnContent"}, - {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, - {604, nullptr, "RegisterContentsExternalKey"}, - {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, - {606, nullptr, "GetContentMetaStorage"}, - {607, nullptr, "ListAvailableAddOnContent"}, - {609, nullptr, "ListAvailabilityAssuredAddOnContent"}, - {610, nullptr, "GetInstalledContentMetaStorage"}, - {611, nullptr, "PrepareAddOnContent"}, - {700, nullptr, "PushDownloadTaskList"}, - {701, nullptr, "ClearTaskStatusList"}, - {702, nullptr, "RequestDownloadTaskList"}, - {703, nullptr, "RequestEnsureDownloadTask"}, - {704, nullptr, "ListDownloadTaskStatus"}, - {705, nullptr, "RequestDownloadTaskListData"}, - {800, nullptr, "RequestVersionList"}, - {801, nullptr, "ListVersionList"}, - {802, nullptr, "RequestVersionListData"}, - {900, nullptr, "GetApplicationRecord"}, - {901, nullptr, "GetApplicationRecordProperty"}, - {902, nullptr, "EnableApplicationAutoUpdate"}, - {903, nullptr, "DisableApplicationAutoUpdate"}, - {904, nullptr, "TouchApplication"}, - {905, nullptr, "RequestApplicationUpdate"}, - {906, nullptr, "IsApplicationUpdateRequested"}, - {907, nullptr, "WithdrawApplicationUpdateRequest"}, - {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, - {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, - {910, nullptr, "HasApplicationRecord"}, - {911, nullptr, "SetPreInstalledApplication"}, - {912, nullptr, "ClearPreInstalledApplicationFlag"}, - {913, nullptr, "ListAllApplicationRecord"}, - {914, nullptr, "HideApplicationRecord"}, - {915, nullptr, "ShowApplicationRecord"}, - {916, nullptr, "IsApplicationAutoDeleteDisabled"}, - {1000, nullptr, "RequestVerifyApplicationDeprecated"}, - {1001, nullptr, "CorruptApplicationForDebug"}, - {1002, nullptr, "RequestVerifyAddOnContentsRights"}, - {1003, nullptr, "RequestVerifyApplication"}, - {1004, nullptr, "CorruptContentForDebug"}, - {1200, nullptr, "NeedsUpdateVulnerability"}, - {1300, nullptr, "IsAnyApplicationEntityInstalled"}, - {1301, nullptr, "DeleteApplicationContentEntities"}, - {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, - {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, - {1304, nullptr, "DeleteApplicationContentEntity"}, - {1305, nullptr, "TryDeleteRunningApplicationEntity"}, - {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, - {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, - {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, - {1309, nullptr, "CleanupUnavailableAddOnContents"}, - {1310, nullptr, "RequestMoveApplicationEntity"}, - {1311, nullptr, "EstimateSizeToMove"}, - {1312, nullptr, "HasMovableEntity"}, - {1313, nullptr, "CleanupOrphanContents"}, - {1314, nullptr, "CheckPreconditionSatisfiedToMove"}, - {1400, nullptr, "PrepareShutdown"}, - {1500, nullptr, "FormatSdCard"}, - {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, - {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, - {1504, nullptr, "InsertSdCard"}, - {1505, nullptr, "RemoveSdCard"}, - {1506, nullptr, "GetSdCardStartupStatus"}, - {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, - {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, - {1700, nullptr, "ListApplicationDownloadingContentMeta"}, - {1701, nullptr, "GetApplicationView"}, - {1702, nullptr, "GetApplicationDownloadTaskStatus"}, - {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, - {1704, nullptr, "GetApplicationViewWithPromotionInfo"}, - {1705, nullptr, "IsPatchAutoDeletableApplication"}, - {1800, nullptr, "IsNotificationSetupCompleted"}, - {1801, nullptr, "GetLastNotificationInfoCount"}, - {1802, nullptr, "ListLastNotificationInfo"}, - {1803, nullptr, "ListNotificationTask"}, - {1900, nullptr, "IsActiveAccount"}, - {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, - {1902, nullptr, "GetApplicationTicketInfo"}, - {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"}, - {2000, nullptr, "GetSystemDeliveryInfo"}, - {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, - {2002, nullptr, "VerifyDeliveryProtocolVersion"}, - {2003, nullptr, "GetApplicationDeliveryInfo"}, - {2004, nullptr, "HasAllContentsToDeliver"}, - {2005, nullptr, "CompareApplicationDeliveryInfo"}, - {2006, nullptr, "CanDeliverApplication"}, - {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, - {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, - {2009, nullptr, "EstimateRequiredSize"}, - {2010, nullptr, "RequestReceiveApplication"}, - {2011, nullptr, "CommitReceiveApplication"}, - {2012, nullptr, "GetReceiveApplicationProgress"}, - {2013, nullptr, "RequestSendApplication"}, - {2014, nullptr, "GetSendApplicationProgress"}, - {2015, nullptr, "CompareSystemDeliveryInfo"}, - {2016, nullptr, "ListNotCommittedContentMeta"}, - {2017, nullptr, "CreateDownloadTask"}, - {2018, nullptr, "GetApplicationDeliveryInfoHash"}, - {2050, nullptr, "GetApplicationRightsOnClient"}, - {2051, nullptr, "InvalidateRightsIdCache"}, - {2100, nullptr, "GetApplicationTerminateResult"}, - {2101, nullptr, "GetRawApplicationTerminateResult"}, - {2150, nullptr, "CreateRightsEnvironment"}, - {2151, nullptr, "DestroyRightsEnvironment"}, - {2152, nullptr, "ActivateRightsEnvironment"}, - {2153, nullptr, "DeactivateRightsEnvironment"}, - {2154, nullptr, "ForceActivateRightsContextForExit"}, - {2155, nullptr, "UpdateRightsEnvironmentStatus"}, - {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"}, - {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, - {2161, nullptr, "SetUsersToRightsEnvironment"}, - {2170, nullptr, "GetRightsEnvironmentStatus"}, - {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, - {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, - {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"}, - {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, - {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, - {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, - {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, - {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, - {2250, nullptr, "RequestReportActiveELicence"}, - {2300, nullptr, "ListEventLog"}, - {2350, nullptr, "PerformAutoUpdateByApplicationId"}, - {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, - {2352, nullptr, "RequestResolveNoDownloadRightsError"}, - {2353, nullptr, "GetApplicationDownloadTaskInfo"}, - {2354, nullptr, "PrioritizeApplicationBackgroundTask"}, - {2355, nullptr, "PreferStorageEfficientUpdate"}, - {2356, nullptr, "RequestStorageEfficientUpdatePreferable"}, - {2357, nullptr, "EnableMultiCoreDownload"}, - {2358, nullptr, "DisableMultiCoreDownload"}, - {2359, nullptr, "IsMultiCoreDownloadEnabled"}, - {2400, nullptr, "GetPromotionInfo"}, - {2401, nullptr, "CountPromotionInfo"}, - {2402, nullptr, "ListPromotionInfo"}, - {2403, nullptr, "ImportPromotionJsonForDebug"}, - {2404, nullptr, "ClearPromotionInfoForDebug"}, - {2500, nullptr, "ConfirmAvailableTime"}, - {2510, nullptr, "CreateApplicationResource"}, - {2511, nullptr, "GetApplicationResource"}, - {2513, nullptr, "LaunchMicroApplication"}, - {2514, nullptr, "ClearTaskOfAsyncTaskManager"}, - {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, - {2516, nullptr, "EnsureApplicationCertificate"}, - {2517, nullptr, "CreateApplicationInstance"}, - {2518, nullptr, "UpdateQualificationForDebug"}, - {2519, nullptr, "IsQualificationTransitionSupported"}, - {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"}, - {2521, nullptr, "GetRightsUserChangedEvent"}, - {2522, nullptr, "IsRomRedirectionAvailable"}, - {2800, nullptr, "GetApplicationIdOfPreomia"}, - {3000, nullptr, "RegisterDeviceLockKey"}, - {3001, nullptr, "UnregisterDeviceLockKey"}, - {3002, nullptr, "VerifyDeviceLockKey"}, - {3003, nullptr, "HideApplicationIcon"}, - {3004, nullptr, "ShowApplicationIcon"}, - {3005, nullptr, "HideApplicationTitle"}, - {3006, nullptr, "ShowApplicationTitle"}, - {3007, nullptr, "EnableGameCard"}, - {3008, nullptr, "DisableGameCard"}, - {3009, nullptr, "EnableLocalContentShare"}, - {3010, nullptr, "DisableLocalContentShare"}, - {3011, nullptr, "IsApplicationIconHidden"}, - {3012, nullptr, "IsApplicationTitleHidden"}, - {3013, nullptr, "IsGameCardEnabled"}, - {3014, nullptr, "IsLocalContentShareEnabled"}, - {3050, nullptr, "ListAssignELicenseTaskResult"}, - {9999, nullptr, "GetApplicationCertificate"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IApplicationManagerInterface::~IApplicationManagerInterface() = default; - -void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto flag = rp.PopRaw<u64>(); - LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); - - const auto title_id = rp.PopRaw<u64>(); - - const auto size = ctx.GetWriteBufferSize(); - - const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), - system.GetContentProvider()}; - const auto control = pm.GetControlMetadata(); - - std::vector<u8> out; - - if (control.first != nullptr) { - if (size < 0x4000) { - LOG_ERROR(Service_NS, - "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size); - IPC::ResponseBuilder rb{ctx, 2}; - // TODO(DarkLordZach): Find a better error code for this. - rb.Push(ResultUnknown); - return; - } - - out.resize(0x4000); - const auto bytes = control.first->GetRawBytes(); - std::memcpy(out.data(), bytes.data(), bytes.size()); - } else { - LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", - title_id); - out.resize(std::min<u64>(0x4000, size)); - } - - if (control.second != nullptr) { - if (size < 0x4000 + control.second->GetSize()) { - LOG_ERROR(Service_NS, - "output buffer is too small! (actual={:016X}, expected_min={:016X})", size, - 0x4000 + control.second->GetSize()); - IPC::ResponseBuilder rb{ctx, 2}; - // TODO(DarkLordZach): Find a better error code for this. - rb.Push(ResultUnknown); - return; - } - - out.resize(0x4000 + control.second->GetSize()); - control.second->Read(out.data() + 0x4000, control.second->GetSize()); - } else { - LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", - title_id); - } - - ctx.WriteBuffer(out); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(static_cast<u32>(out.size())); -} - -void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto supported_languages = rp.Pop<u32>(); - - u8 desired_language{}; - const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); - if (res == ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(desired_language); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); - } -} - -Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language, - const u32 supported_languages) { - LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); - - // Get language code from settings - const auto language_code = - Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue())); - - // Convert to application language, get priority list - const auto application_language = ConvertToApplicationLanguage(language_code); - if (application_language == std::nullopt) { - LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", - language_code); - 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 Service::NS::ResultApplicationLanguageNotFound; - } - - // Try to find a valid language. - for (const auto lang : *priority_list) { - const auto supported_flag = GetSupportedLanguageFlag(lang); - if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { - *out_desired_language = static_cast<u8>(lang); - return ResultSuccess; - } - } - - LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}", - supported_languages); - return Service::NS::ResultApplicationLanguageNotFound; -} - -void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( - HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto application_language = rp.Pop<u8>(); - - u64 language_code{}; - const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language); - if (res == ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(language_code); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); - } -} - -Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( - u64* out_language_code, u8 application_language) { - const auto language_code = - ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); - if (language_code == std::nullopt) { - LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language); - return Service::NS::ResultApplicationLanguageNotFound; - } - - *out_language_code = static_cast<u64>(*language_code); - return ResultSuccess; -} - -IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) - : ServiceFramework{system_, "IApplicationVersionInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetLaunchRequiredVersion"}, - {1, nullptr, "UpgradeLaunchRequiredVersion"}, - {35, nullptr, "UpdateVersionList"}, - {36, nullptr, "PushLaunchVersion"}, - {37, nullptr, "ListRequiredVersion"}, - {800, nullptr, "RequestVersionList"}, - {801, nullptr, "ListVersionList"}, - {802, nullptr, "RequestVersionListData"}, - {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"}, - {901, nullptr, "ListDefaultAutoUpdatePolicy"}, - {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"}, - {1000, nullptr, "PerformAutoUpdate"}, - {1001, nullptr, "ListAutoUpdateSchedule"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IApplicationVersionInterface::~IApplicationVersionInterface() = default; - -IContentManagementInterface::IContentManagementInterface(Core::System& system_) - : ServiceFramework{system_, "IContentManagementInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {11, nullptr, "CalculateApplicationOccupiedSize"}, - {43, nullptr, "CheckSdCardMountStatus"}, - {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"}, - {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"}, - {600, nullptr, "CountApplicationContentMeta"}, - {601, nullptr, "ListApplicationContentMetaStatus"}, - {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, - {607, nullptr, "IsAnyApplicationRunning"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IContentManagementInterface::~IContentManagementInterface() = default; - -void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto storage{rp.PopEnum<FileSys::StorageId>()}; - - LOG_INFO(Service_Capture, "called, storage={}", storage); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage)); -} - -void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto storage{rp.PopEnum<FileSys::StorageId>()}; - - LOG_INFO(Service_Capture, "called, storage={}", storage); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage)); -} - -IDocumentInterface::IDocumentInterface(Core::System& system_) - : ServiceFramework{system_, "IDocumentInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {21, nullptr, "GetApplicationContentPath"}, - {23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"}, - {92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IDocumentInterface::~IDocumentInterface() = default; - -void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) { - struct ContentPath { - u8 file_system_proxy_type; - u64 program_id; - }; - static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size"); - - IPC::RequestParser rp{ctx}; - auto content_path = rp.PopRaw<ContentPath>(); - LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}", - content_path.file_system_proxy_type, content_path.program_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto caller_program_id = rp.PopRaw<u64>(); - LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(system.GetApplicationProcessProgramID()); -} - -IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) - : ServiceFramework{system_, "IDownloadTaskInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {701, nullptr, "ClearTaskStatusList"}, - {702, nullptr, "RequestDownloadTaskList"}, - {703, nullptr, "RequestEnsureDownloadTask"}, - {704, nullptr, "ListDownloadTaskStatus"}, - {705, nullptr, "RequestDownloadTaskListData"}, - {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, - {707, nullptr, "EnableAutoCommit"}, - {708, nullptr, "DisableAutoCommit"}, - {709, nullptr, "TriggerDynamicCommitEvent"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IDownloadTaskInterface::~IDownloadTaskInterface() = default; - -IECommerceInterface::IECommerceInterface(Core::System& system_) - : ServiceFramework{system_, "IECommerceInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "RequestLinkDevice"}, - {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, - {2, nullptr, "RequestCleanupPreInstalledApplication"}, - {3, nullptr, "RequestSyncRights"}, - {4, nullptr, "RequestUnlinkDevice"}, - {5, nullptr, "RequestRevokeAllELicense"}, - {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IECommerceInterface::~IECommerceInterface() = default; - -IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) - : ServiceFramework{system_, "IFactoryResetInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {100, nullptr, "ResetToFactorySettings"}, - {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, - {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, - {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"}, - {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"}, - {105, nullptr, "RequestResetToFactorySettingsSecurely"}, - {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IFactoryResetInterface::~IFactoryResetInterface() = default; - -IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_) - : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} { - static const FunctionInfo functions[] = { - {0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"}, - {1, nullptr, "NotifyApplicationFailure"}, - {2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default; - -void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 program_id = rp.PopRaw<u64>(); - LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(1); -} - -void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto result = rp.PopRaw<Result>(); - LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(0); -} - -IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( - Core::System& system_) - : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"}, - {1, nullptr, "GetApplicationDesiredLanguage"}, - {2, nullptr, "ConvertApplicationLanguageToLanguageCode"}, - {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, - {4, nullptr, "SelectApplicationDesiredLanguage"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; - -void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) { - enum class ApplicationControlSource : u8 { - CacheOnly, - Storage, - StorageOnly, - }; - - struct RequestParameters { - ApplicationControlSource source; - u64 application_id; - }; - static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); - - IPC::RequestParser rp{ctx}; - std::vector<u8> nacp_data{}; - const auto parameters{rp.PopRaw<RequestParameters>()}; - const auto result = - system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id); - - if (result == ResultSuccess) { - ctx.WriteBuffer(nacp_data.data(), nacp_data.size()); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { - // clang-format off - static const FunctionInfo functions[] = { - {7988, nullptr, "GetDynamicRightsInterface"}, - {7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"}, - {7991, &NS::PushInterface<IReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"}, - {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, - {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, - {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, - {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, - {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"}, - {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, - {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"}, - {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -NS::~NS() = default; - -std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { - return GetInterface<IApplicationManagerInterface>(system); -} - -class NS_DEV final : public ServiceFramework<NS_DEV> { -public: - explicit NS_DEV(Core::System& system_) : ServiceFramework{system_, "ns:dev"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "LaunchProgram"}, - {1, nullptr, "TerminateProcess"}, - {2, nullptr, "TerminateProgram"}, - {4, nullptr, "GetShellEvent"}, - {5, nullptr, "GetShellEventInfo"}, - {6, nullptr, "TerminateApplication"}, - {7, nullptr, "PrepareLaunchProgramFromHost"}, - {8, nullptr, "LaunchApplicationFromHost"}, - {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, - {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, - {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, - {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"}, - {13, nullptr, "CreateApplicationResourceForDevelop"}, - {14, nullptr, "IsPreomiaForDevelop"}, - {15, nullptr, "GetApplicationProgramIdFromHost"}, - {16, nullptr, "RefreshCachedDebugValues"}, - {17, nullptr, "PrepareLaunchApplicationFromHost"}, - {18, nullptr, "GetLaunchEvent"}, - {19, nullptr, "GetLaunchResult"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> { -public: - explicit ISystemUpdateControl(Core::System& system_) - : ServiceFramework{system_, "ISystemUpdateControl"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "HasDownloaded"}, - {1, nullptr, "RequestCheckLatestUpdate"}, - {2, nullptr, "RequestDownloadLatestUpdate"}, - {3, nullptr, "GetDownloadProgress"}, - {4, nullptr, "ApplyDownloadedUpdate"}, - {5, nullptr, "RequestPrepareCardUpdate"}, - {6, nullptr, "GetPrepareCardUpdateProgress"}, - {7, nullptr, "HasPreparedCardUpdate"}, - {8, nullptr, "ApplyCardUpdate"}, - {9, nullptr, "GetDownloadedEulaDataSize"}, - {10, nullptr, "GetDownloadedEulaData"}, - {11, nullptr, "SetupCardUpdate"}, - {12, nullptr, "GetPreparedCardUpdateEulaDataSize"}, - {13, nullptr, "GetPreparedCardUpdateEulaData"}, - {14, nullptr, "SetupCardUpdateViaSystemUpdater"}, - {15, nullptr, "HasReceived"}, - {16, nullptr, "RequestReceiveSystemUpdate"}, - {17, nullptr, "GetReceiveProgress"}, - {18, nullptr, "ApplyReceivedUpdate"}, - {19, nullptr, "GetReceivedEulaDataSize"}, - {20, nullptr, "GetReceivedEulaData"}, - {21, nullptr, "SetupToReceiveSystemUpdate"}, - {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - -class NS_SU final : public ServiceFramework<NS_SU> { -public: - explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetBackgroundNetworkUpdateState"}, - {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"}, - {2, nullptr, "NotifyExFatDriverRequired"}, - {3, nullptr, "ClearExFatDriverStatusForDebug"}, - {4, nullptr, "RequestBackgroundNetworkUpdate"}, - {5, nullptr, "NotifyBackgroundNetworkUpdate"}, - {6, nullptr, "NotifyExFatDriverDownloadedForDebug"}, - {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"}, - {10, nullptr, "NotifySystemUpdateForContentDelivery"}, - {11, nullptr, "PrepareShutdown"}, - {12, nullptr, "Unknown12"}, - {13, nullptr, "Unknown13"}, - {14, nullptr, "Unknown14"}, - {15, nullptr, "Unknown15"}, - {16, nullptr, "DestroySystemUpdateTask"}, - {17, nullptr, "RequestSendSystemUpdate"}, - {18, nullptr, "GetSendSystemUpdateProgress"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void OpenSystemUpdateControl(HLERequestContext& ctx) { - LOG_DEBUG(Service_NS, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISystemUpdateControl>(system); - } -}; - -class NS_VM final : public ServiceFramework<NS_VM> { -public: - explicit NS_VM(Core::System& system_) : ServiceFramework{system_, "ns:vm"} { - // clang-format off - static const FunctionInfo functions[] = { - {1200, &NS_VM::NeedsUpdateVulnerability, "NeedsUpdateVulnerability"}, - {1201, nullptr, "UpdateSafeSystemVersionForDebug"}, - {1202, nullptr, "GetSafeSystemVersion"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void NeedsUpdateVulnerability(HLERequestContext& ctx) { - LOG_WARNING(Service_NS, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(false); - } -}; - void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system)); - server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system)); - server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system)); - server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system)); - server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system)); - server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system)); - - server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system)); - server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system)); - server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system)); - server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system)); + server_manager->RegisterNamedService( + "ns:am2", std::make_shared<IServiceGetterInterface>(system, "ns:am2")); + server_manager->RegisterNamedService( + "ns:ec", std::make_shared<IServiceGetterInterface>(system, "ns:ec")); + server_manager->RegisterNamedService( + "ns:rid", std::make_shared<IServiceGetterInterface>(system, "ns:rid")); + server_manager->RegisterNamedService( + "ns:rt", std::make_shared<IServiceGetterInterface>(system, "ns:rt")); + server_manager->RegisterNamedService( + "ns:web", std::make_shared<IServiceGetterInterface>(system, "ns:web")); + server_manager->RegisterNamedService( + "ns:ro", std::make_shared<IServiceGetterInterface>(system, "ns:ro")); + + server_manager->RegisterNamedService("ns:dev", std::make_shared<IDevelopInterface>(system)); + server_manager->RegisterNamedService("ns:su", std::make_shared<ISystemUpdateInterface>(system)); + server_manager->RegisterNamedService("ns:vm", + std::make_shared<IVulnerabilityManagerInterface>(system)); + server_manager->RegisterNamedService("pdm:qry", std::make_shared<IQueryService>(system)); server_manager->RegisterNamedService("pl:s", std::make_shared<IPlatformServiceManager>(system, "pl:s")); diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 9ee306ef9..f79b4ae3d 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -3,141 +3,12 @@ #pragma once -#include "core/hle/service/service.h" - namespace Core { class System; } -namespace Service { - -namespace FileSystem { -class FileSystemController; -} // namespace FileSystem - -namespace NS { - -class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { -public: - explicit IAccountProxyInterface(Core::System& system_); - ~IAccountProxyInterface() override; -}; - -class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { -public: - explicit IApplicationManagerInterface(Core::System& system_); - ~IApplicationManagerInterface() override; - - Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages); - Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code, - u8 application_language); - -private: - void GetApplicationControlData(HLERequestContext& ctx); - void GetApplicationDesiredLanguage(HLERequestContext& ctx); - void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx); -}; - -class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { -public: - explicit IApplicationVersionInterface(Core::System& system_); - ~IApplicationVersionInterface() override; -}; - -class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> { -public: - explicit IContentManagementInterface(Core::System& system_); - ~IContentManagementInterface() override; - -private: - void GetTotalSpaceSize(HLERequestContext& ctx); - void GetFreeSpaceSize(HLERequestContext& ctx); -}; - -class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { -public: - explicit IDocumentInterface(Core::System& system_); - ~IDocumentInterface() override; - -private: - void ResolveApplicationContentPath(HLERequestContext& ctx); - void GetRunningApplicationProgramId(HLERequestContext& ctx); -}; - -class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { -public: - explicit IDownloadTaskInterface(Core::System& system_); - ~IDownloadTaskInterface() override; -}; - -class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { -public: - explicit IECommerceInterface(Core::System& system_); - ~IECommerceInterface() override; -}; - -class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { -public: - explicit IFactoryResetInterface(Core::System& system_); - ~IFactoryResetInterface() override; -}; - -class IReadOnlyApplicationRecordInterface final - : public ServiceFramework<IReadOnlyApplicationRecordInterface> { -public: - explicit IReadOnlyApplicationRecordInterface(Core::System& system_); - ~IReadOnlyApplicationRecordInterface() override; - -private: - void HasApplicationRecord(HLERequestContext& ctx); - void IsDataCorruptedResult(HLERequestContext& ctx); -}; - -class IReadOnlyApplicationControlDataInterface final - : public ServiceFramework<IReadOnlyApplicationControlDataInterface> { -public: - explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); - ~IReadOnlyApplicationControlDataInterface() override; - -private: - void GetApplicationControlData(HLERequestContext& ctx); -}; - -class NS final : public ServiceFramework<NS> { -public: - explicit NS(const char* name, Core::System& system_); - ~NS() override; - - std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; - -private: - template <typename T, typename... Args> - void PushInterface(HLERequestContext& ctx) { - LOG_DEBUG(Service_NS, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<T>(system); - } - - void PushIApplicationManagerInterface(HLERequestContext& ctx) { - LOG_DEBUG(Service_NS, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationManagerInterface>(system); - } - - template <typename T, typename... Args> - std::shared_ptr<T> GetInterface(Args&&... args) const { - static_assert(std::is_base_of_v<SessionRequestHandler, T>, - "Not a base of ServiceFrameworkBase"); - - return std::make_shared<T>(std::forward<Args>(args)...); - } -}; +namespace Service::NS { void LoopProcess(Core::System& system); -} // namespace NS -} // namespace Service +} // namespace Service::NS diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/ns_results.h index 16d2ea6f7..16d2ea6f7 100644 --- a/src/core/hle/service/ns/errors.h +++ b/src/core/hle/service/ns/ns_results.h diff --git a/src/core/hle/service/ns/ns_types.h b/src/core/hle/service/ns/ns_types.h new file mode 100644 index 000000000..2dd664c4e --- /dev/null +++ b/src/core/hle/service/ns/ns_types.h @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_funcs.h" +#include "common/uuid.h" +#include "core/file_sys/romfs_factory.h" + +namespace Service::NS { + +enum class ApplicationRecordType : u8 { + Installing = 2, + Installed = 3, + GameCardNotInserted = 5, + Archived = 11, + GameCard = 16, +}; + +enum class ApplicationControlSource : u8 { + CacheOnly = 0, + Storage = 1, + StorageOnly = 2, +}; + +enum class BackgroundNetworkUpdateState : u8 { + None, + InProgress, + Ready, +}; + +struct ApplicationRecord { + u64 application_id; + ApplicationRecordType type; + u8 unknown; + INSERT_PADDING_BYTES_NOINIT(0x6); + u8 unknown2; + INSERT_PADDING_BYTES_NOINIT(0x7); +}; +static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord has incorrect size."); + +/// ApplicationView +struct ApplicationView { + u64 application_id; ///< ApplicationId. + u32 unk; ///< Unknown. + u32 flags; ///< Flags. + std::array<u8, 0x10> unk_x10; ///< Unknown. + u32 unk_x20; ///< Unknown. + u16 unk_x24; ///< Unknown. + std::array<u8, 0x2> unk_x26; ///< Unknown. + std::array<u8, 0x8> unk_x28; ///< Unknown. + std::array<u8, 0x10> unk_x30; ///< Unknown. + u32 unk_x40; ///< Unknown. + u8 unk_x44; ///< Unknown. + std::array<u8, 0xb> unk_x45; ///< Unknown. +}; +static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size."); + +struct ApplicationRightsOnClient { + u64 application_id; + Common::UUID uid; + u8 flags; + u8 flags2; + INSERT_PADDING_BYTES_NOINIT(0x6); +}; +static_assert(sizeof(ApplicationRightsOnClient) == 0x20, + "ApplicationRightsOnClient has incorrect size."); + +/// NsPromotionInfo +struct PromotionInfo { + u64 start_timestamp; ///< POSIX timestamp for the promotion start. + u64 end_timestamp; ///< POSIX timestamp for the promotion end. + s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds + ///< ({end_timestamp - current_time} converted to nanoseconds). + INSERT_PADDING_BYTES_NOINIT(0x4); + u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear: + ///< remaining_time is set. + INSERT_PADDING_BYTES_NOINIT(0x3); +}; +static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size."); + +/// NsApplicationViewWithPromotionInfo +struct ApplicationViewWithPromotionInfo { + ApplicationView view; ///< \ref NsApplicationView + PromotionInfo promotion; ///< \ref NsPromotionInfo +}; +static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x70, + "ApplicationViewWithPromotionInfo has incorrect size."); + +struct ApplicationOccupiedSizeEntity { + FileSys::StorageId storage_id; + u64 app_size; + u64 patch_size; + u64 aoc_size; +}; +static_assert(sizeof(ApplicationOccupiedSizeEntity) == 0x20, + "ApplicationOccupiedSizeEntity has incorrect size."); + +struct ApplicationOccupiedSize { + std::array<ApplicationOccupiedSizeEntity, 4> entities; +}; +static_assert(sizeof(ApplicationOccupiedSize) == 0x80, + "ApplicationOccupiedSize has incorrect size."); + +struct ContentPath { + u8 file_system_proxy_type; + u64 program_id; +}; +static_assert(sizeof(ContentPath) == 0x10, "ContentPath has incorrect size."); + +struct Uid { + alignas(8) Common::UUID uuid; +}; +static_assert(sizeof(Uid) == 0x10, "Uid has incorrect size."); + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp deleted file mode 100644 index ce0ee30e0..000000000 --- a/src/core/hle/service/ns/pdm_qry.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <memory> - -#include "common/logging/log.h" -#include "common/uuid.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/ns/pdm_qry.h" -#include "core/hle/service/service.h" - -namespace Service::NS { - -PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "QueryAppletEvent"}, - {1, nullptr, "QueryPlayStatistics"}, - {2, nullptr, "QueryPlayStatisticsByUserAccountId"}, - {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"}, - {4, nullptr, "QueryPlayStatisticsByApplicationId"}, - {5, &PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId, "QueryPlayStatisticsByApplicationIdAndUserAccountId"}, - {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"}, - {7, nullptr, "QueryLastPlayTimeV0"}, - {8, nullptr, "QueryPlayEvent"}, - {9, nullptr, "GetAvailablePlayEventRange"}, - {10, nullptr, "QueryAccountEvent"}, - {11, nullptr, "QueryAccountPlayEvent"}, - {12, nullptr, "GetAvailableAccountPlayEventRange"}, - {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"}, - {14, nullptr, "QueryRecentlyPlayedApplication"}, - {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"}, - {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"}, - {17, nullptr, "QueryLastPlayTime"}, - {18, nullptr, "QueryApplicationPlayStatisticsForSystem"}, - {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -PDM_QRY::~PDM_QRY() = default; - -void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto unknown = rp.Pop<bool>(); - rp.Pop<u8>(); // Padding - const auto application_id = rp.Pop<u64>(); - const auto user_account_uid = rp.PopRaw<Common::UUID>(); - - // TODO(German77): Read statistics of the game - PlayStatistics statistics{ - .application_id = application_id, - .total_launches = 1, - }; - - LOG_WARNING(Service_NS, - "(STUBBED) called. unknown={}. application_id=0x{:016X}, user_account_uid=0x{}", - unknown, application_id, user_account_uid.RawString()); - - IPC::ResponseBuilder rb{ctx, 12}; - rb.Push(ResultSuccess); - rb.PushRaw(statistics); -} - -} // namespace Service::NS diff --git a/src/core/hle/service/ns/pdm_qry.h b/src/core/hle/service/ns/pdm_qry.h deleted file mode 100644 index c98e01660..000000000 --- a/src/core/hle/service/ns/pdm_qry.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service::NS { - -struct PlayStatistics { - u64 application_id{}; - u32 first_entry_index{}; - u32 first_timestamp_user{}; - u32 first_timestamp_network{}; - u32 last_entry_index{}; - u32 last_timestamp_user{}; - u32 last_timestamp_network{}; - u32 play_time_in_minutes{}; - u32 total_launches{}; -}; -static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size"); - -class PDM_QRY final : public ServiceFramework<PDM_QRY> { -public: - explicit PDM_QRY(Core::System& system_); - ~PDM_QRY() override; - -private: - void QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx); -}; - -} // namespace Service::NS diff --git a/src/core/hle/service/ns/platform_service_manager.cpp b/src/core/hle/service/ns/platform_service_manager.cpp new file mode 100644 index 000000000..23cf05005 --- /dev/null +++ b/src/core/hle/service/ns/platform_service_manager.cpp @@ -0,0 +1,273 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <algorithm> +#include <cstring> +#include <vector> + +#include "common/assert.h" +#include "common/common_types.h" +#include "common/logging/log.h" +#include "common/swap.h" +#include "core/core.h" +#include "core/file_sys/content_archive.h" +#include "core/file_sys/nca_metadata.h" +#include "core/file_sys/registered_cache.h" +#include "core/file_sys/romfs.h" +#include "core/file_sys/system_archive/system_archive.h" +#include "core/hle/kernel/k_shared_memory.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_memory.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/platform_service_manager.h" + +namespace Service::NS { + +struct FontRegion { + u32 offset; + u32 size; +}; + +// The below data is specific to shared font data dumped from Switch on f/w 2.2 +// Virtual address and offsets/sizes likely will vary by dump +[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL}; +constexpr u32 EXPECTED_RESULT{0x7f9a0218}; // What we expect the decrypted bfttf first 4 bytes to be +constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf first 4 bytes to be +constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000}; +constexpr FontRegion EMPTY_REGION{0, 0}; + +static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMemory& output, + std::size_t& offset) { + ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, + "Shared fonts exceeds 17mb!"); + ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); + + const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor + std::vector<u32> transformed_font(input.size()); + // TODO(ogniK): Figure out a better way to do this + std::transform(input.begin(), input.end(), transformed_font.begin(), + [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); + transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size + std::memcpy(output.data() + offset, transformed_font.data(), + transformed_font.size() * sizeof(u32)); + offset += transformed_font.size() * sizeof(u32); +} + +void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) { + ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); + + if (input.size() < 2) { + LOG_ERROR(Service_NS, "Input font is empty"); + return; + } + + const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor + std::vector<u32> transformed_font(input.size()); + // TODO(ogniK): Figure out a better way to do this + std::transform(input.begin(), input.end(), transformed_font.begin(), + [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); + std::memcpy(output.data(), transformed_font.data() + 2, + (transformed_font.size() - 2) * sizeof(u32)); +} + +void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, + std::size_t& offset) { + ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, + "Shared fonts exceeds 17mb!"); + + const auto key = Common::swap32(EXPECTED_RESULT ^ EXPECTED_MAGIC); + std::vector<u32> transformed_font(input.size() + 2); + transformed_font[0] = Common::swap32(EXPECTED_MAGIC); + transformed_font[1] = Common::swap32(static_cast<u32>(input.size() * sizeof(u32))) ^ key; + std::transform(input.begin(), input.end(), transformed_font.begin() + 2, + [key](u32 in) { return in ^ key; }); + std::memcpy(output.data() + offset, transformed_font.data(), + transformed_font.size() * sizeof(u32)); + offset += transformed_font.size() * sizeof(u32); +} + +// Helper function to make BuildSharedFontsRawRegions a bit nicer +static u32 GetU32Swapped(const u8* data) { + u32 value; + std::memcpy(&value, data, sizeof(value)); + return Common::swap32(value); +} + +struct IPlatformServiceManager::Impl { + const FontRegion& GetSharedFontRegion(std::size_t index) const { + if (index >= shared_font_regions.size() || shared_font_regions.empty()) { + // No font fallback + return EMPTY_REGION; + } + return shared_font_regions.at(index); + } + + void BuildSharedFontsRawRegions(const Kernel::PhysicalMemory& input) { + // As we can derive the xor key we can just populate the offsets + // based on the shared memory dump + unsigned cur_offset = 0; + + for (std::size_t i = 0; i < SHARED_FONTS.size(); i++) { + // Out of shared fonts/invalid font + if (GetU32Swapped(input.data() + cur_offset) != EXPECTED_RESULT) { + break; + } + + // Derive key within inverse xor + const u32 KEY = GetU32Swapped(input.data() + cur_offset) ^ EXPECTED_MAGIC; + const u32 SIZE = GetU32Swapped(input.data() + cur_offset + 4) ^ KEY; + shared_font_regions.push_back(FontRegion{cur_offset + 8, SIZE}); + cur_offset += SIZE + 8; + } + } + + /// Backing memory for the shared font data + std::shared_ptr<Kernel::PhysicalMemory> shared_font; + + // Automatically populated based on shared_fonts dump or system archives. + std::vector<FontRegion> shared_font_regions; +}; + +IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_) + : ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IPlatformServiceManager::RequestLoad>, "RequestLoad"}, + {1, D<&IPlatformServiceManager::GetLoadState>, "GetLoadState"}, + {2, D<&IPlatformServiceManager::GetSize>, "GetSize"}, + {3, D<&IPlatformServiceManager::GetSharedMemoryAddressOffset>, "GetSharedMemoryAddressOffset"}, + {4, D<&IPlatformServiceManager::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"}, + {5, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriority"}, + {6, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriorityForSystem"}, + {100, nullptr, "RequestApplicationFunctionAuthorization"}, + {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, + {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, + {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"}, + {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"}, + {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"}, + {106, nullptr, "GetFunctionBlackListVersion"}, + {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"}, + {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"}, + }; + // clang-format on + RegisterHandlers(functions); + + auto& fsc = system.GetFileSystemController(); + + // Attempt to load shared font data from disk + const auto* nand = fsc.GetSystemNANDContents(); + std::size_t offset = 0; + // Rebuild shared fonts from data ncas or synthesize + + impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE); + for (auto font : SHARED_FONTS) { + FileSys::VirtualFile romfs; + const auto nca = + nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data); + if (nca) { + romfs = nca->GetRomFS(); + } + + if (!romfs) { + romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast<u64>(font.first)); + } + + if (!romfs) { + LOG_ERROR(Service_NS, "Failed to find or synthesize {:016X}! Skipping", font.first); + continue; + } + + const auto extracted_romfs = FileSys::ExtractRomFS(romfs); + if (!extracted_romfs) { + LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping", font.first); + continue; + } + const auto font_fp = extracted_romfs->GetFile(font.second); + if (!font_fp) { + LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping", font.first, font.second); + continue; + } + std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32)); + font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize()); + // We need to be BigEndian as u32s for the xor encryption + std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(), + Common::swap32); + // Font offset and size do not account for the header + const FontRegion region{static_cast<u32>(offset + 8), + static_cast<u32>((font_data_u32.size() * sizeof(u32)) - 8)}; + DecryptSharedFont(font_data_u32, *impl->shared_font, offset); + impl->shared_font_regions.push_back(region); + } +} + +IPlatformServiceManager::~IPlatformServiceManager() = default; + +Result IPlatformServiceManager::RequestLoad(SharedFontType type) { + // Games don't call this so all fonts should be loaded + LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetLoadState(Out<LoadState> out_load_state, SharedFontType type) { + LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); + *out_load_state = LoadState::Loaded; + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetSize(Out<u32> out_size, SharedFontType type) { + LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); + *out_size = impl->GetSharedFontRegion(static_cast<size_t>(type)).size; + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, + SharedFontType type) { + LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); + *out_shared_memory_offset = impl->GetSharedFontRegion(static_cast<size_t>(type)).offset; + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetSharedMemoryNativeHandle( + OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle) { + // Map backing memory for the font data + LOG_DEBUG(Service_NS, "called"); + + // Create shared font memory object + std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(), + impl->shared_font->size()); + + // FIXME: this shouldn't belong to the kernel + *out_shared_memory_native_handle = &kernel.GetFontSharedMem(); + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetSharedFontInOrderOfPriority( + OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes, + OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets, + OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, Out<bool> out_fonts_are_loaded, + Out<u32> out_font_count, Set::LanguageCode language_code) { + LOG_DEBUG(Service_NS, "called, language_code={:#x}", language_code); + + // The maximum number of elements that can be returned is 6. Regardless of the available fonts + // or buffer size. + constexpr size_t MaxElementCount = 6; + + // TODO(ogniK): Have actual priority order + const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(), + out_font_sizes.size(), impl->shared_font_regions.size()}); + + for (size_t i = 0; i < max_size; i++) { + auto region = impl->GetSharedFontRegion(i); + + out_font_codes[i] = static_cast<u32>(i); + out_font_offsets[i] = region.offset; + out_font_sizes[i] = region.size; + } + + *out_fonts_are_loaded = true; + *out_font_count = static_cast<u32>(max_size); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/platform_service_manager.h b/src/core/hle/service/ns/platform_service_manager.h new file mode 100644 index 000000000..b82c385a6 --- /dev/null +++ b/src/core/hle/service/ns/platform_service_manager.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <memory> +#include <vector> +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" +#include "core/hle/service/set/settings_types.h" + +namespace Service { + +namespace FileSystem { +class FileSystemController; +} // namespace FileSystem + +namespace NS { + +enum class FontArchives : u64 { + Extension = 0x0100000000000810, + Standard = 0x0100000000000811, + Korean = 0x0100000000000812, + ChineseTraditional = 0x0100000000000813, + ChineseSimple = 0x0100000000000814, +}; + +enum class SharedFontType : u32 { + JapanUSEuropeStandard = 0, + ChineseSimplified = 1, + ExtendedChineseSimplified = 2, + ChineseTraditional = 3, + KoreanHangul = 4, + NintendoExtended = 5, +}; + +enum class LoadState : u32 { + Loading = 0, + Loaded = 1, +}; + +constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{ + std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"), + std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"), + std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"), + std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"), + std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"), + std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"), + std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"), +}; + +void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output); +void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); + +class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> { +public: + explicit IPlatformServiceManager(Core::System& system_, const char* service_name_); + ~IPlatformServiceManager() override; + +private: + Result RequestLoad(SharedFontType type); + Result GetLoadState(Out<LoadState> out_load_state, SharedFontType type); + Result GetSize(Out<u32> out_size, SharedFontType type); + Result GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, SharedFontType type); + Result GetSharedMemoryNativeHandle( + OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle); + Result GetSharedFontInOrderOfPriority(OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes, + OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets, + OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, + Out<bool> out_fonts_are_loaded, Out<u32> out_font_count, + Set::LanguageCode language_code); + + struct Impl; + std::unique_ptr<Impl> impl; +}; + +} // namespace NS + +} // namespace Service diff --git a/src/core/hle/service/ns/query_service.cpp b/src/core/hle/service/ns/query_service.cpp new file mode 100644 index 000000000..138400541 --- /dev/null +++ b/src/core/hle/service/ns/query_service.cpp @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "common/uuid.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/query_service.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "QueryAppletEvent"}, + {1, nullptr, "QueryPlayStatistics"}, + {2, nullptr, "QueryPlayStatisticsByUserAccountId"}, + {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"}, + {4, nullptr, "QueryPlayStatisticsByApplicationId"}, + {5, D<&IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId>, "QueryPlayStatisticsByApplicationIdAndUserAccountId"}, + {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"}, + {7, nullptr, "QueryLastPlayTimeV0"}, + {8, nullptr, "QueryPlayEvent"}, + {9, nullptr, "GetAvailablePlayEventRange"}, + {10, nullptr, "QueryAccountEvent"}, + {11, nullptr, "QueryAccountPlayEvent"}, + {12, nullptr, "GetAvailableAccountPlayEventRange"}, + {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"}, + {14, nullptr, "QueryRecentlyPlayedApplication"}, + {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"}, + {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"}, + {17, nullptr, "QueryLastPlayTime"}, + {18, nullptr, "QueryApplicationPlayStatisticsForSystem"}, + {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IQueryService::~IQueryService() = default; + +Result IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId( + Out<PlayStatistics> out_play_statistics, bool unknown, u64 application_id, Uid account_id) { + // TODO(German77): Read statistics of the game + *out_play_statistics = { + .application_id = application_id, + .total_launches = 1, + }; + + LOG_WARNING(Service_NS, "(STUBBED) called. unknown={}. application_id={:016X}, account_id={}", + unknown, application_id, account_id.uuid.FormattedString()); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/query_service.h b/src/core/hle/service/ns/query_service.h new file mode 100644 index 000000000..c4c82b752 --- /dev/null +++ b/src/core/hle/service/ns/query_service.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/uuid.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +struct PlayStatistics { + u64 application_id{}; + u32 first_entry_index{}; + u32 first_timestamp_user{}; + u32 first_timestamp_network{}; + u32 last_entry_index{}; + u32 last_timestamp_user{}; + u32 last_timestamp_network{}; + u32 play_time_in_minutes{}; + u32 total_launches{}; +}; +static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size"); + +class IQueryService final : public ServiceFramework<IQueryService> { +public: + explicit IQueryService(Core::System& system_); + ~IQueryService() override; + +private: + Result QueryPlayStatisticsByApplicationIdAndUserAccountId( + Out<PlayStatistics> out_play_statistics, bool unknown, u64 application_id, Uid account_id); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp new file mode 100644 index 000000000..9b2ca94a4 --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/vfs/vfs.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/ns_results.h" +#include "core/hle/service/ns/read_only_application_control_data_interface.h" +#include "core/hle/service/set/settings_server.h" + +namespace Service::NS { + +IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface( + Core::System& system_) + : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"}, + {1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"}, + {2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"}, + {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, + {4, nullptr, "SelectApplicationDesiredLanguage"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default; + +Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData( + OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size, + ApplicationControlSource application_control_source, u64 application_id) { + LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}", + application_control_source, application_id); + + const FileSys::PatchManager pm{application_id, system.GetFileSystemController(), + system.GetContentProvider()}; + const auto control = pm.GetControlMetadata(); + const auto size = out_buffer.size(); + + const auto icon_size = control.second ? control.second->GetSize() : 0; + const auto total_size = sizeof(FileSys::RawNACP) + icon_size; + + if (size < total_size) { + LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)", + size); + R_THROW(ResultUnknown); + } + + if (control.first != nullptr) { + const auto bytes = control.first->GetRawBytes(); + std::memcpy(out_buffer.data(), bytes.data(), bytes.size()); + } else { + LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero", + application_id); + std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP)); + } + + if (control.second != nullptr) { + control.second->Read(out_buffer.data() + sizeof(FileSys::RawNACP), icon_size); + } else { + LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id); + } + + *out_actual_size = static_cast<u32>(total_size); + R_SUCCEED(); +} + +Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage( + Out<ApplicationLanguage> out_desired_language, u32 supported_languages) { + LOG_INFO(Service_NS, "called with supported_languages={:08X}", supported_languages); + + // Get language code from settings + const auto language_code = + Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue())); + + // Convert to application language, get priority list + const auto application_language = ConvertToApplicationLanguage(language_code); + if (application_language == std::nullopt) { + LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", + language_code); + R_THROW(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); + R_THROW(Service::NS::ResultApplicationLanguageNotFound); + } + + // Try to find a valid language. + for (const auto lang : *priority_list) { + const auto supported_flag = GetSupportedLanguageFlag(lang); + if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { + *out_desired_language = lang; + R_SUCCEED(); + } + } + + LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}", + supported_languages); + R_THROW(Service::NS::ResultApplicationLanguageNotFound); +} + +Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode( + Out<u64> out_language_code, ApplicationLanguage application_language) { + const auto language_code = ConvertToLanguageCode(application_language); + if (language_code == std::nullopt) { + LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language); + R_THROW(Service::NS::ResultApplicationLanguageNotFound); + } + + *out_language_code = static_cast<u64>(*language_code); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.h b/src/core/hle/service/ns/read_only_application_control_data_interface.h new file mode 100644 index 000000000..ac099435a --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/ns/language.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IReadOnlyApplicationControlDataInterface final + : public ServiceFramework<IReadOnlyApplicationControlDataInterface> { +public: + explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); + ~IReadOnlyApplicationControlDataInterface() override; + +public: + Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, + Out<u32> out_actual_size, + ApplicationControlSource application_control_source, + u64 application_id); + Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language, + u32 supported_languages); + Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code, + ApplicationLanguage application_language); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_record_interface.cpp b/src/core/hle/service/ns/read_only_application_record_interface.cpp new file mode 100644 index 000000000..816a1e1dc --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_record_interface.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/read_only_application_record_interface.h" + +namespace Service::NS { + +IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_) + : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} { + static const FunctionInfo functions[] = { + {0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"}, + {1, nullptr, "NotifyApplicationFailure"}, + {2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>, + "IsDataCorruptedResult"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default; + +Result IReadOnlyApplicationRecordInterface::HasApplicationRecord( + Out<bool> out_has_application_record, u64 program_id) { + LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:016X}", program_id); + *out_has_application_record = true; + R_SUCCEED(); +} + +Result IReadOnlyApplicationRecordInterface::IsDataCorruptedResult( + Out<bool> out_is_data_corrupted_result, Result result) { + LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); + *out_is_data_corrupted_result = false; + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/read_only_application_record_interface.h b/src/core/hle/service/ns/read_only_application_record_interface.h new file mode 100644 index 000000000..d06e8f5e6 --- /dev/null +++ b/src/core/hle/service/ns/read_only_application_record_interface.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IReadOnlyApplicationRecordInterface final + : public ServiceFramework<IReadOnlyApplicationRecordInterface> { +public: + explicit IReadOnlyApplicationRecordInterface(Core::System& system_); + ~IReadOnlyApplicationRecordInterface() override; + +private: + Result HasApplicationRecord(Out<bool> out_has_application_record, u64 program_id); + Result IsDataCorruptedResult(Out<bool> out_is_data_corrupted_result, Result result); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/service_getter_interface.cpp b/src/core/hle/service/ns/service_getter_interface.cpp new file mode 100644 index 000000000..1a3dd7166 --- /dev/null +++ b/src/core/hle/service/ns/service_getter_interface.cpp @@ -0,0 +1,120 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/account_proxy_interface.h" +#include "core/hle/service/ns/application_manager_interface.h" +#include "core/hle/service/ns/application_version_interface.h" +#include "core/hle/service/ns/content_management_interface.h" +#include "core/hle/service/ns/document_interface.h" +#include "core/hle/service/ns/download_task_interface.h" +#include "core/hle/service/ns/dynamic_rights_interface.h" +#include "core/hle/service/ns/ecommerce_interface.h" +#include "core/hle/service/ns/factory_reset_interface.h" +#include "core/hle/service/ns/read_only_application_control_data_interface.h" +#include "core/hle/service/ns/read_only_application_record_interface.h" +#include "core/hle/service/ns/service_getter_interface.h" + +namespace Service::NS { + +IServiceGetterInterface::IServiceGetterInterface(Core::System& system_, const char* name) + : ServiceFramework{system_, name} { + // clang-format off + static const FunctionInfo functions[] = { + {7988, D<&IServiceGetterInterface::GetDynamicRightsInterface>, "GetDynamicRightsInterface"}, + {7989, D<&IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"}, + {7991, D<&IServiceGetterInterface::GetReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"}, + {7992, D<&IServiceGetterInterface::GetECommerceInterface>, "GetECommerceInterface"}, + {7993, D<&IServiceGetterInterface::GetApplicationVersionInterface>, "GetApplicationVersionInterface"}, + {7994, D<&IServiceGetterInterface::GetFactoryResetInterface>, "GetFactoryResetInterface"}, + {7995, D<&IServiceGetterInterface::GetAccountProxyInterface>, "GetAccountProxyInterface"}, + {7996, D<&IServiceGetterInterface::GetApplicationManagerInterface>, "GetApplicationManagerInterface"}, + {7997, D<&IServiceGetterInterface::GetDownloadTaskInterface>, "GetDownloadTaskInterface"}, + {7998, D<&IServiceGetterInterface::GetContentManagementInterface>, "GetContentManagementInterface"}, + {7999, D<&IServiceGetterInterface::GetDocumentInterface>, "GetDocumentInterface"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IServiceGetterInterface::~IServiceGetterInterface() = default; + +Result IServiceGetterInterface::GetDynamicRightsInterface( + Out<SharedPointer<IDynamicRightsInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IDynamicRightsInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface( + Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IReadOnlyApplicationControlDataInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetReadOnlyApplicationRecordInterface( + Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IReadOnlyApplicationRecordInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetECommerceInterface( + Out<SharedPointer<IECommerceInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IECommerceInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetApplicationVersionInterface( + Out<SharedPointer<IApplicationVersionInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IApplicationVersionInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetFactoryResetInterface( + Out<SharedPointer<IFactoryResetInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IFactoryResetInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetAccountProxyInterface( + Out<SharedPointer<IAccountProxyInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IAccountProxyInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetApplicationManagerInterface( + Out<SharedPointer<IApplicationManagerInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IApplicationManagerInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetDownloadTaskInterface( + Out<SharedPointer<IDownloadTaskInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IDownloadTaskInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetContentManagementInterface( + Out<SharedPointer<IContentManagementInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IContentManagementInterface>(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetDocumentInterface( + Out<SharedPointer<IDocumentInterface>> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared<IDocumentInterface>(system); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/service_getter_interface.h b/src/core/hle/service/ns/service_getter_interface.h new file mode 100644 index 000000000..bbc18d444 --- /dev/null +++ b/src/core/hle/service/ns/service_getter_interface.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IDynamicRightsInterface; +class IReadOnlyApplicationControlDataInterface; +class IReadOnlyApplicationRecordInterface; +class IECommerceInterface; +class IApplicationVersionInterface; +class IFactoryResetInterface; +class IAccountProxyInterface; +class IApplicationManagerInterface; +class IDownloadTaskInterface; +class IContentManagementInterface; +class IDocumentInterface; + +class IServiceGetterInterface : public ServiceFramework<IServiceGetterInterface> { +public: + explicit IServiceGetterInterface(Core::System& system_, const char* name); + ~IServiceGetterInterface() override; + +public: + Result GetDynamicRightsInterface(Out<SharedPointer<IDynamicRightsInterface>> out_interface); + Result GetReadOnlyApplicationControlDataInterface( + Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface); + Result GetReadOnlyApplicationRecordInterface( + Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface); + Result GetECommerceInterface(Out<SharedPointer<IECommerceInterface>> out_interface); + Result GetApplicationVersionInterface( + Out<SharedPointer<IApplicationVersionInterface>> out_interface); + Result GetFactoryResetInterface(Out<SharedPointer<IFactoryResetInterface>> out_interface); + Result GetAccountProxyInterface(Out<SharedPointer<IAccountProxyInterface>> out_interface); + Result GetApplicationManagerInterface( + Out<SharedPointer<IApplicationManagerInterface>> out_interface); + Result GetDownloadTaskInterface(Out<SharedPointer<IDownloadTaskInterface>> out_interface); + Result GetContentManagementInterface( + Out<SharedPointer<IContentManagementInterface>> out_interface); + Result GetDocumentInterface(Out<SharedPointer<IDocumentInterface>> out_interface); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_control.cpp b/src/core/hle/service/ns/system_update_control.cpp new file mode 100644 index 000000000..f5f5cfd90 --- /dev/null +++ b/src/core/hle/service/ns/system_update_control.cpp @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/system_update_control.h" + +namespace Service::NS { + +ISystemUpdateControl::ISystemUpdateControl(Core::System& system_) + : ServiceFramework{system_, "ISystemUpdateControl"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "HasDownloaded"}, + {1, nullptr, "RequestCheckLatestUpdate"}, + {2, nullptr, "RequestDownloadLatestUpdate"}, + {3, nullptr, "GetDownloadProgress"}, + {4, nullptr, "ApplyDownloadedUpdate"}, + {5, nullptr, "RequestPrepareCardUpdate"}, + {6, nullptr, "GetPrepareCardUpdateProgress"}, + {7, nullptr, "HasPreparedCardUpdate"}, + {8, nullptr, "ApplyCardUpdate"}, + {9, nullptr, "GetDownloadedEulaDataSize"}, + {10, nullptr, "GetDownloadedEulaData"}, + {11, nullptr, "SetupCardUpdate"}, + {12, nullptr, "GetPreparedCardUpdateEulaDataSize"}, + {13, nullptr, "GetPreparedCardUpdateEulaData"}, + {14, nullptr, "SetupCardUpdateViaSystemUpdater"}, + {15, nullptr, "HasReceived"}, + {16, nullptr, "RequestReceiveSystemUpdate"}, + {17, nullptr, "GetReceiveProgress"}, + {18, nullptr, "ApplyReceivedUpdate"}, + {19, nullptr, "GetReceivedEulaDataSize"}, + {20, nullptr, "GetReceivedEulaData"}, + {21, nullptr, "SetupToReceiveSystemUpdate"}, + {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISystemUpdateControl::~ISystemUpdateControl() = default; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_control.h b/src/core/hle/service/ns/system_update_control.h new file mode 100644 index 000000000..a30a09000 --- /dev/null +++ b/src/core/hle/service/ns/system_update_control.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::NS { + +class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> { +public: + explicit ISystemUpdateControl(Core::System& system_); + ~ISystemUpdateControl() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_interface.cpp b/src/core/hle/service/ns/system_update_interface.cpp new file mode 100644 index 000000000..7e22ca3db --- /dev/null +++ b/src/core/hle/service/ns/system_update_interface.cpp @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/system_update_control.h" +#include "core/hle/service/ns/system_update_interface.h" + +namespace Service::NS { + +ISystemUpdateInterface::ISystemUpdateInterface(Core::System& system_) + : ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"}, + update_notification_event{service_context} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&ISystemUpdateInterface::GetBackgroundNetworkUpdateState>, "GetBackgroundNetworkUpdateState"}, + {1, D<&ISystemUpdateInterface::OpenSystemUpdateControl>, "OpenSystemUpdateControl"}, + {2, nullptr, "NotifyExFatDriverRequired"}, + {3, nullptr, "ClearExFatDriverStatusForDebug"}, + {4, nullptr, "RequestBackgroundNetworkUpdate"}, + {5, nullptr, "NotifyBackgroundNetworkUpdate"}, + {6, nullptr, "NotifyExFatDriverDownloadedForDebug"}, + {9, D<&ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery>, "GetSystemUpdateNotificationEventForContentDelivery"}, + {10, nullptr, "NotifySystemUpdateForContentDelivery"}, + {11, nullptr, "PrepareShutdown"}, + {12, nullptr, "Unknown12"}, + {13, nullptr, "Unknown13"}, + {14, nullptr, "Unknown14"}, + {15, nullptr, "Unknown15"}, + {16, nullptr, "DestroySystemUpdateTask"}, + {17, nullptr, "RequestSendSystemUpdate"}, + {18, nullptr, "GetSendSystemUpdateProgress"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISystemUpdateInterface::~ISystemUpdateInterface() = default; + +Result ISystemUpdateInterface::GetBackgroundNetworkUpdateState( + Out<BackgroundNetworkUpdateState> out_background_network_update_state) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_background_network_update_state = BackgroundNetworkUpdateState::None; + R_SUCCEED(); +} + +Result ISystemUpdateInterface::OpenSystemUpdateControl( + Out<SharedPointer<ISystemUpdateControl>> out_system_update_control) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_system_update_control = std::make_shared<ISystemUpdateControl>(system); + R_SUCCEED(); +} + +Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_event = update_notification_event.GetHandle(); + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/system_update_interface.h b/src/core/hle/service/ns/system_update_interface.h new file mode 100644 index 000000000..36a2880ec --- /dev/null +++ b/src/core/hle/service/ns/system_update_interface.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/ns/ns_types.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::NS { + +class ISystemUpdateControl; + +class ISystemUpdateInterface final : public ServiceFramework<ISystemUpdateInterface> { +public: + explicit ISystemUpdateInterface(Core::System& system_); + ~ISystemUpdateInterface() override; + +private: + Result GetBackgroundNetworkUpdateState( + Out<BackgroundNetworkUpdateState> out_background_network_update_state); + Result OpenSystemUpdateControl( + Out<SharedPointer<ISystemUpdateControl>> out_system_update_control); + Result GetSystemUpdateNotificationEventForContentDelivery( + OutCopyHandle<Kernel::KReadableEvent> out_event); + +private: + KernelHelpers::ServiceContext service_context; + Event update_notification_event; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.cpp b/src/core/hle/service/ns/vulnerability_manager_interface.cpp new file mode 100644 index 000000000..69c21fb89 --- /dev/null +++ b/src/core/hle/service/ns/vulnerability_manager_interface.cpp @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ns/vulnerability_manager_interface.h" + +namespace Service::NS { + +IVulnerabilityManagerInterface::IVulnerabilityManagerInterface(Core::System& system_) + : ServiceFramework{system_, "ns:vm"} { + // clang-format off + static const FunctionInfo functions[] = { + {1200, D<&IVulnerabilityManagerInterface::NeedsUpdateVulnerability>, "NeedsUpdateVulnerability"}, + {1201, nullptr, "UpdateSafeSystemVersionForDebug"}, + {1202, nullptr, "GetSafeSystemVersion"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IVulnerabilityManagerInterface::~IVulnerabilityManagerInterface() = default; + +Result IVulnerabilityManagerInterface::NeedsUpdateVulnerability( + Out<bool> out_needs_update_vulnerability) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_needs_update_vulnerability = false; + R_SUCCEED(); +} + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.h b/src/core/hle/service/ns/vulnerability_manager_interface.h new file mode 100644 index 000000000..c689cf7ec --- /dev/null +++ b/src/core/hle/service/ns/vulnerability_manager_interface.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Service::NS { + +class IVulnerabilityManagerInterface final + : public ServiceFramework<IVulnerabilityManagerInterface> { +public: + explicit IVulnerabilityManagerInterface(Core::System& system_); + ~IVulnerabilityManagerInterface() override; + +private: + Result NeedsUpdateVulnerability(Out<bool> out_needs_update_vulnerability); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 250d01de3..0265d55f2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -92,11 +92,11 @@ NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_a bool must_unmark_fail = !is_allocation; const u32 event_id = params.value.raw; - SCOPE_EXIT({ + SCOPE_EXIT { if (must_unmark_fail) { events[event_id].fails = 0; } - }); + }; const u32 fence_id = static_cast<u32>(params.fence.id); diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index cb256e5b4..03eb507b9 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -42,7 +42,7 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) { module.service_context.CloseEvent(event); } -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { +void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); auto module = std::make_shared<Module>(system); const auto NvdrvInterfaceFactoryForApplication = [&, module] { @@ -62,7 +62,6 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules); server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting); server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); - nvnflinger.SetNVDrvInstance(module); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index c594f0e5e..b76f81e59 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -10,13 +10,11 @@ #include <span> #include <string> #include <unordered_map> -#include <vector> #include "common/common_types.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvnflinger/ui/fence.h" #include "core/hle/service/service.h" namespace Core { @@ -27,10 +25,6 @@ namespace Kernel { class KEvent; } -namespace Service::Nvnflinger { -class Nvnflinger; -} - namespace Service::Nvidia { namespace NvCore { @@ -99,7 +93,6 @@ public: private: friend class EventInterface; - friend class Service::Nvnflinger::Nvnflinger; /// Manages syncpoints on the host NvCore::Container container; @@ -118,6 +111,6 @@ private: std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders; }; -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); +void LoopProcess(Core::System& system); } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index ffe72f281..258970fd5 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -154,10 +154,10 @@ void NVDRV::Close(HLERequestContext& ctx) { void NVDRV::Initialize(HLERequestContext& ctx) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; - SCOPE_EXIT({ + SCOPE_EXIT { rb.Push(ResultSuccess); rb.PushEnum(NvResult::Success); - }); + }; if (is_initialized) { // No need to initialize again @@ -263,8 +263,10 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* } NVDRV::~NVDRV() { - auto& container = nvdrv->GetContainer(); - container.CloseSession(session_id); + if (is_initialized) { + auto& container = nvdrv->GetContainer(); + container.CloseSession(session_id); + } } } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index f2195ae1e..c72f92597 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h @@ -16,6 +16,10 @@ public: explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name); ~NVDRV() override; + std::shared_ptr<Module> GetModule() const { + return nvdrv; + } + private: void Open(HLERequestContext& ctx); void Ioctl1(HLERequestContext& ctx); diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h index aef1477e3..124accb94 100644 --- a/src/core/hle/service/nvnflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h @@ -6,6 +6,8 @@ #pragma once +#include <span> + #include "common/common_types.h" namespace Kernel { @@ -18,28 +20,12 @@ class HLERequestContext; namespace Service::android { -enum class TransactionId { - RequestBuffer = 1, - SetBufferCount = 2, - DequeueBuffer = 3, - DetachBuffer = 4, - DetachNextBuffer = 5, - AttachBuffer = 6, - QueueBuffer = 7, - CancelBuffer = 8, - Query = 9, - Connect = 10, - Disconnect = 11, - AllocateBuffers = 13, - SetPreallocatedBuffer = 14, - GetBufferHistory = 17, -}; - class IBinder { public: virtual ~IBinder() = default; - virtual void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 0; - virtual Kernel::KReadableEvent& GetNativeHandle() = 0; + virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, + u32 flags) = 0; + virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0; }; } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp index cf151ea3a..123507123 100644 --- a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp @@ -12,7 +12,7 @@ namespace Service::android { -BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_) +BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_) : ConsumerBase{std::move(consumer_)} {} Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.h b/src/core/hle/service/nvnflinger/buffer_item_consumer.h index e0c6b3604..9f95c9280 100644 --- a/src/core/hle/service/nvnflinger/buffer_item_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.h @@ -19,7 +19,7 @@ class BufferItem; class BufferItemConsumer final : public ConsumerBase { public: - explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer); + explicit BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer); Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, bool wait_for_fence = true); Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence); diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index bbe8e06d4..3bc23aa97 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -4,12 +4,13 @@ // Parts of this implementation were based on: // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp +#include "common/assert.h" #include "common/logging/log.h" #include "core/hle/service/nvnflinger/buffer_item.h" #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/parcel.h" #include "core/hle/service/nvnflinger/producer_listener.h" -#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" namespace Service::android { @@ -254,4 +255,77 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { return Status::NoError; } +void BufferQueueConsumer::Transact(u32 code, std::span<const u8> parcel_data, + std::span<u8> parcel_reply, u32 flags) { + // Values used by BnGraphicBufferConsumer onTransact + enum class TransactionId { + AcquireBuffer = 1, + DetachBuffer = 2, + AttachBuffer = 3, + ReleaseBuffer = 4, + ConsumerConnect = 5, + ConsumerDisconnect = 6, + GetReleasedBuffers = 7, + SetDefaultBufferSize = 8, + SetDefaultMaxBufferCount = 9, + DisableAsyncBuffer = 10, + SetMaxAcquiredBufferCount = 11, + SetConsumerName = 12, + SetDefaultBufferFormat = 13, + SetConsumerUsageBits = 14, + SetTransformHint = 15, + GetSidebandStream = 16, + Unknown18 = 18, + Unknown20 = 20, + }; + + Status status{Status::NoError}; + InputParcel parcel_in{parcel_data}; + OutputParcel parcel_out{}; + + switch (static_cast<TransactionId>(code)) { + case TransactionId::AcquireBuffer: { + BufferItem item; + const s64 present_when = parcel_in.Read<s64>(); + + status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when}); + + // TODO: can't write this directly, needs a flattener for the sp<GraphicBuffer> + // parcel_out.WriteFlattened(item); + UNREACHABLE(); + } + case TransactionId::ReleaseBuffer: { + const s32 slot = parcel_in.Read<s32>(); + const u64 frame_number = parcel_in.Read<u64>(); + const auto release_fence = parcel_in.ReadFlattened<Fence>(); + + status = ReleaseBuffer(slot, frame_number, release_fence); + + break; + } + case TransactionId::GetReleasedBuffers: { + u64 slot_mask = 0; + + status = GetReleasedBuffers(&slot_mask); + + parcel_out.Write(slot_mask); + break; + } + default: + ASSERT_MSG(false, "called, code={} flags={}", code, flags); + break; + } + + parcel_out.Write(status); + + const auto serialized = parcel_out.Serialize(); + std::memcpy(parcel_reply.data(), serialized.data(), + std::min(parcel_reply.size(), serialized.size())); +} + +Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) { + ASSERT_MSG(false, "called, type_id={}", type_id); + return nullptr; +} + } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h index 0a61e8dbd..a9226f1c3 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h @@ -10,6 +10,7 @@ #include <memory> #include "common/common_types.h" +#include "core/hle/service/nvnflinger/binder.h" #include "core/hle/service/nvnflinger/buffer_queue_defs.h" #include "core/hle/service/nvnflinger/status.h" @@ -19,10 +20,10 @@ class BufferItem; class BufferQueueCore; class IConsumerListener; -class BufferQueueConsumer final { +class BufferQueueConsumer final : public IBinder { public: explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); - ~BufferQueueConsumer(); + ~BufferQueueConsumer() override; Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); @@ -30,6 +31,11 @@ public: Status Disconnect(); Status GetReleasedBuffers(u64* out_slot_mask); + void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, + u32 flags) override; + + Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; + private: std::shared_ptr<BufferQueueCore> core; BufferQueueDefs::SlotsType& slots; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 5d8762d25..9e5091eeb 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -6,12 +6,9 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "common/settings.h" -#include "core/core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/service/hle_ipc.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/buffer_queue_producer.h" @@ -19,7 +16,6 @@ #include "core/hle/service/nvnflinger/parcel.h" #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" #include "core/hle/service/nvnflinger/window.h" -#include "core/hle/service/vi/vi.h" namespace Service::android { @@ -807,12 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, return Status::NoError; } -void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) { +void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data, + std::span<u8> parcel_reply, u32 flags) { + // Values used by BnGraphicBufferProducer onTransact + enum class TransactionId { + RequestBuffer = 1, + SetBufferCount = 2, + DequeueBuffer = 3, + DetachBuffer = 4, + DetachNextBuffer = 5, + AttachBuffer = 6, + QueueBuffer = 7, + CancelBuffer = 8, + Query = 9, + Connect = 10, + Disconnect = 11, + AllocateBuffers = 13, + SetPreallocatedBuffer = 14, + GetBufferHistory = 17, + }; + Status status{Status::NoError}; - InputParcel parcel_in{ctx.ReadBuffer()}; + InputParcel parcel_in{parcel_data}; OutputParcel parcel_out{}; - switch (code) { + switch (static_cast<TransactionId>(code)) { case TransactionId::Connect: { const auto enable_listener = parcel_in.Read<bool>(); const auto api = parcel_in.Read<NativeWindowApi>(); @@ -917,11 +932,13 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u parcel_out.Write(status); - ctx.WriteBuffer(parcel_out.Serialize()); + const auto serialized = parcel_out.Serialize(); + std::memcpy(parcel_reply.data(), serialized.data(), + std::min(parcel_reply.size(), serialized.size())); } -Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { - return buffer_wait_event->GetReadableEvent(); +Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) { + return &buffer_wait_event->GetReadableEvent(); } } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 64c17d56c..048523514 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -45,11 +45,12 @@ public: explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, std::shared_ptr<BufferQueueCore> buffer_queue_core_, Service::Nvidia::NvCore::NvMap& nvmap_); - ~BufferQueueProducer(); + ~BufferQueueProducer() override; - void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) override; + void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, + u32 flags) override; - Kernel::KReadableEvent& GetNativeHandle() override; + Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; public: Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf); diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp index 1059e72bf..e360ebfd8 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.cpp +++ b/src/core/hle/service/nvnflinger/consumer_base.cpp @@ -14,7 +14,7 @@ namespace Service::android { -ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_) +ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_) : consumer{std::move(consumer_)} {} ConsumerBase::~ConsumerBase() { diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h index ea3e9e97a..b29c16f86 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.h +++ b/src/core/hle/service/nvnflinger/consumer_base.h @@ -27,7 +27,7 @@ public: void Abandon(); protected: - explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); + explicit ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_); ~ConsumerBase() override; void OnFrameAvailable(const BufferItem& item) override; @@ -54,7 +54,7 @@ protected: bool is_abandoned{}; - std::unique_ptr<BufferQueueConsumer> consumer; + std::shared_ptr<BufferQueueConsumer> consumer; mutable std::mutex mutex; }; diff --git a/src/core/hle/service/nvnflinger/display.h b/src/core/hle/service/nvnflinger/display.h new file mode 100644 index 000000000..40aa59787 --- /dev/null +++ b/src/core/hle/service/nvnflinger/display.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/nvnflinger/buffer_item_consumer.h" +#include "core/hle/service/nvnflinger/hwc_layer.h" + +namespace Service::Nvnflinger { + +struct Layer { + explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_, + s32 consumer_id_) + : buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_), + blending(LayerBlending::None), visible(true) {} + ~Layer() { + buffer_item_consumer->Abandon(); + } + + std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer; + s32 consumer_id; + LayerBlending blending; + bool visible; +}; + +struct LayerStack { + std::vector<std::shared_ptr<Layer>> layers; + + std::shared_ptr<Layer> FindLayer(s32 consumer_id) { + for (auto& layer : layers) { + if (layer->consumer_id == consumer_id) { + return layer; + } + } + + return nullptr; + } + + bool HasLayers() { + return !layers.empty(); + } +}; + +struct Display { + explicit Display(u64 id_) { + id = id_; + } + + u64 id; + LayerStack stack; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp deleted file mode 100644 index 90f7248a0..000000000 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ /dev/null @@ -1,447 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <random> - -#include "core/core.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_system_resource.h" -#include "core/hle/service/nvdrv/devices/nvmap.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/buffer_queue_producer.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/pixel_format.h" -#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/layer/vi_layer.h" -#include "core/hle/service/vi/vi_results.h" -#include "video_core/gpu.h" -#include "video_core/host1x/host1x.h" - -namespace Service::Nvnflinger { - -namespace { - -Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group, - Core::System& system, u32 size) { - using Core::Memory::YUZU_PAGESIZE; - - // Allocate memory for the system shared buffer. - // FIXME: This memory belongs to vi's .data section. - auto& kernel = system.Kernel(); - - // Hold a temporary page group reference while we try to map it. - auto pg = std::make_unique<Kernel::KPageGroup>( - kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); - - // Allocate memory from secure pool. - R_TRY(kernel.MemoryManager().AllocateAndOpen( - pg.get(), size / YUZU_PAGESIZE, - Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure, - Kernel::KMemoryManager::Direction::FromBack))); - - // Fill the output data with red. - for (auto& block : *pg) { - u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress()); - u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize()); - - for (; start < end; start++) { - *start = 0xFF0000FF; - } - } - - // Return the mapped page group. - *out_page_group = std::move(pg); - - // We succeeded. - R_SUCCEED(); -} - -Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address, - std::unique_ptr<Kernel::KPageGroup>& pg, - Kernel::KProcess* process, Core::System& system) { - using Core::Memory::YUZU_PAGESIZE; - - auto& page_table = process->GetPageTable(); - - // Get bounds of where mapping is possible. - const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart()); - const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE; - const auto state = Kernel::KMemoryState::IoMemory; - const auto perm = Kernel::KMemoryPermission::UserReadWrite; - std::mt19937_64 rng{process->GetRandomEntropy(0)}; - - // Retry up to 64 times to map into alias code range. - Result res = ResultSuccess; - int i; - for (i = 0; i < 64; i++) { - *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE); - res = page_table.MapPageGroup(*out_map_address, *pg, state, perm); - if (R_SUCCEEDED(res)) { - break; - } - } - - // Return failure, if necessary - R_UNLESS(i < 64, res); - - // We succeeded. - R_SUCCEED(); -} - -Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { - // Create a handle. - Nvidia::Devices::nvmap::IocCreateParams create_params{ - .size = size, - .handle = 0, - }; - R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success, - VI::ResultOperationFailed); - - // Assign the output handle. - *out_nv_map_handle = create_params.handle; - - // We succeeded. - R_SUCCEED(); -} - -Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) { - // Free the handle. - Nvidia::Devices::nvmap::IocFreeParams free_params{ - .handle = handle, - }; - R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success, - VI::ResultOperationFailed); - - // We succeeded. - R_SUCCEED(); -} - -Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, - u32 size, Nvidia::DeviceFD nvmap_fd) { - // Assign the allocated memory to the handle. - Nvidia::Devices::nvmap::IocAllocParams alloc_params{ - .handle = handle, - .heap_mask = 0, - .flags = {}, - .align = 0, - .kind = 0, - .address = GetInteger(buffer), - }; - R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success, - VI::ResultOperationFailed); - - // We succeeded. - R_SUCCEED(); -} - -Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd, - Common::ProcessAddress buffer, u32 size) { - // Get the nvmap device. - auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); - ASSERT(nvmap != nullptr); - - // Create a handle. - R_TRY(CreateNvMapHandle(out_handle, *nvmap, size)); - - // Ensure we maintain a clean state on failure. - ON_RESULT_FAILURE { - R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd)); - }; - - // Assign the allocated memory to the handle. - R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd)); -} - -void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) { - auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); - ASSERT(nvmap != nullptr); - - R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd)); -} - -constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; -constexpr u32 SharedBufferBlockLinearBpp = 4; - -constexpr u32 SharedBufferBlockLinearWidth = 1280; -constexpr u32 SharedBufferBlockLinearHeight = 768; -constexpr u32 SharedBufferBlockLinearStride = - SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp; -constexpr u32 SharedBufferNumSlots = 7; - -constexpr u32 SharedBufferWidth = 1280; -constexpr u32 SharedBufferHeight = 720; -constexpr u32 SharedBufferAsync = false; - -constexpr u32 SharedBufferSlotSize = - SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp; -constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots; - -constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] { - SharedMemoryPoolLayout layout{}; - layout.num_slots = SharedBufferNumSlots; - - for (u32 i = 0; i < SharedBufferNumSlots; i++) { - layout.slots[i].buffer_offset = i * SharedBufferSlotSize; - layout.slots[i].size = SharedBufferSlotSize; - layout.slots[i].width = SharedBufferWidth; - layout.slots[i].height = SharedBufferHeight; - } - - return layout; -}(); - -void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { - auto buffer = std::make_shared<android::NvGraphicBuffer>(); - buffer->width = SharedBufferWidth; - buffer->height = SharedBufferHeight; - buffer->stride = SharedBufferBlockLinearStride; - buffer->format = SharedBufferBlockLinearFormat; - buffer->external_format = SharedBufferBlockLinearFormat; - buffer->buffer_id = handle; - buffer->offset = slot * SharedBufferSlotSize; - ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError); -} - -} // namespace - -FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger, - std::shared_ptr<Nvidia::Module> nvdrv) - : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {} - -FbShareBufferManager::~FbShareBufferManager() = default; - -Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, - u64* out_layer_handle, u64 display_id, - LayerBlending blending) { - std::scoped_lock lk{m_guard}; - - // Ensure we haven't already created. - const u64 aruid = owner_process->GetProcessId(); - R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied); - - // Allocate memory for the shared buffer if needed. - if (!m_buffer_page_group) { - R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system, - SharedBufferSize)); - - // Record buffer id. - m_buffer_id = m_next_buffer_id++; - - // Record display id. - m_display_id = display_id; - } - - // Map into process. - Common::ProcessAddress map_address{}; - R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group, - owner_process, m_system)); - - // Create new session. - auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{}); - auto& session = it->second; - - auto& container = m_nvdrv->GetContainer(); - session.session_id = container.OpenSession(owner_process); - session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id); - - // Create an nvmap handle for the buffer and assign the memory to it. - R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv, - session.nvmap_fd, map_address, SharedBufferSize)); - - // Create and open a layer for the display. - session.layer_id = m_flinger.CreateLayer(m_display_id, blending).value(); - m_flinger.OpenLayer(session.layer_id); - - // Get the layer. - VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id); - ASSERT(layer != nullptr); - - // Get the producer and set preallocated buffers. - auto& producer = layer->GetBufferQueue(); - MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle); - MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle); - - // Assign outputs. - *out_buffer_id = m_buffer_id; - *out_layer_handle = session.layer_id; - - // We succeeded. - R_SUCCEED(); -} - -void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) { - std::scoped_lock lk{m_guard}; - - if (m_buffer_id == 0) { - return; - } - - const u64 aruid = owner_process->GetProcessId(); - const auto it = m_sessions.find(aruid); - if (it == m_sessions.end()) { - return; - } - - auto& session = it->second; - - // Destroy the layer. - m_flinger.DestroyLayer(session.layer_id); - - // Close nvmap handle. - FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); - - // Close nvmap device. - m_nvdrv->Close(session.nvmap_fd); - - // Close session. - auto& container = m_nvdrv->GetContainer(); - container.CloseSession(session.session_id); - - // Erase. - m_sessions.erase(it); -} - -Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, - s32* out_nvmap_handle, - SharedMemoryPoolLayout* out_pool_layout, - u64 buffer_id, - u64 applet_resource_user_id) { - std::scoped_lock lk{m_guard}; - - R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); - R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound); - R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound); - - *out_pool_layout = SharedBufferPoolLayout; - *out_buffer_size = SharedBufferSize; - *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle; - - R_SUCCEED(); -} - -Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { - // Ensure the layer id is valid. - R_UNLESS(layer_id > 0, VI::ResultNotFound); - - // Get the layer. - VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id); - R_UNLESS(layer != nullptr, VI::ResultNotFound); - - // We succeeded. - *out_layer = layer; - R_SUCCEED(); -} - -Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, - std::array<s32, 4>& out_slot_indexes, - s64* out_target_slot, u64 layer_id) { - std::scoped_lock lk{m_guard}; - - // Get the layer. - VI::Layer* layer; - R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); - - // Get the producer. - auto& producer = layer->GetBufferQueue(); - - // Get the next buffer from the producer. - s32 slot; - R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, - SharedBufferWidth, SharedBufferHeight, - SharedBufferBlockLinearFormat, 0) == android::Status::NoError, - VI::ResultOperationFailed); - - // Assign remaining outputs. - *out_target_slot = slot; - out_slot_indexes = {0, 1, -1, -1}; - - // We succeeded. - R_SUCCEED(); -} - -Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence, - Common::Rectangle<s32> crop_region, - u32 transform, s32 swap_interval, - u64 layer_id, s64 slot) { - std::scoped_lock lk{m_guard}; - - // Get the layer. - VI::Layer* layer; - R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); - - // Get the producer. - auto& producer = layer->GetBufferQueue(); - - // Request to queue the buffer. - std::shared_ptr<android::GraphicBuffer> buffer; - R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == - android::Status::NoError, - VI::ResultOperationFailed); - - ON_RESULT_FAILURE { - producer.CancelBuffer(static_cast<s32>(slot), fence); - }; - - // Queue the buffer to the producer. - android::QueueBufferInput input{}; - android::QueueBufferOutput output{}; - input.crop = crop_region; - input.fence = fence; - input.transform = static_cast<android::NativeWindowTransform>(transform); - input.swap_interval = swap_interval; - R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == - android::Status::NoError, - VI::ResultOperationFailed); - - // We succeeded. - R_SUCCEED(); -} - -Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, - u64 layer_id) { - std::scoped_lock lk{m_guard}; - - // Get the layer. - VI::Layer* layer; - R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); - - // Get the producer. - auto& producer = layer->GetBufferQueue(); - - // Set the event. - *out_event = std::addressof(producer.GetNativeHandle()); - - // We succeeded. - R_SUCCEED(); -} - -Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { - std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer()); - Common::ScratchBuffer<u32> scratch; - - // TODO: this could be optimized - s64 e = -1280 * 768 * 4; - for (auto& block : *m_buffer_page_group) { - u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress()); - u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize()); - - for (; start < end; start++) { - *start = 0; - - if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) { - *start = capture_buffer[e]; - } - e++; - } - - m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) { - m_system.GPU().InvalidateRegion(addr, end - start); - }); - } - - *out_was_written = true; - *out_layer_index = 1; - R_SUCCEED(); -} - -} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h deleted file mode 100644 index b79a7d23a..000000000 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <map> - -#include "common/math_util.h" -#include "core/hle/service/nvdrv/core/container.h" -#include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvnflinger/hwc_layer.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/nvnflinger/ui/fence.h" - -namespace Kernel { -class KPageGroup; -} - -namespace Service::Nvnflinger { - -struct SharedMemorySlot { - u64 buffer_offset; - u64 size; - s32 width; - s32 height; -}; -static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size"); - -struct SharedMemoryPoolLayout { - s32 num_slots; - std::array<SharedMemorySlot, 0x10> slots; -}; -static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); - -struct FbShareSession; - -class FbShareBufferManager final { -public: - explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger, - std::shared_ptr<Nvidia::Module> nvdrv); - ~FbShareBufferManager(); - - Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, - u64 display_id, LayerBlending blending); - void Finalize(Kernel::KProcess* owner_process); - - Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, - SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, - u64 applet_resource_user_id); - Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots, - s64* out_target_slot, u64 layer_id); - Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, - u32 transform, s32 swap_interval, u64 layer_id, s64 slot); - Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); - - Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); - -private: - Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); - -private: - u64 m_next_buffer_id = 1; - u64 m_display_id = 0; - u64 m_buffer_id = 0; - SharedMemoryPoolLayout m_pool_layout = {}; - std::map<u64, FbShareSession> m_sessions; - std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; - - std::mutex m_guard; - Core::System& m_system; - Nvnflinger& m_flinger; - std::shared_ptr<Nvidia::Module> m_nvdrv; -}; - -struct FbShareSession { - Nvidia::DeviceFD nvmap_fd = {}; - Nvidia::NvCore::SessionId session_id = {}; - u64 layer_id = {}; - u32 buffer_nvmap_handle = 0; -}; - -} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp index be7eb97a3..f2dfe85a9 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.cpp +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp @@ -10,8 +10,6 @@ #include "core/hle/service/nvnflinger/hardware_composer.h" #include "core/hle/service/nvnflinger/hwc_layer.h" #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h" namespace Service::Nvnflinger { @@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) { HardwareComposer::HardwareComposer() = default; HardwareComposer::~HardwareComposer() = default; -u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, +u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display, Nvidia::Devices::nvdisp_disp0& nvdisp) { boost::container::small_vector<HwcLayer, 2> composition_stack; @@ -56,12 +54,11 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, bool has_acquired_buffer{}; // Acquire all necessary framebuffers. - for (size_t i = 0; i < display.GetNumLayers(); i++) { - auto& layer = display.GetLayer(i); - auto layer_id = layer.GetLayerId(); + for (auto& layer : display.stack.layers) { + auto consumer_id = layer->consumer_id; // Try to fetch the framebuffer (either new or stale). - const auto result = this->CacheFramebufferLocked(layer, layer_id); + const auto result = this->CacheFramebufferLocked(*layer, consumer_id); // If we failed, skip this layer. if (result == CacheStatus::NoBufferAvailable) { @@ -73,24 +70,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, has_acquired_buffer = true; } - const auto& buffer = m_framebuffers[layer_id]; + const auto& buffer = m_framebuffers[consumer_id]; const auto& item = buffer.item; const auto& igbp_buffer = *item.graphic_buffer; // TODO: get proper Z-index from layer - composition_stack.emplace_back(HwcLayer{ - .buffer_handle = igbp_buffer.BufferId(), - .offset = igbp_buffer.Offset(), - .format = igbp_buffer.ExternalFormat(), - .width = igbp_buffer.Width(), - .height = igbp_buffer.Height(), - .stride = igbp_buffer.Stride(), - .z_index = 0, - .blending = layer.GetBlending(), - .transform = static_cast<android::BufferTransformFlags>(item.transform), - .crop_rect = item.crop, - .acquire_fence = item.fence, - }); + if (layer->visible) { + composition_stack.emplace_back(HwcLayer{ + .buffer_handle = igbp_buffer.BufferId(), + .offset = igbp_buffer.Offset(), + .format = igbp_buffer.ExternalFormat(), + .width = igbp_buffer.Width(), + .height = igbp_buffer.Height(), + .stride = igbp_buffer.Stride(), + .z_index = 0, + .blending = layer->blending, + .transform = static_cast<android::BufferTransformFlags>(item.transform), + .crop_rect = item.crop, + .acquire_fence = item.fence, + }); + } // We need to compose again either before this frame is supposed to // be released, or exactly on the vsync period it should be released. @@ -135,10 +134,10 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, continue; } - if (auto* layer = display.FindLayer(layer_id); layer != nullptr) { + if (const auto layer = display.stack.FindLayer(layer_id); layer != nullptr) { // TODO: support release fence // This is needed to prevent screen tearing - layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence()); + layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence()); framebuffer.is_acquired = false; } } @@ -146,26 +145,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, return frame_advance; } -void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) { - // Check if we are tracking a slot with this layer_id. - const auto it = m_framebuffers.find(layer_id); +void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) { + // Check if we are tracking a slot with this consumer_id. + const auto it = m_framebuffers.find(consumer_id); if (it == m_framebuffers.end()) { return; } // Try to release the buffer item. - auto* const layer = display.FindLayer(layer_id); + const auto layer = display.stack.FindLayer(consumer_id); if (layer && it->second.is_acquired) { - layer->GetConsumer().ReleaseBuffer(it->second.item, android::Fence::NoFence()); + layer->buffer_item_consumer->ReleaseBuffer(it->second.item, android::Fence::NoFence()); } // Erase the slot. m_framebuffers.erase(it); } -bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) { +bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer) { // Attempt the update. - const auto status = layer.GetConsumer().AcquireBuffer(&framebuffer.item, {}, false); + const auto status = layer.buffer_item_consumer->AcquireBuffer(&framebuffer.item, {}, false); if (status != android::Status::NoError) { return false; } @@ -178,10 +177,10 @@ bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer return true; } -HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer, - LayerId layer_id) { +HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(Layer& layer, + ConsumerId consumer_id) { // Check if this framebuffer is already present. - const auto it = m_framebuffers.find(layer_id); + const auto it = m_framebuffers.find(consumer_id); if (it != m_framebuffers.end()) { // If it's currently still acquired, we are done. if (it->second.is_acquired) { @@ -203,7 +202,7 @@ HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer if (this->TryAcquireFramebufferLocked(layer, framebuffer)) { // Move the buffer item into a new slot. - m_framebuffers.emplace(layer_id, std::move(framebuffer)); + m_framebuffers.emplace(consumer_id, std::move(framebuffer)); // We succeeded. return CacheStatus::BufferAcquired; diff --git a/src/core/hle/service/nvnflinger/hardware_composer.h b/src/core/hle/service/nvnflinger/hardware_composer.h index 28392c512..c5b830468 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.h +++ b/src/core/hle/service/nvnflinger/hardware_composer.h @@ -3,35 +3,29 @@ #pragma once -#include <memory> #include <boost/container/flat_map.hpp> #include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/display.h" namespace Service::Nvidia::Devices { class nvdisp_disp0; } -namespace Service::VI { -class Display; -class Layer; -} // namespace Service::VI - namespace Service::Nvnflinger { -using LayerId = u64; +using ConsumerId = s32; class HardwareComposer { public: explicit HardwareComposer(); ~HardwareComposer(); - u32 ComposeLocked(f32* out_speed_scale, VI::Display& display, + u32 ComposeLocked(f32* out_speed_scale, Display& display, Nvidia::Devices::nvdisp_disp0& nvdisp); - void RemoveLayerLocked(VI::Display& display, LayerId layer_id); + void RemoveLayerLocked(Display& display, ConsumerId consumer_id); private: - // TODO: do we want to track frame number in vi instead? u64 m_frame_number{0}; private: @@ -49,11 +43,11 @@ private: CachedBufferReused, }; - boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{}; + boost::container::flat_map<ConsumerId, Framebuffer> m_framebuffers{}; private: - bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer); - CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id); + bool TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer); + CacheStatus CacheFramebufferLocked(Layer& layer, ConsumerId consumer_id); }; } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp new file mode 100644 index 000000000..8629a2e89 --- /dev/null +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/nvnflinger/binder.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" + +namespace Service::Nvnflinger { + +IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, + std::shared_ptr<HosBinderDriverServer> server, + std::shared_ptr<SurfaceFlinger> surface_flinger) + : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server), + m_surface_flinger(surface_flinger) { + static const FunctionInfo functions[] = { + {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"}, + {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, + {2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"}, + {3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"}, + }; + RegisterHandlers(functions); +} + +IHOSBinderDriver::~IHOSBinderDriver() = default; + +Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id, + InBuffer<BufferAttr_HipcMapAlias> parcel_data, + OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, + u32 flags) { + LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id, + flags); + + const auto binder = m_server->TryGetBinder(binder_id); + R_SUCCEED_IF(binder == nullptr); + + binder->Transact(transaction_id, parcel_data, parcel_reply, flags); + + R_SUCCEED(); +} + +Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) { + LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type); + R_SUCCEED(); +} + +Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, + OutCopyHandle<Kernel::KReadableEvent> out_handle) { + LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); + + const auto binder = m_server->TryGetBinder(binder_id); + R_UNLESS(binder != nullptr, ResultUnknown); + + *out_handle = binder->GetNativeHandle(type_id); + + R_SUCCEED(); +} + +Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, u32 transaction_id, + InBuffer<BufferAttr_HipcAutoSelect> parcel_data, + OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, + u32 flags) { + R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags)); +} + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.h b/src/core/hle/service/nvnflinger/hos_binder_driver.h new file mode 100644 index 000000000..b7fb07bd2 --- /dev/null +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::Nvnflinger { + +class HosBinderDriverServer; +class SurfaceFlinger; + +class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { +public: + explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr<HosBinderDriverServer> server, + std::shared_ptr<SurfaceFlinger> surface_flinger); + ~IHOSBinderDriver() override; + + std::shared_ptr<SurfaceFlinger> GetSurfaceFlinger() { + return m_surface_flinger; + } + + std::shared_ptr<HosBinderDriverServer> GetServer() { + return m_server; + } + +private: + Result TransactParcel(s32 binder_id, u32 transaction_id, + InBuffer<BufferAttr_HipcMapAlias> parcel_data, + OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags); + Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); + Result GetNativeHandle(s32 binder_id, u32 type_id, + OutCopyHandle<Kernel::KReadableEvent> out_handle); + Result TransactParcelAuto(s32 binder_id, u32 transaction_id, + InBuffer<BufferAttr_HipcAutoSelect> parcel_data, + OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags); + +private: + const std::shared_ptr<HosBinderDriverServer> m_server; + const std::shared_ptr<SurfaceFlinger> m_surface_flinger; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp index b86a79ec9..29addda44 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp @@ -8,26 +8,30 @@ namespace Service::Nvnflinger { -HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) - : service_context(system_, "HosBinderDriverServer") {} +HosBinderDriverServer::HosBinderDriverServer() = default; +HosBinderDriverServer::~HosBinderDriverServer() = default; -HosBinderDriverServer::~HosBinderDriverServer() {} - -u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) { +s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) { std::scoped_lock lk{lock}; last_id++; - producers[last_id] = std::move(binder); + binders[last_id] = std::move(binder); return last_id; } -android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { +void HosBinderDriverServer::UnregisterBinder(s32 binder_id) { + std::scoped_lock lk{lock}; + + binders.erase(binder_id); +} + +std::shared_ptr<android::IBinder> HosBinderDriverServer::TryGetBinder(s32 id) const { std::scoped_lock lk{lock}; - if (auto search = producers.find(id); search != producers.end()) { - return search->second.get(); + if (auto search = binders.find(id); search != binders.end()) { + return search->second; } return {}; diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h index 58bb9469a..d72b50833 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h @@ -8,7 +8,6 @@ #include <unordered_map> #include "common/common_types.h" -#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/nvnflinger/binder.h" namespace Core { @@ -19,19 +18,18 @@ namespace Service::Nvnflinger { class HosBinderDriverServer final { public: - explicit HosBinderDriverServer(Core::System& system_); + explicit HosBinderDriverServer(); ~HosBinderDriverServer(); - u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder); + s32 RegisterBinder(std::shared_ptr<android::IBinder>&& binder); + void UnregisterBinder(s32 binder_id); - android::IBinder* TryGetProducer(u64 id); + std::shared_ptr<android::IBinder> TryGetBinder(s32 id) const; private: - KernelHelpers::ServiceContext service_context; - - std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers; - std::mutex lock; - u64 last_id{}; + std::unordered_map<s32, std::shared_ptr<android::IBinder>> binders; + mutable std::mutex lock; + s32 last_id{}; }; } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 687ccc9f9..9e3b68b8a 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -1,335 +1,24 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include <algorithm> -#include <optional> - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/microprofile.h" -#include "common/scope_exit.h" -#include "common/settings.h" -#include "common/thread.h" #include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/buffer_item_consumer.h" -#include "core/hle/service/nvnflinger/buffer_queue_core.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/hardware_composer.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h" #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" #include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h" -#include "core/hle/service/vi/vi_results.h" -#include "video_core/gpu.h" -#include "video_core/host1x/host1x.h" -#include "video_core/host1x/syncpoint_manager.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/server_manager.h" +#include "core/hle/service/sm/sm.h" namespace Service::Nvnflinger { -constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; - -void Nvnflinger::SplitVSync(std::stop_token stop_token) { - system.RegisterHostThread(); - std::string name = "VSyncThread"; - MicroProfileOnThreadCreate(name.c_str()); - - // Cleanup - SCOPE_EXIT({ MicroProfileOnThreadExit(); }); - - Common::SetCurrentThreadName(name.c_str()); - Common::SetCurrentThreadPriority(Common::ThreadPriority::High); - - while (!stop_token.stop_requested()) { - vsync_signal.Wait(); - - const auto lock_guard = Lock(); - - if (!is_abandoned) { - Compose(); - } - } -} - -Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_) - : system(system_), service_context(system_, "nvnflinger"), - hos_binder_driver_server(hos_binder_driver_server_) { - displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system); - displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system); - displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system); - displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system); - displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system); - guard = std::make_shared<std::mutex>(); - - // Schedule the screen composition events - multi_composition_event = Core::Timing::CreateEvent( - "ScreenComposition", - [this](s64 time, - std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - vsync_signal.Set(); - return std::chrono::nanoseconds(GetNextTicks()); - }); - - single_composition_event = Core::Timing::CreateEvent( - "ScreenComposition", - [this](s64 time, - std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { - const auto lock_guard = Lock(); - Compose(); - - return std::chrono::nanoseconds(GetNextTicks()); - }); - - if (system.IsMulticore()) { - system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event); - vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); - } else { - system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event); - } -} - -Nvnflinger::~Nvnflinger() { - if (system.IsMulticore()) { - system.CoreTiming().UnscheduleEvent(multi_composition_event); - vsync_thread.request_stop(); - vsync_signal.Set(); - } else { - system.CoreTiming().UnscheduleEvent(single_composition_event); - } - - ShutdownLayers(); - - if (nvdrv) { - nvdrv->Close(disp_fd); - } -} - -void Nvnflinger::ShutdownLayers() { - // Abandon consumers. - { - const auto lock_guard = Lock(); - for (auto& display : displays) { - display.Abandon(); - } - - is_abandoned = true; - } - - // Join the vsync thread, if it exists. - vsync_thread = {}; -} - -void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { - nvdrv = std::move(instance); - disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); -} - -std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { - const auto lock_guard = Lock(); - - LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name); - - const auto itr = - std::find_if(displays.begin(), displays.end(), - [&](const VI::Display& display) { return display.GetName() == name; }); - - if (itr == displays.end()) { - return std::nullopt; - } - - return itr->GetID(); -} - -bool Nvnflinger::CloseDisplay(u64 display_id) { - const auto lock_guard = Lock(); - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return false; - } - - display->Reset(); - - return true; -} - -std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) { - const auto lock_guard = Lock(); - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return std::nullopt; - } - - const u64 layer_id = next_layer_id++; - CreateLayerAtId(*display, layer_id, blending); - return layer_id; -} - -void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) { - const auto buffer_id = next_buffer_queue_id++; - display.CreateLayer(layer_id, buffer_id, nvdrv->container); - display.FindLayer(layer_id)->SetBlending(blending); -} - -bool Nvnflinger::OpenLayer(u64 layer_id) { - const auto lock_guard = Lock(); - - for (auto& display : displays) { - if (auto* layer = display.FindLayer(layer_id); layer) { - return layer->Open(); - } - } - - return false; -} - -bool Nvnflinger::CloseLayer(u64 layer_id) { - const auto lock_guard = Lock(); - - for (auto& display : displays) { - if (auto* layer = display.FindLayer(layer_id); layer) { - return layer->Close(); - } - } - - return false; -} - -void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) { - const auto lock_guard = Lock(); - - for (auto& display : displays) { - if (auto* layer = display.FindLayer(layer_id); layer) { - layer->SetVisibility(visible); - } - } -} - -void Nvnflinger::DestroyLayer(u64 layer_id) { - const auto lock_guard = Lock(); - - for (auto& display : displays) { - display.DestroyLayer(layer_id); - } -} - -std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) { - const auto lock_guard = Lock(); - const auto* const layer = FindLayer(display_id, layer_id); - - if (layer == nullptr) { - return std::nullopt; - } - - return layer->GetBinderId(); -} - -Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) { - const auto lock_guard = Lock(); - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return VI::ResultNotFound; - } - - *out_vsync_event = display->GetVSyncEvent(); - return ResultSuccess; -} - -VI::Display* Nvnflinger::FindDisplay(u64 display_id) { - const auto itr = - std::find_if(displays.begin(), displays.end(), - [&](const VI::Display& display) { return display.GetID() == display_id; }); - - if (itr == displays.end()) { - return nullptr; - } - - return &*itr; -} - -const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const { - const auto itr = - std::find_if(displays.begin(), displays.end(), - [&](const VI::Display& display) { return display.GetID() == display_id; }); - - if (itr == displays.end()) { - return nullptr; - } - - return &*itr; -} - -VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) { - auto* const display = FindDisplay(display_id); - - if (display == nullptr) { - return nullptr; - } - - return display->FindLayer(layer_id); -} - -void Nvnflinger::Compose() { - for (auto& display : displays) { - // Trigger vsync for this display at the end of drawing - SCOPE_EXIT({ display.SignalVSyncEvent(); }); - - // Don't do anything for displays without layers. - if (!display.HasLayers()) { - continue; - } - - if (!system.IsPoweredOn()) { - return; // We are likely shutting down - } - - auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); - ASSERT(nvdisp); - - swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp); - } -} - -s64 Nvnflinger::GetNextTicks() const { - const auto& settings = Settings::values; - auto speed_scale = 1.f; - if (settings.use_multi_core.GetValue()) { - if (settings.use_speed_limit.GetValue()) { - // Scales the speed based on speed_limit setting on MC. SC is handled by - // SpeedLimiter::DoSpeedLimiting. - speed_scale = 100.f / settings.speed_limit.GetValue(); - } else { - // Run at unlocked framerate. - speed_scale = 0.01f; - } - } - - // Adjust by speed limit determined during composition. - speed_scale /= compose_speed_scale; - - if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { - // Run at intended presentation rate during video playback. - speed_scale = 1.f; - } - - const f32 effective_fps = 60.f / static_cast<f32>(swap_interval); - return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); -} - -FbShareBufferManager& Nvnflinger::GetSystemBufferManager() { - const auto lock_guard = Lock(); - - if (!system_buffer_manager) { - system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv); - } +void LoopProcess(Core::System& system) { + const auto binder_server = std::make_shared<HosBinderDriverServer>(); + const auto surface_flinger = std::make_shared<SurfaceFlinger>(system, *binder_server); - return *system_buffer_manager; + auto server_manager = std::make_unique<ServerManager>(system); + server_manager->RegisterNamedService( + "dispdrv", std::make_shared<IHOSBinderDriver>(system, binder_server, surface_flinger)); + ServerManager::RunServer(std::move(server_manager)); } } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 4cf4f069d..5c41f3013 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -3,170 +3,12 @@ #pragma once -#include <list> -#include <memory> -#include <mutex> -#include <optional> -#include <thread> -#include <vector> - -#include "common/common_types.h" -#include "common/polyfill_thread.h" -#include "common/thread.h" -#include "core/hle/result.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvnflinger/hwc_layer.h" - -namespace Common { -class Event; -} // namespace Common - -namespace Core::Timing { -class CoreTiming; -struct EventType; -} // namespace Core::Timing - -namespace Kernel { -class KReadableEvent; -} // namespace Kernel - -namespace Service::Nvidia { -class Module; -} // namespace Service::Nvidia - -namespace Service::VI { -class Display; -class Layer; -} // namespace Service::VI - -namespace Service::android { -class BufferQueueCore; -class BufferQueueProducer; -} // namespace Service::android +namespace Core { +class System; +} namespace Service::Nvnflinger { -class FbShareBufferManager; -class HardwareComposer; -class HosBinderDriverServer; - -class Nvnflinger final { -public: - explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); - ~Nvnflinger(); - - void ShutdownLayers(); - - /// Sets the NVDrv module instance to use to send buffers to the GPU. - void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance); - - /// Opens the specified display and returns the ID. - /// - /// If an invalid display name is provided, then an empty optional is returned. - [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name); - - /// Closes the specified display by its ID. - /// - /// Returns false if an invalid display ID is provided. - [[nodiscard]] bool CloseDisplay(u64 display_id); - - /// Creates a layer on the specified display and returns the layer ID. - /// - /// If an invalid display ID is specified, then an empty optional is returned. - [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id, - LayerBlending blending = LayerBlending::None); - - /// Opens a layer on all displays for the given layer ID. - bool OpenLayer(u64 layer_id); - - /// Closes a layer on all displays for the given layer ID. - bool CloseLayer(u64 layer_id); - - /// Makes a layer visible on all displays for the given layer ID. - void SetLayerVisibility(u64 layer_id, bool visible); - - /// Destroys the given layer ID. - void DestroyLayer(u64 layer_id); - - /// Finds the buffer queue ID of the specified layer in the specified display. - /// - /// If an invalid display ID or layer ID is provided, then an empty optional is returned. - [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id); - - /// Gets the vsync event for the specified display. - /// - /// If an invalid display ID is provided, then VI::ResultNotFound is returned. - /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. - [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id); - - /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when - /// finished. - void Compose(); - - [[nodiscard]] s64 GetNextTicks() const; - - FbShareBufferManager& GetSystemBufferManager(); - -private: - struct Layer { - std::unique_ptr<android::BufferQueueCore> core; - std::unique_ptr<android::BufferQueueProducer> producer; - }; - - friend class FbShareBufferManager; - -private: - [[nodiscard]] std::unique_lock<std::mutex> Lock() const { - return std::unique_lock{*guard}; - } - - /// Finds the display identified by the specified ID. - [[nodiscard]] VI::Display* FindDisplay(u64 display_id); - - /// Finds the display identified by the specified ID. - [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; - - /// Finds the layer identified by the specified ID in the desired display. - [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); - - /// Creates a layer with the specified layer ID in the desired display. - void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending); - - void SplitVSync(std::stop_token stop_token); - - std::shared_ptr<Nvidia::Module> nvdrv; - s32 disp_fd; - - std::list<VI::Display> displays; - - /// Id to use for the next layer that is created, this counter is shared among all displays. - u64 next_layer_id = 1; - /// Id to use for the next buffer queue that is created, this counter is shared among all - /// layers. - u32 next_buffer_queue_id = 1; - - s32 swap_interval = 1; - f32 compose_speed_scale = 1.0f; - - bool is_abandoned = false; - - /// Event that handles screen composition. - std::shared_ptr<Core::Timing::EventType> multi_composition_event; - std::shared_ptr<Core::Timing::EventType> single_composition_event; - - std::unique_ptr<FbShareBufferManager> system_buffer_manager; - - std::shared_ptr<std::mutex> guard; - - Core::System& system; - - Common::Event vsync_signal; - - std::jthread vsync_thread; - - KernelHelpers::ServiceContext service_context; - - HosBinderDriverServer& hos_binder_driver_server; -}; +void LoopProcess(Core::System& system); } // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/surface_flinger.cpp b/src/core/hle/service/nvnflinger/surface_flinger.cpp new file mode 100644 index 000000000..8362b65e5 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp @@ -0,0 +1,139 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" +#include "core/hle/service/nvdrv/nvdrv_interface.h" +#include "core/hle/service/nvnflinger/display.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/sm/sm.h" + +#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_core.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" + +namespace Service::Nvnflinger { + +SurfaceFlinger::SurfaceFlinger(Core::System& system, HosBinderDriverServer& server) + : m_system(system), m_server(server), m_context(m_system, "SurfaceFlinger") { + nvdrv = m_system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); + disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); +} + +SurfaceFlinger::~SurfaceFlinger() { + nvdrv->Close(disp_fd); +} + +void SurfaceFlinger::AddDisplay(u64 display_id) { + m_displays.emplace_back(display_id); +} + +void SurfaceFlinger::RemoveDisplay(u64 display_id) { + std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; }); +} + +bool SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, + u64 display_id) { + auto* const display = this->FindDisplay(display_id); + if (!display || !display->stack.HasLayers()) { + return false; + } + + *out_swap_interval = + m_composer.ComposeLocked(out_compose_speed_scale, *display, + *nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd)); + return true; +} + +void SurfaceFlinger::CreateLayer(s32 consumer_binder_id) { + auto binder = std::static_pointer_cast<android::BufferQueueConsumer>( + m_server.TryGetBinder(consumer_binder_id)); + if (!binder) { + return; + } + + auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(binder)); + buffer_item_consumer->Connect(false); + + m_layers.layers.emplace_back( + std::make_shared<Layer>(std::move(buffer_item_consumer), consumer_binder_id)); +} + +void SurfaceFlinger::DestroyLayer(s32 consumer_binder_id) { + std::erase_if(m_layers.layers, + [&](auto& layer) { return layer->consumer_id == consumer_binder_id; }); +} + +void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) { + auto* const display = this->FindDisplay(display_id); + auto layer = this->FindLayer(consumer_binder_id); + + if (!display || !layer) { + return; + } + + display->stack.layers.emplace_back(std::move(layer)); +} + +void SurfaceFlinger::RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id) { + auto* const display = this->FindDisplay(display_id); + if (!display) { + return; + } + + m_composer.RemoveLayerLocked(*display, consumer_binder_id); + std::erase_if(display->stack.layers, + [&](auto& layer) { return layer->consumer_id == consumer_binder_id; }); +} + +void SurfaceFlinger::SetLayerVisibility(s32 consumer_binder_id, bool visible) { + if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) { + layer->visible = visible; + return; + } +} + +void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) { + if (const auto layer = this->FindLayer(consumer_binder_id); layer != nullptr) { + layer->blending = blending; + return; + } +} + +Display* SurfaceFlinger::FindDisplay(u64 display_id) { + for (auto& display : m_displays) { + if (display.id == display_id) { + return &display; + } + } + + return nullptr; +} + +std::shared_ptr<Layer> SurfaceFlinger::FindLayer(s32 consumer_binder_id) { + for (auto& layer : m_layers.layers) { + if (layer->consumer_id == consumer_binder_id) { + return layer; + } + } + + return nullptr; +} + +void SurfaceFlinger::CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id) { + auto& nvmap = nvdrv->GetContainer().GetNvMapFile(); + auto core = std::make_shared<android::BufferQueueCore>(); + auto producer = std::make_shared<android::BufferQueueProducer>(m_context, core, nvmap); + auto consumer = std::make_shared<android::BufferQueueConsumer>(core); + + *out_consumer_binder_id = m_server.RegisterBinder(std::move(consumer)); + *out_producer_binder_id = m_server.RegisterBinder(std::move(producer)); +} + +void SurfaceFlinger::DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id) { + m_server.UnregisterBinder(producer_binder_id); + m_server.UnregisterBinder(consumer_binder_id); +} + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/surface_flinger.h b/src/core/hle/service/nvnflinger/surface_flinger.h new file mode 100644 index 000000000..406281c83 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.h @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <vector> + +#include "common/common_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/nvnflinger/hardware_composer.h" + +namespace Core { +class System; +} + +namespace Service::Nvidia { +class Module; +} + +// TODO: ISurfaceComposer +// TODO: ISurfaceComposerClient + +namespace Service::Nvnflinger { + +struct Display; +class HosBinderDriverServer; +enum class LayerBlending : u32; +struct Layer; + +class SurfaceFlinger { +public: + explicit SurfaceFlinger(Core::System& system, HosBinderDriverServer& server); + ~SurfaceFlinger(); + + void AddDisplay(u64 display_id); + void RemoveDisplay(u64 display_id); + bool ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id); + + void CreateLayer(s32 consumer_binder_id); + void DestroyLayer(s32 consumer_binder_id); + + void AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id); + void RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id); + + void SetLayerVisibility(s32 consumer_binder_id, bool visible); + void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending); + +private: + Display* FindDisplay(u64 display_id); + std::shared_ptr<Layer> FindLayer(s32 consumer_binder_id); + +public: + // TODO: these don't belong here + void CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id); + void DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id); + +private: + Core::System& m_system; + HosBinderDriverServer& m_server; + KernelHelpers::ServiceContext m_context; + + std::vector<Display> m_displays; + LayerStack m_layers; + std::shared_ptr<Nvidia::Module> nvdrv; + s32 disp_fd; + HardwareComposer m_composer; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/omm/omm.cpp b/src/core/hle/service/omm/omm.cpp new file mode 100644 index 000000000..b95319e26 --- /dev/null +++ b/src/core/hle/service/omm/omm.cpp @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/omm/omm.h" +#include "core/hle/service/omm/operation_mode_manager.h" +#include "core/hle/service/omm/policy_manager_system.h" +#include "core/hle/service/omm/power_state_interface.h" +#include "core/hle/service/server_manager.h" + +namespace Service::OMM { + +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + + server_manager->RegisterNamedService("idle:sys", + std::make_shared<IPolicyManagerSystem>(system)); + server_manager->RegisterNamedService("omm", std::make_shared<IOperationModeManager>(system)); + server_manager->RegisterNamedService("spsm", std::make_shared<IPowerStateInterface>(system)); + ServerManager::RunServer(std::move(server_manager)); +} + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/omm.h b/src/core/hle/service/omm/omm.h new file mode 100644 index 000000000..7bf04688a --- /dev/null +++ b/src/core/hle/service/omm/omm.h @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +namespace Core { +class System; +} + +namespace Service::OMM { + +void LoopProcess(Core::System& system); + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/operation_mode_manager.cpp b/src/core/hle/service/omm/operation_mode_manager.cpp new file mode 100644 index 000000000..fe7ed84a7 --- /dev/null +++ b/src/core/hle/service/omm/operation_mode_manager.cpp @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/omm/operation_mode_manager.h" + +namespace Service::OMM { + +IOperationModeManager::IOperationModeManager(Core::System& system_) + : ServiceFramework{system_, "omm"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetOperationMode"}, + {1, nullptr, "GetOperationModeChangeEvent"}, + {2, nullptr, "EnableAudioVisual"}, + {3, nullptr, "DisableAudioVisual"}, + {4, nullptr, "EnterSleepAndWait"}, + {5, nullptr, "GetCradleStatus"}, + {6, nullptr, "FadeInDisplay"}, + {7, nullptr, "FadeOutDisplay"}, + {8, nullptr, "GetCradleFwVersion"}, + {9, nullptr, "NotifyCecSettingsChanged"}, + {10, nullptr, "SetOperationModePolicy"}, + {11, nullptr, "GetDefaultDisplayResolution"}, + {12, nullptr, "GetDefaultDisplayResolutionChangeEvent"}, + {13, nullptr, "UpdateDefaultDisplayResolution"}, + {14, nullptr, "ShouldSleepOnBoot"}, + {15, nullptr, "NotifyHdcpApplicationExecutionStarted"}, + {16, nullptr, "NotifyHdcpApplicationExecutionFinished"}, + {17, nullptr, "NotifyHdcpApplicationDrawingStarted"}, + {18, nullptr, "NotifyHdcpApplicationDrawingFinished"}, + {19, nullptr, "GetHdcpAuthenticationFailedEvent"}, + {20, nullptr, "GetHdcpAuthenticationFailedEmulationEnabled"}, + {21, nullptr, "SetHdcpAuthenticationFailedEmulation"}, + {22, nullptr, "GetHdcpStateChangeEvent"}, + {23, nullptr, "GetHdcpState"}, + {24, nullptr, "ShowCardUpdateProcessing"}, + {25, nullptr, "SetApplicationCecSettingsAndNotifyChanged"}, + {26, nullptr, "GetOperationModeSystemInfo"}, + {27, nullptr, "GetAppletFullAwakingSystemEvent"}, + {28, nullptr, "CreateCradleFirmwareUpdater"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IOperationModeManager::~IOperationModeManager() = default; + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/operation_mode_manager.h b/src/core/hle/service/omm/operation_mode_manager.h new file mode 100644 index 000000000..32bc7b2f9 --- /dev/null +++ b/src/core/hle/service/omm/operation_mode_manager.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::OMM { + +class IOperationModeManager final : public ServiceFramework<IOperationModeManager> { +public: + explicit IOperationModeManager(Core::System& system_); + ~IOperationModeManager() override; +}; + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/policy_manager_system.cpp b/src/core/hle/service/omm/policy_manager_system.cpp new file mode 100644 index 000000000..1cd6fd807 --- /dev/null +++ b/src/core/hle/service/omm/policy_manager_system.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/omm/policy_manager_system.h" + +namespace Service::OMM { + +IPolicyManagerSystem::IPolicyManagerSystem(Core::System& system_) + : ServiceFramework{system_, "idle:sys"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetAutoPowerDownEvent"}, + {1, nullptr, "IsAutoPowerDownRequested"}, + {2, nullptr, "Unknown2"}, + {3, nullptr, "SetHandlingContext"}, + {4, nullptr, "LoadAndApplySettings"}, + {5, nullptr, "ReportUserIsActive"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IPolicyManagerSystem::~IPolicyManagerSystem() = default; + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/policy_manager_system.h b/src/core/hle/service/omm/policy_manager_system.h new file mode 100644 index 000000000..151ca0d2e --- /dev/null +++ b/src/core/hle/service/omm/policy_manager_system.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::OMM { + +class IPolicyManagerSystem final : public ServiceFramework<IPolicyManagerSystem> { +public: + explicit IPolicyManagerSystem(Core::System& system_); + ~IPolicyManagerSystem() override; +}; + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/power_state_interface.cpp b/src/core/hle/service/omm/power_state_interface.cpp new file mode 100644 index 000000000..22cac8259 --- /dev/null +++ b/src/core/hle/service/omm/power_state_interface.cpp @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/omm/power_state_interface.h" + +namespace Service::OMM { + +IPowerStateInterface::IPowerStateInterface(Core::System& system_) + : ServiceFramework{system_, "spsm"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetState"}, + {1, nullptr, "EnterSleep"}, + {2, nullptr, "GetLastWakeReason"}, + {3, nullptr, "Shutdown"}, + {4, nullptr, "GetNotificationMessageEventHandle"}, + {5, nullptr, "ReceiveNotificationMessage"}, + {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"}, + {7, nullptr, "ResetEventLog"}, + {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, + {9, nullptr, "ChangeHomeButtonLongPressingTime"}, + {10, nullptr, "PutErrorState"}, + {11, nullptr, "InvalidateCurrentHomeButtonPressing"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IPowerStateInterface::~IPowerStateInterface() = default; + +} // namespace Service::OMM diff --git a/src/core/hle/service/omm/power_state_interface.h b/src/core/hle/service/omm/power_state_interface.h new file mode 100644 index 000000000..825a6512d --- /dev/null +++ b/src/core/hle/service/omm/power_state_interface.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::OMM { + +class IPowerStateInterface final : public ServiceFramework<IPowerStateInterface> { +public: + explicit IPowerStateInterface(Core::System& system_); + ~IPowerStateInterface() override; +}; + +} // namespace Service::OMM diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 24b85cc61..9a0adb295 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -144,7 +144,9 @@ Result StaticService::GetStandardSteadyClockRtcValue(Out<s64> out_rtc_value) { Result StaticService::IsStandardUserSystemClockAutomaticCorrectionEnabled( Out<bool> out_is_enabled) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_is_enabled={}", *out_is_enabled); + }; R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); @@ -180,7 +182,9 @@ Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { } Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_is_sufficient={}", *out_is_sufficient); + }; *out_is_sufficient = m_network_system_clock.IsAccuracySufficient(); @@ -189,7 +193,9 @@ Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> o Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Out<SteadyClockTimePoint> out_time_point) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); + }; R_UNLESS(m_user_system_clock.IsInitialized(), ResultClockUninitialized); @@ -200,7 +206,9 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( Out<s64> out_time, const SystemClockContext& context) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); + }; R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); @@ -219,8 +227,9 @@ Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( } Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type) { - SCOPE_EXIT( - { LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. type={} out_snapshot={}", type, *out_snapshot); + }; SystemClockContext user_context{}; R_TRY(m_user_system_clock.GetContext(user_context)); @@ -234,11 +243,11 @@ Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType t Result StaticService::GetClockSnapshotFromSystemClockContext( TimeType type, OutClockSnapshot out_snapshot, const SystemClockContext& user_context, const SystemClockContext& network_context) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. type={} user_context={} network_context={} out_snapshot={}", type, user_context, network_context, *out_snapshot); - }); + }; R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); } @@ -246,9 +255,9 @@ Result StaticService::GetClockSnapshotFromSystemClockContext( Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, InClockSnapshot a, InClockSnapshot b) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. a={} b={} out_difference={}", *a, *b, *out_difference); - }); + }; auto diff_s = std::chrono::seconds(b->user_context.offset) - std::chrono::seconds(a->user_context.offset); @@ -276,7 +285,9 @@ Result StaticService::CalculateStandardUserSystemClockDifferenceByUser(Out<s64> Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. a={} b={} out_time={}", *a, *b, *out_time); + }; s64 time_s{}; auto res = diff --git a/src/core/hle/service/psc/time/steady_clock.cpp b/src/core/hle/service/psc/time/steady_clock.cpp index 948610a2b..78dcf532c 100644 --- a/src/core/hle/service/psc/time/steady_clock.cpp +++ b/src/core/hle/service/psc/time/steady_clock.cpp @@ -29,7 +29,9 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man } Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_time_point={}", *out_time_point); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -38,7 +40,9 @@ Result SteadyClock::GetCurrentTimePoint(Out<SteadyClockTimePoint> out_time_point } Result SteadyClock::GetTestOffset(Out<s64> out_test_offset) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_test_offset={}", *out_test_offset); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -59,7 +63,9 @@ Result SteadyClock::SetTestOffset(s64 test_offset) { } Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_rtc_value={}", *out_rtc_value); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -68,7 +74,9 @@ Result SteadyClock::GetRtcValue(Out<s64> out_rtc_value) { } Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_is_detected={}", *out_is_detected); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -78,7 +86,9 @@ Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) { } Result SteadyClock::GetSetupResultValue(Out<Result> out_result) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_result=0x{:X}", out_result->raw); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -88,8 +98,9 @@ Result SteadyClock::GetSetupResultValue(Out<Result> out_result) { } Result SteadyClock::GetInternalOffset(Out<s64> out_internal_offset) { - SCOPE_EXIT( - { LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_internal_offset={}", *out_internal_offset); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp index b4e9264d8..9f841d8e0 100644 --- a/src/core/hle/service/psc/time/system_clock.cpp +++ b/src/core/hle/service/psc/time/system_clock.cpp @@ -26,7 +26,9 @@ SystemClock::SystemClock(Core::System& system_, SystemClockCore& clock_core, boo } Result SystemClock::GetCurrentTime(Out<s64> out_time) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_time={}", *out_time); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); @@ -45,7 +47,9 @@ Result SystemClock::SetCurrentTime(s64 time) { } Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_context={}", *out_context); + }; R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(), ResultClockUninitialized); diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index 2f80030a4..9e0674f27 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp @@ -37,7 +37,9 @@ TimeZoneService::TimeZoneService(Core::System& system_, StandardSteadyClockCore& } Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_name) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_location_name={}", *out_location_name); + }; R_RETURN(m_time_zone.GetLocationName(*out_location_name)); } @@ -50,7 +52,9 @@ Result TimeZoneService::SetDeviceLocationName(const LocationName& location_name) } Result TimeZoneService::GetTotalLocationNameCount(Out<u32> out_count) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_count={}", *out_count); + }; R_RETURN(m_time_zone.GetTotalLocationCount(*out_count)); } @@ -69,17 +73,19 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, const LocationName& l } Result TimeZoneService::GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version) { - SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); }); + SCOPE_EXIT { + LOG_DEBUG(Service_Time, "called. out_rule_version={}", *out_rule_version); + }; R_RETURN(m_time_zone.GetRuleVersion(*out_rule_version)); } Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( Out<LocationName> out_location_name, Out<SteadyClockTimePoint> out_time_point) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. out_location_name={} out_time_point={}", *out_location_name, *out_time_point); - }); + }; R_TRY(m_time_zone.GetLocationName(*out_location_name)); R_RETURN(m_time_zone.GetTimePoint(*out_time_point)); @@ -116,10 +122,10 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle( Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time, Out<CalendarAdditionalInfo> out_additional_info, s64 time, InRule rule) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, *out_calendar_time, *out_additional_info); - }); + }; R_RETURN( m_time_zone.ToCalendarTime(*out_calendar_time, *out_additional_info, time, *rule.Get())); @@ -128,10 +134,10 @@ Result TimeZoneService::ToCalendarTime(Out<CalendarTime> out_calendar_time, Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time, Out<CalendarAdditionalInfo> out_additional_info, s64 time) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. time={} out_calendar_time={} out_additional_info={}", time, *out_calendar_time, *out_additional_info); - }); + }; R_RETURN(m_time_zone.ToCalendarTimeWithMyRule(*out_calendar_time, *out_additional_info, time)); } @@ -139,11 +145,11 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_ Result TimeZoneService::ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, const CalendarTime& calendar_time, InRule rule) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", calendar_time, *out_count, out_times[0], out_times[1]); - }); + }; R_RETURN( m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule)); @@ -152,11 +158,11 @@ Result TimeZoneService::ToPosixTime(Out<u32> out_count, Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times, const CalendarTime& calendar_time) { - SCOPE_EXIT({ + SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", calendar_time, *out_count, out_times[0], out_times[1]); - }); + }; R_RETURN( m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time)); diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 8c7f94c8c..0b41bbcb9 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -177,10 +177,10 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, Kernel::KPort::Register(m_system.Kernel(), port); // Ensure that our reference to the port is closed if we fail to register it. - SCOPE_EXIT({ + SCOPE_EXIT { port->GetClientPort().Close(); port->GetServerPort().Close(); - }); + }; // Register the object name with the kernel. R_TRY(Kernel::KObjectName::NewFromName(m_system.Kernel(), std::addressof(port->GetClientPort()), @@ -237,7 +237,9 @@ void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_thre } Result ServerManager::LoopProcess() { - SCOPE_EXIT({ m_stopped.Set(); }); + SCOPE_EXIT { + m_stopped.Set(); + }; R_RETURN(this->LoopProcessImpl()); } diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index f68c3c686..ce5e3b5b4 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -7,67 +7,10 @@ #include "common/settings.h" #include "core/core.h" #include "core/hle/ipc.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_server_port.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/service/acc/acc.h" -#include "core/hle/service/am/am.h" -#include "core/hle/service/aoc/aoc_u.h" -#include "core/hle/service/apm/apm.h" -#include "core/hle/service/audio/audio.h" -#include "core/hle/service/bcat/bcat.h" -#include "core/hle/service/bpc/bpc.h" -#include "core/hle/service/btdrv/btdrv.h" -#include "core/hle/service/btm/btm.h" -#include "core/hle/service/caps/caps.h" -#include "core/hle/service/erpt/erpt.h" -#include "core/hle/service/es/es.h" -#include "core/hle/service/eupld/eupld.h" -#include "core/hle/service/fatal/fatal.h" -#include "core/hle/service/fgm/fgm.h" -#include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/friend/friend.h" -#include "core/hle/service/glue/glue.h" -#include "core/hle/service/grc/grc.h" -#include "core/hle/service/hid/hid.h" #include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/jit/jit.h" -#include "core/hle/service/lbl/lbl.h" -#include "core/hle/service/ldn/ldn.h" -#include "core/hle/service/ldr/ldr.h" -#include "core/hle/service/lm/lm.h" -#include "core/hle/service/mig/mig.h" -#include "core/hle/service/mii/mii.h" -#include "core/hle/service/mm/mm_u.h" -#include "core/hle/service/mnpp/mnpp_app.h" -#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/ngc/ngc.h" -#include "core/hle/service/nifm/nifm.h" -#include "core/hle/service/nim/nim.h" -#include "core/hle/service/npns/npns.h" -#include "core/hle/service/ns/ns.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/olsc/olsc.h" -#include "core/hle/service/pcie/pcie.h" -#include "core/hle/service/pctl/pctl_module.h" -#include "core/hle/service/pcv/pcv.h" -#include "core/hle/service/pm/pm.h" -#include "core/hle/service/prepo/prepo.h" -#include "core/hle/service/psc/psc.h" -#include "core/hle/service/ptm/ptm.h" -#include "core/hle/service/ro/ro.h" #include "core/hle/service/service.h" -#include "core/hle/service/set/settings.h" #include "core/hle/service/sm/sm.h" -#include "core/hle/service/sockets/sockets.h" -#include "core/hle/service/spl/spl_module.h" -#include "core/hle/service/ssl/ssl.h" -#include "core/hle/service/usb/usb.h" -#include "core/hle/service/vi/vi.h" #include "core/reporter.h" namespace Service { @@ -208,81 +151,4 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, return result; } -/// Initialize Services -Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) - : hos_binder_driver_server{std::make_unique<Nvnflinger::HosBinderDriverServer>(system)}, - nv_flinger{std::make_unique<Nvnflinger::Nvnflinger>(system, *hos_binder_driver_server)} { - - auto& kernel = system.Kernel(); - - // Nvnflinger needs to be accessed by several services like Vi and AppletOE so we instantiate it - // here and pass it into the respective InstallInterfaces functions. - system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); - - // clang-format off - kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach(); - kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach(); - kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach(); - kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach(); - kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach(); - kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach(); - kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach(); - kernel.RunOnHostCoreProcess("vi", [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach(); - - kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(*nv_flinger, system); }); - kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); }); - // glue depends on settings and psc, so they must come first - kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); }); - kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); }); - // clang-format on -} - -Services::~Services() = default; - -void Services::KillNVNFlinger() { - nv_flinger->ShutdownLayers(); -} - } // namespace Service diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 22d1343d5..36aae1c79 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -28,11 +28,6 @@ namespace FileSystem { class FileSystemController; } -namespace Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Nvnflinger - namespace SM { class ServiceManager; } @@ -236,20 +231,4 @@ private: } }; -/** - * The purpose of this class is to own any objects that need to be shared across the other service - * implementations. Will be torn down when the global system instance is shutdown. - */ -class Services final { -public: - explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); - ~Services(); - - void KillNVNFlinger(); - -private: - std::unique_ptr<Nvnflinger::HosBinderDriverServer> hos_binder_driver_server; - std::unique_ptr<Nvnflinger::Nvnflinger> nv_flinger; -}; - } // namespace Service diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp new file mode 100644 index 000000000..d6c6eff50 --- /dev/null +++ b/src/core/hle/service/services.cpp @@ -0,0 +1,136 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/services.h" + +#include "core/hle/service/acc/acc.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/aoc/aoc_u.h" +#include "core/hle/service/apm/apm.h" +#include "core/hle/service/audio/audio.h" +#include "core/hle/service/bcat/bcat.h" +#include "core/hle/service/bpc/bpc.h" +#include "core/hle/service/btdrv/btdrv.h" +#include "core/hle/service/btm/btm.h" +#include "core/hle/service/caps/caps.h" +#include "core/hle/service/erpt/erpt.h" +#include "core/hle/service/es/es.h" +#include "core/hle/service/eupld/eupld.h" +#include "core/hle/service/fatal/fatal.h" +#include "core/hle/service/fgm/fgm.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/friend/friend.h" +#include "core/hle/service/glue/glue.h" +#include "core/hle/service/grc/grc.h" +#include "core/hle/service/hid/hid.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/jit/jit.h" +#include "core/hle/service/lbl/lbl.h" +#include "core/hle/service/ldn/ldn.h" +#include "core/hle/service/ldr/ldr.h" +#include "core/hle/service/lm/lm.h" +#include "core/hle/service/mig/mig.h" +#include "core/hle/service/mii/mii.h" +#include "core/hle/service/mm/mm_u.h" +#include "core/hle/service/mnpp/mnpp_app.h" +#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/ngc/ngc.h" +#include "core/hle/service/nifm/nifm.h" +#include "core/hle/service/nim/nim.h" +#include "core/hle/service/npns/npns.h" +#include "core/hle/service/ns/ns.h" +#include "core/hle/service/nvdrv/nvdrv.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/olsc/olsc.h" +#include "core/hle/service/omm/omm.h" +#include "core/hle/service/pcie/pcie.h" +#include "core/hle/service/pctl/pctl_module.h" +#include "core/hle/service/pcv/pcv.h" +#include "core/hle/service/pm/pm.h" +#include "core/hle/service/prepo/prepo.h" +#include "core/hle/service/psc/psc.h" +#include "core/hle/service/ptm/ptm.h" +#include "core/hle/service/ro/ro.h" +#include "core/hle/service/service.h" +#include "core/hle/service/set/settings.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/sockets/sockets.h" +#include "core/hle/service/spl/spl_module.h" +#include "core/hle/service/ssl/ssl.h" +#include "core/hle/service/usb/usb.h" +#include "core/hle/service/vi/vi.h" + +namespace Service { + +Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, + std::stop_token token) { + auto& kernel = system.Kernel(); + + system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); + + // clang-format off + kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach(); + kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach(); + + kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nvnflinger", [&] { Nvnflinger::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); }); + kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); }); + // clang-format on +} + +Services::~Services() = default; + +} // namespace Service diff --git a/src/core/hle/service/services.h b/src/core/hle/service/services.h new file mode 100644 index 000000000..a99fa1e53 --- /dev/null +++ b/src/core/hle/service/services.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/polyfill_thread.h" +#include "core/hle/service/sm/sm.h" + +namespace Service { + +/** + * The purpose of this class is to own any objects that need to be shared across the other service + * implementations. Will be torn down when the global system instance is shutdown. + */ +class Services final { +public: + explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, + std::stop_token token); + ~Services(); +}; + +} // namespace Service diff --git a/src/core/hle/service/set/key_code_map.h b/src/core/hle/service/set/key_code_map.h new file mode 100644 index 000000000..c76dc5729 --- /dev/null +++ b/src/core/hle/service/set/key_code_map.h @@ -0,0 +1,973 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <array> + +#include "common/common_types.h" + +namespace Service::Set { + +// Raw key codes map extracted from the settings sysmodule FW 16.2.0 +// This is nn::kpr::KeyCodeMap +using KeyCodeMap = std::array<u8, 0x1000>; + +constexpr KeyCodeMap KeyCodeMapChineseTraditional = { + 0x61, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x07, 0x31, 0x00, 0x00, 0xE5, 0x65, 0x00, 0x00, 0x01, 0x10, + 0x62, 0x00, 0x42, 0x00, 0x16, 0x31, 0x00, 0x00, 0x08, 0x67, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, + 0x43, 0x00, 0x0F, 0x31, 0x00, 0x00, 0xD1, 0x91, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, + 0x0E, 0x31, 0x00, 0x00, 0x28, 0x67, 0x00, 0x00, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x0D, 0x31, + 0x00, 0x00, 0x34, 0x6C, 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x11, 0x31, 0x00, 0x00, + 0x6B, 0x70, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x15, 0x31, 0x00, 0x00, 0x1F, 0x57, + 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x18, 0x31, 0x00, 0x00, 0xF9, 0x7A, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x1B, 0x31, 0x00, 0x00, 0x08, 0x62, 0x00, 0x00, 0x01, 0x10, + 0x6A, 0x00, 0x4A, 0x00, 0x28, 0x31, 0x00, 0x00, 0x41, 0x53, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, + 0x4B, 0x00, 0x1C, 0x31, 0x00, 0x00, 0x27, 0x59, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, + 0x20, 0x31, 0x00, 0x00, 0x2D, 0x4E, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x29, 0x31, + 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x19, 0x31, 0x00, 0x00, + 0x13, 0x5F, 0x00, 0x00, 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x1F, 0x31, 0x00, 0x00, 0xBA, 0x4E, + 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x23, 0x31, 0x00, 0x00, 0xC3, 0x5F, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x06, 0x31, 0x00, 0x00, 0x4B, 0x62, 0x00, 0x00, 0x01, 0x10, + 0x72, 0x00, 0x52, 0x00, 0x10, 0x31, 0x00, 0x00, 0xE3, 0x53, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, + 0x53, 0x00, 0x0B, 0x31, 0x00, 0x00, 0x38, 0x5C, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, + 0x14, 0x31, 0x00, 0x00, 0xFF, 0x5E, 0x00, 0x00, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x27, 0x31, + 0x00, 0x00, 0x71, 0x5C, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x12, 0x31, 0x00, 0x00, + 0x73, 0x59, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x0A, 0x31, 0x00, 0x00, 0x30, 0x75, + 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x0C, 0x31, 0x00, 0x00, 0xE3, 0x96, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x17, 0x31, 0x00, 0x00, 0x5C, 0x53, 0x00, 0x00, 0x01, 0x10, + 0x7A, 0x00, 0x5A, 0x00, 0x08, 0x31, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10, 0x31, 0x00, + 0x21, 0x00, 0x05, 0x31, 0x00, 0x00, 0x31, 0x00, 0x21, 0x00, 0x00, 0x10, 0x32, 0x00, 0x40, 0x00, + 0x09, 0x31, 0x00, 0x00, 0x32, 0x00, 0x40, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0xC7, 0x02, + 0x00, 0x00, 0x33, 0x00, 0x23, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xCB, 0x02, 0x00, 0x00, + 0x34, 0x00, 0x24, 0x00, 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x13, 0x31, 0x00, 0x00, 0x35, 0x00, + 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0xCA, 0x02, 0x00, 0x00, 0x36, 0x00, 0x5E, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0xD9, 0x02, 0x00, 0x00, 0x37, 0x00, 0x26, 0x00, 0x00, 0x10, + 0x38, 0x00, 0x2A, 0x00, 0x1A, 0x31, 0x00, 0x00, 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00, + 0x28, 0x00, 0x1E, 0x31, 0x00, 0x00, 0x39, 0x00, 0x28, 0x00, 0x00, 0x10, 0x30, 0x00, 0x29, 0x00, + 0x22, 0x31, 0x00, 0x00, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, + 0x2D, 0x00, 0x5F, 0x00, 0x26, 0x31, 0x00, 0x00, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00, + 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x00, 0x10, 0x5B, 0x00, 0x7B, 0x00, + 0x5B, 0x00, 0x7B, 0x00, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x5D, 0x00, + 0x7D, 0x00, 0x5D, 0x00, 0x7D, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, + 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, + 0x7C, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x24, 0x31, 0x00, 0x00, 0x3B, 0x00, 0x3A, 0x00, + 0x00, 0x10, 0x27, 0x00, 0x22, 0x00, 0x27, 0x00, 0x22, 0x00, 0x27, 0x00, 0x22, 0x00, 0x00, 0x10, + 0x60, 0x00, 0x7E, 0x00, 0x60, 0x00, 0x7E, 0x00, 0x60, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x2C, 0x00, + 0x3C, 0x00, 0x1D, 0x31, 0x00, 0x00, 0x2C, 0x00, 0x3C, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3E, 0x00, + 0x21, 0x31, 0x00, 0x00, 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x25, 0x31, + 0x00, 0x00, 0x2F, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, + 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, + 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, + 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, + 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, + 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapChineseSimplified = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x01, 0x10, 0x63, 0x00, + 0x43, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x01, 0x10, + 0x66, 0x00, 0x46, 0x00, 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x01, 0x10, 0x6B, 0x00, + 0x4B, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x01, 0x10, + 0x6E, 0x00, 0x4E, 0x00, 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x01, 0x10, 0x73, 0x00, + 0x53, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x01, 0x10, + 0x76, 0x00, 0x56, 0x00, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x10, 0x31, 0x00, + 0x21, 0x00, 0x00, 0x10, 0x32, 0x00, 0x40, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x00, 0x10, + 0x34, 0x00, 0x24, 0x00, 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00, + 0x28, 0x00, 0x00, 0x10, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00, + 0x2B, 0x00, 0x00, 0x10, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x00, 0x10, + 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, + 0x00, 0x10, 0x27, 0x00, 0x22, 0x00, 0x00, 0x10, 0x60, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x2C, 0x00, + 0x3C, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, + 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x36, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapKorean = { + 0x11, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x41, 0x31, 0x41, 0x31, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, + 0x60, 0x31, 0x60, 0x31, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x4A, 0x31, 0x4A, 0x31, 0x01, 0x10, + 0x64, 0x00, 0x44, 0x00, 0x47, 0x31, 0x47, 0x31, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x37, 0x31, + 0x38, 0x31, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x39, 0x31, 0x39, 0x31, 0x01, 0x10, 0x67, 0x00, + 0x47, 0x00, 0x4E, 0x31, 0x4E, 0x31, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x57, 0x31, 0x57, 0x31, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x51, 0x31, 0x51, 0x31, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, + 0x53, 0x31, 0x53, 0x31, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x4F, 0x31, 0x4F, 0x31, 0x01, 0x10, + 0x6C, 0x00, 0x4C, 0x00, 0x63, 0x31, 0x63, 0x31, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x61, 0x31, + 0x61, 0x31, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x5C, 0x31, 0x5C, 0x31, 0x01, 0x10, 0x6F, 0x00, + 0x4F, 0x00, 0x50, 0x31, 0x52, 0x31, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x54, 0x31, 0x56, 0x31, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x42, 0x31, 0x43, 0x31, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, + 0x31, 0x31, 0x32, 0x31, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x34, 0x31, 0x34, 0x31, 0x01, 0x10, + 0x74, 0x00, 0x54, 0x00, 0x45, 0x31, 0x46, 0x31, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x55, 0x31, + 0x55, 0x31, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x4D, 0x31, 0x4D, 0x31, 0x01, 0x10, 0x77, 0x00, + 0x57, 0x00, 0x48, 0x31, 0x49, 0x31, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x4C, 0x31, 0x4C, 0x31, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x5B, 0x31, 0x5B, 0x31, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, + 0x4B, 0x31, 0x4B, 0x31, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x31, 0x00, 0x21, 0x00, 0x00, 0x10, + 0x32, 0x00, 0x40, 0x00, 0x32, 0x00, 0x40, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x33, 0x00, + 0x23, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x34, 0x00, 0x24, 0x00, 0x00, 0x10, 0x35, 0x00, + 0x25, 0x00, 0x35, 0x00, 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0x36, 0x00, 0x5E, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x37, 0x00, 0x26, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, + 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x39, 0x00, 0x28, 0x00, 0x00, 0x10, + 0x30, 0x00, 0x29, 0x00, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, + 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x00, 0x10, + 0x5B, 0x00, 0x7B, 0x00, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x5D, 0x00, + 0x7D, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x5C, 0x00, + 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3A, 0x00, + 0x00, 0x10, 0x27, 0x00, 0x22, 0x00, 0x27, 0x00, 0x22, 0x00, 0x00, 0x10, 0x60, 0x00, 0x7E, 0x00, + 0x60, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0x2C, 0x00, 0x3C, 0x00, 0x00, 0x10, + 0x2E, 0x00, 0x3E, 0x00, 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x2F, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, + 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, + 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapRussian = { + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x10, 0x61, 0x00, 0x41, 0x00, 0x44, 0x04, 0x24, 0x04, 0x11, 0x10, 0x62, 0x00, 0x42, 0x00, + 0x38, 0x04, 0x18, 0x04, 0x11, 0x10, 0x63, 0x00, 0x43, 0x00, 0x41, 0x04, 0x21, 0x04, 0x11, 0x10, + 0x64, 0x00, 0x44, 0x00, 0x32, 0x04, 0x12, 0x04, 0x11, 0x10, 0x65, 0x00, 0x45, 0x00, 0x43, 0x04, + 0x23, 0x04, 0x11, 0x10, 0x66, 0x00, 0x46, 0x00, 0x30, 0x04, 0x10, 0x04, 0x11, 0x10, 0x67, 0x00, + 0x47, 0x00, 0x3F, 0x04, 0x1F, 0x04, 0x11, 0x10, 0x68, 0x00, 0x48, 0x00, 0x40, 0x04, 0x20, 0x04, + 0x11, 0x10, 0x69, 0x00, 0x49, 0x00, 0x48, 0x04, 0x28, 0x04, 0x11, 0x10, 0x6A, 0x00, 0x4A, 0x00, + 0x3E, 0x04, 0x1E, 0x04, 0x11, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x3B, 0x04, 0x1B, 0x04, 0x11, 0x10, + 0x6C, 0x00, 0x4C, 0x00, 0x34, 0x04, 0x14, 0x04, 0x11, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x4C, 0x04, + 0x2C, 0x04, 0x11, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x42, 0x04, 0x22, 0x04, 0x11, 0x10, 0x6F, 0x00, + 0x4F, 0x00, 0x49, 0x04, 0x29, 0x04, 0x11, 0x10, 0x70, 0x00, 0x50, 0x00, 0x37, 0x04, 0x17, 0x04, + 0x11, 0x10, 0x71, 0x00, 0x51, 0x00, 0x39, 0x04, 0x19, 0x04, 0x11, 0x10, 0x72, 0x00, 0x52, 0x00, + 0x3A, 0x04, 0x1A, 0x04, 0x11, 0x10, 0x73, 0x00, 0x53, 0x00, 0x4B, 0x04, 0x2B, 0x04, 0x11, 0x10, + 0x74, 0x00, 0x54, 0x00, 0x35, 0x04, 0x15, 0x04, 0x11, 0x10, 0x75, 0x00, 0x55, 0x00, 0x33, 0x04, + 0x13, 0x04, 0x11, 0x10, 0x76, 0x00, 0x56, 0x00, 0x3C, 0x04, 0x1C, 0x04, 0x11, 0x10, 0x77, 0x00, + 0x57, 0x00, 0x46, 0x04, 0x26, 0x04, 0x11, 0x10, 0x78, 0x00, 0x58, 0x00, 0x47, 0x04, 0x27, 0x04, + 0x11, 0x10, 0x79, 0x00, 0x59, 0x00, 0x3D, 0x04, 0x1D, 0x04, 0x11, 0x10, 0x7A, 0x00, 0x5A, 0x00, + 0x4F, 0x04, 0x2F, 0x04, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x31, 0x00, 0x21, 0x00, 0x00, 0x10, + 0x32, 0x00, 0x40, 0x00, 0x32, 0x00, 0x22, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x33, 0x00, + 0x16, 0x21, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x34, 0x00, 0x3B, 0x00, 0x00, 0x10, 0x35, 0x00, + 0x25, 0x00, 0x35, 0x00, 0x25, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0x36, 0x00, 0x3A, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x37, 0x00, 0x3F, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, + 0x38, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x39, 0x00, 0x28, 0x00, 0x00, 0x10, + 0x30, 0x00, 0x29, 0x00, 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, + 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x3D, 0x00, 0x2B, 0x00, 0x10, 0x10, + 0x5B, 0x00, 0x7B, 0x00, 0x45, 0x04, 0x25, 0x04, 0x10, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x4A, 0x04, + 0x2A, 0x04, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x5C, 0x00, + 0x7C, 0x00, 0x5C, 0x00, 0x2F, 0x00, 0x10, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x36, 0x04, 0x16, 0x04, + 0x10, 0x10, 0x27, 0x00, 0x22, 0x00, 0x4D, 0x04, 0x2D, 0x04, 0x10, 0x10, 0x60, 0x00, 0x7E, 0x00, + 0x51, 0x04, 0x01, 0x04, 0x10, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0x31, 0x04, 0x11, 0x04, 0x10, 0x10, + 0x2E, 0x00, 0x3E, 0x00, 0x4E, 0x04, 0x2E, 0x04, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x2E, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, + 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, + 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x00, + 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapPortuguese = { + 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x40, 0x00, + 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0xA3, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xA7, 0x00, + 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, 0x5B, 0x00, + 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x5D, 0x00, 0x00, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x7D, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x10, 0xAB, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x08, 0x03, + 0x00, 0x10, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x03, 0x03, 0x02, 0x03, 0x00, 0x00, + 0x00, 0x10, 0x03, 0x03, 0x02, 0x03, 0x00, 0x00, 0x01, 0x10, 0xE7, 0x00, 0xC7, 0x00, 0x00, 0x00, + 0x00, 0x10, 0xBA, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapItalian = { + 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, + 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6F, 0x00, + 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x32, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x33, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x35, 0x00, + 0x25, 0x00, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xEC, 0x00, 0x5E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x10, + 0xE8, 0x00, 0xE9, 0x00, 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x5D, 0x00, + 0x7D, 0x00, 0x00, 0x10, 0xF9, 0x00, 0xA7, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF9, 0x00, + 0xA7, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF2, 0x00, 0xE7, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x10, 0xE0, 0x00, 0xB0, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, + 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, + 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapGerman = { + 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0xB5, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x40, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x10, 0x32, 0x00, 0x22, 0x00, 0xB2, 0x00, + 0x01, 0x10, 0x33, 0x00, 0xA7, 0x00, 0xB3, 0x00, 0x01, 0x10, 0x34, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x7B, 0x00, 0x01, 0x10, 0x38, 0x00, 0x28, 0x00, 0x5B, 0x00, + 0x01, 0x10, 0x39, 0x00, 0x29, 0x00, 0x5D, 0x00, 0x01, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x7D, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x01, 0x10, 0xDF, 0x00, 0x3F, 0x00, 0x5C, 0x00, + 0x00, 0x10, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x01, 0x10, 0xFC, 0x00, 0xDC, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x7E, 0x00, 0x01, 0x10, 0x23, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x23, 0x00, 0x27, 0x00, 0x00, 0x00, 0x01, 0x10, 0xF6, 0x00, 0xD6, 0x00, 0x00, 0x00, + 0x01, 0x10, 0xE4, 0x00, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x03, 0xB0, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapSpanishLatin = { + 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x40, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, 0x5C, 0x00, + 0x00, 0x10, 0xBF, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x03, 0x08, 0x03, 0x00, 0x00, + 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x7E, 0x00, 0x00, 0x10, 0x7D, 0x00, 0x5D, 0x00, 0x00, 0x03, + 0x00, 0x10, 0x7D, 0x00, 0x5D, 0x00, 0x00, 0x03, 0x01, 0x10, 0xF1, 0x00, 0xD1, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x7B, 0x00, 0x5B, 0x00, 0x02, 0x03, 0x00, 0x10, 0x7C, 0x00, 0xB0, 0x00, 0xAC, 0x00, + 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapSpanish = { + 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x7C, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x40, 0x00, + 0x00, 0x10, 0x33, 0x00, 0xB7, 0x00, 0x23, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x03, 0x03, + 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0xAC, 0x20, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0xAC, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x39, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x00, 0x3D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x27, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x10, 0xA1, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x02, 0x03, 0x5B, 0x00, + 0x00, 0x10, 0x2B, 0x00, 0x2A, 0x00, 0x5D, 0x00, 0x01, 0x10, 0xE7, 0x00, 0xC7, 0x00, 0x7D, 0x00, + 0x01, 0x10, 0xE7, 0x00, 0xC7, 0x00, 0x7D, 0x00, 0x01, 0x10, 0xF1, 0x00, 0xD1, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x03, 0x08, 0x03, 0x7B, 0x00, 0x00, 0x10, 0xBA, 0x00, 0xAA, 0x00, 0x5C, 0x00, + 0x00, 0x10, 0x2C, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapFrenchCa = { + 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0xB5, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0xA7, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0xB6, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0xB1, 0x00, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, 0x40, 0x00, + 0x00, 0x10, 0x33, 0x00, 0x2F, 0x00, 0xA3, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xA2, 0x00, + 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0xA4, 0x00, 0x00, 0x10, 0x36, 0x00, 0x3F, 0x00, 0xAC, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0xA6, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, 0xB2, 0x00, + 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0xB3, 0x00, 0x00, 0x10, 0x30, 0x00, 0x29, 0x00, 0xBC, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, 0xBD, 0x00, + 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0xBE, 0x00, 0x00, 0x10, 0x02, 0x03, 0x02, 0x03, 0x5B, 0x00, + 0x00, 0x10, 0x27, 0x03, 0x08, 0x03, 0x5D, 0x00, 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x7D, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x7D, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x7E, 0x00, + 0x00, 0x10, 0x00, 0x03, 0x00, 0x03, 0x7B, 0x00, 0x00, 0x10, 0x23, 0x00, 0x7C, 0x00, 0x5C, 0x00, + 0x00, 0x10, 0x2C, 0x00, 0x27, 0x00, 0xAF, 0x00, 0x00, 0x10, 0x2E, 0x00, 0x2E, 0x00, 0x2D, 0x00, + 0x01, 0x10, 0xE9, 0x00, 0xC9, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0xAB, 0x00, 0xBB, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapFrench = { + 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0xAC, 0x20, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x2C, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x26, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x32, 0x00, 0x03, 0x03, + 0x01, 0x10, 0x22, 0x00, 0x33, 0x00, 0x23, 0x00, 0x01, 0x10, 0x27, 0x00, 0x34, 0x00, 0x7B, 0x00, + 0x01, 0x10, 0x28, 0x00, 0x35, 0x00, 0x5B, 0x00, 0x01, 0x10, 0x2D, 0x00, 0x36, 0x00, 0x7C, 0x00, + 0x01, 0x10, 0xE8, 0x00, 0x37, 0x00, 0x00, 0x03, 0x01, 0x10, 0x5F, 0x00, 0x38, 0x00, 0x5C, 0x00, + 0x01, 0x10, 0xE7, 0x00, 0x39, 0x00, 0x5E, 0x00, 0x01, 0x10, 0xE0, 0x00, 0x30, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x01, 0x10, 0x29, 0x00, 0xB0, 0x00, 0x5D, 0x00, + 0x01, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x7D, 0x00, 0x01, 0x10, 0x02, 0x03, 0x08, 0x03, 0x00, 0x00, + 0x01, 0x10, 0x24, 0x00, 0xA3, 0x00, 0xA4, 0x00, 0x01, 0x10, 0x2A, 0x00, 0xB5, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x2A, 0x00, 0xB5, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x01, 0x10, 0xF9, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x3B, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x01, 0x10, 0x3A, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x21, 0x00, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, + 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x3C, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapEnglishUk = { + 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x61, 0x00, 0x41, 0x00, 0xE1, 0x00, 0xC1, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x64, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x65, 0x00, 0x45, 0x00, 0xE9, 0x00, + 0xC9, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x69, 0x00, 0x49, 0x00, 0xED, 0x00, 0xCD, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x6C, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x6F, 0x00, + 0x4F, 0x00, 0xF3, 0x00, 0xD3, 0x00, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x74, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x75, 0x00, 0x55, 0x00, 0xFA, 0x00, + 0xDA, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x7A, 0x00, 0x5A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x32, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x33, 0x00, 0xA3, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x10, 0x35, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x30, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x5B, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x23, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x23, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x27, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x60, 0x00, 0xAC, 0x00, + 0xA6, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, + 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, + 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapJapanese = { + 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x61, 0x00, 0x41, 0x00, 0x61, 0x30, 0x61, 0x30, 0xC1, 0x30, 0xC1, 0x30, 0x01, 0x10, + 0x62, 0x00, 0x42, 0x00, 0x53, 0x30, 0x53, 0x30, 0xB3, 0x30, 0xB3, 0x30, 0x01, 0x10, 0x63, 0x00, + 0x43, 0x00, 0x5D, 0x30, 0x5D, 0x30, 0xBD, 0x30, 0xBD, 0x30, 0x01, 0x10, 0x64, 0x00, 0x44, 0x00, + 0x57, 0x30, 0x57, 0x30, 0xB7, 0x30, 0xB7, 0x30, 0x01, 0x10, 0x65, 0x00, 0x45, 0x00, 0x44, 0x30, + 0x43, 0x30, 0xA4, 0x30, 0xA3, 0x30, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x6F, 0x30, 0x6F, 0x30, + 0xCF, 0x30, 0xCF, 0x30, 0x01, 0x10, 0x67, 0x00, 0x47, 0x00, 0x4D, 0x30, 0x4D, 0x30, 0xAD, 0x30, + 0xAD, 0x30, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x4F, 0x30, 0x4F, 0x30, 0xAF, 0x30, 0xAF, 0x30, + 0x01, 0x10, 0x69, 0x00, 0x49, 0x00, 0x6B, 0x30, 0x6B, 0x30, 0xCB, 0x30, 0xCB, 0x30, 0x01, 0x10, + 0x6A, 0x00, 0x4A, 0x00, 0x7E, 0x30, 0x7E, 0x30, 0xDE, 0x30, 0xDE, 0x30, 0x01, 0x10, 0x6B, 0x00, + 0x4B, 0x00, 0x6E, 0x30, 0x6E, 0x30, 0xCE, 0x30, 0xCE, 0x30, 0x01, 0x10, 0x6C, 0x00, 0x4C, 0x00, + 0x8A, 0x30, 0x8A, 0x30, 0xEA, 0x30, 0xEA, 0x30, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0x82, 0x30, + 0x82, 0x30, 0xE2, 0x30, 0xE2, 0x30, 0x01, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0x7F, 0x30, 0x7F, 0x30, + 0xDF, 0x30, 0xDF, 0x30, 0x01, 0x10, 0x6F, 0x00, 0x4F, 0x00, 0x89, 0x30, 0x89, 0x30, 0xE9, 0x30, + 0xE9, 0x30, 0x01, 0x10, 0x70, 0x00, 0x50, 0x00, 0x5B, 0x30, 0x5B, 0x30, 0xBB, 0x30, 0xBB, 0x30, + 0x01, 0x10, 0x71, 0x00, 0x51, 0x00, 0x5F, 0x30, 0x5F, 0x30, 0xBF, 0x30, 0xBF, 0x30, 0x01, 0x10, + 0x72, 0x00, 0x52, 0x00, 0x59, 0x30, 0x59, 0x30, 0xB9, 0x30, 0xB9, 0x30, 0x01, 0x10, 0x73, 0x00, + 0x53, 0x00, 0x68, 0x30, 0x68, 0x30, 0xC8, 0x30, 0xC8, 0x30, 0x01, 0x10, 0x74, 0x00, 0x54, 0x00, + 0x4B, 0x30, 0x4B, 0x30, 0xAB, 0x30, 0xAB, 0x30, 0x01, 0x10, 0x75, 0x00, 0x55, 0x00, 0x6A, 0x30, + 0x6A, 0x30, 0xCA, 0x30, 0xCA, 0x30, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x72, 0x30, 0x72, 0x30, + 0xD2, 0x30, 0xD2, 0x30, 0x01, 0x10, 0x77, 0x00, 0x57, 0x00, 0x66, 0x30, 0x66, 0x30, 0xC6, 0x30, + 0xC6, 0x30, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x55, 0x30, 0x55, 0x30, 0xB5, 0x30, 0xB5, 0x30, + 0x01, 0x10, 0x79, 0x00, 0x59, 0x00, 0x93, 0x30, 0x93, 0x30, 0xF3, 0x30, 0xF3, 0x30, 0x01, 0x10, + 0x7A, 0x00, 0x5A, 0x00, 0x64, 0x30, 0x63, 0x30, 0xC4, 0x30, 0xC3, 0x30, 0x00, 0x10, 0x31, 0x00, + 0x21, 0x00, 0x6C, 0x30, 0x6C, 0x30, 0xCC, 0x30, 0xCC, 0x30, 0x00, 0x10, 0x32, 0x00, 0x22, 0x00, + 0x75, 0x30, 0x75, 0x30, 0xD5, 0x30, 0xD5, 0x30, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0x42, 0x30, + 0x41, 0x30, 0xA2, 0x30, 0xA1, 0x30, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0x46, 0x30, 0x45, 0x30, + 0xA6, 0x30, 0xA5, 0x30, 0x00, 0x10, 0x35, 0x00, 0x25, 0x00, 0x48, 0x30, 0x47, 0x30, 0xA8, 0x30, + 0xA7, 0x30, 0x00, 0x10, 0x36, 0x00, 0x26, 0x00, 0x4A, 0x30, 0x49, 0x30, 0xAA, 0x30, 0xA9, 0x30, + 0x00, 0x10, 0x37, 0x00, 0x27, 0x00, 0x84, 0x30, 0x83, 0x30, 0xE4, 0x30, 0xE3, 0x30, 0x00, 0x10, + 0x38, 0x00, 0x28, 0x00, 0x86, 0x30, 0x85, 0x30, 0xE6, 0x30, 0xE5, 0x30, 0x00, 0x10, 0x39, 0x00, + 0x29, 0x00, 0x88, 0x30, 0x87, 0x30, 0xE8, 0x30, 0xE7, 0x30, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, + 0x8F, 0x30, 0x92, 0x30, 0xEF, 0x30, 0xF2, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, + 0x2D, 0x00, 0x3D, 0x00, 0x7B, 0x30, 0x7B, 0x30, 0xDB, 0x30, 0xDB, 0x30, 0x00, 0x10, 0x5E, 0x00, + 0x7E, 0x00, 0x78, 0x30, 0x78, 0x30, 0xD8, 0x30, 0xD8, 0x30, 0x00, 0x10, 0x40, 0x00, 0x60, 0x00, + 0x9E, 0xFF, 0x9E, 0xFF, 0x9E, 0xFF, 0x9E, 0xFF, 0x00, 0x10, 0x5B, 0x00, 0x7B, 0x00, 0x9F, 0xFF, + 0x62, 0xFF, 0x9F, 0xFF, 0x62, 0xFF, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x80, 0x30, 0x63, 0xFF, + 0xE0, 0x30, 0x63, 0xFF, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0x80, 0x30, 0x63, 0xFF, 0xE0, 0x30, + 0x63, 0xFF, 0x00, 0x10, 0x3B, 0x00, 0x2B, 0x00, 0x8C, 0x30, 0x8C, 0x30, 0xEC, 0x30, 0xEC, 0x30, + 0x00, 0x10, 0x3A, 0x00, 0x2A, 0x00, 0x51, 0x30, 0x51, 0x30, 0xB1, 0x30, 0xB1, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2C, 0x00, + 0x3C, 0x00, 0x6D, 0x30, 0x64, 0xFF, 0xCD, 0x30, 0x64, 0xFF, 0x00, 0x10, 0x2E, 0x00, 0x3E, 0x00, + 0x8B, 0x30, 0x61, 0xFF, 0xEB, 0x30, 0x61, 0xFF, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0x81, 0x30, + 0x65, 0xFF, 0xE1, 0x30, 0x65, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, + 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, + 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, 0x2B, 0x00, 0x2B, 0x00, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, + 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, + 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x37, 0x00, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, + 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x3D, 0x00, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x5F, 0x00, + 0x8D, 0x30, 0x8D, 0x30, 0xED, 0x30, 0xED, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x70, 0xFF, 0x70, 0xFF, + 0x70, 0xFF, 0x70, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +constexpr KeyCodeMap KeyCodeMapEnglishUsInternational = { + 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x61, 0x00, 0x41, 0x00, 0xE1, 0x00, 0xC1, 0x00, 0x01, 0x10, 0x62, 0x00, 0x42, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x63, 0x00, 0x43, 0x00, 0xA9, 0x00, 0xA2, 0x00, 0x03, 0x10, + 0x64, 0x00, 0x44, 0x00, 0xF0, 0x00, 0xD0, 0x00, 0x03, 0x10, 0x65, 0x00, 0x45, 0x00, 0xE9, 0x00, + 0xC9, 0x00, 0x01, 0x10, 0x66, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x67, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x69, 0x00, 0x49, 0x00, 0xED, 0x00, 0xCD, 0x00, 0x01, 0x10, 0x6A, 0x00, 0x4A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x6B, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, + 0x6C, 0x00, 0x4C, 0x00, 0xF8, 0x00, 0xD8, 0x00, 0x01, 0x10, 0x6D, 0x00, 0x4D, 0x00, 0xB5, 0x00, + 0x00, 0x00, 0x03, 0x10, 0x6E, 0x00, 0x4E, 0x00, 0xF1, 0x00, 0xD1, 0x00, 0x03, 0x10, 0x6F, 0x00, + 0x4F, 0x00, 0xF3, 0x00, 0xD3, 0x00, 0x03, 0x10, 0x70, 0x00, 0x50, 0x00, 0xF6, 0x00, 0xD6, 0x00, + 0x03, 0x10, 0x71, 0x00, 0x51, 0x00, 0xE4, 0x00, 0xC4, 0x00, 0x01, 0x10, 0x72, 0x00, 0x52, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x01, 0x10, 0x73, 0x00, 0x53, 0x00, 0xDF, 0x00, 0xA7, 0x00, 0x03, 0x10, + 0x74, 0x00, 0x54, 0x00, 0xFE, 0x00, 0xDE, 0x00, 0x03, 0x10, 0x75, 0x00, 0x55, 0x00, 0xFA, 0x00, + 0xDA, 0x00, 0x01, 0x10, 0x76, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10, 0x77, 0x00, + 0x57, 0x00, 0xE5, 0x00, 0xC5, 0x00, 0x01, 0x10, 0x78, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x79, 0x00, 0x59, 0x00, 0xFC, 0x00, 0xDC, 0x00, 0x03, 0x10, 0x7A, 0x00, 0x5A, 0x00, + 0xE6, 0x00, 0xC6, 0x00, 0x00, 0x10, 0x31, 0x00, 0x21, 0x00, 0xA1, 0x00, 0xB9, 0x00, 0x00, 0x10, + 0x32, 0x00, 0x40, 0x00, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x10, 0x33, 0x00, 0x23, 0x00, 0xB3, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x34, 0x00, 0x24, 0x00, 0xA4, 0x00, 0xA3, 0x00, 0x00, 0x10, 0x35, 0x00, + 0x25, 0x00, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x10, 0x36, 0x00, 0x02, 0x03, 0xBC, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x37, 0x00, 0x26, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00, 0x2A, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x00, 0x28, 0x00, 0x18, 0x20, 0x00, 0x00, 0x00, 0x10, + 0x30, 0x00, 0x29, 0x00, 0x19, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x5F, 0x00, + 0xA5, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3D, 0x00, 0x2B, 0x00, 0xD7, 0x00, 0xF7, 0x00, 0x00, 0x10, + 0x5B, 0x00, 0x7B, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5D, 0x00, 0x7D, 0x00, 0xBB, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0xAC, 0x00, 0xA6, 0x00, 0x00, 0x10, 0x5C, 0x00, + 0x7C, 0x00, 0xAC, 0x00, 0xA6, 0x00, 0x00, 0x10, 0x3B, 0x00, 0x3A, 0x00, 0xB6, 0x00, 0xB0, 0x00, + 0x00, 0x10, 0x0D, 0x03, 0x0E, 0x03, 0xB4, 0x00, 0xA8, 0x00, 0x00, 0x10, 0x00, 0x03, 0x03, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x2C, 0x00, 0x3C, 0x00, 0xE7, 0x00, 0xC7, 0x00, 0x00, 0x10, + 0x2E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2F, 0x00, 0x3F, 0x00, 0xBF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x00, 0x10, 0x2A, 0x00, 0x2A, 0x00, + 0x2A, 0x00, 0x2A, 0x00, 0x00, 0x10, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x10, + 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, 0x32, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x33, 0x00, + 0xFF, 0x20, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0xFF, 0x20, 0x20, 0x00, 0x35, 0x00, + 0x20, 0x00, 0x35, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x36, 0x00, 0xFF, 0x20, + 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x37, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x39, 0x00, 0xFF, 0x20, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFF, 0x20, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2E, 0x00, + 0x00, 0x10, 0x5C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +} // namespace Service::Set diff --git a/src/core/hle/service/set/private_settings.h b/src/core/hle/service/set/private_settings.h deleted file mode 100644 index b02291ce7..000000000 --- a/src/core/hle/service/set/private_settings.h +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> - -#include "common/bit_field.h" -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/uuid.h" -#include "core/hle/service/psc/time/common.h" - -namespace Service::Set { - -/// This is nn::settings::system::InitialLaunchFlag -struct InitialLaunchFlag { - union { - u32 raw{}; - - BitField<0, 1, u32> InitialLaunchCompletionFlag; - BitField<8, 1, u32> InitialLaunchUserAdditionFlag; - BitField<16, 1, u32> InitialLaunchTimestampFlag; - }; -}; -static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size"); - -/// This is nn::settings::system::InitialLaunchSettings -struct InitialLaunchSettings { - InitialLaunchFlag flags; - INSERT_PADDING_BYTES(0x4); - Service::PSC::Time::SteadyClockTimePoint timestamp; -}; -static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size"); - -#pragma pack(push, 4) -struct InitialLaunchSettingsPacked { - InitialLaunchFlag flags; - Service::PSC::Time::SteadyClockTimePoint timestamp; -}; -#pragma pack(pop) -static_assert(sizeof(InitialLaunchSettingsPacked) == 0x1C, - "InitialLaunchSettingsPacked is incorrect size"); - -struct PrivateSettings { - std::array<u8, 0x10> reserved_00; - - // nn::settings::system::InitialLaunchSettings - InitialLaunchSettings initial_launch_settings; - - std::array<u8, 0x20> reserved_30; - - Common::UUID external_clock_source_id; - s64 shutdown_rtc_value; - s64 external_steady_clock_internal_offset; - - std::array<u8, 0x60> reserved_70; - - // nn::settings::system::PlatformRegion - std::array<u8, 0x4> platform_region; - - std::array<u8, 0x4> reserved_D4; -}; -static_assert(offsetof(PrivateSettings, initial_launch_settings) == 0x10); -static_assert(offsetof(PrivateSettings, external_clock_source_id) == 0x50); -static_assert(offsetof(PrivateSettings, reserved_70) == 0x70); -static_assert(offsetof(PrivateSettings, platform_region) == 0xD0); -static_assert(sizeof(PrivateSettings) == 0xD8, "PrivateSettings has the wrong size!"); - -PrivateSettings DefaultPrivateSettings(); - -} // namespace Service::Set diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h index 40230182a..a5b1552a5 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.h +++ b/src/core/hle/service/set/setting_formats/system_settings.h @@ -244,7 +244,7 @@ struct SystemSettings { INSERT_PADDING_BYTES(0x60); // Reserved // nn::settings::system::AccountNotificationSettings - u32 account_notification_settings_count; + s32 account_notification_settings_count; INSERT_PADDING_BYTES(0xC); // Reserved std::array<AccountNotificationSettings, 8> account_notification_settings; INSERT_PADDING_BYTES(0x140); // Reserved @@ -308,7 +308,7 @@ struct SystemSettings { INSERT_PADDING_BYTES(0x34); // Reserved // nn::settings::system::EulaVersion - u32 eula_version_count; + s32 eula_version_count; INSERT_PADDING_BYTES(0xC); // Reserved std::array<EulaVersion, 32> eula_versions; INSERT_PADDING_BYTES(0x200); // Reserved diff --git a/src/core/hle/service/set/settings_server.cpp b/src/core/hle/service/set/settings_server.cpp index b2caa00ff..a9321b98d 100644 --- a/src/core/hle/service/set/settings_server.cpp +++ b/src/core/hle/service/set/settings_server.cpp @@ -6,7 +6,9 @@ #include <chrono> #include "common/logging/log.h" #include "common/settings.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/set/key_code_map.h" #include "core/hle/service/set/settings_server.h" namespace Service::Set { @@ -15,43 +17,69 @@ constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; constexpr Result ResultInvalidLanguage{ErrorModule::Settings, 625}; - -void PushResponseLanguageCode(HLERequestContext& ctx, std::size_t num_language_codes) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(num_language_codes)); -} - -void GetAvailableLanguageCodesImpl(HLERequestContext& ctx, std::size_t max_entries) { - const std::size_t requested_amount = ctx.GetWriteBufferNumElements<LanguageCode>(); - const std::size_t max_amount = std::min(requested_amount, max_entries); - const std::size_t copy_amount = std::min(available_language_codes.size(), max_amount); - const std::size_t copy_size = copy_amount * sizeof(LanguageCode); - - ctx.WriteBuffer(available_language_codes.data(), copy_size); - PushResponseLanguageCode(ctx, copy_amount); -} - -void GetKeyCodeMapImpl(HLERequestContext& ctx) { - const auto language_code = - available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]; - const auto key_code = - std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), - [=](const auto& element) { return element.first == language_code; }); - KeyboardLayout layout = KeyboardLayout::EnglishUs; - if (key_code == language_to_layout.cend()) { - LOG_ERROR(Service_SET, - "Could not find keyboard layout for language index {}, defaulting to English us", - Settings::values.language_index.GetValue()); - } else { - layout = key_code->second; +constexpr Result ResultNullPointer{ErrorModule::Settings, 1261}; + +Result GetKeyCodeMapImpl(KeyCodeMap& out_key_code_map, KeyboardLayout keyboard_layout, + LanguageCode language_code) { + switch (keyboard_layout) { + case KeyboardLayout::Japanese: + out_key_code_map = KeyCodeMapJapanese; + R_SUCCEED(); + case KeyboardLayout::EnglishUs: + out_key_code_map = KeyCodeMapEnglishUsInternational; + if (language_code == LanguageCode::KO) { + out_key_code_map = KeyCodeMapKorean; + } + if (language_code == LanguageCode::ZH_HANS) { + out_key_code_map = KeyCodeMapChineseSimplified; + } + if (language_code == LanguageCode::ZH_HANT) { + out_key_code_map = KeyCodeMapChineseTraditional; + } + R_SUCCEED(); + case KeyboardLayout::EnglishUk: + out_key_code_map = KeyCodeMapEnglishUk; + R_SUCCEED(); + case KeyboardLayout::French: + out_key_code_map = KeyCodeMapFrench; + R_SUCCEED(); + case KeyboardLayout::FrenchCa: + out_key_code_map = KeyCodeMapFrenchCa; + R_SUCCEED(); + case KeyboardLayout::Spanish: + out_key_code_map = KeyCodeMapSpanish; + R_SUCCEED(); + case KeyboardLayout::SpanishLatin: + out_key_code_map = KeyCodeMapSpanishLatin; + R_SUCCEED(); + case KeyboardLayout::German: + out_key_code_map = KeyCodeMapGerman; + R_SUCCEED(); + case KeyboardLayout::Italian: + out_key_code_map = KeyCodeMapItalian; + R_SUCCEED(); + case KeyboardLayout::Portuguese: + out_key_code_map = KeyCodeMapPortuguese; + R_SUCCEED(); + case KeyboardLayout::Russian: + out_key_code_map = KeyCodeMapRussian; + R_SUCCEED(); + case KeyboardLayout::Korean: + out_key_code_map = KeyCodeMapKorean; + R_SUCCEED(); + case KeyboardLayout::ChineseSimplified: + out_key_code_map = KeyCodeMapChineseSimplified; + R_SUCCEED(); + case KeyboardLayout::ChineseTraditional: + out_key_code_map = KeyCodeMapChineseTraditional; + R_SUCCEED(); + default: + case KeyboardLayout::EnglishUsInternational: + out_key_code_map = KeyCodeMapEnglishUsInternational; + R_SUCCEED(); } - - ctx.WriteBuffer(layout); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); } + } // Anonymous namespace LanguageCode GetLanguageCodeFromIndex(std::size_t index) { @@ -61,18 +89,18 @@ LanguageCode GetLanguageCodeFromIndex(std::size_t index) { ISettingsServer::ISettingsServer(Core::System& system_) : ServiceFramework{system_, "set"} { // clang-format off static const FunctionInfo functions[] = { - {0, &ISettingsServer::GetLanguageCode, "GetLanguageCode"}, - {1, &ISettingsServer::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"}, - {2, &ISettingsServer::MakeLanguageCode, "MakeLanguageCode"}, - {3, &ISettingsServer::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"}, - {4, &ISettingsServer::GetRegionCode, "GetRegionCode"}, - {5, &ISettingsServer::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"}, - {6, &ISettingsServer::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"}, - {7, &ISettingsServer::GetKeyCodeMap, "GetKeyCodeMap"}, - {8, &ISettingsServer::GetQuestFlag, "GetQuestFlag"}, - {9, &ISettingsServer::GetKeyCodeMap2, "GetKeyCodeMap2"}, + {0, C<&ISettingsServer::GetLanguageCode>, "GetLanguageCode"}, + {1, C<&ISettingsServer::GetAvailableLanguageCodes>, "GetAvailableLanguageCodes"}, + {2, C<&ISettingsServer::MakeLanguageCode>, "MakeLanguageCode"}, + {3, C<&ISettingsServer::GetAvailableLanguageCodeCount>, "GetAvailableLanguageCodeCount"}, + {4, C<&ISettingsServer::GetRegionCode>, "GetRegionCode"}, + {5, C<&ISettingsServer::GetAvailableLanguageCodes2>, "GetAvailableLanguageCodes2"}, + {6, C<&ISettingsServer::GetAvailableLanguageCodeCount2>, "GetAvailableLanguageCodeCount2"}, + {7, C<&ISettingsServer::GetKeyCodeMap>, "GetKeyCodeMap"}, + {8, C<&ISettingsServer::GetQuestFlag>, "GetQuestFlag"}, + {9, C<&ISettingsServer::GetKeyCodeMap2>, "GetKeyCodeMap2"}, {10, nullptr, "GetFirmwareVersionForDebug"}, - {11, &ISettingsServer::GetDeviceNickName, "GetDeviceNickName"}, + {11, C<&ISettingsServer::GetDeviceNickName>, "GetDeviceNickName"}, }; // clang-format on @@ -81,86 +109,134 @@ ISettingsServer::ISettingsServer(Core::System& system_) : ServiceFramework{syste ISettingsServer::~ISettingsServer() = default; -void ISettingsServer::GetAvailableLanguageCodes(HLERequestContext& ctx) { +Result ISettingsServer::GetLanguageCode(Out<LanguageCode> out_language_code) { + LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue()); + + *out_language_code = available_language_codes[static_cast<std::size_t>( + Settings::values.language_index.GetValue())]; + R_SUCCEED(); +} + +Result ISettingsServer::GetAvailableLanguageCodes( + Out<s32> out_count, OutArray<LanguageCode, BufferAttr_HipcPointer> out_language_codes) { LOG_DEBUG(Service_SET, "called"); - GetAvailableLanguageCodesImpl(ctx, PRE_4_0_0_MAX_ENTRIES); + const std::size_t max_amount = std::min(PRE_4_0_0_MAX_ENTRIES, out_language_codes.size()); + *out_count = static_cast<s32>(std::min(available_language_codes.size(), max_amount)); + + memcpy(out_language_codes.data(), available_language_codes.data(), + static_cast<std::size_t>(*out_count) * sizeof(LanguageCode)); + + R_SUCCEED(); } -void ISettingsServer::MakeLanguageCode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto index = rp.Pop<u32>(); +Result ISettingsServer::MakeLanguageCode(Out<LanguageCode> out_language_code, Language language) { + LOG_DEBUG(Service_SET, "called, language={}", language); - if (index >= available_language_codes.size()) { - LOG_ERROR(Service_SET, "Invalid language code index! index={}", index); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(Set::ResultInvalidLanguage); - return; - } + const auto index = static_cast<std::size_t>(language); + R_UNLESS(index < available_language_codes.size(), Set::ResultInvalidLanguage); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(available_language_codes[index]); + *out_language_code = available_language_codes[index]; + R_SUCCEED(); } -void ISettingsServer::GetAvailableLanguageCodes2(HLERequestContext& ctx) { +Result ISettingsServer::GetAvailableLanguageCodeCount(Out<s32> out_count) { LOG_DEBUG(Service_SET, "called"); - GetAvailableLanguageCodesImpl(ctx, POST_4_0_0_MAX_ENTRIES); + *out_count = PRE_4_0_0_MAX_ENTRIES; + R_SUCCEED(); } -void ISettingsServer::GetAvailableLanguageCodeCount(HLERequestContext& ctx) { +Result ISettingsServer::GetRegionCode(Out<SystemRegionCode> out_region_code) { LOG_DEBUG(Service_SET, "called"); - PushResponseLanguageCode(ctx, PRE_4_0_0_MAX_ENTRIES); + *out_region_code = static_cast<SystemRegionCode>(Settings::values.region_index.GetValue()); + R_SUCCEED(); } -void ISettingsServer::GetAvailableLanguageCodeCount2(HLERequestContext& ctx) { +Result ISettingsServer::GetAvailableLanguageCodes2( + Out<s32> out_count, OutArray<LanguageCode, BufferAttr_HipcMapAlias> language_codes) { LOG_DEBUG(Service_SET, "called"); - PushResponseLanguageCode(ctx, POST_4_0_0_MAX_ENTRIES); + const std::size_t max_amount = std::min(POST_4_0_0_MAX_ENTRIES, language_codes.size()); + *out_count = static_cast<s32>(std::min(available_language_codes.size(), max_amount)); + + memcpy(language_codes.data(), available_language_codes.data(), + static_cast<std::size_t>(*out_count) * sizeof(LanguageCode)); + + R_SUCCEED(); } -void ISettingsServer::GetQuestFlag(HLERequestContext& ctx) { +Result ISettingsServer::GetAvailableLanguageCodeCount2(Out<s32> out_count) { LOG_DEBUG(Service_SET, "called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<s32>(Settings::values.quest_flag.GetValue())); + *out_count = POST_4_0_0_MAX_ENTRIES; + R_SUCCEED(); } -void ISettingsServer::GetLanguageCode(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index.GetValue()); +Result ISettingsServer::GetKeyCodeMap( + OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map) { + LOG_DEBUG(Service_SET, "called"); + + R_UNLESS(out_key_code_map != nullptr, ResultNullPointer); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum( - available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]); + const auto language_code = + available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]; + const auto key_code = + std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), + [=](const auto& element) { return element.first == language_code; }); + + if (key_code == language_to_layout.cend()) { + LOG_ERROR(Service_SET, + "Could not find keyboard layout for language index {}, defaulting to English us", + Settings::values.language_index.GetValue()); + *out_key_code_map = KeyCodeMapEnglishUsInternational; + R_SUCCEED(); + } + + R_RETURN(GetKeyCodeMapImpl(*out_key_code_map, key_code->second, key_code->first)); } -void ISettingsServer::GetRegionCode(HLERequestContext& ctx) { +Result ISettingsServer::GetQuestFlag(Out<bool> out_quest_flag) { LOG_DEBUG(Service_SET, "called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(Settings::values.region_index.GetValue())); + *out_quest_flag = Settings::values.quest_flag.GetValue(); + R_SUCCEED(); } -void ISettingsServer::GetKeyCodeMap(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "Called {}", ctx.Description()); - GetKeyCodeMapImpl(ctx); -} +Result ISettingsServer::GetKeyCodeMap2( + OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map) { + LOG_DEBUG(Service_SET, "called"); + + R_UNLESS(out_key_code_map != nullptr, ResultNullPointer); -void ISettingsServer::GetKeyCodeMap2(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "Called {}", ctx.Description()); - GetKeyCodeMapImpl(ctx); + const auto language_code = + available_language_codes[static_cast<s32>(Settings::values.language_index.GetValue())]; + const auto key_code = + std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), + [=](const auto& element) { return element.first == language_code; }); + + if (key_code == language_to_layout.cend()) { + LOG_ERROR(Service_SET, + "Could not find keyboard layout for language index {}, defaulting to English us", + Settings::values.language_index.GetValue()); + *out_key_code_map = KeyCodeMapEnglishUsInternational; + R_SUCCEED(); + } + + R_RETURN(GetKeyCodeMapImpl(*out_key_code_map, key_code->second, key_code->first)); } -void ISettingsServer::GetDeviceNickName(HLERequestContext& ctx) { +Result ISettingsServer::GetDeviceNickName( + OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name) { LOG_DEBUG(Service_SET, "called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - ctx.WriteBuffer(Settings::values.device_name.GetValue()); + + const std::size_t string_size = + std::min(Settings::values.device_name.GetValue().size(), out_device_name->size()); + + *out_device_name = {}; + memcpy(out_device_name->data(), Settings::values.device_name.GetValue().data(), string_size); + R_SUCCEED(); } } // namespace Service::Set diff --git a/src/core/hle/service/set/settings_server.h b/src/core/hle/service/set/settings_server.h index 8304e8424..a39971fe9 100644 --- a/src/core/hle/service/set/settings_server.h +++ b/src/core/hle/service/set/settings_server.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" #include "core/hle/service/set/settings_types.h" @@ -11,6 +12,7 @@ class System; } namespace Service::Set { +using KeyCodeMap = std::array<u8, 0x1000>; LanguageCode GetLanguageCodeFromIndex(std::size_t idx); @@ -20,17 +22,30 @@ public: ~ISettingsServer() override; private: - void GetLanguageCode(HLERequestContext& ctx); - void GetAvailableLanguageCodes(HLERequestContext& ctx); - void MakeLanguageCode(HLERequestContext& ctx); - void GetAvailableLanguageCodes2(HLERequestContext& ctx); - void GetAvailableLanguageCodeCount(HLERequestContext& ctx); - void GetAvailableLanguageCodeCount2(HLERequestContext& ctx); - void GetQuestFlag(HLERequestContext& ctx); - void GetRegionCode(HLERequestContext& ctx); - void GetKeyCodeMap(HLERequestContext& ctx); - void GetKeyCodeMap2(HLERequestContext& ctx); - void GetDeviceNickName(HLERequestContext& ctx); + Result GetLanguageCode(Out<LanguageCode> out_language_code); + + Result GetAvailableLanguageCodes(Out<s32> out_count, + OutArray<LanguageCode, BufferAttr_HipcPointer> language_codes); + + Result MakeLanguageCode(Out<LanguageCode> out_language_code, Language language); + + Result GetAvailableLanguageCodeCount(Out<s32> out_count); + + Result GetRegionCode(Out<SystemRegionCode> out_region_code); + + Result GetAvailableLanguageCodes2( + Out<s32> out_count, OutArray<LanguageCode, BufferAttr_HipcMapAlias> language_codes); + + Result GetAvailableLanguageCodeCount2(Out<s32> out_count); + + Result GetKeyCodeMap(OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map); + + Result GetQuestFlag(Out<bool> out_quest_flag); + + Result GetKeyCodeMap2(OutLargeData<KeyCodeMap, BufferAttr_HipcMapAlias> out_key_code_map); + + Result GetDeviceNickName( + OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name); }; } // namespace Service::Set diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h index ceb85b82a..29664e88c 100644 --- a/src/core/hle/service/set/settings_types.h +++ b/src/core/hle/service/set/settings_types.h @@ -12,6 +12,7 @@ #include "core/hle/service/psc/time/common.h" namespace Service::Set { +using SettingItemName = std::array<u8, 0x48>; /// This is nn::settings::system::AudioOutputMode enum class AudioOutputMode : u32 { @@ -148,6 +149,28 @@ enum class KeyboardLayout : u32 { ChineseTraditional = 14, }; +// This is nn::settings::Language +enum class Language : u32 { + Japanese, + AmericanEnglish, + French, + German, + Italian, + Spanish, + Chinese, + Korean, + Dutch, + Portiguesue, + Russian, + Taiwanese, + BritishEnglish, + CanadianFrench, + LatinAmericanSpanish, + SimplifiedCHhinese, + TraditionalChinese, + BrazilianPortuguese, +}; + /// This is "nn::settings::LanguageCode", which is a NUL-terminated string stored in a u64. enum class LanguageCode : u64 { JA = 0x000000000000616A, @@ -391,16 +414,18 @@ struct FirmwareVersionFormat { u8 major; u8 minor; u8 micro; - INSERT_PADDING_BYTES(1); + INSERT_PADDING_BYTES_NOINIT(1); u8 revision_major; u8 revision_minor; - INSERT_PADDING_BYTES(2); + INSERT_PADDING_BYTES_NOINIT(2); std::array<char, 0x20> platform; std::array<u8, 0x40> version_hash; std::array<char, 0x18> display_version; std::array<char, 0x80> display_title; }; static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size"); +static_assert(std::is_trivial_v<FirmwareVersionFormat>, + "FirmwareVersionFormat type must be trivially copyable."); /// This is nn::settings::system::HomeMenuScheme struct HomeMenuScheme { diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index 7ef4a0ded..93925f783 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -17,6 +17,7 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/romfs.h" #include "core/file_sys/system_archive/system_archive.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/set/settings_server.h" @@ -91,83 +92,83 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) : ServiceFramework{system_, "set:sys"}, m_system{system} { // clang-format off static const FunctionInfo functions[] = { - {0, &ISystemSettingsServer::SetLanguageCode, "SetLanguageCode"}, + {0, C<&ISystemSettingsServer::SetLanguageCode>, "SetLanguageCode"}, {1, nullptr, "SetNetworkSettings"}, {2, nullptr, "GetNetworkSettings"}, - {3, &ISystemSettingsServer::GetFirmwareVersion, "GetFirmwareVersion"}, - {4, &ISystemSettingsServer::GetFirmwareVersion2, "GetFirmwareVersion2"}, + {3, C<&ISystemSettingsServer::GetFirmwareVersion>, "GetFirmwareVersion"}, + {4, C<&ISystemSettingsServer::GetFirmwareVersion2>, "GetFirmwareVersion2"}, {5, nullptr, "GetFirmwareVersionDigest"}, - {7, &ISystemSettingsServer::GetLockScreenFlag, "GetLockScreenFlag"}, - {8, &ISystemSettingsServer::SetLockScreenFlag, "SetLockScreenFlag"}, + {7, C<&ISystemSettingsServer::GetLockScreenFlag>, "GetLockScreenFlag"}, + {8, C<&ISystemSettingsServer::SetLockScreenFlag>, "SetLockScreenFlag"}, {9, nullptr, "GetBacklightSettings"}, {10, nullptr, "SetBacklightSettings"}, {11, nullptr, "SetBluetoothDevicesSettings"}, {12, nullptr, "GetBluetoothDevicesSettings"}, - {13, &ISystemSettingsServer::GetExternalSteadyClockSourceId, "GetExternalSteadyClockSourceId"}, - {14, &ISystemSettingsServer::SetExternalSteadyClockSourceId, "SetExternalSteadyClockSourceId"}, - {15, &ISystemSettingsServer::GetUserSystemClockContext, "GetUserSystemClockContext"}, - {16, &ISystemSettingsServer::SetUserSystemClockContext, "SetUserSystemClockContext"}, - {17, &ISystemSettingsServer::GetAccountSettings, "GetAccountSettings"}, - {18, &ISystemSettingsServer::SetAccountSettings, "SetAccountSettings"}, + {13, C<&ISystemSettingsServer::GetExternalSteadyClockSourceId>, "GetExternalSteadyClockSourceId"}, + {14, C<&ISystemSettingsServer::SetExternalSteadyClockSourceId>, "SetExternalSteadyClockSourceId"}, + {15, C<&ISystemSettingsServer::GetUserSystemClockContext>, "GetUserSystemClockContext"}, + {16, C<&ISystemSettingsServer::SetUserSystemClockContext>, "SetUserSystemClockContext"}, + {17, C<&ISystemSettingsServer::GetAccountSettings>, "GetAccountSettings"}, + {18, C<&ISystemSettingsServer::SetAccountSettings>, "SetAccountSettings"}, {19, nullptr, "GetAudioVolume"}, {20, nullptr, "SetAudioVolume"}, - {21, &ISystemSettingsServer::GetEulaVersions, "GetEulaVersions"}, - {22, &ISystemSettingsServer::SetEulaVersions, "SetEulaVersions"}, - {23, &ISystemSettingsServer::GetColorSetId, "GetColorSetId"}, - {24, &ISystemSettingsServer::SetColorSetId, "SetColorSetId"}, + {21, C<&ISystemSettingsServer::GetEulaVersions>, "GetEulaVersions"}, + {22, C<&ISystemSettingsServer::SetEulaVersions>, "SetEulaVersions"}, + {23, C<&ISystemSettingsServer::GetColorSetId>, "GetColorSetId"}, + {24, C<&ISystemSettingsServer::SetColorSetId>, "SetColorSetId"}, {25, nullptr, "GetConsoleInformationUploadFlag"}, {26, nullptr, "SetConsoleInformationUploadFlag"}, {27, nullptr, "GetAutomaticApplicationDownloadFlag"}, {28, nullptr, "SetAutomaticApplicationDownloadFlag"}, - {29, &ISystemSettingsServer::GetNotificationSettings, "GetNotificationSettings"}, - {30, &ISystemSettingsServer::SetNotificationSettings, "SetNotificationSettings"}, - {31, &ISystemSettingsServer::GetAccountNotificationSettings, "GetAccountNotificationSettings"}, - {32, &ISystemSettingsServer::SetAccountNotificationSettings, "SetAccountNotificationSettings"}, - {35, &ISystemSettingsServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"}, - {36, &ISystemSettingsServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"}, - {37, &ISystemSettingsServer::GetSettingsItemValueSize, "GetSettingsItemValueSize"}, - {38, &ISystemSettingsServer::GetSettingsItemValue, "GetSettingsItemValue"}, - {39, &ISystemSettingsServer::GetTvSettings, "GetTvSettings"}, - {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"}, + {29, C<&ISystemSettingsServer::GetNotificationSettings>, "GetNotificationSettings"}, + {30, C<&ISystemSettingsServer::SetNotificationSettings>, "SetNotificationSettings"}, + {31, C<&ISystemSettingsServer::GetAccountNotificationSettings>, "GetAccountNotificationSettings"}, + {32, C<&ISystemSettingsServer::SetAccountNotificationSettings>, "SetAccountNotificationSettings"}, + {35, C<&ISystemSettingsServer::GetVibrationMasterVolume>, "GetVibrationMasterVolume"}, + {36, C<&ISystemSettingsServer::SetVibrationMasterVolume>, "SetVibrationMasterVolume"}, + {37, C<&ISystemSettingsServer::GetSettingsItemValueSize>, "GetSettingsItemValueSize"}, + {38, C<&ISystemSettingsServer::GetSettingsItemValue>, "GetSettingsItemValue"}, + {39, C<&ISystemSettingsServer::GetTvSettings>, "GetTvSettings"}, + {40, C<&ISystemSettingsServer::SetTvSettings>, "SetTvSettings"}, {41, nullptr, "GetEdid"}, {42, nullptr, "SetEdid"}, - {43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"}, - {44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"}, - {45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"}, - {46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"}, - {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"}, - {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"}, + {43, C<&ISystemSettingsServer::GetAudioOutputMode>, "GetAudioOutputMode"}, + {44, C<&ISystemSettingsServer::SetAudioOutputMode>, "SetAudioOutputMode"}, + {45, C<&ISystemSettingsServer::GetSpeakerAutoMuteFlag> , "GetSpeakerAutoMuteFlag"}, + {46, C<&ISystemSettingsServer::SetSpeakerAutoMuteFlag> , "SetSpeakerAutoMuteFlag"}, + {47, C<&ISystemSettingsServer::GetQuestFlag>, "GetQuestFlag"}, + {48, C<&ISystemSettingsServer::SetQuestFlag>, "SetQuestFlag"}, {49, nullptr, "GetDataDeletionSettings"}, {50, nullptr, "SetDataDeletionSettings"}, {51, nullptr, "GetInitialSystemAppletProgramId"}, {52, nullptr, "GetOverlayDispProgramId"}, - {53, &ISystemSettingsServer::GetDeviceTimeZoneLocationName, "GetDeviceTimeZoneLocationName"}, - {54, &ISystemSettingsServer::SetDeviceTimeZoneLocationName, "SetDeviceTimeZoneLocationName"}, + {53, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationName>, "GetDeviceTimeZoneLocationName"}, + {54, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationName>, "SetDeviceTimeZoneLocationName"}, {55, nullptr, "GetWirelessCertificationFileSize"}, {56, nullptr, "GetWirelessCertificationFile"}, - {57, &ISystemSettingsServer::SetRegionCode, "SetRegionCode"}, - {58, &ISystemSettingsServer::GetNetworkSystemClockContext, "GetNetworkSystemClockContext"}, - {59, &ISystemSettingsServer::SetNetworkSystemClockContext, "SetNetworkSystemClockContext"}, - {60, &ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled, "IsUserSystemClockAutomaticCorrectionEnabled"}, - {61, &ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled, "SetUserSystemClockAutomaticCorrectionEnabled"}, - {62, &ISystemSettingsServer::GetDebugModeFlag, "GetDebugModeFlag"}, - {63, &ISystemSettingsServer::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"}, - {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"}, + {57, C<&ISystemSettingsServer::SetRegionCode>, "SetRegionCode"}, + {58, C<&ISystemSettingsServer::GetNetworkSystemClockContext>, "GetNetworkSystemClockContext"}, + {59, C<&ISystemSettingsServer::SetNetworkSystemClockContext>, "SetNetworkSystemClockContext"}, + {60, C<&ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled>, "IsUserSystemClockAutomaticCorrectionEnabled"}, + {61, C<&ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled>, "SetUserSystemClockAutomaticCorrectionEnabled"}, + {62, C<&ISystemSettingsServer::GetDebugModeFlag>, "GetDebugModeFlag"}, + {63, C<&ISystemSettingsServer::GetPrimaryAlbumStorage>, "GetPrimaryAlbumStorage"}, + {64, C<&ISystemSettingsServer::SetPrimaryAlbumStorage>, "SetPrimaryAlbumStorage"}, {65, nullptr, "GetUsb30EnableFlag"}, {66, nullptr, "SetUsb30EnableFlag"}, - {67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"}, - {68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"}, - {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"}, - {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"}, - {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"}, - {72, &ISystemSettingsServer::SetSleepSettings, "SetSleepSettings"}, - {73, &ISystemSettingsServer::GetWirelessLanEnableFlag, "GetWirelessLanEnableFlag"}, - {74, &ISystemSettingsServer::SetWirelessLanEnableFlag, "SetWirelessLanEnableFlag"}, - {75, &ISystemSettingsServer::GetInitialLaunchSettings, "GetInitialLaunchSettings"}, - {76, &ISystemSettingsServer::SetInitialLaunchSettings, "SetInitialLaunchSettings"}, - {77, &ISystemSettingsServer::GetDeviceNickName, "GetDeviceNickName"}, - {78, &ISystemSettingsServer::SetDeviceNickName, "SetDeviceNickName"}, - {79, &ISystemSettingsServer::GetProductModel, "GetProductModel"}, + {67, C<&ISystemSettingsServer::GetBatteryLot>, "GetBatteryLot"}, + {68, C<&ISystemSettingsServer::GetSerialNumber>, "GetSerialNumber"}, + {69, C<&ISystemSettingsServer::GetNfcEnableFlag>, "GetNfcEnableFlag"}, + {70, C<&ISystemSettingsServer::SetNfcEnableFlag>, "SetNfcEnableFlag"}, + {71, C<&ISystemSettingsServer::GetSleepSettings>, "GetSleepSettings"}, + {72, C<&ISystemSettingsServer::SetSleepSettings>, "SetSleepSettings"}, + {73, C<&ISystemSettingsServer::GetWirelessLanEnableFlag>, "GetWirelessLanEnableFlag"}, + {74, C<&ISystemSettingsServer::SetWirelessLanEnableFlag>, "SetWirelessLanEnableFlag"}, + {75, C<&ISystemSettingsServer::GetInitialLaunchSettings>, "GetInitialLaunchSettings"}, + {76, C<&ISystemSettingsServer::SetInitialLaunchSettings>, "SetInitialLaunchSettings"}, + {77, C<&ISystemSettingsServer::GetDeviceNickName>, "GetDeviceNickName"}, + {78, C<&ISystemSettingsServer::SetDeviceNickName>, "SetDeviceNickName"}, + {79, C<&ISystemSettingsServer::GetProductModel>, "GetProductModel"}, {80, nullptr, "GetLdnChannel"}, {81, nullptr, "SetLdnChannel"}, {82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"}, @@ -176,25 +177,25 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {85, nullptr, "SetPtmBatteryLot"}, {86, nullptr, "GetPtmFuelGaugeParameter"}, {87, nullptr, "SetPtmFuelGaugeParameter"}, - {88, &ISystemSettingsServer::GetBluetoothEnableFlag, "GetBluetoothEnableFlag"}, - {89, &ISystemSettingsServer::SetBluetoothEnableFlag, "SetBluetoothEnableFlag"}, - {90, &ISystemSettingsServer::GetMiiAuthorId, "GetMiiAuthorId"}, + {88, C<&ISystemSettingsServer::GetBluetoothEnableFlag>, "GetBluetoothEnableFlag"}, + {89, C<&ISystemSettingsServer::SetBluetoothEnableFlag>, "SetBluetoothEnableFlag"}, + {90, C<&ISystemSettingsServer::GetMiiAuthorId>, "GetMiiAuthorId"}, {91, nullptr, "SetShutdownRtcValue"}, {92, nullptr, "GetShutdownRtcValue"}, {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, {94, nullptr, "GetFatalDirtyFlags"}, - {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"}, - {96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"}, + {95, C<&ISystemSettingsServer::GetAutoUpdateEnableFlag>, "GetAutoUpdateEnableFlag"}, + {96, C<&ISystemSettingsServer::SetAutoUpdateEnableFlag>, "SetAutoUpdateEnableFlag"}, {97, nullptr, "GetNxControllerSettings"}, {98, nullptr, "SetNxControllerSettings"}, - {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"}, - {100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"}, + {99, C<&ISystemSettingsServer::GetBatteryPercentageFlag>, "GetBatteryPercentageFlag"}, + {100, C<&ISystemSettingsServer::SetBatteryPercentageFlag>, "SetBatteryPercentageFlag"}, {101, nullptr, "GetExternalRtcResetFlag"}, {102, nullptr, "SetExternalRtcResetFlag"}, {103, nullptr, "GetUsbFullKeyEnableFlag"}, {104, nullptr, "SetUsbFullKeyEnableFlag"}, - {105, &ISystemSettingsServer::SetExternalSteadyClockInternalOffset, "SetExternalSteadyClockInternalOffset"}, - {106, &ISystemSettingsServer::GetExternalSteadyClockInternalOffset, "GetExternalSteadyClockInternalOffset"}, + {105, C<&ISystemSettingsServer::SetExternalSteadyClockInternalOffset>, "SetExternalSteadyClockInternalOffset"}, + {106, C<&ISystemSettingsServer::GetExternalSteadyClockInternalOffset>, "GetExternalSteadyClockInternalOffset"}, {107, nullptr, "GetBacklightSettingsEx"}, {108, nullptr, "SetBacklightSettingsEx"}, {109, nullptr, "GetHeadphoneVolumeWarningCount"}, @@ -208,14 +209,14 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {117, nullptr, "GetHeadphoneVolumeUpdateFlag"}, {118, nullptr, "SetHeadphoneVolumeUpdateFlag"}, {119, nullptr, "NeedsToUpdateHeadphoneVolume"}, - {120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"}, - {121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"}, + {120, C<&ISystemSettingsServer::GetPushNotificationActivityModeOnSleep>, "GetPushNotificationActivityModeOnSleep"}, + {121, C<&ISystemSettingsServer::SetPushNotificationActivityModeOnSleep>, "SetPushNotificationActivityModeOnSleep"}, {122, nullptr, "GetServiceDiscoveryControlSettings"}, {123, nullptr, "SetServiceDiscoveryControlSettings"}, - {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"}, - {125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"}, - {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"}, - {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"}, + {124, C<&ISystemSettingsServer::GetErrorReportSharePermission>, "GetErrorReportSharePermission"}, + {125, C<&ISystemSettingsServer::SetErrorReportSharePermission>, "SetErrorReportSharePermission"}, + {126, C<&ISystemSettingsServer::GetAppletLaunchFlags>, "GetAppletLaunchFlags"}, + {127, C<&ISystemSettingsServer::SetAppletLaunchFlags>, "SetAppletLaunchFlags"}, {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, {129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"}, {130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"}, @@ -224,8 +225,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"}, {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, - {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"}, - {137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"}, + {136, C<&ISystemSettingsServer::GetKeyboardLayout>, "GetKeyboardLayout"}, + {137, C<&ISystemSettingsServer::SetKeyboardLayout>, "SetKeyboardLayout"}, {138, nullptr, "GetWebInspectorFlag"}, {139, nullptr, "GetAllowedSslHosts"}, {140, nullptr, "GetHostFsMountPoint"}, @@ -238,10 +239,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"}, {148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"}, {149, nullptr, "GetRebootlessSystemUpdateVersion"}, - {150, &ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime, "GetDeviceTimeZoneLocationUpdatedTime"}, - {151, &ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime, "SetDeviceTimeZoneLocationUpdatedTime"}, - {152, &ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime, "GetUserSystemClockAutomaticCorrectionUpdatedTime"}, - {153, &ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime, "SetUserSystemClockAutomaticCorrectionUpdatedTime"}, + {150, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime>, "GetDeviceTimeZoneLocationUpdatedTime"}, + {151, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime>, "SetDeviceTimeZoneLocationUpdatedTime"}, + {152, C<&ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime>, "GetUserSystemClockAutomaticCorrectionUpdatedTime"}, + {153, C<&ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime>, "SetUserSystemClockAutomaticCorrectionUpdatedTime"}, {154, nullptr, "GetAccountOnlineStorageSettings"}, {155, nullptr, "SetAccountOnlineStorageSettings"}, {156, nullptr, "GetPctlReadyFlag"}, @@ -258,11 +259,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {167, nullptr, "SetUsb30DeviceEnableFlag"}, {168, nullptr, "GetThemeId"}, {169, nullptr, "SetThemeId"}, - {170, &ISystemSettingsServer::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"}, + {170, C<&ISystemSettingsServer::GetChineseTraditionalInputMethod>, "GetChineseTraditionalInputMethod"}, {171, nullptr, "SetChineseTraditionalInputMethod"}, {172, nullptr, "GetPtmCycleCountReliability"}, {173, nullptr, "SetPtmCycleCountReliability"}, - {174, &ISystemSettingsServer::GetHomeMenuScheme, "GetHomeMenuScheme"}, + {174, C<&ISystemSettingsServer::GetHomeMenuScheme>, "GetHomeMenuScheme"}, {175, nullptr, "GetThemeSettings"}, {176, nullptr, "SetThemeSettings"}, {177, nullptr, "GetThemeKey"}, @@ -273,10 +274,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {182, nullptr, "SetT"}, {183, nullptr, "GetPlatformRegion"}, {184, nullptr, "SetPlatformRegion"}, - {185, &ISystemSettingsServer::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"}, + {185, C<&ISystemSettingsServer::GetHomeMenuSchemeModel>, "GetHomeMenuSchemeModel"}, {186, nullptr, "GetMemoryUsageRateFlag"}, - {187, &ISystemSettingsServer::GetTouchScreenMode, "GetTouchScreenMode"}, - {188, &ISystemSettingsServer::SetTouchScreenMode, "SetTouchScreenMode"}, + {187, C<&ISystemSettingsServer::GetTouchScreenMode>, "GetTouchScreenMode"}, + {188, C<&ISystemSettingsServer::SetTouchScreenMode>, "SetTouchScreenMode"}, {189, nullptr, "GetButtonConfigSettingsFull"}, {190, nullptr, "SetButtonConfigSettingsFull"}, {191, nullptr, "GetButtonConfigSettingsEmbedded"}, @@ -289,10 +290,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, {199, nullptr, "GetButtonConfigRegisteredSettings"}, {200, nullptr, "SetButtonConfigRegisteredSettings"}, - {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"}, + {201, C<&ISystemSettingsServer::GetFieldTestingFlag>, "GetFieldTestingFlag"}, {202, nullptr, "SetFieldTestingFlag"}, - {203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"}, - {204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"}, + {203, C<&ISystemSettingsServer::GetPanelCrcMode>, "GetPanelCrcMode"}, + {204, C<&ISystemSettingsServer::SetPanelCrcMode>, "SetPanelCrcMode"}, {205, nullptr, "GetNxControllerSettingsEx"}, {206, nullptr, "SetNxControllerSettingsEx"}, {207, nullptr, "GetHearingProtectionSafeguardFlag"}, @@ -422,178 +423,134 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto& return true; } -void ISystemSettingsServer::SetLanguageCode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.language_code = rp.PopEnum<LanguageCode>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, language_code={}", m_system_settings.language_code); +Result ISystemSettingsServer::SetLanguageCode(LanguageCode language_code) { + LOG_INFO(Service_SET, "called, language_code={}", language_code); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.language_code = language_code; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetFirmwareVersion(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetFirmwareVersion( + OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data) { LOG_DEBUG(Service_SET, "called"); - FirmwareVersionFormat firmware_data{}; - const auto result = - GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1); - - if (result.IsSuccess()) { - ctx.WriteBuffer(firmware_data); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(GetFirmwareVersionImpl(*out_firmware_data, system, GetFirmwareVersionType::Version1)); } -void ISystemSettingsServer::GetFirmwareVersion2(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetFirmwareVersion2( + OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data) { LOG_DEBUG(Service_SET, "called"); - FirmwareVersionFormat firmware_data{}; - const auto result = - GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2); - - if (result.IsSuccess()) { - ctx.WriteBuffer(firmware_data); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(GetFirmwareVersionImpl(*out_firmware_data, system, GetFirmwareVersionType::Version2)); } -void ISystemSettingsServer::GetExternalSteadyClockSourceId(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); - - Common::UUID id{}; - const auto res = GetExternalSteadyClockSourceId(id); +Result ISystemSettingsServer::GetLockScreenFlag(Out<bool> out_lock_screen_flag) { + LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag); - IPC::ResponseBuilder rb{ctx, 2 + sizeof(Common::UUID) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw(id); + *out_lock_screen_flag = m_system_settings.lock_screen_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetExternalSteadyClockSourceId(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); +Result ISystemSettingsServer::SetLockScreenFlag(bool lock_screen_flag) { + LOG_INFO(Service_SET, "called, lock_screen_flag={}", lock_screen_flag); - IPC::RequestParser rp{ctx}; - const auto id{rp.PopRaw<Common::UUID>()}; + m_system_settings.lock_screen_flag = lock_screen_flag; + SetSaveNeeded(); + R_SUCCEED(); +} - const auto res = SetExternalSteadyClockSourceId(id); +Result ISystemSettingsServer::GetExternalSteadyClockSourceId( + Out<Common::UUID> out_clock_source_id) { + LOG_INFO(Service_SET, "called, clock_source_id={}", + m_private_settings.external_clock_source_id.FormattedString()); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + *out_clock_source_id = m_private_settings.external_clock_source_id; + R_SUCCEED(); } -void ISystemSettingsServer::GetUserSystemClockContext(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); - - Service::PSC::Time::SystemClockContext context{}; - const auto res = GetUserSystemClockContext(context); +Result ISystemSettingsServer::SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id) { + LOG_INFO(Service_SET, "called, clock_source_id={}", clock_source_id.FormattedString()); - IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::SystemClockContext) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw(context); + m_private_settings.external_clock_source_id = clock_source_id; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::SetUserSystemClockContext(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetUserSystemClockContext( + Out<Service::PSC::Time::SystemClockContext> out_clock_context) { LOG_INFO(Service_SET, "called"); - IPC::RequestParser rp{ctx}; - const auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; - - const auto res = SetUserSystemClockContext(context); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + *out_clock_context = m_system_settings.user_system_clock_context; + R_SUCCEED(); } -void ISystemSettingsServer::GetLockScreenFlag(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.lock_screen_flag); -} +Result ISystemSettingsServer::SetUserSystemClockContext( + const Service::PSC::Time::SystemClockContext& clock_context) { + LOG_INFO(Service_SET, "called"); -void ISystemSettingsServer::SetLockScreenFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.lock_screen_flag = rp.Pop<bool>(); + m_system_settings.user_system_clock_context = clock_context; SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::GetAccountSettings(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); +Result ISystemSettingsServer::GetAccountSettings(Out<AccountSettings> out_account_settings) { + LOG_INFO(Service_SET, "called, account_settings_flags={}", + m_system_settings.account_settings.flags); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.account_settings); + *out_account_settings = m_system_settings.account_settings; + R_SUCCEED(); } -void ISystemSettingsServer::SetAccountSettings(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.account_settings = rp.PopRaw<AccountSettings>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, account_settings_flags={}", - m_system_settings.account_settings.flags); +Result ISystemSettingsServer::SetAccountSettings(AccountSettings account_settings) { + LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.account_settings = account_settings; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetEulaVersions(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetEulaVersions( + Out<s32> out_count, OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions) { LOG_INFO(Service_SET, "called, elements={}", m_system_settings.eula_version_count); - ctx.WriteBuffer(m_system_settings.eula_versions); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.eula_version_count); + *out_count = + std::min(m_system_settings.eula_version_count, static_cast<s32>(out_eula_versions.size())); + memcpy(out_eula_versions.data(), m_system_settings.eula_versions.data(), + static_cast<std::size_t>(*out_count) * sizeof(EulaVersion)); + R_SUCCEED(); } -void ISystemSettingsServer::SetEulaVersions(HLERequestContext& ctx) { - const auto elements = ctx.GetReadBufferNumElements<EulaVersion>(); - const auto buffer_data = ctx.ReadBuffer(); +Result ISystemSettingsServer::SetEulaVersions( + InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions) { + LOG_INFO(Service_SET, "called, elements={}", eula_versions.size()); - LOG_INFO(Service_SET, "called, elements={}", elements); - ASSERT(elements <= m_system_settings.eula_versions.size()); + ASSERT(eula_versions.size() <= m_system_settings.eula_versions.size()); - m_system_settings.eula_version_count = static_cast<u32>(elements); - std::memcpy(&m_system_settings.eula_versions, buffer_data.data(), - sizeof(EulaVersion) * elements); + m_system_settings.eula_version_count = static_cast<s32>(eula_versions.size()); + std::memcpy(m_system_settings.eula_versions.data(), eula_versions.data(), + eula_versions.size() * sizeof(EulaVersion)); SetSaveNeeded(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::GetColorSetId(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetColorSetId(Out<ColorSet> out_color_set_id) { LOG_DEBUG(Service_SET, "called, color_set=", m_system_settings.color_set_id); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(m_system_settings.color_set_id); + *out_color_set_id = m_system_settings.color_set_id; + R_SUCCEED(); } -void ISystemSettingsServer::SetColorSetId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.color_set_id = rp.PopEnum<ColorSet>(); - SetSaveNeeded(); - - LOG_DEBUG(Service_SET, "called, color_set={}", m_system_settings.color_set_id); +Result ISystemSettingsServer::SetColorSetId(ColorSet color_set_id) { + LOG_DEBUG(Service_SET, "called, color_set={}", color_set_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.color_set_id = color_set_id; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetNotificationSettings( + Out<NotificationSettings> out_notification_settings) { LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}", m_system_settings.notification_settings.flags.raw, m_system_settings.notification_settings.volume, @@ -602,77 +559,67 @@ void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) { m_system_settings.notification_settings.stop_time.hour, m_system_settings.notification_settings.stop_time.minute); - IPC::ResponseBuilder rb{ctx, 8}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.notification_settings); + *out_notification_settings = m_system_settings.notification_settings; + R_SUCCEED(); } -void ISystemSettingsServer::SetNotificationSettings(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.notification_settings = rp.PopRaw<NotificationSettings>(); - SetSaveNeeded(); - +Result ISystemSettingsServer::SetNotificationSettings( + const NotificationSettings& notification_settings) { LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}", - m_system_settings.notification_settings.flags.raw, - m_system_settings.notification_settings.volume, - m_system_settings.notification_settings.start_time.hour, - m_system_settings.notification_settings.start_time.minute, - m_system_settings.notification_settings.stop_time.hour, - m_system_settings.notification_settings.stop_time.minute); + notification_settings.flags.raw, notification_settings.volume, + notification_settings.start_time.hour, notification_settings.start_time.minute, + notification_settings.stop_time.hour, notification_settings.stop_time.minute); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.notification_settings = notification_settings; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetAccountNotificationSettings(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetAccountNotificationSettings( + Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> + out_account_notification_settings) { LOG_INFO(Service_SET, "called, elements={}", m_system_settings.account_notification_settings_count); - ctx.WriteBuffer(m_system_settings.account_notification_settings); + *out_count = std::min(m_system_settings.account_notification_settings_count, + static_cast<s32>(out_account_notification_settings.size())); + memcpy(out_account_notification_settings.data(), + m_system_settings.account_notification_settings.data(), + static_cast<std::size_t>(*out_count) * sizeof(AccountNotificationSettings)); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.account_notification_settings_count); + R_SUCCEED(); } -void ISystemSettingsServer::SetAccountNotificationSettings(HLERequestContext& ctx) { - const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>(); - const auto buffer_data = ctx.ReadBuffer(); - - LOG_INFO(Service_SET, "called, elements={}", elements); +Result ISystemSettingsServer::SetAccountNotificationSettings( + InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> account_notification_settings) { + LOG_INFO(Service_SET, "called, elements={}", account_notification_settings.size()); - ASSERT(elements <= m_system_settings.account_notification_settings.size()); + ASSERT(account_notification_settings.size() <= + m_system_settings.account_notification_settings.size()); - m_system_settings.account_notification_settings_count = static_cast<u32>(elements); - std::memcpy(&m_system_settings.account_notification_settings, buffer_data.data(), - elements * sizeof(AccountNotificationSettings)); + m_system_settings.account_notification_settings_count = + static_cast<s32>(account_notification_settings.size()); + std::memcpy(m_system_settings.account_notification_settings.data(), + account_notification_settings.data(), + account_notification_settings.size() * sizeof(AccountNotificationSettings)); SetSaveNeeded(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::GetVibrationMasterVolume(HLERequestContext& ctx) { - f32 vibration_master_volume = {}; - const auto result = GetVibrationMasterVolume(vibration_master_volume); +Result ISystemSettingsServer::GetVibrationMasterVolume(Out<f32> vibration_master_volume) { + LOG_INFO(Service_SET, "called, vibration_master_volume={}", + m_system_settings.vibration_master_volume); - LOG_INFO(Service_SET, "called, master_volume={}", vibration_master_volume); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.Push(vibration_master_volume); + *vibration_master_volume = m_system_settings.vibration_master_volume; + R_SUCCEED(); } -void ISystemSettingsServer::SetVibrationMasterVolume(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto vibration_master_volume = rp.PopRaw<f32>(); - - LOG_INFO(Service_SET, "called, elements={}", m_system_settings.vibration_master_volume); +Result ISystemSettingsServer::SetVibrationMasterVolume(f32 vibration_master_volume) { + LOG_INFO(Service_SET, "called, vibration_master_volume={}", vibration_master_volume); - const auto result = SetVibrationMasterVolume(vibration_master_volume); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + m_system_settings.vibration_master_volume = vibration_master_volume; + SetSaveNeeded(); + R_SUCCEED(); } // FIXME: implement support for the real system_settings.ini @@ -734,55 +681,38 @@ static Settings GetSettings() { return ret; } -void ISystemSettingsServer::GetSettingsItemValueSize(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called"); +Result ISystemSettingsServer::GetSettingsItemValueSize( + Out<u64> out_size, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) { + const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)}; + const std::string setting_name{Common::StringFromBuffer(*setting_name_buffer)}; - // The category of the setting. This corresponds to the top-level keys of - // system_settings.ini. - const auto setting_category_buf{ctx.ReadBuffer(0)}; - const std::string setting_category{Common::StringFromBuffer(setting_category_buf)}; + LOG_DEBUG(Service_SET, "called, category={}, name={}", setting_category, setting_name); - // The name of the setting. This corresponds to the second-level keys of - // system_settings.ini. - const auto setting_name_buf{ctx.ReadBuffer(1)}; - const std::string setting_name{Common::StringFromBuffer(setting_name_buf)}; + *out_size = 0; auto settings{GetSettings()}; - u64 response_size{0}; - if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) { - response_size = settings[setting_category][setting_name].size(); + *out_size = settings[setting_category][setting_name].size(); } - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(response_size == 0 ? ResultUnknown : ResultSuccess); - rb.Push(response_size); + R_UNLESS(*out_size != 0, ResultUnknown); + R_SUCCEED(); } -void ISystemSettingsServer::GetSettingsItemValue(HLERequestContext& ctx) { - // The category of the setting. This corresponds to the top-level keys of - // system_settings.ini. - const auto setting_category_buf{ctx.ReadBuffer(0)}; - const std::string setting_category{Common::StringFromBuffer(setting_category_buf)}; - - // The name of the setting. This corresponds to the second-level keys of - // system_settings.ini. - const auto setting_name_buf{ctx.ReadBuffer(1)}; - const std::string setting_name{Common::StringFromBuffer(setting_name_buf)}; +Result ISystemSettingsServer::GetSettingsItemValue( + OutBuffer<BufferAttr_HipcMapAlias> out_data, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) { + const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)}; + const std::string setting_name{Common::StringFromBuffer(*setting_name_buffer)}; - std::vector<u8> value; - auto response = GetSettingsItemValue(value, setting_category, setting_name); + LOG_INFO(Service_SET, "called, category={}, name={}", setting_category, setting_name); - LOG_INFO(Service_SET, "called. category={}, name={} -- res=0x{:X}", setting_category, - setting_name, response.raw); - - ctx.WriteBuffer(value.data(), value.size()); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(response); + R_RETURN(GetSettingsItemValueImpl(out_data, setting_category, setting_name)); } -void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetTvSettings(Out<TvSettings> out_tv_settings) { LOG_INFO(Service_SET, "called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, " "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", @@ -793,371 +723,335 @@ void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) { m_system_settings.tv_settings.tv_resolution, m_system_settings.tv_settings.tv_underscan); - IPC::ResponseBuilder rb{ctx, 10}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.tv_settings); + *out_tv_settings = m_system_settings.tv_settings; + R_SUCCEED(); } -void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.tv_settings = rp.PopRaw<TvSettings>(); - SetSaveNeeded(); +Result ISystemSettingsServer::SetTvSettings(TvSettings tv_settings) { LOG_INFO(Service_SET, "called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, " "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", - m_system_settings.tv_settings.flags.raw, m_system_settings.tv_settings.cmu_mode, - m_system_settings.tv_settings.contrast_ratio, - m_system_settings.tv_settings.hdmi_content_type, - m_system_settings.tv_settings.rgb_range, m_system_settings.tv_settings.tv_gama, - m_system_settings.tv_settings.tv_resolution, - m_system_settings.tv_settings.tv_underscan); + tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.contrast_ratio, + tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama, + tv_settings.tv_resolution, tv_settings.tv_underscan); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.tv_settings = tv_settings; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto target{rp.PopEnum<AudioOutputModeTarget>()}; - - AudioOutputMode output_mode{}; - const auto result = GetAudioOutputMode(output_mode, target); - - LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); +Result ISystemSettingsServer::GetAudioOutputMode(Out<AudioOutputMode> out_output_mode, + AudioOutputModeTarget target) { + switch (target) { + case AudioOutputModeTarget::Hdmi: + *out_output_mode = m_system_settings.audio_output_mode_hdmi; + break; + case AudioOutputModeTarget::Speaker: + *out_output_mode = m_system_settings.audio_output_mode_speaker; + break; + case AudioOutputModeTarget::Headphone: + *out_output_mode = m_system_settings.audio_output_mode_headphone; + break; + case AudioOutputModeTarget::Type3: + *out_output_mode = m_system_settings.audio_output_mode_type3; + break; + case AudioOutputModeTarget::Type4: + *out_output_mode = m_system_settings.audio_output_mode_type4; + break; + default: + LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target); + } - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(result); - rb.PushEnum(output_mode); + LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode); + R_SUCCEED(); } -void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto target{rp.PopEnum<AudioOutputModeTarget>()}; - const auto output_mode{rp.PopEnum<AudioOutputMode>()}; - - const auto result = SetAudioOutputMode(target, output_mode); - +Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target, + AudioOutputMode output_mode) { LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + switch (target) { + case AudioOutputModeTarget::Hdmi: + m_system_settings.audio_output_mode_hdmi = output_mode; + break; + case AudioOutputModeTarget::Speaker: + m_system_settings.audio_output_mode_speaker = output_mode; + break; + case AudioOutputModeTarget::Headphone: + m_system_settings.audio_output_mode_headphone = output_mode; + break; + case AudioOutputModeTarget::Type3: + m_system_settings.audio_output_mode_type3 = output_mode; + break; + case AudioOutputModeTarget::Type4: + m_system_settings.audio_output_mode_type4 = output_mode; + break; + default: + LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target); + } + + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetSpeakerAutoMuteFlag( + Out<bool> out_force_mute_on_headphone_removed) { LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}", m_system_settings.force_mute_on_headphone_removed); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.force_mute_on_headphone_removed); + *out_force_mute_on_headphone_removed = m_system_settings.force_mute_on_headphone_removed; + R_SUCCEED(); } -void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>(); - SetSaveNeeded(); - +Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed) { LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}", - m_system_settings.force_mute_on_headphone_removed); + force_mute_on_headphone_removed); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.force_mute_on_headphone_removed = force_mute_on_headphone_removed; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetQuestFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetQuestFlag(Out<QuestFlag> out_quest_flag) { LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(m_system_settings.quest_flag); + *out_quest_flag = m_system_settings.quest_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetQuestFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.quest_flag = rp.PopEnum<QuestFlag>(); - SetSaveNeeded(); +Result ISystemSettingsServer::SetQuestFlag(QuestFlag quest_flag) { + LOG_INFO(Service_SET, "called, quest_flag={}", quest_flag); - LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.quest_flag = quest_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetDeviceTimeZoneLocationName(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetDeviceTimeZoneLocationName( + Out<Service::PSC::Time::LocationName> out_name) { LOG_INFO(Service_SET, "called"); - Service::PSC::Time::LocationName name{}; - const auto res = GetDeviceTimeZoneLocationName(name); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::LocationName>(name); + *out_name = m_system_settings.device_time_zone_location_name; + R_SUCCEED(); } -void ISystemSettingsServer::SetDeviceTimeZoneLocationName(HLERequestContext& ctx) { +Result ISystemSettingsServer::SetDeviceTimeZoneLocationName( + const Service::PSC::Time::LocationName& name) { LOG_INFO(Service_SET, "called"); - IPC::RequestParser rp{ctx}; - auto name{rp.PopRaw<Service::PSC::Time::LocationName>()}; - - const auto res = SetDeviceTimeZoneLocationName(name); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); -} - -void ISystemSettingsServer::SetRegionCode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.region_code = rp.PopEnum<SystemRegionCode>(); + m_system_settings.device_time_zone_location_name = name; SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, region_code={}", m_system_settings.region_code); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::GetNetworkSystemClockContext(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); +Result ISystemSettingsServer::SetRegionCode(SystemRegionCode region_code) { + LOG_INFO(Service_SET, "called, region_code={}", region_code); - Service::PSC::Time::SystemClockContext context{}; - const auto res = GetNetworkSystemClockContext(context); - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::SystemClockContext) / sizeof(u32)}; - rb.Push(res); - rb.PushRaw(context); + m_system_settings.region_code = region_code; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::SetNetworkSystemClockContext(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetNetworkSystemClockContext( + Out<Service::PSC::Time::SystemClockContext> out_context) { LOG_INFO(Service_SET, "called"); - IPC::RequestParser rp{ctx}; - const auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()}; - - const auto res = SetNetworkSystemClockContext(context); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + *out_context = m_system_settings.network_system_clock_context; + R_SUCCEED(); } -void ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx) { +Result ISystemSettingsServer::SetNetworkSystemClockContext( + const Service::PSC::Time::SystemClockContext& context) { LOG_INFO(Service_SET, "called"); - bool enabled{}; - const auto res = IsUserSystemClockAutomaticCorrectionEnabled(enabled); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.PushRaw(enabled); + m_system_settings.network_system_clock_context = context; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx) { - LOG_INFO(Service_SET, "called"); +Result ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled( + Out<bool> out_automatic_correction_enabled) { + LOG_INFO(Service_SET, "called, out_automatic_correction_enabled={}", + m_system_settings.user_system_clock_automatic_correction_enabled); - IPC::RequestParser rp{ctx}; - auto enabled{rp.Pop<bool>()}; + *out_automatic_correction_enabled = + m_system_settings.user_system_clock_automatic_correction_enabled; + R_SUCCEED(); +} - const auto res = SetUserSystemClockAutomaticCorrectionEnabled(enabled); +Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled( + bool automatic_correction_enabled) { + LOG_INFO(Service_SET, "called, out_automatic_correction_enabled={}", + automatic_correction_enabled); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + m_system_settings.user_system_clock_automatic_correction_enabled = automatic_correction_enabled; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetDebugModeFlag(HLERequestContext& ctx) { - bool is_debug_mode_enabled = false; - GetSettingsItemValue<bool>(is_debug_mode_enabled, "settings_debug", "is_debug_mode_enabled"); +Result ISystemSettingsServer::GetDebugModeFlag(Out<bool> is_debug_mode_enabled) { + const auto result = GetSettingsItemValueImpl<bool>(*is_debug_mode_enabled, "settings_debug", + "is_debug_mode_enabled"); - LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", is_debug_mode_enabled); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(is_debug_mode_enabled); + LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", *is_debug_mode_enabled); + R_RETURN(result); } -void ISystemSettingsServer::GetPrimaryAlbumStorage(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetPrimaryAlbumStorage( + Out<PrimaryAlbumStorage> out_primary_album_storage) { LOG_INFO(Service_SET, "called, primary_album_storage={}", m_system_settings.primary_album_storage); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(m_system_settings.primary_album_storage); + *out_primary_album_storage = m_system_settings.primary_album_storage; + R_SUCCEED(); } -void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.primary_album_storage = rp.PopEnum<PrimaryAlbumStorage>(); - SetSaveNeeded(); +Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage) { + LOG_INFO(Service_SET, "called, primary_album_storage={}", primary_album_storage); - LOG_INFO(Service_SET, "called, primary_album_storage={}", - m_system_settings.primary_album_storage); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.primary_album_storage = primary_album_storage; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) { - BatteryLot battery_lot = {"YUZUEMULATOR123456789"}; - +Result ISystemSettingsServer::GetBatteryLot(Out<BatteryLot> out_battery_lot) { LOG_INFO(Service_SET, "called"); - IPC::ResponseBuilder rb{ctx, 8}; - rb.Push(ResultSuccess); - rb.PushRaw(battery_lot); + *out_battery_lot = {"YUZU0EMULATOR14022024"}; + R_SUCCEED(); } -void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) { - SerialNumber console_serial = {"YUZ10012345678"}; - +Result ISystemSettingsServer::GetSerialNumber(Out<SerialNumber> out_console_serial) { LOG_INFO(Service_SET, "called"); - IPC::ResponseBuilder rb{ctx, 8}; - rb.Push(ResultSuccess); - rb.PushRaw(console_serial); + *out_console_serial = {"YUZ10000000001"}; + R_SUCCEED(); } -void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetNfcEnableFlag(Out<bool> out_nfc_enable_flag) { LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(m_system_settings.nfc_enable_flag); + *out_nfc_enable_flag = m_system_settings.nfc_enable_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetNfcEnableFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.nfc_enable_flag = rp.Pop<bool>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag); +Result ISystemSettingsServer::SetNfcEnableFlag(bool nfc_enable_flag) { + LOG_INFO(Service_SET, "called, nfc_enable_flag={}", nfc_enable_flag); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.nfc_enable_flag = nfc_enable_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetSleepSettings(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetSleepSettings(Out<SleepSettings> out_sleep_settings) { LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}", m_system_settings.sleep_settings.flags.raw, m_system_settings.sleep_settings.handheld_sleep_plan, m_system_settings.sleep_settings.console_sleep_plan); - IPC::ResponseBuilder rb{ctx, 5}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.sleep_settings); + *out_sleep_settings = m_system_settings.sleep_settings; + R_SUCCEED(); } -void ISystemSettingsServer::SetSleepSettings(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.sleep_settings = rp.PopRaw<SleepSettings>(); - SetSaveNeeded(); - +Result ISystemSettingsServer::SetSleepSettings(SleepSettings sleep_settings) { LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}", - m_system_settings.sleep_settings.flags.raw, - m_system_settings.sleep_settings.handheld_sleep_plan, - m_system_settings.sleep_settings.console_sleep_plan); + sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan, + sleep_settings.console_sleep_plan); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.sleep_settings = sleep_settings; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetWirelessLanEnableFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag) { LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", m_system_settings.wireless_lan_enable_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.wireless_lan_enable_flag); + *out_wireless_lan_enable_flag = m_system_settings.wireless_lan_enable_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetWirelessLanEnableFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.wireless_lan_enable_flag = rp.Pop<bool>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", - m_system_settings.wireless_lan_enable_flag); +Result ISystemSettingsServer::SetWirelessLanEnableFlag(bool wireless_lan_enable_flag) { + LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", wireless_lan_enable_flag); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.wireless_lan_enable_flag = wireless_lan_enable_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetInitialLaunchSettings(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetInitialLaunchSettings( + Out<InitialLaunchSettings> out_initial_launch_settings) { LOG_INFO(Service_SET, "called, flags={}, timestamp={}", m_system_settings.initial_launch_settings_packed.flags.raw, m_system_settings.initial_launch_settings_packed.timestamp.time_point); - IPC::ResponseBuilder rb{ctx, 10}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.initial_launch_settings_packed); + *out_initial_launch_settings = { + .flags = m_system_settings.initial_launch_settings_packed.flags, + .timestamp = m_system_settings.initial_launch_settings_packed.timestamp, + }; + R_SUCCEED(); } -void ISystemSettingsServer::SetInitialLaunchSettings(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - auto initial_launch_settings = rp.PopRaw<InitialLaunchSettings>(); +Result ISystemSettingsServer::SetInitialLaunchSettings( + InitialLaunchSettings initial_launch_settings) { + LOG_INFO(Service_SET, "called, flags={}, timestamp={}", initial_launch_settings.flags.raw, + initial_launch_settings.timestamp.time_point); m_system_settings.initial_launch_settings_packed.flags = initial_launch_settings.flags; m_system_settings.initial_launch_settings_packed.timestamp = initial_launch_settings.timestamp; SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, flags={}, timestamp={}", - m_system_settings.initial_launch_settings_packed.flags.raw, - m_system_settings.initial_launch_settings_packed.timestamp.time_point); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::GetDeviceNickName(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetDeviceNickName( + OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name) { LOG_DEBUG(Service_SET, "called"); - ctx.WriteBuffer(::Settings::values.device_name.GetValue()); + *out_device_name = {}; + const auto device_name_buffer = ::Settings::values.device_name.GetValue().c_str(); + memcpy(out_device_name->data(), device_name_buffer, + ::Settings::values.device_name.GetValue().size()); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::SetDeviceNickName(HLERequestContext& ctx) { - const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer()); +Result ISystemSettingsServer::SetDeviceNickName( + InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer) { + const std::string device_name = Common::StringFromBuffer(*device_name_buffer); LOG_INFO(Service_SET, "called, device_name={}", device_name); ::Settings::values.device_name = device_name; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void ISystemSettingsServer::GetProductModel(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetProductModel(Out<u32> out_product_model) { const u32 product_model = 1; LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(product_model); + + *out_product_model = product_model; + R_SUCCEED(); } -void ISystemSettingsServer::GetBluetoothEnableFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag) { LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", m_system_settings.bluetooth_enable_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u8>(m_system_settings.bluetooth_enable_flag); + *out_bluetooth_enable_flag = m_system_settings.bluetooth_enable_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetBluetoothEnableFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.bluetooth_enable_flag = rp.Pop<bool>(); - SetSaveNeeded(); +Result ISystemSettingsServer::SetBluetoothEnableFlag(bool bluetooth_enable_flag) { + LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", bluetooth_enable_flag); - LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", - m_system_settings.bluetooth_enable_flag); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.bluetooth_enable_flag = bluetooth_enable_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetMiiAuthorId(Out<Common::UUID> out_mii_author_id) { if (m_system_settings.mii_author_id.IsInvalid()) { m_system_settings.mii_author_id = Common::UUID::MakeDefault(); SetSaveNeeded(); @@ -1166,282 +1060,224 @@ void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { LOG_INFO(Service_SET, "called, author_id={}", m_system_settings.mii_author_id.FormattedString()); - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.PushRaw(m_system_settings.mii_author_id); + *out_mii_author_id = m_system_settings.mii_author_id; + R_SUCCEED(); } -void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag) { LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.auto_update_enable_flag); + *out_auto_update_enable_flag = m_system_settings.auto_update_enable_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.auto_update_enable_flag = rp.Pop<bool>(); - SetSaveNeeded(); +Result ISystemSettingsServer::SetAutoUpdateEnableFlag(bool auto_update_enable_flag) { + LOG_INFO(Service_SET, "called, auto_update_flag={}", auto_update_enable_flag); - LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.auto_update_enable_flag = auto_update_enable_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag) { LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}", m_system_settings.battery_percentage_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.battery_percentage_flag); + *out_battery_percentage_flag = m_system_settings.battery_percentage_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.battery_percentage_flag = rp.Pop<bool>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, battery_percentage_flag={}", - m_system_settings.battery_percentage_flag); +Result ISystemSettingsServer::SetBatteryPercentageFlag(bool battery_percentage_flag) { + LOG_INFO(Service_SET, "called, battery_percentage_flag={}", battery_percentage_flag); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.battery_percentage_flag = battery_percentage_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called."); - - IPC::RequestParser rp{ctx}; - auto offset{rp.Pop<s64>()}; - - const auto res = SetExternalSteadyClockInternalOffset(offset); +Result ISystemSettingsServer::SetExternalSteadyClockInternalOffset(s64 offset) { + LOG_DEBUG(Service_SET, "called, external_steady_clock_internal_offset={}", offset); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + m_private_settings.external_steady_clock_internal_offset = offset; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called."); +Result ISystemSettingsServer::GetExternalSteadyClockInternalOffset(Out<s64> out_offset) { + LOG_DEBUG(Service_SET, "called, external_steady_clock_internal_offset={}", + m_private_settings.external_steady_clock_internal_offset); - s64 offset{}; - const auto res = GetExternalSteadyClockInternalOffset(offset); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.Push(offset); + *out_offset = m_private_settings.external_steady_clock_internal_offset; + R_SUCCEED(); } -void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetPushNotificationActivityModeOnSleep( + Out<s32> out_push_notification_activity_mode_on_sleep) { LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}", m_system_settings.push_notification_activity_mode_on_sleep); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.push_notification_activity_mode_on_sleep); + *out_push_notification_activity_mode_on_sleep = + m_system_settings.push_notification_activity_mode_on_sleep; + R_SUCCEED(); } -void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>(); - SetSaveNeeded(); - +Result ISystemSettingsServer::SetPushNotificationActivityModeOnSleep( + s32 push_notification_activity_mode_on_sleep) { LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}", - m_system_settings.push_notification_activity_mode_on_sleep); + push_notification_activity_mode_on_sleep); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.push_notification_activity_mode_on_sleep = + push_notification_activity_mode_on_sleep; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetErrorReportSharePermission( + Out<ErrorReportSharePermission> out_error_report_share_permission) { LOG_INFO(Service_SET, "called, error_report_share_permission={}", m_system_settings.error_report_share_permission); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(m_system_settings.error_report_share_permission); + *out_error_report_share_permission = m_system_settings.error_report_share_permission; + R_SUCCEED(); } -void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>(); - SetSaveNeeded(); - +Result ISystemSettingsServer::SetErrorReportSharePermission( + ErrorReportSharePermission error_report_share_permission) { LOG_INFO(Service_SET, "called, error_report_share_permission={}", - m_system_settings.error_report_share_permission); + error_report_share_permission); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.error_report_share_permission = error_report_share_permission; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetAppletLaunchFlags(Out<u32> out_applet_launch_flag) { LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.applet_launch_flag); + *out_applet_launch_flag = m_system_settings.applet_launch_flag; + R_SUCCEED(); } -void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.applet_launch_flag = rp.Pop<u32>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag); +Result ISystemSettingsServer::SetAppletLaunchFlags(u32 applet_launch_flag) { + LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.applet_launch_flag = applet_launch_flag; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout) { LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(m_system_settings.keyboard_layout)); + *out_keyboard_layout = m_system_settings.keyboard_layout; + R_SUCCEED(); } -void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>(); - SetSaveNeeded(); - - LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout); +Result ISystemSettingsServer::SetKeyboardLayout(KeyboardLayout keyboard_layout) { + LOG_INFO(Service_SET, "called, keyboard_layout={}", keyboard_layout); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.keyboard_layout = keyboard_layout; + R_SUCCEED(); } -void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime( + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { LOG_INFO(Service_SET, "called"); - Service::PSC::Time::SteadyClockTimePoint time_point{}; - const auto res = GetDeviceTimeZoneLocationUpdatedTime(time_point); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point); + *out_time_point = m_system_settings.device_time_zone_location_updated_time; + R_SUCCEED(); } -void ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) { +Result ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime( + const Service::PSC::Time::SteadyClockTimePoint& time_point) { LOG_INFO(Service_SET, "called"); - IPC::RequestParser rp{ctx}; - auto time_point{rp.PopRaw<Service::PSC::Time::SteadyClockTimePoint>()}; - - const auto res = SetDeviceTimeZoneLocationUpdatedTime(time_point); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + m_system_settings.device_time_zone_location_updated_time = time_point; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime( - HLERequestContext& ctx) { +Result ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime( + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) { LOG_INFO(Service_SET, "called"); - Service::PSC::Time::SteadyClockTimePoint time_point{}; - const auto res = GetUserSystemClockAutomaticCorrectionUpdatedTime(time_point); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(res); - rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point); + *out_time_point = m_system_settings.user_system_clock_automatic_correction_updated_time_point; + R_SUCCEED(); } -void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime( - HLERequestContext& ctx) { +Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime( + const Service::PSC::Time::SteadyClockTimePoint& out_time_point) { LOG_INFO(Service_SET, "called"); - IPC::RequestParser rp{ctx}; - const auto time_point{rp.PopRaw<Service::PSC::Time::SteadyClockTimePoint>()}; - - const auto res = SetUserSystemClockAutomaticCorrectionUpdatedTime(time_point); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + m_system_settings.user_system_clock_automatic_correction_updated_time_point = out_time_point; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetChineseTraditionalInputMethod(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetChineseTraditionalInputMethod( + Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method) { LOG_INFO(Service_SET, "called, chinese_traditional_input_method={}", m_system_settings.chinese_traditional_input_method); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.PushEnum(m_system_settings.chinese_traditional_input_method); + *out_chinese_traditional_input_method = m_system_settings.chinese_traditional_input_method; + R_SUCCEED(); } -void ISystemSettingsServer::GetHomeMenuScheme(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme) { LOG_DEBUG(Service_SET, "(STUBBED) called"); - const HomeMenuScheme default_color = { + *out_home_menu_scheme = { .main = 0xFF323232, .back = 0xFF323232, .sub = 0xFFFFFFFF, .bezel = 0xFFFFFFFF, .extra = 0xFF000000, }; - - IPC::ResponseBuilder rb{ctx, 2 + sizeof(HomeMenuScheme) / sizeof(u32)}; - rb.Push(ResultSuccess); - rb.PushRaw(default_color); + R_SUCCEED(); } -void ISystemSettingsServer::GetHomeMenuSchemeModel(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model) { LOG_WARNING(Service_SET, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(0); + *out_home_menu_scheme_model = 0; + R_SUCCEED(); } -void ISystemSettingsServer::GetTouchScreenMode(HLERequestContext& ctx) { - TouchScreenMode touch_screen_mode{}; - auto res = GetTouchScreenMode(touch_screen_mode); +Result ISystemSettingsServer::GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode) { + LOG_INFO(Service_SET, "called, touch_screen_mode={}", m_system_settings.touch_screen_mode); - LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(res); - rb.PushEnum(touch_screen_mode); + *out_touch_screen_mode = m_system_settings.touch_screen_mode; + R_SUCCEED(); } -void ISystemSettingsServer::SetTouchScreenMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto touch_screen_mode = rp.PopEnum<TouchScreenMode>(); - auto res = SetTouchScreenMode(touch_screen_mode); - +Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) { LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(res); + m_system_settings.touch_screen_mode = touch_screen_mode; + SetSaveNeeded(); + R_SUCCEED(); } -void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetFieldTestingFlag(Out<bool> out_field_testing_flag) { LOG_INFO(Service_SET, "called, field_testing_flag={}", m_system_settings.field_testing_flag); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.field_testing_flag); + *out_field_testing_flag = m_system_settings.field_testing_flag; + R_SUCCEED(); } -void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) { +Result ISystemSettingsServer::GetPanelCrcMode(Out<s32> out_panel_crc_mode) { LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(m_system_settings.panel_crc_mode); + *out_panel_crc_mode = m_system_settings.panel_crc_mode; + R_SUCCEED(); } -void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - m_system_settings.panel_crc_mode = rp.PopRaw<s32>(); - SetSaveNeeded(); +Result ISystemSettingsServer::SetPanelCrcMode(s32 panel_crc_mode) { + LOG_INFO(Service_SET, "called, panel_crc_mode={}", panel_crc_mode); - LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_system_settings.panel_crc_mode = panel_crc_mode; + SetSaveNeeded(); + R_SUCCEED(); } void ISystemSettingsServer::SetupSettings() { @@ -1513,9 +1349,9 @@ void ISystemSettingsServer::SetSaveNeeded() { m_save_needed = true; } -Result ISystemSettingsServer::GetSettingsItemValue(std::vector<u8>& out_value, - const std::string& category, - const std::string& name) { +Result ISystemSettingsServer::GetSettingsItemValueImpl(std::vector<u8>& out_value, + const std::string& category, + const std::string& name) { auto settings{GetSettings()}; R_UNLESS(settings.contains(category) && settings[category].contains(name), ResultUnknown); @@ -1523,184 +1359,4 @@ Result ISystemSettingsServer::GetSettingsItemValue(std::vector<u8>& out_value, R_SUCCEED(); } -Result ISystemSettingsServer::GetVibrationMasterVolume(f32& out_volume) const { - out_volume = m_system_settings.vibration_master_volume; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) { - m_system_settings.vibration_master_volume = volume; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode, - AudioOutputModeTarget target) const { - switch (target) { - case AudioOutputModeTarget::Hdmi: - out_output_mode = m_system_settings.audio_output_mode_hdmi; - break; - case AudioOutputModeTarget::Speaker: - out_output_mode = m_system_settings.audio_output_mode_speaker; - break; - case AudioOutputModeTarget::Headphone: - out_output_mode = m_system_settings.audio_output_mode_headphone; - break; - case AudioOutputModeTarget::Type3: - out_output_mode = m_system_settings.audio_output_mode_type3; - break; - case AudioOutputModeTarget::Type4: - out_output_mode = m_system_settings.audio_output_mode_type4; - break; - default: - LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target); - } - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target, - AudioOutputMode output_mode) { - switch (target) { - case AudioOutputModeTarget::Hdmi: - m_system_settings.audio_output_mode_hdmi = output_mode; - break; - case AudioOutputModeTarget::Speaker: - m_system_settings.audio_output_mode_speaker = output_mode; - break; - case AudioOutputModeTarget::Headphone: - m_system_settings.audio_output_mode_headphone = output_mode; - break; - case AudioOutputModeTarget::Type3: - m_system_settings.audio_output_mode_type3 = output_mode; - break; - case AudioOutputModeTarget::Type4: - m_system_settings.audio_output_mode_type4 = output_mode; - break; - default: - LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target); - } - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const { - is_auto_mute = m_system_settings.force_mute_on_headphone_removed; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) { - m_system_settings.force_mute_on_headphone_removed = is_auto_mute; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const { - out_id = m_private_settings.external_clock_source_id; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetExternalSteadyClockSourceId(const Common::UUID& id) { - m_private_settings.external_clock_source_id = id; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetUserSystemClockContext( - Service::PSC::Time::SystemClockContext& out_context) const { - out_context = m_system_settings.user_system_clock_context; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetUserSystemClockContext( - const Service::PSC::Time::SystemClockContext& context) { - m_system_settings.user_system_clock_context = context; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetDeviceTimeZoneLocationName( - Service::PSC::Time::LocationName& out_name) const { - out_name = m_system_settings.device_time_zone_location_name; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetDeviceTimeZoneLocationName( - const Service::PSC::Time::LocationName& name) { - m_system_settings.device_time_zone_location_name = name; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetNetworkSystemClockContext( - Service::PSC::Time::SystemClockContext& out_context) const { - out_context = m_system_settings.network_system_clock_context; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetNetworkSystemClockContext( - const Service::PSC::Time::SystemClockContext& context) { - m_system_settings.network_system_clock_context = context; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const { - out_enabled = m_system_settings.user_system_clock_automatic_correction_enabled; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(bool enabled) { - m_system_settings.user_system_clock_automatic_correction_enabled = enabled; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetExternalSteadyClockInternalOffset(s64 offset) { - m_private_settings.external_steady_clock_internal_offset = offset; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetExternalSteadyClockInternalOffset(s64& out_offset) const { - out_offset = m_private_settings.external_steady_clock_internal_offset; - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point) const { - out_time_point = m_system_settings.device_time_zone_location_updated_time; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime( - const Service::PSC::Time::SteadyClockTimePoint& time_point) { - m_system_settings.device_time_zone_location_updated_time = time_point; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point) const { - out_time_point = m_system_settings.user_system_clock_automatic_correction_updated_time_point; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime( - const Service::PSC::Time::SteadyClockTimePoint& out_time_point) { - m_system_settings.user_system_clock_automatic_correction_updated_time_point = out_time_point; - SetSaveNeeded(); - R_SUCCEED(); -} - -Result ISystemSettingsServer::GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const { - touch_screen_mode = m_system_settings.touch_screen_mode; - R_SUCCEED(); -} - -Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) { - m_system_settings.touch_screen_mode = touch_screen_mode; - SetSaveNeeded(); - R_SUCCEED(); -} - } // namespace Service::Set diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h index 9a3b36f0c..46e06c8ea 100644 --- a/src/core/hle/service/set/system_settings_server.h +++ b/src/core/hle/service/set/system_settings_server.h @@ -11,6 +11,7 @@ #include "common/polyfill_thread.h" #include "common/uuid.h" #include "core/hle/result.h" +#include "core/hle/service/cmif_types.h" #include "core/hle/service/psc/time/common.h" #include "core/hle/service/service.h" #include "core/hle/service/set/setting_formats/appln_settings.h" @@ -33,13 +34,14 @@ public: explicit ISystemSettingsServer(Core::System& system_); ~ISystemSettingsServer() override; - Result GetSettingsItemValue(std::vector<u8>& out_value, const std::string& category, - const std::string& name); + Result GetSettingsItemValueImpl(std::vector<u8>& out_value, const std::string& category, + const std::string& name); template <typename T> - Result GetSettingsItemValue(T& value, const std::string& category, const std::string& name) { + Result GetSettingsItemValueImpl(T& value, const std::string& category, + const std::string& name) { std::vector<u8> data; - const auto result = GetSettingsItemValue(data, category, name); + const auto result = GetSettingsItemValueImpl(data, category, name); if (result.IsError()) { return result; } @@ -48,120 +50,114 @@ public: return result; } - Result GetVibrationMasterVolume(f32& out_volume) const; - Result SetVibrationMasterVolume(f32 volume); - Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const; +public: + Result SetLanguageCode(LanguageCode language_code); + Result GetFirmwareVersion( + OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data); + Result GetFirmwareVersion2( + OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data); + Result GetLockScreenFlag(Out<bool> out_lock_screen_flag); + Result SetLockScreenFlag(bool lock_screen_flag); + Result GetExternalSteadyClockSourceId(Out<Common::UUID> out_clock_source_id); + Result SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id); + Result GetUserSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_clock_context); + Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& clock_context); + Result GetAccountSettings(Out<AccountSettings> out_account_settings); + Result SetAccountSettings(AccountSettings account_settings); + Result GetEulaVersions(Out<s32> out_count, + OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions); + Result SetEulaVersions(InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions); + Result GetColorSetId(Out<ColorSet> out_color_set_id); + Result SetColorSetId(ColorSet color_set_id); + Result GetNotificationSettings(Out<NotificationSettings> out_notification_settings); + Result SetNotificationSettings(const NotificationSettings& notification_settings); + Result GetAccountNotificationSettings( + Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> + out_account_notification_settings); + Result SetAccountNotificationSettings( + InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> + account_notification_settings); + Result GetVibrationMasterVolume(Out<f32> vibration_master_volume); + Result SetVibrationMasterVolume(f32 vibration_master_volume); + Result GetSettingsItemValueSize( + Out<u64> out_size, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf); + Result GetSettingsItemValue( + OutBuffer<BufferAttr_HipcMapAlias> out_data, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, + InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer); + Result GetTvSettings(Out<TvSettings> out_tv_settings); + Result SetTvSettings(TvSettings tv_settings); + Result GetAudioOutputMode(Out<AudioOutputMode> out_output_mode, AudioOutputModeTarget target); Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode); - Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const; - Result SetSpeakerAutoMuteFlag(bool auto_mute); - Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const; - Result SetExternalSteadyClockSourceId(const Common::UUID& id); - Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; - Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& context); - Result GetDeviceTimeZoneLocationName(Service::PSC::Time::LocationName& out_name) const; + Result GetSpeakerAutoMuteFlag(Out<bool> out_force_mute_on_headphone_removed); + Result SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed); + Result GetQuestFlag(Out<QuestFlag> out_quest_flag); + Result SetQuestFlag(QuestFlag quest_flag); + Result GetDeviceTimeZoneLocationName(Out<Service::PSC::Time::LocationName> out_name); Result SetDeviceTimeZoneLocationName(const Service::PSC::Time::LocationName& name); - Result GetNetworkSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; + Result SetRegionCode(SystemRegionCode region_code); + Result GetNetworkSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_context); Result SetNetworkSystemClockContext(const Service::PSC::Time::SystemClockContext& context); - Result IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const; - Result SetUserSystemClockAutomaticCorrectionEnabled(bool enabled); + Result IsUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_automatic_correction_enabled); + Result SetUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction_enabled); + Result GetDebugModeFlag(Out<bool> is_debug_mode_enabled); + Result GetPrimaryAlbumStorage(Out<PrimaryAlbumStorage> out_primary_album_storage); + Result SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage); + Result GetBatteryLot(Out<BatteryLot> out_battery_lot); + Result GetSerialNumber(Out<SerialNumber> out_console_serial); + Result GetNfcEnableFlag(Out<bool> out_nfc_enable_flag); + Result SetNfcEnableFlag(bool nfc_enable_flag); + Result GetSleepSettings(Out<SleepSettings> out_sleep_settings); + Result SetSleepSettings(SleepSettings sleep_settings); + Result GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag); + Result SetWirelessLanEnableFlag(bool wireless_lan_enable_flag); + Result GetInitialLaunchSettings(Out<InitialLaunchSettings> out_initial_launch_settings); + Result SetInitialLaunchSettings(InitialLaunchSettings initial_launch_settings); + Result GetDeviceNickName( + OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name); + Result SetDeviceNickName( + InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer); + Result GetProductModel(Out<u32> out_product_model); + Result GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag); + Result SetBluetoothEnableFlag(bool bluetooth_enable_flag); + Result GetMiiAuthorId(Out<Common::UUID> out_mii_author_id); + Result GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag); + Result SetAutoUpdateEnableFlag(bool auto_update_enable_flag); + Result GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag); + Result SetBatteryPercentageFlag(bool battery_percentage_flag); Result SetExternalSteadyClockInternalOffset(s64 offset); - Result GetExternalSteadyClockInternalOffset(s64& out_offset) const; + Result GetExternalSteadyClockInternalOffset(Out<s64> out_offset); + Result GetPushNotificationActivityModeOnSleep( + Out<s32> out_push_notification_activity_mode_on_sleep); + Result SetPushNotificationActivityModeOnSleep(s32 push_notification_activity_mode_on_sleep); + Result GetErrorReportSharePermission( + Out<ErrorReportSharePermission> out_error_report_share_permission); + Result SetErrorReportSharePermission(ErrorReportSharePermission error_report_share_permission); + Result GetAppletLaunchFlags(Out<u32> out_applet_launch_flag); + Result SetAppletLaunchFlags(u32 applet_launch_flag); + Result GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout); + Result SetKeyboardLayout(KeyboardLayout keyboard_layout); Result GetDeviceTimeZoneLocationUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point) const; + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); Result SetDeviceTimeZoneLocationUpdatedTime( const Service::PSC::Time::SteadyClockTimePoint& time_point); Result GetUserSystemClockAutomaticCorrectionUpdatedTime( - Service::PSC::Time::SteadyClockTimePoint& out_time_point) const; + Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); Result SetUserSystemClockAutomaticCorrectionUpdatedTime( - const Service::PSC::Time::SteadyClockTimePoint& time_point); - Result GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const; + const Service::PSC::Time::SteadyClockTimePoint& out_time_point); + Result GetChineseTraditionalInputMethod( + Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method); + Result GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme); + Result GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model); + Result GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode); Result SetTouchScreenMode(TouchScreenMode touch_screen_mode); + Result GetFieldTestingFlag(Out<bool> out_field_testing_flag); + Result GetPanelCrcMode(Out<s32> out_panel_crc_mode); + Result SetPanelCrcMode(s32 panel_crc_mode); private: - void SetLanguageCode(HLERequestContext& ctx); - void GetFirmwareVersion(HLERequestContext& ctx); - void GetFirmwareVersion2(HLERequestContext& ctx); - void GetLockScreenFlag(HLERequestContext& ctx); - void SetLockScreenFlag(HLERequestContext& ctx); - void GetExternalSteadyClockSourceId(HLERequestContext& ctx); - void SetExternalSteadyClockSourceId(HLERequestContext& ctx); - void GetUserSystemClockContext(HLERequestContext& ctx); - void SetUserSystemClockContext(HLERequestContext& ctx); - void GetAccountSettings(HLERequestContext& ctx); - void SetAccountSettings(HLERequestContext& ctx); - void GetEulaVersions(HLERequestContext& ctx); - void SetEulaVersions(HLERequestContext& ctx); - void GetColorSetId(HLERequestContext& ctx); - void SetColorSetId(HLERequestContext& ctx); - void GetNotificationSettings(HLERequestContext& ctx); - void SetNotificationSettings(HLERequestContext& ctx); - void GetAccountNotificationSettings(HLERequestContext& ctx); - void SetAccountNotificationSettings(HLERequestContext& ctx); - void GetVibrationMasterVolume(HLERequestContext& ctx); - void SetVibrationMasterVolume(HLERequestContext& ctx); - void GetSettingsItemValueSize(HLERequestContext& ctx); - void GetSettingsItemValue(HLERequestContext& ctx); - void GetTvSettings(HLERequestContext& ctx); - void SetTvSettings(HLERequestContext& ctx); - void GetAudioOutputMode(HLERequestContext& ctx); - void SetAudioOutputMode(HLERequestContext& ctx); - void GetSpeakerAutoMuteFlag(HLERequestContext& ctx); - void SetSpeakerAutoMuteFlag(HLERequestContext& ctx); - void GetDebugModeFlag(HLERequestContext& ctx); - void GetQuestFlag(HLERequestContext& ctx); - void SetQuestFlag(HLERequestContext& ctx); - void GetDeviceTimeZoneLocationName(HLERequestContext& ctx); - void SetDeviceTimeZoneLocationName(HLERequestContext& ctx); - void SetRegionCode(HLERequestContext& ctx); - void GetNetworkSystemClockContext(HLERequestContext& ctx); - void SetNetworkSystemClockContext(HLERequestContext& ctx); - void IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); - void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); - void GetPrimaryAlbumStorage(HLERequestContext& ctx); - void SetPrimaryAlbumStorage(HLERequestContext& ctx); - void GetBatteryLot(HLERequestContext& ctx); - void GetSerialNumber(HLERequestContext& ctx); - void GetNfcEnableFlag(HLERequestContext& ctx); - void SetNfcEnableFlag(HLERequestContext& ctx); - void GetSleepSettings(HLERequestContext& ctx); - void SetSleepSettings(HLERequestContext& ctx); - void GetWirelessLanEnableFlag(HLERequestContext& ctx); - void SetWirelessLanEnableFlag(HLERequestContext& ctx); - void GetInitialLaunchSettings(HLERequestContext& ctx); - void SetInitialLaunchSettings(HLERequestContext& ctx); - void GetDeviceNickName(HLERequestContext& ctx); - void SetDeviceNickName(HLERequestContext& ctx); - void GetProductModel(HLERequestContext& ctx); - void GetBluetoothEnableFlag(HLERequestContext& ctx); - void SetBluetoothEnableFlag(HLERequestContext& ctx); - void GetMiiAuthorId(HLERequestContext& ctx); - void GetAutoUpdateEnableFlag(HLERequestContext& ctx); - void SetAutoUpdateEnableFlag(HLERequestContext& ctx); - void GetBatteryPercentageFlag(HLERequestContext& ctx); - void SetBatteryPercentageFlag(HLERequestContext& ctx); - void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx); - void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx); - void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx); - void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx); - void GetErrorReportSharePermission(HLERequestContext& ctx); - void SetErrorReportSharePermission(HLERequestContext& ctx); - void GetAppletLaunchFlags(HLERequestContext& ctx); - void SetAppletLaunchFlags(HLERequestContext& ctx); - void GetKeyboardLayout(HLERequestContext& ctx); - void SetKeyboardLayout(HLERequestContext& ctx); - void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); - void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); - void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); - void SetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); - void GetChineseTraditionalInputMethod(HLERequestContext& ctx); - void GetHomeMenuScheme(HLERequestContext& ctx); - void GetHomeMenuSchemeModel(HLERequestContext& ctx); - void GetTouchScreenMode(HLERequestContext& ctx); - void SetTouchScreenMode(HLERequestContext& ctx); - void GetFieldTestingFlag(HLERequestContext& ctx); - void GetPanelCrcMode(HLERequestContext& ctx); - void SetPanelCrcMode(HLERequestContext& ctx); - bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func); bool StoreSettingsFile(std::filesystem::path& path, auto& settings); void SetupSettings(); diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp new file mode 100644 index 000000000..6b0bcb536 --- /dev/null +++ b/src/core/hle/service/vi/application_display_service.cpp @@ -0,0 +1,302 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h" +#include "core/hle/service/nvnflinger/parcel.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/manager_display_service.h" +#include "core/hle/service/vi/system_display_service.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::VI { + +IApplicationDisplayService::IApplicationDisplayService(Core::System& system_, + std::shared_ptr<Container> container) + : ServiceFramework{system_, "IApplicationDisplayService"}, + m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} { + // clang-format off + static const FunctionInfo functions[] = { + {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, + {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"}, + {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"}, + {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"}, + {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"}, + {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"}, + {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"}, + {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"}, + {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"}, + {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"}, + {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"}, + {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"}, + {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"}, + {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"}, + {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"}, + {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"}, + {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"}, + {2451, nullptr, "GetIndirectLayerImageCropMap"}, + {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"}, + {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"}, + {5203, nullptr, "GetDisplayVsyncEventForDebug"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IApplicationDisplayService::~IApplicationDisplayService() { + for (auto& [display_id, event] : m_display_vsync_events) { + m_container->UnlinkVsyncEvent(display_id, &event); + } + for (const auto layer_id : m_open_layer_ids) { + m_container->CloseLayer(layer_id); + } + for (const auto layer_id : m_stray_layer_ids) { + m_container->DestroyStrayLayer(layer_id); + } +} + +Result IApplicationDisplayService::GetRelayService( + Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + R_RETURN(m_container->GetBinderDriver(out_relay_service)); +} + +Result IApplicationDisplayService::GetSystemDisplayService( + Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_container); + R_SUCCEED(); +} + +Result IApplicationDisplayService::GetManagerDisplayService( + Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_container); + R_SUCCEED(); +} + +Result IApplicationDisplayService::GetIndirectDisplayTransactionService( + Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service)); +} + +Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + display_name[display_name.size() - 1] = '\0'; + ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, + "Non-default displays aren't supported yet"); + + R_RETURN(m_container->OpenDisplay(out_display_id, display_name)); +} + +Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"})); +} + +Result IApplicationDisplayService::CloseDisplay(u64 display_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_container->CloseDisplay(display_id)); +} + +Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { + LOG_DEBUG(Service_VI, "called"); + + // This literally does nothing internally in the actual service itself, + // and just returns a successful result code regardless of the input. + R_SUCCEED(); +} + +Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, + u64 display_id) { + LOG_DEBUG(Service_VI, "called. display_id={}", display_id); + + // This only returns the fixed values of 1280x720 and makes no distinguishing + // between docked and undocked dimensions. + *out_width = static_cast<s64>(DisplayResolution::UndockedWidth); + *out_height = static_cast<s64>(DisplayResolution::UndockedHeight); + R_SUCCEED(); +} + +Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) { + LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id); + + if (scale_mode > NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Invalid scaling mode provided."); + R_THROW(VI::ResultOperationFailed); + } + + if (scale_mode != NintendoScaleMode::ScaleToWindow && + scale_mode != NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); + R_THROW(VI::ResultNotSupported); + } + + R_SUCCEED(); +} + +Result IApplicationDisplayService::ListDisplays( + Out<u64> out_count, OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + if (out_displays.size() > 0) { + out_displays[0] = DisplayInfo{}; + *out_count = 1; + } else { + *out_count = 0; + } + + R_SUCCEED(); +} + +Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, + OutBuffer<BufferAttr_HipcMapAlias> out_native_window, + DisplayName display_name, u64 layer_id, + ClientAppletResourceUserId aruid) { + display_name[display_name.size() - 1] = '\0'; + + LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); + + u64 display_id; + R_TRY(m_container->OpenDisplay(&display_id, display_name)); + + s32 producer_binder_id; + R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid)); + + { + std::scoped_lock lk{m_lock}; + m_open_layer_ids.insert(layer_id); + } + + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{producer_binder_id}); + + const auto buffer = parcel.Serialize(); + std::memcpy(out_native_window.data(), buffer.data(), + std::min(out_native_window.size(), buffer.size())); + *out_size = buffer.size(); + + R_SUCCEED(); +} + +Result IApplicationDisplayService::CloseLayer(u64 layer_id) { + LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); + + { + std::scoped_lock lk{m_lock}; + R_UNLESS(m_open_layer_ids.contains(layer_id), VI::ResultNotFound); + m_open_layer_ids.erase(layer_id); + } + + R_RETURN(m_container->CloseLayer(layer_id)); +} + +Result IApplicationDisplayService::CreateStrayLayer( + Out<u64> out_layer_id, Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window, + u32 flags, u64 display_id) { + LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); + + s32 producer_binder_id; + R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id)); + + std::scoped_lock lk{m_lock}; + m_stray_layer_ids.insert(*out_layer_id); + + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{producer_binder_id}); + + const auto buffer = parcel.Serialize(); + std::memcpy(out_native_window.data(), buffer.data(), + std::min(out_native_window.size(), buffer.size())); + + *out_size = buffer.size(); + + R_SUCCEED(); +} + +Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); + + { + std::scoped_lock lk{m_lock}; + R_UNLESS(m_stray_layer_ids.contains(layer_id), VI::ResultNotFound); + m_stray_layer_ids.erase(layer_id); + } + + R_RETURN(m_container->DestroyStrayLayer(layer_id)); +} + +Result IApplicationDisplayService::GetDisplayVsyncEvent( + OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { + LOG_DEBUG(Service_VI, "called. display_id={}", display_id); + + std::scoped_lock lk{m_lock}; + + auto [it, created] = m_display_vsync_events.emplace(display_id, m_context); + R_UNLESS(created, VI::ResultPermissionDenied); + + m_container->LinkVsyncEvent(display_id, &it->second); + *out_vsync_event = it->second.GetHandle(); + + R_SUCCEED(); +} + +Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, + NintendoScaleMode mode) { + LOG_DEBUG(Service_VI, "called mode={}", mode); + + switch (mode) { + case NintendoScaleMode::None: + *out_scaling_mode = ConvertedScaleMode::None; + R_SUCCEED(); + case NintendoScaleMode::Freeze: + *out_scaling_mode = ConvertedScaleMode::Freeze; + R_SUCCEED(); + case NintendoScaleMode::ScaleToWindow: + *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; + R_SUCCEED(); + case NintendoScaleMode::ScaleAndCrop: + *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; + R_SUCCEED(); + case NintendoScaleMode::PreserveAspectRatio: + *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; + R_SUCCEED(); + default: + LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); + R_THROW(VI::ResultOperationFailed); + } +} + +Result IApplicationDisplayService::GetIndirectLayerImageMap( + Out<u64> out_size, Out<u64> out_stride, + OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer, + s64 width, s64 height, u64 indirect_layer_consumer_handle, ClientAppletResourceUserId aruid) { + LOG_WARNING( + Service_VI, + "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, aruid={:#x}", + width, height, indirect_layer_consumer_handle, aruid.pid); + *out_size = 0; + *out_stride = 0; + R_SUCCEED(); +} + +Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, + Out<s64> out_alignment, + s64 width, s64 height) { + LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); + + constexpr u64 base_size = 0x20000; + const auto texture_size = width * height * 4; + + *out_alignment = 0x1000; + *out_size = (texture_size + base_size - 1) / base_size * base_size; + + R_SUCCEED(); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h new file mode 100644 index 000000000..1bdeb8f84 --- /dev/null +++ b/src/core/hle/service/vi/application_display_service.h @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <map> +#include <set> + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Kernel { +class KReadableEvent; +} + +namespace Service::Nvnflinger { +class IHOSBinderDriver; +} + +namespace Service::VI { + +class Container; +class IManagerDisplayService; +class ISystemDisplayService; + +class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { +public: + IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container); + ~IApplicationDisplayService() override; + + std::shared_ptr<Container> GetContainer() const { + return m_container; + } + +public: + Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service); + Result GetSystemDisplayService( + Out<SharedPointer<ISystemDisplayService>> out_system_display_service); + Result GetManagerDisplayService( + Out<SharedPointer<IManagerDisplayService>> out_manager_display_service); + Result GetIndirectDisplayTransactionService( + Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service); + Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name); + Result OpenDefaultDisplay(Out<u64> out_display_id); + Result CloseDisplay(u64 display_id); + Result SetDisplayEnabled(u32 state, u64 display_id); + Result GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, u64 display_id); + Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id); + Result ListDisplays(Out<u64> out_count, + OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays); + Result OpenLayer(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window, + DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid); + Result CloseLayer(u64 layer_id); + Result CreateStrayLayer(Out<u64> out_layer_id, Out<u64> out_size, + OutBuffer<BufferAttr_HipcMapAlias> out_native_window, u32 flags, + u64 display_id); + Result DestroyStrayLayer(u64 layer_id); + Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, + u64 display_id); + Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode); + Result GetIndirectLayerImageMap( + Out<u64> out_size, Out<u64> out_stride, + OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer, + s64 width, s64 height, u64 indirect_layer_consumer_handle, + ClientAppletResourceUserId aruid); + Result GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, Out<s64> out_alignment, + s64 width, s64 height); + +private: + const std::shared_ptr<Container> m_container; + + KernelHelpers::ServiceContext m_context; + std::mutex m_lock{}; + std::set<u64> m_open_layer_ids{}; + std::set<u64> m_stray_layer_ids{}; + std::map<u64, Event> m_display_vsync_events{}; + bool m_vsync_event_fetched{false}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp new file mode 100644 index 000000000..7f35a048d --- /dev/null +++ b/src/core/hle/service/vi/application_root_service.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/application_root_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/service_creator.h" +#include "core/hle/service/vi/vi.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +IApplicationRootService::IApplicationRootService(Core::System& system_, + std::shared_ptr<Container> container) + : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} { + static const FunctionInfo functions[] = { + {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, + {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, + }; + RegisterHandlers(functions); +} + +IApplicationRootService::~IApplicationRootService() = default; + +Result IApplicationRootService::GetDisplayService( + Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, + Permission::User, policy)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h new file mode 100644 index 000000000..15aa4483d --- /dev/null +++ b/src/core/hle/service/vi/application_root_service.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::VI { + +class Container; +class IApplicationDisplayService; +enum class Policy : u32; + +class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { +public: + explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container); + ~IApplicationRootService() override; + +private: + Result GetDisplayService( + Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, + Policy policy); + +private: + const std::shared_ptr<Container> m_container; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp new file mode 100644 index 000000000..c8ce4fca0 --- /dev/null +++ b/src/core/hle/service/vi/conductor.cpp @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/hle/service/vi/conductor.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/display_list.h" +#include "core/hle/service/vi/vsync_manager.h" + +constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60}; + +namespace Service::VI { + +Conductor::Conductor(Core::System& system, Container& container, DisplayList& displays) + : m_system(system), m_container(container) { + displays.ForEachDisplay([&](Display& display) { + m_vsync_managers.insert({display.GetId(), VsyncManager{}}); + }); + + if (system.IsMulticore()) { + m_event = Core::Timing::CreateEvent( + "ScreenComposition", + [this](s64 time, + std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { + m_signal.Set(); + return std::chrono::nanoseconds(this->GetNextTicks()); + }); + + system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); + m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); }); + } else { + m_event = Core::Timing::CreateEvent( + "ScreenComposition", + [this](s64 time, + std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { + this->ProcessVsync(); + return std::chrono::nanoseconds(this->GetNextTicks()); + }); + + system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); + } +} + +Conductor::~Conductor() { + m_system.CoreTiming().UnscheduleEvent(m_event); + + if (m_system.IsMulticore()) { + m_thread.request_stop(); + m_signal.Set(); + } +} + +void Conductor::LinkVsyncEvent(u64 display_id, Event* event) { + if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) { + it->second.LinkVsyncEvent(event); + } +} + +void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { + if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) { + it->second.UnlinkVsyncEvent(event); + } +} + +void Conductor::ProcessVsync() { + for (auto& [display_id, manager] : m_vsync_managers) { + m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); + manager.SignalVsync(); + } +} + +void Conductor::VsyncThread(std::stop_token token) { + Common::SetCurrentThreadName("VSyncThread"); + + while (!token.stop_requested()) { + m_signal.Wait(); + + if (m_system.IsShuttingDown()) { + return; + } + + this->ProcessVsync(); + } +} + +s64 Conductor::GetNextTicks() const { + const auto& settings = Settings::values; + auto speed_scale = 1.f; + if (settings.use_multi_core.GetValue()) { + if (settings.use_speed_limit.GetValue()) { + // Scales the speed based on speed_limit setting on MC. SC is handled by + // SpeedLimiter::DoSpeedLimiting. + speed_scale = 100.f / settings.speed_limit.GetValue(); + } else { + // Run at unlocked framerate. + speed_scale = 0.01f; + } + } + + // Adjust by speed limit determined during composition. + speed_scale /= m_compose_speed_scale; + + if (m_system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { + // Run at intended presentation rate during video playback. + speed_scale = 1.f; + } + + const f32 effective_fps = 60.f / static_cast<f32>(m_swap_interval); + return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/conductor.h b/src/core/hle/service/vi/conductor.h new file mode 100644 index 000000000..52e3595d2 --- /dev/null +++ b/src/core/hle/service/vi/conductor.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <memory> +#include <unordered_map> + +#include "common/common_types.h" +#include "common/polyfill_thread.h" +#include "common/thread.h" + +namespace Core { +class System; +} + +namespace Core::Timing { +struct EventType; +} + +namespace Service { +class Event; +} + +namespace Service::VI { + +class Container; +class DisplayList; +class VsyncManager; + +class Conductor { +public: + explicit Conductor(Core::System& system, Container& container, DisplayList& displays); + ~Conductor(); + + void LinkVsyncEvent(u64 display_id, Event* event); + void UnlinkVsyncEvent(u64 display_id, Event* event); + +private: + void ProcessVsync(); + void VsyncThread(std::stop_token token); + s64 GetNextTicks() const; + +private: + Core::System& m_system; + Container& m_container; + std::unordered_map<u64, VsyncManager> m_vsync_managers; + std::shared_ptr<Core::Timing::EventType> m_event; + Common::Event m_signal; + std::jthread m_thread; + +private: + s32 m_swap_interval = 1; + f32 m_compose_speed_scale = 1.0f; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/container.cpp b/src/core/hle/service/vi/container.cpp new file mode 100644 index 000000000..9074f4ae0 --- /dev/null +++ b/src/core/hle/service/vi/container.cpp @@ -0,0 +1,226 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/nvdrv/nvdrv_interface.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::VI { + +Container::Container(Core::System& system) { + m_displays.CreateDisplay(DisplayName{"Default"}); + m_displays.CreateDisplay(DisplayName{"External"}); + m_displays.CreateDisplay(DisplayName{"Edid"}); + m_displays.CreateDisplay(DisplayName{"Internal"}); + m_displays.CreateDisplay(DisplayName{"Null"}); + + m_binder_driver = + system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true); + m_surface_flinger = m_binder_driver->GetSurfaceFlinger(); + + const auto nvdrv = + system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); + m_shared_buffer_manager.emplace(system, *this, nvdrv); + + m_displays.ForEachDisplay( + [&](auto& display) { m_surface_flinger->AddDisplay(display.GetId()); }); + + m_conductor.emplace(system, *this, m_displays); +} + +Container::~Container() { + this->OnTerminate(); +} + +void Container::OnTerminate() { + std::scoped_lock lk{m_lock}; + + m_is_shut_down = true; + + m_layers.ForEachLayer([&](auto& layer) { this->DestroyLayerLocked(layer.GetId()); }); + + m_displays.ForEachDisplay( + [&](auto& display) { m_surface_flinger->RemoveDisplay(display.GetId()); }); +} + +SharedBufferManager* Container::GetSharedBufferManager() { + return std::addressof(*m_shared_buffer_manager); +} + +Result Container::GetBinderDriver( + std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver) { + *out_binder_driver = m_binder_driver; + R_SUCCEED(); +} + +Result Container::GetLayerProducerHandle( + std::shared_ptr<android::BufferQueueProducer>* out_producer, u64 layer_id) { + std::scoped_lock lk{m_lock}; + + auto* const layer = m_layers.GetLayerById(layer_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + + const auto binder = m_binder_driver->GetServer()->TryGetBinder(layer->GetProducerBinderId()); + R_UNLESS(binder != nullptr, VI::ResultNotFound); + + *out_producer = std::static_pointer_cast<android::BufferQueueProducer>(binder); + R_SUCCEED(); +} + +Result Container::OpenDisplay(u64* out_display_id, const DisplayName& display_name) { + auto* const display = m_displays.GetDisplayByName(display_name); + R_UNLESS(display != nullptr, VI::ResultNotFound); + + *out_display_id = display->GetId(); + R_SUCCEED(); +} + +Result Container::CloseDisplay(u64 display_id) { + R_SUCCEED(); +} + +Result Container::CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid) { + std::scoped_lock lk{m_lock}; + R_RETURN(this->CreateLayerLocked(out_layer_id, display_id, owner_aruid)); +} + +Result Container::DestroyManagedLayer(u64 layer_id) { + std::scoped_lock lk{m_lock}; + + // Try to close, if open, but don't fail if not. + this->CloseLayerLocked(layer_id); + + R_RETURN(this->DestroyLayerLocked(layer_id)); +} + +Result Container::OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid) { + std::scoped_lock lk{m_lock}; + R_RETURN(this->OpenLayerLocked(out_producer_binder_id, layer_id, aruid)); +} + +Result Container::CloseLayer(u64 layer_id) { + std::scoped_lock lk{m_lock}; + R_RETURN(this->CloseLayerLocked(layer_id)); +} + +Result Container::SetLayerVisibility(u64 layer_id, bool visible) { + std::scoped_lock lk{m_lock}; + + auto* const layer = m_layers.GetLayerById(layer_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + + m_surface_flinger->SetLayerVisibility(layer->GetConsumerBinderId(), visible); + R_SUCCEED(); +} + +Result Container::SetLayerBlending(u64 layer_id, bool enabled) { + std::scoped_lock lk{m_lock}; + + auto* const layer = m_layers.GetLayerById(layer_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + + m_surface_flinger->SetLayerBlending(layer->GetConsumerBinderId(), + enabled ? Nvnflinger::LayerBlending::Coverage + : Nvnflinger::LayerBlending::None); + R_SUCCEED(); +} + +void Container::LinkVsyncEvent(u64 display_id, Event* event) { + std::scoped_lock lk{m_lock}; + m_conductor->LinkVsyncEvent(display_id, event); +} + +void Container::UnlinkVsyncEvent(u64 display_id, Event* event) { + std::scoped_lock lk{m_lock}; + m_conductor->UnlinkVsyncEvent(display_id, event); +} + +Result Container::CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id) { + std::scoped_lock lk{m_lock}; + R_TRY(this->CreateLayerLocked(out_layer_id, display_id, {})); + R_RETURN(this->OpenLayerLocked(out_producer_binder_id, *out_layer_id, {})); +} + +Result Container::DestroyStrayLayer(u64 layer_id) { + std::scoped_lock lk{m_lock}; + R_TRY(this->CloseLayerLocked(layer_id)); + R_RETURN(this->DestroyLayerLocked(layer_id)); +} + +Result Container::CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid) { + auto* const display = m_displays.GetDisplayById(display_id); + R_UNLESS(display != nullptr, VI::ResultNotFound); + + s32 consumer_binder_id, producer_binder_id; + m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id); + + auto* const layer = + m_layers.CreateLayer(owner_aruid, display, consumer_binder_id, producer_binder_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + + m_surface_flinger->CreateLayer(consumer_binder_id); + + *out_layer_id = layer->GetId(); + R_SUCCEED(); +} + +Result Container::DestroyLayerLocked(u64 layer_id) { + auto* const layer = m_layers.GetLayerById(layer_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + + m_surface_flinger->DestroyLayer(layer->GetConsumerBinderId()); + m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(), + layer->GetProducerBinderId()); + m_layers.DestroyLayer(layer_id); + + R_SUCCEED(); +} + +Result Container::OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid) { + R_UNLESS(!m_is_shut_down, VI::ResultOperationFailed); + + auto* const layer = m_layers.GetLayerById(layer_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + R_UNLESS(!layer->IsOpen(), VI::ResultOperationFailed); + R_UNLESS(layer->GetOwnerAruid() == aruid, VI::ResultPermissionDenied); + + layer->Open(); + + if (auto* display = layer->GetDisplay(); display != nullptr) { + m_surface_flinger->AddLayerToDisplayStack(display->GetId(), layer->GetConsumerBinderId()); + } + + *out_producer_binder_id = layer->GetProducerBinderId(); + + R_SUCCEED(); +} + +Result Container::CloseLayerLocked(u64 layer_id) { + auto* const layer = m_layers.GetLayerById(layer_id); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + R_UNLESS(layer->IsOpen(), VI::ResultOperationFailed); + + if (auto* display = layer->GetDisplay(); display != nullptr) { + m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(), + layer->GetConsumerBinderId()); + } + + layer->Close(); + + R_SUCCEED(); +} + +bool Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, + u64 display_id) { + std::scoped_lock lk{m_lock}; + return m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale, + display_id); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/container.h b/src/core/hle/service/vi/container.h new file mode 100644 index 000000000..5eac4d77d --- /dev/null +++ b/src/core/hle/service/vi/container.h @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <memory> +#include <mutex> +#include <optional> + +#include "core/hle/service/vi/conductor.h" +#include "core/hle/service/vi/display_list.h" +#include "core/hle/service/vi/layer_list.h" +#include "core/hle/service/vi/shared_buffer_manager.h" + +union Result; + +namespace Service::android { +class BufferQueueProducer; +} + +namespace Service::Nvnflinger { +class IHOSBinderDriver; +class SurfaceFlinger; +} // namespace Service::Nvnflinger + +namespace Service { +class Event; +} + +namespace Service::VI { + +class SharedBufferManager; + +class Container { +public: + explicit Container(Core::System& system); + ~Container(); + + void OnTerminate(); + + SharedBufferManager* GetSharedBufferManager(); + + Result GetBinderDriver(std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver); + Result GetLayerProducerHandle(std::shared_ptr<android::BufferQueueProducer>* out_producer, + u64 layer_id); + + Result OpenDisplay(u64* out_display_id, const DisplayName& display_name); + Result CloseDisplay(u64 display_id); + + // Managed layers are created by the interaction between am and ommdisp + // on behalf of an applet. Their lifetime ends with the lifetime of the + // applet's ISelfController. + Result CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid); + Result DestroyManagedLayer(u64 layer_id); + Result OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid); + Result CloseLayer(u64 layer_id); + + // Stray layers are created by non-applet sysmodules. Their lifetime ends + // with the lifetime of the IApplicationDisplayService which created them. + Result CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id); + Result DestroyStrayLayer(u64 layer_id); + + Result SetLayerVisibility(u64 layer_id, bool visible); + Result SetLayerBlending(u64 layer_id, bool enabled); + + void LinkVsyncEvent(u64 display_id, Event* event); + void UnlinkVsyncEvent(u64 display_id, Event* event); + +private: + Result CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid); + Result DestroyLayerLocked(u64 layer_id); + Result OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid); + Result CloseLayerLocked(u64 layer_id); + +public: + bool ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id); + +private: + std::mutex m_lock{}; + DisplayList m_displays{}; + LayerList m_layers{}; + std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_driver{}; + std::shared_ptr<Nvnflinger::SurfaceFlinger> m_surface_flinger{}; + std::optional<SharedBufferManager> m_shared_buffer_manager{}; + std::optional<Conductor> m_conductor{}; + bool m_is_shut_down{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/display.h b/src/core/hle/service/vi/display.h new file mode 100644 index 000000000..fceda75e3 --- /dev/null +++ b/src/core/hle/service/vi/display.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +class Display { +public: + constexpr Display() = default; + + void Initialize(u64 id, const DisplayName& display_name) { + m_id = id; + m_display_name = display_name; + m_is_initialized = true; + } + + void Finalize() { + m_id = {}; + m_display_name = {}; + m_is_initialized = {}; + } + + u64 GetId() const { + return m_id; + } + + const DisplayName& GetDisplayName() const { + return m_display_name; + } + + bool IsInitialized() const { + return m_is_initialized; + } + +private: + u64 m_id{}; + DisplayName m_display_name{}; + bool m_is_initialized{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp deleted file mode 100644 index 7f2af9acc..000000000 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <utility> - -#include <fmt/format.h> - -#include "common/assert.h" -#include "core/core.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/nvdrv/core/container.h" -#include "core/hle/service/nvnflinger/buffer_item_consumer.h" -#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" -#include "core/hle/service/nvnflinger/buffer_queue_core.h" -#include "core/hle/service/nvnflinger/buffer_queue_producer.h" -#include "core/hle/service/nvnflinger/hardware_composer.h" -#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/vi/display/vi_display.h" -#include "core/hle/service/vi/layer/vi_layer.h" -#include "core/hle/service/vi/vi_results.h" - -namespace Service::VI { - -struct BufferQueue { - std::shared_ptr<android::BufferQueueCore> core; - std::unique_ptr<android::BufferQueueProducer> producer; - std::unique_ptr<android::BufferQueueConsumer> consumer; -}; - -static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context, - Service::Nvidia::NvCore::NvMap& nvmap) { - auto buffer_queue_core = std::make_shared<android::BufferQueueCore>(); - return { - buffer_queue_core, - std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), - std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)}; -} - -Display::Display(u64 id, std::string name_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, - KernelHelpers::ServiceContext& service_context_, Core::System& system_) - : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_}, - service_context{service_context_} { - hardware_composer = std::make_unique<Nvnflinger::HardwareComposer>(); - vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id)); -} - -Display::~Display() { - service_context.CloseEvent(vsync_event); -} - -Layer& Display::GetLayer(std::size_t index) { - size_t i = 0; - for (auto& layer : layers) { - if (!layer->IsOpen() || !layer->IsVisible()) { - continue; - } - - if (i == index) { - return *layer; - } - - i++; - } - - UNREACHABLE(); -} - -size_t Display::GetNumLayers() const { - return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); }); -} - -Kernel::KReadableEvent* Display::GetVSyncEvent() { - return &vsync_event->GetReadableEvent(); -} - -void Display::SignalVSyncEvent() { - vsync_event->Signal(); -} - -void Display::CreateLayer(u64 layer_id, u32 binder_id, - Service::Nvidia::NvCore::Container& nv_core) { - auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile()); - - auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer)); - buffer_item_consumer->Connect(false); - - layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, - std::move(buffer_item_consumer))); - - if (is_abandoned) { - this->FindLayer(layer_id)->GetConsumer().Abandon(); - } - - hos_binder_driver_server.RegisterProducer(std::move(producer)); -} - -void Display::DestroyLayer(u64 layer_id) { - if (auto* layer = this->FindLayer(layer_id); layer != nullptr) { - layer->GetConsumer().Abandon(); - } - - std::erase_if(layers, - [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); -} - -void Display::Abandon() { - for (auto& layer : layers) { - layer->GetConsumer().Abandon(); - } - is_abandoned = true; -} - -Layer* Display::FindLayer(u64 layer_id) { - const auto itr = - std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { - return layer->GetLayerId() == layer_id; - }); - - if (itr == layers.end()) { - return nullptr; - } - - return itr->get(); -} - -const Layer* Display::FindLayer(u64 layer_id) const { - const auto itr = - std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { - return layer->GetLayerId() == layer_id; - }); - - if (itr == layers.end()) { - return nullptr; - } - - return itr->get(); -} - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h deleted file mode 100644 index 220292cff..000000000 --- a/src/core/hle/service/vi/display/vi_display.h +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <string> -#include <vector> - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "core/hle/result.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KEvent; -class KReadableEvent; -} // namespace Kernel - -namespace Service::android { -class BufferQueueProducer; -} - -namespace Service::KernelHelpers { -class ServiceContext; -} - -namespace Service::Nvnflinger { -class HardwareComposer; -class HosBinderDriverServer; -} // namespace Service::Nvnflinger - -namespace Service::Nvidia::NvCore { -class Container; -class NvMap; -} // namespace Service::Nvidia::NvCore - -namespace Service::VI { - -class Layer; - -/// Represents a single display type -class Display { -public: - YUZU_NON_COPYABLE(Display); - YUZU_NON_MOVEABLE(Display); - - /// Constructs a display with a given unique ID and name. - /// - /// @param id The unique ID for this display. - /// @param hos_binder_driver_server_ Nvnflinger HOSBinderDriver server instance. - /// @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_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, - KernelHelpers::ServiceContext& service_context_, Core::System& system_); - ~Display(); - - /// Gets the unique ID assigned to this display. - u64 GetID() const { - return display_id; - } - - /// Gets the name of this display - const std::string& GetName() const { - return name; - } - - /// Whether or not this display has any layers added to it. - bool HasLayers() const { - return GetNumLayers() > 0; - } - - /// Gets a layer for this display based off an index. - Layer& GetLayer(std::size_t index); - - std::size_t GetNumLayers() const; - - /// Gets the internal vsync event. - Kernel::KReadableEvent* GetVSyncEvent(); - - /// Signals the internal vsync event. - void SignalVSyncEvent(); - - /// Creates and adds a layer to this display with the given ID. - /// - /// @param layer_id The ID to assign to the created layer. - /// @param binder_id The ID assigned to the buffer queue. - /// - void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core); - - /// Removes a layer from this display with the given ID. - /// - /// @param layer_id The ID assigned to the layer to destroy. - /// - void DestroyLayer(u64 layer_id); - - /// Resets the display for a new connection. - void Reset() { - layers.clear(); - } - - void Abandon(); - - /// Attempts to find a layer with the given ID. - /// - /// @param layer_id The layer ID. - /// - /// @returns If found, the Layer instance with the given ID. - /// If not found, then nullptr is returned. - /// - Layer* FindLayer(u64 layer_id); - - /// Attempts to find a layer with the given ID. - /// - /// @param layer_id The layer ID. - /// - /// @returns If found, the Layer instance with the given ID. - /// If not found, then nullptr is returned. - /// - const Layer* FindLayer(u64 layer_id) const; - - Nvnflinger::HardwareComposer& GetComposer() const { - return *hardware_composer; - } - -private: - u64 display_id; - std::string name; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; - KernelHelpers::ServiceContext& service_context; - - std::vector<std::unique_ptr<Layer>> layers; - std::unique_ptr<Nvnflinger::HardwareComposer> hardware_composer; - Kernel::KEvent* vsync_event{}; - bool is_abandoned{}; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/display_list.h b/src/core/hle/service/vi/display_list.h new file mode 100644 index 000000000..f710ac472 --- /dev/null +++ b/src/core/hle/service/vi/display_list.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <cstring> + +#include "core/hle/service/vi/display.h" + +namespace Service::VI { + +class DisplayList { +public: + constexpr DisplayList() = default; + + bool CreateDisplay(const DisplayName& name) { + Display* const display = this->GetFreeDisplay(); + if (!display) { + return false; + } + + display->Initialize(m_next_id++, name); + return true; + } + + bool DestroyDisplay(u64 display_id) { + Display* display = this->GetDisplayById(display_id); + if (!display) { + return false; + } + + display->Finalize(); + return true; + } + + Display* GetDisplayByName(const DisplayName& name) { + for (auto& display : m_displays) { + if (display.IsInitialized() && + std::strncmp(name.data(), display.GetDisplayName().data(), sizeof(DisplayName)) == + 0) { + return &display; + } + } + + return nullptr; + } + + Display* GetDisplayById(u64 display_id) { + for (auto& display : m_displays) { + if (display.IsInitialized() && display.GetId() == display_id) { + return &display; + } + } + + return nullptr; + } + + template <typename F> + void ForEachDisplay(F&& cb) { + for (auto& display : m_displays) { + if (display.IsInitialized()) { + cb(display); + } + } + } + +private: + Display* GetFreeDisplay() { + for (auto& display : m_displays) { + if (!display.IsInitialized()) { + return &display; + } + } + + return nullptr; + } + +private: + std::array<Display, 8> m_displays{}; + u64 m_next_id{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer.h b/src/core/hle/service/vi/layer.h new file mode 100644 index 000000000..e4c9c9864 --- /dev/null +++ b/src/core/hle/service/vi/layer.h @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Service::VI { + +class Display; + +class Layer { +public: + constexpr Layer() = default; + + void Initialize(u64 id, u64 owner_aruid, Display* display, s32 consumer_binder_id, + s32 producer_binder_id) { + m_id = id; + m_owner_aruid = owner_aruid; + m_display = display; + m_consumer_binder_id = consumer_binder_id; + m_producer_binder_id = producer_binder_id; + m_is_initialized = true; + } + + void Finalize() { + m_id = {}; + m_owner_aruid = {}; + m_display = {}; + m_consumer_binder_id = {}; + m_producer_binder_id = {}; + m_is_initialized = {}; + } + + void Open() { + m_is_open = true; + } + + void Close() { + m_is_open = false; + } + + u64 GetId() const { + return m_id; + } + + u64 GetOwnerAruid() const { + return m_owner_aruid; + } + + Display* GetDisplay() const { + return m_display; + } + + s32 GetConsumerBinderId() const { + return m_consumer_binder_id; + } + + s32 GetProducerBinderId() const { + return m_producer_binder_id; + } + + bool IsInitialized() const { + return m_is_initialized; + } + + bool IsOpen() const { + return m_is_open; + } + +private: + u64 m_id{}; + u64 m_owner_aruid{}; + Display* m_display{}; + s32 m_consumer_binder_id{}; + s32 m_producer_binder_id{}; + bool m_is_initialized{}; + bool m_is_open{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp deleted file mode 100644 index eca35d82a..000000000 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/service/nvnflinger/hwc_layer.h" -#include "core/hle/service/vi/layer/vi_layer.h" - -namespace Service::VI { - -Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, - android::BufferQueueProducer& binder_, - std::shared_ptr<android::BufferItemConsumer>&& consumer_) - : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move( - consumer_)}, - blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {} - -Layer::~Layer() = default; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h deleted file mode 100644 index 14e229903..000000000 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <utility> - -#include "common/common_types.h" - -namespace Service::android { -class BufferItemConsumer; -class BufferQueueCore; -class BufferQueueProducer; -} // namespace Service::android - -namespace Service::Nvnflinger { -enum class LayerBlending : u32; -} - -namespace Service::VI { - -/// Represents a single display layer. -class Layer { -public: - /// Constructs a layer with a given ID and buffer queue. - /// - /// @param layer_id_ The ID to assign to this layer. - /// @param binder_id_ The binder ID to assign to this layer. - /// @param binder_ The buffer producer queue for this layer to use. - /// - Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, - android::BufferQueueProducer& binder_, - std::shared_ptr<android::BufferItemConsumer>&& consumer_); - ~Layer(); - - Layer(const Layer&) = delete; - Layer& operator=(const Layer&) = delete; - - Layer(Layer&&) = default; - Layer& operator=(Layer&&) = delete; - - /// Gets the ID for this layer. - u64 GetLayerId() const { - return layer_id; - } - - /// Gets the binder ID for this layer. - u32 GetBinderId() const { - return binder_id; - } - - /// Gets a reference to the buffer queue this layer is using. - android::BufferQueueProducer& GetBufferQueue() { - return binder; - } - - /// Gets a const reference to the buffer queue this layer is using. - const android::BufferQueueProducer& GetBufferQueue() const { - return binder; - } - - android::BufferItemConsumer& GetConsumer() { - return *consumer; - } - - const android::BufferItemConsumer& GetConsumer() const { - return *consumer; - } - - android::BufferQueueCore& Core() { - return core; - } - - const android::BufferQueueCore& Core() const { - return core; - } - - bool IsVisible() const { - return visible; - } - - void SetVisibility(bool v) { - visible = v; - } - - bool IsOpen() const { - return open; - } - - bool Close() { - return std::exchange(open, false); - } - - bool Open() { - return !std::exchange(open, true); - } - - Nvnflinger::LayerBlending GetBlending() { - return blending; - } - - void SetBlending(Nvnflinger::LayerBlending b) { - blending = b; - } - -private: - const u64 layer_id; - const u32 binder_id; - android::BufferQueueCore& core; - android::BufferQueueProducer& binder; - std::shared_ptr<android::BufferItemConsumer> consumer; - Service::Nvnflinger::LayerBlending blending; - bool open; - bool visible; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/layer_list.h b/src/core/hle/service/vi/layer_list.h new file mode 100644 index 000000000..4afca6f40 --- /dev/null +++ b/src/core/hle/service/vi/layer_list.h @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/vi/layer.h" + +namespace Service::VI { + +class LayerList { +public: + constexpr LayerList() = default; + + Layer* CreateLayer(u64 owner_aruid, Display* display, s32 consumer_binder_id, + s32 producer_binder_id) { + Layer* const layer = GetFreeLayer(); + if (!layer) { + return nullptr; + } + + layer->Initialize(++m_next_id, owner_aruid, display, consumer_binder_id, + producer_binder_id); + return layer; + } + + bool DestroyLayer(u64 layer_id) { + Layer* const layer = GetLayerById(layer_id); + if (!layer) { + return false; + } + + layer->Finalize(); + return true; + } + + Layer* GetLayerById(u64 layer_id) { + for (auto& layer : m_layers) { + if (layer.IsInitialized() && layer.GetId() == layer_id) { + return &layer; + } + } + + return nullptr; + } + + template <typename F> + void ForEachLayer(F&& cb) { + for (auto& layer : m_layers) { + if (layer.IsInitialized()) { + cb(layer); + } + } + } + +private: + Layer* GetFreeLayer() { + for (auto& layer : m_layers) { + if (!layer.IsInitialized()) { + return &layer; + } + } + + return nullptr; + } + +private: + std::array<Layer, 8> m_layers{}; + u64 m_next_id{}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_display_service.cpp b/src/core/hle/service/vi/manager_display_service.cpp new file mode 100644 index 000000000..9f856282e --- /dev/null +++ b/src/core/hle/service/vi/manager_display_service.cpp @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/manager_display_service.h" + +namespace Service::VI { + +IManagerDisplayService::IManagerDisplayService(Core::System& system_, + std::shared_ptr<Container> container) + : ServiceFramework{system_, "IManagerDisplayService"}, m_container{std::move(container)} { + // clang-format off + static const FunctionInfo functions[] = { + {200, nullptr, "AllocateProcessHeapBlock"}, + {201, nullptr, "FreeProcessHeapBlock"}, + {1102, nullptr, "GetDisplayResolution"}, + {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, + {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"}, + {2012, nullptr, "CreateStrayLayer"}, + {2050, nullptr, "CreateIndirectLayer"}, + {2051, nullptr, "DestroyIndirectLayer"}, + {2052, nullptr, "CreateIndirectProducerEndPoint"}, + {2053, nullptr, "DestroyIndirectProducerEndPoint"}, + {2054, nullptr, "CreateIndirectConsumerEndPoint"}, + {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, + {2060, nullptr, "CreateWatermarkCompositor"}, + {2062, nullptr, "SetWatermarkText"}, + {2063, nullptr, "SetWatermarkLayerStacks"}, + {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, + {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, + {2302, nullptr, "GetDisplayHotplugEvent"}, + {2303, nullptr, "GetDisplayModeChangedEvent"}, + {2402, nullptr, "GetDisplayHotplugState"}, + {2501, nullptr, "GetCompositorErrorInfo"}, + {2601, nullptr, "GetDisplayErrorEvent"}, + {2701, nullptr, "GetDisplayFatalErrorEvent"}, + {4201, nullptr, "SetDisplayAlpha"}, + {4203, nullptr, "SetDisplayLayerStack"}, + {4205, nullptr, "SetDisplayPowerState"}, + {4206, nullptr, "SetDefaultDisplay"}, + {4207, nullptr, "ResetDisplayPanel"}, + {4208, nullptr, "SetDisplayFatalErrorEnabled"}, + {4209, nullptr, "IsDisplayPanelOn"}, + {4300, nullptr, "GetInternalPanelId"}, + {6000, C<&IManagerDisplayService::AddToLayerStack>, "AddToLayerStack"}, + {6001, nullptr, "RemoveFromLayerStack"}, + {6002, C<&IManagerDisplayService::SetLayerVisibility>, "SetLayerVisibility"}, + {6003, nullptr, "SetLayerConfig"}, + {6004, nullptr, "AttachLayerPresentationTracer"}, + {6005, nullptr, "DetachLayerPresentationTracer"}, + {6006, nullptr, "StartLayerPresentationRecording"}, + {6007, nullptr, "StopLayerPresentationRecording"}, + {6008, nullptr, "StartLayerPresentationFenceWait"}, + {6009, nullptr, "StopLayerPresentationFenceWait"}, + {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, + {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, + {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, + {6013, nullptr, "SetLayerOpacity"}, + {6014, nullptr, "AttachLayerWatermarkCompositor"}, + {6015, nullptr, "DetachLayerWatermarkCompositor"}, + {7000, nullptr, "SetContentVisibility"}, + {8000, nullptr, "SetConductorLayer"}, + {8001, nullptr, "SetTimestampTracking"}, + {8100, nullptr, "SetIndirectProducerFlipOffset"}, + {8200, nullptr, "CreateSharedBufferStaticStorage"}, + {8201, nullptr, "CreateSharedBufferTransferMemory"}, + {8202, nullptr, "DestroySharedBuffer"}, + {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, + {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, + {8207, nullptr, "UnbindSharedLowLevelLayer"}, + {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, + {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, + {8210, nullptr, "CreateSharedLayer"}, + {8211, nullptr, "DestroySharedLayer"}, + {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, + {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, + {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, + {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, + {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, + {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, + {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, + {8223, nullptr, "RegisterSharedBufferImporterAruid"}, + {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, + {8227, nullptr, "CreateSharedBufferProcessHeap"}, + {8228, nullptr, "GetSharedLayerLayerStacks"}, + {8229, nullptr, "SetSharedLayerLayerStacks"}, + {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, + {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, + {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, + {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, + {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, + {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, + {8297, nullptr, "GetSharedFrameBufferContentParameter"}, + {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IManagerDisplayService::~IManagerDisplayService() = default; + +Result IManagerDisplayService::CreateSharedLayerSession(Kernel::KProcess* owner_process, + u64* out_buffer_id, u64* out_layer_handle, + u64 display_id, bool enable_blending) { + R_RETURN(m_container->GetSharedBufferManager()->CreateSession( + owner_process, out_buffer_id, out_layer_handle, display_id, enable_blending)); +} + +void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) { + m_container->GetSharedBufferManager()->DestroySession(owner_process); +} + +Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) { + R_RETURN(m_container->SetLayerBlending(layer_id, enabled)); +} + +Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id, + AppletResourceUserId aruid) { + LOG_DEBUG(Service_VI, "called. flags={}, display={}, aruid={}", flags, display_id, aruid.pid); + R_RETURN(m_container->CreateManagedLayer(out_layer_id, display_id, aruid.pid)); +} + +Result IManagerDisplayService::DestroyManagedLayer(u64 layer_id) { + LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); + R_RETURN(m_container->DestroyManagedLayer(layer_id)); +} + +Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called. stack_id={}, layer_id={}", stack_id, layer_id); + R_SUCCEED(); +} + +Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { + LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); + R_RETURN(m_container->SetLayerVisibility(layer_id, visible)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_display_service.h b/src/core/hle/service/vi/manager_display_service.h new file mode 100644 index 000000000..b1bdf7f41 --- /dev/null +++ b/src/core/hle/service/vi/manager_display_service.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Kernel { +class KProcess; +} + +namespace Service::VI { + +class Container; + +class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { +public: + explicit IManagerDisplayService(Core::System& system_, std::shared_ptr<Container> container); + ~IManagerDisplayService() override; + + Result CreateSharedLayerSession(Kernel::KProcess* owner_process, u64* out_buffer_id, + u64* out_layer_handle, u64 display_id, bool enable_blending); + void DestroySharedLayerSession(Kernel::KProcess* owner_process); + + Result SetLayerBlending(bool enabled, u64 layer_id); + +public: + Result CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id, + AppletResourceUserId aruid); + Result DestroyManagedLayer(u64 layer_id); + Result AddToLayerStack(u32 stack_id, u64 layer_id); + Result SetLayerVisibility(bool visible, u64 layer_id); + +private: + const std::shared_ptr<Container> m_container; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp new file mode 100644 index 000000000..0f16a15b4 --- /dev/null +++ b/src/core/hle/service/vi/manager_root_service.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/nvnflinger/hos_binder_driver.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/manager_root_service.h" +#include "core/hle/service/vi/service_creator.h" +#include "core/hle/service/vi/vi.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +IManagerRootService::IManagerRootService(Core::System& system_, + std::shared_ptr<Container> container) + : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} { + static const FunctionInfo functions[] = { + {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, + {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, + {100, nullptr, "PrepareFatal"}, + {101, nullptr, "ShowFatal"}, + {102, nullptr, "DrawFatalRectangle"}, + {103, nullptr, "DrawFatalText32"}, + }; + RegisterHandlers(functions); +} + +IManagerRootService::~IManagerRootService() = default; + +Result IManagerRootService::GetDisplayService( + Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, + Permission::Manager, policy)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h new file mode 100644 index 000000000..77cd32869 --- /dev/null +++ b/src/core/hle/service/vi/manager_root_service.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::VI { + +class Container; +class IApplicationDisplayService; +enum class Policy : u32; + +class IManagerRootService final : public ServiceFramework<IManagerRootService> { +public: + explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container); + ~IManagerRootService() override; + + Result GetDisplayService( + Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, + Policy policy); + +private: + const std::shared_ptr<Container> m_container; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp new file mode 100644 index 000000000..2b8e5f957 --- /dev/null +++ b/src/core/hle/service/vi/service_creator.cpp @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/service_creator.h" +#include "core/hle/service/vi/vi_results.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +static bool IsValidServiceAccess(Permission permission, Policy policy) { + if (permission == Permission::User) { + return policy == Policy::User; + } + + if (permission == Permission::System || permission == Permission::Manager) { + return policy == Policy::User || policy == Policy::Compositor; + } + + return false; +} + +Result GetApplicationDisplayService( + std::shared_ptr<IApplicationDisplayService>* out_application_display_service, + Core::System& system, std::shared_ptr<Container> container, Permission permission, + Policy policy) { + + if (!IsValidServiceAccess(permission, policy)) { + LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); + R_THROW(ResultPermissionDenied); + } + + *out_application_display_service = + std::make_shared<IApplicationDisplayService>(system, std::move(container)); + R_SUCCEED(); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h new file mode 100644 index 000000000..c6ba1797d --- /dev/null +++ b/src/core/hle/service/vi/service_creator.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <memory> + +#include "common/common_types.h" + +namespace Core { +class System; +} + +union Result; + +namespace Service::VI { + +class Container; +class IApplicationDisplayService; +enum class Permission; +enum class Policy : u32; + +Result GetApplicationDisplayService( + std::shared_ptr<IApplicationDisplayService>* out_application_display_service, + Core::System& system, std::shared_ptr<Container> container, Permission permission, + Policy policy); + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/shared_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp new file mode 100644 index 000000000..12cba16fa --- /dev/null +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp @@ -0,0 +1,431 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <random> + +#include "core/core.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_system_resource.h" +#include "core/hle/service/nvdrv/devices/nvmap.h" +#include "core/hle/service/nvdrv/nvdrv.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/shared_buffer_manager.h" +#include "core/hle/service/vi/vi_results.h" +#include "video_core/gpu.h" +#include "video_core/host1x/host1x.h" + +namespace Service::VI { + +namespace { + +Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group, + Core::System& system, u32 size) { + using Core::Memory::YUZU_PAGESIZE; + + // Allocate memory for the system shared buffer. + auto& kernel = system.Kernel(); + + // Hold a temporary page group reference while we try to map it. + auto pg = std::make_unique<Kernel::KPageGroup>( + kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); + + // Allocate memory from secure pool. + R_TRY(kernel.MemoryManager().AllocateAndOpen( + pg.get(), size / YUZU_PAGESIZE, + Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure, + Kernel::KMemoryManager::Direction::FromBack))); + + // Fill the output data with red. + for (auto& block : *pg) { + u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress()); + u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize()); + + for (; start < end; start++) { + *start = 0xFF0000FF; + } + } + + // Return the mapped page group. + *out_page_group = std::move(pg); + + // We succeeded. + R_SUCCEED(); +} + +Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address, + std::unique_ptr<Kernel::KPageGroup>& pg, + Kernel::KProcess* process, Core::System& system) { + using Core::Memory::YUZU_PAGESIZE; + + auto& page_table = process->GetPageTable(); + + // Get bounds of where mapping is possible. + const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart()); + const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE; + const auto state = Kernel::KMemoryState::IoMemory; + const auto perm = Kernel::KMemoryPermission::UserReadWrite; + std::mt19937_64 rng{process->GetRandomEntropy(0)}; + + // Retry up to 64 times to map into alias code range. + Result res = ResultSuccess; + int i; + for (i = 0; i < 64; i++) { + *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE); + res = page_table.MapPageGroup(*out_map_address, *pg, state, perm); + if (R_SUCCEEDED(res)) { + break; + } + } + + // Return failure, if necessary + R_UNLESS(i < 64, res); + + // We succeeded. + R_SUCCEED(); +} + +Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { + // Create a handle. + Nvidia::Devices::nvmap::IocCreateParams create_params{ + .size = size, + .handle = 0, + }; + R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success, + VI::ResultOperationFailed); + + // Assign the output handle. + *out_nv_map_handle = create_params.handle; + + // We succeeded. + R_SUCCEED(); +} + +Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) { + // Free the handle. + Nvidia::Devices::nvmap::IocFreeParams free_params{ + .handle = handle, + }; + R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success, + VI::ResultOperationFailed); + + // We succeeded. + R_SUCCEED(); +} + +Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, + u32 size, Nvidia::DeviceFD nvmap_fd) { + // Assign the allocated memory to the handle. + Nvidia::Devices::nvmap::IocAllocParams alloc_params{ + .handle = handle, + .heap_mask = 0, + .flags = {}, + .align = 0, + .kind = 0, + .address = GetInteger(buffer), + }; + R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success, + VI::ResultOperationFailed); + + // We succeeded. + R_SUCCEED(); +} + +Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd, + Common::ProcessAddress buffer, u32 size) { + // Get the nvmap device. + auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); + ASSERT(nvmap != nullptr); + + // Create a handle. + R_TRY(CreateNvMapHandle(out_handle, *nvmap, size)); + + // Ensure we maintain a clean state on failure. + ON_RESULT_FAILURE { + R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd)); + }; + + // Assign the allocated memory to the handle. + R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd)); +} + +void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) { + auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); + ASSERT(nvmap != nullptr); + + R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd)); +} + +constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; +constexpr u32 SharedBufferBlockLinearBpp = 4; + +constexpr u32 SharedBufferBlockLinearWidth = 1280; +constexpr u32 SharedBufferBlockLinearHeight = 768; +constexpr u32 SharedBufferBlockLinearStride = + SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp; +constexpr u32 SharedBufferNumSlots = 7; + +constexpr u32 SharedBufferWidth = 1280; +constexpr u32 SharedBufferHeight = 720; +constexpr u32 SharedBufferAsync = false; + +constexpr u32 SharedBufferSlotSize = + SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp; +constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots; + +constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] { + SharedMemoryPoolLayout layout{}; + layout.num_slots = SharedBufferNumSlots; + + for (u32 i = 0; i < SharedBufferNumSlots; i++) { + layout.slots[i].buffer_offset = i * SharedBufferSlotSize; + layout.slots[i].size = SharedBufferSlotSize; + layout.slots[i].width = SharedBufferWidth; + layout.slots[i].height = SharedBufferHeight; + } + + return layout; +}(); + +void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { + auto buffer = std::make_shared<android::NvGraphicBuffer>(); + buffer->width = SharedBufferWidth; + buffer->height = SharedBufferHeight; + buffer->stride = SharedBufferBlockLinearStride; + buffer->format = SharedBufferBlockLinearFormat; + buffer->external_format = SharedBufferBlockLinearFormat; + buffer->buffer_id = handle; + buffer->offset = slot * SharedBufferSlotSize; + ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError); +} + +} // namespace + +SharedBufferManager::SharedBufferManager(Core::System& system, Container& container, + std::shared_ptr<Nvidia::Module> nvdrv) + : m_system(system), m_container(container), m_nvdrv(std::move(nvdrv)) {} + +SharedBufferManager::~SharedBufferManager() = default; + +Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, + u64* out_layer_handle, u64 display_id, + bool enable_blending) { + std::scoped_lock lk{m_guard}; + + // Ensure we haven't already created. + const u64 aruid = owner_process->GetProcessId(); + R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied); + + // Allocate memory for the shared buffer if needed. + if (!m_buffer_page_group) { + R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system, + SharedBufferSize)); + + // Record buffer id. + m_buffer_id = m_next_buffer_id++; + + // Record display id. + m_display_id = display_id; + } + + // Map into process. + Common::ProcessAddress map_address{}; + R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group, + owner_process, m_system)); + + // Create new session. + auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{}); + auto& session = it->second; + + auto& container = m_nvdrv->GetContainer(); + session.session_id = container.OpenSession(owner_process); + session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id); + + // Create an nvmap handle for the buffer and assign the memory to it. + R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv, + session.nvmap_fd, map_address, SharedBufferSize)); + + // Create and open a layer for the display. + s32 producer_binder_id; + R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id), + std::addressof(session.layer_id), display_id)); + + // Configure blending. + R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending)); + + // Get the producer and set preallocated buffers. + std::shared_ptr<android::BufferQueueProducer> producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id)); + MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle); + MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle); + + // Assign outputs. + *out_buffer_id = m_buffer_id; + *out_layer_handle = session.layer_id; + + // We succeeded. + R_SUCCEED(); +} + +void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) { + std::scoped_lock lk{m_guard}; + + if (m_buffer_id == 0) { + return; + } + + const u64 aruid = owner_process->GetProcessId(); + const auto it = m_sessions.find(aruid); + if (it == m_sessions.end()) { + return; + } + + auto& session = it->second; + + // Destroy the layer. + m_container.DestroyStrayLayer(session.layer_id); + + // Close nvmap handle. + FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); + + // Close nvmap device. + m_nvdrv->Close(session.nvmap_fd); + + // Close session. + auto& container = m_nvdrv->GetContainer(); + container.CloseSession(session.session_id); + + // Erase. + m_sessions.erase(it); +} + +Result SharedBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, + s32* out_nvmap_handle, + SharedMemoryPoolLayout* out_pool_layout, + u64 buffer_id, + u64 applet_resource_user_id) { + std::scoped_lock lk{m_guard}; + + R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); + R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound); + R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound); + + *out_pool_layout = SharedBufferPoolLayout; + *out_buffer_size = SharedBufferSize; + *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle; + + R_SUCCEED(); +} + +Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, + std::array<s32, 4>& out_slot_indexes, + s64* out_target_slot, u64 layer_id) { + // Get the producer. + std::shared_ptr<android::BufferQueueProducer> producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); + + // Get the next buffer from the producer. + s32 slot; + R_UNLESS(producer->DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, + SharedBufferWidth, SharedBufferHeight, + SharedBufferBlockLinearFormat, 0) == android::Status::NoError, + VI::ResultOperationFailed); + + // Assign remaining outputs. + *out_target_slot = slot; + out_slot_indexes = {0, 1, -1, -1}; + + // We succeeded. + R_SUCCEED(); +} + +Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, + Common::Rectangle<s32> crop_region, + u32 transform, s32 swap_interval, u64 layer_id, + s64 slot) { + // Get the producer. + std::shared_ptr<android::BufferQueueProducer> producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); + + // Request to queue the buffer. + std::shared_ptr<android::GraphicBuffer> buffer; + R_UNLESS(producer->RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == + android::Status::NoError, + VI::ResultOperationFailed); + + ON_RESULT_FAILURE { + producer->CancelBuffer(static_cast<s32>(slot), fence); + }; + + // Queue the buffer to the producer. + android::QueueBufferInput input{}; + android::QueueBufferOutput output{}; + input.crop = crop_region; + input.fence = fence; + input.transform = static_cast<android::NativeWindowTransform>(transform); + input.swap_interval = swap_interval; + R_UNLESS(producer->QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == + android::Status::NoError, + VI::ResultOperationFailed); + + // We succeeded. + R_SUCCEED(); +} + +Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { + // Get the producer. + std::shared_ptr<android::BufferQueueProducer> producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); + + // Cancel. + producer->CancelBuffer(static_cast<s32>(slot), android::Fence::NoFence()); + + // We succeeded. + R_SUCCEED(); +} + +Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, + u64 layer_id) { + // Get the producer. + std::shared_ptr<android::BufferQueueProducer> producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); + + // Set the event. + *out_event = producer->GetNativeHandle({}); + + // We succeeded. + R_SUCCEED(); +} + +Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { + std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer()); + Common::ScratchBuffer<u32> scratch; + + // TODO: this could be optimized + s64 e = -1280 * 768 * 4; + for (auto& block : *m_buffer_page_group) { + u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress()); + u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize()); + + for (; start < end; start++) { + *start = 0; + + if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) { + *start = capture_buffer[e]; + } + e++; + } + + m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) { + m_system.GPU().InvalidateRegion(addr, end - start); + }); + } + + *out_was_written = true; + *out_layer_index = 1; + R_SUCCEED(); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/shared_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h new file mode 100644 index 000000000..7c9bb7199 --- /dev/null +++ b/src/core/hle/service/vi/shared_buffer_manager.h @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <map> + +#include "common/math_util.h" +#include "core/hle/service/nvdrv/core/container.h" +#include "core/hle/service/nvdrv/nvdata.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/nvnflinger/ui/fence.h" + +namespace Kernel { +class KPageGroup; +class KReadableEvent; +} // namespace Kernel + +namespace Service::android { +class BufferQueueProducer; +} + +namespace Service::Nvidia { +class Module; +} + +union Result; + +namespace Service::VI { + +class Container; + +struct SharedMemorySlot { + u64 buffer_offset; + u64 size; + s32 width; + s32 height; +}; +static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size"); + +struct SharedMemoryPoolLayout { + s32 num_slots; + std::array<SharedMemorySlot, 0x10> slots; +}; +static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); + +struct SharedBufferSession; + +class SharedBufferManager final { +public: + explicit SharedBufferManager(Core::System& system, Container& container, + std::shared_ptr<Nvidia::Module> nvdrv); + ~SharedBufferManager(); + + Result CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, + u64 display_id, bool enable_blending); + void DestroySession(Kernel::KProcess* owner_process); + + Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, + SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, + u64 applet_resource_user_id); + Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots, + s64* out_target_slot, u64 layer_id); + Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, + u32 transform, s32 swap_interval, u64 layer_id, s64 slot); + Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); + Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); + + Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); + +private: + u64 m_next_buffer_id = 1; + u64 m_display_id = 0; + u64 m_buffer_id = 0; + SharedMemoryPoolLayout m_pool_layout = {}; + std::map<u64, SharedBufferSession> m_sessions; + std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; + + std::mutex m_guard; + Core::System& m_system; + Container& m_container; + const std::shared_ptr<Nvidia::Module> m_nvdrv; +}; + +struct SharedBufferSession { + Nvidia::DeviceFD nvmap_fd = {}; + Nvidia::NvCore::SessionId session_id = {}; + u64 layer_id = {}; + u32 buffer_nvmap_handle = 0; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp new file mode 100644 index 000000000..c3c50b07b --- /dev/null +++ b/src/core/hle/service/vi/system_display_service.cpp @@ -0,0 +1,169 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/system_display_service.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +ISystemDisplayService::ISystemDisplayService(Core::System& system_, + std::shared_ptr<Container> container) + : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} { + // clang-format off + static const FunctionInfo functions[] = { + {1200, nullptr, "GetZOrderCountMin"}, + {1202, nullptr, "GetZOrderCountMax"}, + {1203, nullptr, "GetDisplayLogicalResolution"}, + {1204, nullptr, "SetDisplayMagnification"}, + {2201, nullptr, "SetLayerPosition"}, + {2203, nullptr, "SetLayerSize"}, + {2204, nullptr, "GetLayerZ"}, + {2205, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"}, + {2207, C<&ISystemDisplayService::SetLayerVisibility>, "SetLayerVisibility"}, + {2209, nullptr, "SetLayerAlpha"}, + {2210, nullptr, "SetLayerPositionAndSize"}, + {2312, nullptr, "CreateStrayLayer"}, + {2400, nullptr, "OpenIndirectLayer"}, + {2401, nullptr, "CloseIndirectLayer"}, + {2402, nullptr, "FlipIndirectLayer"}, + {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"}, + {3001, nullptr, "ListDisplayRgbRanges"}, + {3002, nullptr, "ListDisplayContentTypes"}, + {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, + {3201, nullptr, "SetDisplayMode"}, + {3202, nullptr, "GetDisplayUnderscan"}, + {3203, nullptr, "SetDisplayUnderscan"}, + {3204, nullptr, "GetDisplayContentType"}, + {3205, nullptr, "SetDisplayContentType"}, + {3206, nullptr, "GetDisplayRgbRange"}, + {3207, nullptr, "SetDisplayRgbRange"}, + {3208, nullptr, "GetDisplayCmuMode"}, + {3209, nullptr, "SetDisplayCmuMode"}, + {3210, nullptr, "GetDisplayContrastRatio"}, + {3211, nullptr, "SetDisplayContrastRatio"}, + {3214, nullptr, "GetDisplayGamma"}, + {3215, nullptr, "SetDisplayGamma"}, + {3216, nullptr, "GetDisplayCmuLuma"}, + {3217, nullptr, "SetDisplayCmuLuma"}, + {3218, nullptr, "SetDisplayCrcMode"}, + {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, + {8225, C<&ISystemDisplayService::GetSharedBufferMemoryHandleId>, "GetSharedBufferMemoryHandleId"}, + {8250, C<&ISystemDisplayService::OpenSharedLayer>, "OpenSharedLayer"}, + {8251, nullptr, "CloseSharedLayer"}, + {8252, C<&ISystemDisplayService::ConnectSharedLayer>, "ConnectSharedLayer"}, + {8253, nullptr, "DisconnectSharedLayer"}, + {8254, C<&ISystemDisplayService::AcquireSharedFrameBuffer>, "AcquireSharedFrameBuffer"}, + {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, + {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, + {8257, nullptr, "FillSharedFrameBufferColor"}, + {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"}, + {9000, nullptr, "GetDp2hdmiController"}, + }; + // clang-format on + RegisterHandlers(functions); +} + +ISystemDisplayService::~ISystemDisplayService() = default; + +Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value); + R_SUCCEED(); +} + +// This function currently does nothing but return a success error code in +// the vi library itself, so do the same thing, but log out the passed in values. +Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { + LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); + R_SUCCEED(); +} + +Result ISystemDisplayService::ListDisplayModes( + Out<u64> out_count, u64 display_id, + OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes) { + LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id); + + if (!out_display_modes.empty()) { + out_display_modes[0] = { + .width = 1920, + .height = 1080, + .refresh_rate = 60.f, + .unknown = {}, + }; + *out_count = 1; + } else { + *out_count = 0; + } + + R_SUCCEED(); +} + +Result ISystemDisplayService::GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id) { + LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id); + + if (Settings::IsDockedMode()) { + out_display_mode->width = static_cast<u32>(DisplayResolution::DockedWidth); + out_display_mode->height = static_cast<u32>(DisplayResolution::DockedHeight); + } else { + out_display_mode->width = static_cast<u32>(DisplayResolution::UndockedWidth); + out_display_mode->height = static_cast<u32>(DisplayResolution::UndockedHeight); + } + + out_display_mode->refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. + out_display_mode->unknown = 0; + + R_SUCCEED(); +} + +Result ISystemDisplayService::GetSharedBufferMemoryHandleId( + Out<s32> out_nvmap_handle, Out<u64> out_size, + OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, u64 buffer_id, + ClientAppletResourceUserId aruid) { + LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); + + R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId( + out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); +} + +Result ISystemDisplayService::OpenSharedLayer(u64 layer_id) { + LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); + R_SUCCEED(); +} + +Result ISystemDisplayService::ConnectSharedLayer(u64 layer_id) { + LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); + R_SUCCEED(); +} + +Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_fence, + Out<std::array<s32, 4>> out_slots, + Out<s64> out_target_slot, u64 layer_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer( + out_fence, *out_slots, out_target_slot, layer_id)); +} + +Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, + Common::Rectangle<s32> crop_region, + u32 window_transform, s32 swap_interval, + u64 layer_id, s64 surface_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer( + fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); +} + +Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_container->GetSharedBufferManager()->GetSharedFrameBufferAcquirableEvent(out_event, + layer_id)); +} + +Result ISystemDisplayService::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_container->GetSharedBufferManager()->CancelSharedFrameBuffer(layer_id, slot)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/system_display_service.h b/src/core/hle/service/vi/system_display_service.h new file mode 100644 index 000000000..7228d826e --- /dev/null +++ b/src/core/hle/service/vi/system_display_service.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/math_util.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/nvnflinger/ui/fence.h" +#include "core/hle/service/service.h" +#include "core/hle/service/vi/shared_buffer_manager.h" + +namespace Service::VI { +struct DisplayMode; + +class Container; + +class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { +public: + explicit ISystemDisplayService(Core::System& system_, std::shared_ptr<Container> container); + ~ISystemDisplayService() override; + +private: + Result SetLayerZ(u32 z_value, u64 layer_id); + Result SetLayerVisibility(bool visible, u64 layer_id); + Result ListDisplayModes(Out<u64> out_count, u64 display_id, + OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes); + Result GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id); + + Result GetSharedBufferMemoryHandleId( + Out<s32> out_nvmap_handle, Out<u64> out_size, + OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, + u64 buffer_id, ClientAppletResourceUserId aruid); + Result OpenSharedLayer(u64 layer_id); + Result ConnectSharedLayer(u64 layer_id); + Result GetSharedFrameBufferAcquirableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event, + u64 layer_id); + Result AcquireSharedFrameBuffer(Out<android::Fence> out_fence, + Out<std::array<s32, 4>> out_slots, Out<s64> out_target_slot, + u64 layer_id); + Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, + u32 window_transform, s32 swap_interval, u64 layer_id, + s64 surface_id); + Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); + +private: + const std::shared_ptr<Container> m_container; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp new file mode 100644 index 000000000..3489727d8 --- /dev/null +++ b/src/core/hle/service/vi/system_root_service.cpp @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/service_creator.h" +#include "core/hle/service/vi/system_root_service.h" +#include "core/hle/service/vi/vi.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr<Container> container) + : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} { + static const FunctionInfo functions[] = { + {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, + {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, + }; + RegisterHandlers(functions); +} + +ISystemRootService::~ISystemRootService() = default; + +Result ISystemRootService::GetDisplayService( + Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, + Permission::System, policy)); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h new file mode 100644 index 000000000..9d5aa53d3 --- /dev/null +++ b/src/core/hle/service/vi/system_root_service.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::VI { + +class Container; +class IApplicationDisplayService; +enum class Policy : u32; + +class ISystemRootService final : public ServiceFramework<ISystemRootService> { +public: + explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container); + ~ISystemRootService() override; + +private: + Result GetDisplayService( + Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, + Policy policy); + + const std::shared_ptr<Container> m_container; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index d508ed28c..b388efaf6 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1,974 +1,30 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include <algorithm> -#include <array> -#include <cstring> -#include <memory> -#include <optional> -#include <type_traits> -#include <utility> - -#include "common/alignment.h" -#include "common/assert.h" -#include "common/common_funcs.h" -#include "common/logging/log.h" -#include "common/math_util.h" -#include "common/settings.h" -#include "common/string_util.h" -#include "common/swap.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nvdrv/devices/nvmap.h" -#include "core/hle/service/nvdrv/nvdata.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/binder.h" -#include "core/hle/service/nvnflinger/buffer_queue_producer.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/nvnflinger/parcel.h" +#include "core/core.h" #include "core/hle/service/server_manager.h" -#include "core/hle/service/service.h" +#include "core/hle/service/vi/application_root_service.h" +#include "core/hle/service/vi/container.h" +#include "core/hle/service/vi/manager_root_service.h" +#include "core/hle/service/vi/system_root_service.h" #include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_m.h" -#include "core/hle/service/vi/vi_results.h" -#include "core/hle/service/vi/vi_s.h" -#include "core/hle/service/vi/vi_u.h" namespace Service::VI { -struct DisplayInfo { - /// The name of this particular display. - char display_name[0x40]{"Default"}; - - /// Whether or not the display has a limited number of layers. - u8 has_limited_layers{1}; - INSERT_PADDING_BYTES(7); - - /// Indicates the total amount of layers supported by the display. - /// @note This is only valid if has_limited_layers is set. - u64 max_layers{1}; - - /// Maximum width in pixels. - u64 width{1920}; - - /// Maximum height in pixels. - u64 height{1080}; -}; -static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); - -class NativeWindow final { -public: - constexpr explicit NativeWindow(u32 id_) : id{id_} {} - constexpr explicit NativeWindow(const NativeWindow& other) = default; - -private: - const u32 magic = 2; - const u32 process_id = 1; - const u64 id; - INSERT_PADDING_WORDS(2); - std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; - INSERT_PADDING_WORDS(2); -}; -static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); - -class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { -public: - explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_) - : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { - static const FunctionInfo functions[] = { - {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, - {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, - {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, - {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, - }; - RegisterHandlers(functions); - } - -private: - void TransactParcel(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop<u32>(); - const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>()); - const u32 flags = rp.Pop<u32>(); - - LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, - transaction, flags); - - server.TryGetProducer(id)->Transact(ctx, transaction, flags); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void AdjustRefcount(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop<u32>(); - const s32 addval = rp.PopRaw<s32>(); - const u32 type = rp.Pop<u32>(); - - LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, - type); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetNativeHandle(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop<u32>(); - const u32 unknown = rp.Pop<u32>(); - - LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); - } - -private: - Nvnflinger::HosBinderDriverServer& server; -}; - -class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { -public: - explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { - // clang-format off - static const FunctionInfo functions[] = { - {1200, nullptr, "GetZOrderCountMin"}, - {1202, nullptr, "GetZOrderCountMax"}, - {1203, nullptr, "GetDisplayLogicalResolution"}, - {1204, nullptr, "SetDisplayMagnification"}, - {2201, nullptr, "SetLayerPosition"}, - {2203, nullptr, "SetLayerSize"}, - {2204, nullptr, "GetLayerZ"}, - {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, - {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, - {2209, nullptr, "SetLayerAlpha"}, - {2210, nullptr, "SetLayerPositionAndSize"}, - {2312, nullptr, "CreateStrayLayer"}, - {2400, nullptr, "OpenIndirectLayer"}, - {2401, nullptr, "CloseIndirectLayer"}, - {2402, nullptr, "FlipIndirectLayer"}, - {3000, nullptr, "ListDisplayModes"}, - {3001, nullptr, "ListDisplayRgbRanges"}, - {3002, nullptr, "ListDisplayContentTypes"}, - {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, - {3201, nullptr, "SetDisplayMode"}, - {3202, nullptr, "GetDisplayUnderscan"}, - {3203, nullptr, "SetDisplayUnderscan"}, - {3204, nullptr, "GetDisplayContentType"}, - {3205, nullptr, "SetDisplayContentType"}, - {3206, nullptr, "GetDisplayRgbRange"}, - {3207, nullptr, "SetDisplayRgbRange"}, - {3208, nullptr, "GetDisplayCmuMode"}, - {3209, nullptr, "SetDisplayCmuMode"}, - {3210, nullptr, "GetDisplayContrastRatio"}, - {3211, nullptr, "SetDisplayContrastRatio"}, - {3214, nullptr, "GetDisplayGamma"}, - {3215, nullptr, "SetDisplayGamma"}, - {3216, nullptr, "GetDisplayCmuLuma"}, - {3217, nullptr, "SetDisplayCmuLuma"}, - {3218, nullptr, "SetDisplayCrcMode"}, - {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, - {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, - {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, - {8251, nullptr, "CloseSharedLayer"}, - {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, - {8253, nullptr, "DisconnectSharedLayer"}, - {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, - {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, - {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, - {8257, nullptr, "FillSharedFrameBufferColor"}, - {8258, nullptr, "CancelSharedFrameBuffer"}, - {9000, nullptr, "GetDp2hdmiController"}, - }; - // clang-format on - RegisterHandlers(functions); - } - -private: - void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 buffer_id = rp.PopRaw<u64>(); - const u64 aruid = ctx.GetPID(); - - LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); - - struct OutputParameters { - s32 nvmap_handle; - u64 size; - }; - - OutputParameters out{}; - Nvnflinger::SharedMemoryPoolLayout layout{}; - const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( - &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); - - ctx.WriteBuffer(&layout, sizeof(layout)); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(result); - rb.PushRaw(out); - } - - void OpenSharedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw<u64>(); - - LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void ConnectSharedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw<u64>(); - - LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw<u64>(); - - Kernel::KReadableEvent* event{}; - const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( - &event, layer_id); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(result); - rb.PushCopyObjects(event); - } - - void AcquireSharedFrameBuffer(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw<u64>(); - - struct OutputParameters { - android::Fence fence; - std::array<s32, 4> slots; - s64 target_slot; - }; - static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); - - OutputParameters out{}; - const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( - &out.fence, out.slots, &out.target_slot, layer_id); - - IPC::ResponseBuilder rb{ctx, 18}; - rb.Push(result); - rb.PushRaw(out); - } - - void PresentSharedFrameBuffer(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - struct InputParameters { - android::Fence fence; - Common::Rectangle<s32> crop_region; - u32 window_transform; - s32 swap_interval; - u64 layer_id; - s64 surface_id; - }; - static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); - - IPC::RequestParser rp{ctx}; - auto input = rp.PopRaw<InputParameters>(); - - const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( - input.fence, input.crop_region, input.window_transform, input.swap_interval, - input.layer_id, input.surface_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - } - - void SetLayerZ(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop<u64>(); - const u64 z_value = rp.Pop<u64>(); - - LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, - z_value); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - // This function currently does nothing but return a success error code in - // the vi library itself, so do the same thing, but log out the passed in values. - void SetLayerVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop<u64>(); - const bool visibility = rp.Pop<bool>(); - - LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetDisplayMode(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - - if (Settings::IsDockedMode()) { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); - } else { - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); - rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); - } - - rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. - rb.Push<u32>(0); - } - -private: - Nvnflinger::Nvnflinger& nvnflinger; -}; - -class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { -public: - explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { - // clang-format off - static const FunctionInfo functions[] = { - {200, nullptr, "AllocateProcessHeapBlock"}, - {201, nullptr, "FreeProcessHeapBlock"}, - {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, - {1102, nullptr, "GetDisplayResolution"}, - {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, - {2011, nullptr, "DestroyManagedLayer"}, - {2012, nullptr, "CreateStrayLayer"}, - {2050, nullptr, "CreateIndirectLayer"}, - {2051, nullptr, "DestroyIndirectLayer"}, - {2052, nullptr, "CreateIndirectProducerEndPoint"}, - {2053, nullptr, "DestroyIndirectProducerEndPoint"}, - {2054, nullptr, "CreateIndirectConsumerEndPoint"}, - {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, - {2060, nullptr, "CreateWatermarkCompositor"}, - {2062, nullptr, "SetWatermarkText"}, - {2063, nullptr, "SetWatermarkLayerStacks"}, - {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, - {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, - {2302, nullptr, "GetDisplayHotplugEvent"}, - {2303, nullptr, "GetDisplayModeChangedEvent"}, - {2402, nullptr, "GetDisplayHotplugState"}, - {2501, nullptr, "GetCompositorErrorInfo"}, - {2601, nullptr, "GetDisplayErrorEvent"}, - {2701, nullptr, "GetDisplayFatalErrorEvent"}, - {4201, nullptr, "SetDisplayAlpha"}, - {4203, nullptr, "SetDisplayLayerStack"}, - {4205, nullptr, "SetDisplayPowerState"}, - {4206, nullptr, "SetDefaultDisplay"}, - {4207, nullptr, "ResetDisplayPanel"}, - {4208, nullptr, "SetDisplayFatalErrorEnabled"}, - {4209, nullptr, "IsDisplayPanelOn"}, - {4300, nullptr, "GetInternalPanelId"}, - {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, - {6001, nullptr, "RemoveFromLayerStack"}, - {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, - {6003, nullptr, "SetLayerConfig"}, - {6004, nullptr, "AttachLayerPresentationTracer"}, - {6005, nullptr, "DetachLayerPresentationTracer"}, - {6006, nullptr, "StartLayerPresentationRecording"}, - {6007, nullptr, "StopLayerPresentationRecording"}, - {6008, nullptr, "StartLayerPresentationFenceWait"}, - {6009, nullptr, "StopLayerPresentationFenceWait"}, - {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, - {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, - {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, - {6013, nullptr, "SetLayerOpacity"}, - {6014, nullptr, "AttachLayerWatermarkCompositor"}, - {6015, nullptr, "DetachLayerWatermarkCompositor"}, - {7000, nullptr, "SetContentVisibility"}, - {8000, nullptr, "SetConductorLayer"}, - {8001, nullptr, "SetTimestampTracking"}, - {8100, nullptr, "SetIndirectProducerFlipOffset"}, - {8200, nullptr, "CreateSharedBufferStaticStorage"}, - {8201, nullptr, "CreateSharedBufferTransferMemory"}, - {8202, nullptr, "DestroySharedBuffer"}, - {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, - {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, - {8207, nullptr, "UnbindSharedLowLevelLayer"}, - {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, - {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, - {8210, nullptr, "CreateSharedLayer"}, - {8211, nullptr, "DestroySharedLayer"}, - {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, - {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, - {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, - {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, - {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, - {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, - {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, - {8223, nullptr, "RegisterSharedBufferImporterAruid"}, - {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, - {8227, nullptr, "CreateSharedBufferProcessHeap"}, - {8228, nullptr, "GetSharedLayerLayerStacks"}, - {8229, nullptr, "SetSharedLayerLayerStacks"}, - {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, - {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, - {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, - {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, - {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, - {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, - {8297, nullptr, "GetSharedFrameBufferContentParameter"}, - {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void CloseDisplay(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display = rp.Pop<u64>(); - - const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - } - - void CreateManagedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 unknown = rp.Pop<u32>(); - rp.Skip(1, false); - const u64 display = rp.Pop<u64>(); - const u64 aruid = rp.Pop<u64>(); - - LOG_WARNING(Service_VI, - "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", - unknown, display, aruid); - - const auto layer_id = nvnflinger.CreateLayer(display); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(*layer_id); - } - - void AddToLayerStack(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 stack = rp.Pop<u32>(); - const u64 layer_id = rp.Pop<u64>(); - - LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, - layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void SetLayerVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop<u64>(); - const bool visibility = rp.Pop<bool>(); - - LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, - visibility); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - Nvnflinger::Nvnflinger& nvnflinger; -}; - -class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { -public: - IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, - hos_binder_driver_server{hos_binder_driver_server_} { - - static const FunctionInfo functions[] = { - {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, - {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, - {102, &IApplicationDisplayService::GetManagerDisplayService, - "GetManagerDisplayService"}, - {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, - "GetIndirectDisplayTransactionService"}, - {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, - {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, - {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, - {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, - {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, - {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, - {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, - {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, - {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, - {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, - {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, - {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, - {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, - "GetIndirectLayerImageMap"}, - {2451, nullptr, "GetIndirectLayerImageCropMap"}, - {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, - "GetIndirectLayerImageRequiredMemoryInfo"}, - {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, - {5203, nullptr, "GetDisplayVsyncEventForDebug"}, - }; - RegisterHandlers(functions); - } - - ~IApplicationDisplayService() { - for (const auto layer_id : stray_layer_ids) { - nvnflinger.DestroyLayer(layer_id); - } - } - -private: - enum class ConvertedScaleMode : u64 { - Freeze = 0, - ScaleToWindow = 1, - ScaleAndCrop = 2, - None = 3, - PreserveAspectRatio = 4, - }; - - enum class NintendoScaleMode : u32 { - None = 0, - Freeze = 1, - ScaleToWindow = 2, - ScaleAndCrop = 3, - PreserveAspectRatio = 4, - }; - - void GetRelayService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); - } - - void GetSystemDisplayService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger); - } - - void GetManagerDisplayService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger); - } - - void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); +void LoopProcess(Core::System& system, std::stop_token token) { + const auto container = std::make_shared<Container>(system); - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); - } - - void OpenDisplay(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::RequestParser rp{ctx}; - const auto name_buf = rp.PopRaw<std::array<char, 0x40>>(); - - OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); - } - - void OpenDefaultDisplay(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - OpenDisplayImpl(ctx, "Default"); - } - - void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { - const auto trim_pos = name.find('\0'); - - if (trim_pos != std::string_view::npos) { - name.remove_suffix(name.size() - trim_pos); - } - - ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); - - const auto display_id = nvnflinger.OpenDisplay(name); - if (!display_id) { - LOG_ERROR(Service_VI, "Display not found! display_name={}", name); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(*display_id); - } - - void CloseDisplay(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop<u64>(); - - const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - } - - // This literally does nothing internally in the actual service itself, - // and just returns a successful result code regardless of the input. - void SetDisplayEnabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetDisplayResolution(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop<u64>(); - - LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - - // This only returns the fixed values of 1280x720 and makes no distinguishing - // between docked and undocked dimensions. We take the liberty of applying - // the resolution scaling factor here. - rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth)); - rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); - } - - void SetLayerScalingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto scaling_mode = rp.PopEnum<NintendoScaleMode>(); - const u64 unknown = rp.Pop<u64>(); - - LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, - unknown); - - IPC::ResponseBuilder rb{ctx, 2}; - - if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { - LOG_ERROR(Service_VI, "Invalid scaling mode provided."); - rb.Push(ResultOperationFailed); - return; - } - - if (scaling_mode != NintendoScaleMode::ScaleToWindow && - scaling_mode != NintendoScaleMode::PreserveAspectRatio) { - LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); - rb.Push(ResultNotSupported); - return; - } - - rb.Push(ResultSuccess); - } - - void ListDisplays(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - const DisplayInfo display_info; - ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(1); - } - - void OpenLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); - const std::string display_name(Common::StringFromBuffer(name_buf)); - - const u64 layer_id = rp.Pop<u64>(); - const u64 aruid = rp.Pop<u64>(); - - LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); - - const auto display_id = nvnflinger.OpenDisplay(display_name); - if (!display_id) { - LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - if (!nvnflinger.OpenLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to open layer which was already open"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultOperationFailed); - return; - } - - android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); - - const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(buffer_size); - } - - void CloseLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto layer_id{rp.Pop<u64>()}; - - LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); - - if (!nvnflinger.CloseLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to close layer which was not open"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultOperationFailed); - return; - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void CreateStrayLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 flags = rp.Pop<u32>(); - rp.Pop<u32>(); // padding - const u64 display_id = rp.Pop<u64>(); - - LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); - - // TODO(Subv): What's the difference between a Stray and a Managed layer? - - const auto layer_id = nvnflinger.CreateLayer(display_id); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - stray_layer_ids.push_back(*layer_id); - const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); - - const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(*layer_id); - rb.Push<u64>(buffer_size); - } - - void DestroyStrayLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop<u64>(); - - LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); - nvnflinger.DestroyLayer(layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetDisplayVsyncEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop<u64>(); - - LOG_DEBUG(Service_VI, "called. display_id={}", display_id); - - Kernel::KReadableEvent* vsync_event{}; - const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); - if (result != ResultSuccess) { - if (result == ResultNotFound) { - LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; - } - if (vsync_event_fetched) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(VI::ResultPermissionDenied); - return; - } - vsync_event_fetched = true; - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(vsync_event); - } - - void ConvertScalingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto mode = rp.PopEnum<NintendoScaleMode>(); - LOG_DEBUG(Service_VI, "called mode={}", mode); - - ConvertedScaleMode converted_mode{}; - const auto result = ConvertScalingModeImpl(&converted_mode, mode); - - if (result == ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(converted_mode); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - } - } - - void GetIndirectLayerImageMap(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto width = rp.Pop<s64>(); - const auto height = rp.Pop<s64>(); - const auto indirect_layer_consumer_handle = rp.Pop<u64>(); - const auto applet_resource_user_id = rp.Pop<u64>(); - - LOG_WARNING(Service_VI, - "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " - "applet_resource_user_id={}", - width, height, indirect_layer_consumer_handle, applet_resource_user_id); - - std::vector<u8> out_buffer(0x46); - ctx.WriteBuffer(out_buffer); - - // TODO: Figure out what these are - - constexpr s64 unknown_result_1 = 0; - constexpr s64 unknown_result_2 = 0; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(unknown_result_1); - rb.Push(unknown_result_2); - rb.Push(ResultSuccess); - } - - void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto width = rp.Pop<u64>(); - const auto height = rp.Pop<u64>(); - LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); - - constexpr u64 base_size = 0x20000; - constexpr u64 alignment = 0x1000; - const auto texture_size = width * height * 4; - const auto out_size = (texture_size + base_size - 1) / base_size * base_size; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(out_size); - rb.Push(alignment); - } - - static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, - NintendoScaleMode mode) { - switch (mode) { - case NintendoScaleMode::None: - *out_scaling_mode = ConvertedScaleMode::None; - return ResultSuccess; - case NintendoScaleMode::Freeze: - *out_scaling_mode = ConvertedScaleMode::Freeze; - return ResultSuccess; - case NintendoScaleMode::ScaleToWindow: - *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; - return ResultSuccess; - case NintendoScaleMode::ScaleAndCrop: - *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; - return ResultSuccess; - case NintendoScaleMode::PreserveAspectRatio: - *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; - return ResultSuccess; - default: - LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); - return ResultOperationFailed; - } - } - - Nvnflinger::Nvnflinger& nvnflinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; - std::vector<u64> stray_layer_ids; - bool vsync_event_fetched{false}; -}; - -static bool IsValidServiceAccess(Permission permission, Policy policy) { - if (permission == Permission::User) { - return policy == Policy::User; - } - - if (permission == Permission::System || permission == Permission::Manager) { - return policy == Policy::User || policy == Policy::Compositor; - } - - return false; -} - -void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, - Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, - Permission permission) { - IPC::RequestParser rp{ctx}; - const auto policy = rp.PopEnum<Policy>(); - - if (!IsValidServiceAccess(permission, policy)) { - LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultPermissionDenied); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); -} - -void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { auto server_manager = std::make_unique<ServerManager>(system); + server_manager->RegisterNamedService("vi:m", + std::make_shared<IManagerRootService>(system, container)); + server_manager->RegisterNamedService("vi:s", + std::make_shared<ISystemRootService>(system, container)); server_manager->RegisterNamedService( - "vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server)); - server_manager->RegisterNamedService( - "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server)); - server_manager->RegisterNamedService( - "vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server)); + "vi:u", std::make_shared<IApplicationRootService>(system, container)); + + std::stop_callback cb(token, [=] { container->OnTerminate(); }); + ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index ee4bcbcfa..7c1f350d8 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -3,52 +3,14 @@ #pragma once -#include "common/common_types.h" +#include "common/polyfill_thread.h" namespace Core { class System; } -namespace Service { -class HLERequestContext; -} - -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - namespace Service::VI { -enum class DisplayResolution : u32 { - DockedWidth = 1920, - DockedHeight = 1080, - UndockedWidth = 1280, - UndockedHeight = 720, -}; - -/// Permission level for a particular VI service instance -enum class Permission { - User, - System, - Manager, -}; - -/// A policy type that may be requested via GetDisplayService and -/// GetDisplayServiceWithProxyNameExchange -enum class Policy { - User, - Compositor, -}; - -namespace detail { -void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, - Nvnflinger::Nvnflinger& nv_flinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, - Permission permission); -} // namespace detail - -void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); +void LoopProcess(Core::System& system, std::stop_token token); } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp deleted file mode 100644 index 0f06dc2f3..000000000 --- a/src/core/hle/service/vi/vi_m.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_m.h" - -namespace Service::VI { - -VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ - hos_binder_driver_server_} { - static const FunctionInfo functions[] = { - {2, &VI_M::GetDisplayService, "GetDisplayService"}, - {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, - {100, nullptr, "PrepareFatal"}, - {101, nullptr, "ShowFatal"}, - {102, nullptr, "DrawFatalRectangle"}, - {103, nullptr, "DrawFatalText32"}, - }; - RegisterHandlers(functions); -} - -VI_M::~VI_M() = default; - -void VI_M::GetDisplayService(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, - Permission::Manager); -} - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h deleted file mode 100644 index 9ca6f3905..000000000 --- a/src/core/hle/service/vi/vi_m.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - -namespace Service::VI { - -class VI_M final : public ServiceFramework<VI_M> { -public: - explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); - ~VI_M() override; - -private: - void GetDisplayService(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nv_flinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp deleted file mode 100644 index 77f7a88ff..000000000 --- a/src/core/hle/service/vi/vi_s.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_s.h" - -namespace Service::VI { - -VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ - hos_binder_driver_server_} { - static const FunctionInfo functions[] = { - {1, &VI_S::GetDisplayService, "GetDisplayService"}, - {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, - }; - RegisterHandlers(functions); -} - -VI_S::~VI_S() = default; - -void VI_S::GetDisplayService(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, - Permission::System); -} - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h deleted file mode 100644 index 157839c91..000000000 --- a/src/core/hle/service/vi/vi_s.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - -namespace Service::VI { - -class VI_S final : public ServiceFramework<VI_S> { -public: - explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); - ~VI_S() override; - -private: - void GetDisplayService(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nv_flinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h new file mode 100644 index 000000000..95ff66358 --- /dev/null +++ b/src/core/hle/service/vi/vi_types.h @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_funcs.h" + +namespace Service::VI { + +enum class DisplayResolution : u32 { + DockedWidth = 1920, + DockedHeight = 1080, + UndockedWidth = 1280, + UndockedHeight = 720, +}; + +/// Permission level for a particular VI service instance +enum class Permission { + User, + System, + Manager, +}; + +/// A policy type that may be requested via GetDisplayService and +/// GetDisplayServiceWithProxyNameExchange +enum class Policy : u32 { + User, + Compositor, +}; + +enum class ConvertedScaleMode : u64 { + Freeze = 0, + ScaleToWindow = 1, + ScaleAndCrop = 2, + None = 3, + PreserveAspectRatio = 4, +}; + +enum class NintendoScaleMode : u32 { + None = 0, + Freeze = 1, + ScaleToWindow = 2, + ScaleAndCrop = 3, + PreserveAspectRatio = 4, +}; + +using DisplayName = std::array<char, 0x40>; + +struct DisplayInfo { + /// The name of this particular display. + DisplayName display_name{"Default"}; + + /// Whether or not the display has a limited number of layers. + u8 has_limited_layers{1}; + INSERT_PADDING_BYTES(7); + + /// Indicates the total amount of layers supported by the display. + /// @note This is only valid if has_limited_layers is set. + u64 max_layers{1}; + + /// Maximum width in pixels. + u64 width{1920}; + + /// Maximum height in pixels. + u64 height{1080}; +}; +static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); + +struct DisplayMode { + u32 width; + u32 height; + f32 refresh_rate; + u32 unknown; +}; +static_assert(sizeof(DisplayMode) == 0x10, "DisplayMode has wrong size"); + +class NativeWindow final { +public: + constexpr explicit NativeWindow(s32 id_) : id{static_cast<u64>(id_)} {} + constexpr explicit NativeWindow(const NativeWindow& other) = default; + +private: + const u32 magic = 2; + const u32 process_id = 1; + const u64 id; + INSERT_PADDING_WORDS(2); + std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; + INSERT_PADDING_WORDS(2); +}; +static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp deleted file mode 100644 index 59e13c86b..000000000 --- a/src/core/hle/service/vi/vi_u.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_u.h" - -namespace Service::VI { - -VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ - hos_binder_driver_server_} { - static const FunctionInfo functions[] = { - {0, &VI_U::GetDisplayService, "GetDisplayService"}, - {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, - }; - RegisterHandlers(functions); -} - -VI_U::~VI_U() = default; - -void VI_U::GetDisplayService(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, - Permission::User); -} - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h deleted file mode 100644 index 5d9ca54c6..000000000 --- a/src/core/hle/service/vi/vi_u.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - -namespace Service::VI { - -class VI_U final : public ServiceFramework<VI_U> { -public: - explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); - ~VI_U() override; - -private: - void GetDisplayService(HLERequestContext& ctx); - - Nvnflinger::Nvnflinger& nv_flinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; -}; - -} // namespace Service::VI diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp new file mode 100644 index 000000000..bdc4dfa96 --- /dev/null +++ b/src/core/hle/service/vi/vsync_manager.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/os/event.h" +#include "core/hle/service/vi/vsync_manager.h" + +namespace Service::VI { + +VsyncManager::VsyncManager() = default; +VsyncManager::~VsyncManager() = default; + +void VsyncManager::SignalVsync() { + for (auto* event : m_vsync_events) { + event->Signal(); + } +} + +void VsyncManager::LinkVsyncEvent(Event* event) { + m_vsync_events.insert(event); +} + +void VsyncManager::UnlinkVsyncEvent(Event* event) { + m_vsync_events.erase(event); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h new file mode 100644 index 000000000..5d45bb5ee --- /dev/null +++ b/src/core/hle/service/vi/vsync_manager.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <set> + +namespace Service { +class Event; +} + +namespace Service::VI { + +class DisplayList; + +class VsyncManager { +public: + explicit VsyncManager(); + ~VsyncManager(); + + void SignalVsync(); + void LinkVsyncEvent(Event* event); + void UnlinkVsyncEvent(Event* event); + +private: + std::set<Event*> m_vsync_events; +}; + +} // namespace Service::VI |