diff --git a/README.md b/README.md index 1f0e7d980..3104ceb70 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4144. +This is the source code for early-access 4145. ## Legal Notice diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2701b481d..560583980 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -423,12 +423,12 @@ add_library(core STATIC hle/service/am/applet_manager.h hle/service/am/applet_message_queue.cpp hle/service/am/applet_message_queue.h + hle/service/am/display_layer_manager.cpp + hle/service/am/display_layer_manager.h hle/service/am/hid_registration.cpp hle/service/am/hid_registration.h hle/service/am/library_applet_storage.cpp hle/service/am/library_applet_storage.h - hle/service/am/managed_layer_holder.cpp - hle/service/am/managed_layer_holder.h hle/service/am/process.cpp hle/service/am/process.h hle/service/am/service/all_system_applet_proxies_service.cpp @@ -481,8 +481,6 @@ add_library(core STATIC hle/service/am/service/system_applet_proxy.h hle/service/am/service/window_controller.cpp hle/service/am/service/window_controller.h - hle/service/am/system_buffer_manager.cpp - hle/service/am/system_buffer_manager.h hle/service/aoc/aoc_u.cpp hle/service/aoc/aoc_u.h hle/service/apm/apm.cpp @@ -491,12 +489,12 @@ add_library(core STATIC hle/service/apm/apm_controller.h hle/service/apm/apm_interface.cpp hle/service/apm/apm_interface.h - hle/service/audio/audctl.cpp - hle/service/audio/audctl.h hle/service/audio/audin_u.cpp hle/service/audio/audin_u.h hle/service/audio/audio.cpp hle/service/audio/audio.h + hle/service/audio/audio_controller.cpp + hle/service/audio/audio_controller.h hle/service/audio/audout_u.cpp hle/service/audio/audout_u.h hle/service/audio/audrec_a.cpp @@ -739,15 +737,48 @@ add_library(core STATIC hle/service/nim/nim.h hle/service/npns/npns.cpp hle/service/npns/npns.h - hle/service/ns/errors.h - hle/service/ns/iplatform_service_manager.cpp - hle/service/ns/iplatform_service_manager.h + hle/service/ns/account_proxy_interface.cpp + hle/service/ns/account_proxy_interface.h + hle/service/ns/application_manager_interface.cpp + hle/service/ns/application_manager_interface.h + hle/service/ns/application_version_interface.cpp + hle/service/ns/application_version_interface.h + hle/service/ns/content_management_interface.cpp + hle/service/ns/content_management_interface.h + hle/service/ns/develop_interface.cpp + hle/service/ns/develop_interface.h + hle/service/ns/document_interface.cpp + hle/service/ns/document_interface.h + hle/service/ns/download_task_interface.cpp + hle/service/ns/download_task_interface.h + hle/service/ns/dynamic_rights_interface.cpp + hle/service/ns/dynamic_rights_interface.h + hle/service/ns/ecommerce_interface.cpp + hle/service/ns/ecommerce_interface.h + hle/service/ns/factory_reset_interface.cpp + hle/service/ns/factory_reset_interface.h hle/service/ns/language.cpp hle/service/ns/language.h + hle/service/ns/ns_results.h + hle/service/ns/ns_types.h hle/service/ns/ns.cpp hle/service/ns/ns.h - hle/service/ns/pdm_qry.cpp - hle/service/ns/pdm_qry.h + hle/service/ns/platform_service_manager.cpp + hle/service/ns/platform_service_manager.h + hle/service/ns/query_service.cpp + hle/service/ns/query_service.h + hle/service/ns/read_only_application_control_data_interface.cpp + hle/service/ns/read_only_application_control_data_interface.h + hle/service/ns/read_only_application_record_interface.cpp + hle/service/ns/read_only_application_record_interface.h + hle/service/ns/service_getter_interface.cpp + hle/service/ns/service_getter_interface.h + hle/service/ns/system_update_control.cpp + hle/service/ns/system_update_control.h + hle/service/ns/system_update_interface.cpp + hle/service/ns/system_update_interface.h + hle/service/ns/vulnerability_manager_interface.cpp + hle/service/ns/vulnerability_manager_interface.h hle/service/nvdrv/core/container.cpp hle/service/nvdrv/core/container.h hle/service/nvdrv/core/heap_mapper.cpp @@ -800,12 +831,12 @@ add_library(core STATIC hle/service/nvnflinger/consumer_base.cpp hle/service/nvnflinger/consumer_base.h hle/service/nvnflinger/consumer_listener.h - hle/service/nvnflinger/fb_share_buffer_manager.cpp - hle/service/nvnflinger/fb_share_buffer_manager.h hle/service/nvnflinger/graphic_buffer_producer.cpp hle/service/nvnflinger/graphic_buffer_producer.h hle/service/nvnflinger/hos_binder_driver_server.cpp hle/service/nvnflinger/hos_binder_driver_server.h + hle/service/nvnflinger/hos_binder_driver.cpp + hle/service/nvnflinger/hos_binder_driver.h hle/service/nvnflinger/hardware_composer.cpp hle/service/nvnflinger/hardware_composer.h hle/service/nvnflinger/hwc_layer.h @@ -815,6 +846,8 @@ add_library(core STATIC hle/service/nvnflinger/pixel_format.h hle/service/nvnflinger/producer_listener.h hle/service/nvnflinger/status.h + hle/service/nvnflinger/surface_flinger.cpp + hle/service/nvnflinger/surface_flinger.h hle/service/nvnflinger/ui/fence.h hle/service/nvnflinger/ui/graphic_buffer.cpp hle/service/nvnflinger/ui/graphic_buffer.h @@ -908,6 +941,8 @@ add_library(core STATIC hle/service/server_manager.h hle/service/service.cpp hle/service/service.h + hle/service/services.cpp + hle/service/services.h hle/service/set/setting_formats/appln_settings.cpp hle/service/set/setting_formats/appln_settings.h hle/service/set/setting_formats/device_settings.cpp @@ -955,22 +990,26 @@ add_library(core STATIC hle/service/ssl/ssl_backend.h hle/service/usb/usb.cpp hle/service/usb/usb.h - hle/service/vi/display/vi_display.cpp - hle/service/vi/display/vi_display.h - hle/service/vi/layer/vi_layer.cpp - hle/service/vi/layer/vi_layer.h hle/service/vi/application_display_service.cpp hle/service/vi/application_display_service.h hle/service/vi/application_root_service.cpp hle/service/vi/application_root_service.h - hle/service/vi/hos_binder_driver.cpp - hle/service/vi/hos_binder_driver.h + hle/service/vi/conductor.cpp + hle/service/vi/conductor.h + hle/service/vi/container.cpp + hle/service/vi/container.h + hle/service/vi/display_list.h + hle/service/vi/display.h + hle/service/vi/layer_list.h + hle/service/vi/layer.h hle/service/vi/manager_display_service.cpp hle/service/vi/manager_display_service.h hle/service/vi/manager_root_service.cpp hle/service/vi/manager_root_service.h hle/service/vi/service_creator.cpp hle/service/vi/service_creator.h + hle/service/vi/shared_buffer_manager.cpp + hle/service/vi/shared_buffer_manager.h hle/service/vi/system_display_service.cpp hle/service/vi/system_display_service.h hle/service/vi/system_root_service.cpp @@ -979,6 +1018,8 @@ add_library(core STATIC hle/service/vi/vi_types.h hle/service/vi/vi.cpp hle/service/vi/vi.h + hle/service/vi/vsync_manager.cpp + hle/service/vi/vsync_manager.h internal_network/network.cpp internal_network/network.h internal_network/network_interface.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index 46a7941de..56f5dd67d 100755 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -47,6 +47,7 @@ #include "core/hle/service/psc/time/system_clock.h" #include "core/hle/service/psc/time/time_zone_service.h" #include "core/hle/service/service.h" +#include "core/hle/service/services.h" #include "core/hle/service/set/system_settings_server.h" #include "core/hle/service/sm/sm.h" #include "core/internal_network/network.h" @@ -310,7 +311,8 @@ struct System::Impl { audio_core = std::make_unique(system); service_manager = std::make_shared(kernel); - services = std::make_unique(service_manager, system); + services = + std::make_unique(service_manager, system, stop_event.get_token()); is_powered_on = true; exit_locked = false; @@ -458,11 +460,10 @@ struct System::Impl { gpu_core->NotifyShutdown(); } + stop_event.request_stop(); + core_timing.SyncPause(false); Network::CancelPendingSocketOperations(); kernel.SuspendEmulation(true); - if (services) { - services->KillNVNFlinger(); - } kernel.CloseServices(); kernel.ShutdownCores(); applet_manager.Reset(); @@ -480,6 +481,7 @@ struct System::Impl { cpu_manager.Shutdown(); debugger.reset(); kernel.Shutdown(); + stop_event = {}; Network::RestartSocketOperations(); if (auto room_member = room_network.GetRoomMember().lock()) { @@ -615,6 +617,7 @@ struct System::Impl { ExecuteProgramCallback execute_program_callback; ExitCallback exit_callback; + std::stop_source stop_event; std::array dynarmic_ticks{}; std::array microprofile_cpu{}; diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp index e378adcb3..ba8057c7d 100755 --- a/src/core/file_sys/system_archive/shared_font.cpp +++ b/src/core/file_sys/system_archive/shared_font.cpp @@ -9,7 +9,7 @@ #include "core/file_sys/system_archive/data/font_standard.h" #include "core/file_sys/system_archive/shared_font.h" #include "core/file_sys/vfs/vfs_vector.h" -#include "core/hle/service/ns/iplatform_service_manager.h" +#include "core/hle/service/ns/platform_service_manager.h" namespace FileSys::SystemArchive { diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index e22a698c8..4b5383bb4 100755 --- 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 1575b505d..df2e7abd7 100755 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -8,13 +8,13 @@ namespace Service::AM { -void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { +void LoopProcess(Core::System& system) { auto server_manager = std::make_unique(system); - server_manager->RegisterNamedService( - "appletAE", std::make_shared(system, nvnflinger)); - server_manager->RegisterNamedService( - "appletOE", std::make_shared(system, nvnflinger)); + server_manager->RegisterNamedService("appletAE", + std::make_shared(system)); + server_manager->RegisterNamedService("appletOE", + std::make_shared(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 28ee4c079..f50b358af 100755 --- 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/applet.h b/src/core/hle/service/am/applet.h index 4f34d4811..ad602153e 100755 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h @@ -14,10 +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/system_buffer_manager.h" namespace Service::AM { @@ -54,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{}; diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index 4c7266f89..2e109181d 100755 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -35,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 argument_data(sizeof(arguments)); + std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); + channel.Push(std::make_shared(system, std::move(argument_data))); +} + void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { const CommonArguments arguments{ .arguments_version = CommonArgumentVersion::Version3, @@ -284,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; 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 100755 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: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 100755 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 + +#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 m_display_service{}; + std::shared_ptr m_manager_display_service{}; + std::set m_managed_display_layers{}; + std::set 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_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp index bb60260b4..835c20c4e 100755 --- a/src/core/hle/service/am/frontend/applet_web_browser.cpp +++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp @@ -22,7 +22,7 @@ #include "core/hle/service/am/frontend/applet_web_browser.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/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp index eebd90ba2..21747783a 100755 --- 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 @@ -10,9 +10,8 @@ namespace Service::AM { -IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_, - Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} { +IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_) + : ServiceFramework{system_, "appletAE"} { // clang-format off static const FunctionInfo functions[] = { {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, @@ -37,8 +36,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy( LOG_DEBUG(Service_AM, "called"); if (const auto applet = this->GetAppletFromProcessId(pid); applet) { - *out_system_applet_proxy = std::make_shared( - system, applet, process_handle.Get(), m_nvnflinger); + *out_system_applet_proxy = + std::make_shared(system, applet, process_handle.Get()); R_SUCCEED(); } else { UNIMPLEMENTED(); @@ -53,8 +52,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy( LOG_DEBUG(Service_AM, "called"); if (const auto applet = this->GetAppletFromProcessId(pid); applet) { - *out_library_applet_proxy = std::make_shared( - system, applet, process_handle.Get(), m_nvnflinger); + *out_library_applet_proxy = + std::make_shared(system, applet, process_handle.Get()); R_SUCCEED(); } else { UNIMPLEMENTED(); 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 index 38b1ca2ea..0e2dcb86d 100755 --- 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 @@ -8,10 +8,6 @@ namespace Service { -namespace Nvnflinger { -class Nvnflinger; -} - namespace AM { struct Applet; @@ -22,8 +18,7 @@ class ISystemAppletProxy; class IAllSystemAppletProxiesService final : public ServiceFramework { public: - explicit IAllSystemAppletProxiesService(Core::System& system_, - Nvnflinger::Nvnflinger& nvnflinger); + explicit IAllSystemAppletProxiesService(Core::System& system_); ~IAllSystemAppletProxiesService() override; private: @@ -40,7 +35,6 @@ private: private: std::shared_ptr GetAppletFromProcessId(ProcessId pid); - Nvnflinger::Nvnflinger& m_nvnflinger; }; } // namespace AM diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp index b788fddd4..07a7152fe 100755 --- a/src/core/hle/service/am/service/application_functions.cpp +++ b/src/core/hle/service/am/service/application_functions.cpp @@ -15,7 +15,8 @@ #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/ns/ns.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 { @@ -162,11 +163,13 @@ Result IApplicationFunctions::GetDesiredLanguage(Out out_language_code) { // Call IApplicationManagerInterface implementation. auto& service_manager = system.ServiceManager(); - auto ns_am2 = service_manager.GetService("ns:am2"); - auto app_man = ns_am2->GetApplicationManagerInterface(); + auto ns_am2 = service_manager.GetService("ns:am2"); + + std::shared_ptr app_man; + R_TRY(ns_am2->GetApplicationManagerInterface(&app_man)); // Get desired application language - u8 desired_language{}; + NS::ApplicationLanguage desired_language{}; R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages)); // Convert to settings language code. diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp index 776f4552b..19d6a3b89 100755 --- a/src/core/hle/service/am/service/application_proxy.cpp +++ b/src/core/hle/service/am/service/application_proxy.cpp @@ -17,9 +17,9 @@ namespace Service::AM { IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "IApplicationProxy"}, - m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(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"}, @@ -77,8 +77,7 @@ Result IApplicationProxy::GetWindowController( Result IApplicationProxy::GetSelfController( Out> out_self_controller) { LOG_DEBUG(Service_AM, "called"); - *out_self_controller = - std::make_shared(system, m_applet, m_process, m_nvnflinger); + *out_self_controller = std::make_shared(system, m_applet, m_process); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h index 1ebc593ba..6da350df7 100755 --- a/src/core/hle/service/am/service/application_proxy.h +++ b/src/core/hle/service/am/service/application_proxy.h @@ -22,7 +22,7 @@ class IWindowController; class IApplicationProxy final : public ServiceFramework { public: explicit IApplicationProxy(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); + Kernel::KProcess* process); ~IApplicationProxy(); private: @@ -40,7 +40,6 @@ private: Out> out_application_functions); private: - Nvnflinger::Nvnflinger& m_nvnflinger; Kernel::KProcess* const m_process; const std::shared_ptr m_applet; }; diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp index 36d4478df..fd66e77b9 100755 --- a/src/core/hle/service/am/service/application_proxy_service.cpp +++ b/src/core/hle/service/am/service/application_proxy_service.cpp @@ -10,9 +10,8 @@ namespace Service::AM { -IApplicationProxyService::IApplicationProxyService(Core::System& system_, - Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} { +IApplicationProxyService::IApplicationProxyService(Core::System& system_) + : ServiceFramework{system_, "appletOE"} { static const FunctionInfo functions[] = { {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"}, }; @@ -28,7 +27,7 @@ Result IApplicationProxyService::OpenApplicationProxy( if (const auto applet = this->GetAppletFromProcessId(pid)) { *out_application_proxy = - std::make_shared(system, applet, process_handle.Get(), m_nvnflinger); + std::make_shared(system, applet, process_handle.Get()); R_SUCCEED(); } else { UNIMPLEMENTED(); diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h index 1c1d32d0b..8efafa31a 100755 --- a/src/core/hle/service/am/service/application_proxy_service.h +++ b/src/core/hle/service/am/service/application_proxy_service.h @@ -8,10 +8,6 @@ namespace Service { -namespace Nvnflinger { -class Nvnflinger; -} - namespace AM { struct Applet; @@ -19,7 +15,7 @@ class IApplicationProxy; class IApplicationProxyService final : public ServiceFramework { public: - explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); + explicit IApplicationProxyService(Core::System& system_); ~IApplicationProxyService() override; private: @@ -28,7 +24,6 @@ private: private: std::shared_ptr GetAppletFromProcessId(ProcessId pid); - Nvnflinger::Nvnflinger& m_nvnflinger; }; } // namespace AM diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp index 249c73dfb..ed71f9093 100755 --- a/src/core/hle/service/am/service/display_controller.cpp +++ b/src/core/hle/service/am/service/display_controller.cpp @@ -69,7 +69,7 @@ Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_i Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( Out out_was_written, Out out_fbshare_layer_index) { LOG_WARNING(Service_AM, "(STUBBED) called"); - R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, out_fbshare_layer_index)); } @@ -81,7 +81,7 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() { Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( Out out_was_written, Out out_fbshare_layer_index) { LOG_WARNING(Service_AM, "(STUBBED) called"); - R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, out_fbshare_layer_index)); } @@ -93,7 +93,7 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() { Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( Out out_was_written, Out out_fbshare_layer_index) { LOG_WARNING(Service_AM, "(STUBBED) called"); - R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, out_fbshare_layer_index)); } diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 166637d60..c97358d81 100755 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -135,7 +135,7 @@ std::shared_ptr CreateGuestApplet(Core::System& system, case LibraryAppletMode::AllForegroundInitiallyHidden: applet->hid_registration.EnableAppletToGetInput(false); applet->focus_state = FocusState::NotInFocus; - applet->system_buffer_manager.SetWindowVisibility(false); + applet->display_layer_manager.SetWindowVisibility(false); applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground); break; } diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp index bcb44a71c..58e709347 100755 --- a/src/core/hle/service/am/service/library_applet_proxy.cpp +++ b/src/core/hle/service/am/service/library_applet_proxy.cpp @@ -19,10 +19,9 @@ namespace Service::AM { ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, - Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "ILibraryAppletProxy"}, - m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(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"}, @@ -83,8 +82,7 @@ Result ILibraryAppletProxy::GetWindowController( Result ILibraryAppletProxy::GetSelfController( Out> out_self_controller) { LOG_DEBUG(Service_AM, "called"); - *out_self_controller = - std::make_shared(system, m_applet, m_process, m_nvnflinger); + *out_self_controller = std::make_shared(system, m_applet, m_process); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h index 23e64e295..7d0714b85 100755 --- a/src/core/hle/service/am/service/library_applet_proxy.h +++ b/src/core/hle/service/am/service/library_applet_proxy.h @@ -25,7 +25,7 @@ class IWindowController; class ILibraryAppletProxy final : public ServiceFramework { public: explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); + Kernel::KProcess* process); ~ILibraryAppletProxy(); private: @@ -47,7 +47,6 @@ private: Result GetGlobalStateController( Out> out_global_state_controller); - Nvnflinger::Nvnflinger& m_nvnflinger; Kernel::KProcess* const m_process; const std::shared_ptr m_applet; }; 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 index 7a3a86e88..330eb26f0 100755 --- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -14,7 +14,8 @@ #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/ns.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 { @@ -256,11 +257,13 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage( // Call IApplicationManagerInterface implementation. auto& service_manager = system.ServiceManager(); - auto ns_am2 = service_manager.GetService("ns:am2"); - auto app_man = ns_am2->GetApplicationManagerInterface(); + auto ns_am2 = service_manager.GetService("ns:am2"); + + std::shared_ptr app_man; + R_TRY(ns_am2->GetApplicationManagerInterface(&app_man)); // Get desired application language - u8 desired_language{}; + NS::ApplicationLanguage desired_language{}; R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages)); // Convert to settings language code. @@ -284,17 +287,17 @@ Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out out_applicat } Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers( - Out out_no_users_available, Out out_users_count, + Out out_can_select_any_user, Out out_users_count, OutArray out_users) { const Service::Account::ProfileManager manager{}; - *out_no_users_available = true; + *out_can_select_any_user = false; *out_users_count = -1; LOG_INFO(Service_AM, "called"); if (manager.GetUserCount() > 0) { - *out_no_users_available = false; + *out_can_select_any_user = true; *out_users_count = static_cast(manager.GetUserCount()); const auto users = manager.GetAllUsers(); 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 index a9743569f..3e60393c2 100755 --- a/src/core/hle/service/am/service/library_applet_self_accessor.h +++ b/src/core/hle/service/am/service/library_applet_self_accessor.h @@ -71,7 +71,7 @@ private: ErrorCode error_code, InLargeData error_context); Result GetMainAppletApplicationDesiredLanguage(Out out_desired_language); Result GetCurrentApplicationId(Out out_application_id); - Result GetMainAppletAvailableUsers(Out out_no_users_available, Out out_users_count, + Result GetMainAppletAvailableUsers(Out out_can_select_any_user, Out out_users_count, OutArray out_users); Result ShouldSetGpuTimeSliceManually(Out out_should_set_gpu_time_slice_manually); Result Cmd160(Out out_unknown0); diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 5c4c13de1..06314407c 100755 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -15,9 +15,9 @@ namespace Service::AM { ISelfController::ISelfController(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "ISelfController"}, - m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(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"}, @@ -72,9 +72,16 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr // 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() = default; +ISelfController::~ISelfController() { + std::scoped_lock lk{m_applet->lock}; + m_applet->display_layer_manager.Finalize(); +} Result ISelfController::Exit() { LOG_DEBUG(Service_AM, "called"); @@ -212,48 +219,42 @@ Result ISelfController::SetAlbumImageOrientation( Result ISelfController::IsSystemBufferSharingEnabled() { LOG_INFO(Service_AM, "called"); - R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize( - &m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode)); - R_THROW(VI::ResultOperationFailed); + + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled()); } Result ISelfController::GetSystemSharedBufferHandle(Out out_buffer_id) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - - R_TRY(this->IsSystemBufferSharingEnabled()); + LOG_INFO(Service_AM, "called"); u64 layer_id; - m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id); - R_SUCCEED(); + + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id)); } Result ISelfController::GetSystemSharedLayerHandle(Out out_buffer_id, Out out_layer_id) { - LOG_INFO(Service_AM, "(STUBBED) called"); + LOG_INFO(Service_AM, "called"); - R_TRY(this->IsSystemBufferSharingEnabled()); - - m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id); - R_SUCCEED(); + 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 out_layer_id) { LOG_INFO(Service_AM, "called"); - m_applet->managed_layer_holder.Initialize(&m_nvnflinger); - m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id); - - R_SUCCEED(); + std::scoped_lock lk{m_applet->lock}; + R_RETURN(m_applet->display_layer_manager.CreateManagedDisplayLayer(out_layer_id)); } Result ISelfController::CreateManagedDisplaySeparableLayer(Out out_layer_id, Out out_recording_layer_id) { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->managed_layer_holder.Initialize(&m_nvnflinger); - m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id, - out_recording_layer_id); - - R_SUCCEED(); + 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) { diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h index 01fa381a3..eca083cfe 100755 --- a/src/core/hle/service/am/service/self_controller.h +++ b/src/core/hle/service/am/service/self_controller.h @@ -23,7 +23,7 @@ struct Applet; class ISelfController final : public ServiceFramework { public: explicit ISelfController(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); + Kernel::KProcess* process); ~ISelfController() override; private: @@ -64,7 +64,6 @@ private: Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option); Result SetRecordVolumeMuted(bool muted); - Nvnflinger::Nvnflinger& m_nvnflinger; Kernel::KProcess* const m_process; const std::shared_ptr m_applet; }; diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp index 5ec509d2e..d1871ef9b 100755 --- a/src/core/hle/service/am/service/system_applet_proxy.cpp +++ b/src/core/hle/service/am/service/system_applet_proxy.cpp @@ -19,10 +19,9 @@ namespace Service::AM { ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr applet, - Kernel::KProcess* process, - Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "ISystemAppletProxy"}, - m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(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"}, @@ -83,8 +82,7 @@ Result ISystemAppletProxy::GetWindowController( Result ISystemAppletProxy::GetSelfController( Out> out_self_controller) { LOG_DEBUG(Service_AM, "called"); - *out_self_controller = - std::make_shared(system, m_applet, m_process, m_nvnflinger); + *out_self_controller = std::make_shared(system, m_applet, m_process); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h index 3d5040315..67cd50e03 100755 --- a/src/core/hle/service/am/service/system_applet_proxy.h +++ b/src/core/hle/service/am/service/system_applet_proxy.h @@ -25,7 +25,7 @@ class IWindowController; class ISystemAppletProxy final : public ServiceFramework { public: explicit ISystemAppletProxy(Core::System& system, std::shared_ptr applet, - Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); + Kernel::KProcess* process); ~ISystemAppletProxy(); private: @@ -46,7 +46,6 @@ private: Result GetGlobalStateController( Out> out_global_state_controller); - Nvnflinger::Nvnflinger& m_nvnflinger; Kernel::KProcess* const m_process; const std::shared_ptr m_applet; }; diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp index b874ecb91..99a4f50a2 100755 --- a/src/core/hle/service/am/service/window_controller.cpp +++ b/src/core/hle/service/am/service/window_controller.cpp @@ -63,7 +63,7 @@ Result IWindowController::RejectToChangeIntoBackground() { } Result IWindowController::SetAppletWindowVisibility(bool visible) { - m_applet->system_buffer_manager.SetWindowVisibility(visible); + m_applet->display_layer_manager.SetWindowVisibility(visible); m_applet->hid_registration.EnableAppletToGetInput(visible); if (visible) { diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp index a3b533bf3..21314b516 100755 --- 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(system); - server_manager->RegisterNamedService("audctl", std::make_shared(system)); + server_manager->RegisterNamedService("audctl", std::make_shared(system)); server_manager->RegisterNamedService("audout:u", std::make_shared(system)); server_manager->RegisterNamedService("audin:u", std::make_shared(system)); server_manager->RegisterNamedService("audrec:a", std::make_shared(system)); diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp new file mode 100755 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("set:sys", true); + notification_event = service_context.CreateEvent("IAudioController:NotificationEvent"); +} + +IAudioController::~IAudioController() { + service_context.CloseEvent(notification_event); +}; + +Result IAudioController::GetTargetVolumeMin(Out 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 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 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 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 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 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 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 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 100755 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 { +public: + explicit IAudioController(Core::System& system_); + ~IAudioController() override; + +private: + enum class ForceMutePolicy { + Disable, + SpeakerMuteOnHeadphoneUnplugged, + }; + + enum class HeadphoneOutputLevelMode { + Normal, + HighPower, + }; + + Result GetTargetVolumeMin(Out out_target_min_volume); + Result GetTargetVolumeMax(Out out_target_max_volume); + Result GetAudioOutputMode(Out out_output_mode, + Set::AudioOutputModeTarget target); + Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode); + Result GetForceMutePolicy(Out out_mute_policy); + Result GetOutputModeSetting(Out out_output_mode, + Set::AudioOutputModeTarget target); + Result SetOutputModeSetting(Set::AudioOutputModeTarget target, + Set::AudioOutputMode output_mode); + Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode); + Result GetHeadphoneOutputLevelMode(Out out_output_level_mode); + Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled); + Result IsSpeakerAutoMuteEnabled(Out out_is_speaker_auto_mute_enabled); + Result AcquireTargetNotification(OutCopyHandle out_notification_event); + + KernelHelpers::ServiceContext service_context; + + Kernel::KEvent* notification_event; + std::shared_ptr m_set_sys; +}; + +} // namespace Service::Audio diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index 3d8f09380..89f7e6c73 100755 --- 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 out_count, AlbumStorage storage, + OutArray 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 8672ba2b1..4264ea82a 100755 --- 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 out_count, AlbumStorage storage, + OutArray out_entries); + Result DeleteAlbumFile(AlbumFileId file_id); Result IsAlbumMounted(Out out_is_mounted, AlbumStorage storage); diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index 900ab5ef8..24e7d377f 100755 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp @@ -3,6 +3,8 @@ #include +#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 buffer_a, + InBuffer 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 { diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index cad755fa7..059ac3fc9 100755 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp @@ -186,6 +186,10 @@ 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); diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h index 1de93f8f9..bb4b65049 100755 --- 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 m_set_sys; 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 100755 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 100755 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 { +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 100755 index 000000000..9c7975b77 --- /dev/null +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -0,0 +1,518 @@ +// 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 out_buffer, Out 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 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 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 out_records, Out 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(i); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent( + OutCopyHandle 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 out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_event = gamecard_mount_failure_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled( + Out 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 out_application_views, + InArray 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 out_application_views, + InArray 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 out_rights, Out out_count, + Common::UUID account_id, u32 flags, u64 application_id) { + LOG_WARNING(Service_NS, "(STUBBED) called, flags={}, application_id={:016X}, account_id={}", + flags, application_id, account_id.FormattedString()); + + if (!out_rights.empty()) { + out_rights[0] = { + .application_id = application_id, + .uid = account_id, + .flags = 0, + .flags2 = 0, + }; + *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 out_event) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_event = sd_card_mount_status_event.GetHandle(); + R_SUCCEED(); +} + +Result IApplicationManagerInterface::GetFreeSpaceSize(Out 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 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 out_total_space_size, + Out 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 out_update_required, + Out 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 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 100755 index 000000000..350ec37ce --- /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 { +public: + explicit IApplicationManagerInterface(Core::System& system_); + ~IApplicationManagerInterface() override; + + Result GetApplicationControlData(OutBuffer out_buffer, + Out out_actual_size, + ApplicationControlSource application_control_source, + u64 application_id); + Result GetApplicationDesiredLanguage(Out out_desired_language, + u32 supported_languages); + Result ConvertApplicationLanguageToLanguageCode(Out out_language_code, + ApplicationLanguage application_language); + Result ListApplicationRecord(OutArray out_records, + Out out_count, s32 offset); + Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle out_event); + Result GetGameCardMountFailureEvent(OutCopyHandle out_event); + Result IsAnyApplicationEntityInstalled(Out out_is_any_application_entity_installed); + Result GetApplicationView( + OutArray out_application_views, + InArray application_ids); + Result GetApplicationViewWithPromotionInfo( + OutArray out_application_views, + InArray application_ids); + Result GetApplicationRightsOnClient( + OutArray out_rights, Out out_count, + Common::UUID account_id, u32 flags, u64 application_id); + Result CheckSdCardMountStatus(); + Result GetSdCardMountStatusChangedEvent(OutCopyHandle out_event); + Result GetFreeSpaceSize(Out out_free_space_size, FileSys::StorageId storage_id); + Result GetGameCardUpdateDetectionEvent(OutCopyHandle out_event); + Result ResumeAll(); + Result GetStorageSize(Out out_total_space_size, Out out_free_space_size, + FileSys::StorageId storage_id); + Result IsApplicationUpdateRequested(Out out_update_required, Out out_update_version, + u64 application_id); + Result CheckApplicationLaunchVersion(u64 application_id); + Result GetApplicationTerminateResult(Out 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 100755 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 100755 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 { +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 100755 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 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 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 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 100755 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 { +public: + explicit IContentManagementInterface(Core::System& system_); + ~IContentManagementInterface() override; + +public: + Result CalculateApplicationOccupiedSize(Out out_size, + u64 application_id); + Result CheckSdCardMountStatus(); + Result GetTotalSpaceSize(Out out_total_space_size, FileSys::StorageId storage_id); + Result GetFreeSpaceSize(Out 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 100755 index 000000000..221cd74ac --- /dev/null +++ b/src/core/hle/service/ns/develop_interface.cpp @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#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 100755 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 { +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 100755 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 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 100755 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 { +public: + explicit IDocumentInterface(Core::System& system_); + ~IDocumentInterface() override; + +private: + Result ResolveApplicationContentPath(ContentPath content_path); + Result GetRunningApplicationProgramId(Out 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 100755 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 100755 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 { +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 100755 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 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 100755 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 { +public: + explicit IDynamicRightsInterface(Core::System& system_); + ~IDynamicRightsInterface() override; + +private: + Result NotifyApplicationRightsCheckStart(); + Result GetRunningApplicationStatus(Out 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 100755 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 100755 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 { +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 100755 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 100755 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 { +public: + explicit IFactoryResetInterface(Core::System& system_); + ~IFactoryResetInterface() override; +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 85a2ec345..d02fe417a 100755 --- 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(); - LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); - - const auto title_id = rp.PopRaw(); - - const auto size = ctx.GetWriteBufferSize(); - - const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), - system.GetContentProvider()}; - const auto control = pm.GetControlMetadata(); - - std::vector 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(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(static_cast(out.size())); -} - -void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto supported_languages = rp.Pop(); - - u8 desired_language{}; - const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); - if (res == ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(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(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(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(); - - 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(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(*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()}; - - LOG_INFO(Service_Capture, "called, storage={}", storage); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(system.GetFileSystemController().GetTotalSpaceSize(storage)); -} - -void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto storage{rp.PopEnum()}; - - LOG_INFO(Service_Capture, "called, storage={}", storage); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(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(); - 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(); - LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(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(); - LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(1); -} - -void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto result = rp.PopRaw(); - LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue()); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(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 nacp_data{}; - const auto parameters{rp.PopRaw()}; - 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, "GetReadOnlyApplicationControlDataInterface"}, - {7991, &NS::PushInterface, "GetReadOnlyApplicationRecordInterface"}, - {7992, &NS::PushInterface, "GetECommerceInterface"}, - {7993, &NS::PushInterface, "GetApplicationVersionInterface"}, - {7994, &NS::PushInterface, "GetFactoryResetInterface"}, - {7995, &NS::PushInterface, "GetAccountProxyInterface"}, - {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"}, - {7997, &NS::PushInterface, "GetDownloadTaskInterface"}, - {7998, &NS::PushInterface, "GetContentManagementInterface"}, - {7999, &NS::PushInterface, "GetDocumentInterface"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -NS::~NS() = default; - -std::shared_ptr NS::GetApplicationManagerInterface() const { - return GetInterface(system); -} - -class NS_DEV final : public ServiceFramework { -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 { -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 { -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(system); - } -}; - -class NS_VM final : public ServiceFramework { -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(system); - server_manager->RegisterNamedService("ns:am2", std::make_shared("ns:am2", system)); - server_manager->RegisterNamedService("ns:ec", std::make_shared("ns:ec", system)); - server_manager->RegisterNamedService("ns:rid", std::make_shared("ns:rid", system)); - server_manager->RegisterNamedService("ns:rt", std::make_shared("ns:rt", system)); - server_manager->RegisterNamedService("ns:web", std::make_shared("ns:web", system)); - server_manager->RegisterNamedService("ns:ro", std::make_shared("ns:ro", system)); + server_manager->RegisterNamedService( + "ns:am2", std::make_shared(system, "ns:am2")); + server_manager->RegisterNamedService( + "ns:ec", std::make_shared(system, "ns:ec")); + server_manager->RegisterNamedService( + "ns:rid", std::make_shared(system, "ns:rid")); + server_manager->RegisterNamedService( + "ns:rt", std::make_shared(system, "ns:rt")); + server_manager->RegisterNamedService( + "ns:web", std::make_shared(system, "ns:web")); + server_manager->RegisterNamedService( + "ns:ro", std::make_shared(system, "ns:ro")); - server_manager->RegisterNamedService("ns:dev", std::make_shared(system)); - server_manager->RegisterNamedService("ns:su", std::make_shared(system)); - server_manager->RegisterNamedService("ns:vm", std::make_shared(system)); - server_manager->RegisterNamedService("pdm:qry", std::make_shared(system)); + server_manager->RegisterNamedService("ns:dev", std::make_shared(system)); + server_manager->RegisterNamedService("ns:su", std::make_shared(system)); + server_manager->RegisterNamedService("ns:vm", + std::make_shared(system)); + server_manager->RegisterNamedService("pdm:qry", std::make_shared(system)); server_manager->RegisterNamedService("pl:s", std::make_shared(system, "pl:s")); diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index e6bf349ba..864094dae 100755 --- 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 { -public: - explicit IAccountProxyInterface(Core::System& system_); - ~IAccountProxyInterface() override; -}; - -class IApplicationManagerInterface final : public ServiceFramework { -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 { -public: - explicit IApplicationVersionInterface(Core::System& system_); - ~IApplicationVersionInterface() override; -}; - -class IContentManagementInterface final : public ServiceFramework { -public: - explicit IContentManagementInterface(Core::System& system_); - ~IContentManagementInterface() override; - -private: - void GetTotalSpaceSize(HLERequestContext& ctx); - void GetFreeSpaceSize(HLERequestContext& ctx); -}; - -class IDocumentInterface final : public ServiceFramework { -public: - explicit IDocumentInterface(Core::System& system_); - ~IDocumentInterface() override; - -private: - void ResolveApplicationContentPath(HLERequestContext& ctx); - void GetRunningApplicationProgramId(HLERequestContext& ctx); -}; - -class IDownloadTaskInterface final : public ServiceFramework { -public: - explicit IDownloadTaskInterface(Core::System& system_); - ~IDownloadTaskInterface() override; -}; - -class IECommerceInterface final : public ServiceFramework { -public: - explicit IECommerceInterface(Core::System& system_); - ~IECommerceInterface() override; -}; - -class IFactoryResetInterface final : public ServiceFramework { -public: - explicit IFactoryResetInterface(Core::System& system_); - ~IFactoryResetInterface() override; -}; - -class IReadOnlyApplicationRecordInterface final - : public ServiceFramework { -public: - explicit IReadOnlyApplicationRecordInterface(Core::System& system_); - ~IReadOnlyApplicationRecordInterface() override; - -private: - void HasApplicationRecord(HLERequestContext& ctx); - void IsDataCorruptedResult(HLERequestContext& ctx); -}; - -class IReadOnlyApplicationControlDataInterface final - : public ServiceFramework { -public: - explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); - ~IReadOnlyApplicationControlDataInterface() override; - -private: - void GetApplicationControlData(HLERequestContext& ctx); -}; - -class NS final : public ServiceFramework { -public: - explicit NS(const char* name, Core::System& system_); - ~NS() override; - - std::shared_ptr GetApplicationManagerInterface() const; - -private: - template - void PushInterface(HLERequestContext& ctx) { - LOG_DEBUG(Service_NS, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system); - } - - void PushIApplicationManagerInterface(HLERequestContext& ctx) { - LOG_DEBUG(Service_NS, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system); - } - - template - std::shared_ptr GetInterface(Args&&... args) const { - static_assert(std::is_base_of_v, - "Not a base of ServiceFrameworkBase"); - - return std::make_shared(std::forward(args)...); - } -}; +namespace Service::NS { void LoopProcess(Core::System& system); -} // namespace NS -} // namespace Service +} // namespace Service::NS diff --git a/src/core/hle/service/ns/ns_results.h b/src/core/hle/service/ns/ns_results.h new file mode 100755 index 000000000..16d2ea6f7 --- /dev/null +++ b/src/core/hle/service/ns/ns_results.h @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/result.h" + +namespace Service::NS { + +constexpr Result ResultApplicationLanguageNotFound{ErrorModule::NS, 300}; + +} diff --git a/src/core/hle/service/ns/ns_types.h b/src/core/hle/service/ns/ns_types.h new file mode 100755 index 000000000..37ff078bd --- /dev/null +++ b/src/core/hle/service/ns/ns_types.h @@ -0,0 +1,102 @@ +// 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 = 0xB, + GameCard = 0x10, +}; + +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 is an invalid size"); + +/// ApplicationView +struct ApplicationView { + u64 application_id; ///< ApplicationId. + u32 unk; ///< Unknown. + u32 flags; ///< Flags. + u8 unk_x10[0x10]; ///< Unknown. + u32 unk_x20; ///< Unknown. + u16 unk_x24; ///< Unknown. + u8 unk_x26[0x2]; ///< Unknown. + u8 unk_x28[0x8]; ///< Unknown. + u8 unk_x30[0x10]; ///< Unknown. + u32 unk_x40; ///< Unknown. + u8 unk_x44; ///< Unknown. + u8 unk_x45[0xb]; ///< Unknown. +}; + +struct ApplicationRightsOnClient { + u64 application_id; + Common::UUID uid; + u8 flags; + u8 flags2; + INSERT_PADDING_BYTES(0x6); +}; + +/// 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); +}; + +/// NsApplicationViewWithPromotionInfo +struct ApplicationViewWithPromotionInfo { + ApplicationView view; ///< \ref NsApplicationView + PromotionInfo promotion; ///< \ref NsPromotionInfo +}; + +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 entities; +}; + +struct ContentPath { + u8 file_system_proxy_type; + u64 program_id; +}; + +} // 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 100755 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 +#include +#include + +#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& 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 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& input, std::vector& 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 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& input, std::vector& 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 transformed_font(input.size() + 2); + transformed_font[0] = Common::swap32(EXPECTED_MAGIC); + transformed_font[1] = Common::swap32(static_cast(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 shared_font; + + // Automatically populated based on shared_fonts dump or system archives. + std::vector shared_font_regions; +}; + +IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_) + : ServiceFramework{system_, service_name_}, impl{std::make_unique()} { + // 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(SHARED_FONT_MEM_SIZE); + for (auto font : SHARED_FONTS) { + FileSys::VirtualFile romfs; + const auto nca = + nand->GetEntry(static_cast(font.first), FileSys::ContentRecordType::Data); + if (nca) { + romfs = nca->GetRomFS(); + } + + if (!romfs) { + romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast(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 font_data_u32(font_fp->GetSize() / sizeof(u32)); + font_fp->ReadBytes(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(offset + 8), + static_cast((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 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 out_size, SharedFontType type) { + LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); + *out_size = impl->GetSharedFontRegion(static_cast(type)).size; + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetSharedMemoryAddressOffset(Out out_shared_memory_offset, + SharedFontType type) { + LOG_DEBUG(Service_NS, "called, shared_font_type={}", type); + *out_shared_memory_offset = impl->GetSharedFontRegion(static_cast(type)).offset; + R_SUCCEED(); +} + +Result IPlatformServiceManager::GetSharedMemoryNativeHandle( + OutCopyHandle 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 out_font_codes, + OutArray out_font_offsets, + OutArray out_font_sizes, Out out_fonts_are_loaded, + Out 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(i); + out_font_offsets[i] = region.offset; + out_font_sizes[i] = region.size; + } + + *out_fonts_are_loaded = true; + *out_font_count = static_cast(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 100755 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 +#include +#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, 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& input, std::vector& output); +void EncryptSharedFont(const std::vector& input, std::vector& output, std::size_t& offset); + +class IPlatformServiceManager final : public ServiceFramework { +public: + explicit IPlatformServiceManager(Core::System& system_, const char* service_name_); + ~IPlatformServiceManager() override; + +private: + Result RequestLoad(SharedFontType type); + Result GetLoadState(Out out_load_state, SharedFontType type); + Result GetSize(Out out_size, SharedFontType type); + Result GetSharedMemoryAddressOffset(Out out_shared_memory_offset, SharedFontType type); + Result GetSharedMemoryNativeHandle( + OutCopyHandle out_shared_memory_native_handle); + Result GetSharedFontInOrderOfPriority(OutArray out_font_codes, + OutArray out_font_offsets, + OutArray out_font_sizes, + Out out_fonts_are_loaded, Out out_font_count, + Set::LanguageCode language_code); + + struct Impl; + std::unique_ptr 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 100755 index 000000000..946b7fa23 --- /dev/null +++ b/src/core/hle/service/ns/query_service.cpp @@ -0,0 +1,57 @@ +// 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 out_play_statistics, bool unknown, Common::UUID account_id, + u64 application_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.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 100755 index 000000000..6cdbfa277 --- /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/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 { +public: + explicit IQueryService(Core::System& system_); + ~IQueryService() override; + +private: + Result QueryPlayStatisticsByApplicationIdAndUserAccountId( + Out out_play_statistics, bool unknown, Common::UUID account_id, + u64 application_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 100755 index 000000000..1587aed44 --- /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 out_buffer, Out 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 = 0x4000 + 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, 0x4000); + } + + if (control.second != nullptr) { + control.second->Read(out_buffer.data() + 0x4000, icon_size); + } else { + LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id); + } + + *out_actual_size = static_cast(total_size); + R_SUCCEED(); +} + +Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage( + Out 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(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 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(*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 100755 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 { +public: + explicit IReadOnlyApplicationControlDataInterface(Core::System& system_); + ~IReadOnlyApplicationControlDataInterface() override; + +public: + Result GetApplicationControlData(OutBuffer out_buffer, + Out out_actual_size, + ApplicationControlSource application_control_source, + u64 application_id); + Result GetApplicationDesiredLanguage(Out out_desired_language, + u32 supported_languages); + Result ConvertApplicationLanguageToLanguageCode(Out 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 100755 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 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 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 100755 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 { +public: + explicit IReadOnlyApplicationRecordInterface(Core::System& system_); + ~IReadOnlyApplicationRecordInterface() override; + +private: + Result HasApplicationRecord(Out out_has_application_record, u64 program_id); + Result IsDataCorruptedResult(Out 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 100755 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> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetReadOnlyApplicationRecordInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetECommerceInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetApplicationVersionInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetFactoryResetInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetAccountProxyInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetApplicationManagerInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetDownloadTaskInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetContentManagementInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(system); + R_SUCCEED(); +} + +Result IServiceGetterInterface::GetDocumentInterface( + Out> out_interface) { + LOG_DEBUG(Service_NS, "called"); + *out_interface = std::make_shared(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 100755 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 { +public: + explicit IServiceGetterInterface(Core::System& system_, const char* name); + ~IServiceGetterInterface() override; + +public: + Result GetDynamicRightsInterface(Out> out_interface); + Result GetReadOnlyApplicationControlDataInterface( + Out> out_interface); + Result GetReadOnlyApplicationRecordInterface( + Out> out_interface); + Result GetECommerceInterface(Out> out_interface); + Result GetApplicationVersionInterface( + Out> out_interface); + Result GetFactoryResetInterface(Out> out_interface); + Result GetAccountProxyInterface(Out> out_interface); + Result GetApplicationManagerInterface( + Out> out_interface); + Result GetDownloadTaskInterface(Out> out_interface); + Result GetContentManagementInterface( + Out> out_interface); + Result GetDocumentInterface(Out> 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 100755 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 100755 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 { +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 100755 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 out_background_network_update_state) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + *out_background_network_update_state = BackgroundNetworkUpdateState::None; + R_SUCCEED(); +} + +Result ISystemUpdateInterface::OpenSystemUpdateControl( + Out> out_system_update_control) { + LOG_WARNING(Service_NS, "(STUBBED) called"); + *out_system_update_control = std::make_shared(system); + R_SUCCEED(); +} + +Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery( + OutCopyHandle 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 100755 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 { +public: + explicit ISystemUpdateInterface(Core::System& system_); + ~ISystemUpdateInterface() override; + +private: + Result GetBackgroundNetworkUpdateState( + Out out_background_network_update_state); + Result OpenSystemUpdateControl( + Out> out_system_update_control); + Result GetSystemUpdateNotificationEventForContentDelivery( + OutCopyHandle 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 100755 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 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 100755 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 { +public: + explicit IVulnerabilityManagerInterface(Core::System& system_); + ~IVulnerabilityManagerInterface() override; + +private: + Result NeedsUpdateVulnerability(Out out_needs_update_vulnerability); +}; + +} // namespace Service::NS diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 1b43f04c2..1fe3dfbb4 100755 --- 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(system); auto module = std::make_shared(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(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 1e9ae9a85..f2c00c833 100755 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -10,13 +10,11 @@ #include #include #include -#include #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> 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 ff0d010ee..2332a7c51 100755 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -263,8 +263,10 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr 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 2a2b73495..b38683814 100755 --- 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 nvdrv_, const char* name); ~NVDRV() override; + std::shared_ptr 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 179938192..124accb94 100755 --- a/src/core/hle/service/nvnflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h @@ -20,29 +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(android::TransactionId code, u32 flags, std::span parcel_data, - std::span parcel_reply) = 0; - virtual Kernel::KReadableEvent& GetNativeHandle() = 0; + virtual void Transact(u32 code, std::span parcel_data, std::span 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 100755 --- 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 consumer_) +BufferItemConsumer::BufferItemConsumer(std::shared_ptr 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 100755 --- 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 consumer); + explicit BufferItemConsumer(std::shared_ptr 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 100755 --- 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 parcel_data, + std::span 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(code)) { + case TransactionId::AcquireBuffer: { + BufferItem item; + const s64 present_when = parcel_in.Read(); + + status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when}); + + // TODO: can't write this directly, needs a flattener for the sp + // parcel_out.WriteFlattened(item); + UNREACHABLE(); + } + case TransactionId::ReleaseBuffer: { + const s32 slot = parcel_in.Read(); + const u64 frame_number = parcel_in.Read(); + const auto release_fence = parcel_in.ReadFlattened(); + + 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 100755 --- 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 #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 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 parcel_data, std::span parcel_reply, + u32 flags) override; + + Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; + private: std::shared_ptr 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 ec83beb9b..9e5091eeb 100755 --- 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,13 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, return Status::NoError; } -void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span parcel_data, - std::span parcel_reply) { +void BufferQueueProducer::Transact(u32 code, std::span parcel_data, + std::span 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{parcel_data}; OutputParcel parcel_out{}; - switch (code) { + switch (static_cast(code)) { case TransactionId::Connect: { const auto enable_listener = parcel_in.Read(); const auto api = parcel_in.Read(); @@ -923,8 +937,8 @@ void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::spanGetReadableEvent(); +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 4682b0f84..048523514 100755 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -45,12 +45,12 @@ public: explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, std::shared_ptr buffer_queue_core_, Service::Nvidia::NvCore::NvMap& nvmap_); - ~BufferQueueProducer(); + ~BufferQueueProducer() override; - void Transact(android::TransactionId code, u32 flags, std::span parcel_data, - std::span parcel_reply) override; + void Transact(u32 code, std::span parcel_data, std::span parcel_reply, + u32 flags) override; - Kernel::KReadableEvent& GetNativeHandle() override; + Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; public: Status RequestBuffer(s32 slot, std::shared_ptr* buf); diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp index 1059e72bf..e360ebfd8 100755 --- 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 consumer_) +ConsumerBase::ConsumerBase(std::shared_ptr 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 100755 --- 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 consumer_); + explicit ConsumerBase(std::shared_ptr consumer_); ~ConsumerBase() override; void OnFrameAvailable(const BufferItem& item) override; @@ -54,7 +54,7 @@ protected: bool is_abandoned{}; - std::unique_ptr consumer; + std::shared_ptr 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 100755 index 000000000..8a1956fe0 --- /dev/null +++ b/src/core/hle/service/nvnflinger/display.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#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 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 buffer_item_consumer; + s32 consumer_id; + LayerBlending blending; + bool visible; +}; + +struct LayerStack { + std::list layers; +}; + +struct Display { + explicit Display(u64 id_) { + id = id_; + } + + Layer* FindLayer(s32 consumer_id) { + for (auto& layer : stack.layers) { + if (layer.consumer_id == consumer_id) { + return &layer; + } + } + + return nullptr; + } + + u64 id; + LayerStack stack; +}; + +} // 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..02215a786 100755 --- 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 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(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(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. @@ -138,7 +137,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, if (auto* layer = display.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); + auto* const layer = display.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 100755 --- 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 #include #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 m_framebuffers{}; + boost::container::flat_map 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 100755 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 server, + std::shared_ptr 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 parcel_data, + OutBuffer 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 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 parcel_data, + OutBuffer 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 100755 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 { +public: + explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr server, + std::shared_ptr surface_flinger); + ~IHOSBinderDriver() override; + + std::shared_ptr GetSurfaceFlinger() { + return m_surface_flinger; + } + + std::shared_ptr GetServer() { + return m_server; + } + +private: + Result TransactParcel(s32 binder_id, u32 transaction_id, + InBuffer parcel_data, + OutBuffer parcel_reply, u32 flags); + Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); + Result GetNativeHandle(s32 binder_id, u32 type_id, + OutCopyHandle out_handle); + Result TransactParcelAuto(s32 binder_id, u32 transaction_id, + InBuffer parcel_data, + OutBuffer parcel_reply, u32 flags); + +private: + const std::shared_ptr m_server; + const std::shared_ptr 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 100755 --- 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&& binder) { +s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr&& 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}; - if (auto search = producers.find(id); search != producers.end()) { - return search->second.get(); + binders.erase(binder_id); +} + +std::shared_ptr HosBinderDriverServer::TryGetBinder(s32 id) const { + std::scoped_lock lk{lock}; + + 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 100755 --- 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 #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&& binder); + s32 RegisterBinder(std::shared_ptr&& binder); + void UnregisterBinder(s32 binder_id); - android::IBinder* TryGetProducer(u64 id); + std::shared_ptr TryGetBinder(s32 id) const; private: - KernelHelpers::ServiceContext service_context; - - std::unordered_map> producers; - std::mutex lock; - u64 last_id{}; + std::unordered_map> 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 100755 --- 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 -#include - -#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(); - - // Schedule the screen composition events - multi_composition_event = Core::Timing::CreateEvent( - "ScreenComposition", - [this](s64 time, - std::chrono::nanoseconds ns_late) -> std::optional { - 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 { - 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 instance) { - nvdrv = std::move(instance); - disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); -} - -std::optional 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 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 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(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(swap_interval); - return static_cast(speed_scale * (1000000000.f / effective_fps)); -} - -FbShareBufferManager& Nvnflinger::GetSystemBufferManager() { - const auto lock_guard = Lock(); - - if (!system_buffer_manager) { - system_buffer_manager = std::make_unique(system, *this, nvdrv); - } - - return *system_buffer_manager; +void LoopProcess(Core::System& system) { + const auto binder_server = std::make_shared(); + const auto surface_flinger = std::make_shared(system, *binder_server); + + auto server_manager = std::make_unique(system); + server_manager->RegisterNamedService( + "dispdrv", std::make_shared(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 100755 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -3,170 +3,12 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#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 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 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 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 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 core; - std::unique_ptr producer; - }; - - friend class FbShareBufferManager; - -private: - [[nodiscard]] std::unique_lock 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 nvdrv; - s32 disp_fd; - - std::list 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 multi_composition_event; - std::shared_ptr single_composition_event; - - std::unique_ptr system_buffer_manager; - - std::shared_ptr 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 100755 index 000000000..0e9714a03 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp @@ -0,0 +1,123 @@ +// 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("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; }); +} + +void SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, + u64 display_id) { + auto* const display = this->FindDisplay(display_id); + if (!display) { + return; + } + + *out_swap_interval = + m_composer.ComposeLocked(out_compose_speed_scale, *display, + *nvdrv->GetDevice(disp_fd)); +} + +void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) { + auto* const display = this->FindDisplay(display_id); + auto binder = std::static_pointer_cast( + m_server.TryGetBinder(consumer_binder_id)); + + if (!display || !binder) { + return; + } + + auto buffer_item_consumer = std::make_shared(std::move(binder)); + buffer_item_consumer->Connect(false); + + display->stack.layers.emplace_back(std::move(buffer_item_consumer), consumer_binder_id); +} + +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 (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) { + layer->visible = visible; + return; + } +} + +void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) { + if (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; +} + +Layer* SurfaceFlinger::FindLayer(s32 consumer_binder_id) { + for (auto& display : m_displays) { + if (auto* layer = display.FindLayer(consumer_binder_id); layer != nullptr) { + 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(); + auto producer = std::make_shared(m_context, core, nvmap); + auto consumer = std::make_shared(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 100755 index 000000000..a2e661430 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.h @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#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); + void ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_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); + 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 m_displays; + std::shared_ptr nvdrv; + s32 disp_fd; + HardwareComposer m_composer; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5a1a286f1..f41588d57 100755 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -7,68 +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/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" #include "core/reporter.h" namespace Service { @@ -209,82 +151,4 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, return result; } -/// Initialize Services -Services::Services(std::shared_ptr& sm, Core::System& system) - : hos_binder_driver_server{std::make_unique(system)}, - nv_flinger{std::make_unique(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("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; - -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 f5ee433f8..224f65fb8 100755 --- 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, Core::System& system); - ~Services(); - - void KillNVNFlinger(); - -private: - std::unique_ptr hos_binder_driver_server; - std::unique_ptr nv_flinger; -}; - } // namespace Service diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp new file mode 100755 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, 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 100755 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, Core::System& system, + std::stop_token token); + ~Services(); +}; + +} // namespace Service diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp index 78229e30f..6b0bcb536 100755 --- a/src/core/hle/service/vi/application_display_service.cpp +++ b/src/core/hle/service/vi/application_display_service.cpp @@ -2,22 +2,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/nvnflinger/nvnflinger.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/hos_binder_driver.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_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) - : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger}, - m_hos_binder_driver_server{hos_binder_driver_server} { - +IApplicationDisplayService::IApplicationDisplayService(Core::System& system_, + std::shared_ptr 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"}, @@ -48,38 +47,41 @@ IApplicationDisplayService::IApplicationDisplayService( } 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_nvnflinger.DestroyLayer(layer_id); + m_container->DestroyStrayLayer(layer_id); } } Result IApplicationDisplayService::GetRelayService( - Out> out_relay_service) { + Out> out_relay_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - *out_relay_service = std::make_shared(system, m_hos_binder_driver_server); - R_SUCCEED(); + R_RETURN(m_container->GetBinderDriver(out_relay_service)); } Result IApplicationDisplayService::GetSystemDisplayService( Out> out_system_display_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - *out_system_display_service = std::make_shared(system, m_nvnflinger); + *out_system_display_service = std::make_shared(system, m_container); R_SUCCEED(); } Result IApplicationDisplayService::GetManagerDisplayService( Out> out_manager_display_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - *out_manager_display_service = std::make_shared(system, m_nvnflinger); + *out_manager_display_service = std::make_shared(system, m_container); R_SUCCEED(); } Result IApplicationDisplayService::GetIndirectDisplayTransactionService( - Out> out_indirect_display_transaction_service) { + Out> out_indirect_display_transaction_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - *out_indirect_display_transaction_service = - std::make_shared(system, m_hos_binder_driver_server); - R_SUCCEED(); + R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service)); } Result IApplicationDisplayService::OpenDisplay(Out out_display_id, DisplayName display_name) { @@ -89,14 +91,7 @@ Result IApplicationDisplayService::OpenDisplay(Out out_display_id, DisplayN ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, "Non-default displays aren't supported yet"); - const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); - if (!display_id) { - LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); - R_THROW(VI::ResultNotFound); - } - - *out_display_id = *display_id; - R_SUCCEED(); + R_RETURN(m_container->OpenDisplay(out_display_id, display_name)); } Result IApplicationDisplayService::OpenDefaultDisplay(Out out_display_id) { @@ -106,8 +101,7 @@ Result IApplicationDisplayService::OpenDefaultDisplay(Out out_display_id) { Result IApplicationDisplayService::CloseDisplay(u64 display_id) { LOG_DEBUG(Service_VI, "called"); - R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id)); - R_THROW(ResultUnknown); + R_RETURN(m_container->CloseDisplay(display_id)); } Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { @@ -168,25 +162,19 @@ Result IApplicationDisplayService::OpenLayer(Out out_size, LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); - const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); - if (!display_id) { - LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); - R_THROW(VI::ResultNotFound); - } + u64 display_id; + R_TRY(m_container->OpenDisplay(&display_id, display_name)); - const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); - R_THROW(VI::ResultNotFound); - } + s32 producer_binder_id; + R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid)); - if (!m_nvnflinger.OpenLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to open layer which was already open"); - R_THROW(VI::ResultOperationFailed); + { + std::scoped_lock lk{m_lock}; + m_open_layer_ids.insert(layer_id); } android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + parcel.WriteInterface(NativeWindow{producer_binder_id}); const auto buffer = parcel.Serialize(); std::memcpy(out_native_window.data(), buffer.data(), @@ -199,12 +187,13 @@ Result IApplicationDisplayService::OpenLayer(Out out_size, Result IApplicationDisplayService::CloseLayer(u64 layer_id) { LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); - if (!m_nvnflinger.CloseLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to close layer which was not open"); - R_THROW(VI::ResultOperationFailed); + { + 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_SUCCEED(); + R_RETURN(m_container->CloseLayer(layer_id)); } Result IApplicationDisplayService::CreateStrayLayer( @@ -212,27 +201,19 @@ Result IApplicationDisplayService::CreateStrayLayer( u32 flags, u64 display_id) { LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); - const auto layer_id = m_nvnflinger.CreateLayer(display_id); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); - R_THROW(VI::ResultNotFound); - } + s32 producer_binder_id; + R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id)); - m_stray_layer_ids.push_back(*layer_id); - const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); - R_THROW(VI::ResultNotFound); - } + std::scoped_lock lk{m_lock}; + m_stray_layer_ids.insert(*out_layer_id); android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + 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_layer_id = *layer_id; *out_size = buffer.size(); R_SUCCEED(); @@ -240,25 +221,27 @@ Result IApplicationDisplayService::CreateStrayLayer( Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); - m_nvnflinger.DestroyLayer(layer_id); - R_SUCCEED(); + + { + 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 out_vsync_event, u64 display_id) { LOG_DEBUG(Service_VI, "called. display_id={}", display_id); - const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id); - if (result != ResultSuccess) { - if (result == ResultNotFound) { - LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); - } + std::scoped_lock lk{m_lock}; - R_THROW(result); - } + auto [it, created] = m_display_vsync_events.emplace(display_id, m_context); + R_UNLESS(created, VI::ResultPermissionDenied); - R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); - m_vsync_event_fetched = true; + m_container->LinkVsyncEvent(display_id, &it->second); + *out_vsync_event = it->second.GetHandle(); R_SUCCEED(); } diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h index 5dff4bb31..1bdeb8f84 100755 --- a/src/core/hle/service/vi/application_display_service.h +++ b/src/core/hle/service/vi/application_display_service.h @@ -1,7 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include + #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" @@ -9,26 +14,33 @@ namespace Kernel { class KReadableEvent; } +namespace Service::Nvnflinger { +class IHOSBinderDriver; +} + namespace Service::VI { -class IHOSBinderDriver; +class Container; class IManagerDisplayService; class ISystemDisplayService; class IApplicationDisplayService final : public ServiceFramework { public: - IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); + IApplicationDisplayService(Core::System& system_, std::shared_ptr container); ~IApplicationDisplayService() override; -private: - Result GetRelayService(Out> out_relay_service); + std::shared_ptr GetContainer() const { + return m_container; + } + +public: + Result GetRelayService(Out> out_relay_service); Result GetSystemDisplayService( Out> out_system_display_service); Result GetManagerDisplayService( Out> out_manager_display_service); Result GetIndirectDisplayTransactionService( - Out> out_indirect_display_transaction_service); + Out> out_indirect_display_transaction_service); Result OpenDisplay(Out out_display_id, DisplayName display_name); Result OpenDefaultDisplay(Out out_display_id); Result CloseDisplay(u64 display_id); @@ -56,9 +68,13 @@ private: s64 width, s64 height); private: - Nvnflinger::Nvnflinger& m_nvnflinger; - Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; - std::vector m_stray_layer_ids; + const std::shared_ptr m_container; + + KernelHelpers::ServiceContext m_context; + std::mutex m_lock{}; + std::set m_open_layer_ids{}; + std::set m_stray_layer_ids{}; + std::map m_display_vsync_events{}; bool m_vsync_event_fetched{false}; }; diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp index 7af7f062c..7f35a048d 100755 --- a/src/core/hle/service/vi/application_root_service.cpp +++ b/src/core/hle/service/vi/application_root_service.cpp @@ -4,17 +4,16 @@ #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_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) - : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ - hos_binder_driver_server} { +IApplicationRootService::IApplicationRootService(Core::System& system_, + std::shared_ptr container) + : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} { static const FunctionInfo functions[] = { {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -27,8 +26,8 @@ IApplicationRootService::~IApplicationRootService() = default; Result IApplicationRootService::GetDisplayService( Out> out_application_display_service, Policy policy) { LOG_DEBUG(Service_VI, "called"); - R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, - m_hos_binder_driver_server, Permission::User, policy)); + 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 index 9dbf28cb4..15aa4483d 100755 --- a/src/core/hle/service/vi/application_root_service.h +++ b/src/core/hle/service/vi/application_root_service.h @@ -10,20 +10,15 @@ namespace Core { class System; } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - namespace Service::VI { +class Container; class IApplicationDisplayService; enum class Policy : u32; class IApplicationRootService final : public ServiceFramework { public: - explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); + explicit IApplicationRootService(Core::System& system_, std::shared_ptr container); ~IApplicationRootService() override; private: @@ -32,8 +27,7 @@ private: Policy policy); private: - Nvnflinger::Nvnflinger& m_nvnflinger; - Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; + const std::shared_ptr 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 100755 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 { + 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 { + 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(m_swap_interval); + return static_cast(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 100755 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 +#include + +#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 m_vsync_managers; + std::shared_ptr 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 100755 index 000000000..2d6b9cbfe --- /dev/null +++ b/src/core/hle/service/vi/container.cpp @@ -0,0 +1,227 @@ +// 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("dispdrv", true); + m_surface_flinger = m_binder_driver->GetSurfaceFlinger(); + + const auto nvdrv = + system.ServiceManager().GetService("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) { + if (layer.IsOpen()) { + this->DestroyBufferQueueLocked(&layer); + } + }); + + 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* out_binder_driver) { + *out_binder_driver = m_binder_driver; + R_SUCCEED(); +} + +Result Container::GetLayerProducerHandle( + std::shared_ptr* 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(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); + + auto* const layer = m_layers.CreateLayer(owner_aruid, display); + R_UNLESS(layer != nullptr, VI::ResultNotFound); + + *out_layer_id = layer->GetId(); + R_SUCCEED(); +} + +Result Container::DestroyLayerLocked(u64 layer_id) { + R_SUCCEED_IF(m_layers.DestroyLayer(layer_id)); + R_THROW(VI::ResultNotFound); +} + +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); + + this->CreateBufferQueueLocked(layer); + *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); + + this->DestroyBufferQueueLocked(layer); + + R_SUCCEED(); +} + +void Container::CreateBufferQueueLocked(Layer* layer) { + s32 consumer_binder_id, producer_binder_id; + m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id); + layer->Open(consumer_binder_id, producer_binder_id); + + if (auto* display = layer->GetDisplay(); display != nullptr) { + m_surface_flinger->AddLayerToDisplayStack(display->GetId(), consumer_binder_id); + } +} + +void Container::DestroyBufferQueueLocked(Layer* layer) { + if (auto* display = layer->GetDisplay(); display != nullptr) { + m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(), + layer->GetConsumerBinderId()); + } + + layer->Close(); + m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(), + layer->GetProducerBinderId()); +} + +void Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, + u64 display_id) { + std::scoped_lock lk{m_lock}; + 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 100755 index 000000000..155c4c629 --- /dev/null +++ b/src/core/hle/service/vi/container.h @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#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* out_binder_driver); + Result GetLayerProducerHandle(std::shared_ptr* 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); + + void CreateBufferQueueLocked(Layer* layer); + void DestroyBufferQueueLocked(Layer* layer); + +public: + void 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 m_binder_driver{}; + std::shared_ptr m_surface_flinger{}; + std::optional m_shared_buffer_manager{}; + std::optional 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 100755 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_list.h b/src/core/hle/service/vi/display_list.h new file mode 100755 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 + +#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 + 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 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 100755 index 000000000..b85c8df61 --- /dev/null +++ b/src/core/hle/service/vi/layer.h @@ -0,0 +1,79 @@ +// 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) { + m_id = id; + m_owner_aruid = owner_aruid; + m_display = display; + m_is_initialized = true; + } + + void Finalize() { + m_id = {}; + m_display = {}; + m_is_initialized = {}; + } + + void Open(s32 consumer_binder_id, s32 producer_binder_id) { + m_consumer_binder_id = consumer_binder_id; + m_producer_binder_id = producer_binder_id; + m_is_open = true; + } + + void Close() { + m_producer_binder_id = {}; + m_consumer_binder_id = {}; + m_is_open = {}; + } + + 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_list.h b/src/core/hle/service/vi/layer_list.h new file mode 100755 index 000000000..1738ede9a --- /dev/null +++ b/src/core/hle/service/vi/layer_list.h @@ -0,0 +1,69 @@ +// 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) { + Layer* const layer = GetFreeLayer(); + if (!layer) { + return nullptr; + } + + layer->Initialize(++m_next_id, owner_aruid, display); + 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 + 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 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 index 17f2f3b8f..9f856282e 100755 --- a/src/core/hle/service/vi/manager_display_service.cpp +++ b/src/core/hle/service/vi/manager_display_service.cpp @@ -2,22 +2,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/vi/container.h" #include "core/hle/service/vi/manager_display_service.h" -#include "core/hle/service/vi/vi_results.h" namespace Service::VI { IManagerDisplayService::IManagerDisplayService(Core::System& system_, - Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "IManagerDisplayService"}, m_nvnflinger{nvnflinger} { + std::shared_ptr 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, nullptr, "DestroyManagedLayer"}, + {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"}, {2012, nullptr, "CreateStrayLayer"}, {2050, nullptr, "CreateIndirectLayer"}, {2051, nullptr, "DestroyIndirectLayer"}, @@ -102,19 +101,30 @@ IManagerDisplayService::IManagerDisplayService(Core::System& system_, IManagerDisplayService::~IManagerDisplayService() = default; -Result IManagerDisplayService::CreateManagedLayer(Out out_layer_id, u32 unknown, - u64 display_id, AppletResourceUserId aruid) { - LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, - display_id, aruid.pid); +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)); +} - const auto layer_id = m_nvnflinger.CreateLayer(display_id); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); - R_THROW(VI::ResultNotFound); - } +void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) { + m_container->GetSharedBufferManager()->DestroySession(owner_process); +} - *out_layer_id = *layer_id; - R_SUCCEED(); +Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) { + R_RETURN(m_container->SetLayerBlending(layer_id, enabled)); +} + +Result IManagerDisplayService::CreateManagedLayer(Out 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) { @@ -123,8 +133,8 @@ Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { } Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { - LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); - R_SUCCEED(); + 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 index 60e646ee0..b1bdf7f41 100755 --- a/src/core/hle/service/vi/manager_display_service.h +++ b/src/core/hle/service/vi/manager_display_service.h @@ -4,21 +4,34 @@ #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 { public: - explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); + explicit IManagerDisplayService(Core::System& system_, std::shared_ptr container); ~IManagerDisplayService() override; -private: - Result CreateManagedLayer(Out out_layer_id, u32 unknown, u64 display_id, + 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 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: - Nvnflinger::Nvnflinger& m_nvnflinger; + const std::shared_ptr 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 index a7eee4f04..0f16a15b4 100755 --- a/src/core/hle/service/vi/manager_root_service.cpp +++ b/src/core/hle/service/vi/manager_root_service.cpp @@ -2,7 +2,9 @@ // 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" @@ -10,11 +12,9 @@ namespace Service::VI { -IManagerRootService::IManagerRootService( - Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) - : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ - hos_binder_driver_server} { +IManagerRootService::IManagerRootService(Core::System& system_, + std::shared_ptr container) + : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} { static const FunctionInfo functions[] = { {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -31,8 +31,8 @@ IManagerRootService::~IManagerRootService() = default; Result IManagerRootService::GetDisplayService( Out> out_application_display_service, Policy policy) { LOG_DEBUG(Service_VI, "called"); - R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, - m_hos_binder_driver_server, Permission::Manager, policy)); + 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 index e6cb77aeb..77cd32869 100755 --- a/src/core/hle/service/vi/manager_root_service.h +++ b/src/core/hle/service/vi/manager_root_service.h @@ -10,29 +10,23 @@ namespace Core { class System; } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - namespace Service::VI { +class Container; class IApplicationDisplayService; enum class Policy : u32; class IManagerRootService final : public ServiceFramework { public: - explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); + explicit IManagerRootService(Core::System& system_, std::shared_ptr container); ~IManagerRootService() override; -private: Result GetDisplayService( Out> out_application_display_service, Policy policy); - Nvnflinger::Nvnflinger& m_nvnflinger; - Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; +private: + const std::shared_ptr 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 index 1de9d61a4..2b8e5f957 100755 --- a/src/core/hle/service/vi/service_creator.cpp +++ b/src/core/hle/service/vi/service_creator.cpp @@ -22,8 +22,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) { Result GetApplicationDisplayService( std::shared_ptr* out_application_display_service, - Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, + Core::System& system, std::shared_ptr container, Permission permission, Policy policy) { if (!IsValidServiceAccess(permission, policy)) { @@ -32,7 +31,7 @@ Result GetApplicationDisplayService( } *out_application_display_service = - std::make_shared(system, nvnflinger, hos_binder_driver_server); + std::make_shared(system, std::move(container)); R_SUCCEED(); } diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h index 8963bcd26..c6ba1797d 100755 --- a/src/core/hle/service/vi/service_creator.h +++ b/src/core/hle/service/vi/service_creator.h @@ -11,23 +11,18 @@ namespace Core { class System; } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - union Result; namespace Service::VI { +class Container; class IApplicationDisplayService; enum class Permission; enum class Policy : u32; Result GetApplicationDisplayService( std::shared_ptr* out_application_display_service, - Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, + Core::System& system, std::shared_ptr 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 100755 index 000000000..869b18961 --- /dev/null +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp @@ -0,0 +1,439 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#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* 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, 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(block.GetAddress()); + u32* end = system.DeviceMemory().GetPointer(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& 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(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(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(); + 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 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 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. + R_ASSERT(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& out_slot_indexes, + s64* out_target_slot, u64 layer_id) { + std::scoped_lock lk{m_guard}; + + // Get the producer. + std::shared_ptr 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 crop_region, + u32 transform, s32 swap_interval, u64 layer_id, + s64 slot) { + std::scoped_lock lk{m_guard}; + + // Get the producer. + std::shared_ptr producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); + + // Request to queue the buffer. + std::shared_ptr buffer; + R_UNLESS(producer->RequestBuffer(static_cast(slot), std::addressof(buffer)) == + android::Status::NoError, + VI::ResultOperationFailed); + + ON_RESULT_FAILURE { + producer->CancelBuffer(static_cast(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(transform); + input.swap_interval = swap_interval; + R_UNLESS(producer->QueueBuffer(static_cast(slot), input, std::addressof(output)) == + android::Status::NoError, + VI::ResultOperationFailed); + + // We succeeded. + R_SUCCEED(); +} + +Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { + std::scoped_lock lk{m_guard}; + + // Get the producer. + std::shared_ptr producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); + + // Cancel. + producer->CancelBuffer(static_cast(slot), android::Fence::NoFence()); + + // We succeeded. + R_SUCCEED(); +} + +Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, + u64 layer_id) { + std::scoped_lock lk{m_guard}; + + // Get the producer. + std::shared_ptr 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 capture_buffer(m_system.GPU().GetAppletCaptureBuffer()); + Common::ScratchBuffer scratch; + + // TODO: this could be optimized + s64 e = -1280 * 768 * 4; + for (auto& block : *m_buffer_page_group) { + u8* start = m_system.DeviceMemory().GetPointer(block.GetAddress()); + u8* end = m_system.DeviceMemory().GetPointer(block.GetAddress() + block.GetSize()); + + for (; start < end; start++) { + *start = 0; + + if (e >= 0 && e < static_cast(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 100755 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 + +#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 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 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& out_slots, + s64* out_target_slot, u64 layer_id); + Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle 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 m_sessions; + std::unique_ptr m_buffer_page_group; + + std::mutex m_guard; + Core::System& m_system; + Container& m_container; + const std::shared_ptr 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 index 1e1cfc817..c3c50b07b 100755 --- a/src/core/hle/service/vi/system_display_service.cpp +++ b/src/core/hle/service/vi/system_display_service.cpp @@ -3,15 +3,15 @@ #include "common/settings.h" #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.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_, - Nvnflinger::Nvnflinger& nvnflinger) - : ServiceFramework{system_, "ISystemDisplayService"}, m_nvnflinger{nvnflinger} { + std::shared_ptr container) + : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} { // clang-format off static const FunctionInfo functions[] = { {1200, nullptr, "GetZOrderCountMin"}, @@ -29,7 +29,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, {2400, nullptr, "OpenIndirectLayer"}, {2401, nullptr, "CloseIndirectLayer"}, {2402, nullptr, "FlipIndirectLayer"}, - {3000, nullptr, "ListDisplayModes"}, + {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"}, {3001, nullptr, "ListDisplayRgbRanges"}, {3002, nullptr, "ListDisplayContentTypes"}, {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, @@ -59,7 +59,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, {8257, nullptr, "FillSharedFrameBufferColor"}, - {8258, nullptr, "CancelSharedFrameBuffer"}, + {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"}, {9000, nullptr, "GetDp2hdmiController"}, }; // clang-format on @@ -80,31 +80,50 @@ Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { R_SUCCEED(); } -Result ISystemDisplayService::GetDisplayMode(Out out_width, Out out_height, - Out out_refresh_rate, Out out_unknown) { - LOG_WARNING(Service_VI, "(STUBBED) called"); +Result ISystemDisplayService::ListDisplayModes( + Out out_count, u64 display_id, + OutArray out_display_modes) { + LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id); - if (Settings::IsDockedMode()) { - *out_width = static_cast(DisplayResolution::DockedWidth); - *out_height = static_cast(DisplayResolution::DockedHeight); + if (!out_display_modes.empty()) { + out_display_modes[0] = { + .width = 1920, + .height = 1080, + .refresh_rate = 60.f, + .unknown = {}, + }; + *out_count = 1; } else { - *out_width = static_cast(DisplayResolution::UndockedWidth); - *out_height = static_cast(DisplayResolution::UndockedHeight); + *out_count = 0; } - *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. - *out_unknown = 0; + R_SUCCEED(); +} + +Result ISystemDisplayService::GetDisplayMode(Out 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(DisplayResolution::DockedWidth); + out_display_mode->height = static_cast(DisplayResolution::DockedHeight); + } else { + out_display_mode->width = static_cast(DisplayResolution::UndockedWidth); + out_display_mode->height = static_cast(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 out_nvmap_handle, Out out_size, - OutLargeData out_pool_layout, - u64 buffer_id, ClientAppletResourceUserId aruid) { + OutLargeData out_pool_layout, u64 buffer_id, + ClientAppletResourceUserId aruid) { LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); - R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( + R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId( out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); } @@ -122,7 +141,7 @@ Result ISystemDisplayService::AcquireSharedFrameBuffer(Out out_f Out> out_slots, Out out_target_slot, u64 layer_id) { LOG_DEBUG(Service_VI, "called"); - R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( + R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer( out_fence, *out_slots, out_target_slot, layer_id)); } @@ -131,15 +150,20 @@ Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, u32 window_transform, s32 swap_interval, u64 layer_id, s64 surface_id) { LOG_DEBUG(Service_VI, "called"); - R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( + R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer( fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); } Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( OutCopyHandle out_event, u64 layer_id) { LOG_DEBUG(Service_VI, "called"); - R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event, - layer_id)); + 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 index cfcb196fd..7228d826e 100755 --- a/src/core/hle/service/vi/system_display_service.h +++ b/src/core/hle/service/vi/system_display_service.h @@ -5,27 +5,28 @@ #include "core/hle/service/cmif_types.h" #include "core/hle/service/nvnflinger/ui/fence.h" #include "core/hle/service/service.h" - -namespace Service::Nvnflinger { -struct SharedMemoryPoolLayout; -} +#include "core/hle/service/vi/shared_buffer_manager.h" namespace Service::VI { +struct DisplayMode; + +class Container; class ISystemDisplayService final : public ServiceFramework { public: - explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); + explicit ISystemDisplayService(Core::System& system_, std::shared_ptr container); ~ISystemDisplayService() override; private: Result SetLayerZ(u32 z_value, u64 layer_id); Result SetLayerVisibility(bool visible, u64 layer_id); - Result GetDisplayMode(Out out_width, Out out_height, Out out_refresh_rate, - Out out_unknown); + Result ListDisplayModes(Out out_count, u64 display_id, + OutArray out_display_modes); + Result GetDisplayMode(Out out_display_mode, u64 display_id); Result GetSharedBufferMemoryHandleId( Out out_nvmap_handle, Out out_size, - OutLargeData out_pool_layout, + OutLargeData out_pool_layout, u64 buffer_id, ClientAppletResourceUserId aruid); Result OpenSharedLayer(u64 layer_id); Result ConnectSharedLayer(u64 layer_id); @@ -37,9 +38,10 @@ private: Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle crop_region, u32 window_transform, s32 swap_interval, u64 layer_id, s64 surface_id); + Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); private: - Nvnflinger::Nvnflinger& m_nvnflinger; + const std::shared_ptr 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 index 8789b4cfb..3489727d8 100755 --- a/src/core/hle/service/vi/system_root_service.cpp +++ b/src/core/hle/service/vi/system_root_service.cpp @@ -3,6 +3,7 @@ #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" @@ -10,10 +11,8 @@ namespace Service::VI { -ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) - : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ - hos_binder_driver_server} { +ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr container) + : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} { static const FunctionInfo functions[] = { {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -26,8 +25,8 @@ ISystemRootService::~ISystemRootService() = default; Result ISystemRootService::GetDisplayService( Out> out_application_display_service, Policy policy) { LOG_DEBUG(Service_VI, "called"); - R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, - m_hos_binder_driver_server, Permission::System, policy)); + 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 index 2c547faa5..9d5aa53d3 100755 --- a/src/core/hle/service/vi/system_root_service.h +++ b/src/core/hle/service/vi/system_root_service.h @@ -10,20 +10,15 @@ namespace Core { class System; } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - namespace Service::VI { +class Container; class IApplicationDisplayService; enum class Policy : u32; class ISystemRootService final : public ServiceFramework { public: - explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); + explicit ISystemRootService(Core::System& system_, std::shared_ptr container); ~ISystemRootService() override; private: @@ -31,8 +26,7 @@ private: Out> out_application_display_service, Policy policy); - Nvnflinger::Nvnflinger& m_nvnflinger; - Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; + const std::shared_ptr m_container; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 18442b265..f4a238683 100755 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1,25 +1,30 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/core.h" #include "core/hle/service/server_manager.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/manager_root_service.h" #include "core/hle/service/vi/system_root_service.h" #include "core/hle/service/vi/vi.h" namespace Service::VI { -void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { +void LoopProcess(Core::System& system, std::stop_token token) { + const auto container = std::make_shared(system); + auto server_manager = std::make_unique(system); - server_manager->RegisterNamedService("vi:m", std::make_shared( - system, nvnflinger, hos_binder_driver_server)); + server_manager->RegisterNamedService("vi:m", + std::make_shared(system, container)); + server_manager->RegisterNamedService("vi:s", + std::make_shared(system, container)); server_manager->RegisterNamedService( - "vi:s", std::make_shared(system, nvnflinger, hos_binder_driver_server)); - server_manager->RegisterNamedService("vi:u", std::make_shared( - system, nvnflinger, hos_binder_driver_server)); + "vi:u", std::make_shared(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 a81a701b0..af562e1a3 100755 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -3,18 +3,14 @@ #pragma once +#include "common/polyfill_thread.h" + namespace Core { class System; } -namespace Service::Nvnflinger { -class HosBinderDriverServer; -class Nvnflinger; -} // namespace Service::Nvnflinger - namespace Service::VI { -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_types.h b/src/core/hle/service/vi/vi_types.h index 91e4b380c..95ff66358 100755 --- a/src/core/hle/service/vi/vi_types.h +++ b/src/core/hle/service/vi/vi_types.h @@ -66,9 +66,17 @@ struct DisplayInfo { }; 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(u32 id_) : id{id_} {} + constexpr explicit NativeWindow(s32 id_) : id{static_cast(id_)} {} constexpr explicit NativeWindow(const NativeWindow& other) = default; private: diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp new file mode 100755 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 100755 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 + +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 m_vsync_events; +}; + +} // namespace Service::VI diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 1d6c117b1..88d166dd5 100755 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1130,7 +1130,7 @@ void BufferCache

::UpdateVertexBuffer(u32 index) { channel_state->vertex_buffers[index] = NULL_BINDING; return; } - if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) { + if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || size >= 64_MiB) { size = static_cast(gpu_memory->MaxContinuousRange(gpu_addr_begin, size)); } const BufferId buffer_id = FindBuffer(*device_addr, size);